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

No-op StopSending If Ingress Closed

Summary: - as title, we should just no-op ::StopSending when ingress is already closed

Reviewed By: jbeshay, mjoras

Differential Revision: D40990383

fbshipit-source-id: e0cd64facf78f510eabe8198e93a643c6ebfb89e
This commit is contained in:
Hani Damlaj
2022-11-04 19:00:24 -07:00
committed by Facebook GitHub Bot
parent 79cf450bbf
commit e1f8e0df1d
2 changed files with 51 additions and 0 deletions

View File

@@ -806,6 +806,13 @@ folly::Expected<folly::Unit, LocalErrorCode> QuicTransportBase::stopSending(
if (!conn_->streamManager->streamExists(id)) { if (!conn_->streamManager->streamExists(id)) {
return folly::makeUnexpected(LocalErrorCode::STREAM_NOT_EXISTS); return folly::makeUnexpected(LocalErrorCode::STREAM_NOT_EXISTS);
} }
auto* stream = CHECK_NOTNULL(conn_->streamManager->getStream(id));
if (stream->recvState == StreamRecvState::Closed) {
// skip STOP_SENDING if ingress is already closed
return folly::unit;
}
// send STOP_SENDING frame to peer
sendSimpleFrame(*conn_, StopSendingFrame(id, error)); sendSimpleFrame(*conn_, StopSendingFrame(id, error));
updateWriteLooper(true); updateWriteLooper(true);
return folly::unit; return folly::unit;

View File

@@ -19,6 +19,7 @@
#include <quic/state/DatagramHandlers.h> #include <quic/state/DatagramHandlers.h>
#include <quic/state/QuicStreamFunctions.h> #include <quic/state/QuicStreamFunctions.h>
#include <quic/state/QuicStreamUtilities.h> #include <quic/state/QuicStreamUtilities.h>
#include <quic/state/stream/StreamReceiveHandlers.h>
#include <quic/state/test/Mocks.h> #include <quic/state/test/Mocks.h>
#include <folly/io/async/test/MockAsyncUDPSocket.h> #include <folly/io/async/test/MockAsyncUDPSocket.h>
@@ -666,6 +667,49 @@ TEST_P(QuicTransportImplTestBase, IdleTimeoutStreamMaessage) {
transport->invokeIdleTimeout(); transport->invokeIdleTimeout();
} }
TEST_P(QuicTransportImplTestBase, StopSendingClosesIngress) {
// create bidi stream
auto streamID = transport->createBidirectionalStream().value();
auto* stream = CHECK_NOTNULL(transport->getStream(streamID));
EXPECT_EQ(stream->sendState, StreamSendState::Open);
EXPECT_EQ(stream->recvState, StreamRecvState::Open);
// suppose we rx a reset from peer which closes our ingress SM
receiveRstStreamSMHandler(
*stream,
RstStreamFrame(stream->id, GenericApplicationErrorCode::NO_ERROR, 0));
EXPECT_EQ(stream->sendState, StreamSendState::Open);
EXPECT_EQ(stream->recvState, StreamRecvState::Closed);
// send stop sending to peer should no-op
transport->stopSending(streamID, GenericApplicationErrorCode::NO_ERROR);
EXPECT_EQ(transport->transportConn->pendingEvents.frames.size(), 0);
// now test ingress uni-directional stream
auto& streamManager = *transport->transportConn->streamManager;
auto nextPeerUniStream =
streamManager.nextAcceptablePeerUnidirectionalStreamId();
EXPECT_TRUE(nextPeerUniStream.has_value());
stream = streamManager.getStream(*nextPeerUniStream);
EXPECT_EQ(stream->sendState, StreamSendState::Invalid);
EXPECT_EQ(stream->recvState, StreamRecvState::Open);
// suppose we rx a reset from peer which closes our ingress SM
receiveRstStreamSMHandler(
*stream,
RstStreamFrame(stream->id, GenericApplicationErrorCode::NO_ERROR, 0));
EXPECT_EQ(stream->sendState, StreamSendState::Invalid);
EXPECT_EQ(stream->recvState, StreamRecvState::Closed);
EXPECT_TRUE(stream->inTerminalStates());
// send stop sending to peer should no-op
transport->stopSending(stream->id, GenericApplicationErrorCode::NO_ERROR);
EXPECT_EQ(transport->transportConn->pendingEvents.frames.size(), 0);
transport.reset();
}
TEST_P(QuicTransportImplTestBase, WriteAckPacketUnsetsLooper) { TEST_P(QuicTransportImplTestBase, WriteAckPacketUnsetsLooper) {
// start looper in running state first // start looper in running state first
transport->writeLooper()->run(true); transport->writeLooper()->run(true);