Http2: Ignore RST frames on already-closed streams
Some http servers like to send RST frames whenever they send their response. The stream is already closed at that point so it's a little weird, but the RFC doesn't disallow it, so we'll just ignore the frames. Fixes: QTBUG-132124 Change-Id: Ic26e249437b739830935e2f3feec572687579b21 Reviewed-by: Øystein Heskestad <oystein.heskestad@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> (cherry picked from commit 2c71fdf043ca94d1c567f169d51245e2702bec19) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
aac98b795d
commit
0a4ff045f1
@ -708,6 +708,9 @@ void QHttp2Stream::handleHEADERS(Http2::FrameFlags frameFlags, const HPack::Http
|
||||
|
||||
void QHttp2Stream::handleRST_STREAM(const Frame &inboundFrame)
|
||||
{
|
||||
if (m_state == State::Closed) // The stream is already closed, we're not sending anything anyway
|
||||
return;
|
||||
|
||||
transitionState(StateTransition::RST);
|
||||
m_RST_STREAM_received = qFromBigEndian<quint32>(inboundFrame.dataBegin());
|
||||
if (isUploadingDATA()) {
|
||||
|
@ -24,6 +24,7 @@ private slots:
|
||||
void testRSTServerSide();
|
||||
void testRSTClientSide();
|
||||
void testRSTReplyOnDATAEND();
|
||||
void resetAfterClose();
|
||||
void testBadFrameSize_data();
|
||||
void testBadFrameSize();
|
||||
void testDataFrameAfterRSTIncoming();
|
||||
@ -420,6 +421,46 @@ void tst_QHttp2Connection::testRSTReplyOnDATAEND()
|
||||
QCOMPARE(errrorServerSpy.count(), 1);
|
||||
}
|
||||
|
||||
void tst_QHttp2Connection::resetAfterClose()
|
||||
{
|
||||
auto [client, server] = makeFakeConnectedSockets();
|
||||
auto connection = makeHttp2Connection(client.get(), {}, Client);
|
||||
auto serverConnection = makeHttp2Connection(server.get(), {}, Server);
|
||||
|
||||
QHttp2Stream *clientStream = connection->createStream().unwrap();
|
||||
QVERIFY(clientStream);
|
||||
QVERIFY(waitForSettingsExchange(connection, serverConnection));
|
||||
|
||||
QSignalSpy newIncomingStreamSpy{ serverConnection, &QHttp2Connection::newIncomingStream };
|
||||
|
||||
QSignalSpy clientHeaderReceivedSpy{ clientStream, &QHttp2Stream::headersReceived };
|
||||
HPack::HttpHeader headers = getRequiredHeaders();
|
||||
clientStream->sendHEADERS(headers, true);
|
||||
|
||||
QVERIFY(newIncomingStreamSpy.wait());
|
||||
auto *serverStream = newIncomingStreamSpy.front().front().value<QHttp2Stream *>();
|
||||
QCOMPARE(clientStream->streamID(), serverStream->streamID());
|
||||
|
||||
QSignalSpy errorSpy(clientStream, &QHttp2Stream::errorOccurred);
|
||||
|
||||
const HPack::HttpHeader StatusOKHeaders{ { ":status", "200" } };
|
||||
serverStream->sendHEADERS(StatusOKHeaders, true);
|
||||
|
||||
// Write the RST_STREAM frame manually because we guard against sending RST_STREAM on closed
|
||||
// streams
|
||||
auto &frameWriter = serverConnection->frameWriter;
|
||||
frameWriter.start(Http2::FrameType::RST_STREAM, Http2::FrameFlag::EMPTY,
|
||||
serverStream->streamID());
|
||||
frameWriter.append(quint32(Http2::Http2Error::STREAM_CLOSED));
|
||||
QVERIFY(frameWriter.write(*serverConnection->getSocket()));
|
||||
|
||||
QVERIFY(clientHeaderReceivedSpy.wait());
|
||||
QCOMPARE(clientStream->state(), QHttp2Stream::State::Closed);
|
||||
|
||||
QTest::qWait(10); // Just needs to process events basically
|
||||
QCOMPARE(errorSpy.count(), 0);
|
||||
}
|
||||
|
||||
void tst_QHttp2Connection::testBadFrameSize_data()
|
||||
{
|
||||
QTest::addColumn<uchar>("frametype");
|
||||
|
Loading…
x
Reference in New Issue
Block a user