From 41d8edda671e42c916f45e6eb2716fd76982a121 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 22 Jul 2010 14:26:45 +0200 Subject: Add MulticastTtlOption and MulticastLoopbackOption to QAbstractSocket These options only make sense and work in QUdpSocket when using multicasting. Previously, the loopback was set when joining a multicast group, but the loopback flag is not a per-group flag, it's per socket, hence this change. The ability to set the multicast TTL is needed as well, so this is added as a socket option as well. Autotest updated to test both. --- src/network/socket/qabstractsocket.cpp | 15 +++++++++++++++ src/network/socket/qabstractsocket.h | 4 +++- src/network/socket/qabstractsocketengine_p.h | 3 ++- src/network/socket/qnativesocketengine_unix.cpp | 14 ++++++++++++-- src/network/socket/qnativesocketengine_win.cpp | 19 +++++++++++++++++-- src/network/socket/qudpsocket.cpp | 9 +++------ src/network/socket/qudpsocket.h | 12 ++---------- tests/auto/qudpsocket/tst_qudpsocket.cpp | 16 ++++++++++++++-- 8 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 3218662..8037d91 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1627,6 +1627,14 @@ void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, cons case KeepAliveOption: d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt()); break; + + case MulticastTtlOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastTtlOption, value.toInt()); + break; + + case MulticastLoopbackOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopbackOption, value.toInt()); + break; } } @@ -1656,6 +1664,13 @@ QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option) case KeepAliveOption: ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption); break; + + case MulticastTtlOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastTtlOption); + break; + case MulticastLoopbackOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastLoopbackOption); + break; } if (ret == -1) return QVariant(); diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 9e487d2..f610db3 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -118,7 +118,9 @@ public: }; enum SocketOption { LowDelayOption, // TCP_NODELAY - KeepAliveOption // SO_KEEPALIVE + KeepAliveOption, // SO_KEEPALIVE + MulticastTtlOption, // IP_MULTICAST_TTL + MulticastLoopbackOption // IP_MULTICAST_LOOPBACK }; QAbstractSocket(SocketType socketType, QObject *parent); diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index bfd9b05..616fdb2 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -96,7 +96,8 @@ public: ReceiveOutOfBandData, LowDelayOption, KeepAliveOption, - MulticastLoopback + MulticastTtlOption, + MulticastLoopbackOption }; virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 8416ed2..f9061f8 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -248,7 +248,12 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; - case QNativeSocketEngine::MulticastLoopback: + case QNativeSocketEngine::MulticastTtlOption: + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + break; + case QNativeSocketEngine::MulticastLoopbackOption: + level = IPPROTO_IP; n = IP_MULTICAST_LOOP; break; } @@ -334,7 +339,12 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; - case QNativeSocketEngine::MulticastLoopback: + case QNativeSocketEngine::MulticastTtlOption: + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + break; + case QNativeSocketEngine::MulticastLoopbackOption: + level = IPPROTO_IP; n = IP_MULTICAST_LOOP; break; } diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index d222fd1..d2479f3 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -401,7 +401,14 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; - case QNativeSocketEngine::MulticastLoopback: + case QNativeSocketEngine::MulticastTtlOption: + { + unsigned long val = 0; + if (WSAIoctl(socketDescriptor, SIO_MULTICAST_SCOPE, 0, 0, &val, sizeof(val), 0, 0 ,0) == 0) + return val; + return -1; + } + case QNativeSocketEngine::MulticastLoopbackOption: { unsigned long val = 0; if (WSAIoctl(socketDescriptor, SIO_MULTIPOINT_LOOPBACK, 0, 0, &val, sizeof(val), 0, 0, 0) == 0) @@ -468,7 +475,15 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; - case QNativeSocketEngine::MulticastLoopback: + case QNativeSocketEngine::MulticastTtlOption: + { + unsigned long val = v, outval; + if (WSAIoctl(socketDescriptor, SIO_MULTICAST_SCOPE, &val, sizeof(val), &outval, sizeof(outval), 0, 0, 0) == 0) + return true; + WS_ERROR_DEBUG(WSAGetLastError()); + return false; + } + case QNativeSocketEngine::MulticastLoopbackOption: { unsigned long val = v, outval; if (WSAIoctl(socketDescriptor, SIO_MULTIPOINT_LOOPBACK, &val, sizeof(val), &outval, sizeof(outval), 0, 0, 0) == 0) diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 29345ca..6eb1335 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -332,9 +332,9 @@ bool QUdpSocket::bind(quint16 port, BindMode mode) /*! \since 4.6 */ -bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, MulticastMode mode) +bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress) { - return joinMulticastGroup(groupAddress, QNetworkInterface(), mode); + return joinMulticastGroup(groupAddress, QNetworkInterface()); } /*! @@ -342,13 +342,10 @@ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, MulticastM \overload */ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface, - MulticastMode mode) + const QNetworkInterface &iface) { Q_D(QUdpSocket); QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false); - d->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopback, - (mode & MulticastLoopback) ? 1 : 0); return d->socketEngine->joinMulticastGroup(groupAddress, iface); } diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h index c8a9678..54f82c9 100644 --- a/src/network/socket/qudpsocket.h +++ b/src/network/socket/qudpsocket.h @@ -68,12 +68,6 @@ public: }; Q_DECLARE_FLAGS(BindMode, BindFlag) - enum MulticastFlag { - DefaultMulticastFlagForPlatform = 0x0, - MulticastLoopback = 0x1 - }; - Q_DECLARE_FLAGS(MulticastMode, MulticastFlag) - explicit QUdpSocket(QObject *parent = 0); virtual ~QUdpSocket(); @@ -83,11 +77,9 @@ public: bool bind(quint16 port, BindMode mode); // ### Qt 5: Merge the bind functions + bool joinMulticastGroup(const QHostAddress &groupAddress); bool joinMulticastGroup(const QHostAddress &groupAddress, - MulticastMode mode = DefaultMulticastFlagForPlatform); - bool joinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface, - MulticastMode mode = DefaultMulticastFlagForPlatform); + const QNetworkInterface &iface); bool leaveMulticastGroup(const QHostAddress &groupAddress); bool leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface); diff --git a/tests/auto/qudpsocket/tst_qudpsocket.cpp b/tests/auto/qudpsocket/tst_qudpsocket.cpp index 3c08cd7..852986d 100644 --- a/tests/auto/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/qudpsocket/tst_qudpsocket.cpp @@ -866,7 +866,15 @@ void tst_QUdpSocket::multicast() // bind first, then verify that we can join the multicast group QVERIFY2(receiver.bind(), qPrintable(receiver.errorString())); - QVERIFY2(receiver.joinMulticastGroup(groupAddress, QUdpSocket::MulticastLoopback), + receiver.setSocketOption(QUdpSocket::MulticastTtlOption, 2); + QCOMPARE(receiver.socketOption(QUdpSocket::MulticastTtlOption).toInt(), 2); + receiver.setSocketOption(QUdpSocket::MulticastTtlOption, 128); + QCOMPARE(receiver.socketOption(QUdpSocket::MulticastTtlOption).toInt(), 128); + receiver.setSocketOption(QUdpSocket::MulticastTtlOption, 0); + QCOMPARE(receiver.socketOption(QUdpSocket::MulticastTtlOption).toInt(), 0); + receiver.setSocketOption(QUdpSocket::MulticastLoopbackOption, 1); + QCOMPARE(receiver.socketOption(QUdpSocket::MulticastLoopbackOption).toInt(), 1); + QVERIFY2(receiver.joinMulticastGroup(groupAddress), qPrintable(receiver.errorString())); QList datagrams = QList() @@ -901,7 +909,11 @@ void tst_QUdpSocket::multicast() QVERIFY2(receiver.bind(), qPrintable(receiver.errorString())); - QVERIFY2(receiver.joinMulticastGroup(groupAddress, QUdpSocket::MulticastLoopback), + receiver.setSocketOption(QUdpSocket::MulticastTtlOption, 128); + QCOMPARE(receiver.socketOption(QUdpSocket::MulticastTtlOption).toInt(), 128); + receiver.setSocketOption(QUdpSocket::MulticastLoopbackOption, 0); + QCOMPARE(receiver.socketOption(QUdpSocket::MulticastLoopbackOption).toInt(), 0); + QVERIFY2(receiver.joinMulticastGroup(groupAddress), qPrintable(receiver.errorString())); receiver.close(); QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::leaveMulticastGroup() called on a QUdpSocket when not in QUdpSocket::BoundState"); -- cgit v0.12