summaryrefslogtreecommitdiffstats
path: root/src/network/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access')
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp25
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp36
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp17
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp6
-rw-r--r--src/network/access/qnetworkrequest.cpp15
-rw-r--r--src/network/access/qnetworkrequest.h3
-rw-r--r--src/network/access/qspdyprotocolhandler.cpp15
-rw-r--r--src/network/access/qspdyprotocolhandler_p.h2
8 files changed, 88 insertions, 31 deletions
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index 93afcf0ee1..0ece5b7179 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -170,7 +170,6 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
encoder(HPack::FieldLookupTable::DefaultSize, true)
{
Q_ASSERT(channel && m_connection);
-
continuedFrames.reserve(20);
const ProtocolParameters params(m_connection->http2Parameters());
@@ -328,10 +327,32 @@ bool QHttp2ProtocolHandler::sendRequest()
return false;
}
+ // Process 'fake' (created by QNetworkAccessManager::connectToHostEncrypted())
+ // requests first:
+ auto &requests = m_channel->spdyRequestsToSend;
+ for (auto it = requests.begin(), endIt = requests.end(); it != endIt;) {
+ const auto &pair = *it;
+ const QString scheme(pair.first.url().scheme());
+ if (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https")) {
+ m_connection->preConnectFinished();
+ emit pair.second->finished();
+ it = requests.erase(it);
+ if (!requests.size()) {
+ // Normally, after a connection was established and H2
+ // was negotiated, we send a client preface. connectToHostEncrypted
+ // though is not meant to send any data, it's just a 'preconnect'.
+ // Thus we return early:
+ return true;
+ }
+ } else {
+ ++it;
+ }
+ }
+
if (!prefaceSent && !sendClientPreface())
return false;
- auto &requests = m_channel->spdyRequestsToSend;
if (!requests.size())
return true;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 6fb4710d77..acc551a7c9 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -128,7 +128,8 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy, const QString &p
QString result;
QUrl copy = url;
QString scheme = copy.scheme();
- bool isEncrypted = scheme == QLatin1String("https");
+ bool isEncrypted = scheme == QLatin1String("https")
+ || scheme == QLatin1String("preconnect-https");
copy.setPort(copy.port(isEncrypted ? 443 : 80));
if (scheme == QLatin1String("preconnect-http")) {
copy.setScheme(QLatin1String("http"));
@@ -296,17 +297,29 @@ void QHttpThreadDelegate::startRequest()
connectionType = QHttpNetworkConnection::ConnectionTypeHTTP2Direct;
}
+ const bool isH2 = httpRequest.isHTTP2Allowed() || httpRequest.isHTTP2Direct();
+ if (isH2) {
+#if QT_CONFIG(ssl)
+ if (ssl) {
+ if (!httpRequest.isHTTP2Direct()) {
+ QList<QByteArray> protocols;
+ protocols << QSslConfiguration::ALPNProtocolHTTP2
+ << QSslConfiguration::NextProtocolHttp1_1;
+ incomingSslConfiguration->setAllowedNextProtocols(protocols);
+ }
+ urlCopy.setScheme(QStringLiteral("h2s"));
+ } else
+#endif // QT_CONFIG(ssl)
+ {
+ urlCopy.setScheme(QStringLiteral("h2"));
+ }
+ }
+
#ifndef QT_NO_SSL
if (ssl && !incomingSslConfiguration.data())
incomingSslConfiguration.reset(new QSslConfiguration);
- if (httpRequest.isHTTP2Allowed() && ssl) {
- // With HTTP2Direct we do not try any protocol negotiation.
- QList<QByteArray> protocols;
- protocols << QSslConfiguration::ALPNProtocolHTTP2
- << QSslConfiguration::NextProtocolHttp1_1;
- incomingSslConfiguration->setAllowedNextProtocols(protocols);
- } else if (httpRequest.isSPDYAllowed() && ssl) {
+ if (!isH2 && httpRequest.isSPDYAllowed() && ssl) {
connectionType = QHttpNetworkConnection::ConnectionTypeSPDY;
urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests
QList<QByteArray> nextProtocols;
@@ -323,12 +336,11 @@ void QHttpThreadDelegate::startRequest()
cacheKey = makeCacheKey(urlCopy, &cacheProxy, httpRequest.peerVerifyName());
else
#endif
- cacheKey = makeCacheKey(urlCopy, 0, httpRequest.peerVerifyName());
-
+ cacheKey = makeCacheKey(urlCopy, nullptr, httpRequest.peerVerifyName());
// the http object is actually a QHttpNetworkConnection
httpConnection = static_cast<QNetworkAccessCachedHttpConnection *>(connections.localData()->requestEntryNow(cacheKey));
- if (httpConnection == 0) {
+ if (!httpConnection) {
// no entry in cache; create an object
// the http object is actually a QHttpNetworkConnection
#ifdef QT_NO_BEARERMANAGEMENT
@@ -358,7 +370,7 @@ void QHttpThreadDelegate::startRequest()
connections.localData()->addEntry(cacheKey, httpConnection);
} else {
if (httpRequest.withCredentials()) {
- QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), 0);
+ QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), nullptr);
if (!credential.user.isEmpty() && !credential.password.isEmpty()) {
QAuthenticator auth;
auth.setUser(credential.user);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index a2996e3533..29192ae7b0 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -493,9 +493,9 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
connect(&d->statusMonitor, SIGNAL(onlineStateChanged(bool)),
SLOT(_q_onlineStateChanged(bool)));
#ifdef QT_NO_BEARERMANAGEMENT
- d->networkAccessible = d->statusMonitor.isNetworkAccesible();
+ d->networkAccessible = d->statusMonitor.isNetworkAccessible();
#else
- d->networkAccessible = d->statusMonitor.isNetworkAccesible() ? Accessible : NotAccessible;
+ d->networkAccessible = d->statusMonitor.isNetworkAccessible() ? Accessible : NotAccessible;
} else {
// if a session is required, we track online state through
// the QNetworkSession's signals if a request is already made.
@@ -1236,10 +1236,11 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin
if (sslConfiguration != QSslConfiguration::defaultConfiguration())
request.setSslConfiguration(sslConfiguration);
- // There is no way to enable SPDY via a request, so we need to check
- // the ssl configuration whether SPDY is allowed here.
- if (sslConfiguration.allowedNextProtocols().contains(
- QSslConfiguration::NextProtocolSpdy3_0))
+ // There is no way to enable SPDY/HTTP2 via a request, so we need to check
+ // the ssl configuration whether SPDY/HTTP2 is allowed here.
+ if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::ALPNProtocolHTTP2))
+ request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
+ else if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::NextProtocolSpdy3_0))
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
request.setPeerVerifyName(peerName);
@@ -1565,8 +1566,8 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
#ifndef QT_NO_BEARERMANAGEMENT
// NETMONTODO: network reply impl must be augmented to use the same monitoring
- // capabilities as http network reply impl does.
- if (!isLocalFile && !d->statusMonitor.isEnabled()) {
+ // capabilities as http network reply impl does. Once it does: uncomment the condition below
+ if (!isLocalFile /*&& !d->statusMonitor.isEnabled()*/) {
connect(this, SIGNAL(networkSessionConnected()),
reply, SLOT(_q_networkSessionConnected()));
}
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
index ee91dc20b3..53784407d8 100644
--- a/src/network/access/qnetworkreplywasmimpl.cpp
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -135,8 +135,10 @@ static void q_loadCallback(val event)
if (readyState == 4) { // done
reply->setReplyAttributes(xhr["data-handler"].as<quintptr>(), status, statusText);
- if (!responseString.isEmpty())
- reply->dataReceived(responseString.toUtf8(), responseString.size());
+ if (!responseString.isEmpty()) {
+ QByteArray responseStringArray = responseString.toUtf8();
+ reply->dataReceived(responseStringArray, responseStringArray.size());
+ }
}
}
if (status >= 400 && !statusText.isEmpty())
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index ba36c75419..37f64c3f52 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -468,13 +468,24 @@ public:
};
/*!
+ Constructs a QNetworkRequest object with no URL to be requested.
+ Use setUrl() to set one.
+
+ \sa url(), setUrl()
+*/
+QNetworkRequest::QNetworkRequest()
+ : d(new QNetworkRequestPrivate)
+{
+}
+
+/*!
Constructs a QNetworkRequest object with \a url as the URL to be
requested.
\sa url(), setUrl()
*/
QNetworkRequest::QNetworkRequest(const QUrl &url)
- : d(new QNetworkRequestPrivate)
+ : QNetworkRequest()
{
d->url = url;
}
@@ -1344,7 +1355,7 @@ QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
QByteArray QNetworkHeadersPrivate::toHttpDate(const QDateTime &dt)
{
- return QLocale::c().toString(dt, QStringViewLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"))
+ return QLocale::c().toString(dt, u"ddd, dd MMM yyyy hh:mm:ss 'GMT'")
.toLatin1();
}
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index 846ead1592..8ad4ab41c0 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -128,7 +128,8 @@ public:
};
- explicit QNetworkRequest(const QUrl &url = QUrl());
+ QNetworkRequest();
+ explicit QNetworkRequest(const QUrl &url);
QNetworkRequest(const QNetworkRequest &other);
~QNetworkRequest();
QNetworkRequest &operator=(QNetworkRequest &&other) noexcept { swap(other); return *this; }
diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp
index 403c01e974..f845235bf7 100644
--- a/src/network/access/qspdyprotocolhandler.cpp
+++ b/src/network/access/qspdyprotocolhandler.cpp
@@ -305,7 +305,7 @@ bool QSpdyProtocolHandler::sendRequest()
currentReply->setSpdyWasUsed(true);
qint32 streamID = generateNextStreamID();
- currentReply->setProperty("SPDYStreamID", streamID);
+ m_streamIDs.insert(currentReply, streamID);
currentReply->setRequest(currentRequest);
currentReply->d_func()->connection = m_connection;
@@ -322,7 +322,7 @@ bool QSpdyProtocolHandler::sendRequest()
void QSpdyProtocolHandler::_q_replyDestroyed(QObject* reply)
{
- qint32 streamID = reply->property("SPDYStreamID").toInt();
+ qint32 streamID = m_streamIDs.take(reply);
if (m_inFlightStreams.remove(streamID))
sendRST_STREAM(streamID, RST_STREAM_CANCEL);
}
@@ -624,10 +624,12 @@ void QSpdyProtocolHandler::sendSYN_STREAM(const HttpMessagePair &messagePair,
// hack: set the stream ID on the device directly, so when we get
// the signal for uploading we know which stream we are sending on
- request.uploadByteDevice()->setProperty("SPDYStreamID", streamID);
+ m_streamIDs.insert(request.uploadByteDevice(), streamID);
QObject::connect(request.uploadByteDevice(), SIGNAL(readyRead()), this,
SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection);
+ QObject::connect(request.uploadByteDevice(), SIGNAL(destroyed(QObject*)), this,
+ SLOT(_q_uploadDataDestroyed(QObject *)));
}
QByteArray namesAndValues = composeHeader(request);
@@ -663,6 +665,11 @@ void QSpdyProtocolHandler::sendSYN_STREAM(const HttpMessagePair &messagePair,
uploadData(streamID);
}
+void QSpdyProtocolHandler::_q_uploadDataDestroyed(QObject *uploadData)
+{
+ m_streamIDs.remove(uploadData);
+}
+
void QSpdyProtocolHandler::sendRST_STREAM(qint32 streamID, RST_STREAM_STATUS_CODE statusCode)
{
char wireData[8];
@@ -756,7 +763,7 @@ void QSpdyProtocolHandler::_q_uploadDataReadyRead()
{
QNonContiguousByteDevice *device = qobject_cast<QNonContiguousByteDevice *>(sender());
Q_ASSERT(device);
- qint32 streamID = device->property("SPDYStreamID").toInt();
+ qint32 streamID = m_streamIDs.value(device);
Q_ASSERT(streamID > 0);
uploadData(streamID);
}
diff --git a/src/network/access/qspdyprotocolhandler_p.h b/src/network/access/qspdyprotocolhandler_p.h
index dd93a9aba2..14e2ff388a 100644
--- a/src/network/access/qspdyprotocolhandler_p.h
+++ b/src/network/access/qspdyprotocolhandler_p.h
@@ -110,6 +110,7 @@ public:
private slots:
void _q_uploadDataReadyRead();
void _q_replyDestroyed(QObject*);
+ void _q_uploadDataDestroyed(QObject *);
private:
@@ -216,6 +217,7 @@ private:
bool m_waitingForCompleteStream;
z_stream m_deflateStream;
z_stream m_inflateStream;
+ QHash<QObject *, qint32> m_streamIDs;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::DataFrameFlags)