diff --git a/quic/api/QuicSocket.h b/quic/api/QuicSocket.h index 71aed841b..ff3d933d4 100644 --- a/quic/api/QuicSocket.h +++ b/quic/api/QuicSocket.h @@ -101,6 +101,11 @@ class QuicSocket { */ virtual void onUnidirectionalStreamsAvailable( uint64_t /*numStreamsAvailable*/) noexcept {} + + /** + * Invoked when transport is detected to be app rate limited. + */ + virtual void onAppRateLimited() noexcept {} }; /** diff --git a/quic/api/QuicTransportBase.cpp b/quic/api/QuicTransportBase.cpp index 9772eda3d..eefd54aed 100644 --- a/quic/api/QuicTransportBase.cpp +++ b/quic/api/QuicTransportBase.cpp @@ -2433,6 +2433,7 @@ void QuicTransportBase::writeSocketData() { currentSendBufLen < conn_->udpSendPacketLen && lossBufferEmpty && conn_->congestionController->getWritableBytes()) { conn_->congestionController->setAppLimited(); + connCallback_->onAppRateLimited(); } } } diff --git a/quic/api/test/Mocks.h b/quic/api/test/Mocks.h index 9e266a27a..aeb455423 100644 --- a/quic/api/test/Mocks.h +++ b/quic/api/test/Mocks.h @@ -117,6 +117,7 @@ class MockConnectionCallback : public QuicSocket::ConnectionCallback { , onUnidirectionalStreamsAvailable, void(uint64_t)); + GMOCK_METHOD0_(, noexcept, , onAppRateLimited, void()); }; class MockDeliveryCallback : public QuicSocket::DeliveryCallback { diff --git a/quic/api/test/QuicTransportTest.cpp b/quic/api/test/QuicTransportTest.cpp index 05ddc5b7d..383f2b909 100644 --- a/quic/api/test/QuicTransportTest.cpp +++ b/quic/api/test/QuicTransportTest.cpp @@ -280,6 +280,7 @@ TEST_F(QuicTransportTest, NotAppLimitedWithLoss) { false, nullptr); EXPECT_CALL(*rawCongestionController, setAppLimited()).Times(0); + EXPECT_CALL(connCallback_, onAppRateLimited()).Times(0); loopForWrites(); transport_->close(folly::none); } @@ -307,6 +308,7 @@ TEST_F(QuicTransportTest, NotAppLimitedWithNoWritableBytes) { false, nullptr); EXPECT_CALL(*rawCongestionController, setAppLimited()).Times(0); + EXPECT_CALL(connCallback_, onAppRateLimited()).Times(0); loopForWrites(); transport_->close(folly::none); } @@ -325,6 +327,7 @@ TEST_F(QuicTransportTest, NotAppLimitedWithLargeBuffer) { auto buf = buildRandomInputData(100 * 2000); transport_->writeChain(stream, buf->clone(), false, false, nullptr); EXPECT_CALL(*rawCongestionController, setAppLimited()).Times(0); + EXPECT_CALL(connCallback_, onAppRateLimited()).Times(0); loopForWrites(); transport_->close(folly::none); } @@ -347,6 +350,7 @@ TEST_F(QuicTransportTest, AppLimited) { false, nullptr); EXPECT_CALL(*rawCongestionController, setAppLimited()).Times(1); + EXPECT_CALL(connCallback_, onAppRateLimited()).Times(1); loopForWrites(); transport_->close(folly::none); }