diff options
Diffstat (limited to 'src/network/access')
-rw-r--r-- | src/network/access/qhttp2configuration.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 25 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler_p.h | 2 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 3 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 21 | ||||
-rw-r--r-- | src/network/access/qhttpthreaddelegate.cpp | 8 | ||||
-rw-r--r-- | src/network/access/qnetworkrequest.cpp | 13 | ||||
-rw-r--r-- | src/network/access/qnetworkrequest.h | 12 |
8 files changed, 72 insertions, 14 deletions
diff --git a/src/network/access/qhttp2configuration.cpp b/src/network/access/qhttp2configuration.cpp index a32bccfd09..bd4318d4e9 100644 --- a/src/network/access/qhttp2configuration.cpp +++ b/src/network/access/qhttp2configuration.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE /*! \class QHttp2Configuration - \brief The QHttp2Configuration class controls HTTP/2 parameters and settings + \brief The QHttp2Configuration class controls HTTP/2 parameters and settings. \since 5.14 \reentrant diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index c1053882af..9bf5547f15 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -58,6 +58,8 @@ #include <QtNetwork/qnetworkproxy.h> #endif +#include <qcoreapplication.h> + #include <algorithm> #include <vector> @@ -195,6 +197,29 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan } } +void QHttp2ProtocolHandler::handleConnectionClosure() +{ + // The channel has just received RemoteHostClosedError and since it will + // not try (for HTTP/2) to re-connect, it's time to finish all replies + // with error. + + // Maybe we still have some data to read and can successfully finish + // a stream/request? + _q_receiveReply(); + + // Finish all still active streams. If we previously had GOAWAY frame, + // we probably already closed some (or all) streams with ContentReSend + // error, but for those still active, not having any data to finish, + // we now report RemoteHostClosedError. + const auto errorString = QCoreApplication::translate("QHttp", "Connection closed"); + for (auto it = activeStreams.begin(), eIt = activeStreams.end(); it != eIt; ++it) + finishStreamWithError(it.value(), QNetworkReply::RemoteHostClosedError, errorString); + + // Make sure we'll never try to read anything later: + activeStreams.clear(); + goingAway = true; +} + void QHttp2ProtocolHandler::_q_uploadDataReadyRead() { if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted. diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h index 1943827e23..43fdb136cd 100644 --- a/src/network/access/qhttp2protocolhandler_p.h +++ b/src/network/access/qhttp2protocolhandler_p.h @@ -92,6 +92,8 @@ public: QHttp2ProtocolHandler &operator = (const QHttp2ProtocolHandler &rhs) = delete; QHttp2ProtocolHandler &operator = (QHttp2ProtocolHandler &&rhs) = delete; + Q_INVOKABLE void handleConnectionClosure(); + private slots: void _q_uploadDataReadyRead(); void _q_replyDestroyed(QObject* reply); diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 13be1aa6b5..21c6359807 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1235,7 +1235,8 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info) emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError); networkLayerState = QHttpNetworkConnectionPrivate::Unknown; } else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY - || connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2) { + || connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2 + || connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) { for (const HttpMessagePair &spdyPair : qAsConst(channels[0].spdyRequestsToSend)) { // emit error for all replies QHttpNetworkReply *currentReply = spdyPair.second; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 716ea6c8b2..39f392a79b 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -854,8 +854,11 @@ void QHttpNetworkConnectionChannel::_q_disconnected() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } state = QHttpNetworkConnectionChannel::IdleState; - - requeueCurrentlyPipelinedRequests(); + if (alreadyPipelinedRequests.length()) { + // If nothing was in a pipeline, no need in calling + // _q_startNextRequest (which it does): + requeueCurrentlyPipelinedRequests(); + } pendingEncrypt = false; } @@ -977,7 +980,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (!reply && state == QHttpNetworkConnectionChannel::IdleState) { // Not actually an error, it is normal for Keep-Alive connections to close after some time if no request // is sent on them. No need to error the other replies below. Just bail out here. - // The _q_disconnected will handle the possibly pipelined replies + // The _q_disconnected will handle the possibly pipelined replies. HTTP/2 is special for now, + // we do not resend, but must report errors if any request is in progress (note, while + // not in its sendRequest(), protocol handler switches the channel to IdleState, thus + // this check is under this condition in 'if'): + if (protocolHandler.data()) { + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct + || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) { + auto h2Handler = static_cast<QHttp2ProtocolHandler *>(protocolHandler.data()); + h2Handler->handleConnectionClosure(); + protocolHandler.reset(); + } + } return; } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { // Try to reconnect/resend before sending an error. @@ -1094,6 +1108,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket || !connection->d_func()->lowPriorityQueue.isEmpty()); if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 + || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct #ifndef QT_NO_SSL || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY #endif diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 1900397eab..63a3c4f204 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -297,6 +297,11 @@ void QHttpThreadDelegate::startRequest() connectionType = QHttpNetworkConnection::ConnectionTypeHTTP2Direct; } +#if QT_CONFIG(ssl) + // See qnetworkreplyhttpimpl, delegate's initialization code. + Q_ASSERT(!ssl || incomingSslConfiguration.data()); +#endif // QT_CONFIG(ssl) + const bool isH2 = httpRequest.isHTTP2Allowed() || httpRequest.isHTTP2Direct(); if (isH2) { #if QT_CONFIG(ssl) @@ -316,9 +321,6 @@ void QHttpThreadDelegate::startRequest() } #ifndef QT_NO_SSL - if (ssl && !incomingSslConfiguration.data()) - incomingSslConfiguration.reset(new QSslConfiguration); - if (!isH2 && httpRequest.isSPDYAllowed() && ssl) { connectionType = QHttpNetworkConnection::ConnectionTypeSPDY; urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 118fb6b1fb..cedb1597de 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -277,23 +277,30 @@ QT_BEGIN_NAMESPACE Indicates whether the QNetworkAccessManager code is allowed to use SPDY with this request. This applies only to SSL requests, and depends on the server supporting SPDY. + Obsolete, use Http2 instead of Spdy. \value SpdyWasUsedAttribute Replies only, type: QMetaType::Bool Indicates whether SPDY was used for receiving - this reply. + this reply. Obsolete, use Http2 instead of Spdy. - \value HTTP2AllowedAttribute + \value Http2AllowedAttribute Requests only, type: QMetaType::Bool (default: false) Indicates whether the QNetworkAccessManager code is allowed to use HTTP/2 with this request. This applies to SSL requests or 'cleartext' HTTP/2. - \value HTTP2WasUsedAttribute + \value Http2WasUsedAttribute Replies only, type: QMetaType::Bool (default: false) Indicates whether HTTP/2 was used for receiving this reply. (This value was introduced in 5.9.) + \value HTTP2AllowedAttribute + Obsolete alias for Http2AllowedAttribute. + + \value HTTP2WasUsedAttribute + Obsolete alias for Http2WasUsedAttribute. + \value EmitAllUploadProgressSignalsAttribute Requests only, type: QMetaType::Bool (default: false) Indicates whether all upload signals should be emitted. diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index e09ff8aaae..72a6555d91 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -89,12 +89,18 @@ public: DownloadBufferAttribute, // internal SynchronousRequestAttribute, // internal BackgroundRequestAttribute, +#if QT_DEPRECATED_SINCE(5, 15) SpdyAllowedAttribute, SpdyWasUsedAttribute, - EmitAllUploadProgressSignalsAttribute, +#endif // QT_DEPRECATED_SINCE(5, 15) + EmitAllUploadProgressSignalsAttribute = BackgroundRequestAttribute + 3, FollowRedirectsAttribute, - HTTP2AllowedAttribute, - HTTP2WasUsedAttribute, + Http2AllowedAttribute, + Http2WasUsedAttribute, +#if QT_DEPRECATED_SINCE(5, 15) + HTTP2AllowedAttribute Q_DECL_ENUMERATOR_DEPRECATED_X("Use Http2AllowedAttribute") = Http2AllowedAttribute, + HTTP2WasUsedAttribute Q_DECL_ENUMERATOR_DEPRECATED_X("Use Http2WasUsedAttribute"), +#endif // QT_DEPRECATED_SINCE(5, 15) OriginalContentLengthAttribute, RedirectPolicyAttribute, Http2DirectAttribute, |