/* Sets the socket option \a opt to \a v. */ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v) { Q_Q(QNativeSocketEngine); if (!q->isValid()) return false; // handle non-setsockopt cases first switch (opt) { case QNativeSocketEngine::NonBlockingSocketOption: { // Make the socket nonblocking. #if !defined(Q_OS_VXWORKS) int flags = ::fcntl(socketDescriptor, F_GETFL, 0); if (flags == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed"); #endif return false; } if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed"); #endif return false; } #else // Q_OS_VXWORKS int onoff = 1; if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed"); #endif return false; } #endif // Q_OS_VXWORKS return true; } case QNativeSocketEngine::BindExclusively: return true; default: break; } int n, level; convertToLevelAndOption(opt, socketProtocol, level, n); #if defined(SO_REUSEPORT) && !defined(Q_OS_LINUX) 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; } #endif return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; }
static QList<QNetworkInterfacePrivate *> interfaceListing() { QList<QNetworkInterfacePrivate *> interfaces; int socket; if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1) return interfaces; // error QSet<QByteArray> names = interfaceNames(socket); QSet<QByteArray>::ConstIterator it = names.constBegin(); for ( ; it != names.constEnd(); ++it) { ifreq req; memset(&req, 0, sizeof(ifreq)); memcpy(req.ifr_name, *it, qMin<int>(it->length() + 1, sizeof(req.ifr_name) - 1)); QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req); // Get the interface broadcast address QNetworkAddressEntry entry; if (iface->flags & QNetworkInterface::CanBroadcast) { if (qt_safe_ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) { sockaddr *sa = &req.ifr_addr; if (sa->sa_family == AF_INET) entry.setBroadcast(addressFromSockaddr(sa)); } } // Get the interface netmask if (qt_safe_ioctl(socket, SIOCGIFNETMASK, &req) >= 0) { sockaddr *sa = &req.ifr_addr; entry.setNetmask(addressFromSockaddr(sa)); } // Get the address of the interface if (qt_safe_ioctl(socket, SIOCGIFADDR, &req) >= 0) { sockaddr *sa = &req.ifr_addr; entry.setIp(addressFromSockaddr(sa)); } iface->addressEntries << entry; } ::close(socket); return interfaces; }
qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { int nbytes = 0; // gives shorter than true amounts on Unix domain sockets. qint64 available = 0; if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0) available = (qint64) nbytes; #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available); #endif return available; }
static QSet<QByteArray> interfaceNames(int socket) { QSet<QByteArray> result; #ifdef QT_NO_IPV6IFNAME QByteArray storageBuffer; struct ifconf interfaceList; forever { // grow the storage buffer storageBuffer.resize(storageBuffer.size() + STORAGEBUFFER_GROWTH); interfaceList.ifc_buf = storageBuffer.data(); interfaceList.ifc_len = storageBuffer.size(); // get the interface list if (qt_safe_ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) { if (int(interfaceList.ifc_len + sizeof(ifreq) + 64) < storageBuffer.size()) { // if the buffer was big enough, break storageBuffer.resize(interfaceList.ifc_len); break; } } else { // internal error return result; } if (storageBuffer.size() > 100000) { // out of space return result; } } int interfaceCount = interfaceList.ifc_len / sizeof(ifreq); for (int i = 0; i < interfaceCount; ++i) { QByteArray name = QByteArray(interfaceList.ifc_req[i].ifr_name); if (!name.isEmpty()) result << name; } return result; #else Q_UNUSED(socket); // use if_nameindex struct if_nameindex *interfaceList = ::if_nameindex(); for (struct if_nameindex *ptr = interfaceList; ptr && ptr->if_name; ++ptr) result << ptr->if_name; if_freenameindex(interfaceList); return result; #endif }
qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { int nbytes = 0; // gives shorter than true amounts on Unix domain sockets. qint64 available = -1; #if defined (SO_NREAD) if (socketType == QAbstractSocket::UdpSocket) { socklen_t sz = sizeof nbytes; if (!::getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &nbytes, &sz)) available = nbytes; } #endif if (available == -1 && qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0) available = nbytes; #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available); #endif return available > 0 ? available : 0; }
static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfacePrivate *> &interfaces, struct ifreq &req) { QNetworkInterfacePrivate *iface = 0; int ifindex = 0; #ifndef QT_NO_IPV6IFNAME // Get the interface index ifindex = if_nametoindex(req.ifr_name); // find the interface data QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin(); for ( ; if_it != interfaces.end(); ++if_it) if ((*if_it)->index == ifindex) { // existing interface iface = *if_it; break; } #else // Search by name QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin(); for ( ; if_it != interfaces.end(); ++if_it) if ((*if_it)->name == QLatin1String(req.ifr_name)) { // existing interface iface = *if_it; break; } #endif if (!iface) { // new interface, create data: iface = new QNetworkInterfacePrivate; iface->index = ifindex; interfaces << iface; #ifdef SIOCGIFNAME // Get the canonical name QByteArray oldName = req.ifr_name; if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) { iface->name = QString::fromLatin1(req.ifr_name); // reset the name: memcpy(req.ifr_name, oldName, qMin<int>(oldName.length() + 1, sizeof(req.ifr_name) - 1)); } else #endif { // use this name anyways iface->name = QString::fromLatin1(req.ifr_name); } // Get interface flags if (qt_safe_ioctl(socket, SIOCGIFFLAGS, &req) >= 0) { iface->flags = convertFlags(req.ifr_flags); } #ifdef SIOCGIFHWADDR // Get the HW address if (qt_safe_ioctl(socket, SIOCGIFHWADDR, &req) >= 0) { uchar *addr = (uchar *)req.ifr_addr.sa_data; iface->hardwareAddress = iface->makeHwAddress(6, addr); } #endif } return iface; }
/* Sets the socket option \a opt to \a v. */ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v) { Q_Q(QNativeSocketEngine); if (!q->isValid()) return false; int n = 0; int level = SOL_SOCKET; // default 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) int flags = ::fcntl(socketDescriptor, F_GETFL, 0); if (flags == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed"); #endif return false; } if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed"); #endif return false; } #else // Q_OS_VXWORKS int onoff = 1; if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed"); #endif return false; } #endif // Q_OS_VXWORKS return true; } case QNativeSocketEngine::AddressReusable: #if defined(SO_REUSEPORT) n = SO_REUSEPORT; #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; } return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; }
/* Sets the socket option \a opt to \a v. */ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v) { Q_Q(QNativeSocketEngine); if (!q->isValid()) return false; int n = 0; int level = SOL_SOCKET; // default 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) int flags = ::fcntl(socketDescriptor, F_GETFL, 0); if (flags == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed"); #endif return false; } if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed"); #endif return false; } #else // Q_OS_VXWORKS int onoff = 1; #ifdef Q_OS_SYMBIAN if (::ioctl(socketDescriptor, FIONBIO, &onoff) < 0) { #else if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) { #endif #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed"); #endif return false; } #endif // Q_OS_VXWORKS return true; } case QNativeSocketEngine::AddressReusable: #if defined(SO_REUSEPORT) && !defined(Q_OS_SYMBIAN) n = SO_REUSEPORT; #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; } return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; } bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) { #ifdef QNATIVESOCKETENGINE_DEBUG qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); #endif struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; if (addr.protocol() == QAbstractSocket::IPv6Protocol) { memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); #ifndef QT_NO_IPV6IFNAME sockAddrIPv6.sin6_scope_id = ::if_nametoindex(addr.scopeId().toLatin1().data()); #else sockAddrIPv6.sin6_scope_id = addr.scopeId().toInt(); #endif Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6)); sockAddrSize = sizeof(sockAddrIPv6); sockAddrPtr = (struct sockaddr *) &sockAddrIPv6; } else #if 0 {} #endif #endif 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 } #ifdef Q_OS_SYMBIAN int connectResult = ::connect(socketDescriptor, sockAddrPtr, sockAddrSize); #else int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize); #endif if (connectResult == -1) { switch (errno) { case EISCONN: socketState = QAbstractSocket::ConnectedState; break; case ECONNREFUSED: case EINVAL: setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); socketState = QAbstractSocket::UnconnectedState; break; case ETIMEDOUT: setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); break; case EHOSTUNREACH: setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); socketState = QAbstractSocket::UnconnectedState; break; case ENETUNREACH: setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); socketState = QAbstractSocket::UnconnectedState; break; case EADDRINUSE: setError(QAbstractSocket::NetworkError, AddressInuseErrorString); break; case EINPROGRESS: case EALREADY: setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString); socketState = QAbstractSocket::ConnectingState; break; case EAGAIN: setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString); setError(QAbstractSocket::SocketResourceError, ResourceErrorString); break; case EACCES: case EPERM: setError(QAbstractSocket::SocketAccessError, AccessErrorString); socketState = QAbstractSocket::UnconnectedState; break; case EAFNOSUPPORT: case EBADF: case EFAULT: case ENOTSOCK: socketState = QAbstractSocket::UnconnectedState; default: break; } if (socketState != QAbstractSocket::ConnectedState) { #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)", addr.toString().toLatin1().constData(), port, socketState == QAbstractSocket::ConnectingState ? "Connection in progress" : socketErrorString.toLatin1().constData()); #endif return false; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true", addr.toString().toLatin1().constData(), port); #endif socketState = QAbstractSocket::ConnectedState; return true; }