summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp25
-rw-r--r--src/network/access/qhttp2protocolhandler_p.h2
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp13
3 files changed, 39 insertions, 1 deletions
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/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 716ea6c8b2..6ff2c47eb4 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -977,7 +977,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.