QNativeSocketEngine Unix: do the same as for Windows
authorThiago Macieira <thiago.macieira@intel.com>
Thu, 12 Mar 2015 01:58:29 +0000 (18:58 -0700)
committerThiago Macieira <thiago.macieira@intel.com>
Sat, 22 Aug 2015 22:26:47 +0000 (22:26 +0000)
Change-Id: Iee8cbc07c4434ce9b560ffff13ca9d9858cf7111
Reviewed-by: Richard J. Moore <rich@kde.org>
src/network/socket/qnativesocketengine_p.h
src/network/socket/qnativesocketengine_unix.cpp
src/network/socket/qnativesocketengine_win.cpp

index c7e545df92309d41ac157143b2cd939677c2bc6e..966f44f774e1ca9099b9b84726320805e9f607ff 100644 (file)
@@ -284,14 +284,40 @@ public:
     int nativeSelect(int timeout, bool selectForRead) const;
     int nativeSelect(int timeout, bool checkRead, bool checkWrite,
                      bool *selectForRead, bool *selectForWrite) const;
-#ifdef Q_OS_WIN
-    void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize);
-#endif
 
     void nativeClose();
 
     bool checkProxy(const QHostAddress &address);
     bool fetchConnectionParameters();
+
+    static uint scopeIdFromString(const QString &scopeid);
+
+    /*! \internal
+        Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize.
+        The address \a is converted to IPv6 if the current socket protocol is also IPv6.
+     */
+    void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize)
+    {
+        if (address.protocol() == QAbstractSocket::IPv6Protocol
+            || address.protocol() == QAbstractSocket::AnyIPProtocol
+            || socketProtocol == QAbstractSocket::IPv6Protocol
+            || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+            memset(&aa->a6, 0, sizeof(qt_sockaddr_in6));
+            aa->a6.sin6_family = AF_INET6;
+            aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId());
+            aa->a6.sin6_port = htons(port);
+            Q_IPV6ADDR tmp = address.toIPv6Address();
+            memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp));
+            *sockAddrSize = sizeof(qt_sockaddr_in6);
+        } else {
+            memset(&aa->a, 0, sizeof(sockaddr_in));
+            aa->a4.sin_family = AF_INET;
+            aa->a4.sin_port = htons(port);
+            aa->a4.sin_addr.s_addr = htonl(address.toIPv4Address());
+            *sockAddrSize = sizeof(sockaddr_in);
+        }
+    }
+
 };
 
 QT_END_NAMESPACE
index f2fac66cd6a352d7f9171c93b156e40ddfbe8ca5..0e14c175c598a4c30a2ae9dcdf83a602876157a8 100644 (file)
@@ -131,9 +131,9 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po
     }
 }
 
-static inline uint makeScopeId(const QHostAddress &addr)
+// inline on purpose
+inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
 {
-    QString scopeid = addr.scopeId();
     if (scopeid.isEmpty())
         return 0;
 
@@ -389,37 +389,11 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
     qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
 #endif
 
-    struct sockaddr_in sockAddrIPv4;
-    struct sockaddr *sockAddrPtr = 0;
-    QT_SOCKLEN_T sockAddrSize = 0;
-
-    struct sockaddr_in6 sockAddrIPv6;
-
-    if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
-        memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
-        sockAddrIPv6.sin6_family = AF_INET6;
-        sockAddrIPv6.sin6_port = htons(port);
-        sockAddrIPv6.sin6_scope_id = makeScopeId(addr);
-
-        Q_IPV6ADDR ip6 = addr.toIPv6Address();
-        memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
-
-        sockAddrSize = sizeof(sockAddrIPv6);
-        sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
-    } else
-    if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
-        memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
-        sockAddrIPv4.sin_family = AF_INET;
-        sockAddrIPv4.sin_port = htons(port);
-        sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address());
-
-        sockAddrSize = sizeof(sockAddrIPv4);
-        sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
-    } else {
-        // unreachable
-    }
+    qt_sockaddr aa;
+    QT_SOCKLEN_T sockAddrSize;
+    setPortAndAddress(port, addr, &aa, &sockAddrSize);
 
-    int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
+    int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
 #if defined (QNATIVESOCKETENGINE_DEBUG)
     int ecopy = errno;
 #endif
@@ -491,51 +465,28 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
 
 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
 {
-    struct sockaddr_in sockAddrIPv4;
-    struct sockaddr *sockAddrPtr = 0;
-    QT_SOCKLEN_T sockAddrSize = 0;
-
-
-    struct sockaddr_in6 sockAddrIPv6;
+    qt_sockaddr aa;
+    QT_SOCKLEN_T sockAddrSize;
+    setPortAndAddress(port, address, &aa, &sockAddrSize);
 
-    if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) {
 #ifdef IPV6_V6ONLY
+    if (aa.a.sa_family == AF_INET6) {
         int ipv6only = 0;
         if (address.protocol() == QAbstractSocket::IPv6Protocol)
             ipv6only = 1;
         //default value of this socket option varies depending on unix variant (or system configuration on BSD), so always set it explicitly
         ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
+    }
 #endif
-        memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
-        sockAddrIPv6.sin6_family = AF_INET6;
-        sockAddrIPv6.sin6_port = htons(port);
-        sockAddrIPv6.sin6_scope_id = makeScopeId(address);
-
-        Q_IPV6ADDR tmp = address.toIPv6Address();
-        memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
-        sockAddrSize = sizeof(sockAddrIPv6);
-        sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
-    } else
-        if (address.protocol() == QAbstractSocket::IPv4Protocol) {
-            memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
-            sockAddrIPv4.sin_family = AF_INET;
-            sockAddrIPv4.sin_port = htons(port);
-            sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
-            sockAddrSize = sizeof(sockAddrIPv4);
-            sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
-        } else {
-            // unreachable
-        }
 
-    int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
+    int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
     if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
-        memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
-        sockAddrIPv4.sin_family = AF_INET;
-        sockAddrIPv4.sin_port = htons(port);
-        sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
-        sockAddrSize = sizeof(sockAddrIPv4);
-        sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
-        bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
+        // retry with v4
+        aa.a4.sin_family = AF_INET;
+        aa.a4.sin_port = htons(port);
+        aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
+        sockAddrSize = sizeof(aa.a4);
+        bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
     }
 
     if (bindResult < 0) {
@@ -992,17 +943,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
     msg.msg_name = &aa.a;
     msg.msg_control = &cbuf;
 
-    if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol
-        || socketProtocol == QAbstractSocket::IPv6Protocol
-        || socketProtocol == QAbstractSocket::AnyIPProtocol) {
-        aa.a6.sin6_family = AF_INET6;
-        aa.a6.sin6_port = htons(header.destinationPort);
-        aa.a6.sin6_scope_id = makeScopeId(header.destinationAddress);
-
-        Q_IPV6ADDR tmp = header.destinationAddress.toIPv6Address();
-        memcpy(&aa.a6.sin6_addr, &tmp, sizeof(tmp));
-        msg.msg_namelen = sizeof(aa.a6);
+    setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.msg_namelen);
 
+    if (msg.msg_namelen == sizeof(aa.a6)) {
         if (header.hopLimit != -1) {
             msg.msg_controllen += CMSG_SPACE(sizeof(int));
             cmsgptr->cmsg_len = CMSG_LEN(sizeof(int));
@@ -1020,16 +963,11 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
             cmsgptr->cmsg_type = IPV6_PKTINFO;
             data->ipi6_ifindex = header.ifindex;
 
-            tmp = header.senderAddress.toIPv6Address();
+            QIPv6Address tmp = header.senderAddress.toIPv6Address();
             memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
             cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
         }
-    } else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) {
-        aa.a4.sin_family = AF_INET;
-        aa.a4.sin_port = htons(header.destinationPort);
-        aa.a4.sin_addr.s_addr = htonl(header.destinationAddress.toIPv4Address());
-        msg.msg_namelen = sizeof(aa.a4);
-
+    } else {
         if (header.hopLimit != -1) {
             msg.msg_controllen += CMSG_SPACE(sizeof(int));
             cmsgptr->cmsg_len = CMSG_LEN(sizeof(int));
@@ -1058,10 +996,6 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
             cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
         }
 #endif
-    } else {
-        // Don't know what IP type this is, let's hope it sends
-        msg.msg_name = 0;
-        msg.msg_namelen = 0;
     }
 
     if (msg.msg_controllen == 0)
index aecae40a441b1a078ad6de17e6dfa9a16d65119f..5e198098df22a16daae395bc83c83c022330d817 100644 (file)
@@ -276,32 +276,6 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
     }
 }
 
-/*! \internal
-
-    Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
-*/
-void QNativeSocketEnginePrivate::setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize)
-{
-    if (address.protocol() == QAbstractSocket::IPv6Protocol
-        || address.protocol() == QAbstractSocket::AnyIPProtocol
-        || socketProtocol == QAbstractSocket::IPv6Protocol
-        || socketProtocol == QAbstractSocket::AnyIPProtocol) {
-        memset(&aa->a6, 0, sizeof(qt_sockaddr_in6));
-        aa->a6.sin6_family = AF_INET6;
-        aa->a6.sin6_scope_id = address.scopeId().toUInt();
-        WSAHtons(socketDescriptor, port, &aa->a6.sin6_port);
-        Q_IPV6ADDR tmp = address.toIPv6Address();
-        memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp));
-        *sockAddrSize = sizeof(qt_sockaddr_in6);
-    } else {
-        memset(&aa->a, 0, sizeof(sockaddr_in));
-        aa->a4.sin_family = AF_INET;
-        WSAHtons(socketDescriptor, port, &aa->a4.sin_port);
-        WSAHtonl(socketDescriptor, address.toIPv4Address(), &aa->a4.sin_addr.s_addr);
-        *sockAddrSize = sizeof(sockaddr_in);
-    }
-}
-
 /*! \internal
 
 */
@@ -348,6 +322,12 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
 #  define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
 #endif
 
+// inline on purpose
+inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
+{
+    return scopeid.toUInt();
+}
+
 bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
 {