mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-06 22:22:38 +03:00
Add idle timer checker
Reviewed By: mjoras Differential Revision: D60913168 fbshipit-source-id: 1b14a2e17545ba24f879e7212153eee19cfe9972
This commit is contained in:
committed by
Facebook GitHub Bot
parent
901fcc5847
commit
b51ee87995
@@ -1122,6 +1122,13 @@ void QuicTransportBase::updateWriteLooper(bool thisIteration) {
|
|||||||
return;
|
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
|
// If socket writable events are in use, do nothing if we are already waiting
|
||||||
// for the write event.
|
// for the write event.
|
||||||
if (conn_->transportSettings.useSockWritableEvents &&
|
if (conn_->transportSettings.useSockWritableEvents &&
|
||||||
@@ -1961,6 +1968,34 @@ void QuicTransportBase::onNetworkData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuicTransportBase::checkIdleTimer(TimePoint now) {
|
||||||
|
if (closeState_ == CloseState::CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!idleTimeout_.isTimerCallbackScheduled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!idleTimeoutCheck_.lastTimeIdleTimeoutScheduled_.has_value()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (idleTimeoutCheck_.forcedIdleTimeoutScheduled_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((now - *idleTimeoutCheck_.lastTimeIdleTimeoutScheduled_) >=
|
||||||
|
idleTimeoutCheck_.idleTimeoutMs) {
|
||||||
|
// Call timer expiration async.
|
||||||
|
idleTimeoutCheck_.forcedIdleTimeoutScheduled_ = true;
|
||||||
|
runOnEvbAsync([](auto self) {
|
||||||
|
if (!self->good() || self->closeState_ == CloseState::CLOSED) {
|
||||||
|
// The connection was probably closed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->idleTimeout_.timeoutExpired();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QuicTransportBase::setIdleTimer() {
|
void QuicTransportBase::setIdleTimer() {
|
||||||
if (closeState_ == CloseState::CLOSED) {
|
if (closeState_ == CloseState::CLOSED) {
|
||||||
return;
|
return;
|
||||||
@@ -1975,6 +2010,10 @@ void QuicTransportBase::setIdleTimer() {
|
|||||||
auto peerIdleTimeout =
|
auto peerIdleTimeout =
|
||||||
conn_->peerIdleTimeout > 0ms ? conn_->peerIdleTimeout : localIdleTimeout;
|
conn_->peerIdleTimeout > 0ms ? conn_->peerIdleTimeout : localIdleTimeout;
|
||||||
auto idleTimeout = timeMin(localIdleTimeout, peerIdleTimeout);
|
auto idleTimeout = timeMin(localIdleTimeout, peerIdleTimeout);
|
||||||
|
|
||||||
|
idleTimeoutCheck_.idleTimeoutMs = idleTimeout;
|
||||||
|
idleTimeoutCheck_.lastTimeIdleTimeoutScheduled_ = Clock::now();
|
||||||
|
|
||||||
scheduleTimeout(&idleTimeout_, idleTimeout);
|
scheduleTimeout(&idleTimeout_, idleTimeout);
|
||||||
auto idleTimeoutCount = idleTimeout.count();
|
auto idleTimeoutCount = idleTimeout.count();
|
||||||
if (conn_->transportSettings.enableKeepalive) {
|
if (conn_->transportSettings.enableKeepalive) {
|
||||||
|
@@ -1015,6 +1015,18 @@ class QuicTransportBase : public QuicSocket,
|
|||||||
void onSocketWritable() noexcept override;
|
void onSocketWritable() noexcept override;
|
||||||
void maybeStopWriteLooperAndArmSocketWritableEvent();
|
void maybeStopWriteLooperAndArmSocketWritableEvent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the idle timer on write events, and if it's past the idle timeout,
|
||||||
|
* calls the timer finctions.
|
||||||
|
*/
|
||||||
|
void checkIdleTimer(TimePoint now);
|
||||||
|
struct IdleTimeoutCheck {
|
||||||
|
std::chrono::milliseconds idleTimeoutMs{0};
|
||||||
|
Optional<TimePoint> lastTimeIdleTimeoutScheduled_;
|
||||||
|
bool forcedIdleTimeoutScheduled_{false};
|
||||||
|
};
|
||||||
|
IdleTimeoutCheck idleTimeoutCheck_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Helper functions to handle new streams.
|
* Helper functions to handle new streams.
|
||||||
|
@@ -413,6 +413,14 @@ class TestQuicTransport
|
|||||||
return readLooper_;
|
return readLooper_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runCheckIdleTimer(TimePoint now) {
|
||||||
|
checkIdleTimer(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
const IdleTimeoutCheck& getIdleTimeoutCheck() {
|
||||||
|
return idleTimeoutCheck_;
|
||||||
|
}
|
||||||
|
|
||||||
void unbindConnection() {}
|
void unbindConnection() {}
|
||||||
|
|
||||||
void onReadError(const folly::AsyncSocketException&) noexcept {}
|
void onReadError(const folly::AsyncSocketException&) noexcept {}
|
||||||
@@ -4961,5 +4969,46 @@ TEST_P(
|
|||||||
transport.reset();
|
transport.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(QuicTransportImplTestBase, TestCheckIdleTimerTimerActiveConnNotExpired) {
|
||||||
|
auto transportSettings = transport->getTransportSettings();
|
||||||
|
transportSettings.checkIdleTimerOnWrite = true;
|
||||||
|
transport->setTransportSettings(transportSettings);
|
||||||
|
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||||
|
transportSettings);
|
||||||
|
|
||||||
|
transport->transportConn->oneRttWriteCipher = test::createNoOpAead();
|
||||||
|
EXPECT_FALSE(transport->isClosed());
|
||||||
|
|
||||||
|
transport->setIdleTimeout();
|
||||||
|
transport->runCheckIdleTimer(Clock::now());
|
||||||
|
qEvb->loopOnce();
|
||||||
|
|
||||||
|
EXPECT_FALSE(transport->isClosed());
|
||||||
|
|
||||||
|
transport.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(QuicTransportImplTestBase, TestCheckIdleTimerTimerActiveConnExpired) {
|
||||||
|
auto transportSettings = transport->getTransportSettings();
|
||||||
|
transportSettings.checkIdleTimerOnWrite = true;
|
||||||
|
transport->setTransportSettings(transportSettings);
|
||||||
|
transport->getConnectionState().streamManager->refreshTransportSettings(
|
||||||
|
transportSettings);
|
||||||
|
|
||||||
|
transport->transportConn->oneRttWriteCipher = test::createNoOpAead();
|
||||||
|
EXPECT_FALSE(transport->isClosed());
|
||||||
|
|
||||||
|
transport->setIdleTimeout();
|
||||||
|
const auto& idleTimerCheck = transport->getIdleTimeoutCheck();
|
||||||
|
TimePoint fakeFutureTs = Clock::now() +
|
||||||
|
std::chrono::milliseconds(idleTimerCheck.idleTimeoutMs.count() + 1000);
|
||||||
|
transport->runCheckIdleTimer(fakeFutureTs);
|
||||||
|
qEvb->loopOnce();
|
||||||
|
|
||||||
|
EXPECT_TRUE(transport->isClosed());
|
||||||
|
|
||||||
|
transport.reset();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
@@ -395,6 +395,8 @@ struct TransportSettings {
|
|||||||
// If flow control updates should be sent based on time passed since last
|
// If flow control updates should be sent based on time passed since last
|
||||||
// update.
|
// update.
|
||||||
bool enableFlowControlTimeBasedUpdates{true};
|
bool enableFlowControlTimeBasedUpdates{true};
|
||||||
|
// Check if idle timer needs to be triggered manually.
|
||||||
|
bool checkIdleTimerOnWrite{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
Reference in New Issue
Block a user