diff options
Diffstat (limited to 'src/network/socket')
-rw-r--r-- | src/network/socket/qabstractsocket.h | 1 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_p.h | 9 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 14 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 39 | ||||
-rw-r--r-- | src/network/socket/qsocks5socketengine.cpp | 10 |
5 files changed, 56 insertions, 17 deletions
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 1959fabdfc..2717ceb58a 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -74,6 +74,7 @@ public: enum NetworkLayerProtocol { IPv4Protocol, IPv6Protocol, + AnyIPProtocol, UnknownNetworkLayerProtocol = -1 }; enum SocketError { diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index c5c4b325d0..a024cd42d1 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -74,6 +74,11 @@ struct qt_sockaddr_storage { char __ss_pad2[QT_SS_PAD2SIZE]; }; +#ifdef Q_OS_WIN +#define QT_SOCKLEN_T int +#define QT_SOCKOPTLEN_T int +#endif + // sockaddr_in6 size changed between old and new SDK // Only the new version is the correct one, so always // use this structure. @@ -265,6 +270,10 @@ 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(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6, + quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize); +#endif void nativeClose(); diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 39570c8c04..26053981ce 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -163,7 +163,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc QAbstractSocket::NetworkLayerProtocol socketProtocol) { #ifndef QT_NO_IPV6 - int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET; + int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) ? AF_INET6 : AF_INET; #else Q_UNUSED(socketProtocol); int protocol = AF_INET; @@ -495,7 +495,14 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; - if (address.protocol() == QAbstractSocket::IPv6Protocol) { + if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) { +#ifdef IPV6_V6ONLY + 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); @@ -866,7 +873,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; - if (host.protocol() == QAbstractSocket::IPv6Protocol) { + if (host.protocol() == QAbstractSocket::IPv6Protocol + || socketProtocol == QAbstractSocket::IPv6Protocol) { memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 88b87b98fe..ba62bd6da2 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -159,11 +159,6 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength) #define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */ #endif -//### -#define QT_SOCKLEN_T int -#define QT_SOCKOPTLEN_T int - - /* Extracts the port and address from a sockaddr, and stores them in \a port and \a addr if they are non-null. @@ -202,11 +197,13 @@ static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6. */ -static inline void qt_socket_setPortAndAddress(SOCKET socketDescriptor, sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6, +void QNativeSocketEnginePrivate::setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6, quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize) { #if !defined(QT_NO_IPV6) - if (address.protocol() == QAbstractSocket::IPv6Protocol) { + if (address.protocol() == QAbstractSocket::IPv6Protocol + || address.protocol() == QAbstractSocket::AnyIPProtocol + || socketProtocol == QAbstractSocket::IPv6Protocol) { memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6)); sockAddrIPv6->sin6_family = AF_INET6; sockAddrIPv6->sin6_scope_id = address.scopeId().toInt(); @@ -306,7 +303,9 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc } */ - int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET; + //Windows XP and 2003 support IPv6 but not dual stack sockets + int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol + || (socketProtocol == QAbstractSocket::AnyIPProtocol && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0)) ? AF_INET6 : AF_INET; int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM; // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking // and recomends alwasy doing it for cross windows version comapablity. @@ -602,7 +601,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; - qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); + setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); forever { int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0); @@ -708,19 +707,35 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) { QHostAddress address = a; + DWORD ipv6only = 0; switch (address.protocol()) { case QAbstractSocket::IPv6Protocol: if (address.toIPv6Address()[0] == 0xff) { // binding to a multicast address address = QHostAddress(QHostAddress::AnyIPv6); } +#if !defined (QT_NO_IPV6) && defined (IPV6_V6ONLY) + //This is default in current windows versions, it may change in future so set it explicitly + if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) { + ipv6only = 1; + ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); + } +#endif break; case QAbstractSocket::IPv4Protocol: if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) { // binding to a multicast address - address = QHostAddress(QHostAddress::Any); + address = QHostAddress(QHostAddress::AnyIPv4); } break; + case QAbstractSocket::AnyIPProtocol: +#if !defined (QT_NO_IPV6) && defined (IPV6_V6ONLY) + if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) + ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); + else +#endif + address = QHostAddress(QHostAddress::AnyIPv4); //xp/WS2003 and earlier don't support dual stack, so bind to IPv4 + break; default: break; } @@ -730,7 +745,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; - qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); + setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize); @@ -1182,7 +1197,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; - qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); + setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); WSABUF buf; #if !defined(Q_OS_WINCE) diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index ab757987f6..514a7a0f6f 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -827,7 +827,7 @@ void QSocks5SocketEnginePrivate::sendRequestMethod() //### set error code .... return; } else if (!peerName.isEmpty() && !qt_socks5_set_host_name_and_port(peerName, port, &buf)) { - QSOCKS5_DEBUG << "error setting address" << address << " : " << port; + QSOCKS5_DEBUG << "error setting peer name" << peerName << " : " << port; //### set error code .... return; } @@ -1325,12 +1325,18 @@ void QSocks5SocketEnginePrivate::_q_udpSocketReadNotification() } #endif // QT_NO_UDPSOCKET -bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port) +bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port) { Q_D(QSocks5SocketEngine); // when bind wee will block until the bind is finished as the info from the proxy server is needed + QHostAddress address; + if (addr.protocol() == QAbstractSocket::AnyIPProtocol) + address = QHostAddress::AnyIPv4; //SOCKS5 doesnt support dual stack, and there isn't any implementation of udp on ipv6 yet + else + address = addr; + if (!d->data) { if (socketType() == QAbstractSocket::TcpSocket) { d->initialize(QSocks5SocketEnginePrivate::BindMode); |