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

Translate API closes to Application closes on the wire.

Summary: Previously we would end up writing a non-application close when the application calls close(folly::none). This isn't correct, as those cases should be an application error with no error.

Reviewed By: afrind

Differential Revision: D20518529

fbshipit-source-id: fe069cccc32bd550fb3ec599694110955816993f
This commit is contained in:
Matt Joras
2020-03-18 19:45:00 -07:00
committed by Facebook GitHub Bot
parent 2f94d3d0e0
commit 42e49bb262
5 changed files with 28 additions and 9 deletions

View File

@@ -178,6 +178,10 @@ std::string cryptoErrorToString(TransportErrorCode code) {
std::string toString(QuicErrorCode code) { std::string toString(QuicErrorCode code) {
switch (code.type()) { switch (code.type()) {
case QuicErrorCode::Type::ApplicationErrorCode_E: case QuicErrorCode::Type::ApplicationErrorCode_E:
if (*code.asApplicationErrorCode() ==
GenericApplicationErrorCode::NO_ERROR) {
return "No Error";
}
return folly::to<std::string>(*code.asApplicationErrorCode()); return folly::to<std::string>(*code.asApplicationErrorCode());
case QuicErrorCode::Type::LocalErrorCode_E: case QuicErrorCode::Type::LocalErrorCode_E:
return toString(*code.asLocalErrorCode()).str(); return toString(*code.asLocalErrorCode()).str();

View File

@@ -147,6 +147,13 @@ void QuicTransportBase::close(
// explicitly called close. // explicitly called close.
connCallback_ = nullptr; connCallback_ = nullptr;
// If we were called with no error code, ensure that we are going to write
// an application close, so the peer knows it didn't come from the transport.
if (!errorCode) {
errorCode = std::make_pair(
GenericApplicationErrorCode::NO_ERROR,
toString(GenericApplicationErrorCode::NO_ERROR));
}
closeImpl(std::move(errorCode), true); closeImpl(std::move(errorCode), true);
conn_->logger.reset(); conn_->logger.reset();
} }
@@ -156,6 +163,11 @@ void QuicTransportBase::closeNow(
DCHECK(getEventBase() && getEventBase()->isInEventBaseThread()); DCHECK(getEventBase() && getEventBase()->isInEventBaseThread());
FOLLY_MAYBE_UNUSED auto self = sharedGuard(); FOLLY_MAYBE_UNUSED auto self = sharedGuard();
VLOG(4) << __func__ << " " << *this; VLOG(4) << __func__ << " " << *this;
if (!errorCode) {
errorCode = std::make_pair(
GenericApplicationErrorCode::NO_ERROR,
toString(GenericApplicationErrorCode::NO_ERROR));
}
closeImpl(std::move(errorCode), false); closeImpl(std::move(errorCode), false);
// the drain timeout may have been scheduled by a previous close, in which // the drain timeout may have been scheduled by a previous close, in which
// case, our close would not take effect. This cancels the drain timeout in // case, our close would not take effect. This cancels the drain timeout in

View File

@@ -1243,7 +1243,9 @@ TEST_F(QuicTransportImplTest, RegisterDeliveryCallbackLowerThanExpectedClose) {
TEST_F(QuicTransportImplTest, TestNotifyPendingConnWriteOnCloseWithoutError) { TEST_F(QuicTransportImplTest, TestNotifyPendingConnWriteOnCloseWithoutError) {
NiceMock<MockWriteCallback> wcb; NiceMock<MockWriteCallback> wcb;
EXPECT_CALL(wcb, onConnectionWriteError(IsError(LocalErrorCode::NO_ERROR))); EXPECT_CALL(
wcb,
onConnectionWriteError(IsError(GenericApplicationErrorCode::NO_ERROR)));
transport->notifyPendingWriteOnConnection(&wcb); transport->notifyPendingWriteOnConnection(&wcb);
transport->close(folly::none); transport->close(folly::none);
evb->loopOnce(); evb->loopOnce();
@@ -1281,7 +1283,9 @@ TEST_F(QuicTransportImplTest, TestNotifyPendingWriteOnCloseWithoutError) {
auto stream = transport->createBidirectionalStream().value(); auto stream = transport->createBidirectionalStream().value();
NiceMock<MockWriteCallback> wcb; NiceMock<MockWriteCallback> wcb;
EXPECT_CALL( EXPECT_CALL(
wcb, onStreamWriteError(stream, IsError(LocalErrorCode::NO_ERROR))); wcb,
onStreamWriteError(
stream, IsError(GenericApplicationErrorCode::NO_ERROR)));
transport->notifyPendingWriteOnStream(stream, &wcb); transport->notifyPendingWriteOnStream(stream, &wcb);
transport->close(folly::none); transport->close(folly::none);
evb->loopOnce(); evb->loopOnce();
@@ -1369,7 +1373,8 @@ TEST_F(QuicTransportImplTest, TestGracefulCloseWithNoActiveStream) {
NiceMock<MockWriteCallback> wcbConn; NiceMock<MockWriteCallback> wcbConn;
NiceMock<MockReadCallback> rcb; NiceMock<MockReadCallback> rcb;
NiceMock<MockDeliveryCallback> deliveryCb; NiceMock<MockDeliveryCallback> deliveryCb;
EXPECT_CALL(rcb, readError(stream, IsError(LocalErrorCode::NO_ERROR))); EXPECT_CALL(
rcb, readError(stream, IsError(GenericApplicationErrorCode::NO_ERROR)));
EXPECT_CALL(deliveryCb, onDeliveryAck(stream, _, _)); EXPECT_CALL(deliveryCb, onDeliveryAck(stream, _, _));
EXPECT_CALL(connCallback, onConnectionEnd()).Times(0); EXPECT_CALL(connCallback, onConnectionEnd()).Times(0);

View File

@@ -1862,7 +1862,7 @@ TEST_F(QuicClientTransportTest, SocketClosedDuringOnTransportReady) {
setupCryptoLayer(); setupCryptoLayer();
client->start(&callback); client->start(&callback);
setConnectionIds(); setConnectionIds();
recvServerHello(); EXPECT_THROW(recvServerHello(), std::runtime_error);
} }
TEST_F(QuicClientTransportTest, NetworkUnreachableIsFatalToConn) { TEST_F(QuicClientTransportTest, NetworkUnreachableIsFatalToConn) {
@@ -3597,10 +3597,8 @@ TEST_P(
EXPECT_EQ(indices.size(), 1); EXPECT_EQ(indices.size(), 1);
auto tmp = std::move(qLogger->logs[indices[0]]); auto tmp = std::move(qLogger->logs[indices[0]]);
auto event = dynamic_cast<QLogConnectionCloseEvent*>(tmp.get()); auto event = dynamic_cast<QLogConnectionCloseEvent*>(tmp.get());
EXPECT_EQ(event->error, kNoError); EXPECT_EQ(event->error, "No Error");
auto reason = folly::to<std::string>( EXPECT_EQ(event->reason, "No Error");
"Server: ", kNoError, ", Peer: isReset: ", 0, ", Peer: isAbandon: ", 0);
EXPECT_EQ(event->reason, reason);
EXPECT_TRUE(event->drainConnection); EXPECT_TRUE(event->drainConnection);
EXPECT_TRUE(event->sendCloseImmediately); EXPECT_TRUE(event->sendCloseImmediately);
} }

View File

@@ -1669,7 +1669,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterReset) {
.WillOnce(Invoke([&](StreamId /*sid*/, ApplicationErrorCode /*e*/) { .WillOnce(Invoke([&](StreamId /*sid*/, ApplicationErrorCode /*e*/) {
server->close(folly::none); server->close(folly::none);
})); }));
deliverData(packetToBuf(packet)); EXPECT_THROW(deliverData(packetToBuf(packet)), std::runtime_error);
} }
TEST_F(QuicServerTransportTest, StopSendingLoss) { TEST_F(QuicServerTransportTest, StopSendingLoss) {