diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-08-05 10:48:44 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-09-01 12:24:46 (GMT) |
commit | 75a56ce44908eb14ef058d111129ef3d285c5364 (patch) | |
tree | d59c138a649140a93ff86b1987e98d1a2e8a322c /src/network/socket/qnativesocketengine_win.cpp | |
parent | 8082ee277b44a158ce87d646e0d2c1d11e7d8348 (diff) | |
download | Qt-75a56ce44908eb14ef058d111129ef3d285c5364.zip Qt-75a56ce44908eb14ef058d111129ef3d285c5364.tar.gz Qt-75a56ce44908eb14ef058d111129ef3d285c5364.tar.bz2 |
Add QUdpSocket::setMulticastInterface() and ::multicastInterface()
This API allows the programmer to set/query the outgoing interface for
multicast packets for the socket. Both functions need an initialized
socket to work.
Autotest updated to test setting each interface in the system as the
multicast interface for IPv4 and IPv6 UDP sockets.
Diffstat (limited to 'src/network/socket/qnativesocketengine_win.cpp')
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index a922b45..2ca1f41 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -853,6 +853,69 @@ bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &g iface); } +QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, &sizeofv) == -1) + return QNetworkInterface(); + return QNetworkInterface::interfaceFromIndex(v); + } +#endif + + struct in_addr v = { 0 }; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, &sizeofv) == -1) + return QNetworkInterface(); + if (v.s_addr != 0 && sizeofv >= sizeof(v)) { + QHostAddress ipv4(ntohl(v.s_addr)); + QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces(); + for (int i = 0; i < ifaces.count(); ++i) { + const QNetworkInterface &iface = ifaces.at(i); + if (!(iface.flags() & QNetworkInterface::CanMulticast)) + continue; + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int j = 0; j < entries.count(); ++j) { + const QNetworkAddressEntry &entry = entries.at(j); + if (entry.ip() == ipv4) + return iface; + } + } + } + return QNetworkInterface(); +} + +bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v = iface.isValid() ? iface.index() : 0; + return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, sizeof(v)) != -1); + } +#endif + + struct in_addr v; + if (iface.isValid()) { + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int i = 0; i < entries.count(); ++i) { + const QNetworkAddressEntry &entry = entries.at(i); + const QHostAddress &ip = entry.ip(); + if (ip.protocol() == QAbstractSocket::IPv4Protocol) { + v.s_addr = htonl(ip.toIPv4Address()); + int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)); + if (r != -1) + return true; + } + } + return false; + } + + v.s_addr = INADDR_ANY; + return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)) != -1); +} + qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { unsigned long nbytes = 0; |