Retire SPDY protocol implementation (Qt6)
As it was superseded by HTTP/2. Bye, Speedy. Since it's Qt 6, we also fix the attribute's enumerator to fit our coding convention with HTTP2AllowedAttribute becoming Http2AllowedAttribute, and the same for HTTP2WasUsedAttribute. tst_qnetworkreply in 'benchmark' directory of qtbase/tests was updated - we have the logic they tested in preConnectEncrypted in tst_http2 now. Manual qnetworkreply test was updated (instead of SPDY in NPN failure we can use H2, the second test was deleted - again, auto-tested in tst_http2). Change-Id: I559c140c333ddf72664911c6e275b1d0d2b980a9 Task-number: QTBUG-78255 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>bb10
parent
3bf3964b37
commit
13e0a36626
|
|
@ -114,11 +114,4 @@ qtConfig(http) {
|
|||
access/qhttpthreaddelegate_p.h \
|
||||
access/qnetworkreplyhttpimpl_p.h \
|
||||
access/qhttp2configuration.h
|
||||
|
||||
qtConfig(ssl) {
|
||||
SOURCES += \
|
||||
access/qspdyprotocolhandler.cpp
|
||||
HEADERS += \
|
||||
access/qspdyprotocolhandler_p.h
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -332,13 +332,13 @@ bool QHttp2ProtocolHandler::sendRequest()
|
|||
// so we cannot create new streams.
|
||||
m_channel->emitFinishedWithError(QNetworkReply::ProtocolUnknownError,
|
||||
"GOAWAY received, cannot start a request");
|
||||
m_channel->spdyRequestsToSend.clear();
|
||||
m_channel->h2RequestsToSend.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process 'fake' (created by QNetworkAccessManager::connectToHostEncrypted())
|
||||
// requests first:
|
||||
auto &requests = m_channel->spdyRequestsToSend;
|
||||
auto &requests = m_channel->h2RequestsToSend;
|
||||
for (auto it = requests.begin(), endIt = requests.end(); it != endIt;) {
|
||||
const auto &pair = *it;
|
||||
const QString scheme(pair.first.url().scheme());
|
||||
|
|
@ -862,7 +862,7 @@ void QHttp2ProtocolHandler::handleGOAWAY()
|
|||
m_channel->emitFinishedWithError(QNetworkReply::ProtocolUnknownError,
|
||||
"GOAWAY received, cannot start a request");
|
||||
// Also, prevent further calls to sendRequest:
|
||||
m_channel->spdyRequestsToSend.clear();
|
||||
m_channel->h2RequestsToSend.clear();
|
||||
|
||||
QNetworkReply::NetworkError error = QNetworkReply::NoError;
|
||||
QString message;
|
||||
|
|
@ -1281,7 +1281,7 @@ quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message, b
|
|||
const auto replyPrivate = reply->d_func();
|
||||
replyPrivate->connection = m_connection;
|
||||
replyPrivate->connectionChannel = m_channel;
|
||||
reply->setSpdyWasUsed(true);
|
||||
reply->setHttp2WasUsed(true);
|
||||
streamIDs.insert(reply, newStreamID);
|
||||
connect(reply, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(_q_replyDestroyed(QObject*)));
|
||||
|
|
@ -1390,7 +1390,7 @@ void QHttp2ProtocolHandler::deleteActiveStream(quint32 streamID)
|
|||
}
|
||||
|
||||
removeFromSuspended(streamID);
|
||||
if (m_channel->spdyRequestsToSend.size())
|
||||
if (m_channel->h2RequestsToSend.size())
|
||||
QMetaObject::invokeMethod(this, "sendRequest", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
|
|
@ -1509,7 +1509,7 @@ void QHttp2ProtocolHandler::initReplyFromPushPromise(const HttpMessagePair &mess
|
|||
Q_ASSERT(promisedData.contains(cacheKey));
|
||||
auto promise = promisedData.take(cacheKey);
|
||||
Q_ASSERT(message.second);
|
||||
message.second->setSpdyWasUsed(true);
|
||||
message.second->setHttp2WasUsed(true);
|
||||
|
||||
qCDebug(QT_HTTP2) << "found cached/promised response on stream" << promise.reservedID;
|
||||
|
||||
|
|
|
|||
|
|
@ -82,9 +82,6 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host
|
|||
hostName(hostName), port(port), encrypt(encrypt), delayIpv4(true)
|
||||
, activeChannelCount(type == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
|| type == QHttpNetworkConnection::ConnectionTypeHTTP2Direct
|
||||
#ifndef QT_NO_SSL
|
||||
|| type == QHttpNetworkConnection::ConnectionTypeSPDY
|
||||
#endif
|
||||
? 1 : defaultHttpChannelCount)
|
||||
, channelCount(defaultHttpChannelCount)
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
|
|
@ -93,9 +90,9 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host
|
|||
, preConnectRequests(0)
|
||||
, connectionType(type)
|
||||
{
|
||||
// We allocate all 6 channels even if it's SPDY or HTTP/2 enabled
|
||||
// connection: in case the protocol negotiation via NPN/ALPN fails,
|
||||
// we will have normally working HTTP/1.1.
|
||||
// We allocate all 6 channels even if it's HTTP/2 enabled connection:
|
||||
// in case the protocol negotiation via NPN/ALPN fails, we will have
|
||||
// normally working HTTP/1.1.
|
||||
Q_ASSERT(channelCount >= activeChannelCount);
|
||||
channels = new QHttpNetworkConnectionChannel[channelCount];
|
||||
}
|
||||
|
|
@ -641,10 +638,10 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
|
|||
break;
|
||||
}
|
||||
}
|
||||
else { // SPDY, HTTP/2 ('h2' mode)
|
||||
else { // HTTP/2 ('h2' mode)
|
||||
if (!pair.second->d_func()->requestIsPrepared)
|
||||
prepareRequest(pair);
|
||||
channels[0].spdyRequestsToSend.insert(request.priority(), pair);
|
||||
channels[0].h2RequestsToSend.insert(request.priority(), pair);
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WINRT
|
||||
|
|
@ -680,7 +677,7 @@ void QHttpNetworkConnectionPrivate::fillHttp2Queue()
|
|||
for (auto &pair : highPriorityQueue) {
|
||||
if (!pair.second->d_func()->requestIsPrepared)
|
||||
prepareRequest(pair);
|
||||
channels[0].spdyRequestsToSend.insert(QHttpNetworkRequest::HighPriority, pair);
|
||||
channels[0].h2RequestsToSend.insert(QHttpNetworkRequest::HighPriority, pair);
|
||||
}
|
||||
|
||||
highPriorityQueue.clear();
|
||||
|
|
@ -688,7 +685,7 @@ void QHttpNetworkConnectionPrivate::fillHttp2Queue()
|
|||
for (auto &pair : lowPriorityQueue) {
|
||||
if (!pair.second->d_func()->requestIsPrepared)
|
||||
prepareRequest(pair);
|
||||
channels[0].spdyRequestsToSend.insert(pair.first.priority(), pair);
|
||||
channels[0].h2RequestsToSend.insert(pair.first.priority(), pair);
|
||||
}
|
||||
|
||||
lowPriorityQueue.clear();
|
||||
|
|
@ -984,12 +981,12 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
|
|||
}
|
||||
}
|
||||
#ifndef QT_NO_SSL
|
||||
// is the reply inside the SPDY pipeline of this channel already?
|
||||
QMultiMap<int, HttpMessagePair>::iterator it = channels[i].spdyRequestsToSend.begin();
|
||||
QMultiMap<int, HttpMessagePair>::iterator end = channels[i].spdyRequestsToSend.end();
|
||||
// is the reply inside the H2 pipeline of this channel already?
|
||||
QMultiMap<int, HttpMessagePair>::iterator it = channels[i].h2RequestsToSend.begin();
|
||||
QMultiMap<int, HttpMessagePair>::iterator end = channels[i].h2RequestsToSend.end();
|
||||
for (; it != end; ++it) {
|
||||
if (it.value().second == reply) {
|
||||
channels[i].spdyRequestsToSend.remove(it.key());
|
||||
channels[i].h2RequestsToSend.remove(it.key());
|
||||
|
||||
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
|
||||
return;
|
||||
|
|
@ -1068,9 +1065,8 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
|
|||
break;
|
||||
}
|
||||
case QHttpNetworkConnection::ConnectionTypeHTTP2Direct:
|
||||
case QHttpNetworkConnection::ConnectionTypeHTTP2:
|
||||
case QHttpNetworkConnection::ConnectionTypeSPDY: {
|
||||
if (channels[0].spdyRequestsToSend.isEmpty() && channels[0].switchedToHttp2)
|
||||
case QHttpNetworkConnection::ConnectionTypeHTTP2: {
|
||||
if (channels[0].h2RequestsToSend.isEmpty() && channels[0].switchedToHttp2)
|
||||
return;
|
||||
|
||||
if (networkLayerState == IPv4)
|
||||
|
|
@ -1079,7 +1075,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
|
|||
channels[0].networkLayerPreference = QAbstractSocket::IPv6Protocol;
|
||||
channels[0].ensureConnection();
|
||||
if (channels[0].socket && channels[0].socket->state() == QAbstractSocket::ConnectedState
|
||||
&& !channels[0].pendingEncrypt && channels[0].spdyRequestsToSend.size())
|
||||
&& !channels[0].pendingEncrypt && channels[0].h2RequestsToSend.size())
|
||||
channels[0].sendRequest();
|
||||
break;
|
||||
}
|
||||
|
|
@ -1234,19 +1230,18 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(const QHostInfo &info)
|
|||
if (dequeueRequest(channels[0].socket)) {
|
||||
emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError);
|
||||
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
||||
} else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY
|
||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
} else if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
for (const HttpMessagePair &spdyPair : qAsConst(channels[0].spdyRequestsToSend)) {
|
||||
for (const HttpMessagePair &h2Pair : qAsConst(channels[0].h2RequestsToSend)) {
|
||||
// emit error for all replies
|
||||
QHttpNetworkReply *currentReply = spdyPair.second;
|
||||
QHttpNetworkReply *currentReply = h2Pair.second;
|
||||
Q_ASSERT(currentReply);
|
||||
emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError);
|
||||
}
|
||||
} else {
|
||||
// Should not happen: we start a host lookup before sending a request,
|
||||
// so it's natural to have requests either in SPDY/HTTP/2 queue,
|
||||
// or in low/high priority queues.
|
||||
// so it's natural to have requests either in HTTP/2 queue, or in low/high
|
||||
// priority queues.
|
||||
qWarning("QHttpNetworkConnectionPrivate::_q_hostLookupFinished"
|
||||
" could not de-queue request, failed to report HostNotFoundError");
|
||||
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
||||
|
|
@ -1576,17 +1571,12 @@ void QHttpNetworkConnectionPrivate::emitProxyAuthenticationRequired(const QHttpN
|
|||
pauseConnection();
|
||||
QHttpNetworkReply *reply;
|
||||
if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct
|
||||
#if QT_CONFIG(ssl)
|
||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeSPDY
|
||||
#endif
|
||||
) {
|
||||
|
||||
|| connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
// we choose the reply to emit the proxyAuth signal from somewhat arbitrarily,
|
||||
// but that does not matter because the signal will ultimately be emitted
|
||||
// by the QNetworkAccessManager.
|
||||
Q_ASSERT(chan->spdyRequestsToSend.count() > 0);
|
||||
reply = chan->spdyRequestsToSend.cbegin().value().second;
|
||||
Q_ASSERT(chan->h2RequestsToSend.count() > 0);
|
||||
reply = chan->h2RequestsToSend.cbegin().value().second;
|
||||
} else { // HTTP
|
||||
reply = chan->reply;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ public:
|
|||
|
||||
enum ConnectionType {
|
||||
ConnectionTypeHTTP,
|
||||
ConnectionTypeSPDY,
|
||||
ConnectionTypeHTTP2,
|
||||
ConnectionTypeHTTP2Direct
|
||||
};
|
||||
|
|
@ -172,7 +171,6 @@ private:
|
|||
friend class QHttpNetworkConnectionChannel;
|
||||
friend class QHttp2ProtocolHandler;
|
||||
friend class QHttpProtocolHandler;
|
||||
friend class QSpdyProtocolHandler;
|
||||
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_hostLookupFinished(QHostInfo))
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
|
||||
#include <private/qhttp2protocolhandler_p.h>
|
||||
#include <private/qhttpprotocolhandler_p.h>
|
||||
#include <private/qspdyprotocolhandler_p.h>
|
||||
#include <private/http2protocol_p.h>
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
|
|
@ -931,7 +930,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
|
|||
} else if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
state = QHttpNetworkConnectionChannel::IdleState;
|
||||
protocolHandler.reset(new QHttp2ProtocolHandler(this));
|
||||
if (spdyRequestsToSend.count() > 0) {
|
||||
if (h2RequestsToSend.count() > 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);
|
||||
|
|
@ -1108,15 +1107,11 @@ 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
|
||||
) {
|
||||
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
||||
for (int a = 0; a < spdyPairs.count(); ++a) {
|
||||
|| connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values();
|
||||
for (int a = 0; a < h2Pairs.count(); ++a) {
|
||||
// emit error for all replies
|
||||
QHttpNetworkReply *currentReply = spdyPairs.at(a).second;
|
||||
QHttpNetworkReply *currentReply = h2Pairs.at(a).second;
|
||||
Q_ASSERT(currentReply);
|
||||
emit currentReply->finishedWithError(errorCode, errorString);
|
||||
}
|
||||
|
|
@ -1143,12 +1138,8 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
|
|||
void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth)
|
||||
{
|
||||
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
|| connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct
|
||||
#ifndef QT_NO_SSL
|
||||
|| connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY
|
||||
#endif
|
||||
) {
|
||||
if (spdyRequestsToSend.count() > 0)
|
||||
|| connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
if (h2RequestsToSend.count() > 0)
|
||||
connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth);
|
||||
} else { // HTTP
|
||||
// Need to dequeue the request before we can emit the error.
|
||||
|
|
@ -1171,9 +1162,9 @@ void QHttpNetworkConnectionChannel::emitFinishedWithError(QNetworkReply::Network
|
|||
{
|
||||
if (reply)
|
||||
emit reply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message));
|
||||
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
||||
for (int a = 0; a < spdyPairs.count(); ++a) {
|
||||
QHttpNetworkReply *currentReply = spdyPairs.at(a).second;
|
||||
QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values();
|
||||
for (int a = 0; a < h2Pairs.count(); ++a) {
|
||||
QHttpNetworkReply *currentReply = h2Pairs.at(a).second;
|
||||
Q_ASSERT(currentReply);
|
||||
emit currentReply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message));
|
||||
}
|
||||
|
|
@ -1195,12 +1186,6 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|||
QByteArray nextProtocol = sslSocket->sslConfiguration().nextNegotiatedProtocol();
|
||||
if (nextProtocol == QSslConfiguration::NextProtocolHttp1_1) {
|
||||
// fall through to create a QHttpProtocolHandler
|
||||
} else if (nextProtocol == QSslConfiguration::NextProtocolSpdy3_0) {
|
||||
protocolHandler.reset(new QSpdyProtocolHandler(this));
|
||||
connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeSPDY);
|
||||
// no need to re-queue requests, if SPDY was enabled on the request it
|
||||
// has gone to the SPDY queue already
|
||||
break;
|
||||
} else if (nextProtocol == QSslConfiguration::ALPNProtocolHTTP2) {
|
||||
switchedToHttp2 = true;
|
||||
protocolHandler.reset(new QHttp2ProtocolHandler(this));
|
||||
|
|
@ -1229,8 +1214,6 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|||
// it again on other channels that our connection can create/open.
|
||||
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2)
|
||||
protocols.removeAll(QSslConfiguration::ALPNProtocolHTTP2);
|
||||
else if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY)
|
||||
protocols.removeAll(QSslConfiguration::NextProtocolSpdy3_0);
|
||||
|
||||
if (nProtocols > protocols.size()) {
|
||||
sslConfiguration->setAllowedNextProtocols(protocols);
|
||||
|
|
@ -1240,13 +1223,13 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|||
}
|
||||
|
||||
connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeHTTP);
|
||||
// We use only one channel for SPDY or HTTP/2, but normally six for
|
||||
// We use only one channel for HTTP/2, but normally six for
|
||||
// HTTP/1.1 - let's restore this number to the reserved number of
|
||||
// channels:
|
||||
if (connection->d_func()->activeChannelCount < connection->d_func()->channelCount) {
|
||||
connection->d_func()->activeChannelCount = connection->d_func()->channelCount;
|
||||
// re-queue requests from SPDY queue to HTTP queue, if any
|
||||
requeueSpdyRequests();
|
||||
// re-queue requests from HTTP/2 queue to HTTP queue, if any
|
||||
requeueHttp2Requests();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1266,11 +1249,9 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|||
state = QHttpNetworkConnectionChannel::IdleState;
|
||||
pendingEncrypt = false;
|
||||
|
||||
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY ||
|
||||
connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 ||
|
||||
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 ||
|
||||
connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
|
||||
// we call setSpdyWasUsed(true) on the replies in the SPDY handler when the request is sent
|
||||
if (spdyRequestsToSend.count() > 0) {
|
||||
if (h2RequestsToSend.count() > 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);
|
||||
|
|
@ -1279,7 +1260,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|||
if (!reply)
|
||||
connection->d_func()->dequeueRequest(socket);
|
||||
if (reply) {
|
||||
reply->setSpdyWasUsed(false);
|
||||
reply->setHttp2WasUsed(false);
|
||||
Q_ASSERT(reply->d_func()->connectionChannel == this);
|
||||
emit reply->encrypted();
|
||||
}
|
||||
|
|
@ -1288,13 +1269,12 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
|||
}
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionChannel::requeueSpdyRequests()
|
||||
void QHttpNetworkConnectionChannel::requeueHttp2Requests()
|
||||
{
|
||||
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
||||
for (int a = 0; a < spdyPairs.count(); ++a) {
|
||||
connection->d_func()->requeueRequest(spdyPairs.at(a));
|
||||
}
|
||||
spdyRequestsToSend.clear();
|
||||
QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values();
|
||||
for (int a = 0; a < h2Pairs.count(); ++a)
|
||||
connection->d_func()->requeueRequest(h2Pairs.at(a));
|
||||
h2RequestsToSend.clear();
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
|
||||
|
|
@ -1312,11 +1292,11 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
|
|||
emit reply->sslErrors(errors);
|
||||
}
|
||||
#ifndef QT_NO_SSL
|
||||
else { // SPDY
|
||||
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
||||
for (int a = 0; a < spdyPairs.count(); ++a) {
|
||||
else { // HTTP/2
|
||||
QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values();
|
||||
for (int a = 0; a < h2Pairs.count(); ++a) {
|
||||
// emit SSL errors for all replies
|
||||
QHttpNetworkReply *currentReply = spdyPairs.at(a).second;
|
||||
QHttpNetworkReply *currentReply = h2Pairs.at(a).second;
|
||||
Q_ASSERT(currentReply);
|
||||
emit currentReply->sslErrors(errors);
|
||||
}
|
||||
|
|
@ -1336,10 +1316,10 @@ void QHttpNetworkConnectionChannel::_q_preSharedKeyAuthenticationRequired(QSslPr
|
|||
if (reply)
|
||||
emit reply->preSharedKeyAuthenticationRequired(authenticator);
|
||||
} else {
|
||||
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
||||
for (int a = 0; a < spdyPairs.count(); ++a) {
|
||||
QList<HttpMessagePair> h2Pairs = h2RequestsToSend.values();
|
||||
for (int a = 0; a < h2Pairs.count(); ++a) {
|
||||
// emit SSL errors for all replies
|
||||
QHttpNetworkReply *currentReply = spdyPairs.at(a).second;
|
||||
QHttpNetworkReply *currentReply = h2Pairs.at(a).second;
|
||||
Q_ASSERT(currentReply);
|
||||
emit currentReply->preSharedKeyAuthenticationRequired(authenticator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,10 +123,7 @@ public:
|
|||
bool authenticationCredentialsSent;
|
||||
bool proxyCredentialsSent;
|
||||
QScopedPointer<QAbstractProtocolHandler> protocolHandler;
|
||||
// SPDY or HTTP/2 requests; SPDY is TLS-only, but
|
||||
// HTTP/2 can be cleartext also, that's why it's
|
||||
// outside of QT_NO_SSL section. Sorted by priority:
|
||||
QMultiMap<int, HttpMessagePair> spdyRequestsToSend;
|
||||
QMultiMap<int, HttpMessagePair> h2RequestsToSend;
|
||||
bool switchedToHttp2 = false;
|
||||
#ifndef QT_NO_SSL
|
||||
bool ignoreAllSslErrors;
|
||||
|
|
@ -135,7 +132,7 @@ public:
|
|||
void ignoreSslErrors();
|
||||
void ignoreSslErrors(const QList<QSslError> &errors);
|
||||
void setSslConfiguration(const QSslConfiguration &config);
|
||||
void requeueSpdyRequests(); // when we wanted SPDY but got HTTP
|
||||
void requeueHttp2Requests(); // when we wanted HTTP/2 but got HTTP/1.1
|
||||
#endif
|
||||
// to emit the signal for all in-flight replies:
|
||||
void emitFinishedWithError(QNetworkReply::NetworkError error, const char *message);
|
||||
|
|
|
|||
|
|
@ -287,14 +287,14 @@ bool QHttpNetworkReply::isPipeliningUsed() const
|
|||
return d_func()->pipeliningUsed;
|
||||
}
|
||||
|
||||
bool QHttpNetworkReply::isSpdyUsed() const
|
||||
bool QHttpNetworkReply::isHttp2Used() const
|
||||
{
|
||||
return d_func()->spdyUsed;
|
||||
return d_func()->h2Used;
|
||||
}
|
||||
|
||||
void QHttpNetworkReply::setSpdyWasUsed(bool spdy)
|
||||
void QHttpNetworkReply::setHttp2WasUsed(bool h2)
|
||||
{
|
||||
d_func()->spdyUsed = spdy;
|
||||
d_func()->h2Used = h2;
|
||||
}
|
||||
|
||||
qint64 QHttpNetworkReply::removedContentLength() const
|
||||
|
|
@ -324,15 +324,11 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
|
|||
forceConnectionCloseEnabled(false),
|
||||
lastChunkRead(false),
|
||||
currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0),
|
||||
windowSizeDownload(65536), // 64K initial window size according to SPDY standard
|
||||
windowSizeUpload(65536), // 64K initial window size according to SPDY standard
|
||||
currentlyReceivedDataInWindow(0),
|
||||
currentlyUploadedDataInWindow(0),
|
||||
totallyUploadedData(0),
|
||||
removedContentLength(-1),
|
||||
connection(0),
|
||||
autoDecompress(false), responseData(), requestIsPrepared(false)
|
||||
,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false)
|
||||
,pipeliningUsed(false), h2Used(false), downstreamLimited(false)
|
||||
,userProvidedDownloadBuffer(0)
|
||||
#ifndef QT_NO_COMPRESS
|
||||
,inflateStrm(0)
|
||||
|
|
|
|||
|
|
@ -137,8 +137,8 @@ public:
|
|||
bool isFinished() const;
|
||||
|
||||
bool isPipeliningUsed() const;
|
||||
bool isSpdyUsed() const;
|
||||
void setSpdyWasUsed(bool spdy);
|
||||
bool isHttp2Used() const;
|
||||
void setHttp2WasUsed(bool h2Used);
|
||||
qint64 removedContentLength() const;
|
||||
|
||||
bool isRedirecting() const;
|
||||
|
|
@ -251,11 +251,7 @@ public:
|
|||
qint64 currentChunkSize;
|
||||
qint64 currentChunkRead;
|
||||
qint64 readBufferMaxSize;
|
||||
qint32 windowSizeDownload; // only for SPDY
|
||||
qint32 windowSizeUpload; // only for SPDY
|
||||
qint32 currentlyReceivedDataInWindow; // only for SPDY
|
||||
qint32 currentlyUploadedDataInWindow; // only for SPDY
|
||||
qint64 totallyUploadedData; // only for SPDY
|
||||
qint64 totallyUploadedData; // HTTP/2
|
||||
qint64 removedContentLength;
|
||||
QPointer<QHttpNetworkConnection> connection;
|
||||
QPointer<QHttpNetworkConnectionChannel> connectionChannel;
|
||||
|
|
@ -267,7 +263,7 @@ public:
|
|||
bool requestIsPrepared;
|
||||
|
||||
bool pipeliningUsed;
|
||||
bool spdyUsed;
|
||||
bool h2Used;
|
||||
bool downstreamLimited;
|
||||
|
||||
char* userProvidedDownloadBuffer;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
|
|||
QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
|
||||
QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
|
||||
: QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
|
||||
autoDecompress(false), pipeliningAllowed(false), spdyAllowed(false), http2Allowed(false),
|
||||
autoDecompress(false), pipeliningAllowed(false), http2Allowed(false),
|
||||
http2Direct(false), withCredentials(true), preConnect(false), redirectCount(0),
|
||||
redirectPolicy(QNetworkRequest::ManualRedirectPolicy)
|
||||
{
|
||||
|
|
@ -59,7 +59,6 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest
|
|||
uploadByteDevice(other.uploadByteDevice),
|
||||
autoDecompress(other.autoDecompress),
|
||||
pipeliningAllowed(other.pipeliningAllowed),
|
||||
spdyAllowed(other.spdyAllowed),
|
||||
http2Allowed(other.http2Allowed),
|
||||
http2Direct(other.http2Direct),
|
||||
withCredentials(other.withCredentials),
|
||||
|
|
@ -83,7 +82,6 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot
|
|||
&& (uploadByteDevice == other.uploadByteDevice)
|
||||
&& (autoDecompress == other.autoDecompress)
|
||||
&& (pipeliningAllowed == other.pipeliningAllowed)
|
||||
&& (spdyAllowed == other.spdyAllowed)
|
||||
&& (http2Allowed == other.http2Allowed)
|
||||
&& (http2Direct == other.http2Direct)
|
||||
// we do not clear the customVerb in setOperation
|
||||
|
|
@ -339,16 +337,6 @@ void QHttpNetworkRequest::setPipeliningAllowed(bool b)
|
|||
d->pipeliningAllowed = b;
|
||||
}
|
||||
|
||||
bool QHttpNetworkRequest::isSPDYAllowed() const
|
||||
{
|
||||
return d->spdyAllowed;
|
||||
}
|
||||
|
||||
void QHttpNetworkRequest::setSPDYAllowed(bool b)
|
||||
{
|
||||
d->spdyAllowed = b;
|
||||
}
|
||||
|
||||
bool QHttpNetworkRequest::isHTTP2Allowed() const
|
||||
{
|
||||
return d->http2Allowed;
|
||||
|
|
|
|||
|
|
@ -116,9 +116,6 @@ public:
|
|||
bool isPipeliningAllowed() const;
|
||||
void setPipeliningAllowed(bool b);
|
||||
|
||||
bool isSPDYAllowed() const;
|
||||
void setSPDYAllowed(bool b);
|
||||
|
||||
bool isHTTP2Allowed() const;
|
||||
void setHTTP2Allowed(bool b);
|
||||
|
||||
|
|
@ -176,7 +173,6 @@ public:
|
|||
mutable QNonContiguousByteDevice* uploadByteDevice;
|
||||
bool autoDecompress;
|
||||
bool pipeliningAllowed;
|
||||
bool spdyAllowed;
|
||||
bool http2Allowed;
|
||||
bool http2Direct;
|
||||
bool withCredentials;
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) :
|
|||
, synchronous(false)
|
||||
, incomingStatusCode(0)
|
||||
, isPipeliningUsed(false)
|
||||
, isSpdyUsed(false)
|
||||
, isHttp2Used(false)
|
||||
, incomingContentLength(-1)
|
||||
, removedContentLength(-1)
|
||||
, incomingErrorCode(QNetworkReply::NoError)
|
||||
|
|
@ -320,17 +320,6 @@ void QHttpThreadDelegate::startRequest()
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
if (!isH2 && httpRequest.isSPDYAllowed() && ssl) {
|
||||
connectionType = QHttpNetworkConnection::ConnectionTypeSPDY;
|
||||
urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests
|
||||
QList<QByteArray> nextProtocols;
|
||||
nextProtocols << QSslConfiguration::NextProtocolSpdy3_0
|
||||
<< QSslConfiguration::NextProtocolHttp1_1;
|
||||
incomingSslConfiguration->setAllowedNextProtocols(nextProtocols);
|
||||
}
|
||||
#endif // QT_NO_SSL
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
if (transparentProxy.type() != QNetworkProxy::NoProxy)
|
||||
cacheKey = makeCacheKey(urlCopy, &transparentProxy, httpRequest.peerVerifyName());
|
||||
|
|
@ -652,7 +641,7 @@ void QHttpThreadDelegate::headerChangedSlot()
|
|||
isPipeliningUsed = httpReply->isPipeliningUsed();
|
||||
incomingContentLength = httpReply->contentLength();
|
||||
removedContentLength = httpReply->removedContentLength();
|
||||
isSpdyUsed = httpReply->isSpdyUsed();
|
||||
isHttp2Used = httpReply->isHttp2Used();
|
||||
|
||||
emit downloadMetaData(incomingHeaders,
|
||||
incomingStatusCode,
|
||||
|
|
@ -661,7 +650,7 @@ void QHttpThreadDelegate::headerChangedSlot()
|
|||
downloadBuffer,
|
||||
incomingContentLength,
|
||||
removedContentLength,
|
||||
isSpdyUsed);
|
||||
isHttp2Used);
|
||||
}
|
||||
|
||||
void QHttpThreadDelegate::synchronousHeaderChangedSlot()
|
||||
|
|
@ -677,7 +666,7 @@ void QHttpThreadDelegate::synchronousHeaderChangedSlot()
|
|||
incomingStatusCode = httpReply->statusCode();
|
||||
incomingReasonPhrase = httpReply->reasonPhrase();
|
||||
isPipeliningUsed = httpReply->isPipeliningUsed();
|
||||
isSpdyUsed = httpReply->isSpdyUsed();
|
||||
isHttp2Used = httpReply->isHttp2Used();
|
||||
incomingContentLength = httpReply->contentLength();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
int incomingStatusCode;
|
||||
QString incomingReasonPhrase;
|
||||
bool isPipeliningUsed;
|
||||
bool isSpdyUsed;
|
||||
bool isHttp2Used;
|
||||
qint64 incomingContentLength;
|
||||
qint64 removedContentLength;
|
||||
QNetworkReply::NetworkError incomingErrorCode;
|
||||
|
|
|
|||
|
|
@ -1237,12 +1237,10 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin
|
|||
if (sslConfiguration != QSslConfiguration::defaultConfiguration())
|
||||
request.setSslConfiguration(sslConfiguration);
|
||||
|
||||
// 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.
|
||||
// There is no way to enable HTTP2 via a request, so we need to check
|
||||
// the ssl configuration whether 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.setAttribute(QNetworkRequest::Http2AllowedAttribute, true);
|
||||
|
||||
request.setPeerVerifyName(peerName);
|
||||
get(request);
|
||||
|
|
|
|||
|
|
@ -774,10 +774,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
|
|||
if (newHttpRequest.attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool())
|
||||
httpRequest.setPipeliningAllowed(true);
|
||||
|
||||
if (request.attribute(QNetworkRequest::SpdyAllowedAttribute).toBool())
|
||||
httpRequest.setSPDYAllowed(true);
|
||||
|
||||
if (request.attribute(QNetworkRequest::HTTP2AllowedAttribute).toBool())
|
||||
if (request.attribute(QNetworkRequest::Http2AllowedAttribute).toBool())
|
||||
httpRequest.setHTTP2Allowed(true);
|
||||
|
||||
if (request.attribute(QNetworkRequest::Http2DirectAttribute).toBool()) {
|
||||
|
|
@ -968,7 +965,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
|
|||
QSharedPointer<char>(),
|
||||
delegate->incomingContentLength,
|
||||
delegate->removedContentLength,
|
||||
delegate->isSpdyUsed);
|
||||
delegate->isHttp2Used);
|
||||
replyDownloadData(delegate->synchronousDownloadData);
|
||||
httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
|
||||
} else {
|
||||
|
|
@ -980,7 +977,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
|
|||
QSharedPointer<char>(),
|
||||
delegate->incomingContentLength,
|
||||
delegate->removedContentLength,
|
||||
delegate->isSpdyUsed);
|
||||
delegate->isHttp2Used);
|
||||
replyDownloadData(delegate->synchronousDownloadData);
|
||||
}
|
||||
|
||||
|
|
@ -1254,7 +1251,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
|
|||
QSharedPointer<char> db,
|
||||
qint64 contentLength,
|
||||
qint64 removedContentLength,
|
||||
bool spdyWasUsed)
|
||||
bool h2Used)
|
||||
{
|
||||
Q_Q(QNetworkReplyHttpImpl);
|
||||
Q_UNUSED(contentLength);
|
||||
|
|
@ -1280,16 +1277,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
|
|||
}
|
||||
|
||||
q->setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu);
|
||||
const QVariant http2Allowed = request.attribute(QNetworkRequest::HTTP2AllowedAttribute);
|
||||
const QVariant http2Direct = request.attribute(QNetworkRequest::Http2DirectAttribute);
|
||||
if ((http2Allowed.isValid() && http2Allowed.toBool())
|
||||
|| (http2Direct.isValid() && http2Direct.toBool())) {
|
||||
q->setAttribute(QNetworkRequest::HTTP2WasUsedAttribute, spdyWasUsed);
|
||||
q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, false);
|
||||
} else {
|
||||
q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, spdyWasUsed);
|
||||
q->setAttribute(QNetworkRequest::HTTP2WasUsedAttribute, false);
|
||||
}
|
||||
q->setAttribute(QNetworkRequest::Http2WasUsedAttribute, h2Used);
|
||||
|
||||
// reconstruct the HTTP header
|
||||
QList<QPair<QByteArray, QByteArray> > headerMap = hm;
|
||||
|
|
|
|||
|
|
@ -272,18 +272,6 @@ QT_BEGIN_NAMESPACE
|
|||
The QNetworkSession ConnectInBackground property will be set according to
|
||||
this attribute.
|
||||
|
||||
\value SpdyAllowedAttribute
|
||||
Requests only, type: QMetaType::Bool (default: false)
|
||||
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. Obsolete, use Http2 instead of Spdy.
|
||||
|
||||
\value Http2AllowedAttribute
|
||||
Requests only, type: QMetaType::Bool (default: false)
|
||||
Indicates whether the QNetworkAccessManager code is
|
||||
|
|
@ -295,12 +283,6 @@ QT_BEGIN_NAMESPACE
|
|||
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.
|
||||
|
|
|
|||
|
|
@ -89,18 +89,10 @@ public:
|
|||
DownloadBufferAttribute, // internal
|
||||
SynchronousRequestAttribute, // internal
|
||||
BackgroundRequestAttribute,
|
||||
#if QT_DEPRECATED_SINCE(5, 15)
|
||||
SpdyAllowedAttribute,
|
||||
SpdyWasUsedAttribute,
|
||||
#endif // QT_DEPRECATED_SINCE(5, 15)
|
||||
EmitAllUploadProgressSignalsAttribute = BackgroundRequestAttribute + 3,
|
||||
FollowRedirectsAttribute,
|
||||
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,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,232 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QSPDYPROTOCOLHANDLER_H
|
||||
#define QSPDYPROTOCOLHANDLER_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of the Network Access API. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtNetwork/private/qtnetworkglobal_p.h>
|
||||
#include <private/qabstractprotocolhandler_p.h>
|
||||
#include <QtNetwork/qnetworkreply.h>
|
||||
#include <private/qbytedata_p.h>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
QT_REQUIRE_CONFIG(http);
|
||||
|
||||
#if !defined(QT_NO_SSL)
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QHttpNetworkRequest;
|
||||
|
||||
#ifndef HttpMessagePair
|
||||
typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
|
||||
#endif
|
||||
|
||||
class QSpdyProtocolHandler : public QObject, public QAbstractProtocolHandler {
|
||||
Q_OBJECT
|
||||
public:
|
||||
QSpdyProtocolHandler(QHttpNetworkConnectionChannel *channel);
|
||||
~QSpdyProtocolHandler();
|
||||
|
||||
enum DataFrameFlag {
|
||||
DataFrame_FLAG_FIN = 0x01,
|
||||
DataFrame_FLAG_COMPRESS = 0x02
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(DataFrameFlags, DataFrameFlag)
|
||||
|
||||
enum ControlFrameFlag {
|
||||
ControlFrame_FLAG_FIN = 0x01,
|
||||
ControlFrame_FLAG_UNIDIRECTIONAL = 0x02
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(ControlFrameFlags, ControlFrameFlag)
|
||||
|
||||
enum SETTINGS_Flag {
|
||||
FLAG_SETTINGS_CLEAR_SETTINGS = 0x01
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(SETTINGS_Flags, SETTINGS_Flag)
|
||||
|
||||
enum SETTINGS_ID_Flag {
|
||||
FLAG_SETTINGS_PERSIST_VALUE = 0x01,
|
||||
FLAG_SETTINGS_PERSISTED = 0x02
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(SETTINGS_ID_Flags, SETTINGS_ID_Flag)
|
||||
|
||||
virtual void _q_receiveReply() override;
|
||||
virtual void _q_readyRead() override;
|
||||
virtual bool sendRequest() override;
|
||||
|
||||
private slots:
|
||||
void _q_uploadDataReadyRead();
|
||||
void _q_replyDestroyed(QObject*);
|
||||
void _q_uploadDataDestroyed(QObject *);
|
||||
|
||||
private:
|
||||
|
||||
enum FrameType {
|
||||
FrameType_SYN_STREAM = 1,
|
||||
FrameType_SYN_REPLY = 2,
|
||||
FrameType_RST_STREAM = 3,
|
||||
FrameType_SETTINGS = 4,
|
||||
FrameType_PING = 6,
|
||||
FrameType_GOAWAY = 7,
|
||||
FrameType_HEADERS = 8,
|
||||
FrameType_WINDOW_UPDATE = 9,
|
||||
FrameType_CREDENTIAL // has a special type
|
||||
};
|
||||
|
||||
enum StatusCode {
|
||||
StatusCode_PROTOCOL_ERROR = 1,
|
||||
StatusCode_INVALID_STREAM = 2,
|
||||
StatusCode_REFUSED_STREAM = 3,
|
||||
StatusCode_UNSUPPORTED_VERSION = 4,
|
||||
StatusCode_CANCEL = 5,
|
||||
StatusCode_INTERNAL_ERROR = 6,
|
||||
StatusCode_FLOW_CONTROL_ERROR = 7,
|
||||
StatusCode_STREAM_IN_USE = 8,
|
||||
StatusCode_STREAM_ALREADY_CLOSED = 9,
|
||||
StatusCode_INVALID_CREDENTIALS = 10,
|
||||
StatusCode_FRAME_TOO_LARGE = 11
|
||||
};
|
||||
|
||||
enum SETTINGS_ID {
|
||||
SETTINGS_UPLOAD_BANDWIDTH = 1,
|
||||
SETTINGS_DOWNLOAD_BANDWIDTH = 2,
|
||||
SETTINGS_ROUND_TRIP_TIME = 3,
|
||||
SETTINGS_MAX_CONCURRENT_STREAMS = 4,
|
||||
SETTINGS_CURRENT_CWND = 5,
|
||||
SETTINGS_DOWNLOAD_RETRANS_RATE = 6,
|
||||
SETTINGS_INITIAL_WINDOW_SIZE = 7,
|
||||
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
|
||||
};
|
||||
|
||||
enum GOAWAY_STATUS {
|
||||
GOAWAY_OK = 0,
|
||||
GOAWAY_PROTOCOL_ERROR = 1,
|
||||
GOAWAY_INTERNAL_ERROR = 11
|
||||
};
|
||||
|
||||
enum RST_STREAM_STATUS_CODE {
|
||||
RST_STREAM_PROTOCOL_ERROR = 1,
|
||||
RST_STREAM_INVALID_STREAM = 2,
|
||||
RST_STREAM_REFUSED_STREAM = 3,
|
||||
RST_STREAM_UNSUPPORTED_VERSION = 4,
|
||||
RST_STREAM_CANCEL = 5,
|
||||
RST_STREAM_INTERNAL_ERROR = 6,
|
||||
RST_STREAM_FLOW_CONTROL_ERROR = 7,
|
||||
RST_STREAM_STREAM_IN_USE = 8,
|
||||
RST_STREAM_STREAM_ALREADY_CLOSED = 9,
|
||||
RST_STREAM_INVALID_CREDENTIALS = 10,
|
||||
RST_STREAM_FRAME_TOO_LARGE = 11
|
||||
};
|
||||
|
||||
quint64 bytesAvailable() const;
|
||||
bool readNextChunk(qint64 length, char *sink);
|
||||
|
||||
void sendControlFrame(FrameType type, ControlFrameFlags flags, const char *data, quint32 length);
|
||||
|
||||
void sendSYN_STREAM(const HttpMessagePair &pair, qint32 streamID,
|
||||
qint32 associatedToStreamID);
|
||||
void sendRST_STREAM(qint32 streamID, RST_STREAM_STATUS_CODE statusCode);
|
||||
void sendPING(quint32 pingID);
|
||||
|
||||
bool uploadData(qint32 streamID);
|
||||
Q_INVOKABLE void sendWINDOW_UPDATE(qint32 streamID, quint32 deltaWindowSize);
|
||||
|
||||
qint64 sendDataFrame(qint32 streamID, DataFrameFlags flags, quint32 length,
|
||||
const char *data);
|
||||
|
||||
QByteArray composeHeader(const QHttpNetworkRequest &request);
|
||||
bool uncompressHeader(const QByteArray &input, QByteArray *output);
|
||||
|
||||
void handleControlFrame(const QByteArray &frameHeaders);
|
||||
void handleDataFrame(const QByteArray &frameHeaders);
|
||||
|
||||
void handleSYN_STREAM(char, quint32, const QByteArray &frameData);
|
||||
void handleSYN_REPLY(char flags, quint32, const QByteArray &frameData);
|
||||
void handleRST_STREAM(char flags, quint32 length, const QByteArray &frameData);
|
||||
void handleSETTINGS(char flags, quint32 length, const QByteArray &frameData);
|
||||
void handlePING(char, quint32 length, const QByteArray &frameData);
|
||||
void handleGOAWAY(char flags, quint32, const QByteArray &frameData);
|
||||
void handleHEADERS(char flags, quint32, const QByteArray &frameData);
|
||||
void handleWINDOW_UPDATE(char, quint32, const QByteArray &frameData);
|
||||
|
||||
qint32 generateNextStreamID();
|
||||
void parseHttpHeaders(char flags, const QByteArray &frameData);
|
||||
|
||||
void replyFinished(QHttpNetworkReply *httpReply, qint32 streamID);
|
||||
void replyFinishedWithError(QHttpNetworkReply *httpReply, qint32 streamID,
|
||||
QNetworkReply::NetworkError errorCode, const char *errorMessage);
|
||||
|
||||
qint32 m_nextStreamID;
|
||||
QHash<quint32, HttpMessagePair> m_inFlightStreams;
|
||||
qint32 m_maxConcurrentStreams;
|
||||
quint32 m_initialWindowSize;
|
||||
QByteDataBuffer m_spdyBuffer;
|
||||
bool m_waitingForCompleteStream;
|
||||
z_stream m_deflateStream;
|
||||
z_stream m_inflateStream;
|
||||
QHash<QObject *, qint32> m_streamIDs;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::DataFrameFlags)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::ControlFrameFlags)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_Flags)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_ID_Flags)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // !defined(QT_NO_SSL)
|
||||
|
||||
#endif // QSPDYPROTOCOLHANDLER_H
|
||||
|
|
@ -54,7 +54,6 @@ const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOp
|
|||
|QSsl::SslOptionDisableSessionPersistence;
|
||||
|
||||
const char QSslConfiguration::ALPNProtocolHTTP2[] = "h2";
|
||||
const char QSslConfiguration::NextProtocolSpdy3_0[] = "spdy/3";
|
||||
const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1";
|
||||
|
||||
/*!
|
||||
|
|
@ -133,12 +132,6 @@ const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1";
|
|||
server could not agree on a common next application protocol.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QSslConfiguration::NextProtocolSpdy3_0
|
||||
\brief The value used for negotiating SPDY 3.0 during the Next
|
||||
Protocol Negotiation.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QSslConfiguration::NextProtocolHttp1_1
|
||||
\brief The value used for negotiating HTTP 1.1 during the Next
|
||||
|
|
@ -967,7 +960,7 @@ QByteArray QSslConfiguration::nextNegotiatedProtocol() const
|
|||
Whether or not the negotiation succeeded can be queried through
|
||||
nextProtocolNegotiationStatus().
|
||||
|
||||
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), allowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1
|
||||
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), allowedNextProtocols(), QSslConfiguration::NextProtocolHttp1_1
|
||||
*/
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
void QSslConfiguration::setAllowedNextProtocols(const QList<QByteArray> &protocols)
|
||||
|
|
@ -985,7 +978,7 @@ void QSslConfiguration::setAllowedNextProtocols(QList<QByteArray> protocols)
|
|||
server through the Next Protocol Negotiation (NPN) or Application-Layer
|
||||
Protocol Negotiation (ALPN) TLS extension, as set by setAllowedNextProtocols().
|
||||
|
||||
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), setAllowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1
|
||||
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), setAllowedNextProtocols(), QSslConfiguration::NextProtocolHttp1_1
|
||||
*/
|
||||
QList<QByteArray> QSslConfiguration::allowedNextProtocols() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -188,7 +188,6 @@ public:
|
|||
NextProtocolNegotiationStatus nextProtocolNegotiationStatus() const;
|
||||
|
||||
static const char ALPNProtocolHTTP2[];
|
||||
static const char NextProtocolSpdy3_0[];
|
||||
static const char NextProtocolHttp1_1[];
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ SUBDIRS=\
|
|||
qnetworkrequest \
|
||||
qhttpnetworkconnection \
|
||||
qnetworkreply \
|
||||
spdy \
|
||||
qnetworkcachemetadata \
|
||||
qftp \
|
||||
qhttpnetworkreply \
|
||||
|
|
|
|||
|
|
@ -219,12 +219,12 @@ void tst_Http2::singleRequest_data()
|
|||
|
||||
// 'Clear text' that should always work, either via the protocol upgrade
|
||||
// or as direct.
|
||||
QTest::addRow("h2c-upgrade") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2c;
|
||||
QTest::addRow("h2c-upgrade") << QNetworkRequest::Http2AllowedAttribute << H2Type::h2c;
|
||||
QTest::addRow("h2c-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2cDirect;
|
||||
|
||||
if (!clearTextHTTP2) {
|
||||
// Qt with TLS where TLS-backend supports ALPN.
|
||||
QTest::addRow("h2-ALPN") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2Alpn;
|
||||
QTest::addRow("h2-ALPN") << QNetworkRequest::Http2AllowedAttribute << H2Type::h2Alpn;
|
||||
}
|
||||
|
||||
#if QT_CONFIG(ssl)
|
||||
|
|
@ -429,7 +429,7 @@ void tst_Http2::pushPromise()
|
|||
url.setPath("/index.html");
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
|
||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true));
|
||||
request.setHttp2Configuration(params);
|
||||
|
||||
auto reply = manager->get(request);
|
||||
|
|
@ -455,7 +455,7 @@ void tst_Http2::pushPromise()
|
|||
|
||||
url.setPath("/script.js");
|
||||
QNetworkRequest promisedRequest(url);
|
||||
promisedRequest.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
|
||||
promisedRequest.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true));
|
||||
reply = manager->get(promisedRequest);
|
||||
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
|
||||
reply->ignoreSslErrors();
|
||||
|
|
@ -509,7 +509,7 @@ void tst_Http2::goaway()
|
|||
for (int i = 0; i < nRequests; ++i) {
|
||||
url.setPath(QString("/%1").arg(i));
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
|
||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true));
|
||||
replies[i] = manager->get(request);
|
||||
QCOMPARE(replies[i]->error(), QNetworkReply::NoError);
|
||||
void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) =
|
||||
|
|
@ -582,7 +582,7 @@ void tst_Http2::connectToHost_data()
|
|||
#if QT_CONFIG(ssl)
|
||||
QTest::addRow("encrypted-h2-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2Direct;
|
||||
if (!clearTextHTTP2)
|
||||
QTest::addRow("encrypted-h2-ALPN") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2Alpn;
|
||||
QTest::addRow("encrypted-h2-ALPN") << QNetworkRequest::Http2AllowedAttribute << H2Type::h2Alpn;
|
||||
#endif // QT_CONFIG(ssl)
|
||||
// This works for all configurations, tests 'preconnect-http' scheme:
|
||||
// h2 with protocol upgrade is not working for now (the logic is a bit
|
||||
|
|
@ -725,7 +725,7 @@ void tst_Http2::maxFrameSize()
|
|||
#endif // QT_CONFIG(securetransport)
|
||||
|
||||
auto connectionType = H2Type::h2Alpn;
|
||||
auto attribute = QNetworkRequest::HTTP2AllowedAttribute;
|
||||
auto attribute = QNetworkRequest::Http2AllowedAttribute;
|
||||
if (clearTextHTTP2) {
|
||||
connectionType = H2Type::h2Direct;
|
||||
attribute = QNetworkRequest::Http2DirectAttribute;
|
||||
|
|
@ -825,7 +825,7 @@ void tst_Http2::sendRequest(int streamNumber,
|
|||
url.setPath(QString("/stream%1.html").arg(streamNumber));
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
|
||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true));
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, QVariant(true));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
|
||||
request.setPriority(priority);
|
||||
|
|
@ -932,20 +932,13 @@ void tst_Http2::replyFinished()
|
|||
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
|
||||
const QVariant http2Used(reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute));
|
||||
const QVariant http2Used(reply->attribute(QNetworkRequest::Http2WasUsedAttribute));
|
||||
if (!http2Used.isValid() || !http2Used.toBool())
|
||||
stopEventLoop();
|
||||
|
||||
QVERIFY(http2Used.isValid());
|
||||
QVERIFY(http2Used.toBool());
|
||||
|
||||
const QVariant spdyUsed(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute));
|
||||
if (!spdyUsed.isValid() || spdyUsed.toBool())
|
||||
stopEventLoop();
|
||||
|
||||
QVERIFY(spdyUsed.isValid());
|
||||
QVERIFY(!spdyUsed.toBool());
|
||||
|
||||
const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute));
|
||||
if (!code.isValid() || !code.canConvert<int>() || code.value<int>() != 200)
|
||||
stopEventLoop();
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
[download]
|
||||
opensuse-leap
|
||||
[upload]
|
||||
opensuse-leap
|
||||
ubuntu-18.04
|
||||
b2qt
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
CONFIG += testcase
|
||||
TARGET = tst_spdy
|
||||
SOURCES += tst_spdy.cpp
|
||||
|
||||
QT = core core-private network network-private testlib
|
||||
|
||||
win32:CONFIG += insignificant_test # QTBUG-47128
|
||||
|
|
@ -1,693 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** 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 General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QHttpPart>
|
||||
#include <QtNetwork/QHttpMultiPart>
|
||||
#include <QtNetwork/QNetworkProxy>
|
||||
#include <QtNetwork/QAuthenticator>
|
||||
#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_OPENSSL)
|
||||
#include <QtNetwork/private/qsslsocket_openssl_p.h>
|
||||
#endif // QT_BUILD_INTERNAL && !QT_NO_OPENSSL
|
||||
|
||||
#include "../../../network-settings.h"
|
||||
|
||||
Q_DECLARE_METATYPE(QAuthenticator*)
|
||||
|
||||
class tst_Spdy: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
tst_Spdy();
|
||||
~tst_Spdy();
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void settingsAndNegotiation_data();
|
||||
void settingsAndNegotiation();
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
void download_data();
|
||||
void download();
|
||||
#endif // !QT_NO_NETWORKPROXY
|
||||
void headerFields();
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
void upload_data();
|
||||
void upload();
|
||||
void errors_data();
|
||||
void errors();
|
||||
#endif // !QT_NO_NETWORKPROXY
|
||||
void multipleRequests_data();
|
||||
void multipleRequests();
|
||||
|
||||
private:
|
||||
QNetworkAccessManager m_manager;
|
||||
int m_multipleRequestsCount;
|
||||
int m_multipleRepliesFinishedCount;
|
||||
const QString m_rfc3252FilePath;
|
||||
|
||||
protected Q_SLOTS:
|
||||
void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *authenticator);
|
||||
void multipleRequestsFinishedSlot();
|
||||
};
|
||||
|
||||
tst_Spdy::tst_Spdy()
|
||||
: m_rfc3252FilePath(QFINDTESTDATA("../qnetworkreply/rfc3252.txt"))
|
||||
{
|
||||
#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
qRegisterMetaType<QNetworkReply *>(); // for QSignalSpy
|
||||
qRegisterMetaType<QAuthenticator *>();
|
||||
|
||||
connect(&m_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),
|
||||
this, SLOT(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
|
||||
#else
|
||||
QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old");
|
||||
#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ...
|
||||
}
|
||||
|
||||
tst_Spdy::~tst_Spdy()
|
||||
{
|
||||
}
|
||||
|
||||
void tst_Spdy::initTestCase()
|
||||
{
|
||||
QVERIFY(!m_rfc3252FilePath.isEmpty());
|
||||
QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
|
||||
}
|
||||
|
||||
void tst_Spdy::settingsAndNegotiation_data()
|
||||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<bool>("setAttribute");
|
||||
QTest::addColumn<bool>("enabled");
|
||||
QTest::addColumn<QByteArray>("expectedProtocol");
|
||||
QTest::addColumn<QByteArray>("expectedContent");
|
||||
|
||||
QTest::newRow("default-settings") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/cgi-bin/echo.cgi?1")
|
||||
<< false << false << QByteArray()
|
||||
<< QByteArray("1");
|
||||
|
||||
QTest::newRow("http-url") << QUrl("http://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/cgi-bin/echo.cgi?1")
|
||||
<< true << true << QByteArray()
|
||||
<< QByteArray("1");
|
||||
|
||||
QTest::newRow("spdy-disabled") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/cgi-bin/echo.cgi?1")
|
||||
<< true << false << QByteArray()
|
||||
<< QByteArray("1");
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
QTest::newRow("spdy-enabled") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/cgi-bin/echo.cgi?1")
|
||||
<< true << true << QByteArray(QSslConfiguration::NextProtocolSpdy3_0)
|
||||
<< QByteArray("1");
|
||||
#endif // QT_NO_OPENSSL
|
||||
}
|
||||
|
||||
void tst_Spdy::settingsAndNegotiation()
|
||||
{
|
||||
QFETCH(QUrl, url);
|
||||
QFETCH(bool, setAttribute);
|
||||
QFETCH(bool, enabled);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
|
||||
if (setAttribute) {
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(enabled));
|
||||
}
|
||||
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
reply->ignoreSslErrors();
|
||||
QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged()));
|
||||
QSignalSpy readyReadSpy(reply, SIGNAL(readyRead()));
|
||||
QSignalSpy finishedSpy(reply, SIGNAL(finished()));
|
||||
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QFETCH(QByteArray, expectedProtocol);
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
bool expectedSpdyUsed = (expectedProtocol == QSslConfiguration::NextProtocolSpdy3_0);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), expectedSpdyUsed);
|
||||
#endif // QT_NO_OPENSSL
|
||||
|
||||
QCOMPARE(metaDataChangedSpy.count(), 1);
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
|
||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
QCOMPARE(statusCode, 200);
|
||||
|
||||
QByteArray content = reply->readAll();
|
||||
|
||||
QFETCH(QByteArray, expectedContent);
|
||||
QCOMPARE(expectedContent, content);
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
QSslConfiguration::NextProtocolNegotiationStatus expectedStatus =
|
||||
(expectedProtocol.isEmpty())
|
||||
? QSslConfiguration::NextProtocolNegotiationNone
|
||||
: QSslConfiguration::NextProtocolNegotiationNegotiated;
|
||||
QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(),
|
||||
expectedStatus);
|
||||
|
||||
QCOMPARE(reply->sslConfiguration().nextNegotiatedProtocol(), expectedProtocol);
|
||||
#endif // QT_NO_OPENSSL
|
||||
}
|
||||
|
||||
void tst_Spdy::proxyAuthenticationRequired(const QNetworkProxy &/*proxy*/,
|
||||
QAuthenticator *authenticator)
|
||||
{
|
||||
authenticator->setUser("qsockstest");
|
||||
authenticator->setPassword("password");
|
||||
}
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
void tst_Spdy::download_data()
|
||||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<QNetworkProxy>("proxy");
|
||||
|
||||
QTest::newRow("mediumfile") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/rfc3252.txt")
|
||||
<< m_rfc3252FilePath
|
||||
<< QNetworkProxy();
|
||||
|
||||
QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName());
|
||||
QString proxyserver = hostInfo.addresses().first().toString();
|
||||
|
||||
QTest::newRow("mediumfile-http-proxy") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/rfc3252.txt")
|
||||
<< m_rfc3252FilePath
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128);
|
||||
|
||||
QTest::newRow("mediumfile-http-proxy-auth") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/rfc3252.txt")
|
||||
<< m_rfc3252FilePath
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy,
|
||||
proxyserver, 3129);
|
||||
|
||||
QTest::newRow("mediumfile-socks-proxy") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/rfc3252.txt")
|
||||
<< m_rfc3252FilePath
|
||||
<< QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080);
|
||||
|
||||
QTest::newRow("mediumfile-socks-proxy-auth") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/rfc3252.txt")
|
||||
<< m_rfc3252FilePath
|
||||
<< QNetworkProxy(QNetworkProxy::Socks5Proxy,
|
||||
proxyserver, 1081);
|
||||
|
||||
QTest::newRow("bigfile") << QUrl("https://" + QtNetworkSettings::serverName()
|
||||
+ "/qtest/bigfile")
|
||||
<< QFINDTESTDATA("../qnetworkreply/bigfile")
|
||||
<< QNetworkProxy();
|
||||
}
|
||||
|
||||
void tst_Spdy::download()
|
||||
{
|
||||
QFETCH(QUrl, url);
|
||||
QFETCH(QString, fileName);
|
||||
QFETCH(QNetworkProxy, proxy);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
|
||||
if (proxy.type() != QNetworkProxy::DefaultProxy) {
|
||||
m_manager.setProxy(proxy);
|
||||
}
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
reply->ignoreSslErrors();
|
||||
QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged()));
|
||||
QSignalSpy downloadProgressSpy(reply, SIGNAL(downloadProgress(qint64, qint64)));
|
||||
QSignalSpy readyReadSpy(reply, SIGNAL(readyRead()));
|
||||
QSignalSpy finishedSpy(reply, SIGNAL(finished()));
|
||||
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*)));
|
||||
QSignalSpy proxyAuthRequiredSpy(&m_manager, SIGNAL(
|
||||
proxyAuthenticationRequired(const QNetworkProxy &,
|
||||
QAuthenticator *)));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(finishedManagerSpy.count(), 1);
|
||||
QCOMPARE(metaDataChangedSpy.count(), 1);
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
QVERIFY(downloadProgressSpy.count() > 0);
|
||||
QVERIFY(readyReadSpy.count() > 0);
|
||||
|
||||
QVERIFY(proxyAuthRequiredSpy.count() <= 1);
|
||||
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||
|
||||
QFile file(fileName);
|
||||
QVERIFY(file.open(QIODevice::ReadOnly));
|
||||
|
||||
qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong();
|
||||
qint64 expectedContentLength = file.bytesAvailable();
|
||||
QCOMPARE(contentLength, expectedContentLength);
|
||||
|
||||
QByteArray expectedContent = file.readAll();
|
||||
QByteArray content = reply->readAll();
|
||||
QCOMPARE(content, expectedContent);
|
||||
|
||||
reply->deleteLater();
|
||||
m_manager.setProxy(QNetworkProxy()); // reset
|
||||
}
|
||||
#endif // !QT_NO_NETWORKPROXY
|
||||
|
||||
void tst_Spdy::headerFields()
|
||||
{
|
||||
QUrl url(QUrl("https://" + QtNetworkSettings::serverName()));
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
reply->ignoreSslErrors();
|
||||
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(reply->rawHeader("Content-Type"), QByteArray("text/html"));
|
||||
QVERIFY(reply->rawHeader("Content-Length").toInt() > 0);
|
||||
QVERIFY(reply->rawHeader("server").contains("Apache"));
|
||||
|
||||
QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader).toByteArray(), QByteArray("text/html"));
|
||||
QVERIFY(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong() > 0);
|
||||
QVERIFY(reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid());
|
||||
QVERIFY(reply->header(QNetworkRequest::ServerHeader).toByteArray().contains("Apache"));
|
||||
}
|
||||
|
||||
static inline QByteArray md5sum(const QByteArray &data)
|
||||
{
|
||||
return QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex().append('\n');
|
||||
}
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
void tst_Spdy::upload_data()
|
||||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<QByteArray>("data");
|
||||
QTest::addColumn<QByteArray>("uploadMethod");
|
||||
QTest::addColumn<QObject *>("uploadObject");
|
||||
QTest::addColumn<QByteArray>("md5sum");
|
||||
QTest::addColumn<QNetworkProxy>("proxy");
|
||||
|
||||
|
||||
// 1. test uploading of byte arrays
|
||||
|
||||
QUrl md5Url("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
|
||||
|
||||
QByteArray data;
|
||||
data = "";
|
||||
QObject *dummyObject = 0;
|
||||
QTest::newRow("empty") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
data = "This is a normal message.";
|
||||
QTest::newRow("generic") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
data = "This is a message to show that Qt rocks!\r\n\n";
|
||||
QTest::newRow("small") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
data = QByteArray("abcd\0\1\2\abcd",12);
|
||||
QTest::newRow("with-nul") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
data = QByteArray(4097, '\4');
|
||||
QTest::newRow("4k+1") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data)<< QNetworkProxy();
|
||||
|
||||
QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName());
|
||||
QString proxyserver = hostInfo.addresses().first().toString();
|
||||
|
||||
QTest::newRow("4k+1-with-http-proxy") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data)
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128);
|
||||
|
||||
QTest::newRow("4k+1-with-http-proxy-auth") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data)
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy,
|
||||
proxyserver, 3129);
|
||||
|
||||
QTest::newRow("4k+1-with-socks-proxy") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data)
|
||||
<< QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080);
|
||||
|
||||
QTest::newRow("4k+1-with-socks-proxy-auth") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data)
|
||||
<< QNetworkProxy(QNetworkProxy::Socks5Proxy,
|
||||
proxyserver, 1081);
|
||||
|
||||
data = QByteArray(128*1024+1, '\177');
|
||||
QTest::newRow("128k+1") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
data = QByteArray(128*1024+1, '\177');
|
||||
QTest::newRow("128k+1-put") << md5Url << data << QByteArray("PUT") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
data = QByteArray(2*1024*1024+1, '\177');
|
||||
QTest::newRow("2MB+1") << md5Url << data << QByteArray("POST") << dummyObject
|
||||
<< md5sum(data) << QNetworkProxy();
|
||||
|
||||
|
||||
// 2. test uploading of files
|
||||
|
||||
QFile *file = new QFile(m_rfc3252FilePath);
|
||||
file->open(QIODevice::ReadOnly);
|
||||
QTest::newRow("file-26K") << md5Url << QByteArray() << QByteArray("POST")
|
||||
<< static_cast<QObject *>(file)
|
||||
<< QByteArray("b3e32ac459b99d3f59318f3ac31e4bee\n") << QNetworkProxy();
|
||||
|
||||
QFile *file2 = new QFile(QFINDTESTDATA("../qnetworkreply/image1.jpg"));
|
||||
file2->open(QIODevice::ReadOnly);
|
||||
QTest::newRow("file-1MB") << md5Url << QByteArray() << QByteArray("POST")
|
||||
<< static_cast<QObject *>(file2)
|
||||
<< QByteArray("87ef3bb319b004ba9e5e9c9fa713776e\n") << QNetworkProxy();
|
||||
|
||||
|
||||
// 3. test uploading of multipart
|
||||
|
||||
QUrl multiPartUrl("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi");
|
||||
|
||||
QHttpPart imagePart31;
|
||||
imagePart31.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
|
||||
imagePart31.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage1\""));
|
||||
imagePart31.setRawHeader("Content-Location", "http://my.test.location.tld");
|
||||
imagePart31.setRawHeader("Content-ID", "my@id.tld");
|
||||
QFile *file31 = new QFile(QFINDTESTDATA("../qnetworkreply/image1.jpg"));
|
||||
file31->open(QIODevice::ReadOnly);
|
||||
imagePart31.setBodyDevice(file31);
|
||||
QHttpMultiPart *imageMultiPart3 = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
imageMultiPart3->append(imagePart31);
|
||||
file31->setParent(imageMultiPart3);
|
||||
QHttpPart imagePart32;
|
||||
imagePart32.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
|
||||
imagePart32.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage2\""));
|
||||
QFile *file32 = new QFile(QFINDTESTDATA("../qnetworkreply/image2.jpg"));
|
||||
file32->open(QIODevice::ReadOnly);
|
||||
imagePart32.setBodyDevice(file31); // check that resetting works
|
||||
imagePart32.setBodyDevice(file32);
|
||||
imageMultiPart3->append(imagePart32);
|
||||
file32->setParent(imageMultiPart3);
|
||||
QHttpPart imagePart33;
|
||||
imagePart33.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
|
||||
imagePart33.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage3\""));
|
||||
QFile *file33 = new QFile(QFINDTESTDATA("../qnetworkreply/image3.jpg"));
|
||||
file33->open(QIODevice::ReadOnly);
|
||||
imagePart33.setBodyDevice(file33);
|
||||
imageMultiPart3->append(imagePart33);
|
||||
file33->setParent(imageMultiPart3);
|
||||
QByteArray expectedData = "content type: multipart/form-data; boundary=\""
|
||||
+ imageMultiPart3->boundary();
|
||||
expectedData.append("\"\nkey: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"
|
||||
"key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n"
|
||||
"key: testImage3, value: ab0eb6fd4fcf8b4436254870b4513033\n");
|
||||
|
||||
QTest::newRow("multipart-3images") << multiPartUrl << QByteArray() << QByteArray("POST")
|
||||
<< static_cast<QObject *>(imageMultiPart3) << expectedData
|
||||
<< QNetworkProxy();
|
||||
}
|
||||
|
||||
void tst_Spdy::upload()
|
||||
{
|
||||
QFETCH(QUrl, url);
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
|
||||
QFETCH(QByteArray, data);
|
||||
QFETCH(QByteArray, uploadMethod);
|
||||
QFETCH(QObject *, uploadObject);
|
||||
QFETCH(QNetworkProxy, proxy);
|
||||
|
||||
if (proxy.type() != QNetworkProxy::DefaultProxy) {
|
||||
m_manager.setProxy(proxy);
|
||||
}
|
||||
|
||||
QNetworkReply *reply;
|
||||
QHttpMultiPart *multiPart = 0;
|
||||
|
||||
if (uploadObject) {
|
||||
// upload via device
|
||||
if (QIODevice *device = qobject_cast<QIODevice *>(uploadObject)) {
|
||||
reply = m_manager.post(request, device);
|
||||
} else if ((multiPart = qobject_cast<QHttpMultiPart *>(uploadObject))) {
|
||||
reply = m_manager.post(request, multiPart);
|
||||
} else {
|
||||
QFAIL("got unknown upload device");
|
||||
}
|
||||
} else {
|
||||
// upload via byte array
|
||||
if (uploadMethod == "PUT") {
|
||||
reply = m_manager.put(request, data);
|
||||
} else {
|
||||
reply = m_manager.post(request, data);
|
||||
}
|
||||
}
|
||||
|
||||
reply->ignoreSslErrors();
|
||||
QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged()));
|
||||
QSignalSpy uploadProgressSpy(reply, SIGNAL(uploadProgress(qint64, qint64)));
|
||||
QSignalSpy readyReadSpy(reply, SIGNAL(readyRead()));
|
||||
QSignalSpy finishedSpy(reply, SIGNAL(finished()));
|
||||
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(20);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(finishedManagerSpy.count(), 1);
|
||||
QCOMPARE(metaDataChangedSpy.count(), 1);
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
QVERIFY(uploadProgressSpy.count() > 0);
|
||||
QVERIFY(readyReadSpy.count() > 0);
|
||||
|
||||
QCOMPARE(reply->error(), QNetworkReply::NoError);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||
|
||||
qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong();
|
||||
if (!multiPart) // script to test multiparts does not return a content length
|
||||
QCOMPARE(contentLength, 33); // 33 bytes for md5 sums (including new line)
|
||||
|
||||
QFETCH(QByteArray, md5sum);
|
||||
QByteArray content = reply->readAll();
|
||||
QCOMPARE(content, md5sum);
|
||||
|
||||
reply->deleteLater();
|
||||
if (uploadObject)
|
||||
uploadObject->deleteLater();
|
||||
|
||||
m_manager.setProxy(QNetworkProxy()); // reset
|
||||
}
|
||||
|
||||
void tst_Spdy::errors_data()
|
||||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
QTest::addColumn<QNetworkProxy>("proxy");
|
||||
QTest::addColumn<bool>("ignoreSslErrors");
|
||||
QTest::addColumn<int>("expectedReplyError");
|
||||
|
||||
QTest::newRow("http-404") << QUrl("https://" + QtNetworkSettings::serverName() + "/non-existent-url")
|
||||
<< QNetworkProxy() << true << int(QNetworkReply::ContentNotFoundError);
|
||||
|
||||
QTest::newRow("ssl-errors") << QUrl("https://" + QtNetworkSettings::serverName())
|
||||
<< QNetworkProxy() << false << int(QNetworkReply::SslHandshakeFailedError);
|
||||
|
||||
QTest::newRow("host-not-found") << QUrl("https://this-host-does-not.exist")
|
||||
<< QNetworkProxy()
|
||||
<< true << int(QNetworkReply::HostNotFoundError);
|
||||
|
||||
QTest::newRow("proxy-not-found") << QUrl("https://" + QtNetworkSettings::serverName())
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy,
|
||||
"https://this-host-does-not.exist", 3128)
|
||||
<< true << int(QNetworkReply::HostNotFoundError);
|
||||
|
||||
QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName());
|
||||
QString proxyserver = hostInfo.addresses().first().toString();
|
||||
|
||||
QTest::newRow("proxy-unavailable") << QUrl("https://" + QtNetworkSettings::serverName())
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 10)
|
||||
<< true << int(QNetworkReply::UnknownNetworkError);
|
||||
|
||||
QTest::newRow("no-proxy-credentials") << QUrl("https://" + QtNetworkSettings::serverName())
|
||||
<< QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3129)
|
||||
<< true << int(QNetworkReply::ProxyAuthenticationRequiredError);
|
||||
}
|
||||
|
||||
void tst_Spdy::errors()
|
||||
{
|
||||
QFETCH(QUrl, url);
|
||||
QFETCH(QNetworkProxy, proxy);
|
||||
QFETCH(bool, ignoreSslErrors);
|
||||
QFETCH(int, expectedReplyError);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
|
||||
disconnect(&m_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),
|
||||
0, 0);
|
||||
if (proxy.type() != QNetworkProxy::DefaultProxy) {
|
||||
m_manager.setProxy(proxy);
|
||||
}
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
if (ignoreSslErrors)
|
||||
reply->ignoreSslErrors();
|
||||
QSignalSpy finishedSpy(reply, SIGNAL(finished()));
|
||||
QSignalSpy errorSpy(reply, SIGNAL(error(QNetworkReply::NetworkError)));
|
||||
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
QCOMPARE(errorSpy.count(), 1);
|
||||
|
||||
QCOMPARE(reply->error(), static_cast<QNetworkReply::NetworkError>(expectedReplyError));
|
||||
|
||||
m_manager.setProxy(QNetworkProxy()); // reset
|
||||
m_manager.clearAccessCache(); // e.g. to get an SSL error we need a new connection
|
||||
connect(&m_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),
|
||||
this, SLOT(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),
|
||||
Qt::UniqueConnection); // reset
|
||||
}
|
||||
#endif // !QT_NO_NETWORKPROXY
|
||||
|
||||
void tst_Spdy::multipleRequests_data()
|
||||
{
|
||||
QTest::addColumn<QList<QUrl> >("urls");
|
||||
|
||||
QString baseUrl = "https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/echo.cgi?";
|
||||
QList<QUrl> urls;
|
||||
for (int a = 1; a <= 50; ++a)
|
||||
urls.append(QUrl(baseUrl + QLatin1String(QByteArray::number(a))));
|
||||
|
||||
QTest::newRow("one-request") << urls.mid(0, 1);
|
||||
QTest::newRow("two-requests") << urls.mid(0, 2);
|
||||
QTest::newRow("ten-requests") << urls.mid(0, 10);
|
||||
QTest::newRow("twenty-requests") << urls.mid(0, 20);
|
||||
QTest::newRow("fifty-requests") << urls;
|
||||
}
|
||||
|
||||
void tst_Spdy::multipleRequestsFinishedSlot()
|
||||
{
|
||||
m_multipleRepliesFinishedCount++;
|
||||
if (m_multipleRepliesFinishedCount == m_multipleRequestsCount)
|
||||
QTestEventLoop::instance().exitLoop();
|
||||
}
|
||||
|
||||
void tst_Spdy::multipleRequests()
|
||||
{
|
||||
QFETCH(QList<QUrl>, urls);
|
||||
m_multipleRequestsCount = urls.count();
|
||||
m_multipleRepliesFinishedCount = 0;
|
||||
|
||||
QList<QNetworkReply *> replies;
|
||||
QList<QSignalSpy *> metaDataChangedSpies;
|
||||
QList<QSignalSpy *> readyReadSpies;
|
||||
QList<QSignalSpy *> finishedSpies;
|
||||
|
||||
foreach (const QUrl &url, urls) {
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
replies.append(reply);
|
||||
reply->ignoreSslErrors();
|
||||
QObject::connect(reply, SIGNAL(finished()), this, SLOT(multipleRequestsFinishedSlot()));
|
||||
QSignalSpy *metaDataChangedSpy = new QSignalSpy(reply, SIGNAL(metaDataChanged()));
|
||||
metaDataChangedSpies << metaDataChangedSpy;
|
||||
QSignalSpy *readyReadSpy = new QSignalSpy(reply, SIGNAL(readyRead()));
|
||||
readyReadSpies << readyReadSpy;
|
||||
QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished()));
|
||||
finishedSpies << finishedSpy;
|
||||
}
|
||||
|
||||
QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(finishedManagerSpy.count(), m_multipleRequestsCount);
|
||||
|
||||
for (int a = 0; a < replies.count(); ++a) {
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
QCOMPARE(replies.at(a)->sslConfiguration().nextProtocolNegotiationStatus(),
|
||||
QSslConfiguration::NextProtocolNegotiationNegotiated);
|
||||
QCOMPARE(replies.at(a)->sslConfiguration().nextNegotiatedProtocol(),
|
||||
QByteArray(QSslConfiguration::NextProtocolSpdy3_0));
|
||||
#endif // QT_NO_OPENSSL
|
||||
|
||||
QCOMPARE(replies.at(a)->error(), QNetworkReply::NoError);
|
||||
QCOMPARE(replies.at(a)->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true);
|
||||
QCOMPARE(replies.at(a)->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true);
|
||||
QCOMPARE(replies.at(a)->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||
|
||||
// using the echo script, a request to "echo.cgi?1" will return a body of "1"
|
||||
QByteArray expectedContent = replies.at(a)->url().query().toUtf8();
|
||||
QByteArray content = replies.at(a)->readAll();
|
||||
QCOMPARE(expectedContent, content);
|
||||
|
||||
QCOMPARE(metaDataChangedSpies.at(a)->count(), 1);
|
||||
metaDataChangedSpies.at(a)->deleteLater();
|
||||
|
||||
QCOMPARE(finishedSpies.at(a)->count(), 1);
|
||||
finishedSpies.at(a)->deleteLater();
|
||||
|
||||
QVERIFY(readyReadSpies.at(a)->count() > 0);
|
||||
readyReadSpies.at(a)->deleteLater();
|
||||
|
||||
replies.at(a)->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_Spdy)
|
||||
|
||||
#include "tst_spdy.moc"
|
||||
|
|
@ -544,15 +544,10 @@ void tst_qnetworkreply::echoPerformance()
|
|||
void tst_qnetworkreply::preConnectEncrypted()
|
||||
{
|
||||
QFETCH(int, sleepTime);
|
||||
QFETCH(QSslConfiguration, sslConfiguration);
|
||||
bool spdyEnabled = !sslConfiguration.isNull();
|
||||
|
||||
QString hostName = QLatin1String("www.google.com");
|
||||
|
||||
QNetworkAccessManager manager;
|
||||
QNetworkRequest request(QUrl("https://" + hostName));
|
||||
if (spdyEnabled)
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
|
||||
// make sure we have a full request including
|
||||
// DNS lookup, TCP and SSL handshakes
|
||||
|
|
@ -578,12 +573,7 @@ void tst_qnetworkreply::preConnectEncrypted()
|
|||
manager.clearAccessCache();
|
||||
|
||||
// now try to make the connection beforehand
|
||||
if (spdyEnabled) {
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
manager.connectToHostEncrypted(hostName, 443, sslConfiguration);
|
||||
} else {
|
||||
manager.connectToHostEncrypted(hostName);
|
||||
}
|
||||
manager.connectToHostEncrypted(hostName);
|
||||
QTestEventLoop::instance().enterLoopMSecs(sleepTime);
|
||||
|
||||
// now make another request and hopefully use the existing connection
|
||||
|
|
@ -591,8 +581,6 @@ void tst_qnetworkreply::preConnectEncrypted()
|
|||
QNetworkReply *preConnectReply = normalResult.first;
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
QVERIFY(preConnectReply->error() == QNetworkReply::NoError);
|
||||
bool spdyWasUsed = preConnectReply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool();
|
||||
QCOMPARE(spdyEnabled, spdyWasUsed);
|
||||
qint64 preConnectElapsed = preConnectResult.second;
|
||||
qDebug() << request.url().toString() << "full request:" << normalElapsed
|
||||
<< "ms, pre-connect request:" << preConnectElapsed << "ms, difference:"
|
||||
|
|
@ -605,27 +593,11 @@ void tst_qnetworkreply::preConnectEncrypted_data()
|
|||
{
|
||||
#ifndef QT_NO_OPENSSL
|
||||
QTest::addColumn<int>("sleepTime");
|
||||
QTest::addColumn<QSslConfiguration>("sslConfiguration");
|
||||
|
||||
// start a new normal request after preconnecting is done
|
||||
QTest::newRow("HTTPS-2secs") << 2000 << QSslConfiguration();
|
||||
QTest::newRow("HTTPS-2secs") << 2000;
|
||||
|
||||
// start a new normal request while preconnecting is in-flight
|
||||
QTest::newRow("HTTPS-100ms") << 100 << QSslConfiguration();
|
||||
|
||||
QSslConfiguration spdySslConf = QSslConfiguration::defaultConfiguration();
|
||||
QList<QByteArray> nextProtocols = QList<QByteArray>()
|
||||
<< QSslConfiguration::NextProtocolSpdy3_0
|
||||
<< QSslConfiguration::NextProtocolHttp1_1;
|
||||
spdySslConf.setAllowedNextProtocols(nextProtocols);
|
||||
|
||||
#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
// start a new SPDY request while preconnecting is done
|
||||
QTest::newRow("SPDY-2secs") << 2000 << spdySslConf;
|
||||
|
||||
// start a new SPDY request while preconnecting is in-flight
|
||||
QTest::newRow("SPDY-100ms") << 100 << spdySslConf;
|
||||
#endif // defined (QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ...
|
||||
QTest::newRow("HTTPS-100ms") << 100;
|
||||
#endif // QT_NO_OPENSSL
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,9 +58,6 @@ private slots:
|
|||
void setSslConfiguration_data();
|
||||
void setSslConfiguration();
|
||||
void uploadToFacebook();
|
||||
void spdy_data();
|
||||
void spdy();
|
||||
void spdyMultipleRequestsPerHost();
|
||||
void proxyAuthentication_data();
|
||||
void proxyAuthentication();
|
||||
void authentication();
|
||||
|
|
@ -290,126 +287,6 @@ void tst_qnetworkreply::uploadToFacebook()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::spdy_data()
|
||||
{
|
||||
QTest::addColumn<QString>("host");
|
||||
QTest::addColumn<bool>("setAttribute");
|
||||
QTest::addColumn<bool>("enabled");
|
||||
QTest::addColumn<QByteArray>("expectedProtocol");
|
||||
|
||||
QList<QString> hosts = QList<QString>()
|
||||
<< QStringLiteral("www.google.com") // sends SPDY and 30x redirect
|
||||
<< QStringLiteral("www.google.de") // sends SPDY and 200 OK
|
||||
<< QStringLiteral("mail.google.com") // sends SPDY and 200 OK
|
||||
<< QStringLiteral("www.youtube.com") // sends SPDY and 200 OK
|
||||
<< QStringLiteral("www.dropbox.com") // no SPDY, but NPN which selects HTTP
|
||||
<< QStringLiteral("www.facebook.com") // sends SPDY and 200 OK
|
||||
<< QStringLiteral("graph.facebook.com") // sends SPDY and 200 OK
|
||||
<< QStringLiteral("www.twitter.com") // sends SPDY and 30x redirect
|
||||
<< QStringLiteral("twitter.com") // sends SPDY and 200 OK
|
||||
<< QStringLiteral("api.twitter.com"); // sends SPDY and 200 OK
|
||||
|
||||
foreach (const QString &host, hosts) {
|
||||
QByteArray tag = host.toLocal8Bit();
|
||||
tag.append("-not-used");
|
||||
QTest::newRow(tag)
|
||||
<< QStringLiteral("https://") + host
|
||||
<< false
|
||||
<< false
|
||||
<< QByteArray();
|
||||
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-disabled");
|
||||
QTest::newRow(tag)
|
||||
<< QStringLiteral("https://") + host
|
||||
<< true
|
||||
<< false
|
||||
<< QByteArray();
|
||||
|
||||
if (host != QStringLiteral("api.twitter.com")) { // they don't offer an API over HTTP
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-no-https-url");
|
||||
QTest::newRow(tag)
|
||||
<< QStringLiteral("http://") + host
|
||||
<< true
|
||||
<< true
|
||||
<< QByteArray();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-enabled");
|
||||
QTest::newRow(tag)
|
||||
<< QStringLiteral("https://") + host
|
||||
<< true
|
||||
<< true
|
||||
<< (host == QStringLiteral("www.dropbox.com")
|
||||
? QByteArray(QSslConfiguration::NextProtocolHttp1_1)
|
||||
: QByteArray(QSslConfiguration::NextProtocolSpdy3_0));
|
||||
#endif // QT_NO_OPENSSL
|
||||
}
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::spdy()
|
||||
{
|
||||
#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
|
||||
m_manager.clearAccessCache();
|
||||
|
||||
QFETCH(QString, host);
|
||||
QUrl url(host);
|
||||
QNetworkRequest request(url);
|
||||
|
||||
QFETCH(bool, setAttribute);
|
||||
QFETCH(bool, enabled);
|
||||
if (setAttribute) {
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(enabled));
|
||||
}
|
||||
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
|
||||
QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged()));
|
||||
QSignalSpy readyReadSpy(reply, SIGNAL(readyRead()));
|
||||
QSignalSpy finishedSpy(reply, SIGNAL(finished()));
|
||||
QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QFETCH(QByteArray, expectedProtocol);
|
||||
|
||||
bool expectedSpdyUsed = (expectedProtocol == QSslConfiguration::NextProtocolSpdy3_0);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), expectedSpdyUsed);
|
||||
|
||||
QCOMPARE(metaDataChangedSpy.count(), 1);
|
||||
QCOMPARE(finishedSpy.count(), 1);
|
||||
QCOMPARE(finishedManagerSpy.count(), 1);
|
||||
|
||||
QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl();
|
||||
QByteArray content = reply->readAll();
|
||||
|
||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
QVERIFY(statusCode >= 200 && statusCode < 500);
|
||||
if (statusCode == 200 || statusCode >= 400) {
|
||||
QVERIFY(readyReadSpy.count() > 0);
|
||||
QVERIFY(!content.isEmpty());
|
||||
} else if (statusCode >= 300 && statusCode < 400) {
|
||||
QVERIFY(!redirectUrl.isEmpty());
|
||||
}
|
||||
|
||||
QSslConfiguration::NextProtocolNegotiationStatus expectedStatus =
|
||||
expectedProtocol.isNull() ? QSslConfiguration::NextProtocolNegotiationNone
|
||||
: QSslConfiguration::NextProtocolNegotiationNegotiated;
|
||||
QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(),
|
||||
expectedStatus);
|
||||
|
||||
QCOMPARE(reply->sslConfiguration().nextNegotiatedProtocol(), expectedProtocol);
|
||||
#else
|
||||
QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old");
|
||||
#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ...
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::spdyReplyFinished()
|
||||
{
|
||||
static int finishedCount = 0;
|
||||
|
|
@ -419,85 +296,6 @@ void tst_qnetworkreply::spdyReplyFinished()
|
|||
QTestEventLoop::instance().exitLoop();
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::spdyMultipleRequestsPerHost()
|
||||
{
|
||||
#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
|
||||
QList<QNetworkRequest> requests;
|
||||
requests
|
||||
<< QNetworkRequest(QUrl("https://www.facebook.com"))
|
||||
<< QNetworkRequest(QUrl("https://www.facebook.com/images/fb_icon_325x325.png"))
|
||||
|
||||
<< QNetworkRequest(QUrl("https://www.google.de"))
|
||||
<< QNetworkRequest(QUrl("https://www.google.de/preferences?hl=de"))
|
||||
<< QNetworkRequest(QUrl("https://www.google.de/intl/de/policies/?fg=1"))
|
||||
<< QNetworkRequest(QUrl("https://www.google.de/intl/de/about.html?fg=1"))
|
||||
<< QNetworkRequest(QUrl("https://www.google.de/services/?fg=1"))
|
||||
<< QNetworkRequest(QUrl("https://www.google.de/intl/de/ads/?fg=1"))
|
||||
|
||||
<< QNetworkRequest(QUrl("https://i1.ytimg.com/li/tnHdj3df7iM/default.jpg"))
|
||||
<< QNetworkRequest(QUrl("https://i1.ytimg.com/li/7Dr1BKwqctY/default.jpg"))
|
||||
<< QNetworkRequest(QUrl("https://i1.ytimg.com/li/hfZhJdhTqX8/default.jpg"))
|
||||
<< QNetworkRequest(QUrl("https://i1.ytimg.com/vi/14Nprh8163I/hqdefault.jpg"))
|
||||
;
|
||||
QList<QNetworkReply *> replies;
|
||||
QList<QSignalSpy *> metaDataChangedSpies;
|
||||
QList<QSignalSpy *> readyReadSpies;
|
||||
QList<QSignalSpy *> finishedSpies;
|
||||
|
||||
QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
foreach (QNetworkRequest request, requests) {
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
QObject::connect(reply, SIGNAL(finished()), this, SLOT(spdyReplyFinished()));
|
||||
replies << reply;
|
||||
QSignalSpy *metaDataChangedSpy = new QSignalSpy(reply, SIGNAL(metaDataChanged()));
|
||||
metaDataChangedSpies << metaDataChangedSpy;
|
||||
QSignalSpy *readyReadSpy = new QSignalSpy(reply, SIGNAL(readyRead()));
|
||||
readyReadSpies << readyReadSpy;
|
||||
QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished()));
|
||||
finishedSpies << finishedSpy;
|
||||
}
|
||||
|
||||
QCOMPARE(requests.count(), replies.count());
|
||||
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
QCOMPARE(finishedManagerSpy.count(), requests.count());
|
||||
|
||||
for (int a = 0; a < replies.count(); ++a) {
|
||||
|
||||
QCOMPARE(replies.at(a)->sslConfiguration().nextProtocolNegotiationStatus(),
|
||||
QSslConfiguration::NextProtocolNegotiationNegotiated);
|
||||
QCOMPARE(replies.at(a)->sslConfiguration().nextNegotiatedProtocol(),
|
||||
QByteArray(QSslConfiguration::NextProtocolSpdy3_0));
|
||||
|
||||
QCOMPARE(replies.at(a)->error(), QNetworkReply::NoError);
|
||||
QCOMPARE(replies.at(a)->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true);
|
||||
QCOMPARE(replies.at(a)->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true);
|
||||
QCOMPARE(replies.at(a)->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||
|
||||
QByteArray content = replies.at(a)->readAll();
|
||||
QVERIFY(content.count() > 0);
|
||||
|
||||
QCOMPARE(metaDataChangedSpies.at(a)->count(), 1);
|
||||
metaDataChangedSpies.at(a)->deleteLater();
|
||||
|
||||
QCOMPARE(finishedSpies.at(a)->count(), 1);
|
||||
finishedSpies.at(a)->deleteLater();
|
||||
|
||||
QVERIFY(readyReadSpies.at(a)->count() > 0);
|
||||
readyReadSpies.at(a)->deleteLater();
|
||||
|
||||
replies.at(a)->deleteLater();
|
||||
}
|
||||
#else
|
||||
QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old");
|
||||
#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ...
|
||||
}
|
||||
|
||||
void tst_qnetworkreply::proxyAuthentication_data()
|
||||
{
|
||||
QTest::addColumn<QUrl>("url");
|
||||
|
|
@ -586,7 +384,7 @@ void tst_qnetworkreply::npnWithEmptyList() // QTBUG-40714
|
|||
|
||||
QUrl url(QStringLiteral("https://www.ossifrage.net/"));
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(true));
|
||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true));
|
||||
QNetworkReply *reply = m_manager.get(request);
|
||||
QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue