QNativeSocketEngine Unix: do the same as for Windows

Change-Id: Iee8cbc07c4434ce9b560ffff13ca9d9858cf7111
Reviewed-by: Richard J. Moore <rich@kde.org>
This commit is contained in:
Thiago Macieira 2015-03-11 18:58:29 -07:00
parent 2c64e05d49
commit 452924c6ff
3 changed files with 57 additions and 117 deletions

View File

@ -284,14 +284,40 @@ 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(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize);
#endif
void nativeClose();
bool checkProxy(const QHostAddress &address);
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

View File

@ -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())
return 0;
@ -389,37 +389,11 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
#endif
struct sockaddr_in sockAddrIPv4;
struct sockaddr *sockAddrPtr = 0;
QT_SOCKLEN_T sockAddrSize = 0;
qt_sockaddr aa;
QT_SOCKLEN_T sockAddrSize;
setPortAndAddress(port, addr, &aa, &sockAddrSize);
struct sockaddr_in6 sockAddrIPv6;
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);
int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
#if defined (QNATIVESOCKETENGINE_DEBUG)
int ecopy = errno;
#endif
@ -491,51 +465,28 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
{
struct sockaddr_in sockAddrIPv4;
struct sockaddr *sockAddrPtr = 0;
QT_SOCKLEN_T sockAddrSize = 0;
qt_sockaddr aa;
QT_SOCKLEN_T sockAddrSize;
setPortAndAddress(port, address, &aa, &sockAddrSize);
struct sockaddr_in6 sockAddrIPv6;
if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) {
#ifdef IPV6_V6ONLY
if (aa.a.sa_family == AF_INET6) {
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);
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
}
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) {
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;
bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
// retry with v4
aa.a4.sin_family = AF_INET;
aa.a4.sin_port = htons(port);
aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
sockAddrSize = sizeof(aa.a4);
bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
}
if (bindResult < 0) {
@ -992,17 +943,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
msg.msg_name = &aa.a;
msg.msg_control = &cbuf;
if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol
|| 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);
setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.msg_namelen);
if (msg.msg_namelen == sizeof(aa.a6)) {
if (header.hopLimit != -1) {
msg.msg_controllen += CMSG_SPACE(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;
data->ipi6_ifindex = header.ifindex;
tmp = header.senderAddress.toIPv6Address();
QIPv6Address tmp = header.senderAddress.toIPv6Address();
memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
}
} else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) {
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);
} else {
if (header.hopLimit != -1) {
msg.msg_controllen += CMSG_SPACE(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)));
}
#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)

View File

@ -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
*/
@ -348,6 +322,12 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif
// inline on purpose
inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
{
return scopeid.toUInt();
}
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{