summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hartmann <peter.hartmann@nokia.com>2009-12-15 09:52:52 (GMT)
committerPeter Hartmann <peter.hartmann@nokia.com>2010-01-11 09:48:05 (GMT)
commit145fecc833926c307819752912e6833169799a53 (patch)
treee527d59a10244b7b6c71b8e63c5019a7dd34c2e4
parentef5a985cf47c32bac0ddd3bae1edb7e922e7ec69 (diff)
downloadQt-145fecc833926c307819752912e6833169799a53.zip
Qt-145fecc833926c307819752912e6833169799a53.tar.gz
Qt-145fecc833926c307819752912e6833169799a53.tar.bz2
network internals: start HTTP GET requests right away when called
on the code path from QNetworkAccessManager::get() to QTcpSocket::write() there were two calls involved that were invoked via a QueuedConnection, which would in some occasions delay writing the data to the socket. This patch makes sure the data is written to the socket immediately, without returning to the event loop (only the HTTP backend was changed for that event, the other backends were not changed) Reviewed-by: Thiago Macieira Reviewed-by: Markus Goetz
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp8
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp12
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h2
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp7
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h2
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp4
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp13
7 files changed, 30 insertions, 18 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 44a0a79..2c56524 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -415,14 +415,13 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
lowPriorityQueue.prepend(pair);
break;
}
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
+ // this used to be called via invokeMethod and a QueuedConnection
+ _q_startNextRequest();
return reply;
}
void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair)
{
- Q_Q(QHttpNetworkConnection);
-
QHttpNetworkRequest request = pair.first;
switch (request.priority()) {
case QHttpNetworkRequest::HighPriority:
@@ -433,7 +432,8 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair)
lowPriorityQueue.prepend(pair);
break;
}
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
+ // this used to be called via invokeMethod and a QueuedConnection
+ _q_startNextRequest();
}
void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socket)
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 1a68e97..7cf632f 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -166,6 +166,8 @@ bool QHttpNetworkConnectionChannel::sendRequest()
QByteArray header = QHttpNetworkRequestPrivate::header(request, false);
#endif
socket->write(header);
+ // flushing is dangerous (QSslSocket calls transmit which might read or error)
+// socket->flush();
QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
if (uploadByteDevice) {
// connect the signals so this function gets called again
@@ -258,7 +260,7 @@ bool QHttpNetworkConnectionChannel::sendRequest()
// ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called
// this is needed if the sends an reply before we have finished sending the request. In that
// case receiveReply had been called before but ignored the server reply
- receiveReply();
+ QMetaObject::invokeMethod(connection, "_q_receiveReply", Qt::QueuedConnection);
break;
}
case QHttpNetworkConnectionChannel::ReadingState:
@@ -272,7 +274,7 @@ bool QHttpNetworkConnectionChannel::sendRequest()
}
-void QHttpNetworkConnectionChannel::receiveReply()
+void QHttpNetworkConnectionChannel::_q_receiveReply()
{
Q_ASSERT(socket);
@@ -567,7 +569,7 @@ void QHttpNetworkConnectionChannel::allDone()
connection->d_func()->fillPipeline(socket);
// continue reading
- receiveReply();
+ _q_receiveReply();
}
} else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) {
eatWhitespace();
@@ -739,7 +741,7 @@ void QHttpNetworkConnectionChannel::_q_readyRead()
if (isSocketWaiting() || isSocketReading()) {
state = QHttpNetworkConnectionChannel::ReadingState;
if (reply)
- receiveReply();
+ _q_receiveReply();
}
}
@@ -758,7 +760,7 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
if (isSocketWaiting() || isSocketReading()) {
state = QHttpNetworkConnectionChannel::ReadingState;
if (reply)
- receiveReply();
+ _q_receiveReply();
} else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) {
// re-sending request because the socket was in ClosingState
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index bbe43cd..c30c236 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -144,7 +144,6 @@ public:
void close();
bool sendRequest();
- void receiveReply();
bool ensureConnection();
@@ -166,6 +165,7 @@ public:
bool isSocketReading() const;
protected slots:
+ void _q_receiveReply();
void _q_bytesWritten(qint64 bytes); // proceed sending
void _q_readyRead(); // pending data to read
void _q_disconnected(); // disconnected from host
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 5a2cce4..ada00df 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -594,9 +594,10 @@ void QNetworkAccessHttpBackend::open()
if (transparentProxy.type() == QNetworkProxy::DefaultProxy &&
cacheProxy.type() == QNetworkProxy::DefaultProxy) {
// unsuitable proxies
- error(QNetworkReply::ProxyNotFoundError,
- tr("No suitable proxy found"));
- finished();
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError),
+ Q_ARG(QString, QCoreApplication::translate("QNetworkAccessHttpBackend", "No suitable proxy found")));
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
return;
}
#endif
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index bc3980d..705323d 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -104,6 +104,7 @@ private slots:
void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
void httpError(QNetworkReply::NetworkError error, const QString &errorString);
bool sendCacheContents(const QNetworkCacheMetaData &metaData);
+ void finished(); // override
private:
QHttpNetworkReply *httpReply;
@@ -118,7 +119,6 @@ private:
#endif
void disconnectFromHttp();
- void finished(); // override
void setupConnection();
void validateCache(QHttpNetworkRequest &httpRequest, bool &loadedFromCache);
void invalidateCache();
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 2f57fee..d27fbe7 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -723,8 +723,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
// third step: find a backend
priv->backend = d->findBackend(op, request);
- // fourth step: setup the reply
- priv->setup(op, request, outgoingData);
#ifndef QT_NO_NETWORKPROXY
QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
priv->proxyList = proxyList;
@@ -733,6 +731,8 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
priv->backend->setParent(reply);
priv->backend->reply = priv;
}
+ // fourth step: setup the reply
+ priv->setup(op, request, outgoingData);
#ifndef QT_NO_OPENSSL
reply->setSslConfiguration(request.sslConfiguration());
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 42e802f..285864d 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -72,6 +72,9 @@ void QNetworkReplyImplPrivate::_q_startOperation()
}
state = Working;
+ // note: if that method is called directly, it cannot happen that the backend is 0,
+ // because we just checked via a qobject_cast that we got a http backend (see
+ // QNetworkReplyImplPrivate::setup())
if (!backend) {
error(QNetworkReplyImpl::ProtocolUnknownError,
QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!;
@@ -203,7 +206,6 @@ void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
}
}
-
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
QIODevice *data)
{
@@ -246,7 +248,14 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
// No outgoing data (e.g. HTTP GET request)
// or no backend
// if no backend, _q_startOperation will handle the error of this
- QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+
+ // for HTTP, we want to send out the request as fast as possible to the network, without
+ // invoking methods in a QueuedConnection
+ if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) {
+ _q_startOperation();
+ } else {
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ }
}
q->QIODevice::open(QIODevice::ReadOnly);