diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-08-06 07:45:34 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-09-01 12:24:48 (GMT) |
commit | 44368b4174eedc9a2eebd9f67cf0e96f42b67188 (patch) | |
tree | c905b10adcf0d20ef466b4ac29f3cb7460d49636 | |
parent | a6cb69085975352f10dcf8e6c93c6470ac9c459e (diff) | |
download | Qt-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.cpp | 73 |
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); |