summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorPeter Hartmann <phartmann@blackberry.com>2013-05-03 15:57:40 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-06-03 23:16:08 +0200
commit1c901913c0af79b2bbde1b9da71f5267cb4fc76a (patch)
treee83c7e1c10cc6262931f1d03b9deb06cf1585bae /src/network
parent15da0a5af20fe6771bcb94ef8d46edbd5c8fb64c (diff)
QNetworkAccessManager: add public methods to pre-TCP/pre-SSL-connect
If an app knows it needs to connect to a host beforehand, it can "warm up" the connection cache by making DNS lookup, TCP (and if needed SSL) handshake before the actual HTTP request is sent. When the HTTP request is made, it will be considerably faster when there is already a working connection. Here are some typical results from the benchmark: * Linux desktop with Ethernet: "http://www.google.com" full request: 279 ms, pre-connect request: 61 ms, difference: 218 ms "https://www.google.com" full request: 344 ms, pre-connect request: 60 ms, difference: 284 ms * mobile device (BlackBerry 10) with Wifi: "https://www.google.com" full request: 898 ms, pre-connect request: 159 ms, difference: 739 ms "http://www.google.com" full request: 707 ms, pre-connect request: 200 ms, difference: 507 ms Task-number: QTBUG-30771 Change-Id: I3566b7f08216ab93a39e2024ae7d1ceb7ae21891 Reviewed-by: Jonas Gastal <gastal@intel.com> Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp10
-rw-r--r--src/network/access/qhttpnetworkreply.cpp5
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp8
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp57
-rw-r--r--src/network/access/qnetworkaccessmanager.h9
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp4
6 files changed, 87 insertions, 6 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 4b8fe8aca7..53436b1769 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -205,6 +205,16 @@ bool QHttpNetworkConnectionChannel::sendRequest()
// _q_connected or _q_encrypted
return false;
}
+ QString scheme = request.url().scheme();
+ if (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https")) {
+ state = QHttpNetworkConnectionChannel::IdleState;
+ reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
+ allDone();
+ reply = 0; // so we can reuse this channel
+ return true; // we have a working connection and are done
+ }
+
written = 0; // excluding the header
bytesTotal = 0;
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index eb8a8869cc..1b9e1f5a53 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -290,6 +290,11 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
#endif
{
+ QString scheme = newUrl.scheme();
+ if (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https"))
+ // make sure we do not close the socket after preconnecting
+ connectionCloseEnabled = false;
}
QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate()
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index a2cee48b22..ee3911c72c 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -107,8 +107,14 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)
{
QString result;
QUrl copy = url;
- bool isEncrypted = copy.scheme().toLower() == QLatin1String("https");
+ QString scheme = copy.scheme().toLower();
+ bool isEncrypted = scheme == QLatin1String("https");
copy.setPort(copy.port(isEncrypted ? 443 : 80));
+ if (scheme == QLatin1String("preconnect-http")) {
+ copy.setScheme(QLatin1String("http"));
+ } else if (scheme == QLatin1String("preconnect-https")) {
+ copy.setScheme(QLatin1String("https"));
+ }
result = copy.toString(QUrl::RemoveUserInfo | QUrl::RemovePath |
QUrl::RemoveQuery | QUrl::RemoveFragment | QUrl::FullyEncoded);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 13fd167f80..91655ef485 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -96,9 +96,11 @@ bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString&
SecProtocolType protocolType = kSecProtocolTypeAny;
if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeFTP;
- } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0) {
+ } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0
+ || scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeHTTP;
- } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0) {
+ } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0
+ || scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) {
protocolType = kSecProtocolTypeHTTPS;
}
QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
@@ -968,6 +970,53 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
}
}
+#ifndef QT_NO_SSL
+/*!
+ \since 5.2
+
+ Initiates a connection to the host given by \a hostName at port \a port, using
+ \a sslConfiguration. This function is useful to complete the TCP and SSL handshake
+ to a host before the HTTPS request is made, resulting in a lower network latency.
+
+ \note This function has no possibility to report errors.
+
+ \sa connectToHost(), get(), post(), put(), deleteResource()
+*/
+void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quint16 port,
+ const QSslConfiguration &sslConfiguration)
+{
+ QUrl url;
+ url.setHost(hostName);
+ url.setPort(port);
+ url.setScheme(QLatin1String("preconnect-https"));
+ QNetworkRequest request(url);
+ if (sslConfiguration != QSslConfiguration::defaultConfiguration())
+ request.setSslConfiguration(sslConfiguration);
+ get(request);
+}
+#endif
+
+/*!
+ \since 5.2
+
+ Initiates a connection to the host given by \a hostName at port \a port.
+ This function is useful to complete the TCP handshake
+ to a host before the HTTP request is made, resulting in a lower network latency.
+
+ \note This function has no possibility to report errors.
+
+ \sa connectToHostEncrypted(), get(), post(), put(), deleteResource()
+*/
+void QNetworkAccessManager::connectToHost(const QString &hostName, quint16 port)
+{
+ QUrl url;
+ url.setHost(hostName);
+ url.setPort(port);
+ url.setScheme(QLatin1String("preconnect-http"));
+ QNetworkRequest request(url);
+ get(request);
+}
+
/*!
\internal
@@ -1112,9 +1161,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
#ifndef QT_NO_HTTP
// Since Qt 5 we use the new QNetworkReplyHttpImpl
- if (scheme == QLatin1String("http")
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("preconnect-http")
#ifndef QT_NO_SSL
- || scheme == QLatin1String("https")
+ || scheme == QLatin1String("https") || scheme == QLatin1String("preconnect-https")
#endif
) {
QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 46e46c49ab..67b9bbcb07 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -43,6 +43,9 @@
#define QNETWORKACCESSMANAGER_H
#include <QtCore/QObject>
+#ifndef QT_NO_SSL
+#include <QtNetwork/QSslConfiguration>
+#endif
QT_BEGIN_NAMESPACE
@@ -135,6 +138,12 @@ public:
NetworkAccessibility networkAccessible() const;
#endif
+#ifndef QT_NO_SSL
+ void connectToHostEncrypted(const QString &hostName, quint16 port = 443,
+ const QSslConfiguration &sslConfiguration = QSslConfiguration::defaultConfiguration());
+#endif
+ void connectToHost(const QString &hostName, quint16 port = 80);
+
Q_SIGNALS:
#ifndef QT_NO_NETWORKPROXY
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index c04421e5c7..443339f029 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -629,7 +629,9 @@ void QNetworkReplyHttpImplPrivate::postRequest()
QUrl url = request.url();
httpRequest.setUrl(url);
- bool ssl = url.scheme().toLower() == QLatin1String("https");
+ QString scheme = url.scheme().toLower();
+ bool ssl = (scheme == QLatin1String("https")
+ || scheme == QLatin1String("preconnect-https"));
q->setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl);
httpRequest.setSsl(ssl);