139 lines
5.1 KiB
Diff
139 lines
5.1 KiB
Diff
|
|
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
|
||
|
|
index ec100708600..80819105201 100644
|
||
|
|
--- a/src/network/access/qhttp2protocolhandler.cpp
|
||
|
|
+++ b/src/network/access/qhttp2protocolhandler.cpp
|
||
|
|
@@ -339,12 +339,12 @@ bool QHttp2ProtocolHandler::sendRequest()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (!prefaceSent && !sendClientPreface())
|
||
|
|
- return false;
|
||
|
|
-
|
||
|
|
if (!requests.size())
|
||
|
|
return true;
|
||
|
|
|
||
|
|
+ if (!prefaceSent && !sendClientPreface())
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
m_channel->state = QHttpNetworkConnectionChannel::WritingState;
|
||
|
|
// Check what was promised/pushed, maybe we do not have to send a request
|
||
|
|
// and have a response already?
|
||
|
|
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
|
||
|
|
index b9e1ae403cd..3cbe1b16f9e 100644
|
||
|
|
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
|
||
|
|
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
|
||
|
|
@@ -209,6 +209,10 @@
|
||
|
|
bool QHttpNetworkConnectionChannel::sendRequest()
|
||
|
|
{
|
||
|
|
Q_ASSERT(protocolHandler);
|
||
|
|
+ if (waitingForPotentialAbort) {
|
||
|
|
+ needInvokeSendRequest = true;
|
||
|
|
+ return false; // this return value is unused
|
||
|
|
+ }
|
||
|
|
return protocolHandler->sendRequest();
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -221,21 +225,28 @@
|
||
|
|
void QHttpNetworkConnectionChannel::sendRequestDelayed()
|
||
|
|
{
|
||
|
|
QMetaObject::invokeMethod(this, [this] {
|
||
|
|
- Q_ASSERT(protocolHandler);
|
||
|
|
if (reply)
|
||
|
|
- protocolHandler->sendRequest();
|
||
|
|
+ sendRequest();
|
||
|
|
}, Qt::ConnectionType::QueuedConnection);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QHttpNetworkConnectionChannel::_q_receiveReply()
|
||
|
|
{
|
||
|
|
Q_ASSERT(protocolHandler);
|
||
|
|
+ if (waitingForPotentialAbort) {
|
||
|
|
+ needInvokeReceiveReply = true;
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
protocolHandler->_q_receiveReply();
|
||
|
|
}
|
||
|
|
|
||
|
|
void QHttpNetworkConnectionChannel::_q_readyRead()
|
||
|
|
{
|
||
|
|
Q_ASSERT(protocolHandler);
|
||
|
|
+ if (waitingForPotentialAbort) {
|
||
|
|
+ needInvokeReadyRead = true;
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
protocolHandler->_q_readyRead();
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -1232,7 +1243,18 @@
|
||
|
|
// Similar to HTTP/1.1 counterpart below:
|
||
|
|
const auto &h2Pairs = h2RequestsToSend.values(); // (request, reply)
|
||
|
|
const auto &pair = h2Pairs.first();
|
||
|
|
+ waitingForPotentialAbort = true;
|
||
|
|
emit pair.second->encrypted();
|
||
|
|
+
|
||
|
|
+ // We don't send or handle any received data until any effects from
|
||
|
|
+ // emitting encrypted() have been processed. This is necessary
|
||
|
|
+ // because the user may have called abort(). We may also abort the
|
||
|
|
+ // whole connection if the request has been aborted and there is
|
||
|
|
+ // no more requests to send.
|
||
|
|
+ QMetaObject::invokeMethod(this,
|
||
|
|
+ &QHttpNetworkConnectionChannel::checkAndResumeCommunication,
|
||
|
|
+ Qt::QueuedConnection);
|
||
|
|
+
|
||
|
|
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
|
||
|
|
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
|
||
|
|
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
||
|
|
@@ -1250,6 +1272,28 @@
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+
|
||
|
|
+void QHttpNetworkConnectionChannel::checkAndResumeCommunication()
|
||
|
|
+{
|
||
|
|
+ Q_ASSERT(connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||
|
|
+ || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct);
|
||
|
|
+
|
||
|
|
+ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond
|
||
|
|
+ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any
|
||
|
|
+ // effects from emitting encrypted() have been processed.
|
||
|
|
+ // This function is called after encrypted() was emitted, so check for changes.
|
||
|
|
+
|
||
|
|
+ if (!reply && h2RequestsToSend.isEmpty())
|
||
|
|
+ abort();
|
||
|
|
+ waitingForPotentialAbort = false;
|
||
|
|
+ if (needInvokeReadyRead)
|
||
|
|
+ _q_readyRead();
|
||
|
|
+ if (needInvokeReceiveReply)
|
||
|
|
+ _q_receiveReply();
|
||
|
|
+ if (needInvokeSendRequest)
|
||
|
|
+ sendRequest();
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
void QHttpNetworkConnectionChannel::requeueHttp2Requests()
|
||
|
|
{
|
||
|
|
QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values();
|
||
|
|
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
|
||
|
|
index e38e56df160..76d5baef2e3 100644
|
||
|
|
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
|
||
|
|
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
|
||
|
|
@@ -73,6 +73,10 @@ public:
|
||
|
|
QAbstractSocket *socket;
|
||
|
|
bool ssl;
|
||
|
|
bool isInitialized;
|
||
|
|
+ bool waitingForPotentialAbort = false;
|
||
|
|
+ bool needInvokeReceiveReply = false;
|
||
|
|
+ bool needInvokeReadyRead = false;
|
||
|
|
+ bool needInvokeSendRequest = false;
|
||
|
|
ChannelState state;
|
||
|
|
QHttpNetworkRequest request; // current request, only used for HTTP
|
||
|
|
QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
|
||
|
|
@@ -145,6 +149,8 @@ public:
|
||
|
|
void closeAndResendCurrentRequest();
|
||
|
|
void resendCurrentRequest();
|
||
|
|
|
||
|
|
+ void checkAndResumeCommunication();
|
||
|
|
+
|
||
|
|
bool isSocketBusy() const;
|
||
|
|
bool isSocketWriting() const;
|
||
|
|
bool isSocketWaiting() const;
|