diff options
author | Shane Kearns <[email protected]> | 2011-06-07 14:38:38 +0100 |
---|---|---|
committer | Qt by Nokia <[email protected]> | 2011-06-22 11:01:00 +0200 |
commit | 85136496bc8517951dcc3e670d1a46d340819f0d (patch) | |
tree | 86ca9423d926ed2f85744f4159966549f454e8f8 /src/network/socket/qnativesocketengine_unix.cpp | |
parent | 665d8a045455214d2cfca72076da6bc75d3058c7 (diff) |
IPv4 + IPv6 dual stack sockets
Adds support for binding "dual stack" sockets (via QUdpSocket or
QTcpServer). A dual stack socket will accept incoming connections on
either IPv4 or IPv6 interfaces.
QHostAddress::Any - use this to bind a dual stack socket
QHostAddress::AnyIPv6 - use this to bind a socket for IPv6 only
QHostAddress::AnyIPv4 - use this to bind a socket for IPv4 only
Binding to a specific address rather than one of the "any" addresses
is restricting you to a protocol anyway so no behaviour change there.
IPv6 sockets were previously dual stack on some OS and v6 only on others
Any previously meant IPv4 only
This commit implemented & tested on Windows 7, Linux (Ubuntu 10.04)
and Mac OS 10.6.7.
Windows XP and server 2003 do not support dual stack sockets, even though
they can support IPv6. On those versions, QHostAddress::Any will still
bind to IPv4 0.0.0.0 (which is also the behaviour anywhere QT_NO_IPV6 is
defined)
Autotests run:
qudpsocket (includes a new test case)
qtcpserver (includes a new test case)
qtcpsocket
qnetworkreply
qhostaddress
Task-number: QTBUG-17080
Change-Id: Id486677c4f832e18dc0ff1a86c5f5fc422c9eb4f
Reviewed-on: http://codereview.qt.nokia.com/421
Reviewed-by: Qt Sanity Bot <[email protected]>
Reviewed-by: Thiago Macieira <[email protected]>
Reviewed-by: Markus Goetz
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 39570c8c040..26053981ceb 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); |