QHttp2Configuration: in QNAM, use old, higher values in flow control

Initially, stream receive window's size was quite significant.
At some point when dealing with a server that did not want
our windows' sizes and was closing the connection (they only
accept 64K) we reduced this size, which ended in a regression
with download speed significantly throttled. We return the old
values (or even more, presuming we have 10 multiplexed streams
and not 100). And also making QNAM consistent with its documentation
(it was not updated).

[ChangeLog][QtNetwork] Stream receive window that HTTP/2 protocol in QNAM is using
increased to 214748364 octets (from the previous 64K) not to throttle download
speed. Clients, working with servers, not accepting such parameters,
must set HTTP/2 configuration on their requests accordingly.

Fixes: QTBUG-105043
Change-Id: I252b6b5eefe92a7304dad15c67928d5a57d9597f
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 9540a4eb9071a17446c6b68e086bbea2b50d50f5)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Timur Pocheptsov 2022-08-29 13:02:58 +02:00 committed by Qt Cherry-pick Bot
parent 17f0d47413
commit 9fd40c04d1
4 changed files with 14 additions and 7 deletions

View File

@ -112,7 +112,8 @@ const quint32 lastValidStreamID((quint32(1) << 31) - 1); // HTTP/2, 5.1.1
// HTTP/2 servers are not afraid to immediately set it to the possible max,
// we do the same and split this window size between our concurrent streams.
const qint32 maxSessionReceiveWindowSize((quint32(1) << 31) - 1);
const qint32 qtDefaultStreamReceiveWindowSize = maxSessionReceiveWindowSize / maxConcurrentStreams;
// Presumably, we never use up to 100 streams so let it be 10 simultaneous:
const qint32 qtDefaultStreamReceiveWindowSize = maxSessionReceiveWindowSize / 10;
struct Frame configurationToSettingsFrame(const QHttp2Configuration &configuration);
QByteArray settingsFrameToBase64(const Frame &settingsFrame);

View File

@ -217,7 +217,7 @@ bool QHttp2Configuration::setStreamReceiveWindowSize(unsigned size)
/*!
Returns the window size for stream-level flow control.
The default value QNetworkAccessManager will be using is
65535 octets (see \l {https://httpwg.org/specs/rfc7540.html#SettingValues}{RFC 7540}).
214748364 octets (see \l {https://httpwg.org/specs/rfc7540.html#SettingValues}{RFC 7540}).
*/
unsigned QHttp2Configuration::streamReceiveWindowSize() const
{

View File

@ -481,10 +481,9 @@ QNetworkRequest::QNetworkRequest()
// Initial values proposed by RFC 7540 are quite draconian, but we
// know about servers configured with this value as maximum possible,
// rejecting our SETTINGS frame and sending us a GOAWAY frame with the
// flow control error set. Unless an application sets its own parameters,
// we don't send SETTINGS_INITIAL_WINDOW_SIZE, but increase
// (via WINDOW_UPDATE) the session window size. These are our 'defaults':
d->h2Configuration.setStreamReceiveWindowSize(Http2::defaultSessionWindowSize);
// flow control error set. If this causes a problem - the app should
// set a proper configuration. We'll use our defaults, as documented.
d->h2Configuration.setStreamReceiveWindowSize(Http2::qtDefaultStreamReceiveWindowSize);
d->h2Configuration.setSessionReceiveWindowSize(Http2::maxSessionReceiveWindowSize);
d->h2Configuration.setServerPushEnabled(false);
#endif // QT_CONFIG(http)
@ -859,7 +858,7 @@ void QNetworkRequest::setPeerVerifyName(const QString &peerName)
\list
\li Window size for connection-level flowcontrol is 2147483647 octets
\li Window size for stream-level flowcontrol is 21474836 octets
\li Window size for stream-level flowcontrol is 214748364 octets
\li Max frame size is 16384
\endlist

View File

@ -69,6 +69,7 @@ public slots:
void init();
private slots:
// Tests:
void defaultQnamHttp2Configuration();
void singleRequest_data();
void singleRequest();
void multipleRequests();
@ -208,6 +209,12 @@ void tst_Http2::init()
manager.reset(new QNetworkAccessManager);
}
void tst_Http2::defaultQnamHttp2Configuration()
{
// The configuration we also implicitly use in QNAM.
QCOMPARE(qt_defaultH2Configuration(), QNetworkRequest().http2Configuration());
}
void tst_Http2::singleRequest_data()
{
QTest::addColumn<QNetworkRequest::Attribute>("h2Attribute");