Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions quic/QuicConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ enum class NoWriteReason {
NO_FRAME,
NO_BODY,
SOCKET_FAILURE,
WRITER_BACKPRESSURE, // async writer SPSC queue full
};

enum class NoReadReason {
Expand Down
23 changes: 23 additions & 0 deletions quic/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@

# Auto-generated by quic/facebook/generate_cmake.py - DO NOT EDIT MANUALLY

mvfst_add_library(mvfst_api_quic_packet_writer
EXPORTED_DEPS
mvfst_exception
mvfst_constants
Folly::folly_io_iobuf
Folly::folly_network_address
)

mvfst_add_library(mvfst_api_quic_batch_writer
SRCS
QuicBatchWriter.cpp
Expand Down Expand Up @@ -112,6 +120,20 @@ mvfst_add_library(mvfst_api_transport_lite
Folly::folly_maybe_managed_ptr
)

mvfst_add_library(mvfst_api_shared_threaded_packet_writer
SRCS
SharedThreadedPacketWriter.cpp
DEPS
mvfst_common_mvfst_logging
EXPORTED_DEPS
mvfst_api_quic_packet_writer
mvfst_codec_types
mvfst_common_event_fd_queue
mvfst_common_events_eventbase
Folly::folly
Folly::folly_io_async_async_udp_socket
)

mvfst_add_library(mvfst_api_ack_scheduler
SRCS
QuicAckScheduler.cpp
Expand Down Expand Up @@ -139,6 +161,7 @@ mvfst_add_library(mvfst_api_transport_helpers
EXPORTED_DEPS
mvfst_api_ack_scheduler
mvfst_api_quic_batch_writer
mvfst_api_quic_packet_writer
mvfst_client_state_and_handshake
mvfst_codec
mvfst_codec_pktbuilder
Expand Down
6 changes: 1 addition & 5 deletions quic/api/IoBufQuicBatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@
#pragma once
#include <quic/QuicException.h>
#include <quic/api/QuicBatchWriter.h>
#include <quic/api/QuicPacketWriter.h>
#include <quic/client/state/ClientStateMachine.h>
#include <quic/state/QuicTransportStatsCallback.h>

namespace quic {

struct BufQuicBatchResult {
uint64_t packetsSent{0};
uint64_t bytesSent{0};
};

class IOBufQuicBatch {
public:
IOBufQuicBatch(
Expand Down
58 changes: 58 additions & 0 deletions quic/api/QuicPacketWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 <cstdint>

#include <folly/SocketAddress.h>
#include <folly/io/IOBuf.h>

#include <quic/QuicException.h>
#include <quic/common/Expected.h>

namespace quic {

// Defined here (not in IoBufQuicBatch.h) so StateData.h can include this
// header without pulling in the IoBufQuicBatch → QuicBatchWriter → StateData
// include cycle.
struct BufQuicBatchResult {
uint64_t packetsSent{0};
uint64_t bytesSent{0};
};

/**
* Abstract interface for sending fully-built, encrypted QUIC packets.
*
* The default path (conn.packetWriter == nullptr) calls IOBufQuicBatch
* directly. When conn.packetWriter is set (ChainedMemory data path only),
* writeConnectionDataToSocket dispatches through this interface instead.
*/
class QuicPacketWriter {
public:
virtual ~QuicPacketWriter() = default;

// Called on the EventBase thread. Returns false → stop write loop
// (backpressure, not an error). Returns unexpected → close connection.
[[nodiscard]] virtual quic::Expected<bool, QuicError> write(
BufPtr&& buf,
size_t encodedSize,
const folly::SocketAddress& peerAddr) = 0;

[[nodiscard]] virtual quic::Expected<bool, QuicError> flush() = 0;

// packetsSent counts packets handed to this writer (enqueued or sent inline).
virtual BufQuicBatchResult getResult() const = 0;

// Last retriable errno (EAGAIN/ENOBUFS) seen. Always 0 for async writers —
// errno tracking is internal to their drain thread.
virtual int getLastRetryableErrno() const {
return 0;
}
};

} // namespace quic
9 changes: 9 additions & 0 deletions quic/api/QuicTransportBaseLite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,15 @@ QuicTransportBaseLite::getStreamFlowControl(StreamId id) const {
stream->flowControlState.advertisedMaxOffset);
}

void QuicTransportBaseLite::setPacketWriter(
std::unique_ptr<QuicPacketWriter> writer) {
conn_->packetWriter = std::move(writer);
}

void QuicTransportBaseLite::scheduleWrite() {
runOnEvbAsyncOp({.type = AsyncOpType::ConnectionWriteReady});
}

void QuicTransportBaseLite::runOnEvbAsyncOp(AsyncOpData data) {
auto evb = getEventBase();
evb->runInLoop(
Expand Down
7 changes: 7 additions & 0 deletions quic/api/QuicTransportBaseLite.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,

virtual void cancelAllAppCallbacks(const QuicError& error) noexcept;

// Install a packet writer on the connection. Must be called before accept().
void setPacketWriter(std::unique_ptr<QuicPacketWriter> writer);

// Schedule a write loop iteration on the connection's EventBase. Safe to
// call from any thread; the write will execute on the EventBase thread.
void scheduleWrite();

void scheduleTimeout(
QuicTimerCallback* callback,
std::chrono::milliseconds timeout);
Expand Down
Loading
Loading