diff options
-rw-r--r-- | src/network/access/http2/http2protocol.cpp | 10 | ||||
-rw-r--r-- | tests/auto/network/access/http2/http2srv.cpp | 6 | ||||
-rw-r--r-- | tests/auto/network/access/http2/http2srv.h | 1 | ||||
-rw-r--r-- | tests/auto/network/access/http2/tst_http2.cpp | 70 |
4 files changed, 83 insertions, 4 deletions
diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp index 0290f9ac00..31da6fd616 100644 --- a/src/network/access/http2/http2protocol.cpp +++ b/src/network/access/http2/http2protocol.cpp @@ -75,9 +75,13 @@ Frame configurationToSettingsFrame(const QHttp2Configuration &config) builder.append(Settings::INITIAL_WINDOW_SIZE_ID); builder.append(config.streamReceiveWindowSize()); - // TODO: Max frame size; in future, if the need - // is proven, we can also set decoding table size - // and header list size. For now, defaults suffice. + if (config.maxFrameSize() != minPayloadLimit) { + builder.append(Settings::MAX_FRAME_SIZE_ID); + builder.append(config.maxFrameSize()); + } + // TODO: In future, if the need is proven, we can + // also send decoding table size and header list size. + // For now, defaults suffice. return builder.outboundFrame(); } diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp index 1ddb6aa77d..a8eebf5a24 100644 --- a/tests/auto/network/access/http2/http2srv.cpp +++ b/tests/auto/network/access/http2/http2srv.cpp @@ -218,7 +218,7 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize) quint32 bytesToSend = std::min<quint32>(windowSize, responseBody.size() - offset); quint32 bytesSent = 0; - const quint32 frameSizeLimit(clientSetting(Settings::MAX_FRAME_SIZE_ID, Http2::maxPayloadSize)); + const quint32 frameSizeLimit(clientSetting(Settings::MAX_FRAME_SIZE_ID, Http2::minPayloadLimit)); const uchar *src = reinterpret_cast<const uchar *>(responseBody.constData() + offset); const bool last = offset + bytesToSend == quint32(responseBody.size()); @@ -236,6 +236,10 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize) src += chunkSize; bytesToSend -= chunkSize; bytesSent += chunkSize; + if (frameSizeLimit != Http2::minPayloadLimit) { + // Our test is probably interested in how many DATA frames were sent. + emit sendingData(); + } } if (interrupted.loadAcquire()) diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h index 9cb846b0b3..3105684d59 100644 --- a/tests/auto/network/access/http2/http2srv.h +++ b/tests/auto/network/access/http2/http2srv.h @@ -128,6 +128,7 @@ Q_SIGNALS: void receivedRequest(quint32 streamID); void receivedData(quint32 streamID); void windowUpdate(quint32 streamID); + void sendingData(); private slots: void connectionEstablished(); diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 6a0dc6db02..e24a06bc34 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -82,6 +82,8 @@ RawSettings qt_H2ConfigurationToSettings(const QHttp2Configuration &config = qt_ RawSettings settings; settings[Http2::Settings::ENABLE_PUSH_ID] = config.serverPushEnabled(); settings[Http2::Settings::INITIAL_WINDOW_SIZE_ID] = config.streamReceiveWindowSize(); + if (config.maxFrameSize() != Http2::minPayloadLimit) + settings[Http2::Settings::MAX_FRAME_SIZE_ID] = config.maxFrameSize(); return settings; } @@ -107,6 +109,7 @@ private slots: void earlyResponse(); void connectToHost_data(); void connectToHost(); + void maxFrameSize(); protected slots: // Slots to listen to our in-process server: @@ -696,6 +699,73 @@ void tst_Http2::connectToHost() QVERIFY(reply->isFinished()); } +void tst_Http2::maxFrameSize() +{ +#if !QT_CONFIG(ssl) + QSKIP("TLS support is needed for this test"); +#endif // QT_CONFIG(ssl) + + // Here we test we send 'MAX_FRAME_SIZE' setting in our + // 'SETTINGS'. If done properly, our server will not chunk + // the payload into several DATA frames. + +#if QT_CONFIG(securetransport) + // Normally on macOS we use plain text only for SecureTransport + // does not support ALPN on the server side. With 'direct encrytped' + // we have to use TLS sockets (== private key) and thus suppress a + // keychain UI asking for permission to use a private key. + // Our CI has this, but somebody testing locally - will have a problem. + qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1")); + auto envRollback = qScopeGuard([](){ + qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN"); + }); +#endif // QT_CONFIG(securetransport) + + auto connectionType = H2Type::h2Alpn; + auto attribute = QNetworkRequest::HTTP2AllowedAttribute; + if (clearTextHTTP2) { + connectionType = H2Type::h2Direct; + attribute = QNetworkRequest::Http2DirectAttribute; + } + + auto h2Config = qt_defaultH2Configuration(); + h2Config.setMaxFrameSize(Http2::minPayloadLimit * 3); + + serverPort = 0; + nRequests = 1; + + ServerPtr srv(newServer(defaultServerSettings, connectionType, + qt_H2ConfigurationToSettings(h2Config))); + srv->setResponseBody(QByteArray(Http2::minPayloadLimit * 2, 'q')); + QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection); + runEventLoop(); + QVERIFY(serverPort != 0); + + const QSignalSpy frameCounter(srv.data(), &Http2Server::sendingData); + auto url = requestUrl(connectionType); + url.setPath(QString("/stream1.html")); + + QNetworkRequest request(url); + request.setAttribute(attribute, QVariant(true)); + request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + request.setHttp2Configuration(h2Config); + + QNetworkReply *reply = manager->get(request); + reply->ignoreSslErrors(); + connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); + + runEventLoop(); + STOP_ON_FAILURE + + // Normally, with a 16kb limit, our server would split such + // a response into 3 'DATA' frames (16kb + 16kb + 0|END_STREAM). + QCOMPARE(frameCounter.count(), 1); + + QVERIFY(nRequests == 0); + QVERIFY(prefaceOK); + QVERIFY(serverGotSettingsACK); +} + void tst_Http2::serverStarted(quint16 port) { serverPort = port; |