summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2010-08-06 07:45:34 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2010-09-01 12:24:48 (GMT)
commit44368b4174eedc9a2eebd9f67cf0e96f42b67188 (patch)
treec905b10adcf0d20ef466b4ac29f3cb7460d49636
parenta6cb69085975352f10dcf8e6c93c6470ac9c459e (diff)
downloadQt-44368b4174eedc9a2eebd9f67cf0e96f42b67188.zip
Qt-44368b4174eedc9a2eebd9f67cf0e96f42b67188.tar.gz
Qt-44368b4174eedc9a2eebd9f67cf0e96f42b67188.tar.bz2
Fix IPv6 support on Windows
We need to make sure that we use the right setsockopt level and option for the multicast TTL and loopback options. Like on UNIX, we need to use IPPROTO_IPV6 level when joining and leaving a group. Also, we cannot bind to a multicast address on Windows (but it is possible on UNIX). work around this by binding to the Any/AnyIPv6 addresses if a multicast address is passed to bind.
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp73
1 files changed, 62 insertions, 11 deletions
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 2ca1f41..f952cee 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -402,12 +402,28 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
n = SO_KEEPALIVE;
break;
case QNativeSocketEngine::MulticastTtlOption:
- level = IPPROTO_IP;
- n = IP_MULTICAST_TTL;
+#ifndef QT_NO_IPV6
+ if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_MULTICAST_HOPS;
+ } else
+#endif
+ {
+ level = IPPROTO_IP;
+ n = IP_MULTICAST_TTL;
+ }
break;
case QNativeSocketEngine::MulticastLoopbackOption:
- level = IPPROTO_IP;
- n = IP_MULTICAST_LOOP;
+#ifndef QT_NO_IPV6
+ if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_MULTICAST_LOOP;
+ } else
+#endif
+ {
+ level = IPPROTO_IP;
+ n = IP_MULTICAST_LOOP;
+ }
break;
}
@@ -470,12 +486,28 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
n = SO_KEEPALIVE;
break;
case QNativeSocketEngine::MulticastTtlOption:
- level = IPPROTO_IP;
- n = IP_MULTICAST_TTL;
+#ifndef QT_NO_IPV6
+ if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_MULTICAST_HOPS;
+ } else
+#endif
+ {
+ level = IPPROTO_IP;
+ n = IP_MULTICAST_TTL;
+ }
break;
case QNativeSocketEngine::MulticastLoopbackOption:
- level = IPPROTO_IP;
- n = IP_MULTICAST_LOOP;
+#ifndef QT_NO_IPV6
+ if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_MULTICAST_LOOP;
+ } else
+#endif
+ {
+ level = IPPROTO_IP;
+ n = IP_MULTICAST_LOOP;
+ }
break;
}
@@ -666,8 +698,24 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
}
-bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
+bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
{
+ QHostAddress address = a;
+ switch (address.protocol()) {
+ case QAbstractSocket::IPv6Protocol:
+ if (address.toIPv6Address()[0] == 0xff) {
+ // binding to a multicast address
+ address = QHostAddress(QHostAddress::AnyIPv6);
+ }
+ break;
+ case QAbstractSocket::IPv4Protocol:
+ if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) {
+ // binding to a multicast address
+ address = QHostAddress(QHostAddress::Any);
+ }
+ break;
+ }
+
struct sockaddr_in sockAddrIPv4;
qt_sockaddr_in6 sockAddrIPv6;
struct sockaddr *sockAddrPtr = 0;
@@ -771,6 +819,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
const QHostAddress &groupAddress,
const QNetworkInterface &iface)
{
+ int level = 0;
int sockOpt = 0;
char *sockArg;
int sockArgSize;
@@ -780,7 +829,8 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
struct ipv6_mreq mreq6;
if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
- sockOpt = how6;
+ level = IPPROTO_IPV6;
+ sockOpt = how6;
sockArg = reinterpret_cast<char *>(&mreq6);
sockArgSize = sizeof(mreq6);
memset(&mreq6, 0, sizeof(mreq6));
@@ -790,6 +840,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
} else
#endif
if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
+ level = IPPROTO_IP;
sockOpt = how4;
sockArg = reinterpret_cast<char *>(&mreq4);
sockArgSize = sizeof(mreq4);
@@ -816,7 +867,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
return false;
}
- int res = setsockopt(d->socketDescriptor, IPPROTO_IP, sockOpt, sockArg, sockArgSize);
+ int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
if (res == -1) {
d->setError(QAbstractSocket::UnsupportedSocketOperationError,
QNativeSocketEnginePrivate::OperationUnsupportedErrorString);