summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qsymbiansocketengine.cpp
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-03-31 11:19:45 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-04-05 10:23:48 (GMT)
commit1d8f8bc70e4f056e4e110a779d483c186fc2ad19 (patch)
tree365b7e02d0a76af431760748e604ae658af67549 /src/network/socket/qsymbiansocketengine.cpp
parentcd907ff4656c8819f5aa19979ea6da25fc5947e6 (diff)
downloadQt-1d8f8bc70e4f056e4e110a779d483c186fc2ad19.zip
Qt-1d8f8bc70e4f056e4e110a779d483c186fc2ad19.tar.gz
Qt-1d8f8bc70e4f056e4e110a779d483c186fc2ad19.tar.bz2
Update address reporting code
When an IP6 address contains a valid IP4 address, report the address in IP4 format (this is needed for SOCKS5 socket engine) When binding Any or AnyIPv6, create a dual mode socket (KAfUnspec), but report the local address as being the same as what the user requested. (by default, symbian returns ::0 for the dual mode socket, which causes problems for SOCKS and UDP code) The intent is that most applications written for IP4 can work transparently in an IP6 environment. QTcpServer or QUdpSocket can accept either IP4 or IP6 from the same socket. Reviewed-by: Markus Goetz
Diffstat (limited to 'src/network/socket/qsymbiansocketengine.cpp')
-rw-r--r--src/network/socket/qsymbiansocketengine.cpp39
1 files changed, 17 insertions, 22 deletions
diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp
index 52f6b68..165316d 100644
--- a/src/network/socket/qsymbiansocketengine.cpp
+++ b/src/network/socket/qsymbiansocketengine.cpp
@@ -147,7 +147,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr)
{
- if (a.Family() == KAfInet6) {
+ if (a.Family() == KAfInet6 && !a.IsV4Compat() && !a.IsV4Mapped()) {
Q_IPV6ADDR tmp;
memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp));
if (addr) {
@@ -226,12 +226,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so
void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr)
{
nativeAddr.SetPort(port);
- if (addr == QHostAddress::Any) {
- //Should allow both IPv4 and IPv6
- //Listening on "0.0.0.0" accepts ONLY ipv4 connections
- //Listening on "::" accepts ONLY ipv6 connections
- nativeAddr.SetFamily(KAFUnspec);
- } else if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
+ if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
TPckgBuf<TSoInetIfQuery> query;
query().iName = qt_QString2TPtrC(addr.scopeId());
TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query);
@@ -274,7 +269,6 @@ QSymbianSocketEngine::QSymbianSocketEngine(QObject *parent)
QSymbianSocketEngine::~QSymbianSocketEngine()
{
close();
- // FIXME what else do we need to free?
}
/*!
@@ -650,7 +644,15 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port)
Q_CHECK_STATE(QSymbianSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
TInetAddr nativeAddr;
- d->setPortAndAddress(nativeAddr, port, address);
+ if (address == QHostAddress::Any || address == QHostAddress::AnyIPv6) {
+ //Should allow both IPv4 and IPv6
+ //Listening on "0.0.0.0" accepts ONLY ipv4 connections
+ //Listening on "::" accepts ONLY ipv6 connections
+ nativeAddr.SetFamily(KAFUnspec);
+ nativeAddr.SetPort(port);
+ } else {
+ d->setPortAndAddress(nativeAddr, port, address);
+ }
TInt err = d->nativeSocket.Bind(nativeAddr);
#ifdef __WINS__
@@ -684,6 +686,11 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port)
d->socketState = QAbstractSocket::BoundState;
d->fetchConnectionParameters();
+
+ // When we bind to unspecified address (to get a dual mode socket), report back the
+ // same type of address that was requested. This is required for SOCKS proxy to work.
+ if (nativeAddr.Family() == KAFUnspec)
+ d->localAddress = address;
return true;
}
@@ -693,8 +700,6 @@ bool QSymbianSocketEngine::listen()
Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::listen(), false);
Q_CHECK_STATE(QSymbianSocketEngine::listen(), QAbstractSocket::BoundState, false);
Q_CHECK_TYPE(QSymbianSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
- // TODO the value 50 is from the QNativeSocketEngine. Maybe it's a bit too much
- // for a mobile platform
TInt err = d->nativeSocket.Listen(50);
if (err) {
d->setError(err);
@@ -898,17 +903,7 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters()
getPortAndAddress(addr, &localPort, &localAddress);
// Determine protocol family
- switch (addr.Family()) {
- case KAfInet:
- socketProtocol = QAbstractSocket::IPv4Protocol;
- break;
- case KAfInet6:
- socketProtocol = QAbstractSocket::IPv6Protocol;
- break;
- default:
- socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
- break;
- }
+ socketProtocol = localAddress.protocol();
// Determine the remote address
nativeSocket.RemoteName(addr);