mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-07 22:46:22 +03:00
Summary: There are many files in this diff, but the relevant ones are: * quic/api/QuicSocket.h * quic/api/QuicSocketLite.h * quic/api/QuicTransportBase.h * quic/api/QuicTransportBaseLite.cpp * quic/observer/SocketObserverContainer.h The purpose of this is to include the observer functionality within the Lite class. Ideally, we'd remove it from the Lite class, but that's going to require some more detailed changes to the interfaces we're using, because observers are used quite a lot within common code (for example, AckHandlers.cpp). I'll make those changes some time after the QuicTransportBase split, as they're going to take a while. Reviewed By: jbeshay, mjoras, kvtsoy Differential Revision: D65685667 fbshipit-source-id: feb07bcf35d6af2e5c2b538ff463b01b67c6aff9
302 lines
10 KiB
C++
302 lines
10 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/QuicException.h>
|
|
#include <quic/api/QuicSocket.h>
|
|
#include <quic/api/QuicTransportBaseLite.h>
|
|
#include <quic/common/NetworkData.h>
|
|
#include <quic/common/events/QuicEventBase.h>
|
|
#include <quic/common/events/QuicTimer.h>
|
|
#include <quic/common/udpsocket/QuicAsyncUDPSocket.h>
|
|
#include <quic/congestion_control/CongestionControllerFactory.h>
|
|
#include <quic/congestion_control/Copa.h>
|
|
#include <quic/congestion_control/NewReno.h>
|
|
#include <quic/congestion_control/QuicCubic.h>
|
|
#include <quic/state/StateData.h>
|
|
|
|
#include <folly/ExceptionWrapper.h>
|
|
|
|
namespace quic {
|
|
|
|
/**
|
|
* Base class for the QUIC Transport. Implements common behavior for both
|
|
* clients and servers. QuicTransportBase assumes the following:
|
|
* 1. It is intended to be sub-classed and used via the subclass directly.
|
|
* 2. Assumes that the sub-class manages its ownership via a shared_ptr.
|
|
* This is needed in order for QUIC to be able to live beyond the lifetime
|
|
* of the object that holds it to send graceful close messages to the peer.
|
|
*/
|
|
class QuicTransportBase : public QuicSocket,
|
|
public QuicTransportBaseLite,
|
|
QuicStreamPrioritiesObserver {
|
|
public:
|
|
QuicTransportBase(
|
|
std::shared_ptr<QuicEventBase> evb,
|
|
std::unique_ptr<QuicAsyncUDPSocket> socket,
|
|
bool useConnectionEndWithErrorCallback = false);
|
|
|
|
~QuicTransportBase() override;
|
|
|
|
void setPacingTimer(QuicTimer::SharedPtr pacingTimer) noexcept;
|
|
|
|
Optional<ConnectionId> getClientConnectionId() const override;
|
|
|
|
Optional<ConnectionId> getServerConnectionId() const override;
|
|
|
|
Optional<ConnectionId> getClientChosenDestConnectionId() const override;
|
|
|
|
const std::shared_ptr<QLogger> getQLogger() const;
|
|
|
|
// QuicSocket interface
|
|
bool replaySafe() const override;
|
|
|
|
void closeGracefully() override;
|
|
|
|
folly::Expected<size_t, LocalErrorCode> getStreamReadOffset(
|
|
StreamId id) const override;
|
|
folly::Expected<size_t, LocalErrorCode> getStreamWriteOffset(
|
|
StreamId id) const override;
|
|
folly::Expected<size_t, LocalErrorCode> getStreamWriteBufferedBytes(
|
|
StreamId id) const override;
|
|
|
|
folly::Expected<QuicSocket::FlowControlState, LocalErrorCode>
|
|
getConnectionFlowControl() const override;
|
|
|
|
folly::Expected<uint64_t, LocalErrorCode> getMaxWritableOnStream(
|
|
StreamId id) const override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> setConnectionFlowControlWindow(
|
|
uint64_t windowSize) override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> setStreamFlowControlWindow(
|
|
StreamId id,
|
|
uint64_t windowSize) override;
|
|
|
|
void unsetAllReadCallbacks() override;
|
|
void unsetAllPeekCallbacks() override;
|
|
void unsetAllDeliveryCallbacks() override;
|
|
folly::Expected<folly::Unit, LocalErrorCode> pauseRead(StreamId id) override;
|
|
folly::Expected<folly::Unit, LocalErrorCode> resumeRead(StreamId id) override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> setPeekCallback(
|
|
StreamId id,
|
|
PeekCallback* cb) override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> pausePeek(StreamId id) override;
|
|
folly::Expected<folly::Unit, LocalErrorCode> resumePeek(StreamId id) override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> peek(
|
|
StreamId id,
|
|
const folly::Function<void(StreamId id, const folly::Range<PeekIterator>&)
|
|
const>& peekCallback) override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> consume(
|
|
StreamId id,
|
|
size_t amount) override;
|
|
|
|
folly::Expected<folly::Unit, std::pair<LocalErrorCode, Optional<uint64_t>>>
|
|
consume(StreamId id, uint64_t offset, size_t amount) override;
|
|
|
|
folly::Expected<StreamGroupId, LocalErrorCode>
|
|
createBidirectionalStreamGroup() override;
|
|
folly::Expected<StreamGroupId, LocalErrorCode>
|
|
createUnidirectionalStreamGroup() override;
|
|
folly::Expected<StreamId, LocalErrorCode> createBidirectionalStreamInGroup(
|
|
StreamGroupId groupId) override;
|
|
folly::Expected<StreamId, LocalErrorCode> createUnidirectionalStreamInGroup(
|
|
StreamGroupId groupId) override;
|
|
bool isClientStream(StreamId stream) noexcept override;
|
|
bool isServerStream(StreamId stream) noexcept override;
|
|
StreamDirectionality getStreamDirectionality(
|
|
StreamId stream) noexcept override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> maybeResetStreamFromReadError(
|
|
StreamId id,
|
|
QuicErrorCode error) override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> setPingCallback(
|
|
PingCallback* cb) override;
|
|
|
|
void sendPing(std::chrono::milliseconds pingTimeout) override;
|
|
|
|
const QuicConnectionStateBase* getState() const override {
|
|
return conn_.get();
|
|
}
|
|
|
|
virtual void setAckRxTimestampsEnabled(bool enableAckRxTimestamps);
|
|
|
|
void setEarlyDataAppParamsFunctions(
|
|
folly::Function<bool(const Optional<std::string>&, const Buf&) const>
|
|
validator,
|
|
folly::Function<Buf()> getter) final;
|
|
|
|
bool isDetachable() override;
|
|
|
|
void detachEventBase() override;
|
|
|
|
void attachEventBase(std::shared_ptr<QuicEventBase> evb) override;
|
|
|
|
// Subclass API.
|
|
|
|
folly::Expected<Priority, LocalErrorCode> getStreamPriority(
|
|
StreamId id) override;
|
|
|
|
/**
|
|
* Register a callback to be invoked when the stream offset was transmitted.
|
|
*
|
|
* Currently, an offset is considered "transmitted" if it has been written to
|
|
* to the underlying UDP socket, indicating that it has passed through
|
|
* congestion control and pacing. In the future, this callback may be
|
|
* triggered by socket/NIC software or hardware timestamps.
|
|
*/
|
|
folly::Expected<folly::Unit, LocalErrorCode> registerTxCallback(
|
|
const StreamId id,
|
|
const uint64_t offset,
|
|
ByteEventCallback* cb) override;
|
|
|
|
/**
|
|
* Reset or send a stop sending on all non-control streams. Leaves the
|
|
* connection otherwise unmodified. Note this will also trigger the
|
|
* onStreamWriteError and readError callbacks immediately.
|
|
*/
|
|
void resetNonControlStreams(
|
|
ApplicationErrorCode error,
|
|
folly::StringPiece errorMsg) override;
|
|
|
|
/*
|
|
* Set the background mode priority threshold and the target bw utilization
|
|
* factor to use when in background mode.
|
|
*
|
|
* If all streams have equal or lower priority compares to the threshold
|
|
* (value >= threshold), the connection is considered to be in background
|
|
* mode.
|
|
*/
|
|
void setBackgroundModeParameters(
|
|
PriorityLevel maxBackgroundPriority,
|
|
float backgroundUtilizationFactor);
|
|
|
|
/*
|
|
* Disable background mode by clearing all related parameters.
|
|
*/
|
|
void clearBackgroundModeParameters();
|
|
|
|
virtual void setQLogger(std::shared_ptr<QLogger> qLogger);
|
|
|
|
void setLoopDetectorCallback(std::shared_ptr<LoopDetectorCallback> callback) {
|
|
conn_->loopDetectorCallback = std::move(callback);
|
|
}
|
|
|
|
/**
|
|
* Set the read callback for Datagrams
|
|
*/
|
|
folly::Expected<folly::Unit, LocalErrorCode> setDatagramCallback(
|
|
DatagramCallback* cb) override;
|
|
|
|
/**
|
|
* Returns the maximum allowed Datagram payload size.
|
|
* 0 means Datagram is not supported
|
|
*/
|
|
FOLLY_NODISCARD uint16_t getDatagramSizeLimit() const override;
|
|
|
|
/**
|
|
* Writes a Datagram frame. If buf is larger than the size limit returned by
|
|
* getDatagramSizeLimit(), or if the write buffer is full, buf will simply be
|
|
* dropped, and a LocalErrorCode will be returned to caller.
|
|
*/
|
|
folly::Expected<folly::Unit, LocalErrorCode> writeDatagram(Buf buf) override;
|
|
|
|
/**
|
|
* Returns the currently available received Datagrams.
|
|
* Returns all datagrams if atMost is 0.
|
|
*/
|
|
folly::Expected<std::vector<ReadDatagram>, LocalErrorCode> readDatagrams(
|
|
size_t atMost = 0) override;
|
|
|
|
/**
|
|
* Returns the currently available received Datagram IOBufs.
|
|
* Returns all datagrams if atMost is 0.
|
|
*/
|
|
folly::Expected<std::vector<Buf>, LocalErrorCode> readDatagramBufs(
|
|
size_t atMost = 0) override;
|
|
|
|
/**
|
|
* Set control messages to be sent for socket_ write, note that it's for this
|
|
* specific transport and does not change the other sockets sharing the same
|
|
* fd.
|
|
*/
|
|
void setCmsgs(const folly::SocketCmsgMap& options);
|
|
|
|
void appendCmsgs(const folly::SocketCmsgMap& options);
|
|
|
|
/**
|
|
* Sets the policy per stream group id.
|
|
* If policy == std::nullopt, the policy is removed for corresponding stream
|
|
* group id (reset to the default rtx policy).
|
|
*/
|
|
folly::Expected<folly::Unit, LocalErrorCode>
|
|
setStreamGroupRetransmissionPolicy(
|
|
StreamGroupId groupId,
|
|
std::optional<QuicStreamGroupRetransmissionPolicy> policy) noexcept
|
|
override;
|
|
|
|
[[nodiscard]] const folly::
|
|
F14FastMap<StreamGroupId, QuicStreamGroupRetransmissionPolicy>&
|
|
getStreamGroupRetransmissionPolicies() const {
|
|
return conn_->retransmissionPolicies;
|
|
}
|
|
|
|
[[nodiscard]] QuicAsyncUDPSocket* getUdpSocket() const {
|
|
return socket_.get();
|
|
}
|
|
|
|
protected:
|
|
/*
|
|
* Observe changes in stream priorities and handle background mode.
|
|
*
|
|
* Implements the QuicStreamPrioritiesObserver interface
|
|
*/
|
|
void onStreamPrioritiesChange() override;
|
|
|
|
folly::Expected<folly::Unit, LocalErrorCode> pauseOrResumeRead(
|
|
StreamId id,
|
|
bool resume);
|
|
folly::Expected<folly::Unit, LocalErrorCode> pauseOrResumePeek(
|
|
StreamId id,
|
|
bool resume);
|
|
folly::Expected<folly::Unit, LocalErrorCode> setPeekCallbackInternal(
|
|
StreamId id,
|
|
PeekCallback* cb) noexcept;
|
|
|
|
void schedulePingTimeout(
|
|
PingCallback* callback,
|
|
std::chrono::milliseconds pingTimeout);
|
|
|
|
bool handshakeDoneNotified_{false};
|
|
|
|
uint64_t qlogRefcnt_{0};
|
|
|
|
// Priority level threshold for background streams
|
|
// If all streams have equal or lower priority to the threshold
|
|
// (value >= threshold), the connection is considered to be in background
|
|
// mode.
|
|
Optional<PriorityLevel> backgroundPriorityThreshold_;
|
|
Optional<float> backgroundUtilizationFactor_;
|
|
|
|
private:
|
|
/**
|
|
* Helper to check if using custom retransmission profiles is feasible.
|
|
* Custom retransmission profiles are only applicable when stream groups are
|
|
* enabled, i.e. advertisedMaxStreamGroups in transport settings is > 0.
|
|
*/
|
|
[[nodiscard]] bool checkCustomRetransmissionProfilesEnabled() const;
|
|
};
|
|
|
|
} // namespace quic
|