diff options
Diffstat (limited to 'src/network/access/qhttpnetworkconnectionchannel.cpp')
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 220 |
1 files changed, 106 insertions, 114 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index ba05e75794..6766989690 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -1,49 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhttpnetworkconnectionchannel_p.h" #include "qhttpnetworkconnection_p.h" #include "qhttp2configuration.h" #include "private/qnoncontiguousbytedevice_p.h" -#include <qpair.h> #include <qdebug.h> #include <private/qhttp2protocolhandler_p.h> @@ -58,6 +21,9 @@ #include "private/qnetconmonitor_p.h" +#include <memory> +#include <utility> + QT_BEGIN_NAMESPACE namespace @@ -74,7 +40,7 @@ private: } -// TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp +// TODO: Put channel specific stuff here so it does not pollute qhttpnetworkconnection.cpp // Because in-flight when sending a request, the server might close our connection (because the persistent HTTP // connection times out) @@ -93,8 +59,6 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() , lastStatus(0) , pendingEncrypt(false) , reconnectAttempts(reconnectAttemptsDefault) - , authMethod(QAuthenticatorPrivate::None) - , proxyAuthMethod(QAuthenticatorPrivate::None) , authenticationCredentialsSent(false) , proxyCredentialsSent(false) , protocolHandler(nullptr) @@ -244,7 +208,7 @@ void QHttpNetworkConnectionChannel::abort() bool QHttpNetworkConnectionChannel::sendRequest() { - Q_ASSERT(!protocolHandler.isNull()); + Q_ASSERT(protocolHandler); return protocolHandler->sendRequest(); } @@ -257,7 +221,7 @@ bool QHttpNetworkConnectionChannel::sendRequest() void QHttpNetworkConnectionChannel::sendRequestDelayed() { QMetaObject::invokeMethod(this, [this] { - Q_ASSERT(!protocolHandler.isNull()); + Q_ASSERT(protocolHandler); if (reply) protocolHandler->sendRequest(); }, Qt::ConnectionType::QueuedConnection); @@ -265,13 +229,13 @@ void QHttpNetworkConnectionChannel::sendRequestDelayed() void QHttpNetworkConnectionChannel::_q_receiveReply() { - Q_ASSERT(!protocolHandler.isNull()); + Q_ASSERT(protocolHandler); protocolHandler->_q_receiveReply(); } void QHttpNetworkConnectionChannel::_q_readyRead() { - Q_ASSERT(!protocolHandler.isNull()); + Q_ASSERT(protocolHandler); protocolHandler->_q_readyRead(); } @@ -358,6 +322,13 @@ bool QHttpNetworkConnectionChannel::ensureConnection() QString connectHost = connection->d_func()->hostName; quint16 connectPort = connection->d_func()->port; + QHttpNetworkReply *potentialReply = connection->d_func()->predictNextRequestsReply(); + if (potentialReply) { + QMetaObject::invokeMethod(potentialReply, "socketStartedConnecting", Qt::QueuedConnection); + } else if (!h2RequestsToSend.isEmpty()) { + QMetaObject::invokeMethod(std::as_const(h2RequestsToSend).first().second, "socketStartedConnecting", Qt::QueuedConnection); + } + #ifndef QT_NO_NETWORKPROXY // HTTPS always use transparent proxy. if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl) { @@ -367,11 +338,20 @@ bool QHttpNetworkConnectionChannel::ensureConnection() if (socket->proxy().type() == QNetworkProxy::HttpProxy) { // Make user-agent field available to HTTP proxy socket engine (QTBUG-17223) QByteArray value; - // ensureConnection is called before any request has been assigned, but can also be called again if reconnecting - if (request.url().isEmpty()) - value = connection->d_func()->predictNextRequest().headerField("user-agent"); - else + // ensureConnection is called before any request has been assigned, but can also be + // called again if reconnecting + if (request.url().isEmpty()) { + if (connection->connectionType() + == QHttpNetworkConnection::ConnectionTypeHTTP2Direct + || (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 + && !h2RequestsToSend.isEmpty())) { + value = std::as_const(h2RequestsToSend).first().first.headerField("user-agent"); + } else { + value = connection->d_func()->predictNextRequest().headerField("user-agent"); + } + } else { value = request.headerField("user-agent"); + } if (!value.isEmpty()) { QNetworkProxy proxy(socket->proxy()); proxy.setRawHeader("User-Agent", value); //detaches @@ -386,8 +366,8 @@ bool QHttpNetworkConnectionChannel::ensureConnection() // check whether we can re-use an existing SSL session // (meaning another socket in this connection has already // performed a full handshake) - if (!connection->sslContext().isNull()) - QSslSocketPrivate::checkSettingSslContext(sslSocket, connection->sslContext()); + if (auto ctx = connection->sslContext()) + QSslSocketPrivate::checkSettingSslContext(sslSocket, std::move(ctx)); sslSocket->setPeerVerifyName(connection->d_func()->peerVerifyName); sslSocket->connectToHostEncrypted(connectHost, connectPort, QIODevice::ReadWrite, networkLayerPreference); @@ -464,18 +444,18 @@ void QHttpNetworkConnectionChannel::allDone() // trick with ProtocolHandlerDeleter, a QObject-derived class. // These dances below just make it somewhat exception-safe. // 1. Create a new owner: - QAbstractProtocolHandler *oldHandler = protocolHandler.data(); - QScopedPointer<ProtocolHandlerDeleter> deleter(new ProtocolHandlerDeleter(oldHandler)); + QAbstractProtocolHandler *oldHandler = protocolHandler.get(); + auto deleter = std::make_unique<ProtocolHandlerDeleter>(oldHandler); // 2. Retire the old one: - protocolHandler.take(); + Q_UNUSED(protocolHandler.release()); // 3. Call 'deleteLater': deleter->deleteLater(); // 3. Give up the ownerthip: - deleter.take(); + Q_UNUSED(deleter.release()); connection->fillHttp2Queue(); protocolHandler.reset(new QHttp2ProtocolHandler(this)); - QHttp2ProtocolHandler *h2c = static_cast<QHttp2ProtocolHandler *>(protocolHandler.data()); + QHttp2ProtocolHandler *h2c = static_cast<QHttp2ProtocolHandler *>(protocolHandler.get()); QMetaObject::invokeMethod(h2c, "_q_receiveReply", Qt::QueuedConnection); QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); // If we only had one request sent with H2 allowed, we may fail to send @@ -570,7 +550,7 @@ void QHttpNetworkConnectionChannel::detectPipeliningSupport() QByteArray serverHeaderField; if ( // check for HTTP/1.1 - (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1) + (reply->majorVersion() == 1 && reply->minorVersion() == 1) // check for not having connection close && (!reply->d_func()->isConnectionCloseEnabled()) // check if it is still connected @@ -593,7 +573,7 @@ void QHttpNetworkConnectionChannel::detectPipeliningSupport() // called when the connection broke and we need to queue some pipelined requests again void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() { - for (int i = 0; i < alreadyPipelinedRequests.length(); i++) + for (int i = 0; i < alreadyPipelinedRequests.size(); i++) connection->d_func()->requeueRequest(alreadyPipelinedRequests.at(i)); alreadyPipelinedRequests.clear(); @@ -678,17 +658,19 @@ bool QHttpNetworkConnectionChannel::resetUploadData() //this happens if server closes connection while QHttpNetworkConnectionPrivate::_q_startNextRequest is pending return false; } - QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); - if (!uploadByteDevice) - return true; - - if (uploadByteDevice->reset()) { + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct + || switchedToHttp2) { + // The else branch doesn't make any sense for HTTP/2, since 1 channel is multiplexed into + // many streams. And having one stream fail to reset upload data should not completely close + // the channel. Handled in the http2 protocol handler. + } else if (QNonContiguousByteDevice *uploadByteDevice = request.uploadByteDevice()) { + if (!uploadByteDevice->reset()) { + connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ContentReSendError); + return false; + } written = 0; - return true; - } else { - connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ContentReSendError); - return false; } + return true; } #ifndef QT_NO_NETWORKPROXY @@ -847,7 +829,7 @@ void QHttpNetworkConnectionChannel::_q_disconnected() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } state = QHttpNetworkConnectionChannel::IdleState; - if (alreadyPipelinedRequests.length()) { + if (alreadyPipelinedRequests.size()) { // If nothing was in a pipeline, no need in calling // _q_startNextRequest (which it does): requeueCurrentlyPipelinedRequests(); @@ -874,9 +856,14 @@ void QHttpNetworkConnectionChannel::_q_connected() connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv6; } connection->d_func()->networkLayerDetected(networkLayerPreference); + if (connection->d_func()->activeChannelCount > 1 && !connection->d_func()->encrypt) + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else { - if (((connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::IPv4) && (networkLayerPreference != QAbstractSocket::IPv4Protocol)) - || ((connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::IPv6) && (networkLayerPreference != QAbstractSocket::IPv6Protocol))) { + bool anyProtocol = networkLayerPreference == QAbstractSocket::AnyIPProtocol; + if (((connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::IPv4) + && (networkLayerPreference != QAbstractSocket::IPv4Protocol && !anyProtocol)) + || ((connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::IPv6) + && (networkLayerPreference != QAbstractSocket::IPv6Protocol && !anyProtocol))) { close(); // This is the second connection so it has to be closed and we can schedule it for another request. QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); @@ -899,7 +886,7 @@ void QHttpNetworkConnectionChannel::_q_connected() pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown; - if (QNetworkStatusMonitor::isEnabled()) { + if (QNetworkConnectionMonitor::isEnabled()) { auto connectionPrivate = connection->d_func(); if (!connectionPrivate->connectionMonitor.isMonitoring()) { // Now that we have a pair of addresses, we can start monitoring the @@ -913,18 +900,17 @@ void QHttpNetworkConnectionChannel::_q_connected() //channels[i].reconnectAttempts = 2; if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState #ifndef QT_NO_SSL - if (connection->sslContext().isNull()) { + if (!connection->sslContext()) { // this socket is making the 1st handshake for this connection, // we need to set the SSL context so new sockets can reuse it - QSharedPointer<QSslContext> socketSslContext = QSslSocketPrivate::sslContext(static_cast<QSslSocket*>(socket)); - if (!socketSslContext.isNull()) - connection->setSslContext(socketSslContext); + if (auto socketSslContext = QSslSocketPrivate::sslContext(static_cast<QSslSocket*>(socket))) + connection->setSslContext(std::move(socketSslContext)); } #endif } else if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) { state = QHttpNetworkConnectionChannel::IdleState; protocolHandler.reset(new QHttp2ProtocolHandler(this)); - if (h2RequestsToSend.count() > 0) { + if (h2RequestsToSend.size() > 0) { // 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); @@ -965,6 +951,10 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket break; case QAbstractSocket::ConnectionRefusedError: errorCode = QNetworkReply::ConnectionRefusedError; +#ifndef QT_NO_NETWORKPROXY + if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl) + errorCode = QNetworkReply::ProxyConnectionRefusedError; +#endif break; case QAbstractSocket::RemoteHostClosedError: // This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer. @@ -977,12 +967,12 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket // 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 (protocolHandler) { if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct - || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) { - auto h2Handler = static_cast<QHttp2ProtocolHandler *>(protocolHandler.data()); + || (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 + && switchedToHttp2)) { + auto h2Handler = static_cast<QHttp2ProtocolHandler *>(protocolHandler.get()); h2Handler->handleConnectionClosure(); - protocolHandler.reset(); } } return; @@ -1046,6 +1036,9 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket } errorCode = QNetworkReply::TimeoutError; break; + case QAbstractSocket::ProxyConnectionRefusedError: + errorCode = QNetworkReply::ProxyConnectionRefusedError; + break; case QAbstractSocket::ProxyAuthenticationRequiredError: errorCode = QNetworkReply::ProxyAuthenticationRequiredError; break; @@ -1103,10 +1096,12 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) { - QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values(); - for (int a = 0; a < h2Pairs.count(); ++a) { + const auto h2RequestsToSendCopy = std::exchange(h2RequestsToSend, {}); + for (const auto &httpMessagePair : h2RequestsToSendCopy) { // emit error for all replies - QHttpNetworkReply *currentReply = h2Pairs.at(a).second; + QHttpNetworkReply *currentReply = httpMessagePair.second; + currentReply->d_func()->errorString = errorString; + currentReply->d_func()->httpErrorCode = errorCode; Q_ASSERT(currentReply); emit currentReply->finishedWithError(errorCode, errorString); } @@ -1132,9 +1127,10 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket #ifndef QT_NO_NETWORKPROXY void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) { - if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 + if ((connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 + && (switchedToHttp2 || h2RequestsToSend.size() > 0)) || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) { - if (h2RequestsToSend.count() > 0) + if (h2RequestsToSend.size() > 0) connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); } else { // HTTP // Need to dequeue the request before we can emit the error. @@ -1157,9 +1153,9 @@ void QHttpNetworkConnectionChannel::emitFinishedWithError(QNetworkReply::Network { if (reply) emit reply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message)); - QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values(); - for (int a = 0; a < h2Pairs.count(); ++a) { - QHttpNetworkReply *currentReply = h2Pairs.at(a).second; + const auto h2RequestsToSendCopy = h2RequestsToSend; + for (const auto &httpMessagePair : h2RequestsToSendCopy) { + QHttpNetworkReply *currentReply = httpMessagePair.second; Q_ASSERT(currentReply); emit currentReply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message)); } @@ -1176,8 +1172,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted() // after establishing a secure connection we immediately start sending // HTTP/2 frames. switch (sslSocket->sslConfiguration().nextProtocolNegotiationStatus()) { - case QSslConfiguration::NextProtocolNegotiationNegotiated: - case QSslConfiguration::NextProtocolNegotiationUnsupported: { + case QSslConfiguration::NextProtocolNegotiationNegotiated: { QByteArray nextProtocol = sslSocket->sslConfiguration().nextNegotiatedProtocol(); if (nextProtocol == QSslConfiguration::NextProtocolHttp1_1) { // fall through to create a QHttpProtocolHandler @@ -1193,17 +1188,12 @@ void QHttpNetworkConnectionChannel::_q_encrypted() } } Q_FALLTHROUGH(); + case QSslConfiguration::NextProtocolNegotiationUnsupported: // No agreement, try HTTP/1(.1) case QSslConfiguration::NextProtocolNegotiationNone: { protocolHandler.reset(new QHttpProtocolHandler(this)); - if (!sslConfiguration.data()) { - // Our own auto-tests bypass the normal initialization (done by - // QHttpThreadDelegate), this means in the past we'd have here - // the default constructed QSslConfiguration without any protocols - // to negotiate. Let's create it now: - sslConfiguration.reset(new QSslConfiguration); - } - QList<QByteArray> protocols = sslConfiguration->allowedNextProtocols(); + QSslConfiguration newConfiguration = sslSocket->sslConfiguration(); + QList<QByteArray> protocols = newConfiguration.allowedNextProtocols(); const int nProtocols = protocols.size(); // Clear the protocol that we failed to negotiate, so we do not try // it again on other channels that our connection can create/open. @@ -1211,10 +1201,10 @@ void QHttpNetworkConnectionChannel::_q_encrypted() protocols.removeAll(QSslConfiguration::ALPNProtocolHTTP2); if (nProtocols > protocols.size()) { - sslConfiguration->setAllowedNextProtocols(protocols); + newConfiguration.setAllowedNextProtocols(protocols); const int channelCount = connection->d_func()->channelCount; for (int i = 0; i < channelCount; ++i) - connection->d_func()->channels[i].setSslConfiguration(*sslConfiguration); + connection->d_func()->channels[i].setSslConfiguration(newConfiguration); } connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeHTTP); @@ -1246,10 +1236,12 @@ void QHttpNetworkConnectionChannel::_q_encrypted() if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) { - if (h2RequestsToSend.count() > 0) { + if (!h2RequestsToSend.isEmpty()) { + // Similar to HTTP/1.1 counterpart below: + const auto &pair = std::as_const(h2RequestsToSend).first(); + emit pair.second->encrypted(); // 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); } } else { // HTTP if (!reply) @@ -1262,14 +1254,14 @@ void QHttpNetworkConnectionChannel::_q_encrypted() if (reply) sendRequestDelayed(); } + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } void QHttpNetworkConnectionChannel::requeueHttp2Requests() { - QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values(); - for (int a = 0; a < h2Pairs.count(); ++a) - connection->d_func()->requeueRequest(h2Pairs.at(a)); - h2RequestsToSend.clear(); + const auto h2RequestsToSendCopy = std::exchange(h2RequestsToSend, {}); + for (const auto &httpMessagePair : h2RequestsToSendCopy) + connection->d_func()->requeueRequest(httpMessagePair); } void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors) @@ -1288,10 +1280,10 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors) } #ifndef QT_NO_SSL else { // HTTP/2 - QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values(); - for (int a = 0; a < h2Pairs.count(); ++a) { + const auto h2RequestsToSendCopy = h2RequestsToSend; + for (const auto &httpMessagePair : h2RequestsToSendCopy) { // emit SSL errors for all replies - QHttpNetworkReply *currentReply = h2Pairs.at(a).second; + QHttpNetworkReply *currentReply = httpMessagePair.second; Q_ASSERT(currentReply); emit currentReply->sslErrors(errors); } @@ -1311,10 +1303,10 @@ void QHttpNetworkConnectionChannel::_q_preSharedKeyAuthenticationRequired(QSslPr if (reply) emit reply->preSharedKeyAuthenticationRequired(authenticator); } else { - QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values(); - for (int a = 0; a < h2Pairs.count(); ++a) { + const auto h2RequestsToSendCopy = h2RequestsToSend; + for (const auto &httpMessagePair : h2RequestsToSendCopy) { // emit SSL errors for all replies - QHttpNetworkReply *currentReply = h2Pairs.at(a).second; + QHttpNetworkReply *currentReply = httpMessagePair.second; Q_ASSERT(currentReply); emit currentReply->preSharedKeyAuthenticationRequired(authenticator); } |