Skip to content

Commit 37135fd

Browse files
Peter Hartmannphartmann
Peter Hartmann
authored andcommitted
[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 <[email protected]>
1 parent ae3b86c commit 37135fd

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

src/network/access/qhttpnetworkconnectionchannel.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,25 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
601601
socket->setProperty("_q_user-agent", value);
602602
}
603603
#endif
604+
if (connection->networkConfiguration().isValid()) {
605+
QList<QHostAddress> hostAddresses = QNetworkConfigurationPrivate::hostIPAddresses(
606+
connection->networkConfiguration());
607+
foreach (const QHostAddress &hostAddress, hostAddresses) {
608+
switch (hostAddress.protocol()) {
609+
// we don't know the protocol (IPv4 vs. IPv6) here yet,
610+
// the bind() will have to wait until after the host lookup
611+
// (then we know whether we are connecting to IPv4 or IPv6).
612+
case QAbstractSocket::IPv4Protocol:
613+
socket->setProperty("_q_bindIPv4Address", hostAddress.toString());
614+
break;
615+
case QAbstractSocket::IPv6Protocol:
616+
socket->setProperty("_q_bindIPv6Address", hostAddress.toString());
617+
break;
618+
default:
619+
qWarning("bind address is neither IPv4 nor IPv6"); // should never happen
620+
}
621+
}
622+
}
604623
if (ssl) {
605624
#ifndef QT_NO_OPENSSL
606625
QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);

src/network/socket/qabstractsocket.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,8 +958,21 @@ void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo)
958958
bool QAbstractSocketPrivate::checkForBind() // ### how about UDP???
959959
{
960960
Q_Q(QAbstractSocket);
961+
QHostAddress bindAddress;
961962
if (!localAddress.isNull()) {
962-
return bind(q, QHostAddress(localAddress.toString()), localPort, localBindMode);
963+
bindAddress = localAddress;
964+
} else if (host.protocol() == QAbstractSocket::IPv4Protocol) {
965+
QString ipv4BindAddress = q->property("_q_bindIPv4Address").toString();
966+
if (!ipv4BindAddress.isEmpty())
967+
bindAddress = QHostAddress(q->property("_q_bindIPv4Address").toString());
968+
} else if (host.protocol() == QAbstractSocket::IPv6Protocol) {
969+
QString ipv6BindAddress = q->property("_q_bindIPv4Address").toString();
970+
if (!ipv6BindAddress.isEmpty())
971+
bindAddress = QHostAddress(q->property("_q_bindIPv6Address").toString());
972+
}
973+
974+
if (!bindAddress.isNull()) {
975+
return bind(q, QHostAddress(bindAddress.toString()), localPort, localBindMode);
963976
} else { // no bind() was called or scheduled via the properties
964977
return true;
965978
}

tests/manual/qnetworkreply/main.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <QtNetwork/qnetworkreply.h>
4747
#include <QtNetwork/qnetworkrequest.h>
4848
#include <QtNetwork/qnetworkaccessmanager.h>
49+
#include <QtNetwork/qnetworkconfigmanager.h>
4950
#include <QtNetwork/qsslconfiguration.h>
5051
#include "../../auto/network-settings.h"
5152

@@ -56,6 +57,10 @@
5657
#define BANDWIDTH_LIMIT_BYTES (1024*100)
5758
#define TIME_ESTIMATION_SECONDS (97)
5859

60+
#ifndef QT_NO_BEARERMANAGEMENT
61+
Q_DECLARE_METATYPE(QNetworkConfiguration)
62+
#endif
63+
5964
class tst_qnetworkreply : public QObject
6065
{
6166
Q_OBJECT
@@ -64,6 +69,10 @@ class tst_qnetworkreply : public QObject
6469
void limiting();
6570
void setSslConfiguration_data();
6671
void setSslConfiguration();
72+
#ifndef QT_NO_BEARERMANAGEMENT
73+
void setNetworkConfiguration_data();
74+
void setNetworkConfiguration();
75+
#endif
6776
};
6877

6978
QNetworkReply *reply;
@@ -167,6 +176,42 @@ void tst_qnetworkreply::setSslConfiguration()
167176
#endif
168177
}
169178

179+
#ifndef QT_NO_BEARERMANAGEMENT
180+
void tst_qnetworkreply::setNetworkConfiguration_data()
181+
{
182+
QTest::addColumn<QNetworkConfiguration>("networkConfiguration");
183+
184+
// add one row per active network configuration
185+
QNetworkConfigurationManager confManager;
186+
QList<QNetworkConfiguration> confs =
187+
confManager.allConfigurations(QNetworkConfiguration::Active);
188+
for (int a = 0; a < confs.count(); a++) {
189+
QString identifier = confs.at(a).identifier();
190+
QTest::newRow(identifier.toLatin1()) << confs.at(a);
191+
}
192+
}
193+
194+
void tst_qnetworkreply::setNetworkConfiguration()
195+
{
196+
QFETCH(QNetworkConfiguration, networkConfiguration);
197+
198+
QNetworkAccessManager manager;
199+
manager.setConfiguration(networkConfiguration);
200+
QNetworkReply *reply = manager.get(
201+
QNetworkRequest(QUrl("http://codereview.qt-project.org")));
202+
203+
connect(reply, SIGNAL(finished()),
204+
&QTestEventLoop::instance(), SLOT(exitLoop()));
205+
QTestEventLoop::instance().enterLoop(15);
206+
207+
QVERIFY(!QTestEventLoop::instance().timeout());
208+
QCOMPARE(reply->error(), QNetworkReply::NoError);
209+
QCOMPARE(reply->manager()->configuration(), networkConfiguration);
210+
qDebug("there are no checks currently whether traffic is flowing over"
211+
" the right interface. Use tcpdump / wireshark etc. to check.");
212+
}
213+
#endif
214+
170215
QTEST_MAIN(tst_qnetworkreply)
171216

172217
#include "main.moc"

0 commit comments

Comments
 (0)