summaryrefslogtreecommitdiffstats
path: root/src/network/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access')
-rw-r--r--src/network/access/qhttp2configuration.cpp2
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp25
-rw-r--r--src/network/access/qhttp2protocolhandler_p.h2
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp3
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp21
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp8
-rw-r--r--src/network/access/qnetworkrequest.cpp13
-rw-r--r--src/network/access/qnetworkrequest.h12
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,