summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hartmann <phartmann@rim.com>2013-02-25 10:27:26 +0100
committerPeter Hartmann <phartmann@blackberry.com>2013-05-07 16:42:43 +0200
commit37135fd71270f9a0ee741e615b7708c948dca903 (patch)
treea45960f5c710d543cf58749d3e1781f92c8254e7
parentae3b86c8a5076f371ef8d80551c5dbb8d5cd5e67 (diff)
[BB10-internal] QHttpNetworkConnectionChannel: set bind addresses on the socket
... and use it in QAbstractSocket. By the time we connect the socket we do not know yet whether we will need an IPv4 or IPv6 bind address, so we set both as properties on the socket and decide after host name lookup and right before connecting. Change-Id: I2be6ab4ab84e7e799158d7f42443337ad37b4e72 Signed-off-by: Peter Hartmann <phartmann@rim.com>
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp19
-rw-r--r--src/network/socket/qabstractsocket.cpp15
-rw-r--r--tests/manual/qnetworkreply/main.cpp45
3 files changed, 78 insertions, 1 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 1ff602d3d5..4faaf15eaa 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -601,6 +601,25 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
socket->setProperty("_q_user-agent", value);
}
#endif
+ if (connection->networkConfiguration().isValid()) {
+ QList<QHostAddress> hostAddresses = QNetworkConfigurationPrivate::hostIPAddresses(
+ connection->networkConfiguration());
+ foreach (const QHostAddress &hostAddress, hostAddresses) {
+ switch (hostAddress.protocol()) {
+ // we don't know the protocol (IPv4 vs. IPv6) here yet,
+ // the bind() will have to wait until after the host lookup
+ // (then we know whether we are connecting to IPv4 or IPv6).
+ case QAbstractSocket::IPv4Protocol:
+ socket->setProperty("_q_bindIPv4Address", hostAddress.toString());
+ break;
+ case QAbstractSocket::IPv6Protocol:
+ socket->setProperty("_q_bindIPv6Address", hostAddress.toString());
+ break;
+ default:
+ qWarning("bind address is neither IPv4 nor IPv6"); // should never happen
+ }
+ }
+ }
if (ssl) {
#ifndef QT_NO_OPENSSL
QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 5943452e9d..0bbeb82842 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -958,8 +958,21 @@ void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo)
bool QAbstractSocketPrivate::checkForBind() // ### how about UDP???
{
Q_Q(QAbstractSocket);
+ QHostAddress bindAddress;
if (!localAddress.isNull()) {
- return bind(q, QHostAddress(localAddress.toString()), localPort, localBindMode);
+ bindAddress = localAddress;
+ } else if (host.protocol() == QAbstractSocket::IPv4Protocol) {
+ QString ipv4BindAddress = q->property("_q_bindIPv4Address").toString();
+ if (!ipv4BindAddress.isEmpty())
+ bindAddress = QHostAddress(q->property("_q_bindIPv4Address").toString());
+ } else if (host.protocol() == QAbstractSocket::IPv6Protocol) {
+ QString ipv6BindAddress = q->property("_q_bindIPv4Address").toString();
+ if (!ipv6BindAddress.isEmpty())
+ bindAddress = QHostAddress(q->property("_q_bindIPv6Address").toString());
+ }
+
+ if (!bindAddress.isNull()) {
+ return bind(q, QHostAddress(bindAddress.toString()), localPort, localBindMode);
} else { // no bind() was called or scheduled via the properties
return true;
}
diff --git a/tests/manual/qnetworkreply/main.cpp b/tests/manual/qnetworkreply/main.cpp
index 9d395eea26..4c271d397c 100644
--- a/tests/manual/qnetworkreply/main.cpp
+++ b/tests/manual/qnetworkreply/main.cpp
@@ -46,6 +46,7 @@
#include <QtNetwork/qnetworkreply.h>
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
#include <QtNetwork/qsslconfiguration.h>
#include "../../auto/network-settings.h"
@@ -56,6 +57,10 @@
#define BANDWIDTH_LIMIT_BYTES (1024*100)
#define TIME_ESTIMATION_SECONDS (97)
+#ifndef QT_NO_BEARERMANAGEMENT
+Q_DECLARE_METATYPE(QNetworkConfiguration)
+#endif
+
class tst_qnetworkreply : public QObject
{
Q_OBJECT
@@ -64,6 +69,10 @@ class tst_qnetworkreply : public QObject
void limiting();
void setSslConfiguration_data();
void setSslConfiguration();
+#ifndef QT_NO_BEARERMANAGEMENT
+ void setNetworkConfiguration_data();
+ void setNetworkConfiguration();
+#endif
};
QNetworkReply *reply;
@@ -167,6 +176,42 @@ void tst_qnetworkreply::setSslConfiguration()
#endif
}
+#ifndef QT_NO_BEARERMANAGEMENT
+void tst_qnetworkreply::setNetworkConfiguration_data()
+{
+ QTest::addColumn<QNetworkConfiguration>("networkConfiguration");
+
+ // add one row per active network configuration
+ QNetworkConfigurationManager confManager;
+ QList<QNetworkConfiguration> confs =
+ confManager.allConfigurations(QNetworkConfiguration::Active);
+ for (int a = 0; a < confs.count(); a++) {
+ QString identifier = confs.at(a).identifier();
+ QTest::newRow(identifier.toLatin1()) << confs.at(a);
+ }
+}
+
+void tst_qnetworkreply::setNetworkConfiguration()
+{
+ QFETCH(QNetworkConfiguration, networkConfiguration);
+
+ QNetworkAccessManager manager;
+ manager.setConfiguration(networkConfiguration);
+ QNetworkReply *reply = manager.get(
+ QNetworkRequest(QUrl("http://codereview.qt-project.org")));
+
+ connect(reply, SIGNAL(finished()),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(15);
+
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QCOMPARE(reply->manager()->configuration(), networkConfiguration);
+ qDebug("there are no checks currently whether traffic is flowing over"
+ " the right interface. Use tcpdump / wireshark etc. to check.");
+}
+#endif
+
QTEST_MAIN(tst_qnetworkreply)
#include "main.moc"