summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qnativesocketengine_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp246
1 files changed, 102 insertions, 144 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index da36e4a6da..4648a3cb5a 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -127,6 +128,83 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po
}
}
+static inline uint makeScopeId(const QHostAddress &addr)
+{
+ QString scopeid = addr.scopeId();
+ if (scopeid.isEmpty())
+ return 0;
+
+ bool ok;
+ uint id = scopeid.toUInt(&ok);
+#ifndef QT_NO_IPV6IFNAME
+ if (!ok)
+ id = ::if_nametoindex(scopeid.toLatin1());
+#endif
+ return id;
+}
+
+static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
+ QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n)
+{
+ n = -1;
+ level = SOL_SOCKET; // default
+
+ switch (opt) {
+ case QNativeSocketEngine::NonBlockingSocketOption: // fcntl, not setsockopt
+ case QNativeSocketEngine::BindExclusively: // not handled on Unix
+ Q_UNREACHABLE();
+
+ case QNativeSocketEngine::BroadcastSocketOption:
+ n = SO_BROADCAST;
+ break;
+ case QNativeSocketEngine::ReceiveBufferSocketOption:
+ n = SO_RCVBUF;
+ break;
+ case QNativeSocketEngine::SendBufferSocketOption:
+ n = SO_SNDBUF;
+ break;
+ case QNativeSocketEngine::AddressReusable:
+ n = SO_REUSEADDR;
+ break;
+ case QNativeSocketEngine::ReceiveOutOfBandData:
+ n = SO_OOBINLINE;
+ break;
+ case QNativeSocketEngine::LowDelayOption:
+ level = IPPROTO_TCP;
+ n = TCP_NODELAY;
+ break;
+ case QNativeSocketEngine::KeepAliveOption:
+ n = SO_KEEPALIVE;
+ break;
+ case QNativeSocketEngine::MulticastTtlOption:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_MULTICAST_HOPS;
+ } else
+ {
+ level = IPPROTO_IP;
+ n = IP_MULTICAST_TTL;
+ }
+ break;
+ case QNativeSocketEngine::MulticastLoopbackOption:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_MULTICAST_LOOP;
+ } else
+ {
+ level = IPPROTO_IP;
+ n = IP_MULTICAST_LOOP;
+ }
+ break;
+ case QNativeSocketEngine::TypeOfServiceOption:
+ if (socketProtocol == QAbstractSocket::IPv4Protocol) {
+ level = IPPROTO_IP;
+ n = IP_TOS;
+ }
+ break;
+ }
+}
+
/*! \internal
Creates and returns a new socket descriptor of type \a socketType
@@ -193,65 +271,16 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
if (!q->isValid())
return -1;
- int n = -1;
- int level = SOL_SOCKET; // default
-
- switch (opt) {
- case QNativeSocketEngine::ReceiveBufferSocketOption:
- n = SO_RCVBUF;
- break;
- case QNativeSocketEngine::SendBufferSocketOption:
- n = SO_SNDBUF;
- break;
- case QNativeSocketEngine::NonBlockingSocketOption:
- break;
- case QNativeSocketEngine::BroadcastSocketOption:
- break;
- case QNativeSocketEngine::AddressReusable:
- n = SO_REUSEADDR;
- break;
- case QNativeSocketEngine::BindExclusively:
+ // handle non-getsockopt cases first
+ if (opt == QNativeSocketEngine::BindExclusively || opt == QNativeSocketEngine::NonBlockingSocketOption
+ || opt == QNativeSocketEngine::BroadcastSocketOption)
return true;
- case QNativeSocketEngine::ReceiveOutOfBandData:
- n = SO_OOBINLINE;
- break;
- case QNativeSocketEngine::LowDelayOption:
- level = IPPROTO_TCP;
- n = TCP_NODELAY;
- break;
- case QNativeSocketEngine::KeepAliveOption:
- n = SO_KEEPALIVE;
- break;
- case QNativeSocketEngine::MulticastTtlOption:
- if (socketProtocol == QAbstractSocket::IPv6Protocol) {
- level = IPPROTO_IPV6;
- n = IPV6_MULTICAST_HOPS;
- } else
- {
- level = IPPROTO_IP;
- n = IP_MULTICAST_TTL;
- }
- break;
- case QNativeSocketEngine::MulticastLoopbackOption:
- if (socketProtocol == QAbstractSocket::IPv6Protocol) {
- level = IPPROTO_IPV6;
- n = IPV6_MULTICAST_LOOP;
- } else
- {
- level = IPPROTO_IP;
- n = IP_MULTICAST_LOOP;
- }
- break;
- case QNativeSocketEngine::TypeOfServiceOption:
- if (socketProtocol == QAbstractSocket::IPv4Protocol) {
- level = IPPROTO_IP;
- n = IP_TOS;
- }
- break;
- }
+ int n, level;
int v = -1;
QT_SOCKOPTLEN_T len = sizeof(v);
+
+ convertToLevelAndOption(opt, socketProtocol, level, n);
if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
return v;
@@ -268,19 +297,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
if (!q->isValid())
return false;
- int n = 0;
- int level = SOL_SOCKET; // default
-
+ // handle non-setsockopt cases first
switch (opt) {
- case QNativeSocketEngine::ReceiveBufferSocketOption:
- n = SO_RCVBUF;
- break;
- case QNativeSocketEngine::SendBufferSocketOption:
- n = SO_SNDBUF;
- break;
- case QNativeSocketEngine::BroadcastSocketOption:
- n = SO_BROADCAST;
- break;
case QNativeSocketEngine::NonBlockingSocketOption: {
// Make the socket nonblocking.
#if !defined(Q_OS_VXWORKS)
@@ -310,58 +328,24 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
#endif // Q_OS_VXWORKS
return true;
}
- case QNativeSocketEngine::AddressReusable:
+ case QNativeSocketEngine::BindExclusively:
+ return true;
+
+ default:
+ break;
+ }
+
+ int n, level;
+ convertToLevelAndOption(opt, socketProtocol, level, n);
#if defined(SO_REUSEPORT)
+ if (opt == QNativeSocketEngine::AddressReusable) {
// on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the
// same port (which is useful for multicast UDP). SO_REUSEPORT is, but
// we most definitely do not want to use this for TCP. See QTBUG-6305.
if (socketType == QAbstractSocket::UdpSocket)
n = SO_REUSEPORT;
- else
- n = SO_REUSEADDR;
-#else
- n = SO_REUSEADDR;
-#endif
- break;
- case QNativeSocketEngine::BindExclusively:
- return true;
- case QNativeSocketEngine::ReceiveOutOfBandData:
- n = SO_OOBINLINE;
- break;
- case QNativeSocketEngine::LowDelayOption:
- level = IPPROTO_TCP;
- n = TCP_NODELAY;
- break;
- case QNativeSocketEngine::KeepAliveOption:
- n = SO_KEEPALIVE;
- break;
- case QNativeSocketEngine::MulticastTtlOption:
- if (socketProtocol == QAbstractSocket::IPv6Protocol) {
- level = IPPROTO_IPV6;
- n = IPV6_MULTICAST_HOPS;
- } else
- {
- level = IPPROTO_IP;
- n = IP_MULTICAST_TTL;
- }
- break;
- case QNativeSocketEngine::MulticastLoopbackOption:
- if (socketProtocol == QAbstractSocket::IPv6Protocol) {
- level = IPPROTO_IPV6;
- n = IPV6_MULTICAST_LOOP;
- } else
- {
- level = IPPROTO_IP;
- n = IP_MULTICAST_LOOP;
- }
- break;
- case QNativeSocketEngine::TypeOfServiceOption:
- if (socketProtocol == QAbstractSocket::IPv4Protocol) {
- level = IPPROTO_IP;
- n = IP_TOS;
- }
- break;
}
+#endif
return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
}
@@ -382,17 +366,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
+ sockAddrIPv6.sin6_scope_id = makeScopeId(addr);
- QString scopeid = addr.scopeId();
-
- if (!scopeid.isEmpty()) {
- bool ok;
- sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
-#ifndef QT_NO_IPV6IFNAME
- if (!ok)
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
-#endif
- }
Q_IPV6ADDR ip6 = addr.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
@@ -501,16 +476,8 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
- QString scopeid = address.scopeId();
+ sockAddrIPv6.sin6_scope_id = makeScopeId(address);
- if (!scopeid.isEmpty()) {
- bool ok;
- sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
-#ifndef QT_NO_IPV6IFNAME
- if (!ok)
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
-#endif
- }
Q_IPV6ADDR tmp = address.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
sockAddrSize = sizeof(sockAddrIPv6);
@@ -749,7 +716,7 @@ bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &g
QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
{
- if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
uint v;
QT_SOCKOPTLEN_T sizeofv = sizeof(v);
if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
@@ -779,7 +746,7 @@ QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface)
{
- if (socketProtocol == QAbstractSocket::IPv6Protocol) {
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
uint v = iface.index();
return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, sizeof(v)) != -1);
}
@@ -918,19 +885,10 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
+ sockAddrIPv6.sin6_scope_id = makeScopeId(host);
Q_IPV6ADDR tmp = host.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
- QString scopeid = host.scopeId();
-
- if (!scopeid.isEmpty()) {
- bool ok;
- sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
-#ifndef QT_NO_IPV6IFNAME
- if (!ok)
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
-#endif
- }
sockAddrSize = sizeof(sockAddrIPv6);
sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
} else if (host.protocol() == QAbstractSocket::IPv4Protocol) {
@@ -1037,7 +995,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
#if defined (QNATIVESOCKETENGINE_DEBUG)
QString socketProtocolStr = QStringLiteral("UnknownProtocol");
if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral("IPv4Protocol");
- else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = QStringLiteral("IPv6Protocol");
+ else if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) socketProtocolStr = QStringLiteral("IPv6Protocol");
QString socketTypeStr = QStringLiteral("UnknownSocketType");
if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral("TcpSocket");