summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/socket/qabstractsocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine.cpp8
-rw-r--r--src/network/socket/qnativesocketengine_p.h9
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp104
-rw-r--r--src/network/socket/qudpsocket.cpp8
-rw-r--r--src/network/socket/qudpsocket.h4
-rw-r--r--tests/auto/qudpsocket/tst_qudpsocket.cpp6
7 files changed, 125 insertions, 18 deletions
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index 0632891..bfd9b05 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -121,9 +121,9 @@ public:
#ifndef QT_NO_UDPSOCKET
virtual bool joinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface) = 0;
+ const QNetworkInterface &iface) = 0;
virtual bool leaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface) = 0;
+ const QNetworkInterface &iface) = 0;
virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
quint16 *port = 0) = 0;
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index ae2cad2..7cb3a1b 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -650,26 +650,26 @@ int QNativeSocketEngine::accept()
\since 4.8
*/
bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface)
+ const QNetworkInterface &iface)
{
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false);
Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
- return d->nativeJoinMulticastGroup(groupAddress, interface);
+ return d->nativeJoinMulticastGroup(groupAddress, iface);
}
/*!
\since 4.8
*/
bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface)
+ const QNetworkInterface &iface)
{
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false);
Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false);
Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false);
- return d->nativeLeaveMulticastGroup(groupAddress, interface);
+ return d->nativeLeaveMulticastGroup(groupAddress, iface);
}
/*!
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index e44aa2e..ce00747 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -101,6 +101,7 @@ union qt_sockaddr {
};
class QNativeSocketEnginePrivate;
+class QNetworkInterface;
class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine
{
@@ -124,9 +125,9 @@ public:
void close();
bool joinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface);
+ const QNetworkInterface &iface);
bool leaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface);
+ const QNetworkInterface &iface);
qint64 bytesAvailable() const;
@@ -243,9 +244,9 @@ public:
bool nativeListen(int backlog);
int nativeAccept();
bool nativeJoinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface);
+ const QNetworkInterface &iface);
bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface);
+ const QNetworkInterface &iface);
qint64 nativeBytesAvailable() const;
bool nativeHasPendingDatagrams() const;
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 477ef45..d222fd1 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <winsock2.h>
+#include <ws2tcpip.h>
#include "qnativesocketengine_p.h"
@@ -47,6 +48,7 @@
#include <qsocketnotifier.h>
#include <qdebug.h>
#include <qdatetime.h>
+#include <qnetworkinterface.h>
//#define QNATIVESOCKETENGINE_DEBUG
#if defined(QNATIVESOCKETENGINE_DEBUG)
@@ -399,6 +401,13 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
case QNativeSocketEngine::KeepAliveOption:
n = SO_KEEPALIVE;
break;
+ case QNativeSocketEngine::MulticastLoopback:
+ {
+ unsigned long val = 0;
+ if (WSAIoctl(socketDescriptor, SIO_MULTIPOINT_LOOPBACK, 0, 0, &val, sizeof(val), 0, 0, 0) == 0)
+ return val;
+ return -1;
+ }
}
int v = -1;
@@ -459,6 +468,14 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
case QNativeSocketEngine::KeepAliveOption:
n = SO_KEEPALIVE;
break;
+ case QNativeSocketEngine::MulticastLoopback:
+ {
+ unsigned long val = v, outval;
+ if (WSAIoctl(socketDescriptor, SIO_MULTIPOINT_LOOPBACK, &val, sizeof(val), &outval, sizeof(outval), 0, 0, 0) == 0)
+ return true;
+ WS_ERROR_DEBUG(WSAGetLastError());
+ return false;
+ }
}
if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
@@ -747,6 +764,93 @@ int QNativeSocketEnginePrivate::nativeAccept()
return acceptedDescriptor;
}
+static bool doMulticast(QNativeSocketEnginePrivate *d,
+ int how6,
+ int how4,
+ const QHostAddress &groupAddress,
+ const QNetworkInterface &iface)
+{
+ int sockOpt = 0;
+ char *sockArg;
+ int sockArgSize;
+
+ struct ip_mreq mreq4;
+#ifndef QT_NO_IPV6
+ struct ipv6_mreq mreq6;
+
+ if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
+ sockOpt = how6;
+ sockArg = reinterpret_cast<char *>(&mreq6);
+ sockArgSize = sizeof(mreq6);
+ memset(&mreq6, 0, sizeof(mreq6));
+ Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
+ memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
+ mreq6.ipv6mr_interface = iface.index();
+ } else
+#endif
+ if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
+ sockOpt = how4;
+ sockArg = reinterpret_cast<char *>(&mreq4);
+ sockArgSize = sizeof(mreq4);
+ memset(&mreq4, 0, sizeof(mreq4));
+ mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
+
+ if (iface.isValid()) {
+ QList<QNetworkAddressEntry> addressEntries = iface.addressEntries();
+ if (!addressEntries.isEmpty()) {
+ QHostAddress firstIP = addressEntries.first().ip();
+ mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address());
+ } else {
+ d->setError(QAbstractSocket::NetworkError,
+ QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
+ return false;
+ }
+ } else {
+ mreq4.imr_interface.s_addr = INADDR_ANY;
+ }
+ } else {
+ // unreachable
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString);
+ return false;
+ }
+
+ int res = setsockopt(d->socketDescriptor, IPPROTO_IP, sockOpt, sockArg, sockArgSize);
+ if (res == -1) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
+ return false;
+ }
+ return true;
+}
+
+bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface)
+{
+ return doMulticast(this,
+#ifndef QT_NO_IPV6
+ IPV6_JOIN_GROUP,
+#else
+ 0,
+#endif
+ IP_ADD_MEMBERSHIP,
+ groupAddress,
+ iface);
+}
+
+bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface)
+{
+ return doMulticast(this,
+#ifndef QT_NO_IPV6
+ IPV6_LEAVE_GROUP,
+#else
+ 0,
+#endif
+ IP_DROP_MEMBERSHIP,
+ groupAddress,
+ iface);
+}
qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
{
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index 84657b4..29345ca 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -342,14 +342,14 @@ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, MulticastM
\overload
*/
bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface,
+ const QNetworkInterface &iface,
MulticastMode mode)
{
Q_D(QUdpSocket);
QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false);
d->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopback,
(mode & MulticastLoopback) ? 1 : 0);
- return d->socketEngine->joinMulticastGroup(groupAddress, interface);
+ return d->socketEngine->joinMulticastGroup(groupAddress, iface);
}
/*!
@@ -365,10 +365,10 @@ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress)
\overload
*/
bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface)
+ const QNetworkInterface &iface)
{
QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
- return d_func()->socketEngine->leaveMulticastGroup(groupAddress, interface);
+ return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
}
/*!
diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h
index ff80712..c8a9678 100644
--- a/src/network/socket/qudpsocket.h
+++ b/src/network/socket/qudpsocket.h
@@ -86,11 +86,11 @@ public:
bool joinMulticastGroup(const QHostAddress &groupAddress,
MulticastMode mode = DefaultMulticastFlagForPlatform);
bool joinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface,
+ const QNetworkInterface &iface,
MulticastMode mode = DefaultMulticastFlagForPlatform);
bool leaveMulticastGroup(const QHostAddress &groupAddress);
bool leaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &interface);
+ const QNetworkInterface &iface);
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;
diff --git a/tests/auto/qudpsocket/tst_qudpsocket.cpp b/tests/auto/qudpsocket/tst_qudpsocket.cpp
index 39a7ab1..3c08cd7 100644
--- a/tests/auto/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/qudpsocket/tst_qudpsocket.cpp
@@ -876,8 +876,10 @@ void tst_QUdpSocket::multicast()
<< QByteArray("cdef");
QUdpSocket sender;
- foreach (const QByteArray &datagram, datagrams)
- sender.writeDatagram(datagram, receiver.localAddress(), receiver.localPort());
+ foreach (const QByteArray &datagram, datagrams) {
+ QCOMPARE(int(sender.writeDatagram(datagram, groupAddress, receiver.localPort())),
+ int(datagram.size()));
+ }
QVERIFY2(receiver.waitForReadyRead(),
qPrintable(receiver.errorString()));