QNativeSocketEngine Unix: do the same as for Windows
Change-Id: Iee8cbc07c4434ce9b560ffff13ca9d9858cf7111 Reviewed-by: Richard J. Moore <rich@kde.org>
This commit is contained in:
parent
2c64e05d49
commit
452924c6ff
@ -284,14 +284,40 @@ public:
|
|||||||
int nativeSelect(int timeout, bool selectForRead) const;
|
int nativeSelect(int timeout, bool selectForRead) const;
|
||||||
int nativeSelect(int timeout, bool checkRead, bool checkWrite,
|
int nativeSelect(int timeout, bool checkRead, bool checkWrite,
|
||||||
bool *selectForRead, bool *selectForWrite) const;
|
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();
|
void nativeClose();
|
||||||
|
|
||||||
bool checkProxy(const QHostAddress &address);
|
bool checkProxy(const QHostAddress &address);
|
||||||
bool fetchConnectionParameters();
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -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())
|
if (scopeid.isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -389,37 +389,11 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
|
|||||||
qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
|
qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sockaddr_in sockAddrIPv4;
|
qt_sockaddr aa;
|
||||||
struct sockaddr *sockAddrPtr = 0;
|
QT_SOCKLEN_T sockAddrSize;
|
||||||
QT_SOCKLEN_T sockAddrSize = 0;
|
setPortAndAddress(port, addr, &aa, &sockAddrSize);
|
||||||
|
|
||||||
struct sockaddr_in6 sockAddrIPv6;
|
int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
|
|
||||||
#if defined (QNATIVESOCKETENGINE_DEBUG)
|
#if defined (QNATIVESOCKETENGINE_DEBUG)
|
||||||
int ecopy = errno;
|
int ecopy = errno;
|
||||||
#endif
|
#endif
|
||||||
@ -491,51 +465,28 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
|
|||||||
|
|
||||||
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
|
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sockAddrIPv4;
|
qt_sockaddr aa;
|
||||||
struct sockaddr *sockAddrPtr = 0;
|
QT_SOCKLEN_T sockAddrSize;
|
||||||
QT_SOCKLEN_T sockAddrSize = 0;
|
setPortAndAddress(port, address, &aa, &sockAddrSize);
|
||||||
|
|
||||||
|
|
||||||
struct sockaddr_in6 sockAddrIPv6;
|
|
||||||
|
|
||||||
if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) {
|
|
||||||
#ifdef IPV6_V6ONLY
|
#ifdef IPV6_V6ONLY
|
||||||
|
if (aa.a.sa_family == AF_INET6) {
|
||||||
int ipv6only = 0;
|
int ipv6only = 0;
|
||||||
if (address.protocol() == QAbstractSocket::IPv6Protocol)
|
if (address.protocol() == QAbstractSocket::IPv6Protocol)
|
||||||
ipv6only = 1;
|
ipv6only = 1;
|
||||||
//default value of this socket option varies depending on unix variant (or system configuration on BSD), so always set it explicitly
|
//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) );
|
::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
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
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) {
|
if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
|
||||||
memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
|
// retry with v4
|
||||||
sockAddrIPv4.sin_family = AF_INET;
|
aa.a4.sin_family = AF_INET;
|
||||||
sockAddrIPv4.sin_port = htons(port);
|
aa.a4.sin_port = htons(port);
|
||||||
sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
|
aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
|
||||||
sockAddrSize = sizeof(sockAddrIPv4);
|
sockAddrSize = sizeof(aa.a4);
|
||||||
sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
|
bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
|
||||||
bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bindResult < 0) {
|
if (bindResult < 0) {
|
||||||
@ -992,17 +943,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
|
|||||||
msg.msg_name = &aa.a;
|
msg.msg_name = &aa.a;
|
||||||
msg.msg_control = &cbuf;
|
msg.msg_control = &cbuf;
|
||||||
|
|
||||||
if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol
|
setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.msg_namelen);
|
||||||
|| 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);
|
|
||||||
|
|
||||||
|
if (msg.msg_namelen == sizeof(aa.a6)) {
|
||||||
if (header.hopLimit != -1) {
|
if (header.hopLimit != -1) {
|
||||||
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
||||||
cmsgptr->cmsg_len = CMSG_LEN(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;
|
cmsgptr->cmsg_type = IPV6_PKTINFO;
|
||||||
data->ipi6_ifindex = header.ifindex;
|
data->ipi6_ifindex = header.ifindex;
|
||||||
|
|
||||||
tmp = header.senderAddress.toIPv6Address();
|
QIPv6Address tmp = header.senderAddress.toIPv6Address();
|
||||||
memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
|
memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
|
||||||
cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
|
cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
|
||||||
}
|
}
|
||||||
} else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) {
|
} else {
|
||||||
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);
|
|
||||||
|
|
||||||
if (header.hopLimit != -1) {
|
if (header.hopLimit != -1) {
|
||||||
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
||||||
cmsgptr->cmsg_len = CMSG_LEN(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)));
|
cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (msg.msg_controllen == 0)
|
||||||
|
@ -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
|
/*! \internal
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@ -348,6 +322,12 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
|
|||||||
# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
|
# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// inline on purpose
|
||||||
|
inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
|
||||||
|
{
|
||||||
|
return scopeid.toUInt();
|
||||||
|
}
|
||||||
|
|
||||||
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
|
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user