1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-08 09:42:06 +03:00

Move core functionality to QuicTransportBaseLite [8/n]

Summary: See title.

Reviewed By: mjoras

Differential Revision: D64065153

fbshipit-source-id: 5c9515dcaba1ef1f30d49f701e366f715854527a
This commit is contained in:
Aman Sharma
2024-10-09 17:37:33 -07:00
committed by Facebook GitHub Bot
parent c62dac180e
commit b7169e3cf7
6 changed files with 247 additions and 277 deletions

View File

@@ -53,17 +53,8 @@ QuicTransportBase::QuicTransportBase(
useConnectionEndWithErrorCallback), useConnectionEndWithErrorCallback),
ackTimeout_(this), ackTimeout_(this),
pathValidationTimeout_(this), pathValidationTimeout_(this),
keepaliveTimeout_(this),
drainTimeout_(this), drainTimeout_(this),
pingTimeout_(this), pingTimeout_(this) {
readLooper_(new FunctionLooper(
evb_,
[this]() { invokeReadDataAndCallbacks(); },
LooperType::ReadLooper)),
peekLooper_(new FunctionLooper(
evb_,
[this]() { invokePeekDataAndCallbacks(); },
LooperType::PeekLooper)) {
writeLooper_->setPacingFunction([this]() -> auto { writeLooper_->setPacingFunction([this]() -> auto {
if (isConnectionPaced(*conn_)) { if (isConnectionPaced(*conn_)) {
return conn_->pacer->getTimeUntilNextWrite(); return conn_->pacer->getTimeUntilNextWrite();
@@ -734,34 +725,6 @@ QuicTransportBase::pauseOrResumeRead(StreamId id, bool resume) {
return folly::unit; return folly::unit;
} }
void QuicTransportBase::updateReadLooper() {
if (closeState_ != CloseState::OPEN) {
VLOG(10) << "Stopping read looper " << *this;
readLooper_->stop();
return;
}
auto iter = std::find_if(
conn_->streamManager->readableStreams().begin(),
conn_->streamManager->readableStreams().end(),
[&readCallbacks = readCallbacks_](StreamId s) {
auto readCb = readCallbacks.find(s);
if (readCb == readCallbacks.end()) {
return false;
}
// TODO: if the stream has an error and it is also paused we should
// still return an error
return readCb->second.readCb && readCb->second.resumed;
});
if (iter != conn_->streamManager->readableStreams().end() ||
!conn_->datagramState.readBuffer.empty()) {
VLOG(10) << "Scheduling read looper " << *this;
readLooper_->run();
} else {
VLOG(10) << "Stopping read looper " << *this;
readLooper_->stop();
}
}
folly::Expected<folly::Unit, LocalErrorCode> QuicTransportBase::setPeekCallback( folly::Expected<folly::Unit, LocalErrorCode> QuicTransportBase::setPeekCallback(
StreamId id, StreamId id,
PeekCallback* cb) { PeekCallback* cb) {
@@ -848,89 +811,6 @@ void QuicTransportBase::invokeStreamsAvailableCallbacks() {
} }
} }
void QuicTransportBase::updatePeekLooper() {
if (peekCallbacks_.empty() || closeState_ != CloseState::OPEN) {
VLOG(10) << "Stopping peek looper " << *this;
peekLooper_->stop();
return;
}
VLOG(10) << "Updating peek looper, has "
<< conn_->streamManager->peekableStreams().size()
<< " peekable streams";
auto iter = std::find_if(
conn_->streamManager->peekableStreams().begin(),
conn_->streamManager->peekableStreams().end(),
[&peekCallbacks = peekCallbacks_](StreamId s) {
VLOG(10) << "Checking stream=" << s;
auto peekCb = peekCallbacks.find(s);
if (peekCb == peekCallbacks.end()) {
VLOG(10) << "No peek callbacks for stream=" << s;
return false;
}
if (!peekCb->second.resumed) {
VLOG(10) << "peek callback for stream=" << s << " not resumed";
}
if (!peekCb->second.peekCb) {
VLOG(10) << "no peekCb in peekCb stream=" << s;
}
return peekCb->second.peekCb && peekCb->second.resumed;
});
if (iter != conn_->streamManager->peekableStreams().end()) {
VLOG(10) << "Scheduling peek looper " << *this;
peekLooper_->run();
} else {
VLOG(10) << "Stopping peek looper " << *this;
peekLooper_->stop();
}
}
void QuicTransportBase::updateWriteLooper(bool thisIteration, bool runInline) {
if (closeState_ == CloseState::CLOSED) {
VLOG(10) << nodeToString(conn_->nodeType)
<< " stopping write looper because conn closed " << *this;
writeLooper_->stop();
return;
}
if (conn_->transportSettings.checkIdleTimerOnWrite) {
checkIdleTimer(Clock::now());
if (closeState_ == CloseState::CLOSED) {
return;
}
}
// If socket writable events are in use, do nothing if we are already waiting
// for the write event.
if (conn_->transportSettings.useSockWritableEvents &&
socket_->isWritableCallbackSet()) {
return;
}
auto writeDataReason = shouldWriteData(*conn_);
if (writeDataReason != WriteDataReason::NO_WRITE) {
VLOG(10) << nodeToString(conn_->nodeType)
<< " running write looper thisIteration=" << thisIteration << " "
<< *this;
writeLooper_->run(thisIteration, runInline);
if (conn_->loopDetectorCallback) {
conn_->writeDebugState.needsWriteLoopDetect =
(conn_->loopDetectorCallback != nullptr);
}
} else {
VLOG(10) << nodeToString(conn_->nodeType) << " stopping write looper "
<< *this;
writeLooper_->stop();
if (conn_->loopDetectorCallback) {
conn_->writeDebugState.needsWriteLoopDetect = false;
conn_->writeDebugState.currentEmptyLoopCount = 0;
}
}
if (conn_->loopDetectorCallback) {
conn_->writeDebugState.writeDataReason = writeDataReason;
}
}
void QuicTransportBase::cancelDeliveryCallbacksForStream(StreamId id) { void QuicTransportBase::cancelDeliveryCallbacksForStream(StreamId id) {
cancelByteEventCallbacksForStream(ByteEvent::Type::ACK, id); cancelByteEventCallbacksForStream(ByteEvent::Type::ACK, id);
} }
@@ -1235,62 +1115,6 @@ void QuicTransportBase::handlePingCallbacks() {
conn_->pendingEvents.cancelPingTimeout = false; conn_->pendingEvents.cancelPingTimeout = false;
} }
void QuicTransportBase::processCallbacksAfterWriteData() {
if (closeState_ != CloseState::OPEN) {
return;
}
auto txStreamId = conn_->streamManager->popTx();
while (txStreamId.has_value()) {
auto streamId = *txStreamId;
auto stream = CHECK_NOTNULL(conn_->streamManager->getStream(streamId));
auto largestOffsetTxed = getLargestWriteOffsetTxed(*stream);
// if it's in the set of streams with TX, we should have a valid offset
CHECK(largestOffsetTxed.has_value());
// lambda to help get the next callback to call for this stream
auto getNextTxCallbackForStreamAndCleanup =
[this, &largestOffsetTxed](
const auto& streamId) -> Optional<ByteEventDetail> {
auto txCallbacksForStreamIt = txCallbacks_.find(streamId);
if (txCallbacksForStreamIt == txCallbacks_.end() ||
txCallbacksForStreamIt->second.empty()) {
return none;
}
auto& txCallbacksForStream = txCallbacksForStreamIt->second;
if (txCallbacksForStream.front().offset > *largestOffsetTxed) {
return none;
}
// extract the callback, pop from the queue, then check for cleanup
auto result = txCallbacksForStream.front();
txCallbacksForStream.pop_front();
if (txCallbacksForStream.empty()) {
txCallbacks_.erase(txCallbacksForStreamIt);
}
return result;
};
Optional<ByteEventDetail> nextOffsetAndCallback;
while (
(nextOffsetAndCallback =
getNextTxCallbackForStreamAndCleanup(streamId))) {
ByteEvent byteEvent{
streamId, nextOffsetAndCallback->offset, ByteEvent::Type::TX};
nextOffsetAndCallback->callback->onByteEvent(byteEvent);
// connection may be closed by callback
if (closeState_ != CloseState::OPEN) {
return;
}
}
// pop the next stream
txStreamId = conn_->streamManager->popTx();
}
}
void QuicTransportBase::handleKnobCallbacks() { void QuicTransportBase::handleKnobCallbacks() {
if (!conn_->transportSettings.advertisedKnobFrameSupport) { if (!conn_->transportSettings.advertisedKnobFrameSupport) {
VLOG(4) << "Received knob frames without advertising support"; VLOG(4) << "Received knob frames without advertising support";
@@ -1770,33 +1594,6 @@ void QuicTransportBase::onNetworkData(
} }
} }
void QuicTransportBase::setIdleTimer() {
if (closeState_ == CloseState::CLOSED) {
return;
}
cancelTimeout(&idleTimeout_);
cancelTimeout(&keepaliveTimeout_);
auto localIdleTimeout = conn_->transportSettings.idleTimeout;
// The local idle timeout being zero means it is disabled.
if (localIdleTimeout == 0ms) {
return;
}
auto peerIdleTimeout =
conn_->peerIdleTimeout > 0ms ? conn_->peerIdleTimeout : localIdleTimeout;
auto idleTimeout = timeMin(localIdleTimeout, peerIdleTimeout);
idleTimeoutCheck_.idleTimeoutMs = idleTimeout;
idleTimeoutCheck_.lastTimeIdleTimeoutScheduled_ = Clock::now();
scheduleTimeout(&idleTimeout_, idleTimeout);
auto idleTimeoutCount = idleTimeout.count();
if (conn_->transportSettings.enableKeepalive) {
std::chrono::milliseconds keepaliveTimeout = std::chrono::milliseconds(
idleTimeoutCount - static_cast<int64_t>(idleTimeoutCount * .15));
scheduleTimeout(&keepaliveTimeout_, keepaliveTimeout);
}
}
uint64_t QuicTransportBase::getNumOpenableBidirectionalStreams() const { uint64_t QuicTransportBase::getNumOpenableBidirectionalStreams() const {
return conn_->streamManager->openableLocalBidirectionalStreams(); return conn_->streamManager->openableLocalBidirectionalStreams();
} }
@@ -2198,12 +1995,6 @@ void QuicTransportBase::pathValidationTimeoutExpired() noexcept {
std::string("Path validation timed out"))); std::string("Path validation timed out")));
} }
void QuicTransportBase::keepaliveTimeoutExpired() noexcept {
[[maybe_unused]] auto self = sharedGuard();
conn_->pendingEvents.sendPing = true;
updateWriteLooper(true, conn_->transportSettings.inlineWriteAfterRead);
}
void QuicTransportBase::scheduleAckTimeout() { void QuicTransportBase::scheduleAckTimeout() {
if (closeState_ == CloseState::CLOSED) { if (closeState_ == CloseState::CLOSED) {
return; return;
@@ -2272,10 +2063,6 @@ void QuicTransportBase::schedulePathValidationTimeout() {
} }
} }
bool QuicTransportBase::isLossTimeoutScheduled() {
return isTimeoutScheduled(&lossTimeout_);
}
void QuicTransportBase::setSupportedVersions( void QuicTransportBase::setSupportedVersions(
const std::vector<QuicVersion>& versions) { const std::vector<QuicVersion>& versions) {
conn_->originalVersion = versions.at(0); conn_->originalVersion = versions.at(0);

View File

@@ -433,24 +433,6 @@ class QuicTransportBase : public QuicSocket,
QuicTransportBase* transport_; QuicTransportBase* transport_;
}; };
class KeepaliveTimeout : public QuicTimerCallback {
public:
~KeepaliveTimeout() override = default;
explicit KeepaliveTimeout(QuicTransportBase* transport)
: transport_(transport) {}
void timeoutExpired() noexcept override {
transport_->keepaliveTimeoutExpired();
}
void callbackCanceled() noexcept override {
// Specifically do nothing since if we got canceled we shouldn't write.
}
private:
QuicTransportBase* transport_;
};
// DrainTimeout is a bit different from other timeouts. It needs to hold a // DrainTimeout is a bit different from other timeouts. It needs to hold a
// shared_ptr to the transport, since if a DrainTimeout is scheduled, // shared_ptr to the transport, since if a DrainTimeout is scheduled,
// transport cannot die. // transport cannot die.
@@ -469,8 +451,6 @@ class QuicTransportBase : public QuicSocket,
QuicTransportBase* transport_; QuicTransportBase* transport_;
}; };
bool isLossTimeoutScheduled() override; // TODO: make this const again
// If you don't set it, the default is Cubic // If you don't set it, the default is Cubic
void setCongestionControl(CongestionControlType type) override; void setCongestionControl(CongestionControlType type) override;
@@ -552,12 +532,8 @@ class QuicTransportBase : public QuicSocket,
void updateCongestionControlSettings( void updateCongestionControlSettings(
const TransportSettings& transportSettings); const TransportSettings& transportSettings);
void updateSocketTosSettings(uint8_t dscpValue); void updateSocketTosSettings(uint8_t dscpValue);
void processCallbacksAfterWriteData() override;
void processCallbacksAfterNetworkData(); void processCallbacksAfterNetworkData();
void invokeStreamsAvailableCallbacks(); void invokeStreamsAvailableCallbacks();
void updateReadLooper() override;
void updatePeekLooper() override;
void updateWriteLooper(bool thisIteration, bool runInline = false) override;
void handlePingCallbacks(); void handlePingCallbacks();
void handleKnobCallbacks(); void handleKnobCallbacks();
void handleAckEventCallbacks(); void handleAckEventCallbacks();
@@ -604,11 +580,9 @@ class QuicTransportBase : public QuicSocket,
void ackTimeoutExpired() noexcept; void ackTimeoutExpired() noexcept;
void pathValidationTimeoutExpired() noexcept; void pathValidationTimeoutExpired() noexcept;
void keepaliveTimeoutExpired() noexcept;
void drainTimeoutExpired() noexcept; void drainTimeoutExpired() noexcept;
void pingTimeoutExpired() noexcept; void pingTimeoutExpired() noexcept;
void setIdleTimer() override;
void scheduleAckTimeout() override; void scheduleAckTimeout() override;
void schedulePathValidationTimeout() override; void schedulePathValidationTimeout() override;
void schedulePingTimeout( void schedulePingTimeout(
@@ -662,11 +636,8 @@ class QuicTransportBase : public QuicSocket,
AckTimeout ackTimeout_; AckTimeout ackTimeout_;
PathValidationTimeout pathValidationTimeout_; PathValidationTimeout pathValidationTimeout_;
KeepaliveTimeout keepaliveTimeout_;
DrainTimeout drainTimeout_; DrainTimeout drainTimeout_;
PingTimeout pingTimeout_; PingTimeout pingTimeout_;
FunctionLooper::Ptr readLooper_;
FunctionLooper::Ptr peekLooper_;
// TODO: This is silly. We need a better solution. // TODO: This is silly. We need a better solution.
// Uninitialied local address as a fallback answer when socket isn't bound. // Uninitialied local address as a fallback answer when socket isn't bound.

View File

@@ -417,6 +417,119 @@ void QuicTransportBaseLite::runOnEvbAsync(
true); true);
} }
void QuicTransportBaseLite::updateWriteLooper(
bool thisIteration,
bool runInline) {
if (closeState_ == CloseState::CLOSED) {
VLOG(10) << nodeToString(conn_->nodeType)
<< " stopping write looper because conn closed " << *this;
writeLooper_->stop();
return;
}
if (conn_->transportSettings.checkIdleTimerOnWrite) {
checkIdleTimer(Clock::now());
if (closeState_ == CloseState::CLOSED) {
return;
}
}
// If socket writable events are in use, do nothing if we are already waiting
// for the write event.
if (conn_->transportSettings.useSockWritableEvents &&
socket_->isWritableCallbackSet()) {
return;
}
auto writeDataReason = shouldWriteData(*conn_);
if (writeDataReason != WriteDataReason::NO_WRITE) {
VLOG(10) << nodeToString(conn_->nodeType)
<< " running write looper thisIteration=" << thisIteration << " "
<< *this;
writeLooper_->run(thisIteration, runInline);
if (conn_->loopDetectorCallback) {
conn_->writeDebugState.needsWriteLoopDetect =
(conn_->loopDetectorCallback != nullptr);
}
} else {
VLOG(10) << nodeToString(conn_->nodeType) << " stopping write looper "
<< *this;
writeLooper_->stop();
if (conn_->loopDetectorCallback) {
conn_->writeDebugState.needsWriteLoopDetect = false;
conn_->writeDebugState.currentEmptyLoopCount = 0;
}
}
if (conn_->loopDetectorCallback) {
conn_->writeDebugState.writeDataReason = writeDataReason;
}
}
void QuicTransportBaseLite::updateReadLooper() {
if (closeState_ != CloseState::OPEN) {
VLOG(10) << "Stopping read looper " << *this;
readLooper_->stop();
return;
}
auto iter = std::find_if(
conn_->streamManager->readableStreams().begin(),
conn_->streamManager->readableStreams().end(),
[&readCallbacks = readCallbacks_](StreamId s) {
auto readCb = readCallbacks.find(s);
if (readCb == readCallbacks.end()) {
return false;
}
// TODO: if the stream has an error and it is also paused we should
// still return an error
return readCb->second.readCb && readCb->second.resumed;
});
if (iter != conn_->streamManager->readableStreams().end() ||
!conn_->datagramState.readBuffer.empty()) {
VLOG(10) << "Scheduling read looper " << *this;
readLooper_->run();
} else {
VLOG(10) << "Stopping read looper " << *this;
readLooper_->stop();
}
}
void QuicTransportBaseLite::updatePeekLooper() {
if (peekCallbacks_.empty() || closeState_ != CloseState::OPEN) {
VLOG(10) << "Stopping peek looper " << *this;
peekLooper_->stop();
return;
}
VLOG(10) << "Updating peek looper, has "
<< conn_->streamManager->peekableStreams().size()
<< " peekable streams";
auto iter = std::find_if(
conn_->streamManager->peekableStreams().begin(),
conn_->streamManager->peekableStreams().end(),
[&peekCallbacks = peekCallbacks_](StreamId s) {
VLOG(10) << "Checking stream=" << s;
auto peekCb = peekCallbacks.find(s);
if (peekCb == peekCallbacks.end()) {
VLOG(10) << "No peek callbacks for stream=" << s;
return false;
}
if (!peekCb->second.resumed) {
VLOG(10) << "peek callback for stream=" << s << " not resumed";
}
if (!peekCb->second.peekCb) {
VLOG(10) << "no peekCb in peekCb stream=" << s;
}
return peekCb->second.peekCb && peekCb->second.resumed;
});
if (iter != conn_->streamManager->peekableStreams().end()) {
VLOG(10) << "Scheduling peek looper " << *this;
peekLooper_->run();
} else {
VLOG(10) << "Stopping peek looper " << *this;
peekLooper_->stop();
}
}
void QuicTransportBaseLite::maybeStopWriteLooperAndArmSocketWritableEvent() { void QuicTransportBaseLite::maybeStopWriteLooperAndArmSocketWritableEvent() {
if (!socket_ || (closeState_ == CloseState::CLOSED)) { if (!socket_ || (closeState_ == CloseState::CLOSED)) {
return; return;
@@ -682,6 +795,12 @@ void QuicTransportBaseLite::idleTimeoutExpired(bool drain) noexcept {
!drain /* sendCloseImmediately */); !drain /* sendCloseImmediately */);
} }
void QuicTransportBaseLite::keepaliveTimeoutExpired() noexcept {
[[maybe_unused]] auto self = sharedGuard();
conn_->pendingEvents.sendPing = true;
updateWriteLooper(true, conn_->transportSettings.inlineWriteAfterRead);
}
bool QuicTransportBaseLite::processCancelCode(const QuicError& cancelCode) { bool QuicTransportBaseLite::processCancelCode(const QuicError& cancelCode) {
bool noError = false; bool noError = false;
switch (cancelCode.code.type()) { switch (cancelCode.code.type()) {
@@ -740,6 +859,10 @@ void QuicTransportBaseLite::cancelLossTimeout() {
cancelTimeout(&lossTimeout_); cancelTimeout(&lossTimeout_);
} }
bool QuicTransportBaseLite::isLossTimeoutScheduled() {
return isTimeoutScheduled(&lossTimeout_);
}
bool QuicTransportBaseLite::isTimeoutScheduled( bool QuicTransportBaseLite::isTimeoutScheduled(
QuicTimerCallback* callback) const { QuicTimerCallback* callback) const {
return callback->isTimerCallbackScheduled(); return callback->isTimerCallbackScheduled();
@@ -857,6 +980,89 @@ void QuicTransportBaseLite::invokePeekDataAndCallbacks() {
} }
} }
void QuicTransportBaseLite::processCallbacksAfterWriteData() {
if (closeState_ != CloseState::OPEN) {
return;
}
auto txStreamId = conn_->streamManager->popTx();
while (txStreamId.has_value()) {
auto streamId = *txStreamId;
auto stream = CHECK_NOTNULL(conn_->streamManager->getStream(streamId));
auto largestOffsetTxed = getLargestWriteOffsetTxed(*stream);
// if it's in the set of streams with TX, we should have a valid offset
CHECK(largestOffsetTxed.has_value());
// lambda to help get the next callback to call for this stream
auto getNextTxCallbackForStreamAndCleanup =
[this, &largestOffsetTxed](
const auto& streamId) -> Optional<ByteEventDetail> {
auto txCallbacksForStreamIt = txCallbacks_.find(streamId);
if (txCallbacksForStreamIt == txCallbacks_.end() ||
txCallbacksForStreamIt->second.empty()) {
return none;
}
auto& txCallbacksForStream = txCallbacksForStreamIt->second;
if (txCallbacksForStream.front().offset > *largestOffsetTxed) {
return none;
}
// extract the callback, pop from the queue, then check for cleanup
auto result = txCallbacksForStream.front();
txCallbacksForStream.pop_front();
if (txCallbacksForStream.empty()) {
txCallbacks_.erase(txCallbacksForStreamIt);
}
return result;
};
Optional<ByteEventDetail> nextOffsetAndCallback;
while (
(nextOffsetAndCallback =
getNextTxCallbackForStreamAndCleanup(streamId))) {
ByteEvent byteEvent{
streamId, nextOffsetAndCallback->offset, ByteEvent::Type::TX};
nextOffsetAndCallback->callback->onByteEvent(byteEvent);
// connection may be closed by callback
if (closeState_ != CloseState::OPEN) {
return;
}
}
// pop the next stream
txStreamId = conn_->streamManager->popTx();
}
}
void QuicTransportBaseLite::setIdleTimer() {
if (closeState_ == CloseState::CLOSED) {
return;
}
cancelTimeout(&idleTimeout_);
cancelTimeout(&keepaliveTimeout_);
auto localIdleTimeout = conn_->transportSettings.idleTimeout;
// The local idle timeout being zero means it is disabled.
if (localIdleTimeout == 0ms) {
return;
}
auto peerIdleTimeout =
conn_->peerIdleTimeout > 0ms ? conn_->peerIdleTimeout : localIdleTimeout;
auto idleTimeout = timeMin(localIdleTimeout, peerIdleTimeout);
idleTimeoutCheck_.idleTimeoutMs = idleTimeout;
idleTimeoutCheck_.lastTimeIdleTimeoutScheduled_ = Clock::now();
scheduleTimeout(&idleTimeout_, idleTimeout);
auto idleTimeoutCount = idleTimeout.count();
if (conn_->transportSettings.enableKeepalive) {
std::chrono::milliseconds keepaliveTimeout = std::chrono::milliseconds(
idleTimeoutCount - static_cast<int64_t>(idleTimeoutCount * .15));
scheduleTimeout(&keepaliveTimeout_, keepaliveTimeout);
}
}
void QuicTransportBaseLite::updatePacketProcessorsPrewriteRequests() { void QuicTransportBaseLite::updatePacketProcessorsPrewriteRequests() {
folly::SocketCmsgMap cmsgs; folly::SocketCmsgMap cmsgs;
for (const auto& pp : conn_->packetProcessors) { for (const auto& pp : conn_->packetProcessors) {

View File

@@ -27,10 +27,19 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,
lossTimeout_(this), lossTimeout_(this),
excessWriteTimeout_(this), excessWriteTimeout_(this),
idleTimeout_(this), idleTimeout_(this),
keepaliveTimeout_(this),
writeLooper_(new FunctionLooper( writeLooper_(new FunctionLooper(
evb_, evb_,
[this]() { pacedWriteDataToSocket(); }, [this]() { pacedWriteDataToSocket(); },
LooperType::WriteLooper)) {} LooperType::WriteLooper)),
readLooper_(new FunctionLooper(
evb_,
[this]() { invokeReadDataAndCallbacks(); },
LooperType::ReadLooper)),
peekLooper_(new FunctionLooper(
evb_,
[this]() { invokePeekDataAndCallbacks(); },
LooperType::PeekLooper)) {}
/** /**
* Invoked when we have to write some data to the wire. * Invoked when we have to write some data to the wire.
@@ -172,15 +181,29 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,
QuicTransportBaseLite* transport_; QuicTransportBaseLite* transport_;
}; };
class KeepaliveTimeout : public QuicTimerCallback {
public:
~KeepaliveTimeout() override = default;
explicit KeepaliveTimeout(QuicTransportBaseLite* transport)
: transport_(transport) {}
void timeoutExpired() noexcept override {
transport_->keepaliveTimeoutExpired();
}
void callbackCanceled() noexcept override {
// Specifically do nothing since if we got canceled we shouldn't write.
}
private:
QuicTransportBaseLite* transport_;
};
void scheduleLossTimeout(std::chrono::milliseconds timeout); void scheduleLossTimeout(std::chrono::milliseconds timeout);
void cancelLossTimeout(); void cancelLossTimeout();
virtual bool isLossTimeoutScheduled() { bool isLossTimeoutScheduled();
// TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier
return false;
}
/** /**
* Returns a shared_ptr which can be used as a guard to keep this * Returns a shared_ptr which can be used as a guard to keep this
@@ -231,22 +254,9 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,
void runOnEvbAsync( void runOnEvbAsync(
folly::Function<void(std::shared_ptr<QuicTransportBaseLite>)> func); folly::Function<void(std::shared_ptr<QuicTransportBaseLite>)> func);
virtual void updateWriteLooper( void updateWriteLooper(bool thisIteration, bool runInline = false);
bool /* thisIteration */, void updateReadLooper();
bool /* runInline */ = false) { void updatePeekLooper();
// TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier
}
virtual void updateReadLooper() {
// TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier
}
virtual void updatePeekLooper() {
// TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier
}
void maybeStopWriteLooperAndArmSocketWritableEvent(); void maybeStopWriteLooperAndArmSocketWritableEvent();
@@ -260,6 +270,7 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,
void excessWriteTimeoutExpired() noexcept; void excessWriteTimeoutExpired() noexcept;
void lossTimeoutExpired() noexcept; void lossTimeoutExpired() noexcept;
void idleTimeoutExpired(bool drain) noexcept; void idleTimeoutExpired(bool drain) noexcept;
void keepaliveTimeoutExpired() noexcept;
bool isTimeoutScheduled(QuicTimerCallback* callback) const; bool isTimeoutScheduled(QuicTimerCallback* callback) const;
@@ -284,15 +295,9 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,
// qualifier // qualifier
} }
virtual void processCallbacksAfterWriteData() { void processCallbacksAfterWriteData();
// TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier
}
virtual void setIdleTimer() { void setIdleTimer();
// TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier
}
virtual void scheduleAckTimeout() { virtual void scheduleAckTimeout() {
// TODO: Fill this in from QuicTransportBase and remove the "virtual" // TODO: Fill this in from QuicTransportBase and remove the "virtual"
// qualifier // qualifier
@@ -377,8 +382,11 @@ class QuicTransportBaseLite : virtual public QuicSocketLite,
LossTimeout lossTimeout_; LossTimeout lossTimeout_;
ExcessWriteTimeout excessWriteTimeout_; ExcessWriteTimeout excessWriteTimeout_;
IdleTimeout idleTimeout_; IdleTimeout idleTimeout_;
KeepaliveTimeout keepaliveTimeout_;
FunctionLooper::Ptr writeLooper_; FunctionLooper::Ptr writeLooper_;
FunctionLooper::Ptr readLooper_;
FunctionLooper::Ptr peekLooper_;
Optional<std::string> exceptionCloseWhat_; Optional<std::string> exceptionCloseWhat_;

View File

@@ -588,8 +588,7 @@ class TestQuicTransport
return none; return none;
} }
void updateWriteLooper(bool thisIteration, bool /* runInline */ = false) void updateWriteLooper(bool thisIteration, bool /* runInline */ = false) {
override {
QuicTransportBase::updateWriteLooper(thisIteration); QuicTransportBase::updateWriteLooper(thisIteration);
} }

View File

@@ -74,8 +74,7 @@ class TestQuicTransport
return conn.version.value_or(*conn.originalVersion); return conn.version.value_or(*conn.originalVersion);
} }
void updateWriteLooper(bool thisIteration, bool /* runInline */ = false) void updateWriteLooper(bool thisIteration, bool /* runInline */ = false) {
override {
QuicTransportBase::updateWriteLooper(thisIteration); QuicTransportBase::updateWriteLooper(thisIteration);
} }