diff options
Diffstat (limited to 'src/network/socket')
-rw-r--r-- | src/network/socket/qabstractsocket.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qabstractsocket_p.h | 1 | ||||
-rw-r--r-- | src/network/socket/qlocalserver_win.cpp | 2 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 26 | ||||
-rw-r--r-- | src/network/socket/qudpsocket.cpp | 10 |
5 files changed, 41 insertions, 2 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 98baa0c047..13e10e4102 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1713,6 +1713,8 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, } #endif + // Sync up with error string, which open() shall clear. + d->socketError = UnknownSocketError; if (openMode & QIODevice::Unbuffered) d->isBuffered = false; else if (!d_func()->isBuffered) @@ -1948,6 +1950,8 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState return false; } + // Sync up with error string, which open() shall clear. + d->socketError = UnknownSocketError; if (d->threadData->hasEventDispatcher()) d->socketEngine->setReceiver(d); diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 3d788319a8..066a35ff85 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -156,6 +156,7 @@ public: QAbstractSocket::SocketType socketType; QAbstractSocket::SocketState state; + // Must be kept in sync with QIODevicePrivate::errorString. QAbstractSocket::SocketError socketError; QAbstractSocket::NetworkLayerProtocol preferredNetworkLayerProtocol; diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index 8cb3449343..ced923ced1 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -225,7 +225,7 @@ bool QLocalServerPrivate::addListener() void QLocalServerPrivate::setError(const QString &function) { int windowsError = GetLastError(); - errorString = QString::fromLatin1("%1: %2").arg(function).arg(qt_error_string(windowsError)); + errorString = QString::fromLatin1("%1: %2").arg(function, qt_error_string(windowsError)); error = QAbstractSocket::UnknownSocketError; } diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index e8ab8de469..c303f01648 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1321,6 +1321,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.namelen); + uint oldIfIndex = 0; + bool mustSetIpv6MulticastIf = false; + if (msg.namelen == sizeof(aa.a6)) { // sending IPv6 if (header.hopLimit != -1) { @@ -1332,7 +1335,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr) + WSA_CMSG_SPACE(sizeof(int))); } - if (header.ifindex != 0 || !header.senderAddress.isNull()) { + if (!header.senderAddress.isNull()) { struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsgptr)); memset(data, 0, sizeof(*data)); msg.Control.len += WSA_CMSG_SPACE(sizeof(*data)); @@ -1345,6 +1348,21 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr) + WSA_CMSG_SPACE(sizeof(*data))); + } else if (header.ifindex != 0) { + // Unlike other operating systems, setting the interface index in the in6_pktinfo + // structure above and leaving the ipi6_addr set to :: will cause the packets to be + // sent with source address ::. So we have to use IPV6_MULTICAST_IF, which MSDN is + // quite clear that "This option does not change the default interface for receiving + // IPv6 multicast traffic." + QT_SOCKOPTLEN_T len = sizeof(oldIfIndex); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, + reinterpret_cast<char *>(&oldIfIndex), &len) == -1 + || ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, + reinterpret_cast<const char *>(&header.ifindex), sizeof(header.ifindex)) == -1) { + setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + return -1; + } + mustSetIpv6MulticastIf = true; } } else { // sending IPv4 @@ -1398,6 +1416,12 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l ret = qint64(bytesSent); } + if (mustSetIpv6MulticastIf) { + // undo what we did above + ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, + reinterpret_cast<char *>(&oldIfIndex), sizeof(oldIfIndex)); + } + #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), len, diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 79629a07f2..85c4f4cbfd 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -185,6 +185,10 @@ QUdpSocket::~QUdpSocket() This function returns \c true if successful; otherwise it returns \c false and sets the socket error accordingly. + \note Joining IPv6 multicast groups without an interface selection is not + supported in all operating systems. Consider using the overload where the + interface is specified. + \sa leaveMulticastGroup() */ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress) @@ -219,6 +223,9 @@ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, This function returns \c true if successful; otherwise it returns \c false and sets the socket error accordingly. + \note This function should be called with the same arguments as were passed + to joinMulticastGroup(). + \sa joinMulticastGroup() */ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress) @@ -233,6 +240,9 @@ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress) Leaves the multicast group specified by \a groupAddress on the interface \a iface. + \note This function should be called with the same arguments as were passed + to joinMulticastGroup(). + \sa joinMulticastGroup() */ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress, |