From 3a53b2853c0f1d4ace0eaf73f8c5ca5ded172345 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 09:23:04 +0100 Subject: Symbian socket engine: Some more comments --- src/network/socket/qnativesocketengine_symbian.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp index d1a0819..cfaee03 100644 --- a/src/network/socket/qnativesocketengine_symbian.cpp +++ b/src/network/socket/qnativesocketengine_symbian.cpp @@ -165,6 +165,9 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return false; } + // FIXME Set socket to nonblocking. While we are still a QNativeSocketEngine this is done already. + // Uncomment the following when we switch to QSymbianSocketEngine. + // setOption(NonBlockingSocketOption, 1) socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket); return true; @@ -444,7 +447,8 @@ int QNativeSocketEnginePrivate::nativeAccept() qWarning("QNativeSocketEnginePrivate::nativeAccept() - error %d", status.Int()); return 0; } - + // FIXME Qt Handle of new socket must be retrieved from QSymbianSocketManager + // and then returned. Not the SubSessionHandle! Also set the socket to nonblocking. return blankSocket.SubSessionHandle(); } @@ -452,6 +456,8 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { int nbytes = 0; qint64 available = 0; + // FIXME is this the right thing also for UDP? + // What is expected for UDP, the length for the next packet I guess? TInt err = nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); if(err) return 0; @@ -476,6 +482,8 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const int nbytes; TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); return qint64(nbytes-28); //TODO: why -28 (open C version had this)? + // Why = Could it be that this is about header lengths etc? if yes + // this could be pretty broken, especially for IPv6 } qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, @@ -744,6 +752,8 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c //writeStat = ? array[count++] = writeStat; } + // TODO: for selecting, we can use getOpt(KSOSelectPoll) to get the select result + // and KIOCtlSelect for the selecting. User::WaitForNRequest(array, count); //IMPORTANT - WaitForNRequest only decrements the thread semaphore once, although more than one status may have completed. -- cgit v0.12 From fcb60092c90934df77f1441df7ab2a14fc5edf32 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 09:43:07 +0100 Subject: Copy qhostinfo_unix.cpp to qhostinfo_symbian.cpp --- src/network/kernel/kernel.pri | 2 +- src/network/kernel/qhostinfo_symbian.cpp | 407 +++++++++++++++++++++++++++++++ 2 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 src/network/kernel/qhostinfo_symbian.cpp diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 6145c43..ccc113c 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -20,7 +20,7 @@ SOURCES += kernel/qauthenticator.cpp \ kernel/qnetworkproxy.cpp \ kernel/qnetworkinterface.cpp -symbian: SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_symbian.cpp +symbian: SOURCES += kernel/qhostinfo_symbian.cpp kernel/qnetworkinterface_symbian.cpp unix:!symbian:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp new file mode 100644 index 0000000..5ca15a3 --- /dev/null +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -0,0 +1,407 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//#define QHOSTINFO_DEBUG + +#include "qplatformdefs.h" + +#include "qhostinfo_p.h" +#include "private/qnativesocketengine_p.h" +#include "qiodevice.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#if defined(Q_OS_VXWORKS) +# include +#else +# include +#endif + +#if defined (QT_NO_GETADDRINFO) +#include +QT_BEGIN_NAMESPACE +Q_GLOBAL_STATIC(QMutex, getHostByNameMutex) +QT_END_NAMESPACE +#endif + +QT_BEGIN_NAMESPACE + +// Almost always the same. If not, specify in qplatformdefs.h. +#if !defined(QT_SOCKOPTLEN_T) +# define QT_SOCKOPTLEN_T QT_SOCKLEN_T +#endif + +// HP-UXi has a bug in getaddrinfo(3) that makes it thread-unsafe +// with this flag. So disable it in that platform. +#if defined(AI_ADDRCONFIG) && !defined(Q_OS_HPUX) +# define Q_ADDRCONFIG AI_ADDRCONFIG +#endif + +typedef struct __res_state *res_state_ptr; + +typedef int (*res_init_proto)(void); +static res_init_proto local_res_init = 0; +typedef int (*res_ninit_proto)(res_state_ptr); +static res_ninit_proto local_res_ninit = 0; +typedef void (*res_nclose_proto)(res_state_ptr); +static res_nclose_proto local_res_nclose = 0; +static res_state_ptr local_res = 0; + +static void resolveLibrary() +{ +#ifndef QT_NO_LIBRARY + QLibrary lib(QLatin1String("resolv")); + if (!lib.load()) + return; + + local_res_init = res_init_proto(lib.resolve("__res_init")); + if (!local_res_init) + local_res_init = res_init_proto(lib.resolve("res_init")); + + local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit")); + if (!local_res_ninit) + local_res_ninit = res_ninit_proto(lib.resolve("res_ninit")); + + if (!local_res_ninit) { + // if we can't get a thread-safe context, we have to use the global _res state + local_res = res_state_ptr(lib.resolve("_res")); + } else { + local_res_nclose = res_nclose_proto(lib.resolve("res_nclose")); + if (!local_res_nclose) + local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose")); + if (!local_res_nclose) + local_res_ninit = 0; + } +#endif +} + +QHostInfo QHostInfoAgent::fromName(const QString &hostName) +{ + QHostInfo results; + +#if defined(QHOSTINFO_DEBUG) + qDebug("QHostInfoAgent::fromName(%s) looking up...", + hostName.toLatin1().constData()); +#endif + + // Load res_init on demand. + static volatile bool triedResolve = false; + if (!triedResolve) { + QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); + if (!triedResolve) { + resolveLibrary(); + triedResolve = true; + } + } + + // If res_init is available, poll it. + if (local_res_init) + local_res_init(); + + QHostAddress address; + if (address.setAddress(hostName)) { + // Reverse lookup +// Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. +#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) && !defined (Q_OS_SYMBIAN) + sockaddr_in sa4; +#ifndef QT_NO_IPV6 + sockaddr_in6 sa6; +#endif + sockaddr *sa = 0; + QT_SOCKLEN_T saSize = 0; + if (address.protocol() == QAbstractSocket::IPv4Protocol) { + sa = (sockaddr *)&sa4; + saSize = sizeof(sa4); + memset(&sa4, 0, sizeof(sa4)); + sa4.sin_family = AF_INET; + sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); + } +#ifndef QT_NO_IPV6 + else { + sa = (sockaddr *)&sa6; + saSize = sizeof(sa6); + memset(&sa6, 0, sizeof(sa6)); + sa6.sin6_family = AF_INET6; + memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); + } +#endif + + char hbuf[NI_MAXHOST]; + if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) + results.setHostName(QString::fromLatin1(hbuf)); +#else + in_addr_t inetaddr = qt_safe_inet_addr(hostName.toLatin1().constData()); + struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET); + if (ent) + results.setHostName(QString::fromLatin1(ent->h_name)); +#endif + + if (results.hostName().isEmpty()) + results.setHostName(address.toString()); + results.setAddresses(QList() << address); + return results; + } + + // IDN support + QByteArray aceHostname = QUrl::toAce(hostName); + results.setHostName(hostName); + if (aceHostname.isEmpty()) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(hostName.isEmpty() ? + QCoreApplication::translate("QHostInfoAgent", "No host name given") : + QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); + return results; + } + +#if !defined (QT_NO_GETADDRINFO) + // Call getaddrinfo, and place all IPv4 addresses at the start and + // the IPv6 addresses at the end of the address list in results. + addrinfo *res = 0; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef Q_ADDRCONFIG + hints.ai_flags = Q_ADDRCONFIG; +#endif +#ifdef Q_OS_SYMBIAN +# ifdef QHOSTINFO_DEBUG + qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'"; +# endif +#endif + + int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); +# ifdef Q_ADDRCONFIG + if (result == EAI_BADFLAGS) { + // if the lookup failed with AI_ADDRCONFIG set, try again without it + hints.ai_flags = 0; +#ifdef Q_OS_SYMBIAN +# ifdef QHOSTINFO_DEBUG + qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'"; +# endif + hints.ai_flags &= AI_V4MAPPED | AI_ALL; +#endif + result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); + } +# endif + + if (result == 0) { + addrinfo *node = res; + QList addresses; + while (node) { +#ifdef QHOSTINFO_DEBUG + qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen; +#endif + if (node->ai_family == AF_INET) { + QHostAddress addr; + addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); + if (!addresses.contains(addr)) + addresses.append(addr); + } +#ifndef QT_NO_IPV6 + else if (node->ai_family == AF_INET6) { + QHostAddress addr; + sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; + addr.setAddress(sa6->sin6_addr.s6_addr); + if (sa6->sin6_scope_id) + addr.setScopeId(QString::number(sa6->sin6_scope_id)); + if (!addresses.contains(addr)) + addresses.append(addr); + } +#endif + node = node->ai_next; + } + if (addresses.isEmpty() && node == 0) { + // Reached the end of the list, but no addresses were found; this + // means the list contains one or more unknown address types. + results.setError(QHostInfo::UnknownError); + results.setErrorString(tr("Unknown address type")); + } + + results.setAddresses(addresses); + freeaddrinfo(res); + } else if (result == EAI_NONAME + || result == EAI_FAIL +#ifdef EAI_NODATA + // EAI_NODATA is deprecated in RFC 3493 + || result == EAI_NODATA +#endif + ) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(tr("Host not found")); + } else { + results.setError(QHostInfo::UnknownError); + results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); + } + +#else + // Fall back to gethostbyname for platforms that don't define + // getaddrinfo. gethostbyname does not support IPv6, and it's not + // reentrant on all platforms. For now this is okay since we only + // use one QHostInfoAgent, but if more agents are introduced, locking + // must be provided. + QMutexLocker locker(::getHostByNameMutex()); + hostent *result = gethostbyname(aceHostname.constData()); + if (result) { + if (result->h_addrtype == AF_INET) { + QList addresses; + for (char **p = result->h_addr_list; *p != 0; p++) { + QHostAddress addr; + addr.setAddress(ntohl(*((quint32 *)*p))); + if (!addresses.contains(addr)) + addresses.prepend(addr); + } + results.setAddresses(addresses); + } else { + results.setError(QHostInfo::UnknownError); + results.setErrorString(tr("Unknown address type")); + } +#if !defined(Q_OS_VXWORKS) + } else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA + || h_errno == NO_ADDRESS) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(tr("Host not found")); +#endif + } else { + results.setError(QHostInfo::UnknownError); + results.setErrorString(tr("Unknown error")); + } +#endif // !defined (QT_NO_GETADDRINFO) + +#if defined(QHOSTINFO_DEBUG) + if (results.error() != QHostInfo::NoError) { + qDebug("QHostInfoAgent::fromName(): error #%d %s", + h_errno, results.errorString().toLatin1().constData()); + } else { + QString tmp; + QList addresses = results.addresses(); + for (int i = 0; i < addresses.count(); ++i) { + if (i != 0) tmp += ", "; + tmp += addresses.at(i).toString(); + } + qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", + addresses.count(), hostName.toLatin1().constData(), + tmp.toLatin1().constData()); + } +#endif + return results; +} + +QString QHostInfo::localHostName() +{ + char hostName[512]; + if (gethostname(hostName, sizeof(hostName)) == -1) + return QString(); + hostName[sizeof(hostName) - 1] = '\0'; + return QString::fromLocal8Bit(hostName); +} + +QString QHostInfo::localDomainName() +{ +#if !defined(Q_OS_VXWORKS) + resolveLibrary(); + if (local_res_ninit) { + // using thread-safe version + res_state_ptr state = res_state_ptr(qMalloc(sizeof(*state))); + Q_CHECK_PTR(state); + memset(state, 0, sizeof(*state)); + local_res_ninit(state); + QString domainName = QUrl::fromAce(state->defdname); + if (domainName.isEmpty()) + domainName = QUrl::fromAce(state->dnsrch[0]); + local_res_nclose(state); + qFree(state); + + return domainName; + } + + if (local_res_init && local_res) { + // using thread-unsafe version + +#if defined(QT_NO_GETADDRINFO) + // We have to call res_init to be sure that _res was initialized + // So, for systems without getaddrinfo (which is thread-safe), we lock the mutex too + QMutexLocker locker(::getHostByNameMutex()); +#endif + local_res_init(); + QString domainName = QUrl::fromAce(local_res->defdname); + if (domainName.isEmpty()) + domainName = QUrl::fromAce(local_res->dnsrch[0]); + return domainName; + } +#endif + // nothing worked, try doing it by ourselves: + QFile resolvconf; +#if defined(_PATH_RESCONF) + resolvconf.setFileName(QFile::decodeName(_PATH_RESCONF)); +#else + resolvconf.setFileName(QLatin1String("/etc/resolv.conf")); +#endif + if (!resolvconf.open(QIODevice::ReadOnly)) + return QString(); // failure + + QString domainName; + while (!resolvconf.atEnd()) { + QByteArray line = resolvconf.readLine().trimmed(); + if (line.startsWith("domain ")) + return QUrl::fromAce(line.mid(sizeof "domain " - 1).trimmed()); + + // in case there's no "domain" line, fall back to the first "search" entry + if (domainName.isEmpty() && line.startsWith("search ")) { + QByteArray searchDomain = line.mid(sizeof "search " - 1).trimmed(); + int pos = searchDomain.indexOf(' '); + if (pos != -1) + searchDomain.truncate(pos); + domainName = QUrl::fromAce(searchDomain); + } + } + + // return the fallen-back-to searched domain + return domainName; +} + +QT_END_NAMESPACE -- cgit v0.12 From 5c75d5bed133a4cd77329b5e90d1f47f86f92a17 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 10:01:08 +0100 Subject: Weed out old unix code from qhostinfo_symbian.cpp --- src/network/kernel/qhostinfo_symbian.cpp | 322 +------------------------------ 1 file changed, 9 insertions(+), 313 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 5ca15a3..2e1e6ca 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -44,82 +44,9 @@ #include "qplatformdefs.h" #include "qhostinfo_p.h" -#include "private/qnativesocketengine_p.h" -#include "qiodevice.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#if defined(Q_OS_VXWORKS) -# include -#else -# include -#endif - -#if defined (QT_NO_GETADDRINFO) -#include -QT_BEGIN_NAMESPACE -Q_GLOBAL_STATIC(QMutex, getHostByNameMutex) -QT_END_NAMESPACE -#endif QT_BEGIN_NAMESPACE -// Almost always the same. If not, specify in qplatformdefs.h. -#if !defined(QT_SOCKOPTLEN_T) -# define QT_SOCKOPTLEN_T QT_SOCKLEN_T -#endif - -// HP-UXi has a bug in getaddrinfo(3) that makes it thread-unsafe -// with this flag. So disable it in that platform. -#if defined(AI_ADDRCONFIG) && !defined(Q_OS_HPUX) -# define Q_ADDRCONFIG AI_ADDRCONFIG -#endif - -typedef struct __res_state *res_state_ptr; - -typedef int (*res_init_proto)(void); -static res_init_proto local_res_init = 0; -typedef int (*res_ninit_proto)(res_state_ptr); -static res_ninit_proto local_res_ninit = 0; -typedef void (*res_nclose_proto)(res_state_ptr); -static res_nclose_proto local_res_nclose = 0; -static res_state_ptr local_res = 0; - -static void resolveLibrary() -{ -#ifndef QT_NO_LIBRARY - QLibrary lib(QLatin1String("resolv")); - if (!lib.load()) - return; - - local_res_init = res_init_proto(lib.resolve("__res_init")); - if (!local_res_init) - local_res_init = res_init_proto(lib.resolve("res_init")); - - local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit")); - if (!local_res_ninit) - local_res_ninit = res_ninit_proto(lib.resolve("res_ninit")); - - if (!local_res_ninit) { - // if we can't get a thread-safe context, we have to use the global _res state - local_res = res_state_ptr(lib.resolve("_res")); - } else { - local_res_nclose = res_nclose_proto(lib.resolve("res_nclose")); - if (!local_res_nclose) - local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose")); - if (!local_res_nclose) - local_res_ninit = 0; - } -#endif -} - QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; @@ -129,60 +56,11 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) hostName.toLatin1().constData()); #endif - // Load res_init on demand. - static volatile bool triedResolve = false; - if (!triedResolve) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); - if (!triedResolve) { - resolveLibrary(); - triedResolve = true; - } - } - - // If res_init is available, poll it. - if (local_res_init) - local_res_init(); - QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup -// Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. -#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) && !defined (Q_OS_SYMBIAN) - sockaddr_in sa4; -#ifndef QT_NO_IPV6 - sockaddr_in6 sa6; -#endif - sockaddr *sa = 0; - QT_SOCKLEN_T saSize = 0; - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - sa = (sockaddr *)&sa4; - saSize = sizeof(sa4); - memset(&sa4, 0, sizeof(sa4)); - sa4.sin_family = AF_INET; - sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); - } -#ifndef QT_NO_IPV6 - else { - sa = (sockaddr *)&sa6; - saSize = sizeof(sa6); - memset(&sa6, 0, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); - } -#endif - - char hbuf[NI_MAXHOST]; - if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) - results.setHostName(QString::fromLatin1(hbuf)); -#else - in_addr_t inetaddr = qt_safe_inet_addr(hostName.toLatin1().constData()); - struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET); - if (ent) - results.setHostName(QString::fromLatin1(ent->h_name)); -#endif - - if (results.hostName().isEmpty()) - results.setHostName(address.toString()); + // TODO + results.setHostName("assume.it.works"); results.setAddresses(QList() << address); return results; } @@ -198,210 +76,28 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } -#if !defined (QT_NO_GETADDRINFO) // Call getaddrinfo, and place all IPv4 addresses at the start and // the IPv6 addresses at the end of the address list in results. - addrinfo *res = 0; - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; -#ifdef Q_ADDRCONFIG - hints.ai_flags = Q_ADDRCONFIG; -#endif -#ifdef Q_OS_SYMBIAN -# ifdef QHOSTINFO_DEBUG - qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'"; -# endif -#endif - - int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); -# ifdef Q_ADDRCONFIG - if (result == EAI_BADFLAGS) { - // if the lookup failed with AI_ADDRCONFIG set, try again without it - hints.ai_flags = 0; -#ifdef Q_OS_SYMBIAN -# ifdef QHOSTINFO_DEBUG - qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'"; -# endif - hints.ai_flags &= AI_V4MAPPED | AI_ALL; -#endif - result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); - } -# endif - - if (result == 0) { - addrinfo *node = res; - QList addresses; - while (node) { -#ifdef QHOSTINFO_DEBUG - qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen; -#endif - if (node->ai_family == AF_INET) { - QHostAddress addr; - addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); - if (!addresses.contains(addr)) - addresses.append(addr); - } -#ifndef QT_NO_IPV6 - else if (node->ai_family == AF_INET6) { - QHostAddress addr; - sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; - addr.setAddress(sa6->sin6_addr.s6_addr); - if (sa6->sin6_scope_id) - addr.setScopeId(QString::number(sa6->sin6_scope_id)); - if (!addresses.contains(addr)) - addresses.append(addr); - } -#endif - node = node->ai_next; - } - if (addresses.isEmpty() && node == 0) { - // Reached the end of the list, but no addresses were found; this - // means the list contains one or more unknown address types. - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown address type")); - } - - results.setAddresses(addresses); - freeaddrinfo(res); - } else if (result == EAI_NONAME - || result == EAI_FAIL -#ifdef EAI_NODATA - // EAI_NODATA is deprecated in RFC 3493 - || result == EAI_NODATA -#endif - ) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(tr("Host not found")); + /* + results.setError(QHostInfo::HostNotFound); + results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); } - -#else - // Fall back to gethostbyname for platforms that don't define - // getaddrinfo. gethostbyname does not support IPv6, and it's not - // reentrant on all platforms. For now this is okay since we only - // use one QHostInfoAgent, but if more agents are introduced, locking - // must be provided. - QMutexLocker locker(::getHostByNameMutex()); - hostent *result = gethostbyname(aceHostname.constData()); - if (result) { - if (result->h_addrtype == AF_INET) { - QList addresses; - for (char **p = result->h_addr_list; *p != 0; p++) { - QHostAddress addr; - addr.setAddress(ntohl(*((quint32 *)*p))); - if (!addresses.contains(addr)) - addresses.prepend(addr); - } - results.setAddresses(addresses); - } else { - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown address type")); - } -#if !defined(Q_OS_VXWORKS) - } else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA - || h_errno == NO_ADDRESS) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(tr("Host not found")); -#endif - } else { - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown error")); - } -#endif // !defined (QT_NO_GETADDRINFO) - -#if defined(QHOSTINFO_DEBUG) - if (results.error() != QHostInfo::NoError) { - qDebug("QHostInfoAgent::fromName(): error #%d %s", - h_errno, results.errorString().toLatin1().constData()); - } else { - QString tmp; - QList addresses = results.addresses(); - for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += ", "; - tmp += addresses.at(i).toString(); - } - qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", - addresses.count(), hostName.toLatin1().constData(), - tmp.toLatin1().constData()); - } -#endif + */ + return results; } QString QHostInfo::localHostName() { - char hostName[512]; - if (gethostname(hostName, sizeof(hostName)) == -1) - return QString(); - hostName[sizeof(hostName) - 1] = '\0'; - return QString::fromLocal8Bit(hostName); + return QString() } QString QHostInfo::localDomainName() { -#if !defined(Q_OS_VXWORKS) - resolveLibrary(); - if (local_res_ninit) { - // using thread-safe version - res_state_ptr state = res_state_ptr(qMalloc(sizeof(*state))); - Q_CHECK_PTR(state); - memset(state, 0, sizeof(*state)); - local_res_ninit(state); - QString domainName = QUrl::fromAce(state->defdname); - if (domainName.isEmpty()) - domainName = QUrl::fromAce(state->dnsrch[0]); - local_res_nclose(state); - qFree(state); - - return domainName; - } - - if (local_res_init && local_res) { - // using thread-unsafe version - -#if defined(QT_NO_GETADDRINFO) - // We have to call res_init to be sure that _res was initialized - // So, for systems without getaddrinfo (which is thread-safe), we lock the mutex too - QMutexLocker locker(::getHostByNameMutex()); -#endif - local_res_init(); - QString domainName = QUrl::fromAce(local_res->defdname); - if (domainName.isEmpty()) - domainName = QUrl::fromAce(local_res->dnsrch[0]); - return domainName; - } -#endif - // nothing worked, try doing it by ourselves: - QFile resolvconf; -#if defined(_PATH_RESCONF) - resolvconf.setFileName(QFile::decodeName(_PATH_RESCONF)); -#else - resolvconf.setFileName(QLatin1String("/etc/resolv.conf")); -#endif - if (!resolvconf.open(QIODevice::ReadOnly)) - return QString(); // failure - - QString domainName; - while (!resolvconf.atEnd()) { - QByteArray line = resolvconf.readLine().trimmed(); - if (line.startsWith("domain ")) - return QUrl::fromAce(line.mid(sizeof "domain " - 1).trimmed()); - - // in case there's no "domain" line, fall back to the first "search" entry - if (domainName.isEmpty() && line.startsWith("search ")) { - QByteArray searchDomain = line.mid(sizeof "search " - 1).trimmed(); - int pos = searchDomain.indexOf(' '); - if (pos != -1) - searchDomain.truncate(pos); - domainName = QUrl::fromAce(searchDomain); - } - } - - // return the fallen-back-to searched domain - return domainName; + return QString(); } QT_END_NAMESPACE -- cgit v0.12 From 2533c00db1851e712b036329d6cc7562fe106da1 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 10:50:45 +0100 Subject: Added qnetworkproxy_symbian.cpp --- src/network/kernel/kernel.pri | 1 + src/network/kernel/qnetworkproxy_symbian.cpp | 61 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/network/kernel/qnetworkproxy_symbian.cpp diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index ccc113c..8aeb5c2 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -27,5 +27,6 @@ win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation mac:SOURCES += kernel/qnetworkproxy_mac.cpp else:win32:SOURCES += kernel/qnetworkproxy_win.cpp +else:symbian:SOURCES += kernel/qnetworkproxy_symbian.cpp else:SOURCES += kernel/qnetworkproxy_generic.cpp diff --git a/src/network/kernel/qnetworkproxy_symbian.cpp b/src/network/kernel/qnetworkproxy_symbian.cpp new file mode 100644 index 0000000..7eba2c2 --- /dev/null +++ b/src/network/kernel/qnetworkproxy_symbian.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnetworkproxy.h" + +#ifndef QT_NO_NETWORKPROXY + +QT_BEGIN_NAMESPACE + +QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &) +{ + // TODO: Get the current QNetworkSession which has the Symbian RConnection we use + + // TODO: Get the proxy from that RConnection + + + // Default case: No network proxy found/needed + return QList() << QNetworkProxy::NoProxy; +} + +QT_END_NAMESPACE + +#endif -- cgit v0.12 From 0ce754850de6473bc0df1918d76a9b127b445260 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 11:01:30 +0100 Subject: Some more qnetworkproxy_symbian information --- src/network/kernel/qnetworkproxy_symbian.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/network/kernel/qnetworkproxy_symbian.cpp b/src/network/kernel/qnetworkproxy_symbian.cpp index 7eba2c2..62266d1 100644 --- a/src/network/kernel/qnetworkproxy_symbian.cpp +++ b/src/network/kernel/qnetworkproxy_symbian.cpp @@ -48,9 +48,14 @@ QT_BEGIN_NAMESPACE QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &) { // TODO: Get the current QNetworkSession which has the Symbian RConnection we use + // I am wondering if we already have a connected QNetworkSession when the code + // is run that retrieves the proxy (for QNetworkAccessManager it's somewhere called + // from createRequest() which might be too early...) // TODO: Get the proxy from that RConnection + // See http://bugreports.qt.nokia.com/browse/QTBUG-13857 and http://bugreports.qt.nokia.com/browse/QTBUG-11016 + // and the mails we have received. // Default case: No network proxy found/needed return QList() << QNetworkProxy::NoProxy; -- cgit v0.12 From 7dce8f9b28288b95daf0e8fd1016b8b75bccc61c Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 12:12:48 +0100 Subject: QTestLib: Wait a bit on Symbian at exit Reviewed-by: Shane Kearns --- src/testlib/qabstracttestlogger.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp index f7269d6..a23638e 100644 --- a/src/testlib/qabstracttestlogger.cpp +++ b/src/testlib/qabstracttestlogger.cpp @@ -104,8 +104,16 @@ void QAbstractTestLogger::startLogging() void QAbstractTestLogger::stopLogging() { QTEST_ASSERT(QTest::stream); - if (QTest::stream != stdout) + if (QTest::stream != stdout) { fclose(QTest::stream); + } else { +#ifdef Q_OS_SYMBIAN + // Convenience sleep for Symbian and TRK. Without this sleep depending on the timing the + // user would not see the complete output because it is still pending in any of the buffers + // before arriving via the USB port on the development PC + User::AfterHighRes(2*1000*1000); +#endif + } QTest::stream = 0; } -- cgit v0.12 From 2b60cdf7b0c17372cbeb32e3eac1e18c0baea0e4 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 15:50:05 +0100 Subject: Move qnativesocketengine_symbian* to QSymbianSocketEngine Reviewed-By: Shane Kearns --- src/network/socket/qnativesocketengine_symbian.cpp | 806 --------------------- src/network/socket/qsymbiansocketengine.cpp | 806 +++++++++++++++++++++ src/network/socket/qsymbiansocketengine_p.h | 289 ++++++++ src/network/socket/socket.pri | 5 +- 4 files changed, 1099 insertions(+), 807 deletions(-) delete mode 100644 src/network/socket/qnativesocketengine_symbian.cpp create mode 100644 src/network/socket/qsymbiansocketengine.cpp create mode 100644 src/network/socket/qsymbiansocketengine_p.h diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp deleted file mode 100644 index cfaee03..0000000 --- a/src/network/socket/qnativesocketengine_symbian.cpp +++ /dev/null @@ -1,806 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//#define QNATIVESOCKETENGINE_DEBUG -#include "qnativesocketengine_p.h" -#include "private/qnet_unix_p.h" -#include "qiodevice.h" -#include "qhostaddress.h" -#include "qelapsedtimer.h" -#include "qvarlengtharray.h" -#include "qnetworkinterface.h" -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -#define QNATIVESOCKETENGINE_DEBUG - -#if defined QNATIVESOCKETENGINE_DEBUG -#include -#include -#endif - -QT_BEGIN_NAMESPACE - -#if defined QNATIVESOCKETENGINE_DEBUG - -/* - Returns a human readable representation of the first \a len - characters in \a data. -*/ -static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) -{ - if (!data) return "(null)"; - QByteArray out; - for (int i = 0; i < len; ++i) { - char c = data[i]; - if (isprint(c)) { - out += c; - } else switch (c) { - case '\n': out += "\\n"; break; - case '\r': out += "\\r"; break; - case '\t': out += "\\t"; break; - default: - QString tmp; - tmp.sprintf("\\%o", c); - out += tmp.toLatin1(); - } - } - - if (len < maxSize) - out += "..."; - - return out; -} -#endif - -void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) -{ -#if !defined(QT_NO_IPV6) - if (a.Family() == KAfInet6) { - Q_IPV6ADDR tmp; - memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp)); - if (addr) { - QHostAddress tmpAddress; - tmpAddress.setAddress(tmp); - *addr = tmpAddress; -#ifndef QT_NO_IPV6IFNAME - TPckgBuf query; - query().iSrcAddr = a; - TInt err = nativeSocket.GetOpt(KSoInetIfQueryBySrcAddr, KSolInetIfQuery, query); - if(!err) - addr->setScopeId(qt_TDesC2QString(query().iName)); - else -#endif - addr->setScopeId(QString::number(a.Scope())); - } - if (port) - *port = a.Port(); - return; - } -#endif - if (port) - *port = a.Port(); - if (addr) { - QHostAddress tmpAddress; - tmpAddress.setAddress(a.Address()); - *addr = tmpAddress; - } -} -/*! \internal - - Creates and returns a new socket descriptor of type \a socketType - and \a socketProtocol. Returns -1 on failure. -*/ -bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, - QAbstractSocket::NetworkLayerProtocol socketProtocol) -{ -#ifndef QT_NO_IPV6 - TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet; -#else - Q_UNUSED(socketProtocol); - TUint family = KAfInet; -#endif - TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; - TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; - TInt err = nativeSocket.Open(socketServer, family, type, protocol, connection); - - if (err != KErrNone) { - switch (err) { - case KErrNotSupported: - case KErrNotFound: - setError(QAbstractSocket::UnsupportedSocketOperationError, - ProtocolUnsupportedErrorString); - break; - case KErrNoMemory: - setError(QAbstractSocket::SocketResourceError, ResourceErrorString); - break; - case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AccessErrorString); - break; - default: - break; - } - - return false; - } - // FIXME Set socket to nonblocking. While we are still a QNativeSocketEngine this is done already. - // Uncomment the following when we switch to QSymbianSocketEngine. - // setOption(NonBlockingSocketOption, 1) - - socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket); - return true; -} - -/* - Returns the value of the socket option \a opt. -*/ -int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const -{ - Q_Q(const QNativeSocketEngine); - if (!q->isValid()) - return -1; - - TUint n; - TUint level = KSOLSocket; // default - - switch (opt) { - case QNativeSocketEngine::ReceiveBufferSocketOption: - n = KSORecvBuf; - break; - case QNativeSocketEngine::SendBufferSocketOption: - n = KSOSendBuf; - break; - case QNativeSocketEngine::NonBlockingSocketOption: - n = KSONonBlockingIO; - break; - case QNativeSocketEngine::BroadcastSocketOption: - return true; //symbian doesn't support or require this option - case QNativeSocketEngine::AddressReusable: - level = KSolInetIp; - n = KSoReuseAddr; - break; - case QNativeSocketEngine::BindExclusively: - return true; - case QNativeSocketEngine::ReceiveOutOfBandData: - level = KSolInetTcp; - n = KSoTcpOobInline; - break; - case QNativeSocketEngine::LowDelayOption: - level = KSolInetTcp; - n = KSoTcpNoDelay; - break; - case QNativeSocketEngine::KeepAliveOption: - level = KSolInetTcp; - n = KSoTcpKeepAlive; - break; - default: - return -1; - } - - int v = -1; - //GetOpt() is non const - TInt err = nativeSocket.GetOpt(n, level, v); - if (!err) - return v; - - return -1; -} - - -/* - 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 = KSORecvBuf; - break; - case QNativeSocketEngine::SendBufferSocketOption: - n = KSOSendBuf; - break; - case QNativeSocketEngine::BroadcastSocketOption: - return true; - case QNativeSocketEngine::NonBlockingSocketOption: - n = KSONonBlockingIO; - break; - case QNativeSocketEngine::AddressReusable: - level = KSolInetIp; - n = KSoReuseAddr; - break; - case QNativeSocketEngine::BindExclusively: - return true; - case QNativeSocketEngine::ReceiveOutOfBandData: - level = KSolInetTcp; - n = KSoTcpOobInline; - break; - case QNativeSocketEngine::LowDelayOption: - level = KSolInetTcp; - n = KSoTcpNoDelay; - break; - case QNativeSocketEngine::KeepAliveOption: - level = KSolInetTcp; - n = KSoTcpKeepAlive; - break; - } - - return (KErrNone == nativeSocket.SetOpt(n, level, v)); -} - -void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) -{ - nativeAddr.SetPort(port); -#if !defined(QT_NO_IPV6) - if (addr.protocol() == QAbstractSocket::IPv6Protocol) { -#ifndef QT_NO_IPV6IFNAME - TPckgBuf query; - query().iName = qt_QString2TPtrC(addr.scopeId()); - TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); - if(!err) - nativeAddr.SetScope(query().iIndex); - else - nativeAddr.SetScope(0); -#else - nativeAddr.SetScope(addr.scopeId().toInt()); -#endif - Q_IPV6ADDR ip6 = addr.toIPv6Address(); - TIp6Addr v6addr; - memcpy(v6addr.u.iAddr8, ip6.c, 16); - nativeAddr.SetAddress(v6addr); - } else -#endif - if (addr.protocol() == QAbstractSocket::IPv4Protocol) { - nativeAddr.SetAddress(addr.toIPv4Address()); - } else { - qWarning("unsupported network protocol (%d)", addr.protocol()); - } -} - -bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) -{ -#ifdef QNATIVESOCKETENGINE_DEBUG - qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); -#endif - - TInetAddr nativeAddr; - setPortAndAddress(nativeAddr, port, addr); - //TODO: async connect with active object - from here to end of function is a mess - TRequestStatus status; - nativeSocket.Connect(nativeAddr, status); - User::WaitForRequest(status); - TInt err = status.Int(); - if (err) { - switch (err) { - case KErrCouldNotConnect: - setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case KErrTimedOut: - setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); - break; - case KErrHostUnreach: - setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case KErrNetUnreach: - setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case KErrInUse: - setError(QAbstractSocket::NetworkError, AddressInuseErrorString); - break; - case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AccessErrorString); - socketState = QAbstractSocket::UnconnectedState; - break; - case KErrNotSupported: - case KErrBadDescriptor: - 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; -} - -bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) -{ - TInetAddr nativeAddr; - setPortAndAddress(nativeAddr, port, address); - - TInt err = nativeSocket.Bind(nativeAddr); - - if (err) { - switch(errno) { - case KErrInUse: - setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); - break; - case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); - break; - case KErrNotSupported: - setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); - break; - default: - break; - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", - address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData()); -#endif - - return false; - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true", - address.toString().toLatin1().constData(), port); -#endif - socketState = QAbstractSocket::BoundState; - return true; -} - -bool QNativeSocketEnginePrivate::nativeListen(int backlog) -{ - TInt err = nativeSocket.Listen(backlog); - if (err) { - switch (errno) { - case KErrInUse: - setError(QAbstractSocket::AddressInUseError, - PortInuseErrorString); - break; - default: - break; - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)", - backlog, socketErrorString.toLatin1().constData()); -#endif - return false; - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog); -#endif - - socketState = QAbstractSocket::ListeningState; - return true; -} - -int QNativeSocketEnginePrivate::nativeAccept() -{ - RSocket blankSocket; - //TODO: this is unbelievably broken, needs to be properly async - blankSocket.Open(socketServer); - TRequestStatus status; - nativeSocket.Accept(blankSocket, status); - User::WaitForRequest(status); - if(status.Int()) { - qWarning("QNativeSocketEnginePrivate::nativeAccept() - error %d", status.Int()); - return 0; - } - // FIXME Qt Handle of new socket must be retrieved from QSymbianSocketManager - // and then returned. Not the SubSessionHandle! Also set the socket to nonblocking. - return blankSocket.SubSessionHandle(); -} - -qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const -{ - int nbytes = 0; - qint64 available = 0; - // FIXME is this the right thing also for UDP? - // What is expected for UDP, the length for the next packet I guess? - TInt err = nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); - if(err) - return 0; - available = (qint64) nbytes; - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available); -#endif - return available; -} - -bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const -{ - int nbytes; - TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); - return err == KErrNone && nbytes > 0; - //TODO: this is pretty horrible too... -} - -qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const -{ - int nbytes; - TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); - return qint64(nbytes-28); //TODO: why -28 (open C version had this)? - // Why = Could it be that this is about header lengths etc? if yes - // this could be pretty broken, especially for IPv6 -} - -qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, - QHostAddress *address, quint16 *port) -{ - TPtr8 buffer((TUint8*)data, (int)maxSize); - TInetAddr addr; - TRequestStatus status; //TODO: OMG sync receive! - nativeSocket.RecvFrom(buffer, addr, 0, status); - User::WaitForRequest(status); - - if (status.Int()) { - setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); - } else if (port || address) { - getPortAndAddress(addr, port, address); - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - int len = buffer.Length(); - qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", - data, qt_prettyDebug(data, qMin(len, ssize_t(16)), len).data(), maxSize, - address ? address->toString().toLatin1().constData() : "(nil)", - port ? *port : 0, (qint64) len); -#endif - - if (status.Int()) - return -1; - return qint64(buffer.Length()); -} - -qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, - const QHostAddress &host, quint16 port) -{ - TPtrC8 buffer((TUint8*)data, (int)len); - TInetAddr addr; - setPortAndAddress(addr, port, host); - TSockXfrLength sentBytes; - TRequestStatus status; //TODO: OMG sync send! - nativeSocket.SendTo(buffer, addr, 0, status, sentBytes); - User::WaitForRequest(status); - TInt err = status.Int(); - - if (err) { - switch (err) { - case KErrTooBig: - setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); - break; - default: - setError(QAbstractSocket::NetworkError, SendDatagramErrorString); - } - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, - qt_prettyDebug(data, qMin(len, 16), len).data(), len, host.toString().toLatin1().constData(), - port, (qint64) sentBytes()); -#endif - - return qint64(sentBytes()); -} - -bool QNativeSocketEnginePrivate::fetchConnectionParameters() -{ - localPort = 0; - localAddress.clear(); - peerPort = 0; - peerAddress.clear(); - - if (socketDescriptor == -1) - return false; - - if (!nativeSocket.SubSessionHandle()) { - if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket)) - return false; - } - - // Determine local address - TSockAddr addr; - nativeSocket.LocalName(addr); - getPortAndAddress(addr, &localPort, &localAddress); - - // Determine protocol family - switch (addr.Family()) { - case KAfInet: - socketProtocol = QAbstractSocket::IPv4Protocol; - break; -#if !defined (QT_NO_IPV6) - case KAfInet6: - socketProtocol = QAbstractSocket::IPv6Protocol; - break; -#endif - default: - socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol; - break; - } - - // Determine the remote address - nativeSocket.RemoteName(addr); - getPortAndAddress(addr, &peerPort, &peerAddress); - - // Determine the socket type (UDP/TCP) - TProtocolDesc protocol; - TInt err = nativeSocket.Info(protocol); - if (err) { - QAbstractSocket::UnknownSocketType; - } else { - switch (protocol.iProtocol) { - case KProtocolInetTcp: - socketType = QAbstractSocket::TcpSocket; - break; - case KProtocolInetUdp: - socketType = QAbstractSocket::UdpSocket; - break; - default: - socketType = QAbstractSocket::UnknownSocketType; - break; - } - } -#if defined (QNATIVESOCKETENGINE_DEBUG) - QString socketProtocolStr = "UnknownProtocol"; - if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol"; - else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol"; - - QString socketTypeStr = "UnknownSocketType"; - if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket"; - else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket"; - - qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i," - " peer == %s:%i, socket == %s - %s", - localAddress.toString().toLatin1().constData(), localPort, - peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(), - socketProtocolStr.toLatin1().constData()); -#endif - return true; -} - -void QNativeSocketEnginePrivate::nativeClose() -{ -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEngine::nativeClose()"); -#endif - - //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? - nativeSocket.Close(); - QSymbianSocketManager::instance().removeSocket(nativeSocket); -} - -qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) -{ - Q_Q(QNativeSocketEngine); - TPtrC8 buffer((TUint8*)data, (int)len); - TSockXfrLength sentBytes; - TRequestStatus status; //TODO: OMG sync send! - nativeSocket.Send(buffer, 0, status, sentBytes); - User::WaitForRequest(status); - TInt err = status.Int(); - - if (err) { - switch (err) { - case KErrDisconnected: - sentBytes = -1; - setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); - q->close(); - break; - case KErrTooBig: - setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); - break; - case KErrWouldBlock: - sentBytes = 0; - default: - setError(QAbstractSocket::NetworkError, SendDatagramErrorString); - } - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", - data, qt_prettyDebug(data, qMin((int) len, 16), - (int) len).data(), len, (int) sentBytes()); -#endif - - return qint64(sentBytes()); -} -/* -*/ -qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) -{ - Q_Q(QNativeSocketEngine); - if (!q->isValid()) { - qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); - return -1; - } - - TPtr8 buffer((TUint8*)data, (int)maxSize); - TSockXfrLength received = 0; - TRequestStatus status; //TODO: OMG sync receive! - nativeSocket.RecvOneOrMore(buffer, 0, status, received); - User::WaitForRequest(status); - TInt err = status.Int(); - int r = received(); - - if (err) { - switch(err) { - case KErrWouldBlock: - // No data was available for reading - r = -2; - break; - case KErrDisconnected: - r = 0; - break; - default: - r = -1; - //error string is now set in read(), not here in nativeRead() - break; - } - } - -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", - data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), - maxSize, r); -#endif - - return qint64(r); -} - -int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const -{ - bool readyRead = false; - bool readyWrite = false; - if (selectForRead) - return nativeSelect(timeout, true, false, &readyRead, &readyWrite); - else - return nativeSelect(timeout, false, true, &readyRead, &readyWrite); -} - -/*! - \internal - \param timeout timeout in milliseconds - \param checkRead caller is interested if the socket is ready to read - \param checkWrite caller is interested if the socket is ready for write - \param selectForRead (out) should set to true if ready to read - \param selectForWrite (out) should set to true if ready to write - \return 0 on timeout, >0 on success, <0 on error - */ -int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, - bool *selectForRead, bool *selectForWrite) const -{ - //TODO: implement - //as above, but checking both read and write status at the same time - if (!selectTimer.Handle()) - qt_symbian_throwIfError(selectTimer.CreateLocal()); - TRequestStatus timerStat; - selectTimer.HighRes(timerStat, timeout * 1000); - TRequestStatus* readStat = 0; - TRequestStatus* writeStat = 0; - TRequestStatus* array[3]; - array[0] = &timerStat; - int count = 1; - if (checkRead) { - //TODO: get from read AO - //readStat = ? - array[count++] = readStat; - } - if (checkWrite) { - //TODO: get from write AO - //writeStat = ? - array[count++] = writeStat; - } - // TODO: for selecting, we can use getOpt(KSOSelectPoll) to get the select result - // and KIOCtlSelect for the selecting. - - User::WaitForNRequest(array, count); - //IMPORTANT - WaitForNRequest only decrements the thread semaphore once, although more than one status may have completed. - if (timerStat.Int() != KRequestPending) { - //timed out - return 0; - } - selectTimer.Cancel(); - User::WaitForRequest(timerStat); - - if(readStat && readStat->Int() != KRequestPending) { - Q_ASSERT(checkRead && selectForRead); - //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive() - *selectForRead = true; - } - if(writeStat && writeStat->Int() != KRequestPending) { - Q_ASSERT(checkWrite && selectForWrite); - //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive() - *selectForWrite = true; - } - return 1; -} - -bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface) -{ - //TODO - return false; -} - -bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface) -{ - //TODO - return false; -} - -QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const -{ - //TODO - return QNetworkInterface(); -} - -bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) -{ - //TODO - return false; -} - -QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp new file mode 100644 index 0000000..cfaee03 --- /dev/null +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -0,0 +1,806 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//#define QNATIVESOCKETENGINE_DEBUG +#include "qnativesocketengine_p.h" +#include "private/qnet_unix_p.h" +#include "qiodevice.h" +#include "qhostaddress.h" +#include "qelapsedtimer.h" +#include "qvarlengtharray.h" +#include "qnetworkinterface.h" +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +#define QNATIVESOCKETENGINE_DEBUG + +#if defined QNATIVESOCKETENGINE_DEBUG +#include +#include +#endif + +QT_BEGIN_NAMESPACE + +#if defined QNATIVESOCKETENGINE_DEBUG + +/* + Returns a human readable representation of the first \a len + characters in \a data. +*/ +static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) +{ + if (!data) return "(null)"; + QByteArray out; + for (int i = 0; i < len; ++i) { + char c = data[i]; + if (isprint(c)) { + out += c; + } else switch (c) { + case '\n': out += "\\n"; break; + case '\r': out += "\\r"; break; + case '\t': out += "\\t"; break; + default: + QString tmp; + tmp.sprintf("\\%o", c); + out += tmp.toLatin1(); + } + } + + if (len < maxSize) + out += "..."; + + return out; +} +#endif + +void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) +{ +#if !defined(QT_NO_IPV6) + if (a.Family() == KAfInet6) { + Q_IPV6ADDR tmp; + memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp)); + if (addr) { + QHostAddress tmpAddress; + tmpAddress.setAddress(tmp); + *addr = tmpAddress; +#ifndef QT_NO_IPV6IFNAME + TPckgBuf query; + query().iSrcAddr = a; + TInt err = nativeSocket.GetOpt(KSoInetIfQueryBySrcAddr, KSolInetIfQuery, query); + if(!err) + addr->setScopeId(qt_TDesC2QString(query().iName)); + else +#endif + addr->setScopeId(QString::number(a.Scope())); + } + if (port) + *port = a.Port(); + return; + } +#endif + if (port) + *port = a.Port(); + if (addr) { + QHostAddress tmpAddress; + tmpAddress.setAddress(a.Address()); + *addr = tmpAddress; + } +} +/*! \internal + + Creates and returns a new socket descriptor of type \a socketType + and \a socketProtocol. Returns -1 on failure. +*/ +bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, + QAbstractSocket::NetworkLayerProtocol socketProtocol) +{ +#ifndef QT_NO_IPV6 + TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet; +#else + Q_UNUSED(socketProtocol); + TUint family = KAfInet; +#endif + TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; + TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; + TInt err = nativeSocket.Open(socketServer, family, type, protocol, connection); + + if (err != KErrNone) { + switch (err) { + case KErrNotSupported: + case KErrNotFound: + setError(QAbstractSocket::UnsupportedSocketOperationError, + ProtocolUnsupportedErrorString); + break; + case KErrNoMemory: + setError(QAbstractSocket::SocketResourceError, ResourceErrorString); + break; + case KErrPermissionDenied: + setError(QAbstractSocket::SocketAccessError, AccessErrorString); + break; + default: + break; + } + + return false; + } + // FIXME Set socket to nonblocking. While we are still a QNativeSocketEngine this is done already. + // Uncomment the following when we switch to QSymbianSocketEngine. + // setOption(NonBlockingSocketOption, 1) + + socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket); + return true; +} + +/* + Returns the value of the socket option \a opt. +*/ +int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const +{ + Q_Q(const QNativeSocketEngine); + if (!q->isValid()) + return -1; + + TUint n; + TUint level = KSOLSocket; // default + + switch (opt) { + case QNativeSocketEngine::ReceiveBufferSocketOption: + n = KSORecvBuf; + break; + case QNativeSocketEngine::SendBufferSocketOption: + n = KSOSendBuf; + break; + case QNativeSocketEngine::NonBlockingSocketOption: + n = KSONonBlockingIO; + break; + case QNativeSocketEngine::BroadcastSocketOption: + return true; //symbian doesn't support or require this option + case QNativeSocketEngine::AddressReusable: + level = KSolInetIp; + n = KSoReuseAddr; + break; + case QNativeSocketEngine::BindExclusively: + return true; + case QNativeSocketEngine::ReceiveOutOfBandData: + level = KSolInetTcp; + n = KSoTcpOobInline; + break; + case QNativeSocketEngine::LowDelayOption: + level = KSolInetTcp; + n = KSoTcpNoDelay; + break; + case QNativeSocketEngine::KeepAliveOption: + level = KSolInetTcp; + n = KSoTcpKeepAlive; + break; + default: + return -1; + } + + int v = -1; + //GetOpt() is non const + TInt err = nativeSocket.GetOpt(n, level, v); + if (!err) + return v; + + return -1; +} + + +/* + 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 = KSORecvBuf; + break; + case QNativeSocketEngine::SendBufferSocketOption: + n = KSOSendBuf; + break; + case QNativeSocketEngine::BroadcastSocketOption: + return true; + case QNativeSocketEngine::NonBlockingSocketOption: + n = KSONonBlockingIO; + break; + case QNativeSocketEngine::AddressReusable: + level = KSolInetIp; + n = KSoReuseAddr; + break; + case QNativeSocketEngine::BindExclusively: + return true; + case QNativeSocketEngine::ReceiveOutOfBandData: + level = KSolInetTcp; + n = KSoTcpOobInline; + break; + case QNativeSocketEngine::LowDelayOption: + level = KSolInetTcp; + n = KSoTcpNoDelay; + break; + case QNativeSocketEngine::KeepAliveOption: + level = KSolInetTcp; + n = KSoTcpKeepAlive; + break; + } + + return (KErrNone == nativeSocket.SetOpt(n, level, v)); +} + +void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) +{ + nativeAddr.SetPort(port); +#if !defined(QT_NO_IPV6) + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { +#ifndef QT_NO_IPV6IFNAME + TPckgBuf query; + query().iName = qt_QString2TPtrC(addr.scopeId()); + TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); + if(!err) + nativeAddr.SetScope(query().iIndex); + else + nativeAddr.SetScope(0); +#else + nativeAddr.SetScope(addr.scopeId().toInt()); +#endif + Q_IPV6ADDR ip6 = addr.toIPv6Address(); + TIp6Addr v6addr; + memcpy(v6addr.u.iAddr8, ip6.c, 16); + nativeAddr.SetAddress(v6addr); + } else +#endif + if (addr.protocol() == QAbstractSocket::IPv4Protocol) { + nativeAddr.SetAddress(addr.toIPv4Address()); + } else { + qWarning("unsupported network protocol (%d)", addr.protocol()); + } +} + +bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) +{ +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); +#endif + + TInetAddr nativeAddr; + setPortAndAddress(nativeAddr, port, addr); + //TODO: async connect with active object - from here to end of function is a mess + TRequestStatus status; + nativeSocket.Connect(nativeAddr, status); + User::WaitForRequest(status); + TInt err = status.Int(); + if (err) { + switch (err) { + case KErrCouldNotConnect: + setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); + socketState = QAbstractSocket::UnconnectedState; + break; + case KErrTimedOut: + setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); + break; + case KErrHostUnreach: + setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); + socketState = QAbstractSocket::UnconnectedState; + break; + case KErrNetUnreach: + setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); + socketState = QAbstractSocket::UnconnectedState; + break; + case KErrInUse: + setError(QAbstractSocket::NetworkError, AddressInuseErrorString); + break; + case KErrPermissionDenied: + setError(QAbstractSocket::SocketAccessError, AccessErrorString); + socketState = QAbstractSocket::UnconnectedState; + break; + case KErrNotSupported: + case KErrBadDescriptor: + 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; +} + +bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) +{ + TInetAddr nativeAddr; + setPortAndAddress(nativeAddr, port, address); + + TInt err = nativeSocket.Bind(nativeAddr); + + if (err) { + switch(errno) { + case KErrInUse: + setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); + break; + case KErrPermissionDenied: + setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); + break; + case KErrNotSupported: + setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); + break; + default: + break; + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", + address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData()); +#endif + + return false; + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true", + address.toString().toLatin1().constData(), port); +#endif + socketState = QAbstractSocket::BoundState; + return true; +} + +bool QNativeSocketEnginePrivate::nativeListen(int backlog) +{ + TInt err = nativeSocket.Listen(backlog); + if (err) { + switch (errno) { + case KErrInUse: + setError(QAbstractSocket::AddressInUseError, + PortInuseErrorString); + break; + default: + break; + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)", + backlog, socketErrorString.toLatin1().constData()); +#endif + return false; + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog); +#endif + + socketState = QAbstractSocket::ListeningState; + return true; +} + +int QNativeSocketEnginePrivate::nativeAccept() +{ + RSocket blankSocket; + //TODO: this is unbelievably broken, needs to be properly async + blankSocket.Open(socketServer); + TRequestStatus status; + nativeSocket.Accept(blankSocket, status); + User::WaitForRequest(status); + if(status.Int()) { + qWarning("QNativeSocketEnginePrivate::nativeAccept() - error %d", status.Int()); + return 0; + } + // FIXME Qt Handle of new socket must be retrieved from QSymbianSocketManager + // and then returned. Not the SubSessionHandle! Also set the socket to nonblocking. + return blankSocket.SubSessionHandle(); +} + +qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const +{ + int nbytes = 0; + qint64 available = 0; + // FIXME is this the right thing also for UDP? + // What is expected for UDP, the length for the next packet I guess? + TInt err = nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); + if(err) + return 0; + available = (qint64) nbytes; + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available); +#endif + return available; +} + +bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const +{ + int nbytes; + TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); + return err == KErrNone && nbytes > 0; + //TODO: this is pretty horrible too... +} + +qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const +{ + int nbytes; + TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); + return qint64(nbytes-28); //TODO: why -28 (open C version had this)? + // Why = Could it be that this is about header lengths etc? if yes + // this could be pretty broken, especially for IPv6 +} + +qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, + QHostAddress *address, quint16 *port) +{ + TPtr8 buffer((TUint8*)data, (int)maxSize); + TInetAddr addr; + TRequestStatus status; //TODO: OMG sync receive! + nativeSocket.RecvFrom(buffer, addr, 0, status); + User::WaitForRequest(status); + + if (status.Int()) { + setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); + } else if (port || address) { + getPortAndAddress(addr, port, address); + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + int len = buffer.Length(); + qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", + data, qt_prettyDebug(data, qMin(len, ssize_t(16)), len).data(), maxSize, + address ? address->toString().toLatin1().constData() : "(nil)", + port ? *port : 0, (qint64) len); +#endif + + if (status.Int()) + return -1; + return qint64(buffer.Length()); +} + +qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, + const QHostAddress &host, quint16 port) +{ + TPtrC8 buffer((TUint8*)data, (int)len); + TInetAddr addr; + setPortAndAddress(addr, port, host); + TSockXfrLength sentBytes; + TRequestStatus status; //TODO: OMG sync send! + nativeSocket.SendTo(buffer, addr, 0, status, sentBytes); + User::WaitForRequest(status); + TInt err = status.Int(); + + if (err) { + switch (err) { + case KErrTooBig: + setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); + break; + default: + setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + } + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, + qt_prettyDebug(data, qMin(len, 16), len).data(), len, host.toString().toLatin1().constData(), + port, (qint64) sentBytes()); +#endif + + return qint64(sentBytes()); +} + +bool QNativeSocketEnginePrivate::fetchConnectionParameters() +{ + localPort = 0; + localAddress.clear(); + peerPort = 0; + peerAddress.clear(); + + if (socketDescriptor == -1) + return false; + + if (!nativeSocket.SubSessionHandle()) { + if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket)) + return false; + } + + // Determine local address + TSockAddr addr; + nativeSocket.LocalName(addr); + getPortAndAddress(addr, &localPort, &localAddress); + + // Determine protocol family + switch (addr.Family()) { + case KAfInet: + socketProtocol = QAbstractSocket::IPv4Protocol; + break; +#if !defined (QT_NO_IPV6) + case KAfInet6: + socketProtocol = QAbstractSocket::IPv6Protocol; + break; +#endif + default: + socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol; + break; + } + + // Determine the remote address + nativeSocket.RemoteName(addr); + getPortAndAddress(addr, &peerPort, &peerAddress); + + // Determine the socket type (UDP/TCP) + TProtocolDesc protocol; + TInt err = nativeSocket.Info(protocol); + if (err) { + QAbstractSocket::UnknownSocketType; + } else { + switch (protocol.iProtocol) { + case KProtocolInetTcp: + socketType = QAbstractSocket::TcpSocket; + break; + case KProtocolInetUdp: + socketType = QAbstractSocket::UdpSocket; + break; + default: + socketType = QAbstractSocket::UnknownSocketType; + break; + } + } +#if defined (QNATIVESOCKETENGINE_DEBUG) + QString socketProtocolStr = "UnknownProtocol"; + if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol"; + else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol"; + + QString socketTypeStr = "UnknownSocketType"; + if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket"; + else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket"; + + qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i," + " peer == %s:%i, socket == %s - %s", + localAddress.toString().toLatin1().constData(), localPort, + peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(), + socketProtocolStr.toLatin1().constData()); +#endif + return true; +} + +void QNativeSocketEnginePrivate::nativeClose() +{ +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEngine::nativeClose()"); +#endif + + //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? + nativeSocket.Close(); + QSymbianSocketManager::instance().removeSocket(nativeSocket); +} + +qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) +{ + Q_Q(QNativeSocketEngine); + TPtrC8 buffer((TUint8*)data, (int)len); + TSockXfrLength sentBytes; + TRequestStatus status; //TODO: OMG sync send! + nativeSocket.Send(buffer, 0, status, sentBytes); + User::WaitForRequest(status); + TInt err = status.Int(); + + if (err) { + switch (err) { + case KErrDisconnected: + sentBytes = -1; + setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); + q->close(); + break; + case KErrTooBig: + setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); + break; + case KErrWouldBlock: + sentBytes = 0; + default: + setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + } + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", + data, qt_prettyDebug(data, qMin((int) len, 16), + (int) len).data(), len, (int) sentBytes()); +#endif + + return qint64(sentBytes()); +} +/* +*/ +qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) +{ + Q_Q(QNativeSocketEngine); + if (!q->isValid()) { + qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); + return -1; + } + + TPtr8 buffer((TUint8*)data, (int)maxSize); + TSockXfrLength received = 0; + TRequestStatus status; //TODO: OMG sync receive! + nativeSocket.RecvOneOrMore(buffer, 0, status, received); + User::WaitForRequest(status); + TInt err = status.Int(); + int r = received(); + + if (err) { + switch(err) { + case KErrWouldBlock: + // No data was available for reading + r = -2; + break; + case KErrDisconnected: + r = 0; + break; + default: + r = -1; + //error string is now set in read(), not here in nativeRead() + break; + } + } + +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", + data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), + maxSize, r); +#endif + + return qint64(r); +} + +int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const +{ + bool readyRead = false; + bool readyWrite = false; + if (selectForRead) + return nativeSelect(timeout, true, false, &readyRead, &readyWrite); + else + return nativeSelect(timeout, false, true, &readyRead, &readyWrite); +} + +/*! + \internal + \param timeout timeout in milliseconds + \param checkRead caller is interested if the socket is ready to read + \param checkWrite caller is interested if the socket is ready for write + \param selectForRead (out) should set to true if ready to read + \param selectForWrite (out) should set to true if ready to write + \return 0 on timeout, >0 on success, <0 on error + */ +int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) const +{ + //TODO: implement + //as above, but checking both read and write status at the same time + if (!selectTimer.Handle()) + qt_symbian_throwIfError(selectTimer.CreateLocal()); + TRequestStatus timerStat; + selectTimer.HighRes(timerStat, timeout * 1000); + TRequestStatus* readStat = 0; + TRequestStatus* writeStat = 0; + TRequestStatus* array[3]; + array[0] = &timerStat; + int count = 1; + if (checkRead) { + //TODO: get from read AO + //readStat = ? + array[count++] = readStat; + } + if (checkWrite) { + //TODO: get from write AO + //writeStat = ? + array[count++] = writeStat; + } + // TODO: for selecting, we can use getOpt(KSOSelectPoll) to get the select result + // and KIOCtlSelect for the selecting. + + User::WaitForNRequest(array, count); + //IMPORTANT - WaitForNRequest only decrements the thread semaphore once, although more than one status may have completed. + if (timerStat.Int() != KRequestPending) { + //timed out + return 0; + } + selectTimer.Cancel(); + User::WaitForRequest(timerStat); + + if(readStat && readStat->Int() != KRequestPending) { + Q_ASSERT(checkRead && selectForRead); + //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive() + *selectForRead = true; + } + if(writeStat && writeStat->Int() != KRequestPending) { + Q_ASSERT(checkWrite && selectForWrite); + //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive() + *selectForWrite = true; + } + return 1; +} + +bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + //TODO + return false; +} + +bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + //TODO + return false; +} + +QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +{ + //TODO + return QNetworkInterface(); +} + +bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +{ + //TODO + return false; +} + +QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h new file mode 100644 index 0000000..c017065 --- /dev/null +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNATIVESOCKETENGINE_P_H +#define QNATIVESOCKETENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +#include "QtNetwork/qhostaddress.h" +#include "private/qabstractsocketengine_p.h" +#ifndef Q_OS_WIN +# include "qplatformdefs.h" +#else +# include +#endif + +#ifdef Q_OS_SYMBIAN +#include +#include +#include +#include +#endif + +QT_BEGIN_NAMESPACE + +// Use our own defines and structs which we know are correct +# define QT_SS_MAXSIZE 128 +# define QT_SS_ALIGNSIZE (sizeof(qint64)) +# define QT_SS_PAD1SIZE (QT_SS_ALIGNSIZE - sizeof (short)) +# define QT_SS_PAD2SIZE (QT_SS_MAXSIZE - (sizeof (short) + QT_SS_PAD1SIZE + QT_SS_ALIGNSIZE)) +struct qt_sockaddr_storage { + short ss_family; + char __ss_pad1[QT_SS_PAD1SIZE]; + qint64 __ss_align; + char __ss_pad2[QT_SS_PAD2SIZE]; +}; + +// sockaddr_in6 size changed between old and new SDK +// Only the new version is the correct one, so always +// use this structure. +struct qt_in6_addr { + quint8 qt_s6_addr[16]; +}; +struct qt_sockaddr_in6 { + short sin6_family; /* AF_INET6 */ + quint16 sin6_port; /* Transport level port number */ + quint32 sin6_flowinfo; /* IPv6 flow information */ + struct qt_in6_addr sin6_addr; /* IPv6 address */ + quint32 sin6_scope_id; /* set of interfaces for a scope */ +}; + +union qt_sockaddr { + sockaddr a; + sockaddr_in a4; + qt_sockaddr_in6 a6; + qt_sockaddr_storage storage; +}; + +class QNativeSocketEnginePrivate; +class QNetworkInterface; + +class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine +{ + Q_OBJECT +public: + QNativeSocketEngine(QObject *parent = 0); + ~QNativeSocketEngine(); + + bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol); + bool initialize(int socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState); + + int socketDescriptor() const; + + bool isValid() const; + + bool connectToHost(const QHostAddress &address, quint16 port); + bool connectToHostByName(const QString &name, quint16 port); + bool bind(const QHostAddress &address, quint16 port); + bool listen(); + int accept(); + void close(); + + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + + qint64 bytesAvailable() const; + + qint64 read(char *data, qint64 maxlen); + qint64 write(const char *data, qint64 len); + + qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, + quint16 *port = 0); + qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, + quint16 port); + bool hasPendingDatagrams() const; + qint64 pendingDatagramSize() const; + + qint64 bytesToWrite() const; + + qint64 receiveBufferSize() const; + void setReceiveBufferSize(qint64 bufferSize); + + qint64 sendBufferSize() const; + void setSendBufferSize(qint64 bufferSize); + + int option(SocketOption option) const; + bool setOption(SocketOption option, int value); + + bool waitForRead(int msecs = 30000, bool *timedOut = 0); + bool waitForWrite(int msecs = 30000, bool *timedOut = 0); + bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, + bool checkRead, bool checkWrite, + int msecs = 30000, bool *timedOut = 0); + + bool isReadNotificationEnabled() const; + void setReadNotificationEnabled(bool enable); + bool isWriteNotificationEnabled() const; + void setWriteNotificationEnabled(bool enable); + bool isExceptionNotificationEnabled() const; + void setExceptionNotificationEnabled(bool enable); + +public Q_SLOTS: + // non-virtual override; + void connectionNotification(); + +private: + Q_DECLARE_PRIVATE(QNativeSocketEngine) + Q_DISABLE_COPY(QNativeSocketEngine) +}; + +#ifdef Q_OS_WIN +class QWindowsSockInit +{ +public: + QWindowsSockInit(); + ~QWindowsSockInit(); + int version; +}; +#endif + +class QSocketNotifier; + +class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate +{ + Q_DECLARE_PUBLIC(QNativeSocketEngine) +public: + QNativeSocketEnginePrivate(); + ~QNativeSocketEnginePrivate(); + + int socketDescriptor; +#ifdef Q_OS_SYMBIAN + mutable RSocket nativeSocket; + RSocketServ& socketServer; + RConnection connection; //TODO: shared ref + mutable RTimer selectTimer; +#endif + + QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; + +#ifdef Q_OS_WIN + QWindowsSockInit winSock; +#endif + + enum ErrorString { + NonBlockingInitFailedErrorString, + BroadcastingInitFailedErrorString, + NoIpV6ErrorString, + RemoteHostClosedErrorString, + TimeOutErrorString, + ResourceErrorString, + OperationUnsupportedErrorString, + ProtocolUnsupportedErrorString, + InvalidSocketErrorString, + HostUnreachableErrorString, + NetworkUnreachableErrorString, + AccessErrorString, + ConnectionTimeOutErrorString, + ConnectionRefusedErrorString, + AddressInuseErrorString, + AddressNotAvailableErrorString, + AddressProtectedErrorString, + DatagramTooLargeErrorString, + SendDatagramErrorString, + ReceiveDatagramErrorString, + WriteErrorString, + ReadErrorString, + PortInuseErrorString, + NotSocketErrorString, + InvalidProxyTypeString, + + UnknownSocketErrorString = -1 + }; + +#ifdef Q_OS_SYMBIAN + void getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr); + void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr); + void setError(TInt symbianError); +#endif + void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; + + // native functions + int option(QNativeSocketEngine::SocketOption option) const; + bool setOption(QNativeSocketEngine::SocketOption option, int value); + + bool createNewSocket(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol); + + bool nativeConnect(const QHostAddress &address, quint16 port); + bool nativeBind(const QHostAddress &address, quint16 port); + bool nativeListen(int backlog); + int nativeAccept(); + bool nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + QNetworkInterface nativeMulticastInterface() const; + bool nativeSetMulticastInterface(const QNetworkInterface &iface); + qint64 nativeBytesAvailable() const; + + bool nativeHasPendingDatagrams() const; + qint64 nativePendingDatagramSize() const; + qint64 nativeReceiveDatagram(char *data, qint64 maxLength, + QHostAddress *address, quint16 *port); + qint64 nativeSendDatagram(const char *data, qint64 length, + const QHostAddress &host, quint16 port); + qint64 nativeRead(char *data, qint64 maxLength); + qint64 nativeWrite(const char *data, qint64 length); + int nativeSelect(int timeout, bool selectForRead) const; + int nativeSelect(int timeout, bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) const; + + void nativeClose(); + + bool checkProxy(const QHostAddress &address); + bool fetchConnectionParameters(); +}; + +QT_END_NAMESPACE + +#endif // QNATIVESOCKETENGINE_P_H diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index f2262fe..3356cdd 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -26,7 +26,10 @@ SOURCES += socket/qabstractsocketengine.cpp \ socket/qlocalserver.cpp unix:!symbian:SOURCES += socket/qnativesocketengine_unix.cpp -symbian:SOURCES += socket/qnativesocketengine_symbian.cpp + +symbian:SOURCES += socket/qsymbiansocketengine.cpp +symbian:HEADERS += socket/qsymbiansocketengine_p.h + unix:SOURCES += \ socket/qlocalsocket_unix.cpp \ socket/qlocalserver_unix.cpp -- cgit v0.12 From 2073995a5af4d6a7677f78757aa72e598ef4b1ac Mon Sep 17 00:00:00 2001 From: Aaron Tunney Date: Tue, 7 Dec 2010 16:10:55 +0000 Subject: Fixed typo and includes. Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_symbian.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 2e1e6ca..ffa0b46 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ //#define QHOSTINFO_DEBUG +#include +#include #include "qplatformdefs.h" @@ -92,7 +94,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QString QHostInfo::localHostName() { - return QString() + return QString(); } QString QHostInfo::localDomainName() -- cgit v0.12 From 443d9e8a951ead746bd92ddb3835cd9cd63a063b Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 16:17:19 +0100 Subject: Continue code moving Reviewed-by: Shane Kearns --- src/network/socket/qsymbiansocketengine.cpp | 120 ++++++++++++++-------------- src/network/socket/qsymbiansocketengine_p.h | 114 +++++--------------------- 2 files changed, 80 insertions(+), 154 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index cfaee03..b553110 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -95,7 +95,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) } #endif -void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) +void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) { #if !defined(QT_NO_IPV6) if (a.Family() == KAfInet6) { @@ -133,7 +133,7 @@ void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 * Creates and returns a new socket descriptor of type \a socketType and \a socketProtocol. Returns -1 on failure. */ -bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, +bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol socketProtocol) { #ifndef QT_NO_IPV6 @@ -176,9 +176,9 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc /* Returns the value of the socket option \a opt. */ -int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const +int QSymbianSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) const { - Q_Q(const QNativeSocketEngine); + Q_Q(const QSymbianSocketEngine); if (!q->isValid()) return -1; @@ -186,32 +186,32 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co TUint level = KSOLSocket; // default switch (opt) { - case QNativeSocketEngine::ReceiveBufferSocketOption: + case QAbstractSocketEngine::ReceiveBufferSocketOption: n = KSORecvBuf; break; - case QNativeSocketEngine::SendBufferSocketOption: + case QAbstractSocketEngine::SendBufferSocketOption: n = KSOSendBuf; break; - case QNativeSocketEngine::NonBlockingSocketOption: + case QAbstractSocketEngine::NonBlockingSocketOption: n = KSONonBlockingIO; break; - case QNativeSocketEngine::BroadcastSocketOption: + case QAbstractSocketEngine::BroadcastSocketOption: return true; //symbian doesn't support or require this option - case QNativeSocketEngine::AddressReusable: + case QAbstractSocketEngine::AddressReusable: level = KSolInetIp; n = KSoReuseAddr; break; - case QNativeSocketEngine::BindExclusively: + case QAbstractSocketEngine::BindExclusively: return true; - case QNativeSocketEngine::ReceiveOutOfBandData: + case QAbstractSocketEngine::ReceiveOutOfBandData: level = KSolInetTcp; n = KSoTcpOobInline; break; - case QNativeSocketEngine::LowDelayOption: + case QAbstractSocketEngine::LowDelayOption: level = KSolInetTcp; n = KSoTcpNoDelay; break; - case QNativeSocketEngine::KeepAliveOption: + case QAbstractSocketEngine::KeepAliveOption: level = KSolInetTcp; n = KSoTcpKeepAlive; break; @@ -232,9 +232,9 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co /* Sets the socket option \a opt to \a v. */ -bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v) +bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, int v) { - Q_Q(QNativeSocketEngine); + Q_Q(QSymbianSocketEngine); if (!q->isValid()) return false; @@ -242,32 +242,32 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt int level = SOL_SOCKET; // default switch (opt) { - case QNativeSocketEngine::ReceiveBufferSocketOption: + case QAbstractSocketEngine::ReceiveBufferSocketOption: n = KSORecvBuf; break; - case QNativeSocketEngine::SendBufferSocketOption: + case QAbstractSocketEngine::SendBufferSocketOption: n = KSOSendBuf; break; - case QNativeSocketEngine::BroadcastSocketOption: + case QAbstractSocketEngine::BroadcastSocketOption: return true; - case QNativeSocketEngine::NonBlockingSocketOption: + case QAbstractSocketEngine::NonBlockingSocketOption: n = KSONonBlockingIO; break; - case QNativeSocketEngine::AddressReusable: + case QAbstractSocketEngine::AddressReusable: level = KSolInetIp; n = KSoReuseAddr; break; - case QNativeSocketEngine::BindExclusively: + case QAbstractSocketEngine::BindExclusively: return true; - case QNativeSocketEngine::ReceiveOutOfBandData: + case QAbstractSocketEngine::ReceiveOutOfBandData: level = KSolInetTcp; n = KSoTcpOobInline; break; - case QNativeSocketEngine::LowDelayOption: + case QAbstractSocketEngine::LowDelayOption: level = KSolInetTcp; n = KSoTcpNoDelay; break; - case QNativeSocketEngine::KeepAliveOption: + case QAbstractSocketEngine::KeepAliveOption: level = KSolInetTcp; n = KSoTcpKeepAlive; break; @@ -276,7 +276,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return (KErrNone == nativeSocket.SetOpt(n, level, v)); } -void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) +void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) { nativeAddr.SetPort(port); #if !defined(QT_NO_IPV6) @@ -305,10 +305,10 @@ void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint1 } } -bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) +bool QSymbianSocketEngine::connect(const QHostAddress &addr, quint16 port) { #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); + qDebug("QSymbianSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); #endif TInetAddr nativeAddr; @@ -351,7 +351,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 if (socketState != QAbstractSocket::ConnectedState) { #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)", + qDebug("QSymbianSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)", addr.toString().toLatin1().constData(), port, socketState == QAbstractSocket::ConnectingState ? "Connection in progress" : socketErrorString.toLatin1().constData()); @@ -369,7 +369,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 return true; } -bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) +bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) { TInetAddr nativeAddr; setPortAndAddress(nativeAddr, port, address); @@ -392,7 +392,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", + qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData()); #endif @@ -400,14 +400,14 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true", + qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == true", address.toString().toLatin1().constData(), port); #endif socketState = QAbstractSocket::BoundState; return true; } -bool QNativeSocketEnginePrivate::nativeListen(int backlog) +bool QSymbianSocketEngine::listen(int backlog) { TInt err = nativeSocket.Listen(backlog); if (err) { @@ -421,21 +421,21 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)", + qDebug("QSymbianSocketEnginePrivate::nativeListen(%i) == false (%s)", backlog, socketErrorString.toLatin1().constData()); #endif return false; } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog); + qDebug("QSymbianSocketEnginePrivate::nativeListen(%i) == true", backlog); #endif socketState = QAbstractSocket::ListeningState; return true; } -int QNativeSocketEnginePrivate::nativeAccept() +int QSymbianSocketEngine::accept() { RSocket blankSocket; //TODO: this is unbelievably broken, needs to be properly async @@ -444,7 +444,7 @@ int QNativeSocketEnginePrivate::nativeAccept() nativeSocket.Accept(blankSocket, status); User::WaitForRequest(status); if(status.Int()) { - qWarning("QNativeSocketEnginePrivate::nativeAccept() - error %d", status.Int()); + qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); return 0; } // FIXME Qt Handle of new socket must be retrieved from QSymbianSocketManager @@ -452,7 +452,7 @@ int QNativeSocketEnginePrivate::nativeAccept() return blankSocket.SubSessionHandle(); } -qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const +qint64 QSymbianSocketEngine::bytesAvailable() const { int nbytes = 0; qint64 available = 0; @@ -464,12 +464,12 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const available = (qint64) nbytes; #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available); + qDebug("QSymbianSocketEnginePrivate::nativeBytesAvailable() == %lli", available); #endif return available; } -bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const +bool QSymbianSocketEngine::hasPendingDatagrams() const { int nbytes; TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); @@ -477,7 +477,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const //TODO: this is pretty horrible too... } -qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const +qint64 QSymbianSocketEngine::pendingDatagramSize() const { int nbytes; TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); @@ -486,7 +486,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const // this could be pretty broken, especially for IPv6 } -qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, +qint64 QSymbianSocketEngine::nativeReceiveDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { TPtr8 buffer((TUint8*)data, (int)maxSize); @@ -503,7 +503,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS #if defined (QNATIVESOCKETENGINE_DEBUG) int len = buffer.Length(); - qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", + qDebug("QSymbianSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", data, qt_prettyDebug(data, qMin(len, ssize_t(16)), len).data(), maxSize, address ? address->toString().toLatin1().constData() : "(nil)", port ? *port : 0, (qint64) len); @@ -514,7 +514,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS return qint64(buffer.Length()); } -qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, +qint64 QSymbianSocketEngine::sendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port) { TPtrC8 buffer((TUint8*)data, (int)len); @@ -537,7 +537,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, + qDebug("QSymbianSocketEnginePrivate::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, qt_prettyDebug(data, qMin(len, 16), len).data(), len, host.toString().toLatin1().constData(), port, (qint64) sentBytes()); #endif @@ -545,7 +545,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l return qint64(sentBytes()); } -bool QNativeSocketEnginePrivate::fetchConnectionParameters() +bool QSymbianSocketEnginePrivate::fetchConnectionParameters() { localPort = 0; localAddress.clear(); @@ -611,7 +611,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket"; else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket"; - qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i," + qDebug("QSymbianSocketEnginePrivate::fetchConnectionParameters() local == %s:%i," " peer == %s:%i, socket == %s - %s", localAddress.toString().toLatin1().constData(), localPort, peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(), @@ -620,10 +620,10 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() return true; } -void QNativeSocketEnginePrivate::nativeClose() +void QSymbianSocketEngine::close() { #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEngine::nativeClose()"); + qDebug("QSymbianSocketEnginePrivate::nativeClose()"); #endif //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? @@ -631,9 +631,9 @@ void QNativeSocketEnginePrivate::nativeClose() QSymbianSocketManager::instance().removeSocket(nativeSocket); } -qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) +qint64 QSymbianSocketEngine::write(const char *data, qint64 len) { - Q_Q(QNativeSocketEngine); + Q_Q(QSymbianSocketEngine); TPtrC8 buffer((TUint8*)data, (int)len); TSockXfrLength sentBytes; TRequestStatus status; //TODO: OMG sync send! @@ -659,7 +659,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", + qDebug("QSymbianSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin((int) len, 16), (int) len).data(), len, (int) sentBytes()); #endif @@ -668,11 +668,11 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) } /* */ -qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) +qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) { - Q_Q(QNativeSocketEngine); + Q_Q(QSymbianSocketEngine); if (!q->isValid()) { - qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); + qWarning("QSymbianSocketEnginePrivate::nativeRead: Invalid socket"); return -1; } @@ -709,7 +709,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) return qint64(r); } -int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const +int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const { bool readyRead = false; bool readyWrite = false; @@ -728,7 +728,7 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) co \param selectForWrite (out) should set to true if ready to write \return 0 on timeout, >0 on success, <0 on error */ -int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, +int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, bool *selectForRead, bool *selectForWrite) const { //TODO: implement @@ -777,27 +777,27 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c return 1; } -bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, +bool QSymbianSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { //TODO return false; } -bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, +bool QSymbianSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { //TODO return false; } -QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +QNetworkInterface QSymbianSocketEngine::multicastInterface() const { //TODO return QNetworkInterface(); } -bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +bool QSymbianSocketEngine::setMulticastInterface(const QNetworkInterface &iface) { //TODO return false; diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index c017065..07e1b69 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QNATIVESOCKETENGINE_P_H -#define QNATIVESOCKETENGINE_P_H +#ifndef QSYMBIANSOCKETENGINE_P_H +#define QSYMBIANSOCKETENGINE_P_H // // W A R N I N G @@ -54,63 +54,27 @@ // #include "QtNetwork/qhostaddress.h" #include "private/qabstractsocketengine_p.h" -#ifndef Q_OS_WIN -# include "qplatformdefs.h" -#else -# include -#endif +#include "qplatformdefs.h" -#ifdef Q_OS_SYMBIAN #include #include #include #include -#endif +// TODO -QT_BEGIN_NAMESPACE -// Use our own defines and structs which we know are correct -# define QT_SS_MAXSIZE 128 -# define QT_SS_ALIGNSIZE (sizeof(qint64)) -# define QT_SS_PAD1SIZE (QT_SS_ALIGNSIZE - sizeof (short)) -# define QT_SS_PAD2SIZE (QT_SS_MAXSIZE - (sizeof (short) + QT_SS_PAD1SIZE + QT_SS_ALIGNSIZE)) -struct qt_sockaddr_storage { - short ss_family; - char __ss_pad1[QT_SS_PAD1SIZE]; - qint64 __ss_align; - char __ss_pad2[QT_SS_PAD2SIZE]; -}; +QT_BEGIN_NAMESPACE -// sockaddr_in6 size changed between old and new SDK -// Only the new version is the correct one, so always -// use this structure. -struct qt_in6_addr { - quint8 qt_s6_addr[16]; -}; -struct qt_sockaddr_in6 { - short sin6_family; /* AF_INET6 */ - quint16 sin6_port; /* Transport level port number */ - quint32 sin6_flowinfo; /* IPv6 flow information */ - struct qt_in6_addr sin6_addr; /* IPv6 address */ - quint32 sin6_scope_id; /* set of interfaces for a scope */ -}; -union qt_sockaddr { - sockaddr a; - sockaddr_in a4; - qt_sockaddr_in6 a6; - qt_sockaddr_storage storage; -}; - -class QNativeSocketEnginePrivate; +class QSymbianSocketEnginePrivate; class QNetworkInterface; -class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine +class Q_AUTOTEST_EXPORT QSymbianSocketEngine : public QAbstractSocketEngine { Q_OBJECT public: - QNativeSocketEngine(QObject *parent = 0); - ~QNativeSocketEngine(); + QSymbianSocketEngine(QObject *parent = 0); + ~QSymbianSocketEngine(); bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol); bool initialize(int socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState); @@ -156,6 +120,7 @@ public: int option(SocketOption option) const; bool setOption(SocketOption option, int value); + // FIXME actually implement bool waitForRead(int msecs = 30000, bool *timedOut = 0); bool waitForWrite(int msecs = 30000, bool *timedOut = 0); bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, @@ -170,32 +135,23 @@ public: void setExceptionNotificationEnabled(bool enable); public Q_SLOTS: + // TODO: Why do we do this? This is private Qt implementation stuff anyway, no need for it // non-virtual override; void connectionNotification(); private: - Q_DECLARE_PRIVATE(QNativeSocketEngine) - Q_DISABLE_COPY(QNativeSocketEngine) -}; - -#ifdef Q_OS_WIN -class QWindowsSockInit -{ -public: - QWindowsSockInit(); - ~QWindowsSockInit(); - int version; + Q_DECLARE_PRIVATE(QSymbianSocketEngine) + Q_DISABLE_COPY(QSymbianSocketEngine) }; -#endif class QSocketNotifier; -class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate +class QSymbianSocketEnginePrivate : public QAbstractSocketEnginePrivate { - Q_DECLARE_PUBLIC(QNativeSocketEngine) + Q_DECLARE_PUBLIC(QSymbianSocketEngine) public: - QNativeSocketEnginePrivate(); - ~QNativeSocketEnginePrivate(); + QSymbianSocketEnginePrivate(); + ~QSymbianSocketEnginePrivate(); int socketDescriptor; #ifdef Q_OS_SYMBIAN @@ -207,10 +163,6 @@ public: QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; -#ifdef Q_OS_WIN - QWindowsSockInit winSock; -#endif - enum ErrorString { NonBlockingInitFailedErrorString, BroadcastingInitFailedErrorString, @@ -248,37 +200,11 @@ public: #endif void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; - // native functions - int option(QNativeSocketEngine::SocketOption option) const; - bool setOption(QNativeSocketEngine::SocketOption option, int value); - - bool createNewSocket(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol); - - bool nativeConnect(const QHostAddress &address, quint16 port); - bool nativeBind(const QHostAddress &address, quint16 port); - bool nativeListen(int backlog); - int nativeAccept(); - bool nativeJoinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface); - bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface); - QNetworkInterface nativeMulticastInterface() const; - bool nativeSetMulticastInterface(const QNetworkInterface &iface); - qint64 nativeBytesAvailable() const; - - bool nativeHasPendingDatagrams() const; - qint64 nativePendingDatagramSize() const; - qint64 nativeReceiveDatagram(char *data, qint64 maxLength, - QHostAddress *address, quint16 *port); - qint64 nativeSendDatagram(const char *data, qint64 length, - const QHostAddress &host, quint16 port); - qint64 nativeRead(char *data, qint64 maxLength); - qint64 nativeWrite(const char *data, qint64 length); + // FIXME int nativeSelect(int timeout, bool selectForRead) const; int nativeSelect(int timeout, bool checkRead, bool checkWrite, - bool *selectForRead, bool *selectForWrite) const; + bool *selectForRead, bool *selectForWrite) const; - void nativeClose(); bool checkProxy(const QHostAddress &address); bool fetchConnectionParameters(); @@ -286,4 +212,4 @@ public: QT_END_NAMESPACE -#endif // QNATIVESOCKETENGINE_P_H +#endif // QSYMBIANSOCKETENGINE_P_H -- cgit v0.12 From 8adba785c8b68b9fdc98b51ecf317e17ad145d13 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 7 Dec 2010 16:03:09 +0000 Subject: default RConnection for sockets Bearer pushes RConnection into QtCore. QSocket can pull this RConnection back out when it needs to open an RSocket (potentially this can be removed again later if QSocket is made QNetworkSession aware) Reviewed-by: Markus Goetz --- src/corelib/kernel/qcore_symbian_p.cpp | 12 +++++++++++- src/corelib/kernel/qcore_symbian_p.h | 16 +++++++++++++++- src/plugins/bearer/symbian/qnetworksession_impl.cpp | 10 ++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index b6688f7..ede8464 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -217,7 +217,7 @@ Q_CORE_EXPORT RFs& qt_s60GetRFs() } QSymbianSocketManager::QSymbianSocketManager() : - iNextSocket(0) + iNextSocket(0), iDefaultConnection(0) { TSessionPref preferences; // ### In future this could be changed to KAfInet6 when that is more common than IPv4 @@ -290,6 +290,16 @@ bool QSymbianSocketManager::lookupSocket(int fd, RSocket& socket) const { return true; } +void QSymbianSocketManager::setDefaultConnection(RConnection* con) +{ + iDefaultConnection = con; +} + +RConnection* QSymbianSocketManager::defaultConnection() const +{ + return iDefaultConnection; +} + Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager); QSymbianSocketManager& QSymbianSocketManager::instance() diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index 8ffa247..d5d10ef 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -172,7 +172,7 @@ public: } bool operator<(const QHashableSocket &other) const { - if(Session().Handle() == other.Session().Handle()) + if (Session().Handle() == other.Session().Handle()) return SubSessionHandle() < other.SubSessionHandle(); return Session().Handle() < other.Session().Handle(); } @@ -230,6 +230,19 @@ public: /*! \internal + Set the default connection to use for new sockets + \param an open connection + */ + void setDefaultConnection(RConnection* con); + /*! + \internal + Get the default connection to use for new sockets + \return the connection, or null pointer if there is none set + */ + RConnection *defaultConnection() const; + + /*! + \internal Gets a reference to the singleton socket manager */ static QSymbianSocketManager& instance(); @@ -243,6 +256,7 @@ private: QHash reverseSocketMap; mutable QMutex iMutex; RSocketServ iSocketServ; + RConnection *iDefaultConnection; }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index cfb55bf..759c86a 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -114,6 +114,7 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() // Close global 'Open C' RConnection // Clears also possible unsetdefaultif() flags. setdefaultif(0); + QSymbianSocketManager::instance().setDefaultConnection(0); iConnectionMonitor.Close(); iOpenCLibrary.Close(); @@ -533,6 +534,7 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) setdefaultif(0); } + QSymbianSocketManager::instance().setDefaultConnection(0); // If UserChoice, go down immediately. If some other configuration, // go down immediately if there is no reports expected from the platform; // in practice Connection Monitor is aware of connections only after @@ -634,6 +636,7 @@ void QNetworkSessionPrivateImpl::migrate() } else { setdefaultif(0); } + QSymbianSocketManager::instance().setDefaultConnection(0); // Start migrating to new IAP iMobility->MigrateToPreferredCarrier(); } @@ -670,6 +673,8 @@ void QNetworkSessionPrivateImpl::accept() strcpy(ifr.ifr_name, nameAsByteArray.constData()); setdefaultif(&ifr); + QSymbianSocketManager::instance().setDefaultConnection(&iConnection); + newState(QNetworkSession::Connected, iNewRoamingIap); } #endif @@ -693,6 +698,8 @@ void QNetworkSessionPrivateImpl::reject() strcpy(ifr.ifr_name, nameAsByteArray.constData()); setdefaultif(&ifr); + QSymbianSocketManager::instance().setDefaultConnection(&iConnection); + newState(QNetworkSession::Connected, iOldRoamingIap); } } @@ -1079,6 +1086,7 @@ void QNetworkSessionPrivateImpl::RunL() QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); strcpy(ifr.ifr_name, nameAsByteArray.constData()); error = setdefaultif(&ifr); + QSymbianSocketManager::instance().setDefaultConnection(&iConnection); } if (error != KErrNone) { isOpen = false; @@ -1092,6 +1100,7 @@ void QNetworkSessionPrivateImpl::RunL() // No valid configuration, bail out. // Status updates from QNCM won't be received correctly // because there is no configuration to associate them with so transit here. + QSymbianSocketManager::instance().setDefaultConnection(0); iConnection.Close(); newState(QNetworkSession::Closing); newState(QNetworkSession::Disconnected); @@ -1205,6 +1214,7 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint strcpy(ifr.ifr_name, nameAsByteArray.constData()); setdefaultif(&ifr); + QSymbianSocketManager::instance().setDefaultConnection(&iConnection); #endif } -- cgit v0.12 From c59b7067ace1abc5f9a0aca9bd90d49340cb4e79 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 7 Dec 2010 16:07:30 +0000 Subject: Helper functions for synchronously waiting on an active object to complete QtNetwork APIs are based on calling a function asychronously. However the user may call a waitForXXXX function later to convert this into a synchronous call. For Symbian, the async call should be implemented as an active object. These helpers make the synchronous conversion possible. Unix used select() in a polling way to do async mode and blocking way for the synchronous conversion. Reviewed-by: mread --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 80 +++++++++++++++++++++++++ src/corelib/kernel/qeventdispatcher_symbian_p.h | 4 +- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 6154119..55be6eb 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1136,6 +1136,86 @@ void CQtActiveScheduler::Error(TInt aError) const QT_CATCH (const std::bad_alloc&) {} // ignore alloc fails, nothing more can be done } +bool QActiveObject::wait(CActive* ao, int ms) +{ + if (!ao->IsActive()) + return true; //request already complete + bool timedout = false; + if (ms > 0) { + TRequestStatus tstat; + RTimer t; + if (KErrNone != t.CreateLocal()) + return false; + t.HighRes(tstat, ms*1000); + User::WaitForRequest(tstat, ao->iStatus); + if (tstat != KRequestPending) { + timedout = true; + } else { + t.Cancel(); + //balance thread semaphore + User::WaitForRequest(tstat); + } + t.Close(); + } else { + User::WaitForRequest(ao->iStatus); + } + if (timedout) + return false; + + //evil cast to allow calling of protected virtual + ((QActiveObject*)ao)->RunL(); + + //clear active & pending flags + ao->iStatus = TRequestStatus(); + + return true; +} + +bool QActiveObject::wait(QList aos, int ms) +{ + QVector stati; + stati.reserve(aos.count() + 1); + foreach (CActive* ao, aos) { + if (!ao->IsActive()) + return true; //request already complete + stati.append(&(ao->iStatus)); + } + bool timedout = false; + TRequestStatus tstat; + RTimer t; + if (ms > 0) { + if (KErrNone != t.CreateLocal()) + return false; + t.HighRes(tstat, ms*1000); + stati.append(&tstat); + } + User::WaitForNRequest(stati.data(), stati.count()); + if (ms > 0) { + if (tstat != KRequestPending) { + timedout = true; + } else { + t.Cancel(); + //balance thread semaphore + User::WaitForRequest(tstat); + } + t.Close(); + } + if (timedout) + return false; + + foreach (CActive* ao, aos) { + if (ao->iStatus != KRequestPending) { + //evil cast to allow calling of protected virtual + ((QActiveObject*)ao)->RunL(); + + //clear active & pending flags + ao->iStatus = TRequestStatus(); + break; //only call one + } + } + return true; +} + QT_END_NAMESPACE #include "moc_qeventdispatcher_symbian_p.cpp" diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index 3615996..d462dff 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE class QEventDispatcherSymbian; class QTimerActiveObject; -class QActiveObject : public CActive +class Q_AUTOTEST_EXPORT QActiveObject : public CActive { public: QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher); @@ -86,6 +86,8 @@ public: void reactivateAndComplete(); + static bool wait(CActive* ao, int ms); + static bool wait(QList aos, int ms); protected: QEventDispatcherSymbian *m_dispatcher; -- cgit v0.12 From a0528585d02440b37fb93f37e3d15ce2356d2541 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 16:51:48 +0100 Subject: Remove Symbian code from QNativeSocketEngine .. and move one function around Reviewed-by: Shane Kearns --- src/network/socket/qnativesocketengine.cpp | 8 --- src/network/socket/qnativesocketengine_p.h | 11 ---- src/network/socket/qsymbiansocketengine.cpp | 80 ++++++++++++++++++----------- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 00d36b4..1fe5572 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -110,10 +110,6 @@ # include "qtcpserver.h" #endif -#ifdef Q_OS_SYMBIAN -# include -#endif - QT_BEGIN_NAMESPACE //#define QNATIVESOCKETENGINE_DEBUG @@ -164,9 +160,6 @@ QT_BEGIN_NAMESPACE */ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() : socketDescriptor(-1), -#ifdef Q_OS_SYMBIAN - socketServer(qt_symbianGetSocketServer()), -#endif readNotifier(0), writeNotifier(0), exceptNotifier(0) @@ -394,7 +387,6 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb // Make sure we receive out-of-band data - // On Symbian OS this works only with native IP stack, not with WinSock if (socketType == QAbstractSocket::TcpSocket && !setOption(ReceiveOutOfBandData, 1)) { qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index c017065..1f13433 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -198,12 +198,6 @@ public: ~QNativeSocketEnginePrivate(); int socketDescriptor; -#ifdef Q_OS_SYMBIAN - mutable RSocket nativeSocket; - RSocketServ& socketServer; - RConnection connection; //TODO: shared ref - mutable RTimer selectTimer; -#endif QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; @@ -241,11 +235,6 @@ public: UnknownSocketErrorString = -1 }; -#ifdef Q_OS_SYMBIAN - void getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr); - void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr); - void setError(TInt symbianError); -#endif void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; // native functions diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index b553110..7a22918 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -53,6 +53,7 @@ #ifndef QT_NO_IPV6IFNAME #include #endif +# include #define QNATIVESOCKETENGINE_DEBUG @@ -229,6 +230,56 @@ int QSymbianSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) } +void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) +{ + nativeAddr.SetPort(port); +#if !defined(QT_NO_IPV6) + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { +#ifndef QT_NO_IPV6IFNAME + TPckgBuf query; + query().iName = qt_QString2TPtrC(addr.scopeId()); + TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); + if(!err) + nativeAddr.SetScope(query().iIndex); + else + nativeAddr.SetScope(0); +#else + nativeAddr.SetScope(addr.scopeId().toInt()); +#endif + Q_IPV6ADDR ip6 = addr.toIPv6Address(); + TIp6Addr v6addr; + memcpy(v6addr.u.iAddr8, ip6.c, 16); + nativeAddr.SetAddress(v6addr); + } else +#endif + if (addr.protocol() == QAbstractSocket::IPv4Protocol) { + nativeAddr.SetAddress(addr.toIPv4Address()); + } else { + qWarning("unsupported network protocol (%d)", addr.protocol()); + } +} + +QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : + socketDescriptor(-1), + socketServer(qt_symbianGetSocketServer()), + readNotifier(0), + writeNotifier(0), + exceptNotifier(0) +{ +} + + +QSymbianSocketEngine::QSymbianSocketEngine(QObject *parent) + : QAbstractSocketEngine(*new QSymbianSocketEnginePrivate(), parent) +{ +} + + +QSymbianSocketEngine::~QSymbianSocketEngine() +{ + close(); +} + /* Sets the socket option \a opt to \a v. */ @@ -276,35 +327,6 @@ bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, in return (KErrNone == nativeSocket.SetOpt(n, level, v)); } -void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) -{ - nativeAddr.SetPort(port); -#if !defined(QT_NO_IPV6) - if (addr.protocol() == QAbstractSocket::IPv6Protocol) { -#ifndef QT_NO_IPV6IFNAME - TPckgBuf query; - query().iName = qt_QString2TPtrC(addr.scopeId()); - TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); - if(!err) - nativeAddr.SetScope(query().iIndex); - else - nativeAddr.SetScope(0); -#else - nativeAddr.SetScope(addr.scopeId().toInt()); -#endif - Q_IPV6ADDR ip6 = addr.toIPv6Address(); - TIp6Addr v6addr; - memcpy(v6addr.u.iAddr8, ip6.c, 16); - nativeAddr.SetAddress(v6addr); - } else -#endif - if (addr.protocol() == QAbstractSocket::IPv4Protocol) { - nativeAddr.SetAddress(addr.toIPv4Address()); - } else { - qWarning("unsupported network protocol (%d)", addr.protocol()); - } -} - bool QSymbianSocketEngine::connect(const QHostAddress &addr, quint16 port) { #ifdef QNATIVESOCKETENGINE_DEBUG -- cgit v0.12 From f16b745ca427e75bc045076f5e14742a2a2c713a Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 17:07:19 +0100 Subject: Create QSymbianSocketEngine when requested Reviewed-by: Shane Kearns --- src/network/socket/qabstractsocketengine.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/network/socket/qabstractsocketengine.cpp b/src/network/socket/qabstractsocketengine.cpp index 79eed8c..1b2a1f4 100644 --- a/src/network/socket/qabstractsocketengine.cpp +++ b/src/network/socket/qabstractsocketengine.cpp @@ -113,7 +113,11 @@ QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(QAbstractSocket return 0; #endif +#ifdef Q_OS_SYMBIAN + return new QSymbianSocketEngine(parent); +#else return new QNativeSocketEngine(parent); +#endif } QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(int socketDescripter, QObject *parent) @@ -123,7 +127,11 @@ QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(int socketDescr if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketDescripter, parent)) return ret; } +#ifdef Q_OS_SYMBIAN + return new QSymbianSocketEngine(parent); +#else return new QNativeSocketEngine(parent); +#endif } QAbstractSocket::SocketError QAbstractSocketEngine::error() const -- cgit v0.12 From c2f9ec2ae225fbaeaa0e463308427fb075d9c2af Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 7 Dec 2010 17:23:15 +0100 Subject: QSymbianSocketEngine: Get global RConnection* Reviewed-by: Shane Kearns --- src/network/socket/qsymbiansocketengine.cpp | 3 ++- src/network/socket/qsymbiansocketengine_p.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 7a22918..55fe12b 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -145,7 +145,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so #endif TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; - TInt err = nativeSocket.Open(socketServer, family, type, protocol, connection); + TInt err = nativeSocket.Open(socketServer, family, type, protocol, *connection); if (err != KErrNone) { switch (err) { @@ -262,6 +262,7 @@ void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : socketDescriptor(-1), socketServer(qt_symbianGetSocketServer()), + connection(QSymbianSocketManager::instance().defaultConnection()), readNotifier(0), writeNotifier(0), exceptNotifier(0) diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 07e1b69..fd449ca 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -156,8 +156,10 @@ public: int socketDescriptor; #ifdef Q_OS_SYMBIAN mutable RSocket nativeSocket; + // From QtCore: RSocketServ& socketServer; - RConnection connection; //TODO: shared ref + // From QtCore, check lifetime issues, also should be pulling this out of a QNetworkSession somehow: + RConnection *connection; mutable RTimer selectTimer; #endif -- cgit v0.12 From e879d46b2733aa3fe69a3e1dabd2ae377b8a714d Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 09:51:04 +0100 Subject: QSymbianSocketEngine: Compile fixes.. --- src/network/socket/qabstractsocketengine.cpp | 6 + src/network/socket/qsymbiansocketengine.cpp | 235 ++++++++++++++++++--------- src/network/socket/qsymbiansocketengine_p.h | 2 + 3 files changed, 169 insertions(+), 74 deletions(-) diff --git a/src/network/socket/qabstractsocketengine.cpp b/src/network/socket/qabstractsocketengine.cpp index 1b2a1f4..16b9d57 100644 --- a/src/network/socket/qabstractsocketengine.cpp +++ b/src/network/socket/qabstractsocketengine.cpp @@ -40,7 +40,13 @@ ****************************************************************************/ #include "qabstractsocketengine_p.h" + +#ifdef Q_OS_SYMBIAN +#include "qsymbiansocketengine_p.h" +#else #include "qnativesocketengine_p.h" +#endif + #include "qmutex.h" #include "qnetworkproxy.h" diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 55fe12b..7957baf 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -40,8 +40,8 @@ ****************************************************************************/ //#define QNATIVESOCKETENGINE_DEBUG -#include "qnativesocketengine_p.h" -#include "private/qnet_unix_p.h" +#include "qsymbiansocketengine_p.h" + #include "qiodevice.h" #include "qhostaddress.h" #include "qelapsedtimer.h" @@ -49,11 +49,17 @@ #include "qnetworkinterface.h" #include #include -#include #ifndef QT_NO_IPV6IFNAME #include #endif -# include + +#include + +#if !defined(QT_NO_NETWORKPROXY) +# include "qnetworkproxy.h" +# include "qabstractsocket.h" +# include "qtcpserver.h" +#endif #define QNATIVESOCKETENGINE_DEBUG @@ -137,6 +143,7 @@ void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol socketProtocol) { + Q_Q(QSymbianSocketEngine); #ifndef QT_NO_IPV6 TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet; #else @@ -177,10 +184,10 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so /* Returns the value of the socket option \a opt. */ -int QSymbianSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) const +int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const { - Q_Q(const QSymbianSocketEngine); - if (!q->isValid()) + Q_D(const QSymbianSocketEngine); + if (!isValid()) return -1; TUint n; @@ -222,7 +229,7 @@ int QSymbianSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) int v = -1; //GetOpt() is non const - TInt err = nativeSocket.GetOpt(n, level, v); + TInt err = d->nativeSocket.GetOpt(n, level, v); if (!err) return v; @@ -269,6 +276,10 @@ QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : { } +QSymbianSocketEnginePrivate::~QSymbianSocketEnginePrivate() +{ +} + QSymbianSocketEngine::QSymbianSocketEngine(QObject *parent) : QAbstractSocketEngine(*new QSymbianSocketEnginePrivate(), parent) @@ -279,6 +290,7 @@ QSymbianSocketEngine::QSymbianSocketEngine(QObject *parent) QSymbianSocketEngine::~QSymbianSocketEngine() { close(); + // FIXME what else do we need to free? } /* @@ -286,8 +298,8 @@ QSymbianSocketEngine::~QSymbianSocketEngine() */ bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, int v) { - Q_Q(QSymbianSocketEngine); - if (!q->isValid()) + Q_D(QSymbianSocketEngine); + if (!isValid()) return false; int n = 0; @@ -325,59 +337,82 @@ bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, in break; } - return (KErrNone == nativeSocket.SetOpt(n, level, v)); + return (KErrNone == d->nativeSocket.SetOpt(n, level, v)); } -bool QSymbianSocketEngine::connect(const QHostAddress &addr, quint16 port) +bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port) { + // FIXME for engines that support hostnames.. not for us then i guess. + + return false; +} + + +bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) +{ + Q_D(QSymbianSocketEngine); + #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug("QSymbianSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); + qDebug("QSymbianSocketEngine::connectToHost() : %d ", d->socketDescriptor); #endif +#if defined (QT_NO_IPV6) + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + NoIpV6ErrorString); + return false; + } +#endif + if (!d->checkProxy(addr)) + return false; + + d->peerAddress = addr; + d->peerPort = port; + TInetAddr nativeAddr; - setPortAndAddress(nativeAddr, port, addr); + d->setPortAndAddress(nativeAddr, port, addr); //TODO: async connect with active object - from here to end of function is a mess TRequestStatus status; - nativeSocket.Connect(nativeAddr, status); + d->nativeSocket.Connect(nativeAddr, status); User::WaitForRequest(status); TInt err = status.Int(); if (err) { switch (err) { case KErrCouldNotConnect: - setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); - socketState = QAbstractSocket::UnconnectedState; + d->setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); + d->socketState = QAbstractSocket::UnconnectedState; break; case KErrTimedOut: - setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); + d->setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); break; case KErrHostUnreach: - setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; + d->setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; break; case KErrNetUnreach: - setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); - socketState = QAbstractSocket::UnconnectedState; + d->setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; break; case KErrInUse: - setError(QAbstractSocket::NetworkError, AddressInuseErrorString); + d->setError(QAbstractSocket::NetworkError, AddressInuseErrorString); break; case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AccessErrorString); - socketState = QAbstractSocket::UnconnectedState; + d->setError(QAbstractSocket::SocketAccessError, AccessErrorString); + d->socketState = QAbstractSocket::UnconnectedState; break; case KErrNotSupported: case KErrBadDescriptor: - socketState = QAbstractSocket::UnconnectedState; + d->socketState = QAbstractSocket::UnconnectedState; default: break; } - if (socketState != QAbstractSocket::ConnectedState) { + if (d->socketState != QAbstractSocket::ConnectedState) { #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)", addr.toString().toLatin1().constData(), port, - socketState == QAbstractSocket::ConnectingState - ? "Connection in progress" : socketErrorString.toLatin1().constData()); + d->socketState == QAbstractSocket::ConnectingState + ? "Connection in progress" : d->socketErrorString.toLatin1().constData()); #endif return false; } @@ -388,27 +423,29 @@ bool QSymbianSocketEngine::connect(const QHostAddress &addr, quint16 port) addr.toString().toLatin1().constData(), port); #endif - socketState = QAbstractSocket::ConnectedState; + d->socketState = QAbstractSocket::ConnectedState; + d->fetchConnectionParameters(); return true; } bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) { + Q_D(QSymbianSocketEngine); TInetAddr nativeAddr; - setPortAndAddress(nativeAddr, port, address); + d->setPortAndAddress(nativeAddr, port, address); - TInt err = nativeSocket.Bind(nativeAddr); + TInt err = d->nativeSocket.Bind(nativeAddr); if (err) { switch(errno) { case KErrInUse: - setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); + d->setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); break; case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); + d->setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); break; case KErrNotSupported: - setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); + d->setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); break; default: break; @@ -416,7 +453,7 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", - address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData()); + address.toString().toLatin1().constData(), port, d->socketErrorString.toLatin1().constData()); #endif return false; @@ -426,17 +463,20 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == true", address.toString().toLatin1().constData(), port); #endif - socketState = QAbstractSocket::BoundState; + d->socketState = QAbstractSocket::BoundState; return true; } -bool QSymbianSocketEngine::listen(int backlog) +bool QSymbianSocketEngine::listen() { - TInt err = nativeSocket.Listen(backlog); + Q_D(QSymbianSocketEngine); + // TODO the value 50 is from the QNativeSocketEngine. Maybe it's a bit too much + // for a mobile platform + TInt err = d->nativeSocket.Listen(50); if (err) { switch (errno) { case KErrInUse: - setError(QAbstractSocket::AddressInUseError, + d->setError(QAbstractSocket::AddressInUseError, PortInuseErrorString); break; default: @@ -444,27 +484,28 @@ bool QSymbianSocketEngine::listen(int backlog) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeListen(%i) == false (%s)", - backlog, socketErrorString.toLatin1().constData()); + qDebug("QSymbianSocketEnginePrivate::nativeListen() == false (%s)", + d->socketErrorString.toLatin1().constData()); #endif return false; } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeListen(%i) == true", backlog); + qDebug("QSymbianSocketEnginePrivate::nativeListen() == true"); #endif - socketState = QAbstractSocket::ListeningState; + d->socketState = QAbstractSocket::ListeningState; return true; } int QSymbianSocketEngine::accept() { + Q_D(QSymbianSocketEngine); RSocket blankSocket; //TODO: this is unbelievably broken, needs to be properly async - blankSocket.Open(socketServer); + blankSocket.Open(d->socketServer); TRequestStatus status; - nativeSocket.Accept(blankSocket, status); + d->nativeSocket.Accept(blankSocket, status); User::WaitForRequest(status); if(status.Int()) { qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); @@ -477,11 +518,12 @@ int QSymbianSocketEngine::accept() qint64 QSymbianSocketEngine::bytesAvailable() const { + Q_D(const QSymbianSocketEngine); int nbytes = 0; qint64 available = 0; // FIXME is this the right thing also for UDP? // What is expected for UDP, the length for the next packet I guess? - TInt err = nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); + TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); if(err) return 0; available = (qint64) nbytes; @@ -494,34 +536,39 @@ qint64 QSymbianSocketEngine::bytesAvailable() const bool QSymbianSocketEngine::hasPendingDatagrams() const { + Q_D(const QSymbianSocketEngine); int nbytes; - TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); + TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); return err == KErrNone && nbytes > 0; //TODO: this is pretty horrible too... + // FIXME why? } qint64 QSymbianSocketEngine::pendingDatagramSize() const { + Q_D(const QSymbianSocketEngine); int nbytes; - TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); + TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); return qint64(nbytes-28); //TODO: why -28 (open C version had this)? // Why = Could it be that this is about header lengths etc? if yes // this could be pretty broken, especially for IPv6 } -qint64 QSymbianSocketEngine::nativeReceiveDatagram(char *data, qint64 maxSize, + +qint64 QSymbianSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { + Q_D(QSymbianSocketEngine); TPtr8 buffer((TUint8*)data, (int)maxSize); TInetAddr addr; TRequestStatus status; //TODO: OMG sync receive! - nativeSocket.RecvFrom(buffer, addr, 0, status); + d->nativeSocket.RecvFrom(buffer, addr, 0, status); User::WaitForRequest(status); if (status.Int()) { - setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); + d->setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); } else if (port || address) { - getPortAndAddress(addr, port, address); + d->getPortAndAddress(addr, port, address); } #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -537,15 +584,17 @@ qint64 QSymbianSocketEngine::nativeReceiveDatagram(char *data, qint64 maxSize, return qint64(buffer.Length()); } -qint64 QSymbianSocketEngine::sendDatagram(const char *data, qint64 len, + +qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port) { + Q_D(QSymbianSocketEngine); TPtrC8 buffer((TUint8*)data, (int)len); TInetAddr addr; - setPortAndAddress(addr, port, host); + d->setPortAndAddress(addr, port, host); TSockXfrLength sentBytes; TRequestStatus status; //TODO: OMG sync send! - nativeSocket.SendTo(buffer, addr, 0, status, sentBytes); + d->nativeSocket.SendTo(buffer, addr, 0, status, sentBytes); User::WaitForRequest(status); TInt err = status.Int(); @@ -568,6 +617,7 @@ qint64 QSymbianSocketEngine::sendDatagram(const char *data, qint64 len, return qint64(sentBytes()); } +// FIXME check where the native socket engine called that.. bool QSymbianSocketEnginePrivate::fetchConnectionParameters() { localPort = 0; @@ -611,7 +661,8 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() TProtocolDesc protocol; TInt err = nativeSocket.Info(protocol); if (err) { - QAbstractSocket::UnknownSocketType; + // ? + // QAbstractSocket::UnknownSocketType; } else { switch (protocol.iProtocol) { case KProtocolInetTcp: @@ -626,13 +677,13 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() } } #if defined (QNATIVESOCKETENGINE_DEBUG) - QString socketProtocolStr = "UnknownProtocol"; - if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol"; - else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol"; + QString socketProtocolStr = QLatin1String("UnknownProtocol"); + if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QLatin1String("IPv4Protocol"); + else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = QLatin1String("IPv6Protocol"); - QString socketTypeStr = "UnknownSocketType"; - if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket"; - else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket"; + QString socketTypeStr = QLatin1String("UnknownSocketType"); + if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QLatin1String("TcpSocket"); + else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QLatin1String("UdpSocket"); qDebug("QSymbianSocketEnginePrivate::fetchConnectionParameters() local == %s:%i," " peer == %s:%i, socket == %s - %s", @@ -645,22 +696,25 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() void QSymbianSocketEngine::close() { + Q_D(QSymbianSocketEngine); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEnginePrivate::nativeClose()"); #endif //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? - nativeSocket.Close(); - QSymbianSocketManager::instance().removeSocket(nativeSocket); + d->nativeSocket.Close(); + QSymbianSocketManager::instance().removeSocket(d->nativeSocket); + + // FIXME set nativeSocket to 0 ? } qint64 QSymbianSocketEngine::write(const char *data, qint64 len) { - Q_Q(QSymbianSocketEngine); + Q_D(QSymbianSocketEngine); TPtrC8 buffer((TUint8*)data, (int)len); TSockXfrLength sentBytes; TRequestStatus status; //TODO: OMG sync send! - nativeSocket.Send(buffer, 0, status, sentBytes); + d->nativeSocket.Send(buffer, 0, status, sentBytes); User::WaitForRequest(status); TInt err = status.Int(); @@ -668,16 +722,16 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) switch (err) { case KErrDisconnected: sentBytes = -1; - setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); - q->close(); + d->setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); + close(); break; case KErrTooBig: - setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); + d->setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; case KErrWouldBlock: sentBytes = 0; default: - setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + d->setError(QAbstractSocket::NetworkError, SendDatagramErrorString); } } @@ -693,8 +747,8 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) */ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) { - Q_Q(QSymbianSocketEngine); - if (!q->isValid()) { + Q_D(QSymbianSocketEngine); + if (!isValid()) { qWarning("QSymbianSocketEnginePrivate::nativeRead: Invalid socket"); return -1; } @@ -702,7 +756,7 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) TPtr8 buffer((TUint8*)data, (int)maxSize); TSockXfrLength received = 0; TRequestStatus status; //TODO: OMG sync receive! - nativeSocket.RecvOneOrMore(buffer, 0, status, received); + d->nativeSocket.RecvOneOrMore(buffer, 0, status, received); User::WaitForRequest(status); TInt err = status.Int(); int r = received(); @@ -732,6 +786,7 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) return qint64(r); } +// FIXME wait vs select int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const { bool readyRead = false; @@ -826,4 +881,36 @@ bool QSymbianSocketEngine::setMulticastInterface(const QNetworkInterface &iface) return false; } +bool QSymbianSocketEnginePrivate::checkProxy(const QHostAddress &address) +{ + if (address == QHostAddress::LocalHost || address == QHostAddress::LocalHostIPv6) + return true; + +#if !defined(QT_NO_NETWORKPROXY) + QObject *parent = q_func()->parent(); + QNetworkProxy proxy; + if (QAbstractSocket *socket = qobject_cast(parent)) { + proxy = socket->proxy(); + } else if (QTcpServer *server = qobject_cast(parent)) { + proxy = server->proxy(); + } else { + // no parent -> no proxy + return true; + } + + if (proxy.type() == QNetworkProxy::DefaultProxy) + proxy = QNetworkProxy::applicationProxy(); + + if (proxy.type() != QNetworkProxy::DefaultProxy && + proxy.type() != QNetworkProxy::NoProxy) { + // QNativeSocketEngine doesn't do proxies + setError(QAbstractSocket::UnsupportedSocketOperationError, + InvalidProxyTypeString); + return false; + } +#endif + + return true; +} + QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index fd449ca..0b385a9 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -207,6 +207,8 @@ public: int nativeSelect(int timeout, bool checkRead, bool checkWrite, bool *selectForRead, bool *selectForWrite) const; + bool createNewSocket(QAbstractSocket::SocketType socketType, + QAbstractSocket::NetworkLayerProtocol socketProtocol); bool checkProxy(const QHostAddress &address); bool fetchConnectionParameters(); -- cgit v0.12 From f71a7c4ef3c4c5a02730544d93200ef96d777aa0 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 11:49:09 +0100 Subject: QSymbianSocketEngine: More compile fixes --- src/network/socket/qsymbiansocketengine.cpp | 578 ++++++++++++++++++++++++---- src/network/socket/qsymbiansocketengine_p.h | 3 +- src/network/socket/socket.pri | 10 +- 3 files changed, 510 insertions(+), 81 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 7957baf..43f0a36 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -61,6 +61,14 @@ # include "qtcpserver.h" #endif +#include +#include +#include + +#include "qnativesocketengine_p.h" +#include +#include + #define QNATIVESOCKETENGINE_DEBUG #if defined QNATIVESOCKETENGINE_DEBUG @@ -173,70 +181,11 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so return false; } - // FIXME Set socket to nonblocking. While we are still a QNativeSocketEngine this is done already. - // Uncomment the following when we switch to QSymbianSocketEngine. - // setOption(NonBlockingSocketOption, 1) socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket); return true; } -/* - Returns the value of the socket option \a opt. -*/ -int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const -{ - Q_D(const QSymbianSocketEngine); - if (!isValid()) - return -1; - - TUint n; - TUint level = KSOLSocket; // default - - switch (opt) { - case QAbstractSocketEngine::ReceiveBufferSocketOption: - n = KSORecvBuf; - break; - case QAbstractSocketEngine::SendBufferSocketOption: - n = KSOSendBuf; - break; - case QAbstractSocketEngine::NonBlockingSocketOption: - n = KSONonBlockingIO; - break; - case QAbstractSocketEngine::BroadcastSocketOption: - return true; //symbian doesn't support or require this option - case QAbstractSocketEngine::AddressReusable: - level = KSolInetIp; - n = KSoReuseAddr; - break; - case QAbstractSocketEngine::BindExclusively: - return true; - case QAbstractSocketEngine::ReceiveOutOfBandData: - level = KSolInetTcp; - n = KSoTcpOobInline; - break; - case QAbstractSocketEngine::LowDelayOption: - level = KSolInetTcp; - n = KSoTcpNoDelay; - break; - case QAbstractSocketEngine::KeepAliveOption: - level = KSolInetTcp; - n = KSoTcpKeepAlive; - break; - default: - return -1; - } - - int v = -1; - //GetOpt() is non const - TInt err = d->nativeSocket.GetOpt(n, level, v); - if (!err) - return v; - - return -1; -} - - void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) { nativeAddr.SetPort(port); @@ -293,6 +242,150 @@ QSymbianSocketEngine::~QSymbianSocketEngine() // FIXME what else do we need to free? } +/*! + Initializes a QSymbianSocketEngine by creating a new socket of type \a + socketType and network layer protocol \a protocol. Returns true on + success; otherwise returns false. + + If the socket was already initialized, this function closes the + socket before reeinitializing it. + + The new socket is non-blocking, and for UDP sockets it's also + broadcast enabled. +*/ +bool QSymbianSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol protocol) +{ + Q_D(QSymbianSocketEngine); + if (isValid()) + close(); + +#if defined(QT_NO_IPV6) + if (protocol == QAbstractSocket::IPv6Protocol) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + d->NoIpV6ErrorString); + return false; + } +#endif + + // Create the socket + if (!d->createNewSocket(socketType, protocol)) { +#if defined (QNATIVESOCKETENGINE_DEBUG) + QString typeStr = QLatin1String("UnknownSocketType"); + if (socketType == QAbstractSocket::TcpSocket) typeStr = QLatin1String("TcpSocket"); + else if (socketType == QAbstractSocket::UdpSocket) typeStr = QLatin1String("UdpSocket"); + QString protocolStr = QLatin1String("UnknownProtocol"); + if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = QLatin1String("IPv4Protocol"); + else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = QLatin1String("IPv6Protocol"); + qDebug("QNativeSocketEngine::initialize(type == %s, protocol == %s) failed: %s", + typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), d->socketErrorString.toLatin1().constData()); +#endif + return false; + } + + // Make the socket nonblocking. + if (!setOption(NonBlockingSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + d->NonBlockingInitFailedErrorString); + close(); + return false; + } + + // Set the broadcasting flag if it's a UDP socket. + if (socketType == QAbstractSocket::UdpSocket + && !setOption(BroadcastSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + d->BroadcastingInitFailedErrorString); + close(); + return false; + } + + + // Make sure we receive out-of-band data + if (socketType == QAbstractSocket::TcpSocket + && !setOption(ReceiveOutOfBandData, 1)) { + qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); + } + + + d->socketType = socketType; + d->socketProtocol = protocol; + return true; +} + +/*! \overload + + Initializes the socket using \a socketDescriptor instead of + creating a new one. The socket type and network layer protocol are + determined automatically. The socket's state is set to \a + socketState. + + If the socket type is either TCP or UDP, it is made non-blocking. + UDP sockets are also broadcast enabled. + */ +bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::SocketState socketState) +{ + Q_D(QSymbianSocketEngine); + + if (isValid()) + close(); + + d->socketDescriptor = socketDescriptor; + + // determine socket type and protocol + if (!d->fetchConnectionParameters()) { +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QNativeSocketEngine::initialize(socketDescriptor == %i) failed: %s", + socketDescriptor, d->socketErrorString.toLatin1().constData()); +#endif + d->socketDescriptor = -1; + return false; + } + + if (d->socketType != QAbstractSocket::UnknownSocketType) { + // Make the socket nonblocking. + if (!setOption(NonBlockingSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + d->NonBlockingInitFailedErrorString); + close(); + return false; + } + + // Set the broadcasting flag if it's a UDP socket. + if (d->socketType == QAbstractSocket::UdpSocket + && !setOption(BroadcastSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + d->BroadcastingInitFailedErrorString); + close(); + return false; + } + } + + d->socketState = socketState; + return true; +} + +/*! + Returns true if the socket is valid; otherwise returns false. A + socket is valid if it has not been successfully initialized, or if + it has been closed. +*/ +bool QSymbianSocketEngine::isValid() const +{ + Q_D(const QSymbianSocketEngine); + return d->socketDescriptor != -1; +} + + +/*! + Returns the native socket descriptor. Any use of this descriptor + stands the risk of being non-portable. +*/ +int QSymbianSocketEngine::socketDescriptor() const +{ + Q_D(const QSymbianSocketEngine); + return d->socketDescriptor; +} + /* Sets the socket option \a opt to \a v. */ @@ -340,6 +433,61 @@ bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, in return (KErrNone == d->nativeSocket.SetOpt(n, level, v)); } +/* + Returns the value of the socket option \a opt. +*/ +int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const +{ + Q_D(const QSymbianSocketEngine); + if (!isValid()) + return -1; + + TUint n; + TUint level = KSOLSocket; // default + + switch (opt) { + case QAbstractSocketEngine::ReceiveBufferSocketOption: + n = KSORecvBuf; + break; + case QAbstractSocketEngine::SendBufferSocketOption: + n = KSOSendBuf; + break; + case QAbstractSocketEngine::NonBlockingSocketOption: + n = KSONonBlockingIO; + break; + case QAbstractSocketEngine::BroadcastSocketOption: + return true; //symbian doesn't support or require this option + case QAbstractSocketEngine::AddressReusable: + level = KSolInetIp; + n = KSoReuseAddr; + break; + case QAbstractSocketEngine::BindExclusively: + return true; + case QAbstractSocketEngine::ReceiveOutOfBandData: + level = KSolInetTcp; + n = KSoTcpOobInline; + break; + case QAbstractSocketEngine::LowDelayOption: + level = KSolInetTcp; + n = KSoTcpNoDelay; + break; + case QAbstractSocketEngine::KeepAliveOption: + level = KSolInetTcp; + n = KSoTcpKeepAlive; + break; + default: + return -1; + } + + int v = -1; + //GetOpt() is non const + TInt err = d->nativeSocket.GetOpt(n, level, v); + if (!err) + return v; + + return -1; +} + bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port) { // FIXME for engines that support hostnames.. not for us then i guess. @@ -347,6 +495,23 @@ bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port return false; } +/*! + If there's a connection activity on the socket, process it. Then + notify our parent if there really was activity. +*/ +void QSymbianSocketEngine::connectionNotification() +{ + // FIXME check if we really need to do it like that in Symbian + Q_D(QSymbianSocketEngine); + Q_ASSERT(state() == QAbstractSocket::ConnectingState); + + connectToHost(d->peerAddress, d->peerPort); + if (state() != QAbstractSocket::ConnectingState) { + // we changed states + QAbstractSocketEngine::connectionNotification(); + } +} + bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) { @@ -359,7 +524,7 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) #if defined (QT_NO_IPV6) if (addr.protocol() == QAbstractSocket::IPv6Protocol) { d->setError(QAbstractSocket::UnsupportedSocketOperationError, - NoIpV6ErrorString); + d->NoIpV6ErrorString); return false; } #endif @@ -379,25 +544,25 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) if (err) { switch (err) { case KErrCouldNotConnect: - d->setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); + d->setError(QAbstractSocket::ConnectionRefusedError, d->ConnectionRefusedErrorString); d->socketState = QAbstractSocket::UnconnectedState; break; case KErrTimedOut: - d->setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); + d->setError(QAbstractSocket::NetworkError, d->ConnectionTimeOutErrorString); break; case KErrHostUnreach: - d->setError(QAbstractSocket::NetworkError, HostUnreachableErrorString); + d->setError(QAbstractSocket::NetworkError, d->HostUnreachableErrorString); d->socketState = QAbstractSocket::UnconnectedState; break; case KErrNetUnreach: - d->setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString); + d->setError(QAbstractSocket::NetworkError, d->NetworkUnreachableErrorString); d->socketState = QAbstractSocket::UnconnectedState; break; case KErrInUse: - d->setError(QAbstractSocket::NetworkError, AddressInuseErrorString); + d->setError(QAbstractSocket::NetworkError, d->AddressInuseErrorString); break; case KErrPermissionDenied: - d->setError(QAbstractSocket::SocketAccessError, AccessErrorString); + d->setError(QAbstractSocket::SocketAccessError, d->AccessErrorString); d->socketState = QAbstractSocket::UnconnectedState; break; case KErrNotSupported: @@ -439,13 +604,13 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) if (err) { switch(errno) { case KErrInUse: - d->setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); + d->setError(QAbstractSocket::AddressInUseError, d->AddressInuseErrorString); break; case KErrPermissionDenied: - d->setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); + d->setError(QAbstractSocket::SocketAccessError, d->AddressProtectedErrorString); break; case KErrNotSupported: - d->setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); + d->setError(QAbstractSocket::UnsupportedSocketOperationError, d->OperationUnsupportedErrorString); break; default: break; @@ -477,7 +642,7 @@ bool QSymbianSocketEngine::listen() switch (errno) { case KErrInUse: d->setError(QAbstractSocket::AddressInUseError, - PortInuseErrorString); + d->PortInuseErrorString); break; default: break; @@ -566,7 +731,7 @@ qint64 QSymbianSocketEngine::readDatagram(char *data, qint64 maxSize, User::WaitForRequest(status); if (status.Int()) { - d->setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); + d->setError(QAbstractSocket::NetworkError, d->ReceiveDatagramErrorString); } else if (port || address) { d->getPortAndAddress(addr, port, address); } @@ -601,10 +766,10 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, if (err) { switch (err) { case KErrTooBig: - setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); + d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString); break; default: - setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + d->setError(QAbstractSocket::NetworkError, d->SendDatagramErrorString); } } @@ -722,16 +887,16 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) switch (err) { case KErrDisconnected: sentBytes = -1; - d->setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); + d->setError(QAbstractSocket::RemoteHostClosedError, d->RemoteHostClosedErrorString); close(); break; case KErrTooBig: - d->setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); + d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString); break; case KErrWouldBlock: sentBytes = 0; default: - d->setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + d->setError(QAbstractSocket::NetworkError, d->SendDatagramErrorString); } } @@ -913,4 +1078,265 @@ bool QSymbianSocketEnginePrivate::checkProxy(const QHostAddress &address) return true; } +// FIXME this is also in QNativeSocketEngine, unify it +/*! \internal + + Sets the error and error string if not set already. The only + interesting error is the first one that occurred, and not the last + one. +*/ +void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const +{ + if (hasSetSocketError) { + // Only set socket errors once for one engine; expect the + // socket to recreate its engine after an error. Note: There's + // one exception: SocketError(11) bypasses this as it's purely + // a temporary internal error condition. + // Another exception is the way the waitFor*() functions set + // an error when a timeout occurs. After the call to setError() + // they reset the hasSetSocketError to false + return; + } + if (error != QAbstractSocket::SocketError(11)) + hasSetSocketError = true; + + socketError = error; + + switch (errorString) { + case NonBlockingInitFailedErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unable to initialize non-blocking socket"); + break; + case BroadcastingInitFailedErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unable to initialize broadcast socket"); + break; + case NoIpV6ErrorString: + socketErrorString = QSymbianSocketEngine::tr("Attempt to use IPv6 socket on a platform with no IPv6 support"); + break; + case RemoteHostClosedErrorString: + socketErrorString = QSymbianSocketEngine::tr("The remote host closed the connection"); + break; + case TimeOutErrorString: + socketErrorString = QSymbianSocketEngine::tr("Network operation timed out"); + break; + case ResourceErrorString: + socketErrorString = QSymbianSocketEngine::tr("Out of resources"); + break; + case OperationUnsupportedErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unsupported socket operation"); + break; + case ProtocolUnsupportedErrorString: + socketErrorString = QSymbianSocketEngine::tr("Protocol type not supported"); + break; + case InvalidSocketErrorString: + socketErrorString = QSymbianSocketEngine::tr("Invalid socket descriptor"); + break; + case HostUnreachableErrorString: + socketErrorString = QSymbianSocketEngine::tr("Host unreachable"); + break; + case NetworkUnreachableErrorString: + socketErrorString = QSymbianSocketEngine::tr("Network unreachable"); + break; + case AccessErrorString: + socketErrorString = QSymbianSocketEngine::tr("Permission denied"); + break; + case ConnectionTimeOutErrorString: + socketErrorString = QSymbianSocketEngine::tr("Connection timed out"); + break; + case ConnectionRefusedErrorString: + socketErrorString = QSymbianSocketEngine::tr("Connection refused"); + break; + case AddressInuseErrorString: + socketErrorString = QSymbianSocketEngine::tr("The bound address is already in use"); + break; + case AddressNotAvailableErrorString: + socketErrorString = QSymbianSocketEngine::tr("The address is not available"); + break; + case AddressProtectedErrorString: + socketErrorString = QSymbianSocketEngine::tr("The address is protected"); + break; + case DatagramTooLargeErrorString: + socketErrorString = QSymbianSocketEngine::tr("Datagram was too large to send"); + break; + case SendDatagramErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unable to send a message"); + break; + case ReceiveDatagramErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unable to receive a message"); + break; + case WriteErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unable to write"); + break; + case ReadErrorString: + socketErrorString = QSymbianSocketEngine::tr("Network error"); + break; + case PortInuseErrorString: + socketErrorString = QSymbianSocketEngine::tr("Another socket is already listening on the same port"); + break; + case NotSocketErrorString: + socketErrorString = QSymbianSocketEngine::tr("Operation on non-socket"); + break; + case InvalidProxyTypeString: + socketErrorString = QSymbianSocketEngine::tr("The proxy type is invalid for this operation"); + break; + case UnknownSocketErrorString: + socketErrorString = QSymbianSocketEngine::tr("Unknown error"); + break; + } +} + +class QReadNotifier : public QSocketNotifier +{ +public: + QReadNotifier(int fd, QSymbianSocketEngine *parent) + : QSocketNotifier(fd, QSocketNotifier::Read, parent) + { engine = parent; } +protected: + QSymbianSocketEngine *engine; +}; + +bool QSymbianSocketEngine::isReadNotificationEnabled() const +{ + Q_D(const QSymbianSocketEngine); + // TODO + return d->readNotifier && d->readNotifier->isEnabled(); +} + +void QSymbianSocketEngine::setReadNotificationEnabled(bool enable) +{ + Q_D(QSymbianSocketEngine); + // TODO + if (d->readNotifier) { + d->readNotifier->setEnabled(enable); + } else if (enable && d->threadData->eventDispatcher) { + d->readNotifier = new QReadNotifier(d->socketDescriptor, this); + d->readNotifier->setEnabled(true); + } +} + + +class QWriteNotifier : public QSocketNotifier +{ +public: + QWriteNotifier(int fd, QSymbianSocketEngine *parent) + : QSocketNotifier(fd, QSocketNotifier::Read, parent) + { engine = parent; } +protected: + QSymbianSocketEngine *engine; +}; + +bool QSymbianSocketEngine::isWriteNotificationEnabled() const +{ + Q_D(const QSymbianSocketEngine); + // TODO + return d->writeNotifier && d->writeNotifier->isEnabled(); +} + +void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) +{ + Q_D(QSymbianSocketEngine); + // TODO + if (d->writeNotifier) { + d->writeNotifier->setEnabled(enable); + } else if (enable && d->threadData->eventDispatcher) { + d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this); + d->writeNotifier->setEnabled(true); + } +} + +// FIXME do we really need this for symbian? +bool QSymbianSocketEngine::isExceptionNotificationEnabled() const +{ +// Q_D(const QSymbianSocketEngine); +// // TODO +// return d->exceptNotifier && d->exceptNotifier->isEnabled(); + return false; +} + +// FIXME do we really need this for symbian? +void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) +{ + Q_D(QSymbianSocketEngine); + // TODO +// if (d->exceptNotifier) { +// d->exceptNotifier->setEnabled(enable); +// } else if (enable && d->threadData->eventDispatcher) { +// d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this); +// d->exceptNotifier->setEnabled(true); +// } +} + +bool QSymbianSocketEngine::waitForRead(int msecs, bool *timedOut) +{ + Q_D(const QSymbianSocketEngine); + + if (timedOut) + *timedOut = false; + + int ret = d->nativeSelect(msecs, true); + if (ret == 0) { + if (timedOut) + *timedOut = true; + d->setError(QAbstractSocket::SocketTimeoutError, + d->TimeOutErrorString); + d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions + return false; + } else if (state() == QAbstractSocket::ConnectingState) { + connectToHost(d->peerAddress, d->peerPort); + } + + return ret > 0; +} + +bool QSymbianSocketEngine::waitForWrite(int msecs, bool *timedOut) +{ + Q_D(QSymbianSocketEngine); + + if (timedOut) + *timedOut = false; + + int ret = d->nativeSelect(msecs, false); + + if (ret == 0) { + if (timedOut) + *timedOut = true; + d->setError(QAbstractSocket::SocketTimeoutError, + d->TimeOutErrorString); + d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions + return false; + } else if (state() == QAbstractSocket::ConnectingState) { + connectToHost(d->peerAddress, d->peerPort); + } + + return ret > 0; +} + +bool QSymbianSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, + bool checkRead, bool checkWrite, + int msecs, bool *timedOut) +{ + Q_D(QSymbianSocketEngine); + + int ret = d->nativeSelect(msecs, checkRead, checkWrite, readyToRead, readyToWrite); + + if (ret == 0) { + if (timedOut) + *timedOut = true; + d->setError(QAbstractSocket::SocketTimeoutError, + d->TimeOutErrorString); + d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions + return false; + } else if (state() == QAbstractSocket::ConnectingState) { + connectToHost(d->peerAddress, d->peerPort); + } + + return ret > 0; +} + +qint64 QSymbianSocketEngine::bytesToWrite() const +{ + // This is what the QNativeSocketEngine does + return 0; +} + + QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 0b385a9..0c8bc53 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -165,6 +165,7 @@ public: QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; + // FIXME this is duplicated from qnativesocketengine_p.h enum ErrorString { NonBlockingInitFailedErrorString, BroadcastingInitFailedErrorString, @@ -194,13 +195,13 @@ public: UnknownSocketErrorString = -1 }; + void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; #ifdef Q_OS_SYMBIAN void getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr); void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr); void setError(TInt symbianError); #endif - void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; // FIXME int nativeSelect(int timeout, bool selectForRead) const; diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index 3356cdd..3eb54a2 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -1,7 +1,6 @@ # Qt network socket HEADERS += socket/qabstractsocketengine_p.h \ - socket/qnativesocketengine_p.h \ socket/qhttpsocketengine_p.h \ socket/qsocks5socketengine_p.h \ socket/qabstractsocket.h \ @@ -15,7 +14,6 @@ HEADERS += socket/qabstractsocketengine_p.h \ socket/qlocalsocket_p.h SOURCES += socket/qabstractsocketengine.cpp \ - socket/qnativesocketengine.cpp \ socket/qhttpsocketengine.cpp \ socket/qsocks5socketengine.cpp \ socket/qabstractsocket.cpp \ @@ -25,10 +23,14 @@ SOURCES += socket/qabstractsocketengine.cpp \ socket/qlocalsocket.cpp \ socket/qlocalserver.cpp -unix:!symbian:SOURCES += socket/qnativesocketengine_unix.cpp - +# On Symbian we use QSymbianSocketEngine symbian:SOURCES += socket/qsymbiansocketengine.cpp symbian:HEADERS += socket/qsymbiansocketengine_p.h +# On others we use QNativeSocketEngine +!symbian:SOURCES += socket/qnativesocketengine.cpp +!symbian:HEADERS += socket/qnativesocketengine_p.h + +unix:!symbian:SOURCES += socket/qnativesocketengine_unix.cpp unix:SOURCES += \ socket/qlocalsocket_unix.cpp \ -- cgit v0.12 From fc3f909c0cbbe15f2079edefe66ce52eb127a326 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 12:14:26 +0100 Subject: QSymbianSocketEngine: Always support IPv6 --- src/network/kernel/qnetworkproxy_symbian.cpp | 17 +++++++------ src/network/socket/qsymbiansocketengine.cpp | 37 +--------------------------- 2 files changed, 11 insertions(+), 43 deletions(-) diff --git a/src/network/kernel/qnetworkproxy_symbian.cpp b/src/network/kernel/qnetworkproxy_symbian.cpp index 62266d1..7f53b4d 100644 --- a/src/network/kernel/qnetworkproxy_symbian.cpp +++ b/src/network/kernel/qnetworkproxy_symbian.cpp @@ -48,14 +48,17 @@ QT_BEGIN_NAMESPACE QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &) { // TODO: Get the current QNetworkSession which has the Symbian RConnection we use - // I am wondering if we already have a connected QNetworkSession when the code - // is run that retrieves the proxy (for QNetworkAccessManager it's somewhere called - // from createRequest() which might be too early...) - - // TODO: Get the proxy from that RConnection + // I am wondering if we already have a connected QNetworkSession when the code + // is run that retrieves the proxy (for QNetworkAccessManager it's somewhere called + // from createRequest() which might be too early...) - // See http://bugreports.qt.nokia.com/browse/QTBUG-13857 and http://bugreports.qt.nokia.com/browse/QTBUG-11016 - // and the mails we have received. + // TODO: Get the proxy from that RConnection + + // The QNetworkProxyQuery could have a QNetworkSession and then take the RConnection + // from there. If it does not have one, we have to use the "global RConnection". + + // See http://bugreports.qt.nokia.com/browse/QTBUG-13857 and http://bugreports.qt.nokia.com/browse/QTBUG-11016 + // and the mails we have received. // Default case: No network proxy found/needed return QList() << QNetworkProxy::NoProxy; diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 43f0a36..a937f7c 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -49,9 +49,7 @@ #include "qnetworkinterface.h" #include #include -#ifndef QT_NO_IPV6IFNAME #include -#endif #include @@ -112,7 +110,6 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) { -#if !defined(QT_NO_IPV6) if (a.Family() == KAfInet6) { Q_IPV6ADDR tmp; memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp)); @@ -120,21 +117,18 @@ void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 QHostAddress tmpAddress; tmpAddress.setAddress(tmp); *addr = tmpAddress; -#ifndef QT_NO_IPV6IFNAME TPckgBuf query; query().iSrcAddr = a; TInt err = nativeSocket.GetOpt(KSoInetIfQueryBySrcAddr, KSolInetIfQuery, query); if(!err) addr->setScopeId(qt_TDesC2QString(query().iName)); else -#endif addr->setScopeId(QString::number(a.Scope())); } if (port) *port = a.Port(); return; } -#endif if (port) *port = a.Port(); if (addr) { @@ -152,12 +146,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so QAbstractSocket::NetworkLayerProtocol socketProtocol) { Q_Q(QSymbianSocketEngine); -#ifndef QT_NO_IPV6 TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet; -#else - Q_UNUSED(socketProtocol); - TUint family = KAfInet; -#endif TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; TInt err = nativeSocket.Open(socketServer, family, type, protocol, *connection); @@ -189,9 +178,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) { nativeAddr.SetPort(port); -#if !defined(QT_NO_IPV6) if (addr.protocol() == QAbstractSocket::IPv6Protocol) { -#ifndef QT_NO_IPV6IFNAME TPckgBuf query; query().iName = qt_QString2TPtrC(addr.scopeId()); TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); @@ -199,16 +186,11 @@ void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint nativeAddr.SetScope(query().iIndex); else nativeAddr.SetScope(0); -#else - nativeAddr.SetScope(addr.scopeId().toInt()); -#endif Q_IPV6ADDR ip6 = addr.toIPv6Address(); TIp6Addr v6addr; memcpy(v6addr.u.iAddr8, ip6.c, 16); nativeAddr.SetAddress(v6addr); - } else -#endif - if (addr.protocol() == QAbstractSocket::IPv4Protocol) { + } else if (addr.protocol() == QAbstractSocket::IPv4Protocol) { nativeAddr.SetAddress(addr.toIPv4Address()); } else { qWarning("unsupported network protocol (%d)", addr.protocol()); @@ -259,14 +241,6 @@ bool QSymbianSocketEngine::initialize(QAbstractSocket::SocketType socketType, QA if (isValid()) close(); -#if defined(QT_NO_IPV6) - if (protocol == QAbstractSocket::IPv6Protocol) { - d->setError(QAbstractSocket::UnsupportedSocketOperationError, - d->NoIpV6ErrorString); - return false; - } -#endif - // Create the socket if (!d->createNewSocket(socketType, protocol)) { #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -521,13 +495,6 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) qDebug("QSymbianSocketEngine::connectToHost() : %d ", d->socketDescriptor); #endif -#if defined (QT_NO_IPV6) - if (addr.protocol() == QAbstractSocket::IPv6Protocol) { - d->setError(QAbstractSocket::UnsupportedSocketOperationError, - d->NoIpV6ErrorString); - return false; - } -#endif if (!d->checkProxy(addr)) return false; @@ -808,11 +775,9 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() case KAfInet: socketProtocol = QAbstractSocket::IPv4Protocol; break; -#if !defined (QT_NO_IPV6) case KAfInet6: socketProtocol = QAbstractSocket::IPv6Protocol; break; -#endif default: socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol; break; -- cgit v0.12 From 0975f046497deccd57b59aacded3ffc3c3c912f6 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 12:44:51 +0100 Subject: QNativeSocketEngine: Remove symbian code --- src/network/socket/qnativesocketengine_p.h | 7 -- src/network/socket/qnativesocketengine_unix.cpp | 105 +----------------------- 2 files changed, 1 insertion(+), 111 deletions(-) diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 1f13433..b122722 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -60,13 +60,6 @@ # include #endif -#ifdef Q_OS_SYMBIAN -#include -#include -#include -#include -#endif - QT_BEGIN_NAMESPACE // Use our own defines and structs which we know are correct diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index aa55009..47a9084 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -65,12 +65,7 @@ #include #endif -#ifdef Q_OS_SYMBIAN // ### TODO: Are these headers right? -#include -#include -#else #include -#endif QT_BEGIN_NAMESPACE @@ -1049,11 +1044,7 @@ void QNativeSocketEnginePrivate::nativeClose() qDebug("QNativeSocketEngine::nativeClose()"); #endif -#ifdef Q_OS_SYMBIAN - ::close(socketDescriptor); -#else - qt_safe_close(socketDescriptor); -#endif + qt_safe_close(socketDescriptor); } qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) @@ -1064,12 +1055,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) qt_ignore_sigpipe(); ssize_t writtenBytes; -#ifdef Q_OS_SYMBIAN - // Symbian does not support signals natively and Open C returns EINTR when moving to offline - writtenBytes = ::write(socketDescriptor, data, len); -#else writtenBytes = qt_safe_write(socketDescriptor, data, len); -#endif if (writtenBytes < 0) { switch (errno) { @@ -1109,11 +1095,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) } ssize_t r = 0; -#ifdef Q_OS_SYMBIAN - r = ::read(socketDescriptor, data, maxSize); -#else r = qt_safe_read(socketDescriptor, data, maxSize); -#endif if (r < 0) { r = -1; @@ -1130,9 +1112,6 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) case EIO: //error string is now set in read(), not here in nativeRead() break; -#ifdef Q_OS_SYMBIAN - case EPIPE: -#endif case ECONNRESET: #if defined(Q_OS_VXWORKS) case ESHUTDOWN: @@ -1163,40 +1142,11 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) co tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; -#ifdef Q_OS_SYMBIAN - fd_set fdexception; - FD_ZERO(&fdexception); - FD_SET(socketDescriptor, &fdexception); -#endif - int retval; if (selectForRead) -#ifdef Q_OS_SYMBIAN - retval = ::select(socketDescriptor + 1, &fds, 0, &fdexception, timeout < 0 ? 0 : &tv); -#else retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); -#endif else -#ifdef Q_OS_SYMBIAN - retval = ::select(socketDescriptor + 1, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv); -#else retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); -#endif - - -#ifdef Q_OS_SYMBIAN - bool selectForExec = false; - if(retval != 0) { - if(retval < 0) { - qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor); - } - selectForExec = FD_ISSET(socketDescriptor, &fdexception); - } - if(selectForExec) { - qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected exception for fd %d", - selectForRead, retval, errno, socketDescriptor); - } -#endif return retval; } @@ -1214,65 +1164,12 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c if (checkWrite) FD_SET(socketDescriptor, &fdwrite); -#ifdef Q_OS_SYMBIAN - fd_set fdexception; - FD_ZERO(&fdexception); - FD_SET(socketDescriptor, &fdexception); -#endif - struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; int ret; -#ifndef Q_OS_SYMBIAN ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); -#else - QElapsedTimer timer; - timer.start(); - - do { - ret = ::select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv); - bool selectForExec = false; - if(ret != 0) { - if(ret < 0) { - qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor); - } - selectForExec = FD_ISSET(socketDescriptor, &fdexception); - } - if(selectForExec) { - qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d", - checkRead, checkWrite, ret, errno, socketDescriptor); - if (checkWrite){ - FD_CLR(socketDescriptor, &fdread); - FD_SET(socketDescriptor, &fdwrite); - } else if (checkRead) - FD_SET(socketDescriptor, &fdread); - - - if ((ret == -1) && ( errno == ECONNREFUSED || errno == EPIPE )) - ret = 1; - - } - - if (ret != -1 || errno != EINTR) { - break; - } - - if (timeout > 0) { - // recalculate the timeout - int t = timeout - timer.elapsed(); - if (t < 0) { - // oops, timeout turned negative? - ret = -1; - break; - } - - tv.tv_sec = t / 1000; - tv.tv_usec = (t % 1000) * 1000; - } - } while (true); -#endif if (ret <= 0) return ret; -- cgit v0.12 From 4b31d0c75755a57667d5d76e44e4b8653aa15219 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 12:50:50 +0100 Subject: Symbian: Enable IPv6 again. The native QSymbianSocketEngine supports IPv6 just fine. This reverts commit 0c7d5d106152924dedd822da8c90d9f3247a9947. --- configure | 8 ++------ tools/configure/configureapp.cpp | 4 ---- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 05b5629..401299b 100755 --- a/configure +++ b/configure @@ -6463,13 +6463,9 @@ fi # find if the platform supports IPv6 if [ "$CFG_IPV6" != "no" ]; then - # - # We accidently enabled IPv6 for Qt Symbian in 4.6.x. However the underlying OpenC does not fully support IPV6. - # Therefore for 4.7.1 and following we disable it until OpenC either supports it or we have the native Qt - # symbian socket engine. - # if [ "$XPLATFORM_SYMBIAN" = "yes" ]; then - CFG_IPV6=no + #IPV6 should always be enabled for Symbian release + CFG_IPV6=yes elif "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/ipv6 "IPv6" $L_FLAGS $I_FLAGS $l_FLAGS $MAC_CONFIG_TEST_COMMANDLINE; then CFG_IPV6=yes else diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 479fd4c..f4a558d 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1522,10 +1522,6 @@ void Configure::applySpecSpecifics() dictionary[ "QT3SUPPORT" ] = "no"; dictionary[ "OPENGL" ] = "no"; dictionary[ "OPENSSL" ] = "yes"; - // We accidently enabled IPv6 for Qt Symbian in 4.6.x. However the underlying OpenC does not fully support IPV6. - // Therefore for 4.7.1 and following we disable it until OpenC either supports it or we have the native Qt - // symbian socket engine. - dictionary[ "IPV6" ] = "no"; dictionary[ "STL" ] = "yes"; dictionary[ "EXCEPTIONS" ] = "yes"; dictionary[ "RTTI" ] = "yes"; -- cgit v0.12 From f237b3ff201c271c386c912f496069825fd5cc12 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 13:02:16 +0100 Subject: Symbian: Also force IPv6 on Windows configure.exe --- tools/configure/configureapp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index f4a558d..62e7859 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1522,6 +1522,8 @@ void Configure::applySpecSpecifics() dictionary[ "QT3SUPPORT" ] = "no"; dictionary[ "OPENGL" ] = "no"; dictionary[ "OPENSSL" ] = "yes"; + // On Symbian we now always will have IPv6 with no chance to disable it + dictionary[ "IPV6" ] = "yes"; dictionary[ "STL" ] = "yes"; dictionary[ "EXCEPTIONS" ] = "yes"; dictionary[ "RTTI" ] = "yes"; -- cgit v0.12 From 664bd5adea54a2235414878d9cc4f1197fa2bd53 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 8 Dec 2010 13:06:14 +0000 Subject: Fix compile errors including qnativesocketengine_p.h causes link errors Reviewed-by: Markus Goetz --- src/network/socket/qabstractsocket_p.h | 2 +- src/network/socket/qlocalserver_p.h | 2 +- src/network/socket/qlocalsocket_p.h | 2 +- src/network/socket/qsymbiansocketengine.cpp | 1 - src/network/socket/qsymbiansocketengine_p.h | 2 -- src/network/socket/qtcpserver.cpp | 2 +- 6 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 8ca83fc..732d609 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -59,7 +59,7 @@ #include "QtCore/qtimer.h" #include "private/qringbuffer_p.h" #include "private/qiodevice_p.h" -#include "private/qnativesocketengine_p.h" +#include "private/qabstractsocketengine_p.h" #include "qnetworkproxy.h" QT_BEGIN_NAMESPACE diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h index 4f92b64..e9c8563 100644 --- a/src/network/socket/qlocalserver_p.h +++ b/src/network/socket/qlocalserver_p.h @@ -65,7 +65,7 @@ # include # include #else -# include +# include # include #endif diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 57ca3c2..7b912fb 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -67,7 +67,7 @@ # include "private/qringbuffer_p.h" # include #else -# include "private/qnativesocketengine_p.h" +# include "private/qabstractsocketengine_p.h" # include # include # include diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index a937f7c..1d2a11b 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -63,7 +63,6 @@ #include #include -#include "qnativesocketengine_p.h" #include #include diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 0c8bc53..3111442 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -154,14 +154,12 @@ public: ~QSymbianSocketEnginePrivate(); int socketDescriptor; -#ifdef Q_OS_SYMBIAN mutable RSocket nativeSocket; // From QtCore: RSocketServ& socketServer; // From QtCore, check lifetime issues, also should be pulling this out of a QNetworkSession somehow: RConnection *connection; mutable RTimer selectTimer; -#endif QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index 0640c7c..642983f 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -105,7 +105,7 @@ #include "qhostaddress.h" #include "qlist.h" #include "qpointer.h" -#include "qnativesocketengine_p.h" +#include "qabstractsocketengine_p.h" #include "qtcpserver.h" #include "qtcpsocket.h" #include "qnetworkproxy.h" -- cgit v0.12 From a50a764095f4894790dcb5bdfeb845ca65da7501 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 14:38:19 +0100 Subject: Remove more Q_OS_SYMBIAN stuff from network code --- src/network/kernel/qhostinfo_unix.cpp | 13 +---- src/network/socket/qnativesocketengine_unix.cpp | 64 +++---------------------- src/network/socket/qsymbiansocketengine_p.h | 2 - 3 files changed, 7 insertions(+), 72 deletions(-) diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 5ca15a3..cb1ec43 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -147,7 +147,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) if (address.setAddress(hostName)) { // Reverse lookup // Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. -#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) && !defined (Q_OS_SYMBIAN) +#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) sockaddr_in sa4; #ifndef QT_NO_IPV6 sockaddr_in6 sa6; @@ -208,23 +208,12 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #ifdef Q_ADDRCONFIG hints.ai_flags = Q_ADDRCONFIG; #endif -#ifdef Q_OS_SYMBIAN -# ifdef QHOSTINFO_DEBUG - qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'"; -# endif -#endif int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); # ifdef Q_ADDRCONFIG if (result == EAI_BADFLAGS) { // if the lookup failed with AI_ADDRCONFIG set, try again without it hints.ai_flags = 0; -#ifdef Q_OS_SYMBIAN -# ifdef QHOSTINFO_DEBUG - qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'"; -# endif - hints.ai_flags &= AI_V4MAPPED | AI_ALL; -#endif result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); } # endif diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 47a9084..1aaa6e6 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -169,11 +169,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc int protocol = AF_INET; #endif int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM; -#ifdef Q_OS_SYMBIAN - int socket = ::socket(protocol, type, 0); -#else + int socket = qt_safe_socket(protocol, type, 0); -#endif if (socket <= 0) { switch (errno) { @@ -318,11 +315,9 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt } #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 @@ -332,7 +327,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return true; } case QNativeSocketEngine::AddressReusable: -#if defined(SO_REUSEPORT) && !defined(Q_OS_SYMBIAN) +#if defined(SO_REUSEPORT) n = SO_REUSEPORT; #else n = SO_REUSEADDR; @@ -425,11 +420,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 } 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: @@ -472,9 +464,6 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 case EBADF: case EFAULT: case ENOTSOCK: -#ifdef Q_OS_SYMBIAN - case EPIPE: -#endif socketState = QAbstractSocket::UnconnectedState; default: break; @@ -573,11 +562,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 bool QNativeSocketEnginePrivate::nativeListen(int backlog) { -#ifdef Q_OS_SYMBIAN - if (::listen(socketDescriptor, backlog) < 0) { -#else if (qt_safe_listen(socketDescriptor, backlog) < 0) { -#endif switch (errno) { case EADDRINUSE: setError(QAbstractSocket::AddressInUseError, @@ -604,21 +589,12 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog) int QNativeSocketEnginePrivate::nativeAccept() { -#ifdef Q_OS_SYMBIAN - int acceptedDescriptor = ::accept(socketDescriptor, 0, 0); -#else int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0); -#endif //check if we have valid descriptor at all if(acceptedDescriptor > 0) { // Ensure that the socket is closed on exec*() ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC); } -#ifdef Q_OS_SYMBIAN - else { - qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0"); - } -#endif return acceptedDescriptor; } @@ -793,11 +769,7 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const int nbytes = 0; // gives shorter than true amounts on Unix domain sockets. qint64 available = 0; -#ifdef Q_OS_SYMBIAN - if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0) -#else if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0) -#endif available = (qint64) nbytes; #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -816,15 +788,10 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const // Peek 0 bytes into the next message. The size of the message may // well be 0, so we can't check recvfrom's return value. ssize_t readBytes; -#ifdef Q_OS_SYMBIAN - char c; - readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize); -#else do { char c; readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize); } while (readBytes == -1 && errno == EINTR); -#endif // If there's no error, or if our buffer was too small, there must be a // pending datagram. @@ -837,14 +804,6 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const return result; } -#ifdef Q_OS_SYMBIAN -qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const -{ - size_t nbytes = 0; - ::ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes); - return qint64(nbytes-28); -} -#else qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const { QVarLengthArray udpMessagePeekBuffer(8192); @@ -871,7 +830,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const return qint64(recvResult); } -#endif + qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { @@ -881,17 +840,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS sz = sizeof(aa); ssize_t recvFromResult = 0; -#ifdef Q_OS_SYMBIAN - char c; - recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, - 0, &aa.a, &sz); -#else do { char c; recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, 0, &aa.a, &sz); } while (recvFromResult == -1 && errno == EINTR); -#endif if (recvFromResult == -1) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); @@ -940,13 +893,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l // ignore the SIGPIPE signal qt_ignore_sigpipe(); -#ifdef Q_OS_SYMBIAN - ssize_t sentBytes = ::sendto(socketDescriptor, data, len, - 0, sockAddrPtr, sockAddrSize); -#else ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len, 0, sockAddrPtr, sockAddrSize); -#endif if (sentBytes < 0) { switch (errno) { diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 3111442..43e5e61 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -195,11 +195,9 @@ public: }; void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; -#ifdef Q_OS_SYMBIAN void getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr); void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr); void setError(TInt symbianError); -#endif // FIXME int nativeSelect(int timeout, bool selectForRead) const; -- cgit v0.12 From a97d9d6f2038ddab25d3721817b121dcea61f571 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 15:57:34 +0100 Subject: Added manual test for socketengine development --- tests/manual/socketengine/main.cpp | 110 +++++++++++++++++++++++++++++ tests/manual/socketengine/socketengine.pro | 13 ++++ 2 files changed, 123 insertions(+) create mode 100644 tests/manual/socketengine/main.cpp create mode 100644 tests/manual/socketengine/socketengine.pro diff --git a/tests/manual/socketengine/main.cpp b/tests/manual/socketengine/main.cpp new file mode 100644 index 0000000..f368573 --- /dev/null +++ b/tests/manual/socketengine/main.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "../../auto/network-settings.h" +#include +#include +#include +#include +#include + +const int bufsize = 16*1024; +char buf[bufsize]; + +int main(int argc, char**argv) +{ + // create it + QAbstractSocketEngine *socketEngine = + QAbstractSocketEngine::createSocketEngine(QAbstractSocket::TcpSocket, QNetworkProxy(QNetworkProxy::NoProxy), 0); + if (!socketEngine) { + qDebug() << "could not create engine"; + exit(1); + } + + // initialize it + bool initialized = socketEngine->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol); + if (!initialized) { + qDebug() << "not able to initialize engine"; + exit(1); + } + + // wait for connected + socketEngine->connectToHost(QHostAddress("74.125.77.99"), 80); // google + bool readyToRead = false; + bool readyToWrite = false; + socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, true, 10*1000); + if (readyToWrite) { + // write the request + QByteArray request("GET /robots.txt HTTP/1.0\r\n\r\n"); + int ret = socketEngine->write(request.constData(), request.length()); + if (ret == request.length()) { + // read the response in a loop + do { + bool waitReadResult = socketEngine->waitForRead(10*1000); + int available = socketEngine->bytesAvailable(); + if (waitReadResult == true && available == 0) { + // disconnected + exit(0); + } + bzero(buf, bufsize); + ret = socketEngine->read(buf, available); + if (ret > 0) { + printf("%s", buf); + } else { + // some failure when reading + exit(1); + } + } while (1); + } else { + qDebug() << "failed writing"; + } + } else { + qDebug() << "failed connecting"; + } + delete socketEngine; +} + diff --git a/tests/manual/socketengine/socketengine.pro b/tests/manual/socketengine/socketengine.pro new file mode 100644 index 0000000..96d0055 --- /dev/null +++ b/tests/manual/socketengine/socketengine.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_socketengine +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui +QT += network + +CONFIG += release + +# Input +SOURCES += main.cpp -- cgit v0.12 From 12974d3dad6a8db29479dd1bbf9d280081d60d58 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 8 Dec 2010 16:47:07 +0000 Subject: Implement sync & async select for symbian socket engine Async select is implemented with an active object rather than using the event dispatcher. Sync select is implemented using User::WaitForRequest to block the thread without requiring an event loop. In both cases, RSocket's KIoctlSelect is used to query the socket state. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 253 +++++++++++++++++++++++----- src/network/socket/qsymbiansocketengine_p.h | 36 ++++ 2 files changed, 244 insertions(+), 45 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 1d2a11b..ad1164a 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -938,49 +938,65 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) c int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, bool *selectForRead, bool *selectForWrite) const { + //cancel asynchronous notifier (only one IOCTL allowed at a time) + if (asyncSelect) + asyncSelect->Cancel(); //TODO: implement //as above, but checking both read and write status at the same time - if (!selectTimer.Handle()) - qt_symbian_throwIfError(selectTimer.CreateLocal()); - TRequestStatus timerStat; - selectTimer.HighRes(timerStat, timeout * 1000); - TRequestStatus* readStat = 0; - TRequestStatus* writeStat = 0; - TRequestStatus* array[3]; - array[0] = &timerStat; - int count = 1; - if (checkRead) { - //TODO: get from read AO - //readStat = ? - array[count++] = readStat; - } - if (checkWrite) { - //TODO: get from write AO - //writeStat = ? - array[count++] = writeStat; - } - // TODO: for selecting, we can use getOpt(KSOSelectPoll) to get the select result - // and KIOCtlSelect for the selecting. - User::WaitForNRequest(array, count); - //IMPORTANT - WaitForNRequest only decrements the thread semaphore once, although more than one status may have completed. - if (timerStat.Int() != KRequestPending) { - //timed out - return 0; + TPckgBuf selectFlags; + selectFlags() = KSockSelectExcept; + if (selectForRead) + selectFlags() |= KSockSelectRead; + if (selectForWrite) + selectFlags() |= KSockSelectWrite; + TRequestStatus selectStat; + nativeSocket.Ioctl(KIOctlSelect, selectStat, &selectFlags, KSOLSocket); + + if (timeout < 0) + User::WaitForRequest(selectStat); //negative means no timeout + else { + if (!selectTimer.Handle()) + qt_symbian_throwIfError(selectTimer.CreateLocal()); + TRequestStatus timerStat; + selectTimer.HighRes(timerStat, timeout * 1000); + User::WaitForRequest(timerStat, selectStat); + if (selectStat == KRequestPending) { + nativeSocket.CancelIoctl(); + //CancelIoctl completes the request (most likely with KErrCancel) + //We need to wait for this to keep the thread semaphore balanced (or active scheduler will panic) + User::WaitForRequest(selectStat); + //restart asynchronous notifier (only one IOCTL allowed at a time) + if (asyncSelect) + asyncSelect->IssueRequest(); + return 0; //timeout + } else { + selectTimer.Cancel(); + User::WaitForRequest(timerStat); + } } - selectTimer.Cancel(); - User::WaitForRequest(timerStat); - if(readStat && readStat->Int() != KRequestPending) { + if (selectStat != KErrNone) + return selectStat.Int(); + if (selectFlags() & KSockSelectExcept) { + TInt err; + nativeSocket.GetOpt(KSOSelectLastError, KSOLSocket, err); + //restart asynchronous notifier (only one IOCTL allowed at a time) + if (asyncSelect) + asyncSelect->IssueRequest(); //TODO: in error case should we restart or not? + return err; + } + if (selectFlags() & KSockSelectRead) { Q_ASSERT(checkRead && selectForRead); - //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive() *selectForRead = true; } - if(writeStat && writeStat->Int() != KRequestPending) { + if (selectFlags() & KSockSelectWrite) { Q_ASSERT(checkWrite && selectForWrite); - //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive() *selectForWrite = true; } + //restart asynchronous notifier (only one IOCTL allowed at a time) + if (asyncSelect) + asyncSelect->IssueRequest(); return 1; } @@ -1150,14 +1166,26 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E class QReadNotifier : public QSocketNotifier { + friend class QAsyncSelect; public: QReadNotifier(int fd, QSymbianSocketEngine *parent) : QSocketNotifier(fd, QSocketNotifier::Read, parent) { engine = parent; } protected: + bool event(QEvent *); + QSymbianSocketEngine *engine; }; +bool QReadNotifier::event(QEvent *e) +{ + if (e->type() == QEvent::SockAct) { + engine->readNotification(); + return true; + } + return QSocketNotifier::event(e); +} + bool QSymbianSocketEngine::isReadNotificationEnabled() const { Q_D(const QSymbianSocketEngine); @@ -1172,22 +1200,44 @@ void QSymbianSocketEngine::setReadNotificationEnabled(bool enable) if (d->readNotifier) { d->readNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { - d->readNotifier = new QReadNotifier(d->socketDescriptor, this); + QReadNotifier *rn = new QReadNotifier(d->socketDescriptor, this); + d->readNotifier = rn; + if (!d->asyncSelect) + d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); + d->asyncSelect->setReadNotifier(rn); d->readNotifier->setEnabled(true); } + // TODO: what do we do if event dispatcher doesn't exist yet? + if (d->asyncSelect) + d->asyncSelect->IssueRequest(); } class QWriteNotifier : public QSocketNotifier { + friend class QAsyncSelect; public: QWriteNotifier(int fd, QSymbianSocketEngine *parent) - : QSocketNotifier(fd, QSocketNotifier::Read, parent) + : QSocketNotifier(fd, QSocketNotifier::Write, parent) { engine = parent; } protected: + bool event(QEvent *); + QSymbianSocketEngine *engine; }; +bool QWriteNotifier::event(QEvent *e) +{ + if (e->type() == QEvent::SockAct) { + if (engine->state() == QAbstractSocket::ConnectingState) + engine->connectionNotification(); + else + engine->writeNotification(); + return true; + } + return QSocketNotifier::event(e); +} + bool QSymbianSocketEngine::isWriteNotificationEnabled() const { Q_D(const QSymbianSocketEngine); @@ -1202,17 +1252,48 @@ void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) if (d->writeNotifier) { d->writeNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { - d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this); + QWriteNotifier *wn = new QWriteNotifier(d->socketDescriptor, this); + d->readNotifier = wn; + if (!(d->asyncSelect)) + d->asyncSelect = q_check_ptr(new QAsyncSelect(d->threadData->eventDispatcher, d->nativeSocket, this)); + d->asyncSelect->setWriteNotifier(wn); d->writeNotifier->setEnabled(true); } + // TODO: what do we do if event dispatcher doesn't exist yet? + if (d->asyncSelect) + d->asyncSelect->IssueRequest(); +} + +class QExceptionNotifier : public QSocketNotifier +{ + friend class QAsyncSelect; +public: + QExceptionNotifier(int fd, QSymbianSocketEngine *parent) + : QSocketNotifier(fd, QSocketNotifier::Exception, parent) { engine = parent; } + +protected: + bool event(QEvent *); + + QSymbianSocketEngine *engine; +}; + +bool QExceptionNotifier::event(QEvent *e) +{ + if (e->type() == QEvent::SockAct) { + if (engine->state() == QAbstractSocket::ConnectingState) + engine->connectionNotification(); + else + engine->exceptionNotification(); + return true; + } + return QSocketNotifier::event(e); } -// FIXME do we really need this for symbian? bool QSymbianSocketEngine::isExceptionNotificationEnabled() const { -// Q_D(const QSymbianSocketEngine); -// // TODO -// return d->exceptNotifier && d->exceptNotifier->isEnabled(); + Q_D(const QSymbianSocketEngine); + // TODO + return d->exceptNotifier && d->exceptNotifier->isEnabled(); return false; } @@ -1221,12 +1302,18 @@ void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); // TODO -// if (d->exceptNotifier) { -// d->exceptNotifier->setEnabled(enable); -// } else if (enable && d->threadData->eventDispatcher) { -// d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this); -// d->exceptNotifier->setEnabled(true); -// } + if (d->exceptNotifier) { + d->exceptNotifier->setEnabled(enable); + } else if (enable && d->threadData->eventDispatcher) { + QExceptionNotifier *en = new QExceptionNotifier(d->socketDescriptor, this); + d->exceptNotifier = en; + if (!(d->asyncSelect)) + d->asyncSelect = q_check_ptr(new QAsyncSelect(d->threadData->eventDispatcher, d->nativeSocket, this)); + d->asyncSelect->setExceptionNotifier(en); + d->writeNotifier->setEnabled(true); + } + if (d->asyncSelect) + d->asyncSelect->IssueRequest(); } bool QSymbianSocketEngine::waitForRead(int msecs, bool *timedOut) @@ -1302,5 +1389,81 @@ qint64 QSymbianSocketEngine::bytesToWrite() const return 0; } +QAsyncSelect::QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent) + : CActive(CActive::EPriorityStandard), + m_inSocketEvent(false), + m_deleteLater(false), + m_socket(sock), + m_selectFlags(0), + engine(parent) +{ + CActiveScheduler::Add(this); +} + +QAsyncSelect::~QAsyncSelect() +{ + Cancel(); +} + +void QAsyncSelect::DoCancel() +{ + m_socket.CancelIoctl(); +} + +void QAsyncSelect::RunL() +{ + //TODO: block when event loop demands it + //if (maybeQueueForLater()) + // return; + + m_inSocketEvent = true; + //TODO: KSockSelectReadContinuation does what? + if (m_selectBuf() & KSockSelectRead) { + QEvent e(QEvent::SockAct); + iReadN->event(&e); + } + if (m_selectBuf() & KSockSelectWrite) { + QEvent e(QEvent::SockAct); + iWriteN->event(&e); + } + if ((m_selectBuf() && KSockSelectExcept) || iStatus != KErrNone) { + QEvent e(QEvent::SockAct); + iExcN->event(&e); + } + m_inSocketEvent = false; + // select again (unless disabled by one of the callbacks) + IssueRequest(); +} + +void QAsyncSelect::deleteLater() +{ + if (m_inSocketEvent) { + m_deleteLater = true; + } else { + delete this; + } +} + +void QAsyncSelect::IssueRequest() +{ + if (m_inSocketEvent) + return; //prevent thrashing during a callback - socket engine enables/disables multiple notifiers + TUint selectFlags = 0; + if (iReadN && iReadN->isEnabled()) + selectFlags |= KSockSelectRead; + if (iWriteN && iWriteN->isEnabled()) + selectFlags |= KSockSelectWrite; + if (iExcN && iExcN->isEnabled()) + selectFlags |= KSockSelectExcept; + if (selectFlags != m_selectFlags) { + Cancel(); + m_selectFlags = selectFlags; + } + if (m_selectFlags && !IsActive()) { + m_selectBuf() = m_selectFlags; + m_socket.Ioctl(KIOctlSelect, iStatus, &m_selectBuf, KSOLSocket); + SetActive(); + } +} QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 43e5e61..ebd8092 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -146,6 +146,41 @@ private: class QSocketNotifier; +class QReadNotifier; +class QWriteNotifier; +class QExceptionNotifier; +class QAsyncSelect : public CActive +{ +public: + QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent); + ~QAsyncSelect(); + + void deleteLater(); + void IssueRequest(); + + void refresh(); + + void setReadNotifier(QReadNotifier *rn) { iReadN = rn; } + void setWriteNotifier(QWriteNotifier *wn) { iWriteN = wn; } + void setExceptionNotifier(QExceptionNotifier *en) { iExcN = en; } + +protected: + void DoCancel(); + void RunL(); + +private: + QReadNotifier* iReadN; + QWriteNotifier* iWriteN; + QExceptionNotifier* iExcN; + bool m_inSocketEvent; // TODO ? + bool m_deleteLater; // TODO ? + RSocket &m_socket; + + TUint m_selectFlags; + TPckgBuf m_selectBuf; //in & out IPC buffer + QSymbianSocketEngine *engine; +}; + class QSymbianSocketEnginePrivate : public QAbstractSocketEnginePrivate { Q_DECLARE_PUBLIC(QSymbianSocketEngine) @@ -162,6 +197,7 @@ public: mutable RTimer selectTimer; QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; + QAsyncSelect* asyncSelect; // FIXME this is duplicated from qnativesocketengine_p.h enum ErrorString { -- cgit v0.12 From 82ab30acff0322f51f732c520dd1e5d7b40482a6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 8 Dec 2010 19:25:29 +0000 Subject: Whitespace fixes Reviewed-by: Trust Me --- src/network/kernel/qhostinfo_symbian.cpp | 2 +- src/network/socket/qsymbiansocketengine.cpp | 8 ++++---- src/network/socket/qsymbiansocketengine_p.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index ffa0b46..287021f 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -88,7 +88,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); } */ - + return results; } diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index ad1164a..2af2029 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -119,7 +119,7 @@ void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 TPckgBuf query; query().iSrcAddr = a; TInt err = nativeSocket.GetOpt(KSoInetIfQueryBySrcAddr, KSolInetIfQuery, query); - if(!err) + if (!err) addr->setScopeId(qt_TDesC2QString(query().iName)); else addr->setScopeId(QString::number(a.Scope())); @@ -181,7 +181,7 @@ void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint TPckgBuf query; query().iName = qt_QString2TPtrC(addr.scopeId()); TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); - if(!err) + if (!err) nativeAddr.SetScope(query().iIndex); else nativeAddr.SetScope(0); @@ -638,7 +638,7 @@ int QSymbianSocketEngine::accept() TRequestStatus status; d->nativeSocket.Accept(blankSocket, status); User::WaitForRequest(status); - if(status.Int()) { + if (status.Int()) { qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); return 0; } @@ -655,7 +655,7 @@ qint64 QSymbianSocketEngine::bytesAvailable() const // FIXME is this the right thing also for UDP? // What is expected for UDP, the length for the next packet I guess? TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); - if(err) + if (err) return 0; available = (qint64) nbytes; diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index ebd8092..2d5bcd8 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -124,8 +124,8 @@ public: bool waitForRead(int msecs = 30000, bool *timedOut = 0); bool waitForWrite(int msecs = 30000, bool *timedOut = 0); bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, - bool checkRead, bool checkWrite, - int msecs = 30000, bool *timedOut = 0); + bool checkRead, bool checkWrite, + int msecs = 30000, bool *timedOut = 0); bool isReadNotificationEnabled() const; void setReadNotificationEnabled(bool enable); -- cgit v0.12 From 92705ba069945bdd9a65b627d89119a893c0cf1e Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 8 Dec 2010 19:33:18 +0000 Subject: Fix handling of select ioctl results The select ioctl report everything not just the flags we asked for. So mask off the results to only look at the requested flags. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 2af2029..b1d8bc0 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -986,12 +986,12 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool asyncSelect->IssueRequest(); //TODO: in error case should we restart or not? return err; } - if (selectFlags() & KSockSelectRead) { - Q_ASSERT(checkRead && selectForRead); + if (checkRead && (selectFlags() & KSockSelectRead)) { + Q_ASSERT(selectForRead); *selectForRead = true; } - if (selectFlags() & KSockSelectWrite) { - Q_ASSERT(checkWrite && selectForWrite); + if (checkWrite && (selectFlags() & KSockSelectWrite)) { + Q_ASSERT(selectForWrite); *selectForWrite = true; } //restart asynchronous notifier (only one IOCTL allowed at a time) @@ -1417,6 +1417,7 @@ void QAsyncSelect::RunL() // return; m_inSocketEvent = true; + m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested //TODO: KSockSelectReadContinuation does what? if (m_selectBuf() & KSockSelectRead) { QEvent e(QEvent::SockAct); -- cgit v0.12 From d7654f94c61d562c8673de577c1cf934f3026614 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 20:14:31 +0100 Subject: QSymbianSocketEngine: Unify a call --- src/network/socket/qsymbiansocketengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index b1d8bc0..e7bd425 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -198,7 +198,7 @@ void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : socketDescriptor(-1), - socketServer(qt_symbianGetSocketServer()), + socketServer(QSymbianSocketManager::instance().getSocketServer()), connection(QSymbianSocketManager::instance().defaultConnection()), readNotifier(0), writeNotifier(0), -- cgit v0.12 From afc7d05995c8f56d0ab9c35f9ca826e0bd0aaea4 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 20:16:27 +0100 Subject: Socket engines: Improve manual test program Reviewed-by: Shane Kearns --- tests/manual/socketengine/main.cpp | 36 ++++++++++++++++++++++++++++++ tests/manual/socketengine/socketengine.pro | 2 ++ 2 files changed, 38 insertions(+) diff --git a/tests/manual/socketengine/main.cpp b/tests/manual/socketengine/main.cpp index f368573..e475942 100644 --- a/tests/manual/socketengine/main.cpp +++ b/tests/manual/socketengine/main.cpp @@ -51,12 +51,48 @@ #include #include #include +#include +#include +#include +#include const int bufsize = 16*1024; char buf[bufsize]; int main(int argc, char**argv) { + QCoreApplication app(argc, argv); + +#ifdef Q_OS_SYMBIAN + QNetworkConfigurationManager configurationManager; + QNetworkConfiguration configuration = configurationManager.defaultConfiguration(); + if (!configuration.isValid()) { + qDebug() << "Got an invalid session configuration"; + exit(1); + } + + qDebug() << "Opening session..."; + QNetworkSession *session = new QNetworkSession(configuration); + + // Does not work: +// session->open(); +// session->waitForOpened(); + + // works: + QEventLoop loop; + QObject::connect(session, SIGNAL(opened()), &loop, SLOT(quit()), Qt::QueuedConnection); + QMetaObject::invokeMethod(session, "open", Qt::QueuedConnection); + loop.exec(); + + + if (session->isOpen()) { + qDebug() << "session opened"; + } else { + qDebug() << "session could not be opened -" << session->errorString(); + exit(1); + } +#endif + // create it QAbstractSocketEngine *socketEngine = QAbstractSocketEngine::createSocketEngine(QAbstractSocket::TcpSocket, QNetworkProxy(QNetworkProxy::NoProxy), 0); diff --git a/tests/manual/socketengine/socketengine.pro b/tests/manual/socketengine/socketengine.pro index 96d0055..76a40be 100644 --- a/tests/manual/socketengine/socketengine.pro +++ b/tests/manual/socketengine/socketengine.pro @@ -9,5 +9,7 @@ QT += network CONFIG += release +symbian: TARGET.CAPABILITY = NetworkServices + # Input SOURCES += main.cpp -- cgit v0.12 From 92f11bd666e8a63d9fc8c5588d843721c5bf68b5 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 8 Dec 2010 20:27:03 +0100 Subject: QSymbianSocketEngine: Fix wrong debug message --- src/network/socket/qsymbiansocketengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index e7bd425..5cee340 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -540,7 +540,7 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) if (d->socketState != QAbstractSocket::ConnectedState) { #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)", + qDebug("QSymbianSocketEngine::connectToHost(%s, %i) == false (%s)", addr.toString().toLatin1().constData(), port, d->socketState == QAbstractSocket::ConnectingState ? "Connection in progress" : d->socketErrorString.toLatin1().constData()); -- cgit v0.12 From b9080b96b05988776daec35f7e2af9ad346abb0a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 9 Dec 2010 10:05:03 +0000 Subject: Fix bug in select When waitForRead was called, it was selecting for read and write, because we were checking the pointers instead of the bools. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 10 +++++++--- tests/manual/socketengine/main.cpp | 8 +++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 5cee340..1490bdd 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -148,7 +148,11 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet; TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; - TInt err = nativeSocket.Open(socketServer, family, type, protocol, *connection); + TInt err; + if (connection) + err = nativeSocket.Open(socketServer, family, type, protocol, *connection); + else + err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead if (err != KErrNone) { switch (err) { @@ -946,9 +950,9 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool TPckgBuf selectFlags; selectFlags() = KSockSelectExcept; - if (selectForRead) + if (checkRead) selectFlags() |= KSockSelectRead; - if (selectForWrite) + if (checkWrite) selectFlags() |= KSockSelectWrite; TRequestStatus selectStat; nativeSocket.Ioctl(KIOctlSelect, selectStat, &selectFlags, KSOLSocket); diff --git a/tests/manual/socketengine/main.cpp b/tests/manual/socketengine/main.cpp index e475942..2f017a0 100644 --- a/tests/manual/socketengine/main.cpp +++ b/tests/manual/socketengine/main.cpp @@ -109,10 +109,12 @@ int main(int argc, char**argv) } // wait for connected - socketEngine->connectToHost(QHostAddress("74.125.77.99"), 80); // google + int r = socketEngine->connectToHost(QHostAddress("74.125.77.99"), 80); // google bool readyToRead = false; bool readyToWrite = false; socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, true, 10*1000); + if (r <= 0) //timeout or error + exit(1); if (readyToWrite) { // write the request QByteArray request("GET /robots.txt HTTP/1.0\r\n\r\n"); @@ -129,7 +131,11 @@ int main(int argc, char**argv) bzero(buf, bufsize); ret = socketEngine->read(buf, available); if (ret > 0) { +#ifdef Q_OS_SYMBIAN + qDebug() << buf; //printf goes only to screen, this goes to remote debug channel +#else printf("%s", buf); +#endif } else { // some failure when reading exit(1); -- cgit v0.12 From af62350d83b27421820536b3a19be36a32384f15 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 9 Dec 2010 14:53:34 +0100 Subject: Move tst_qnativesocketengine to tst_platformsocketengine --- tests/auto/platformsocketengine/.gitignore | 1 + .../platformsocketengine/platformsocketengine.pri | 19 + .../platformsocketengine/platformsocketengine.pro | 13 + .../tst_platformsocketengine.cpp | 705 +++++++++++++++++++++ tests/auto/qnativesocketengine/.gitignore | 1 - .../qnativesocketengine/qnativesocketengine.pro | 13 - tests/auto/qnativesocketengine/qsocketengine.pri | 19 - .../tst_qnativesocketengine.cpp | 705 --------------------- 8 files changed, 738 insertions(+), 738 deletions(-) create mode 100644 tests/auto/platformsocketengine/.gitignore create mode 100644 tests/auto/platformsocketengine/platformsocketengine.pri create mode 100644 tests/auto/platformsocketengine/platformsocketengine.pro create mode 100644 tests/auto/platformsocketengine/tst_platformsocketengine.cpp delete mode 100644 tests/auto/qnativesocketengine/.gitignore delete mode 100644 tests/auto/qnativesocketengine/qnativesocketengine.pro delete mode 100644 tests/auto/qnativesocketengine/qsocketengine.pri delete mode 100644 tests/auto/qnativesocketengine/tst_qnativesocketengine.cpp diff --git a/tests/auto/platformsocketengine/.gitignore b/tests/auto/platformsocketengine/.gitignore new file mode 100644 index 0000000..4700e5e --- /dev/null +++ b/tests/auto/platformsocketengine/.gitignore @@ -0,0 +1 @@ +tst_qnativesocketengine diff --git a/tests/auto/platformsocketengine/platformsocketengine.pri b/tests/auto/platformsocketengine/platformsocketengine.pri new file mode 100644 index 0000000..15f31fd --- /dev/null +++ b/tests/auto/platformsocketengine/platformsocketengine.pri @@ -0,0 +1,19 @@ +QT += network + +QNETWORK_SRC = $$QT_SOURCE_TREE/src/network + +INCLUDEPATH += $$QNETWORK_SRC + +win32 { + wince*: { + LIBS += -lws2 + } else { + LIBS += -lws2_32 + } +} + +unix:contains(QT_CONFIG, reduce_exports) { + SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine_unix.cpp + SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine.cpp + SOURCES += $$QNETWORK_SRC/socket/qabstractsocketengine.cpp +} diff --git a/tests/auto/platformsocketengine/platformsocketengine.pro b/tests/auto/platformsocketengine/platformsocketengine.pro new file mode 100644 index 0000000..0275d37 --- /dev/null +++ b/tests/auto/platformsocketengine/platformsocketengine.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +SOURCES += tst_qnativesocketengine.cpp + +include(../qnativesocketengine/qsocketengine.pri) + +requires(contains(QT_CONFIG,private_tests)) + +MOC_DIR=tmp + +QT = core network + +symbian: TARGET.CAPABILITY = NetworkServices + diff --git a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp new file mode 100644 index 0000000..2b0b632 --- /dev/null +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -0,0 +1,705 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +#ifdef Q_OS_WIN +#include +#endif + +#include + + +#include +#include + +#include +#include + +#ifdef Q_OS_UNIX +#include +#include +#include +#endif + +#include + + +#include + +#include "../network-settings.h" + +//TESTED_FILES=network/qnativesocketengine.cpp network/qnativesocketengine_p.h network/qnativesocketengine_unix.cpp + +class tst_QNativeSocketEngine : public QObject +{ + Q_OBJECT + +public: + tst_QNativeSocketEngine(); + virtual ~tst_QNativeSocketEngine(); + + +public slots: + void init(); + void cleanup(); +private slots: + void construction(); + void simpleConnectToIMAP(); + void udpLoopbackTest(); + void udpIPv6LoopbackTest(); + void broadcastTest(); + void serverTest(); + void udpLoopbackPerformance(); + void tcpLoopbackPerformance(); + void readWriteBufferSize(); + void tooManySockets(); + void bind(); + void networkError(); + void setSocketDescriptor(); + void invalidSend(); + void receiveUrgentData(); +}; + +tst_QNativeSocketEngine::tst_QNativeSocketEngine() +{ + Q_SET_DEFAULT_IAP +} + +tst_QNativeSocketEngine::~tst_QNativeSocketEngine() +{ +} + +void tst_QNativeSocketEngine::init() +{ +} + +void tst_QNativeSocketEngine::cleanup() +{ +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::construction() +{ + QNativeSocketEngine socketDevice; + + QVERIFY(!socketDevice.isValid()); + + // Initialize device + QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); + QVERIFY(socketDevice.isValid()); + QVERIFY(socketDevice.protocol() == QAbstractSocket::IPv4Protocol); + QVERIFY(socketDevice.socketType() == QAbstractSocket::TcpSocket); + QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState); + QVERIFY(socketDevice.socketDescriptor() != -1); + QVERIFY(socketDevice.localAddress() == QHostAddress()); + QVERIFY(socketDevice.localPort() == 0); + QVERIFY(socketDevice.peerAddress() == QHostAddress()); + QVERIFY(socketDevice.peerPort() == 0); + QVERIFY(socketDevice.error() == QAbstractSocket::UnknownSocketError); + + QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::bytesAvailable() was called in QAbstractSocket::UnconnectedState"); + QVERIFY(socketDevice.bytesAvailable() == 0); + + QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState"); + QVERIFY(!socketDevice.hasPendingDatagrams()); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::simpleConnectToIMAP() +{ + QNativeSocketEngine socketDevice; + + // Initialize device + QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); + QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState); + + const bool isConnected = socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143); + if (!isConnected) { + QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState); + QVERIFY(socketDevice.waitForWrite()); + QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState); + } + QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState); + QVERIFY(socketDevice.peerAddress() == QtNetworkSettings::serverIP()); + + // Wait for the greeting + QVERIFY(socketDevice.waitForRead()); + + // Read the greeting + qint64 available = socketDevice.bytesAvailable(); + QVERIFY(available > 0); + QByteArray array; + array.resize(available); + QVERIFY(socketDevice.read(array.data(), array.size()) == available); + + // Check that the greeting is what we expect it to be + QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData()); + + // Write a logout message + QByteArray array2 = "ZZZ LOGOUT\r\n"; + QVERIFY(socketDevice.write(array2.data(), + array2.size()) == array2.size()); + + // Wait for the response + QVERIFY(socketDevice.waitForRead()); + + available = socketDevice.bytesAvailable(); + QVERIFY(available > 0); + array.resize(available); + QVERIFY(socketDevice.read(array.data(), array.size()) == available); + + // Check that the greeting is what we expect it to be + QCOMPARE(array.constData(), + "* BYE LOGOUT received\r\n" + "ZZZ OK Completed\r\n"); + + // Wait for the response + QVERIFY(socketDevice.waitForRead()); + char c; + QVERIFY(socketDevice.read(&c, sizeof(c)) == -1); + QVERIFY(socketDevice.error() == QAbstractSocket::RemoteHostClosedError); + QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::udpLoopbackTest() +{ +#ifdef SYMBIAN_WINSOCK_CONNECTIVITY + QSKIP("Not working on Emulator without WinPCAP", SkipAll); +#endif + QNativeSocketEngine udpSocket; + + // Initialize device #1 + QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); + QVERIFY(udpSocket.isValid()); + QVERIFY(udpSocket.socketDescriptor() != -1); + QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol); + QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket); + QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState); + + // Bind #1 to localhost + QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0)); + QVERIFY(udpSocket.state() == QAbstractSocket::BoundState); + quint16 port = udpSocket.localPort(); + QVERIFY(port != 0); + + // Initialize device #2 + QNativeSocketEngine udpSocket2; + QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); + + // Connect device #2 to #1 + QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port)); + QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState); + + // Write a message to #1 + QByteArray message1 = "hei der"; + QVERIFY(udpSocket2.write(message1.data(), + message1.size()) == message1.size()); + + // Read the message from #2 + QVERIFY(udpSocket.waitForRead()); + QVERIFY(udpSocket.hasPendingDatagrams()); + qint64 available = udpSocket.pendingDatagramSize(); + QVERIFY(available > 0); + QByteArray answer; + answer.resize(available); + QHostAddress senderAddress; + quint16 senderPort = 0; + QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), + &senderAddress, + &senderPort) == message1.size()); + QVERIFY(senderAddress == QHostAddress("127.0.0.1")); + QVERIFY(senderPort != 0); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::udpIPv6LoopbackTest() +{ +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian: IPv6 is not yet supported", SkipAll); +#endif + QNativeSocketEngine udpSocket; + + // Initialize device #1 + bool init = udpSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol); + + if (!init) { + QVERIFY(udpSocket.error() == QAbstractSocket::UnsupportedSocketOperationError); + } else { + QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv6Protocol); + + // Bind #1 to localhost + QVERIFY(udpSocket.bind(QHostAddress("::1"), 0)); + QVERIFY(udpSocket.state() == QAbstractSocket::BoundState); + quint16 port = udpSocket.localPort(); + QVERIFY(port != 0); + + // Initialize device #2 + QNativeSocketEngine udpSocket2; + QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol)); + + // Connect device #2 to #1 + QVERIFY(udpSocket2.connectToHost(QHostAddress("::1"), port)); + QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState); + + // Write a message to #1 + QByteArray message1 = "hei der"; + QVERIFY(udpSocket2.write(message1.data(), + message1.size()) == message1.size()); + + // Read the message from #2 + QVERIFY(udpSocket.waitForRead()); + QVERIFY(udpSocket.hasPendingDatagrams()); + qint64 available = udpSocket.pendingDatagramSize(); + QVERIFY(available > 0); + QByteArray answer; + answer.resize(available); + QHostAddress senderAddress; + quint16 senderPort = 0; + QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), + &senderAddress, + &senderPort) == message1.size()); + QVERIFY(senderAddress == QHostAddress("::1")); + QVERIFY(senderPort != 0); + } +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::broadcastTest() +{ +#ifdef Q_OS_AIX + QSKIP("Broadcast does not work on darko", SkipAll); +#endif + QNativeSocketEngine broadcastSocket; + + // Initialize a regular Udp socket + QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket)); + + // Bind to any port on all interfaces + QVERIFY(broadcastSocket.bind(QHostAddress::Any, 0)); + QVERIFY(broadcastSocket.state() == QAbstractSocket::BoundState); + quint16 port = broadcastSocket.localPort(); + QVERIFY(port > 0); + + // Broadcast an inappropriate troll message + QByteArray trollMessage + = "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH."; + QVERIFY(broadcastSocket.writeDatagram(trollMessage.data(), + trollMessage.size(), + QHostAddress::Broadcast, + port) == trollMessage.size()); + + // Wait until we receive it ourselves +#if defined(Q_OS_FREEBSD) + QEXPECT_FAIL("", "Broadcasting to 255.255.255.255 does not work on FreeBSD", Abort); +#endif + QVERIFY(broadcastSocket.waitForRead()); + QVERIFY(broadcastSocket.hasPendingDatagrams()); + + qlonglong available = broadcastSocket.pendingDatagramSize(); + QByteArray response; + response.resize(available); + QVERIFY(broadcastSocket.readDatagram(response.data(), response.size()) + == response.size()); + QCOMPARE(response, trollMessage); + +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::serverTest() +{ + QNativeSocketEngine server; + + // Initialize a Tcp socket + QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); + + // Bind to any port on all interfaces + QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0)); + QVERIFY(server.state() == QAbstractSocket::BoundState); + quint16 port = server.localPort(); + + // Listen for incoming connections + QVERIFY(server.listen()); + QVERIFY(server.state() == QAbstractSocket::ListeningState); + + // Initialize a Tcp socket + QNativeSocketEngine client; + QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); + if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { + QVERIFY(client.state() == QAbstractSocket::ConnectingState); + QVERIFY(client.waitForWrite()); + QVERIFY(client.state() == QAbstractSocket::ConnectedState); + } + + // The server accepts the connection + int socketDescriptor = server.accept(); + QVERIFY(socketDescriptor > 0); + + // A socket device is initialized on the server side, passing the + // socket descriptor from accept(). It's pre-connected. + QNativeSocketEngine serverSocket; + QVERIFY(serverSocket.initialize(socketDescriptor)); + QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); + + // The server socket sends a greeting to the clietn + QByteArray greeting = "Greetings!"; + QVERIFY(serverSocket.write(greeting.data(), + greeting.size()) == greeting.size()); + + // The client waits for the greeting to arrive + QVERIFY(client.waitForRead()); + qint64 available = client.bytesAvailable(); + QVERIFY(available > 0); + + // The client reads the greeting and checks that it's correct + QByteArray response; + response.resize(available); + QVERIFY(client.read(response.data(), + response.size()) == response.size()); + QCOMPARE(response, greeting); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::udpLoopbackPerformance() +{ +#ifdef SYMBIAN_WINSOCK_CONNECTIVITY + QSKIP("Not working on Emulator without WinPCAP", SkipAll); +#endif + QNativeSocketEngine udpSocket; + + // Initialize device #1 + QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); + QVERIFY(udpSocket.isValid()); + QVERIFY(udpSocket.socketDescriptor() != -1); + QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol); + QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket); + QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState); + + // Bind #1 to localhost + QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0)); + QVERIFY(udpSocket.state() == QAbstractSocket::BoundState); + quint16 port = udpSocket.localPort(); + QVERIFY(port != 0); + + // Initialize device #2 + QNativeSocketEngine udpSocket2; + QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); + + // Connect device #2 to #1 + QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port)); + QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState); + + const int messageSize = 8192; + QByteArray message1(messageSize, '@'); + QByteArray answer(messageSize, '@'); + + QHostAddress localhost = QHostAddress::LocalHost; + + qlonglong readBytes = 0; + QTime timer; + timer.start(); + while (timer.elapsed() < 5000) { + udpSocket2.write(message1.data(), message1.size()); + udpSocket.waitForRead(); + while (udpSocket.hasPendingDatagrams()) { + readBytes += (qlonglong) udpSocket.readDatagram(answer.data(), + answer.size()); + } + } + + qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s", + readBytes / (1024.0 * 1024.0), + timer.elapsed() / 1024.0, + (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024)); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::tcpLoopbackPerformance() +{ + QNativeSocketEngine server; + + // Initialize a Tcp socket + QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); + + // Bind to any port on all interfaces + QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0)); + QVERIFY(server.state() == QAbstractSocket::BoundState); + quint16 port = server.localPort(); + + // Listen for incoming connections + QVERIFY(server.listen()); + QVERIFY(server.state() == QAbstractSocket::ListeningState); + + // Initialize a Tcp socket + QNativeSocketEngine client; + QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); + + // Connect to our server + if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { + QVERIFY(client.state() == QAbstractSocket::ConnectingState); + QVERIFY(client.waitForWrite()); + QVERIFY(client.state() == QAbstractSocket::ConnectedState); + } + + // The server accepts the connectio + int socketDescriptor = server.accept(); + QVERIFY(socketDescriptor > 0); + + // A socket device is initialized on the server side, passing the + // socket descriptor from accept(). It's pre-connected. + QNativeSocketEngine serverSocket; + QVERIFY(serverSocket.initialize(socketDescriptor)); + QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); + + const int messageSize = 1024 * 256; + QByteArray message1(messageSize, '@'); + QByteArray answer(messageSize, '@'); + + QTime timer; + timer.start(); + qlonglong readBytes = 0; + while (timer.elapsed() < 5000) { + qlonglong written = serverSocket.write(message1.data(), message1.size()); + while (written > 0) { + client.waitForRead(); + if (client.bytesAvailable() > 0) { + qlonglong readNow = client.read(answer.data(), answer.size()); + written -= readNow; + readBytes += readNow; + } + } + } + + qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s", + readBytes / (1024.0 * 1024.0), + timer.elapsed() / 1024.0, + (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024)); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::readWriteBufferSize() +{ + QNativeSocketEngine device; + + QVERIFY(device.initialize(QAbstractSocket::TcpSocket)); + + qint64 bufferSize = device.receiveBufferSize(); + QVERIFY(bufferSize != -1); + device.setReceiveBufferSize(bufferSize + 1); +#if defined(Q_OS_WINCE) + QEXPECT_FAIL(0, "Not supported by default on WinCE", Continue); +#endif + QVERIFY(device.receiveBufferSize() > bufferSize); + + bufferSize = device.sendBufferSize(); + QVERIFY(bufferSize != -1); + device.setSendBufferSize(bufferSize + 1); + QVERIFY(device.sendBufferSize() > bufferSize); + +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::tooManySockets() +{ +#if defined Q_OS_WIN + QSKIP("Certain windows machines suffocate and spend too much time in this test.", SkipAll); +#endif + QList sockets; + QNativeSocketEngine *socketLayer = 0; + for (;;) { + socketLayer = new QNativeSocketEngine; + sockets.append(socketLayer); + + if (!socketLayer->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)) + break; + } + + QCOMPARE(socketLayer->error(), QAbstractSocket::SocketResourceError); + + qDeleteAll(sockets); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::bind() +{ +#if !defined Q_OS_WIN && !defined Q_OS_SYMBIAN + QNativeSocketEngine binder; + QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); + QVERIFY(!binder.bind(QHostAddress::Any, 82)); + QVERIFY(binder.error() == QAbstractSocket::SocketAccessError); +#endif + + QNativeSocketEngine binder2; + QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); + QVERIFY(binder2.bind(QHostAddress::Any, 31180)); + + QNativeSocketEngine binder3; + QVERIFY(binder3.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); + QVERIFY(!binder3.bind(QHostAddress::Any, 31180)); + +#ifdef SYMBIAN_WINSOCK_CONNECTIVITY + qDebug("On Symbian Emulator (WinSock) we get EADDRNOTAVAIL instead of EADDRINUSE"); + QVERIFY(binder3.error() == QAbstractSocket::SocketAddressNotAvailableError); +#else + QVERIFY(binder3.error() == QAbstractSocket::AddressInUseError); +#endif +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::networkError() +{ + QNativeSocketEngine client; + + QVERIFY(client.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); + + const bool isConnected = client.connectToHost(QtNetworkSettings::serverIP(), 143); + if (!isConnected) { + QVERIFY(client.state() == QAbstractSocket::ConnectingState); + QVERIFY(client.waitForWrite()); + QVERIFY(client.state() == QAbstractSocket::ConnectedState); + } + QVERIFY(client.state() == QAbstractSocket::ConnectedState); + + // An unexpected network error! +#ifdef Q_OS_WIN + // could use shutdown to produce different errors + ::closesocket(client.socketDescriptor()); +#else + ::close(client.socketDescriptor()); +#endif + + QVERIFY(client.read(0, 0) == -1); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::setSocketDescriptor() +{ + QNativeSocketEngine socket1; + QVERIFY(socket1.initialize(QAbstractSocket::TcpSocket)); + + QNativeSocketEngine socket2; + QVERIFY(socket2.initialize(socket1.socketDescriptor())); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::invalidSend() +{ + QNativeSocketEngine socket; + QVERIFY(socket.initialize(QAbstractSocket::TcpSocket)); + + QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::writeDatagram() was" + " called by a socket other than QAbstractSocket::UdpSocket"); + QCOMPARE(socket.writeDatagram("hei", 3, QHostAddress::LocalHost, 143), + (qlonglong) -1); +} + +//--------------------------------------------------------------------------- +void tst_QNativeSocketEngine::receiveUrgentData() +{ + QNativeSocketEngine server; + + QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); + + // Bind to any port on all interfaces + QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0)); + QVERIFY(server.state() == QAbstractSocket::BoundState); + quint16 port = server.localPort(); + + QVERIFY(server.listen()); + QVERIFY(server.state() == QAbstractSocket::ListeningState); + + QNativeSocketEngine client; + QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); + + if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { + QVERIFY(client.state() == QAbstractSocket::ConnectingState); + QVERIFY(client.waitForWrite()); + QVERIFY(client.state() == QAbstractSocket::ConnectedState); + } + + int socketDescriptor = server.accept(); + QVERIFY(socketDescriptor > 0); + + QNativeSocketEngine serverSocket; + QVERIFY(serverSocket.initialize(socketDescriptor)); + QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); + + char msg; + int available; + QByteArray response; + +#if defined Q_OS_HPUX + QSKIP("Native OOB data test doesn't work on HP-UX.", SkipAll); +#elif defined (Q_OS_WINCE) + QSKIP("Native OOB data test doesn't work on WinCE.", SkipAll); +#endif + + // The server sends an urgent message + msg = 'Q'; + QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); + + // The client receives the urgent message + QVERIFY(client.waitForRead()); + available = client.bytesAvailable(); + QCOMPARE(available, 1); + response.resize(available); + QCOMPARE(client.read(response.data(), response.size()), qint64(1)); + QCOMPARE(response.at(0), msg); + + // The client sends an urgent message + msg = 'T'; + int clientDescriptor = client.socketDescriptor(); + QCOMPARE(int(::send(clientDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); + + // The server receives the urgent message + QVERIFY(serverSocket.waitForRead()); + available = serverSocket.bytesAvailable(); + QCOMPARE(available, 1); + response.resize(available); + QCOMPARE(serverSocket.read(response.data(), response.size()), qint64(1)); + QCOMPARE(response.at(0), msg); + +} + +QTEST_MAIN(tst_QNativeSocketEngine) +#include "tst_qnativesocketengine.moc" diff --git a/tests/auto/qnativesocketengine/.gitignore b/tests/auto/qnativesocketengine/.gitignore deleted file mode 100644 index 4700e5e..0000000 --- a/tests/auto/qnativesocketengine/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qnativesocketengine diff --git a/tests/auto/qnativesocketengine/qnativesocketengine.pro b/tests/auto/qnativesocketengine/qnativesocketengine.pro deleted file mode 100644 index 0275d37..0000000 --- a/tests/auto/qnativesocketengine/qnativesocketengine.pro +++ /dev/null @@ -1,13 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qnativesocketengine.cpp - -include(../qnativesocketengine/qsocketengine.pri) - -requires(contains(QT_CONFIG,private_tests)) - -MOC_DIR=tmp - -QT = core network - -symbian: TARGET.CAPABILITY = NetworkServices - diff --git a/tests/auto/qnativesocketengine/qsocketengine.pri b/tests/auto/qnativesocketengine/qsocketengine.pri deleted file mode 100644 index 15f31fd..0000000 --- a/tests/auto/qnativesocketengine/qsocketengine.pri +++ /dev/null @@ -1,19 +0,0 @@ -QT += network - -QNETWORK_SRC = $$QT_SOURCE_TREE/src/network - -INCLUDEPATH += $$QNETWORK_SRC - -win32 { - wince*: { - LIBS += -lws2 - } else { - LIBS += -lws2_32 - } -} - -unix:contains(QT_CONFIG, reduce_exports) { - SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine_unix.cpp - SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine.cpp - SOURCES += $$QNETWORK_SRC/socket/qabstractsocketengine.cpp -} diff --git a/tests/auto/qnativesocketengine/tst_qnativesocketengine.cpp b/tests/auto/qnativesocketengine/tst_qnativesocketengine.cpp deleted file mode 100644 index 2b0b632..0000000 --- a/tests/auto/qnativesocketengine/tst_qnativesocketengine.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include - -#ifdef Q_OS_WIN -#include -#endif - -#include - - -#include -#include - -#include -#include - -#ifdef Q_OS_UNIX -#include -#include -#include -#endif - -#include - - -#include - -#include "../network-settings.h" - -//TESTED_FILES=network/qnativesocketengine.cpp network/qnativesocketengine_p.h network/qnativesocketengine_unix.cpp - -class tst_QNativeSocketEngine : public QObject -{ - Q_OBJECT - -public: - tst_QNativeSocketEngine(); - virtual ~tst_QNativeSocketEngine(); - - -public slots: - void init(); - void cleanup(); -private slots: - void construction(); - void simpleConnectToIMAP(); - void udpLoopbackTest(); - void udpIPv6LoopbackTest(); - void broadcastTest(); - void serverTest(); - void udpLoopbackPerformance(); - void tcpLoopbackPerformance(); - void readWriteBufferSize(); - void tooManySockets(); - void bind(); - void networkError(); - void setSocketDescriptor(); - void invalidSend(); - void receiveUrgentData(); -}; - -tst_QNativeSocketEngine::tst_QNativeSocketEngine() -{ - Q_SET_DEFAULT_IAP -} - -tst_QNativeSocketEngine::~tst_QNativeSocketEngine() -{ -} - -void tst_QNativeSocketEngine::init() -{ -} - -void tst_QNativeSocketEngine::cleanup() -{ -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::construction() -{ - QNativeSocketEngine socketDevice; - - QVERIFY(!socketDevice.isValid()); - - // Initialize device - QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - QVERIFY(socketDevice.isValid()); - QVERIFY(socketDevice.protocol() == QAbstractSocket::IPv4Protocol); - QVERIFY(socketDevice.socketType() == QAbstractSocket::TcpSocket); - QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState); - QVERIFY(socketDevice.socketDescriptor() != -1); - QVERIFY(socketDevice.localAddress() == QHostAddress()); - QVERIFY(socketDevice.localPort() == 0); - QVERIFY(socketDevice.peerAddress() == QHostAddress()); - QVERIFY(socketDevice.peerPort() == 0); - QVERIFY(socketDevice.error() == QAbstractSocket::UnknownSocketError); - - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::bytesAvailable() was called in QAbstractSocket::UnconnectedState"); - QVERIFY(socketDevice.bytesAvailable() == 0); - - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState"); - QVERIFY(!socketDevice.hasPendingDatagrams()); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::simpleConnectToIMAP() -{ - QNativeSocketEngine socketDevice; - - // Initialize device - QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState); - - const bool isConnected = socketDevice.connectToHost(QtNetworkSettings::serverIP(), 143); - if (!isConnected) { - QVERIFY(socketDevice.state() == QAbstractSocket::ConnectingState); - QVERIFY(socketDevice.waitForWrite()); - QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState); - } - QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState); - QVERIFY(socketDevice.peerAddress() == QtNetworkSettings::serverIP()); - - // Wait for the greeting - QVERIFY(socketDevice.waitForRead()); - - // Read the greeting - qint64 available = socketDevice.bytesAvailable(); - QVERIFY(available > 0); - QByteArray array; - array.resize(available); - QVERIFY(socketDevice.read(array.data(), array.size()) == available); - - // Check that the greeting is what we expect it to be - QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData()); - - // Write a logout message - QByteArray array2 = "ZZZ LOGOUT\r\n"; - QVERIFY(socketDevice.write(array2.data(), - array2.size()) == array2.size()); - - // Wait for the response - QVERIFY(socketDevice.waitForRead()); - - available = socketDevice.bytesAvailable(); - QVERIFY(available > 0); - array.resize(available); - QVERIFY(socketDevice.read(array.data(), array.size()) == available); - - // Check that the greeting is what we expect it to be - QCOMPARE(array.constData(), - "* BYE LOGOUT received\r\n" - "ZZZ OK Completed\r\n"); - - // Wait for the response - QVERIFY(socketDevice.waitForRead()); - char c; - QVERIFY(socketDevice.read(&c, sizeof(c)) == -1); - QVERIFY(socketDevice.error() == QAbstractSocket::RemoteHostClosedError); - QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpLoopbackTest() -{ -#ifdef SYMBIAN_WINSOCK_CONNECTIVITY - QSKIP("Not working on Emulator without WinPCAP", SkipAll); -#endif - QNativeSocketEngine udpSocket; - - // Initialize device #1 - QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); - QVERIFY(udpSocket.isValid()); - QVERIFY(udpSocket.socketDescriptor() != -1); - QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol); - QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket); - QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState); - - // Bind #1 to localhost - QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0)); - QVERIFY(udpSocket.state() == QAbstractSocket::BoundState); - quint16 port = udpSocket.localPort(); - QVERIFY(port != 0); - - // Initialize device #2 - QNativeSocketEngine udpSocket2; - QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); - - // Connect device #2 to #1 - QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port)); - QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState); - - // Write a message to #1 - QByteArray message1 = "hei der"; - QVERIFY(udpSocket2.write(message1.data(), - message1.size()) == message1.size()); - - // Read the message from #2 - QVERIFY(udpSocket.waitForRead()); - QVERIFY(udpSocket.hasPendingDatagrams()); - qint64 available = udpSocket.pendingDatagramSize(); - QVERIFY(available > 0); - QByteArray answer; - answer.resize(available); - QHostAddress senderAddress; - quint16 senderPort = 0; - QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), - &senderAddress, - &senderPort) == message1.size()); - QVERIFY(senderAddress == QHostAddress("127.0.0.1")); - QVERIFY(senderPort != 0); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpIPv6LoopbackTest() -{ -#if defined(Q_OS_SYMBIAN) - QSKIP("Symbian: IPv6 is not yet supported", SkipAll); -#endif - QNativeSocketEngine udpSocket; - - // Initialize device #1 - bool init = udpSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol); - - if (!init) { - QVERIFY(udpSocket.error() == QAbstractSocket::UnsupportedSocketOperationError); - } else { - QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv6Protocol); - - // Bind #1 to localhost - QVERIFY(udpSocket.bind(QHostAddress("::1"), 0)); - QVERIFY(udpSocket.state() == QAbstractSocket::BoundState); - quint16 port = udpSocket.localPort(); - QVERIFY(port != 0); - - // Initialize device #2 - QNativeSocketEngine udpSocket2; - QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol)); - - // Connect device #2 to #1 - QVERIFY(udpSocket2.connectToHost(QHostAddress("::1"), port)); - QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState); - - // Write a message to #1 - QByteArray message1 = "hei der"; - QVERIFY(udpSocket2.write(message1.data(), - message1.size()) == message1.size()); - - // Read the message from #2 - QVERIFY(udpSocket.waitForRead()); - QVERIFY(udpSocket.hasPendingDatagrams()); - qint64 available = udpSocket.pendingDatagramSize(); - QVERIFY(available > 0); - QByteArray answer; - answer.resize(available); - QHostAddress senderAddress; - quint16 senderPort = 0; - QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), - &senderAddress, - &senderPort) == message1.size()); - QVERIFY(senderAddress == QHostAddress("::1")); - QVERIFY(senderPort != 0); - } -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::broadcastTest() -{ -#ifdef Q_OS_AIX - QSKIP("Broadcast does not work on darko", SkipAll); -#endif - QNativeSocketEngine broadcastSocket; - - // Initialize a regular Udp socket - QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket)); - - // Bind to any port on all interfaces - QVERIFY(broadcastSocket.bind(QHostAddress::Any, 0)); - QVERIFY(broadcastSocket.state() == QAbstractSocket::BoundState); - quint16 port = broadcastSocket.localPort(); - QVERIFY(port > 0); - - // Broadcast an inappropriate troll message - QByteArray trollMessage - = "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH."; - QVERIFY(broadcastSocket.writeDatagram(trollMessage.data(), - trollMessage.size(), - QHostAddress::Broadcast, - port) == trollMessage.size()); - - // Wait until we receive it ourselves -#if defined(Q_OS_FREEBSD) - QEXPECT_FAIL("", "Broadcasting to 255.255.255.255 does not work on FreeBSD", Abort); -#endif - QVERIFY(broadcastSocket.waitForRead()); - QVERIFY(broadcastSocket.hasPendingDatagrams()); - - qlonglong available = broadcastSocket.pendingDatagramSize(); - QByteArray response; - response.resize(available); - QVERIFY(broadcastSocket.readDatagram(response.data(), response.size()) - == response.size()); - QCOMPARE(response, trollMessage); - -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::serverTest() -{ - QNativeSocketEngine server; - - // Initialize a Tcp socket - QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); - - // Bind to any port on all interfaces - QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0)); - QVERIFY(server.state() == QAbstractSocket::BoundState); - quint16 port = server.localPort(); - - // Listen for incoming connections - QVERIFY(server.listen()); - QVERIFY(server.state() == QAbstractSocket::ListeningState); - - // Initialize a Tcp socket - QNativeSocketEngine client; - QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); - if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { - QVERIFY(client.state() == QAbstractSocket::ConnectingState); - QVERIFY(client.waitForWrite()); - QVERIFY(client.state() == QAbstractSocket::ConnectedState); - } - - // The server accepts the connection - int socketDescriptor = server.accept(); - QVERIFY(socketDescriptor > 0); - - // A socket device is initialized on the server side, passing the - // socket descriptor from accept(). It's pre-connected. - QNativeSocketEngine serverSocket; - QVERIFY(serverSocket.initialize(socketDescriptor)); - QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); - - // The server socket sends a greeting to the clietn - QByteArray greeting = "Greetings!"; - QVERIFY(serverSocket.write(greeting.data(), - greeting.size()) == greeting.size()); - - // The client waits for the greeting to arrive - QVERIFY(client.waitForRead()); - qint64 available = client.bytesAvailable(); - QVERIFY(available > 0); - - // The client reads the greeting and checks that it's correct - QByteArray response; - response.resize(available); - QVERIFY(client.read(response.data(), - response.size()) == response.size()); - QCOMPARE(response, greeting); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpLoopbackPerformance() -{ -#ifdef SYMBIAN_WINSOCK_CONNECTIVITY - QSKIP("Not working on Emulator without WinPCAP", SkipAll); -#endif - QNativeSocketEngine udpSocket; - - // Initialize device #1 - QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); - QVERIFY(udpSocket.isValid()); - QVERIFY(udpSocket.socketDescriptor() != -1); - QVERIFY(udpSocket.protocol() == QAbstractSocket::IPv4Protocol); - QVERIFY(udpSocket.socketType() == QAbstractSocket::UdpSocket); - QVERIFY(udpSocket.state() == QAbstractSocket::UnconnectedState); - - // Bind #1 to localhost - QVERIFY(udpSocket.bind(QHostAddress("127.0.0.1"), 0)); - QVERIFY(udpSocket.state() == QAbstractSocket::BoundState); - quint16 port = udpSocket.localPort(); - QVERIFY(port != 0); - - // Initialize device #2 - QNativeSocketEngine udpSocket2; - QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); - - // Connect device #2 to #1 - QVERIFY(udpSocket2.connectToHost(QHostAddress("127.0.0.1"), port)); - QVERIFY(udpSocket2.state() == QAbstractSocket::ConnectedState); - - const int messageSize = 8192; - QByteArray message1(messageSize, '@'); - QByteArray answer(messageSize, '@'); - - QHostAddress localhost = QHostAddress::LocalHost; - - qlonglong readBytes = 0; - QTime timer; - timer.start(); - while (timer.elapsed() < 5000) { - udpSocket2.write(message1.data(), message1.size()); - udpSocket.waitForRead(); - while (udpSocket.hasPendingDatagrams()) { - readBytes += (qlonglong) udpSocket.readDatagram(answer.data(), - answer.size()); - } - } - - qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s", - readBytes / (1024.0 * 1024.0), - timer.elapsed() / 1024.0, - (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024)); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::tcpLoopbackPerformance() -{ - QNativeSocketEngine server; - - // Initialize a Tcp socket - QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); - - // Bind to any port on all interfaces - QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0)); - QVERIFY(server.state() == QAbstractSocket::BoundState); - quint16 port = server.localPort(); - - // Listen for incoming connections - QVERIFY(server.listen()); - QVERIFY(server.state() == QAbstractSocket::ListeningState); - - // Initialize a Tcp socket - QNativeSocketEngine client; - QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); - - // Connect to our server - if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { - QVERIFY(client.state() == QAbstractSocket::ConnectingState); - QVERIFY(client.waitForWrite()); - QVERIFY(client.state() == QAbstractSocket::ConnectedState); - } - - // The server accepts the connectio - int socketDescriptor = server.accept(); - QVERIFY(socketDescriptor > 0); - - // A socket device is initialized on the server side, passing the - // socket descriptor from accept(). It's pre-connected. - QNativeSocketEngine serverSocket; - QVERIFY(serverSocket.initialize(socketDescriptor)); - QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); - - const int messageSize = 1024 * 256; - QByteArray message1(messageSize, '@'); - QByteArray answer(messageSize, '@'); - - QTime timer; - timer.start(); - qlonglong readBytes = 0; - while (timer.elapsed() < 5000) { - qlonglong written = serverSocket.write(message1.data(), message1.size()); - while (written > 0) { - client.waitForRead(); - if (client.bytesAvailable() > 0) { - qlonglong readNow = client.read(answer.data(), answer.size()); - written -= readNow; - readBytes += readNow; - } - } - } - - qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s", - readBytes / (1024.0 * 1024.0), - timer.elapsed() / 1024.0, - (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024)); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::readWriteBufferSize() -{ - QNativeSocketEngine device; - - QVERIFY(device.initialize(QAbstractSocket::TcpSocket)); - - qint64 bufferSize = device.receiveBufferSize(); - QVERIFY(bufferSize != -1); - device.setReceiveBufferSize(bufferSize + 1); -#if defined(Q_OS_WINCE) - QEXPECT_FAIL(0, "Not supported by default on WinCE", Continue); -#endif - QVERIFY(device.receiveBufferSize() > bufferSize); - - bufferSize = device.sendBufferSize(); - QVERIFY(bufferSize != -1); - device.setSendBufferSize(bufferSize + 1); - QVERIFY(device.sendBufferSize() > bufferSize); - -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::tooManySockets() -{ -#if defined Q_OS_WIN - QSKIP("Certain windows machines suffocate and spend too much time in this test.", SkipAll); -#endif - QList sockets; - QNativeSocketEngine *socketLayer = 0; - for (;;) { - socketLayer = new QNativeSocketEngine; - sockets.append(socketLayer); - - if (!socketLayer->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)) - break; - } - - QCOMPARE(socketLayer->error(), QAbstractSocket::SocketResourceError); - - qDeleteAll(sockets); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::bind() -{ -#if !defined Q_OS_WIN && !defined Q_OS_SYMBIAN - QNativeSocketEngine binder; - QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - QVERIFY(!binder.bind(QHostAddress::Any, 82)); - QVERIFY(binder.error() == QAbstractSocket::SocketAccessError); -#endif - - QNativeSocketEngine binder2; - QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - QVERIFY(binder2.bind(QHostAddress::Any, 31180)); - - QNativeSocketEngine binder3; - QVERIFY(binder3.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - QVERIFY(!binder3.bind(QHostAddress::Any, 31180)); - -#ifdef SYMBIAN_WINSOCK_CONNECTIVITY - qDebug("On Symbian Emulator (WinSock) we get EADDRNOTAVAIL instead of EADDRINUSE"); - QVERIFY(binder3.error() == QAbstractSocket::SocketAddressNotAvailableError); -#else - QVERIFY(binder3.error() == QAbstractSocket::AddressInUseError); -#endif -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::networkError() -{ - QNativeSocketEngine client; - - QVERIFY(client.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - - const bool isConnected = client.connectToHost(QtNetworkSettings::serverIP(), 143); - if (!isConnected) { - QVERIFY(client.state() == QAbstractSocket::ConnectingState); - QVERIFY(client.waitForWrite()); - QVERIFY(client.state() == QAbstractSocket::ConnectedState); - } - QVERIFY(client.state() == QAbstractSocket::ConnectedState); - - // An unexpected network error! -#ifdef Q_OS_WIN - // could use shutdown to produce different errors - ::closesocket(client.socketDescriptor()); -#else - ::close(client.socketDescriptor()); -#endif - - QVERIFY(client.read(0, 0) == -1); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::setSocketDescriptor() -{ - QNativeSocketEngine socket1; - QVERIFY(socket1.initialize(QAbstractSocket::TcpSocket)); - - QNativeSocketEngine socket2; - QVERIFY(socket2.initialize(socket1.socketDescriptor())); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::invalidSend() -{ - QNativeSocketEngine socket; - QVERIFY(socket.initialize(QAbstractSocket::TcpSocket)); - - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::writeDatagram() was" - " called by a socket other than QAbstractSocket::UdpSocket"); - QCOMPARE(socket.writeDatagram("hei", 3, QHostAddress::LocalHost, 143), - (qlonglong) -1); -} - -//--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::receiveUrgentData() -{ - QNativeSocketEngine server; - - QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); - - // Bind to any port on all interfaces - QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0)); - QVERIFY(server.state() == QAbstractSocket::BoundState); - quint16 port = server.localPort(); - - QVERIFY(server.listen()); - QVERIFY(server.state() == QAbstractSocket::ListeningState); - - QNativeSocketEngine client; - QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); - - if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { - QVERIFY(client.state() == QAbstractSocket::ConnectingState); - QVERIFY(client.waitForWrite()); - QVERIFY(client.state() == QAbstractSocket::ConnectedState); - } - - int socketDescriptor = server.accept(); - QVERIFY(socketDescriptor > 0); - - QNativeSocketEngine serverSocket; - QVERIFY(serverSocket.initialize(socketDescriptor)); - QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); - - char msg; - int available; - QByteArray response; - -#if defined Q_OS_HPUX - QSKIP("Native OOB data test doesn't work on HP-UX.", SkipAll); -#elif defined (Q_OS_WINCE) - QSKIP("Native OOB data test doesn't work on WinCE.", SkipAll); -#endif - - // The server sends an urgent message - msg = 'Q'; - QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); - - // The client receives the urgent message - QVERIFY(client.waitForRead()); - available = client.bytesAvailable(); - QCOMPARE(available, 1); - response.resize(available); - QCOMPARE(client.read(response.data(), response.size()), qint64(1)); - QCOMPARE(response.at(0), msg); - - // The client sends an urgent message - msg = 'T'; - int clientDescriptor = client.socketDescriptor(); - QCOMPARE(int(::send(clientDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); - - // The server receives the urgent message - QVERIFY(serverSocket.waitForRead()); - available = serverSocket.bytesAvailable(); - QCOMPARE(available, 1); - response.resize(available); - QCOMPARE(serverSocket.read(response.data(), response.size()), qint64(1)); - QCOMPARE(response.at(0), msg); - -} - -QTEST_MAIN(tst_QNativeSocketEngine) -#include "tst_qnativesocketengine.moc" -- cgit v0.12 From 94226b6865615e844c46c6c068e3d4e9a9eb2068 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 9 Dec 2010 15:29:30 +0100 Subject: Make tst_platformsocketengine work Compile and instanciate the right engine. Reviewed-by: Shane Kearns --- tests/auto/network.pro | 4 +- tests/auto/platformsocketengine/.gitignore | 2 +- .../platformsocketengine/platformsocketengine.pro | 6 +- .../tst_platformsocketengine.cpp | 114 +++++++++++---------- tests/auto/qhttpsocketengine/qhttpsocketengine.pro | 2 +- .../qsocks5socketengine/qsocks5socketengine.pro | 2 +- 6 files changed, 68 insertions(+), 62 deletions(-) diff --git a/tests/auto/network.pro b/tests/auto/network.pro index 31c754c..5bf6a92 100644 --- a/tests/auto/network.pro +++ b/tests/auto/network.pro @@ -16,7 +16,7 @@ SUBDIRS=\ qhttpnetworkconnection \ qhttpnetworkreply \ qhttpsocketengine \ - qnativesocketengine \ + platformsocketengine \ qnetworkaccessmanager \ qnetworkaddressentry \ qnetworkconfiguration \ @@ -40,7 +40,7 @@ SUBDIRS=\ qauthenticator \ qhttpnetworkconnection \ qhttpnetworkreply \ - qnativesocketengine \ + platformsocketengine \ qsocketnotifier \ qsocks5socketengine \ diff --git a/tests/auto/platformsocketengine/.gitignore b/tests/auto/platformsocketengine/.gitignore index 4700e5e..afe9389 100644 --- a/tests/auto/platformsocketengine/.gitignore +++ b/tests/auto/platformsocketengine/.gitignore @@ -1 +1 @@ -tst_qnativesocketengine +tst_platformsocketengine diff --git a/tests/auto/platformsocketengine/platformsocketengine.pro b/tests/auto/platformsocketengine/platformsocketengine.pro index 0275d37..04816af 100644 --- a/tests/auto/platformsocketengine/platformsocketengine.pro +++ b/tests/auto/platformsocketengine/platformsocketengine.pro @@ -1,7 +1,7 @@ load(qttest_p4) -SOURCES += tst_qnativesocketengine.cpp +SOURCES += tst_platformsocketengine.cpp -include(../qnativesocketengine/qsocketengine.pri) +include(../platformsocketengine/platformsocketengine.pri) requires(contains(QT_CONFIG,private_tests)) @@ -10,4 +10,4 @@ MOC_DIR=tmp QT = core network symbian: TARGET.CAPABILITY = NetworkServices - +symbian: INCLUDEPATH += $$OS_LAYER_SYSTEMINCLUDE \ No newline at end of file diff --git a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp index 2b0b632..bede360 100644 --- a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -50,7 +50,6 @@ #include -#include #include #include @@ -63,6 +62,13 @@ #include +#ifdef Q_OS_SYMBIAN +#define PLATFORMSOCKETENGINE QSymbianSocketEngine +#include +#else +#define PLATFORMSOCKETENGINE QNativeSocketEngine +#include +#endif #include @@ -70,13 +76,13 @@ //TESTED_FILES=network/qnativesocketengine.cpp network/qnativesocketengine_p.h network/qnativesocketengine_unix.cpp -class tst_QNativeSocketEngine : public QObject +class tst_PlatformSocketEngine : public QObject { Q_OBJECT public: - tst_QNativeSocketEngine(); - virtual ~tst_QNativeSocketEngine(); + tst_PlatformSocketEngine(); + virtual ~tst_PlatformSocketEngine(); public slots: @@ -100,27 +106,27 @@ private slots: void receiveUrgentData(); }; -tst_QNativeSocketEngine::tst_QNativeSocketEngine() +tst_PlatformSocketEngine::tst_PlatformSocketEngine() { Q_SET_DEFAULT_IAP } -tst_QNativeSocketEngine::~tst_QNativeSocketEngine() +tst_PlatformSocketEngine::~tst_PlatformSocketEngine() { } -void tst_QNativeSocketEngine::init() +void tst_PlatformSocketEngine::init() { } -void tst_QNativeSocketEngine::cleanup() +void tst_PlatformSocketEngine::cleanup() { } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::construction() +void tst_PlatformSocketEngine::construction() { - QNativeSocketEngine socketDevice; + PLATFORMSOCKETENGINE socketDevice; QVERIFY(!socketDevice.isValid()); @@ -145,9 +151,9 @@ void tst_QNativeSocketEngine::construction() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::simpleConnectToIMAP() +void tst_PlatformSocketEngine::simpleConnectToIMAP() { - QNativeSocketEngine socketDevice; + PLATFORMSOCKETENGINE socketDevice; // Initialize device QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); @@ -202,12 +208,12 @@ void tst_QNativeSocketEngine::simpleConnectToIMAP() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpLoopbackTest() +void tst_PlatformSocketEngine::udpLoopbackTest() { #ifdef SYMBIAN_WINSOCK_CONNECTIVITY QSKIP("Not working on Emulator without WinPCAP", SkipAll); #endif - QNativeSocketEngine udpSocket; + PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); @@ -224,7 +230,7 @@ void tst_QNativeSocketEngine::udpLoopbackTest() QVERIFY(port != 0); // Initialize device #2 - QNativeSocketEngine udpSocket2; + PLATFORMSOCKETENGINE udpSocket2; QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); // Connect device #2 to #1 @@ -253,12 +259,12 @@ void tst_QNativeSocketEngine::udpLoopbackTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpIPv6LoopbackTest() +void tst_PlatformSocketEngine::udpIPv6LoopbackTest() { #if defined(Q_OS_SYMBIAN) QSKIP("Symbian: IPv6 is not yet supported", SkipAll); #endif - QNativeSocketEngine udpSocket; + PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 bool init = udpSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol); @@ -275,7 +281,7 @@ void tst_QNativeSocketEngine::udpIPv6LoopbackTest() QVERIFY(port != 0); // Initialize device #2 - QNativeSocketEngine udpSocket2; + PLATFORMSOCKETENGINE udpSocket2; QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol)); // Connect device #2 to #1 @@ -305,12 +311,12 @@ void tst_QNativeSocketEngine::udpIPv6LoopbackTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::broadcastTest() +void tst_PlatformSocketEngine::broadcastTest() { #ifdef Q_OS_AIX QSKIP("Broadcast does not work on darko", SkipAll); #endif - QNativeSocketEngine broadcastSocket; + PLATFORMSOCKETENGINE broadcastSocket; // Initialize a regular Udp socket QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket)); @@ -346,9 +352,9 @@ void tst_QNativeSocketEngine::broadcastTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::serverTest() +void tst_PlatformSocketEngine::serverTest() { - QNativeSocketEngine server; + PLATFORMSOCKETENGINE server; // Initialize a Tcp socket QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); @@ -363,7 +369,7 @@ void tst_QNativeSocketEngine::serverTest() QVERIFY(server.state() == QAbstractSocket::ListeningState); // Initialize a Tcp socket - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { QVERIFY(client.state() == QAbstractSocket::ConnectingState); @@ -377,7 +383,7 @@ void tst_QNativeSocketEngine::serverTest() // A socket device is initialized on the server side, passing the // socket descriptor from accept(). It's pre-connected. - QNativeSocketEngine serverSocket; + PLATFORMSOCKETENGINE serverSocket; QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); @@ -400,12 +406,12 @@ void tst_QNativeSocketEngine::serverTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpLoopbackPerformance() +void tst_PlatformSocketEngine::udpLoopbackPerformance() { #ifdef SYMBIAN_WINSOCK_CONNECTIVITY QSKIP("Not working on Emulator without WinPCAP", SkipAll); #endif - QNativeSocketEngine udpSocket; + PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); @@ -422,7 +428,7 @@ void tst_QNativeSocketEngine::udpLoopbackPerformance() QVERIFY(port != 0); // Initialize device #2 - QNativeSocketEngine udpSocket2; + PLATFORMSOCKETENGINE udpSocket2; QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); // Connect device #2 to #1 @@ -454,9 +460,9 @@ void tst_QNativeSocketEngine::udpLoopbackPerformance() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::tcpLoopbackPerformance() +void tst_PlatformSocketEngine::tcpLoopbackPerformance() { - QNativeSocketEngine server; + PLATFORMSOCKETENGINE server; // Initialize a Tcp socket QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); @@ -471,7 +477,7 @@ void tst_QNativeSocketEngine::tcpLoopbackPerformance() QVERIFY(server.state() == QAbstractSocket::ListeningState); // Initialize a Tcp socket - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); // Connect to our server @@ -487,7 +493,7 @@ void tst_QNativeSocketEngine::tcpLoopbackPerformance() // A socket device is initialized on the server side, passing the // socket descriptor from accept(). It's pre-connected. - QNativeSocketEngine serverSocket; + PLATFORMSOCKETENGINE serverSocket; QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); @@ -517,9 +523,9 @@ void tst_QNativeSocketEngine::tcpLoopbackPerformance() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::readWriteBufferSize() +void tst_PlatformSocketEngine::readWriteBufferSize() { - QNativeSocketEngine device; + PLATFORMSOCKETENGINE device; QVERIFY(device.initialize(QAbstractSocket::TcpSocket)); @@ -539,15 +545,15 @@ void tst_QNativeSocketEngine::readWriteBufferSize() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::tooManySockets() +void tst_PlatformSocketEngine::tooManySockets() { #if defined Q_OS_WIN QSKIP("Certain windows machines suffocate and spend too much time in this test.", SkipAll); #endif - QList sockets; - QNativeSocketEngine *socketLayer = 0; + QList sockets; + PLATFORMSOCKETENGINE *socketLayer = 0; for (;;) { - socketLayer = new QNativeSocketEngine; + socketLayer = new PLATFORMSOCKETENGINE; sockets.append(socketLayer); if (!socketLayer->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)) @@ -560,20 +566,20 @@ void tst_QNativeSocketEngine::tooManySockets() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::bind() +void tst_PlatformSocketEngine::bind() { #if !defined Q_OS_WIN && !defined Q_OS_SYMBIAN - QNativeSocketEngine binder; + PLATFORMSOCKETENGINE binder; QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); QVERIFY(!binder.bind(QHostAddress::Any, 82)); QVERIFY(binder.error() == QAbstractSocket::SocketAccessError); #endif - QNativeSocketEngine binder2; + PLATFORMSOCKETENGINE binder2; QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); QVERIFY(binder2.bind(QHostAddress::Any, 31180)); - QNativeSocketEngine binder3; + PLATFORMSOCKETENGINE binder3; QVERIFY(binder3.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); QVERIFY(!binder3.bind(QHostAddress::Any, 31180)); @@ -586,9 +592,9 @@ void tst_QNativeSocketEngine::bind() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::networkError() +void tst_PlatformSocketEngine::networkError() { - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); @@ -612,19 +618,19 @@ void tst_QNativeSocketEngine::networkError() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::setSocketDescriptor() +void tst_PlatformSocketEngine::setSocketDescriptor() { - QNativeSocketEngine socket1; + PLATFORMSOCKETENGINE socket1; QVERIFY(socket1.initialize(QAbstractSocket::TcpSocket)); - QNativeSocketEngine socket2; + PLATFORMSOCKETENGINE socket2; QVERIFY(socket2.initialize(socket1.socketDescriptor())); } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::invalidSend() +void tst_PlatformSocketEngine::invalidSend() { - QNativeSocketEngine socket; + PLATFORMSOCKETENGINE socket; QVERIFY(socket.initialize(QAbstractSocket::TcpSocket)); QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::writeDatagram() was" @@ -634,9 +640,9 @@ void tst_QNativeSocketEngine::invalidSend() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::receiveUrgentData() +void tst_PlatformSocketEngine::receiveUrgentData() { - QNativeSocketEngine server; + PLATFORMSOCKETENGINE server; QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); @@ -648,7 +654,7 @@ void tst_QNativeSocketEngine::receiveUrgentData() QVERIFY(server.listen()); QVERIFY(server.state() == QAbstractSocket::ListeningState); - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { @@ -660,7 +666,7 @@ void tst_QNativeSocketEngine::receiveUrgentData() int socketDescriptor = server.accept(); QVERIFY(socketDescriptor > 0); - QNativeSocketEngine serverSocket; + PLATFORMSOCKETENGINE serverSocket; QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); @@ -701,5 +707,5 @@ void tst_QNativeSocketEngine::receiveUrgentData() } -QTEST_MAIN(tst_QNativeSocketEngine) -#include "tst_qnativesocketengine.moc" +QTEST_MAIN(tst_PlatformSocketEngine) +#include "tst_platformsocketengine.moc" diff --git a/tests/auto/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/qhttpsocketengine/qhttpsocketengine.pro index d76ebb6..6df6192 100644 --- a/tests/auto/qhttpsocketengine/qhttpsocketengine.pro +++ b/tests/auto/qhttpsocketengine/qhttpsocketengine.pro @@ -2,7 +2,7 @@ load(qttest_p4) SOURCES += tst_qhttpsocketengine.cpp -include(../qnativesocketengine/qsocketengine.pri) +include(../platformsocketengine/platformsocketengine.pri) MOC_DIR=tmp diff --git a/tests/auto/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/qsocks5socketengine/qsocks5socketengine.pro index 171d428..c82c62d 100644 --- a/tests/auto/qsocks5socketengine/qsocks5socketengine.pro +++ b/tests/auto/qsocks5socketengine/qsocks5socketengine.pro @@ -2,7 +2,7 @@ load(qttest_p4) SOURCES += tst_qsocks5socketengine.cpp -include(../qnativesocketengine/qsocketengine.pri) +include(../platformsocketengine/platformsocketengine.pri) MOC_DIR=tmp -- cgit v0.12 From 9bbe9bc76222fa6f89283d96cbd9e448e331f909 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 9 Dec 2010 15:57:23 +0100 Subject: QSymbianSocketEngine: Some missing functions --- src/network/socket/qsymbiansocketengine.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 1490bdd..9eadf0a 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -465,6 +465,26 @@ int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const return -1; } +qint64 QSymbianSocketEngine::receiveBufferSize() const +{ + return option(ReceiveBufferSocketOption); +} + +void QSymbianSocketEngine::setReceiveBufferSize(qint64 size) +{ + setOption(ReceiveBufferSocketOption, size); +} + +qint64 QSymbianSocketEngine::sendBufferSize() const +{ + return option(SendBufferSocketOption); +} + +void QSymbianSocketEngine::setSendBufferSize(qint64 size) +{ + setOption(SendBufferSocketOption, size); +} + bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port) { // FIXME for engines that support hostnames.. not for us then i guess. -- cgit v0.12 From 931b3189d727f25f97c84f33c1d5fddaf0538777 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 9 Dec 2010 16:08:43 +0000 Subject: Fix some crashes in the symbian socket engine Reviewed-by: Markus Goetz --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 8 +- src/network/kernel/qhostinfo_symbian.cpp | 5 ++ src/network/socket/qsymbiansocketengine.cpp | 113 ++++++++++++++++++------ 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 55be6eb..f70080a 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1026,14 +1026,17 @@ bool QEventDispatcherSymbian::hasPendingEvents() void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier ) { - QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); + //TODO: just need to be able to do something when event loop has sockets disabled +/* QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); Q_CHECK_PTR(socketAO); m_notifiers.insert(notifier, socketAO); - selectThread().requestSocketEvents(notifier, &socketAO->iStatus); + selectThread().requestSocketEvents(notifier, &socketAO->iStatus);*/ } void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notifier ) { + //TODO: just need to be able to do something when event loop has sockets disabled + /* if (m_selectThread) m_selectThread->cancelSocketEvents(notifier); if (m_notifiers.contains(notifier)) { @@ -1042,6 +1045,7 @@ void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notif sockObj->deleteLater(); m_notifiers.remove(notifier); } + */ } void QEventDispatcherSymbian::reactivateSocketNotifier(QSocketNotifier *notifier) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 287021f..e70f2ce 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -89,6 +89,11 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) } */ + //TODO: HACK to return qt-test-server's ip + QList addresses; + addresses.append(QHostAddress("192.168.1.8")); + results.setHostName(hostName); + results.setAddresses(addresses); return results; } diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 9eadf0a..b92b3bc 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -206,7 +206,8 @@ QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : connection(QSymbianSocketManager::instance().defaultConnection()), readNotifier(0), writeNotifier(0), - exceptNotifier(0) + exceptNotifier(0), + asyncSelect(0) { } @@ -306,6 +307,11 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc if (isValid()) close(); + if(!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) { + d->setError(QAbstractSocket::SocketResourceError, + QSymbianSocketEnginePrivate::InvalidSocketErrorString); + return false; + } d->socketDescriptor = socketDescriptor; // determine socket type and protocol @@ -666,9 +672,7 @@ int QSymbianSocketEngine::accept() qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); return 0; } - // FIXME Qt Handle of new socket must be retrieved from QSymbianSocketManager - // and then returned. Not the SubSessionHandle! Also set the socket to nonblocking. - return blankSocket.SubSessionHandle(); + return QSymbianSocketManager::instance().addSocket(blankSocket); } qint64 QSymbianSocketEngine::bytesAvailable() const @@ -854,18 +858,47 @@ void QSymbianSocketEngine::close() qDebug("QSymbianSocketEnginePrivate::nativeClose()"); #endif + if (d->readNotifier) + d->readNotifier->setEnabled(false); + if (d->writeNotifier) + d->writeNotifier->setEnabled(false); + if (d->exceptNotifier) + d->exceptNotifier->setEnabled(false); + if(d->asyncSelect) { + d->asyncSelect->deleteLater(); + d->asyncSelect = 0; + } + //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? d->nativeSocket.Close(); QSymbianSocketManager::instance().removeSocket(d->nativeSocket); - - // FIXME set nativeSocket to 0 ? + d->socketDescriptor = -1; + + d->socketState = QAbstractSocket::UnconnectedState; + d->hasSetSocketError = false; + d->localPort = 0; + d->localAddress.clear(); + d->peerPort = 0; + d->peerAddress.clear(); + if (d->readNotifier) { + qDeleteInEventHandler(d->readNotifier); + d->readNotifier = 0; + } + if (d->writeNotifier) { + qDeleteInEventHandler(d->writeNotifier); + d->writeNotifier = 0; + } + if (d->exceptNotifier) { + qDeleteInEventHandler(d->exceptNotifier); + d->exceptNotifier = 0; + } } qint64 QSymbianSocketEngine::write(const char *data, qint64 len) { Q_D(QSymbianSocketEngine); TPtrC8 buffer((TUint8*)data, (int)len); - TSockXfrLength sentBytes; + TSockXfrLength sentBytes = 0; TRequestStatus status; //TODO: OMG sync send! d->nativeSocket.Send(buffer, 0, status, sentBytes); User::WaitForRequest(status); @@ -874,6 +907,7 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) if (err) { switch (err) { case KErrDisconnected: + case KErrEof: sentBytes = -1; d->setError(QAbstractSocket::RemoteHostClosedError, d->RemoteHostClosedErrorString); close(); @@ -882,9 +916,12 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString); break; case KErrWouldBlock: - sentBytes = 0; + break; default: - d->setError(QAbstractSocket::NetworkError, d->SendDatagramErrorString); + sentBytes = -1; + d->setError(err); + close(); + break; } } @@ -914,20 +951,13 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) TInt err = status.Int(); int r = received(); - if (err) { - switch(err) { - case KErrWouldBlock: - // No data was available for reading - r = -2; - break; - case KErrDisconnected: - r = 0; - break; - default: - r = -1; - //error string is now set in read(), not here in nativeRead() - break; - } + if (err == KErrWouldBlock) { + // No data was available for reading + r = -2; + } else if (err != KErrNone) { + d->setError(err); + close(); + r = -1; } #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -1188,6 +1218,36 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E } } +//TODO: use QSystemError class when file engine is merged to master +void QSymbianSocketEnginePrivate::setError(TInt symbianError) +{ + hasSetSocketError = true; + switch(symbianError) { + case KErrDisconnected: + case KErrEof: + setError(QAbstractSocket::RemoteHostClosedError, + QSymbianSocketEnginePrivate::RemoteHostClosedErrorString); + break; + case KErrNetUnreach: + setError(QAbstractSocket::NetworkError, + QSymbianSocketEnginePrivate::NetworkUnreachableErrorString); + break; + case KErrHostUnreach: + setError(QAbstractSocket::NetworkError, + QSymbianSocketEnginePrivate::HostUnreachableErrorString); + break; + case KErrNoProtocolOpt: + setError(QAbstractSocket::NetworkError, + QSymbianSocketEnginePrivate::ProtocolUnsupportedErrorString); + break; + default: + socketError = QAbstractSocket::NetworkError; + socketErrorString = QString::number(symbianError); + break; + } + +} + class QReadNotifier : public QSocketNotifier { friend class QAsyncSelect; @@ -1277,7 +1337,7 @@ void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) d->writeNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { QWriteNotifier *wn = new QWriteNotifier(d->socketDescriptor, this); - d->readNotifier = wn; + d->writeNotifier = wn; if (!(d->asyncSelect)) d->asyncSelect = q_check_ptr(new QAsyncSelect(d->threadData->eventDispatcher, d->nativeSocket, this)); d->asyncSelect->setWriteNotifier(wn); @@ -1451,7 +1511,7 @@ void QAsyncSelect::RunL() QEvent e(QEvent::SockAct); iWriteN->event(&e); } - if ((m_selectBuf() && KSockSelectExcept) || iStatus != KErrNone) { + if ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone) { QEvent e(QEvent::SockAct); iExcN->event(&e); } @@ -1463,6 +1523,9 @@ void QAsyncSelect::RunL() void QAsyncSelect::deleteLater() { if (m_inSocketEvent) { + iExcN = 0; + iReadN = 0; + iWriteN = 0; m_deleteLater = true; } else { delete this; -- cgit v0.12 From 9a565b61fc8fdb7dd786072a78e6ae903b59ded2 Mon Sep 17 00:00:00 2001 From: Aaron Tunney Date: Thu, 9 Dec 2010 18:03:58 +0000 Subject: QHostInfo: Symbian implementation for fromName() Reviewed-By: Markus Goetz --- src/network/kernel/qhostinfo_symbian.cpp | 106 ++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 15 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index e70f2ce..fbd7fe9 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -40,19 +40,44 @@ ****************************************************************************/ //#define QHOSTINFO_DEBUG + +// Symbian Headers +#include +#include + +// Qt Headers #include #include +#include #include "qplatformdefs.h" #include "qhostinfo_p.h" +#include QT_BEGIN_NAMESPACE + QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; + // Connect to ESOCK + RSocketServ socketServ(qt_symbianGetSocketServer()); + RHostResolver hostResolver; + + // Will return both IPv4 and IPv6 + // TODO: Pass RHostResolver.Open() the global RConnection + int err = hostResolver.Open(socketServ, KAfInet, KProtocolInetUdp); + if (err) { + results.setError(QHostInfo::UnknownError); + results.setErrorString(tr("Symbian error code: %1").arg(err)); + + return results; + } + + TNameEntry nameResult; + #if defined(QHOSTINFO_DEBUG) qDebug("QHostInfoAgent::fromName(%s) looking up...", hostName.toLatin1().constData()); @@ -61,8 +86,26 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup - // TODO - results.setHostName("assume.it.works"); + + TInetAddr IpAdd; + IpAdd.Input(qt_QString2TPtrC(hostName)); + + // Synchronous request. nameResult returns Host Name. + hostResolver.GetByAddress(IpAdd, nameResult); + if (err) { + // TODO - Could there be other errors? Symbian docs don't say. + if (err = KErrNotFound) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(tr("Host not found")); + } else { + results.setError(QHostInfo::UnknownError); + results.setErrorString(tr("Symbian error code: %1").arg(err)); + } + + return results; + } + + results.setHostName(qt_TDesC2QString(nameResult().iName)); results.setAddresses(QList() << address); return results; } @@ -78,32 +121,65 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } - // Call getaddrinfo, and place all IPv4 addresses at the start and + + // Call RHostResolver::GetByAddress, and place all IPv4 addresses at the start and // the IPv6 addresses at the end of the address list in results. - /* - results.setError(QHostInfo::HostNotFound); - results.setErrorString(tr("Host not found")); - } else { - results.setError(QHostInfo::UnknownError); - results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); + + // Synchronous request. + err = hostResolver.GetByName(qt_QString2TPtrC(aceHostname), nameResult); + if (err) { + // TODO - Could there be other errors? Symbian docs don't say. + if (err = KErrNotFound) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(tr("Host not found")); + } else { + results.setError(QHostInfo::UnknownError); + results.setErrorString(tr("Symbian error code: %1").arg(err)); + } + + return results; } - */ - //TODO: HACK to return qt-test-server's ip - QList addresses; - addresses.append(QHostAddress("192.168.1.8")); - results.setHostName(hostName); - results.setAddresses(addresses); + QList hostAddresses; + + TInetAddr hostAdd = nameResult().iAddr; + TBuf<16> ipAddr; + // Fill ipAddr with the IP address from hostAdd + hostAdd.Output(ipAddr); + if (ipAddr.Length() > 0) + hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + + // Check if there's more than one IP address linkd to this name + while (hostResolver.Next(nameResult) == KErrNone) { + hostAdd = nameResult().iAddr; + hostAdd.Output(ipAddr); + + if (ipAddr.Length() > 0) { + if (nameResult().iAddr.Family() == KAfInet) { + // IPv4 - prepend + hostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); + } else { + // IPv6 - append + hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + } + } + } + + hostResolver.Close(); + + results.setAddresses(hostAddresses); return results; } QString QHostInfo::localHostName() { + // TODO - fill with code. return QString(); } QString QHostInfo::localDomainName() { + // TODO - fill with code. return QString(); } -- cgit v0.12 From 9c3967b7738b50655a7b9d6a5a0e89fdf2afc1df Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 9 Dec 2010 18:27:51 +0000 Subject: Fix some issues in symbian socket engine Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 97 ++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 22 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index b92b3bc..602df5c 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -75,6 +75,40 @@ QT_BEGIN_NAMESPACE +// Common constructs +#define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \ + if (!isValid()) { \ + qWarning(""#function" was called on an uninitialized socket device"); \ + return returnValue; \ + } } while (0) +#define Q_CHECK_INVALID_SOCKETLAYER(function, returnValue) do { \ + if (isValid()) { \ + qWarning(""#function" was called on an already initialized socket device"); \ + return returnValue; \ + } } while (0) +#define Q_CHECK_STATE(function, checkState, returnValue) do { \ + if (d->socketState != (checkState)) { \ + qWarning(""#function" was not called in "#checkState); \ + return (returnValue); \ + } } while (0) +#define Q_CHECK_NOT_STATE(function, checkState, returnValue) do { \ + if (d->socketState == (checkState)) { \ + qWarning(""#function" was called in "#checkState); \ + return (returnValue); \ + } } while (0) +#define Q_CHECK_STATES(function, state1, state2, returnValue) do { \ + if (d->socketState != (state1) && d->socketState != (state2)) { \ + qWarning(""#function" was called" \ + " not in "#state1" or "#state2); \ + return (returnValue); \ + } } while (0) +#define Q_CHECK_TYPE(function, type, returnValue) do { \ + if (d->socketType != (type)) { \ + qWarning(#function" was called by a" \ + " socket other than "#type""); \ + return (returnValue); \ + } } while (0) + #if defined QNATIVESOCKETENGINE_DEBUG /* @@ -307,7 +341,7 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc if (isValid()) close(); - if(!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) { + if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) { d->setError(QAbstractSocket::SocketResourceError, QSymbianSocketEnginePrivate::InvalidSocketErrorString); return false; @@ -539,12 +573,16 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) TInt err = status.Int(); if (err) { switch (err) { + case KErrWouldBlock: + d->socketState = QAbstractSocket::ConnectingState; + break; case KErrCouldNotConnect: d->setError(QAbstractSocket::ConnectionRefusedError, d->ConnectionRefusedErrorString); d->socketState = QAbstractSocket::UnconnectedState; break; case KErrTimedOut: d->setError(QAbstractSocket::NetworkError, d->ConnectionTimeOutErrorString); + d->socketState = QAbstractSocket::UnconnectedState; break; case KErrHostUnreach: d->setError(QAbstractSocket::NetworkError, d->HostUnreachableErrorString); @@ -563,8 +601,8 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) break; case KErrNotSupported: case KErrBadDescriptor: - d->socketState = QAbstractSocket::UnconnectedState; default: + d->socketState = QAbstractSocket::UnconnectedState; break; } @@ -592,25 +630,20 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false); + + if (!d->checkProxy(address)) + return false; + + Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); + TInetAddr nativeAddr; d->setPortAndAddress(nativeAddr, port, address); TInt err = d->nativeSocket.Bind(nativeAddr); if (err) { - switch(errno) { - case KErrInUse: - d->setError(QAbstractSocket::AddressInUseError, d->AddressInuseErrorString); - break; - case KErrPermissionDenied: - d->setError(QAbstractSocket::SocketAccessError, d->AddressProtectedErrorString); - break; - case KErrNotSupported: - d->setError(QAbstractSocket::UnsupportedSocketOperationError, d->OperationUnsupportedErrorString); - break; - default: - break; - } + d->setError(err); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", @@ -625,6 +658,8 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) address.toString().toLatin1().constData(), port); #endif d->socketState = QAbstractSocket::BoundState; + + d->fetchConnectionParameters(); return true; } @@ -708,9 +743,7 @@ qint64 QSymbianSocketEngine::pendingDatagramSize() const Q_D(const QSymbianSocketEngine); int nbytes; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); - return qint64(nbytes-28); //TODO: why -28 (open C version had this)? - // Why = Could it be that this is about header lengths etc? if yes - // this could be pretty broken, especially for IPv6 + return qint64(nbytes); } @@ -853,6 +886,8 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() void QSymbianSocketEngine::close() { + if (!isValid()) + return; Q_D(QSymbianSocketEngine); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEnginePrivate::nativeClose()"); @@ -864,12 +899,18 @@ void QSymbianSocketEngine::close() d->writeNotifier->setEnabled(false); if (d->exceptNotifier) d->exceptNotifier->setEnabled(false); - if(d->asyncSelect) { + if (d->asyncSelect) { d->asyncSelect->deleteLater(); d->asyncSelect = 0; } //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? + if (d->socketType == QAbstractSocket::UdpSocket) { + //TODO: Close hangs without this, but only for UDP - why? + TRequestStatus stat; + d->nativeSocket.Shutdown(RSocket::EImmediate, stat); + User::WaitForRequest(stat); + } d->nativeSocket.Close(); QSymbianSocketManager::instance().removeSocket(d->nativeSocket); d->socketDescriptor = -1; @@ -1221,8 +1262,7 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E //TODO: use QSystemError class when file engine is merged to master void QSymbianSocketEnginePrivate::setError(TInt symbianError) { - hasSetSocketError = true; - switch(symbianError) { + switch (symbianError) { case KErrDisconnected: case KErrEof: setError(QAbstractSocket::RemoteHostClosedError, @@ -1240,12 +1280,21 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) setError(QAbstractSocket::NetworkError, QSymbianSocketEnginePrivate::ProtocolUnsupportedErrorString); break; + case KErrInUse: + setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); + break; + case KErrPermissionDenied: + setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); + break; + case KErrNotSupported: + setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); + break; default: socketError = QAbstractSocket::NetworkError; socketErrorString = QString::number(symbianError); break; } - + hasSetSocketError = true; } class QReadNotifier : public QSocketNotifier @@ -1516,6 +1565,10 @@ void QAsyncSelect::RunL() iExcN->event(&e); } m_inSocketEvent = false; + if (m_deleteLater) { + delete this; + return; + } // select again (unless disabled by one of the callbacks) IssueRequest(); } -- cgit v0.12 From cb7a89049f1e41edf02aaab56a00cef8c6005eba Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 10 Dec 2010 10:27:32 +0000 Subject: Fixes for socket engine autotest failures Reviewed-by: Markus Goetz --- src/corelib/kernel/qcore_symbian_p.cpp | 2 +- src/network/socket/qsymbiansocketengine.cpp | 10 ++++++++-- src/network/socket/qsymbiansocketengine_p.h | 4 ++-- .../platformsocketengine/platformsocketengine.pro | 7 +++++-- .../platformsocketengine/tst_platformsocketengine.cpp | 19 ++++++++++++++++--- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index ede8464..fdae31b 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -283,7 +283,7 @@ int QSymbianSocketManager::lookupSocket(const RSocket& socket) const { bool QSymbianSocketManager::lookupSocket(int fd, RSocket& socket) const { QMutexLocker l(&iMutex); - int id = fd + socket_offset; + int id = fd - socket_offset; if(!reverseSocketMap.contains(id)) return false; socket = reverseSocketMap.value(id); diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 602df5c..b63dbf6 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -641,6 +641,10 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) d->setPortAndAddress(nativeAddr, port, address); TInt err = d->nativeSocket.Bind(nativeAddr); +#ifdef __WINS__ + if (err == KErrArgument) // winsock prt returns wrong error code + err = KErrInUse; +#endif if (err) { d->setError(err); @@ -781,6 +785,8 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); + Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1); TPtrC8 buffer((TUint8*)data, (int)len); TInetAddr addr; d->setPortAndAddress(addr, port, host); @@ -940,9 +946,9 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) Q_D(QSymbianSocketEngine); TPtrC8 buffer((TUint8*)data, (int)len); TSockXfrLength sentBytes = 0; - TRequestStatus status; //TODO: OMG sync send! + TRequestStatus status; d->nativeSocket.Send(buffer, 0, status, sentBytes); - User::WaitForRequest(status); + User::WaitForRequest(status); //TODO: on emulator this blocks for write >16kB (non blocking IO not implemented properly?) TInt err = status.Int(); if (err) { diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 2d5bcd8..bc85f9c 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -172,8 +172,8 @@ private: QReadNotifier* iReadN; QWriteNotifier* iWriteN; QExceptionNotifier* iExcN; - bool m_inSocketEvent; // TODO ? - bool m_deleteLater; // TODO ? + bool m_inSocketEvent; + bool m_deleteLater; RSocket &m_socket; TUint m_selectFlags; diff --git a/tests/auto/platformsocketengine/platformsocketengine.pro b/tests/auto/platformsocketengine/platformsocketengine.pro index 04816af..faf745c 100644 --- a/tests/auto/platformsocketengine/platformsocketengine.pro +++ b/tests/auto/platformsocketengine/platformsocketengine.pro @@ -9,5 +9,8 @@ MOC_DIR=tmp QT = core network -symbian: TARGET.CAPABILITY = NetworkServices -symbian: INCLUDEPATH += $$OS_LAYER_SYSTEMINCLUDE \ No newline at end of file +symbian { + TARGET.CAPABILITY = NetworkServices + INCLUDEPATH += $$OS_LAYER_SYSTEMINCLUDE + LIBS += -lesock +} diff --git a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp index bede360..a7b4235 100644 --- a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -65,6 +65,7 @@ #ifdef Q_OS_SYMBIAN #define PLATFORMSOCKETENGINE QSymbianSocketEngine #include +#include #else #define PLATFORMSOCKETENGINE QNativeSocketEngine #include @@ -98,12 +99,12 @@ private slots: void udpLoopbackPerformance(); void tcpLoopbackPerformance(); void readWriteBufferSize(); - void tooManySockets(); void bind(); void networkError(); void setSocketDescriptor(); void invalidSend(); void receiveUrgentData(); + void tooManySockets(); }; tst_PlatformSocketEngine::tst_PlatformSocketEngine() @@ -179,7 +180,9 @@ void tst_PlatformSocketEngine::simpleConnectToIMAP() QVERIFY(socketDevice.read(array.data(), array.size()) == available); // Check that the greeting is what we expect it to be - QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData()); + //QCOMPARE(array.constData(), QtNetworkSettings::expectedReplyIMAP().constData()); + QVERIFY(array.startsWith("* OK")); + QVERIFY(array.endsWith("server ready\r\n")); // Write a logout message QByteArray array2 = "ZZZ LOGOUT\r\n"; @@ -487,7 +490,7 @@ void tst_PlatformSocketEngine::tcpLoopbackPerformance() QVERIFY(client.state() == QAbstractSocket::ConnectedState); } - // The server accepts the connectio + // The server accepts the connection int socketDescriptor = server.accept(); QVERIFY(socketDescriptor > 0); @@ -497,7 +500,11 @@ void tst_PlatformSocketEngine::tcpLoopbackPerformance() QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); +#if defined (Q_OS_SYMBIAN) && defined (__WINS__) + const int messageSize = 1024 * 16; +#else const int messageSize = 1024 * 256; +#endif QByteArray message1(messageSize, '@'); QByteArray answer(messageSize, '@'); @@ -610,6 +617,12 @@ void tst_PlatformSocketEngine::networkError() #ifdef Q_OS_WIN // could use shutdown to produce different errors ::closesocket(client.socketDescriptor()); +#elif defined(Q_OS_SYMBIAN) + RSocket sock; + QVERIFY(QSymbianSocketManager::instance().lookupSocket(client.socketDescriptor(), sock)); + TRequestStatus stat; + sock.Shutdown(RSocket::EImmediate, stat); + User::WaitForRequest(stat); #else ::close(client.socketDescriptor()); #endif -- cgit v0.12 From 4d86bacafad3b12ca01c20988bf578cde7bf3dae Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 10 Dec 2010 15:18:24 +0000 Subject: Platform socket engine test fixes & update TODOs Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 20 ++++++++++++----- .../tst_platformsocketengine.cpp | 25 ++++++++++++++++------ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index b63dbf6..90d5265 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -188,6 +188,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so else err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead + //TODO: combine error handling with setError if (err != KErrNone) { switch (err) { case KErrNotSupported: @@ -375,6 +376,12 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc close(); return false; } + + // Make sure we receive out-of-band data + if (socketType == QAbstractSocket::TcpSocket + && !setOption(ReceiveOutOfBandData, 1)) { + qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); + } } d->socketState = socketState; @@ -566,11 +573,11 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) TInetAddr nativeAddr; d->setPortAndAddress(nativeAddr, port, addr); - //TODO: async connect with active object - from here to end of function is a mess TRequestStatus status; d->nativeSocket.Connect(nativeAddr, status); User::WaitForRequest(status); TInt err = status.Int(); + //TODO: combine with setError(int) if (err) { switch (err) { case KErrWouldBlock: @@ -674,7 +681,8 @@ bool QSymbianSocketEngine::listen() // for a mobile platform TInt err = d->nativeSocket.Listen(50); if (err) { - switch (errno) { + //TODO: combine with setError(int) + switch (err) { case KErrInUse: d->setError(QAbstractSocket::AddressInUseError, d->PortInuseErrorString); @@ -702,7 +710,6 @@ int QSymbianSocketEngine::accept() { Q_D(QSymbianSocketEngine); RSocket blankSocket; - //TODO: this is unbelievably broken, needs to be properly async blankSocket.Open(d->socketServer); TRequestStatus status; d->nativeSocket.Accept(blankSocket, status); @@ -717,10 +724,10 @@ int QSymbianSocketEngine::accept() qint64 QSymbianSocketEngine::bytesAvailable() const { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1); + Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, false); int nbytes = 0; qint64 available = 0; - // FIXME is this the right thing also for UDP? - // What is expected for UDP, the length for the next packet I guess? TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); if (err) return 0; @@ -735,6 +742,9 @@ qint64 QSymbianSocketEngine::bytesAvailable() const bool QSymbianSocketEngine::hasPendingDatagrams() const { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false); + Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false); + Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false); int nbytes; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); return err == KErrNone && nbytes > 0; diff --git a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp index a7b4235..2fb3724 100644 --- a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -213,9 +213,6 @@ void tst_PlatformSocketEngine::simpleConnectToIMAP() //--------------------------------------------------------------------------- void tst_PlatformSocketEngine::udpLoopbackTest() { -#ifdef SYMBIAN_WINSOCK_CONNECTIVITY - QSKIP("Not working on Emulator without WinPCAP", SkipAll); -#endif PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 @@ -264,9 +261,6 @@ void tst_PlatformSocketEngine::udpLoopbackTest() //--------------------------------------------------------------------------- void tst_PlatformSocketEngine::udpIPv6LoopbackTest() { -#if defined(Q_OS_SYMBIAN) - QSKIP("Symbian: IPv6 is not yet supported", SkipAll); -#endif PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 @@ -695,7 +689,18 @@ void tst_PlatformSocketEngine::receiveUrgentData() // The server sends an urgent message msg = 'Q'; +#if defined(Q_OS_SYMBIAN) + RSocket sock; + QVERIFY(QSymbianSocketManager::instance().lookupSocket(socketDescriptor, sock)); + TRequestStatus stat; + TSockXfrLength len; + sock.Send(TPtrC8((TUint8*)&msg,1), KSockWriteUrgent, stat, len); + User::WaitForRequest(stat); + QVERIFY(stat == KErrNone); + QCOMPARE(len(), 1); +#else QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); +#endif // The client receives the urgent message QVERIFY(client.waitForRead()); @@ -708,7 +713,15 @@ void tst_PlatformSocketEngine::receiveUrgentData() // The client sends an urgent message msg = 'T'; int clientDescriptor = client.socketDescriptor(); +#if defined(Q_OS_SYMBIAN) + QVERIFY(QSymbianSocketManager::instance().lookupSocket(clientDescriptor, sock)); + sock.Send(TPtrC8((TUint8*)&msg,1), KSockWriteUrgent, stat, len); + User::WaitForRequest(stat); + QVERIFY(stat == KErrNone); + QCOMPARE(len(), 1); +#else QCOMPARE(int(::send(clientDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); +#endif // The server receives the urgent message QVERIFY(serverSocket.waitForRead()); -- cgit v0.12 From 6beb46f6e2971188c13d8b2922eaa3801a890b71 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 4 Jan 2011 13:47:12 +0000 Subject: Fix compile error --- src/network/socket/qsymbiansocketengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 90d5265..a1ff9b9 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -378,7 +378,7 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc } // Make sure we receive out-of-band data - if (socketType == QAbstractSocket::TcpSocket + if (d->socketType == QAbstractSocket::TcpSocket && !setOption(ReceiveOutOfBandData, 1)) { qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); } -- cgit v0.12 From 29929a3c6368f62cdb58bd7255aa6f93e8d9f2f6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 12 Jan 2011 13:58:50 +0000 Subject: Fix non blocking connect on symbian devices The socket server returns KErrAlreadyExists rather than KErrNone when connect is called as second time after the select ioctl completes. Reviewed-by: Markus Goetz Reviewed-by: Aaron Tunney --- src/network/socket/qsymbiansocketengine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index a1ff9b9..2f991de 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -578,7 +578,10 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) User::WaitForRequest(status); TInt err = status.Int(); //TODO: combine with setError(int) - if (err) { + //For non blocking connect, KErrAlreadyExists is returned from the second Connect() to indicate + //the connection is up. So treat this the same as KErrNone which would be returned from the first + //call if it wouldn't block. (e.g. winsock wrapper in the emulator ignores the nonblocking flag) + if (err && err != KErrAlreadyExists) { switch (err) { case KErrWouldBlock: d->socketState = QAbstractSocket::ConnectingState; -- cgit v0.12 From 1b3b85eca8ccb1cc793586105340980cc238eae3 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 6 Jan 2011 15:16:03 +0000 Subject: Fix KERN-EXEC 0 panic on exit when bearer is searching for WLANs The access point scanner cancels itself in the destructor. This requires the handle to be valid, but it was closed in the symbian engine destructor immediately before deleting the AP scanner. Because of the way symbian active objects work, the crashing function is only called if there was an asynchronous request in progress. So it could be missed in cases where the scan completes faster than the test case. Task-number: QTBUG-16484 Reviewed-by: Markus Goetz --- src/plugins/bearer/symbian/symbianengine.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index f025d86..a370d78 100644 --- a/src/plugins/bearer/symbian/symbianengine.cpp +++ b/src/plugins/bearer/symbian/symbianengine.cpp @@ -144,6 +144,10 @@ SymbianEngine::~SymbianEngine() { Cancel(); + //The scanner may be using the connection monitor so it needs to be + //deleted first while the handle is still valid. + delete ipAccessPointsAvailabilityScanner; + iConnectionMonitor.CancelNotifications(); iConnectionMonitor.Close(); @@ -151,8 +155,6 @@ SymbianEngine::~SymbianEngine() iCmManager.Close(); #endif - delete ipAccessPointsAvailabilityScanner; - // CCommsDatabase destructor uses cleanup stack. Since QNetworkConfigurationManager // is a global static, but the time we are here, E32Main() has been exited already and // the thread's default cleanup stack has been deleted. Without this line, a -- cgit v0.12 From 47604a6de645eaabb3a673bcbedafc6d0da00137 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 17 Jan 2011 13:35:58 +0000 Subject: Add QScopedValueRollback tools class. This template allows a value to be automatically rolled back to a previous state when the class goes out of scope. This can be used to maintain a valid state when an exception is thrown. Reviewed-by: mread Reviewed-by: joao --- src/corelib/tools/qscopedvaluerollback.cpp | 84 ++++++++++++++++++++++++++++++ src/corelib/tools/qscopedvaluerollback.h | 81 ++++++++++++++++++++++++++++ src/corelib/tools/tools.pri | 7 +-- 3 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 src/corelib/tools/qscopedvaluerollback.cpp create mode 100644 src/corelib/tools/qscopedvaluerollback.h diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp new file mode 100644 index 0000000..8933efc --- /dev/null +++ b/src/corelib/tools/qscopedvaluerollback.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qscopedvaluerollback.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QScopedValueRollback + \brief The QScopedValueRollback resets a variable to its previous value on destruction + \since 4.8 + \ingroup misc + + The QScopedAssignment class can be used to revert state when an + exception is thrown without needing to write try-catch blocks. + + It can also be used to manage variables that are temporarily set, + such as reentrancy guards. By using this class, the variable will + be reset whether the function is exited normally, exited early by + a return statement, or exited by an exception. + + The template can only be instantiated with a type that supports assignment. + + \sa QScopedPointer +*/ + +/*! + \fn QScopedValueRollback::QScopedValueRollback(T &var) + + Stores the previous value of var internally, for revert on destruction. +*/ + +/*! + \fn QScopedValueRollback::~QScopedValueRollback() + + Assigns the previous value to the managed variable. + This is the value at construction time, or at the last call to commit() +*/ + +/*! + \fn void QScopedValueRollback::commit() + + Updates the previous value of the managed variable to its current value. +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h new file mode 100644 index 0000000..d344ed8 --- /dev/null +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCOPEDVALUEROLLBACK_H +#define QSCOPEDVALUEROLLBACK_H + +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE +QT_MODULE(Core) + +template +class QScopedValueRollback +{ +public: + QScopedValueRollback(T &var) : + varRef(var) + { + oldValue = varRef; + } + + ~QScopedValueRollback() + { + varRef = oldValue; + } + + void commit() + { + oldValue = varRef; + } + +private: + T& varRef; + T oldValue; + + Q_DISABLE_COPY(QScopedValueRollback); +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QSCOPEDVALUEROLLBACK_H diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 03bb32d..9d564a1 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -29,6 +29,9 @@ HEADERS += \ tools/qrect.h \ tools/qregexp.h \ tools/qringbuffer_p.h \ + tools/qscopedpointer.h \ + tools/qscopedpointer_p.h \ + tools/qscopedvaluerollback.h \ tools/qshareddata.h \ tools/qsharedpointer.h \ tools/qsharedpointer_impl.h \ @@ -45,9 +48,7 @@ HEADERS += \ tools/qelapsedtimer.h \ tools/qunicodetables_p.h \ tools/qvarlengtharray.h \ - tools/qvector.h \ - tools/qscopedpointer.h \ - tools/qscopedpointer_p.h + tools/qvector.h SOURCES += \ -- cgit v0.12 From b1477e557681372d2c7119d637048123f0bad120 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 17 Jan 2011 15:07:46 +0000 Subject: Add autotest for QScopedValueRollback Reviewed-by: mread --- .../qscopedvaluerollback/qscopedvaluerollback.pro | 4 + .../tst_qscopedvaluerollback.cpp | 203 +++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 tests/auto/qscopedvaluerollback/qscopedvaluerollback.pro create mode 100644 tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp diff --git a/tests/auto/qscopedvaluerollback/qscopedvaluerollback.pro b/tests/auto/qscopedvaluerollback/qscopedvaluerollback.pro new file mode 100644 index 0000000..f06e21b --- /dev/null +++ b/tests/auto/qscopedvaluerollback/qscopedvaluerollback.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +SOURCES += tst_qscopedvaluerollback.cpp +QT -= gui +CONFIG += parallel_test diff --git a/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp b/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp new file mode 100644 index 0000000..fac5702 --- /dev/null +++ b/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +/*! + \class tst_QScopedValueRollback + \internal + \since 4.8 + \brief Tests class QScopedValueRollback. + + */ +class tst_QScopedValueRollback : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void leavingScope(); + void leavingScopeAfterCommit(); + void rollbackToPreviousCommit(); + void exceptions(); + void earlyExitScope(); +private: + void earlyExitScope_helper(int exitpoint, int &member); +}; + +void tst_QScopedValueRollback::leavingScope() +{ + int i = 0; + bool b = false; + QString s("This is useful"); + + //test rollback on going out of scope + { + QScopedValueRollback ri(i); + QScopedValueRollback rb(b); + QScopedValueRollback rs(s); + QCOMPARE(b, false); + QCOMPARE(i, 0); + QCOMPARE(s, QString("This is useful")); + b = true; + i = 1; + s = "Useless"; + QCOMPARE(b, true); + QCOMPARE(i, 1); + QCOMPARE(s, QString("Useless")); + } + QCOMPARE(b, false); + QCOMPARE(i, 0); + QCOMPARE(s, QString("This is useful")); +} + +void tst_QScopedValueRollback::leavingScopeAfterCommit() +{ + int i = 0; + bool b = false; + QString s("This is useful"); + + //test rollback on going out of scope + { + QScopedValueRollback ri(i); + QScopedValueRollback rb(b); + QScopedValueRollback rs(s); + QCOMPARE(b, false); + QCOMPARE(i, 0); + QCOMPARE(s, QString("This is useful")); + b = true; + i = 1; + s = "Useless"; + QCOMPARE(b, true); + QCOMPARE(i, 1); + QCOMPARE(s, QString("Useless")); + ri.commit(); + rb.commit(); + rs.commit(); + } + QCOMPARE(b, true); + QCOMPARE(i, 1); + QCOMPARE(s, QString("Useless")); +} + +void tst_QScopedValueRollback::rollbackToPreviousCommit() +{ + int i=0; + { + QScopedValueRollback ri(i); + i++; + ri.commit(); + i++; + } + QCOMPARE(i,1); + { + QScopedValueRollback ri1(i); + i++; + ri1.commit(); + i++; + ri1.commit(); + i++; + } + QCOMPARE(i,3); +} + +void tst_QScopedValueRollback::exceptions() +{ + bool b = false; + bool caught = false; + QT_TRY + { + QScopedValueRollback rb(b); + b = true; + QT_THROW(std::bad_alloc()); //if Qt compiled without exceptions this is noop + rb.commit(); //if Qt compiled without exceptions, true is committed + } + QT_CATCH(...) + { + caught = true; + } + QCOMPARE(b, !caught); //expect false if exception was thrown, true otherwise +} + +void tst_QScopedValueRollback::earlyExitScope() +{ + int i=0; + int j=0; + while (true) { + QScopedValueRollback ri(i); + i++; + j=i; + if (i>8) break; + ri.commit(); + } + QCOMPARE(i,8); + QCOMPARE(j,9); + + for (i = 0; i < 5; i++) { + j=1; + earlyExitScope_helper(i,j); + QCOMPARE(j, 1< r(member); + member *= 2; + if (exitpoint == 0) + return; + r.commit(); + member *= 2; + if (exitpoint == 1) + return; + r.commit(); + member *= 2; + if (exitpoint == 2) + return; + r.commit(); + member *= 2; + if (exitpoint == 3) + return; + r.commit(); +} + +QTEST_MAIN(tst_QScopedValueRollback) +#include "tst_QScopedValueRollback.moc" -- cgit v0.12 From 4fb5c42ede2b33c3092d70aa3e32cf6c677bd4d8 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 17 Jan 2011 15:13:52 +0000 Subject: Fix uncaught exception crash when socket ready read signal throws When the application (in this case, an autotest) ran out of memory by calling readAll() in a slot, the exception propagated to the symbian active scheduler where it caused an assertion failure. Additionally, QAbstractSocket was left in a bad state because its member variables that guard against re-entrancy were left set. 1. Catch exceptions and convert to leaves in QAsyncSelect 2. Implement RunError function to set the socket engine error state 3. Use QScopedValueRollback in QAbstractSocket to ensure the reentrancy guards are reverted if an exception is thrown. Reviewed-by: Markus Goetz Reviewed-by: mread --- src/network/socket/qabstractsocket.cpp | 10 ++++---- src/network/socket/qsymbiansocketengine.cpp | 37 +++++++++++++++++++++++++---- src/network/socket/qsymbiansocketengine_p.h | 3 +++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index c638e2a..156b905 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -375,6 +375,7 @@ #include #include #include +#include #ifndef QT_NO_OPENSSL #include @@ -592,6 +593,7 @@ bool QAbstractSocketPrivate::canReadNotification() socketEngine->setReadNotificationEnabled(false); } } + QScopedValueRollback rsncrollback(readSocketNotifierCalled); readSocketNotifierCalled = true; if (!isBuffered) @@ -605,7 +607,6 @@ bool QAbstractSocketPrivate::canReadNotification() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full"); #endif - readSocketNotifierCalled = false; return false; } @@ -617,7 +618,6 @@ bool QAbstractSocketPrivate::canReadNotification() qDebug("QAbstractSocketPrivate::canReadNotification() disconnecting socket"); #endif q->disconnectFromHost(); - readSocketNotifierCalled = false; return false; } newBytes = readBuffer.size() - newBytes; @@ -637,9 +637,9 @@ bool QAbstractSocketPrivate::canReadNotification() ; if (!emittedReadyRead && hasData) { + QScopedValueRollback r(emittedReadyRead); emittedReadyRead = true; emit q->readyRead(); - emittedReadyRead = false; } // If we were closed as a result of the readyRead() signal, @@ -648,7 +648,6 @@ bool QAbstractSocketPrivate::canReadNotification() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification() socket is closing - returning"); #endif - readSocketNotifierCalled = false; return true; } @@ -662,7 +661,6 @@ bool QAbstractSocketPrivate::canReadNotification() socketEngine->setReadNotificationEnabled(readSocketNotifierState); readSocketNotifierStateSet = false; } - readSocketNotifierCalled = false; return true; } @@ -768,9 +766,9 @@ bool QAbstractSocketPrivate::flush() if (written > 0) { // Don't emit bytesWritten() recursively. if (!emittedBytesWritten) { + QScopedValueRollback r(emittedBytesWritten); emittedBytesWritten = true; emit q->bytesWritten(written); - emittedBytesWritten = false; } } diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 2f991de..455bf5e 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1308,6 +1308,9 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) case KErrNotSupported: setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); break; + case KErrNoMemory: + setError(QAbstractSocket::SocketResourceError, ResourceErrorString); + break; default: socketError = QAbstractSocket::NetworkError; socketErrorString = QString::number(symbianError); @@ -1564,22 +1567,47 @@ void QAsyncSelect::DoCancel() void QAsyncSelect::RunL() { + QT_TRYCATCH_LEAVING(run()); +} + +//RunError is called by the active scheduler if RunL leaves. +//Typically this will happen if a std::bad_alloc propagates down from the application +TInt QAsyncSelect::RunError(TInt aError) +{ + if (engine) { + QT_TRY { + engine->d_func()->setError(aError); + QEvent e(QEvent::SockAct); + if (iExcN) + iExcN->event(&e); + if (iReadN) + iReadN->event(&e); + } + QT_CATCH(...) {} + } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QAsyncSelect::RunError" << aError; +#endif + return KErrNone; +} + +void QAsyncSelect::run() +{ //TODO: block when event loop demands it //if (maybeQueueForLater()) // return; - m_inSocketEvent = true; m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested //TODO: KSockSelectReadContinuation does what? - if (m_selectBuf() & KSockSelectRead) { + if (iReadN && (m_selectBuf() & KSockSelectRead)) { QEvent e(QEvent::SockAct); iReadN->event(&e); } - if (m_selectBuf() & KSockSelectWrite) { + if (iWriteN && (m_selectBuf() & KSockSelectWrite)) { QEvent e(QEvent::SockAct); iWriteN->event(&e); } - if ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone) { + if (iExcN && ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone)) { QEvent e(QEvent::SockAct); iExcN->event(&e); } @@ -1598,6 +1626,7 @@ void QAsyncSelect::deleteLater() iExcN = 0; iReadN = 0; iWriteN = 0; + engine = 0; m_deleteLater = true; } else { delete this; diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index bc85f9c..f36b7dd 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -72,6 +72,7 @@ class QNetworkInterface; class Q_AUTOTEST_EXPORT QSymbianSocketEngine : public QAbstractSocketEngine { Q_OBJECT + friend class QAsyncSelect; public: QSymbianSocketEngine(QObject *parent = 0); ~QSymbianSocketEngine(); @@ -167,6 +168,8 @@ public: protected: void DoCancel(); void RunL(); + void run(); + TInt RunError(TInt aError); private: QReadNotifier* iReadN; -- cgit v0.12 From 066ba528045435519917d37c781d04cea4ca4cfc Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 17 Jan 2011 19:18:39 +0000 Subject: Test case fixes for QNetworkReply 1. Increase maximum heap, as FTP large file test was running out 2. Add an additional QVERIFY so that a test fails instead of suffering an assertion failure in case no data is received. Reviewed-by: Markus Goetz --- tests/auto/qnetworkreply/test/test.pro | 2 +- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qnetworkreply/test/test.pro b/tests/auto/qnetworkreply/test/test.pro index 7efc2fb..12fdf04 100644 --- a/tests/auto/qnetworkreply/test/test.pro +++ b/tests/auto/qnetworkreply/test/test.pro @@ -33,6 +33,6 @@ symbian:{ # Symbian toolchain does not support correct include semantics INCLUDEPATH+=..\\..\\..\\..\\include\\QtNetwork\\private # bigfile test case requires more heap - TARGET.EPOCHEAPSIZE="0x100 0x1000000" + TARGET.EPOCHEAPSIZE="0x100 0x10000000" TARGET.CAPABILITY="ALL -TCB" } diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index c796272..b1fddfa 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -5128,6 +5128,7 @@ public: void finishedSlot() { // We should have already received all readyRead + QVERIFY(!bytesAvailableList.isEmpty()); QVERIFY(bytesAvailableList.last() == uploadSize); } }; -- cgit v0.12 From 4d4bc3f3729a057e428208b4037dddb49b14b1ed Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 18 Jan 2011 14:04:05 +0000 Subject: Fix some issues with socket handle allocation QAbstractSocket requires a handle of -1 to be returned when accept fails. This is a common case, as it calls accept() in a loop to get all incoming connections. Also the blank socket wasn't being closed properly on failure so that is also fixed. Fixed a possible race condition in QSymbianSocketEngine::close - the socket descriptor is now deregistered before closing the symbian socket to avoid another thread getting the symbian handle reused in open and asserting when trying to register it. This patch also adds debug around socket handle allocation when socket engine debug is enabled. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 35 +++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 455bf5e..cf5f33e 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -208,8 +208,13 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so return false; } - +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - created" << nativeSocket.SubSessionHandle(); +#endif socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << " - allocated socket descriptor" << socketDescriptor; +#endif return true; } @@ -343,10 +348,15 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc close(); if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) { + qWarning("QSymbianSocketEngine::initialize - socket descriptor not found"); d->setError(QAbstractSocket::SocketResourceError, QSymbianSocketEnginePrivate::InvalidSocketErrorString); return false; } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::initialize - attached to" << d->nativeSocket.SubSessionHandle() << socketDescriptor; +#endif + Q_ASSERT(d->socketDescriptor == socketDescriptor || d->socketDescriptor == -1); d->socketDescriptor = socketDescriptor; // determine socket type and protocol @@ -712,16 +722,28 @@ bool QSymbianSocketEngine::listen() int QSymbianSocketEngine::accept() { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::accept(), -1); + Q_CHECK_STATE(QSymbianSocketEngine::accept(), QAbstractSocket::ListeningState, false); + Q_CHECK_TYPE(QSymbianSocketEngine::accept(), QAbstractSocket::TcpSocket, false); RSocket blankSocket; blankSocket.Open(d->socketServer); TRequestStatus status; d->nativeSocket.Accept(blankSocket, status); User::WaitForRequest(status); if (status.Int()) { + blankSocket.Close(); qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); - return 0; + return -1; } - return QSymbianSocketManager::instance().addSocket(blankSocket); + +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::accept - created" << blankSocket.SubSessionHandle(); +#endif + int fd = QSymbianSocketManager::instance().addSocket(blankSocket); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << " - allocated socket descriptor" << fd; +#endif + return fd; } qint64 QSymbianSocketEngine::bytesAvailable() const @@ -930,8 +952,13 @@ void QSymbianSocketEngine::close() d->nativeSocket.Shutdown(RSocket::EImmediate, stat); User::WaitForRequest(stat); } - d->nativeSocket.Close(); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::close - closing socket" << d->nativeSocket.SubSessionHandle() << d->socketDescriptor; +#endif + //remove must come before close to avoid a race where another thread gets the old subsession handle + //reused & asserts when calling QSymbianSocketManager::instance->addSocket QSymbianSocketManager::instance().removeSocket(d->nativeSocket); + d->nativeSocket.Close(); d->socketDescriptor = -1; d->socketState = QAbstractSocket::UnconnectedState; -- cgit v0.12 From 9832c60375a9689e42cd899d1de5afd0b776ae48 Mon Sep 17 00:00:00 2001 From: Aaron Tunney Date: Wed, 19 Jan 2011 16:36:46 +0000 Subject: Initial draft of QHostInfo::localHostName(), plus fix for address buffer for IPv6 addresses. Reviewed-by: Shane Kearns --- src/network/kernel/qhostinfo_symbian.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index fbd7fe9..7fc40bc 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -143,7 +143,9 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QList hostAddresses; TInetAddr hostAdd = nameResult().iAddr; - TBuf<16> ipAddr; + // 39 is the maximum length of an IPv6 address. + TBuf<39> ipAddr; + // Fill ipAddr with the IP address from hostAdd hostAdd.Output(ipAddr); if (ipAddr.Length() > 0) @@ -173,8 +175,24 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QString QHostInfo::localHostName() { - // TODO - fill with code. - return QString(); + // Connect to ESOCK + RSocketServ socketServ(qt_symbianGetSocketServer()); + RHostResolver hostResolver; + + // Will return both IPv4 and IPv6 + // TODO: Pass RHostResolver.Open() the global RConnection + int err = hostResolver.Open(socketServ, KAfInet, KProtocolInetUdp); + if (err) + return QString(); + + THostName hostName; + err = hostResolver.GetHostName(hostName); + if (err) + return QString(); + + hostResolver.Close(); + + return qt_TDesC2QString(hostName); } QString QHostInfo::localDomainName() -- cgit v0.12 From 6886c21e0743fdfb1e5d053e0e193aeeed5fe8b2 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 21 Jan 2011 14:49:01 +0000 Subject: Fix error connecting to IPv6 addresses Incorrect usage of KAfInet6 in the symbian socket engine. KAfInet is used for both IPv4 and IPv6 as a protocol family. KAfInet6 is used as the address family for IPv6 addresses. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index cf5f33e..9ed8a42 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -179,7 +179,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so QAbstractSocket::NetworkLayerProtocol socketProtocol) { Q_Q(QSymbianSocketEngine); - TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet; + TUint family = KAfInet; // KAfInet6 is only used as an address family, not as a protocol family TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; TInt err; -- cgit v0.12 From a2ba4ccd2c2d3daf2a4d719295c59395f03aba0b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 21 Jan 2011 14:51:45 +0000 Subject: Fix crashes in httpProxyCommandsSynchronous test case Due to a race condition, the test could fail before its QThread had even started, resulting in a crash during thread startup. This is addressed using a semaphore to synchronise startup & ensure the sub thread is running before continuing the test. Additionally, if the test failed the QThread would be destroyed while still running, which according to the documentation will cause crashes. This is addressed using QScopedPointer to clean up when the test exits early due to failure. Reviewed-by: Markus Goetz --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 47 +++++++++++++++++++++----- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index b1fddfa..390d5bf 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -410,16 +411,23 @@ public: QTcpSocket *client; // always the last one that was received QByteArray dataToTransmit; QByteArray receivedData; + QSemaphore ready; bool doClose; bool doSsl; bool multiple; int totalConnections; - MiniHttpServer(const QByteArray &data, bool ssl = false) + MiniHttpServer(const QByteArray &data, bool ssl = false, QThread *thread = 0) : client(0), dataToTransmit(data), doClose(true), doSsl(ssl), multiple(false), totalConnections(0) { listen(); + if (thread) { + connect(thread, SIGNAL(started()), this, SLOT(threadStartedSlot())); + moveToThread(thread); + thread->start(); + ready.acquire(); + } } protected: @@ -492,6 +500,11 @@ public slots: } } } + + void threadStartedSlot() + { + ready.release(); + } }; class MyCookieJar: public QNetworkCookieJar @@ -4478,6 +4491,26 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous_data() httpProxyCommands_data(); } +struct QThreadCleanup +{ + static inline void cleanup(QThread *thread) + { + thread->quit(); + if (thread->wait(3000)) + delete thread; + else + qWarning("thread hung, leaking memory so test can finish"); + } +}; + +struct QDeleteLaterCleanup +{ + static inline void cleanup(QObject *o) + { + o->deleteLater(); + } +}; + void tst_QNetworkReply::httpProxyCommandsSynchronous() { QFETCH(QUrl, url); @@ -4487,11 +4520,9 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() // when using synchronous commands, we need a different event loop for // the server thread, because the client is never returning to the // event loop - MiniHttpServer proxyServer(responseToSend); - QThread serverThread; - proxyServer.moveToThread(&serverThread); - serverThread.start(); - QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer.serverPort()); + QScopedPointer serverThread(new QThread); + QScopedPointer proxyServer(new MiniHttpServer(responseToSend, false, serverThread.data())); + QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer->serverPort()); manager.setProxy(proxy); QNetworkRequest request(url); @@ -4504,8 +4535,6 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() QNetworkReplyPtr reply = manager.get(request); QVERIFY(reply->isFinished()); // synchronous manager.setProxy(QNetworkProxy()); - serverThread.quit(); - serverThread.wait(3000); //qDebug() << reply->error() << reply->errorString(); @@ -4513,7 +4542,7 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() // especially since it won't succeed in the HTTPS case // so just check that the command was correct - QString receivedHeader = proxyServer.receivedData.left(expectedCommand.length()); + QString receivedHeader = proxyServer->receivedData.left(expectedCommand.length()); QCOMPARE(receivedHeader, expectedCommand); } -- cgit v0.12 From 47ac9016fc778f10f4d5ab1abb056b0d0cc2963a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 21 Jan 2011 14:56:27 +0000 Subject: Use the global message pool to avoid KErrServerBusy errors Symbian IPC has two modes, either a preallocated message pool for the process (up to 255 allowed), or the global message pool. The default for the socket server is 8 preallocated slots, which is not enough to run the qnetworkreply autotest. However preallocating a large number of slots would be wasteful for an application that only uses one or two sockets at a time. Since we can't predict the usage, the global pool seems the best option. Reviewed-by: Iain --- src/corelib/kernel/qcore_symbian_p.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index fdae31b..45e07ad 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -223,7 +223,9 @@ QSymbianSocketManager::QSymbianSocketManager() : // ### In future this could be changed to KAfInet6 when that is more common than IPv4 preferences.iAddrFamily = KAfInet; preferences.iProtocol = KProtocolInetIp; - qt_symbian_throwIfError(iSocketServ.Connect(preferences)); + //use global message pool, as we do not know how many sockets app will use + //TODO: is this the right choice? + qt_symbian_throwIfError(iSocketServ.Connect(preferences, -1)); qt_symbian_throwIfError(iSocketServ.ShareAuto()); } -- cgit v0.12 From b10fe4c9efa0767c9591fa19c86ff7e5c3f88860 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 21 Jan 2011 15:08:15 +0000 Subject: Fix IPv6 server connections Symbian treats listening on "0.0.0.0" to mean "accept any IPv4" and listening on "::" to mean "accept any IPv6". To accept any connection, you must listen with an unspecified address As the Qt documentation explicitly says QHostAddress::Any means to accept any connection, this is converted to an unspecified address (KAfUnspec) by the symbian socket engine. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 9ed8a42..cc55f2a 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -221,7 +221,12 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) { nativeAddr.SetPort(port); - if (addr.protocol() == QAbstractSocket::IPv6Protocol) { + if (addr == QHostAddress::Any) { + //Should allow both IPv4 and IPv6 + //Listening on "0.0.0.0" accepts ONLY ipv4 connections + //Listening on "::" accepts ONLY ipv6 connections + nativeAddr.SetFamily(KAFUnspec); + } else if (addr.protocol() == QAbstractSocket::IPv6Protocol) { TPckgBuf query; query().iName = qt_QString2TPtrC(addr.scopeId()); TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); -- cgit v0.12 From b81b429cb43e19b2211990d0aab80e78e08d87f7 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 21 Jan 2011 15:46:01 +0000 Subject: Implement moveToThread in the symbian socket engine The active object used for socket notifications (QAsyncSelect) is thread specific, so it needs to be deleted and recreated in the new thread. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 44 +++++++++++++++++++++++++++-- src/network/socket/qsymbiansocketengine_p.h | 4 +++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index cc55f2a..487f45c 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -59,6 +59,8 @@ # include "qtcpserver.h" #endif +#include + #include #include #include @@ -1576,6 +1578,41 @@ qint64 QSymbianSocketEngine::bytesToWrite() const return 0; } +//TODO: is defining PostThreadChangeEvent as QEvent::User + 1 safe? +//TODO: would QMetaObject::invokeMethod(obj, "postThreadChangeSlot", Qt::QueuedConnection) be better? +//TODO: if QTBUG-16787 is implemented, use that instead +bool QSymbianSocketEngine::event(QEvent* ev) +{ + Q_D(QSymbianSocketEngine); + switch (ev->type()) { + case QEvent::ThreadChange: + if (d->asyncSelect) { + delete d->asyncSelect; + d->asyncSelect = 0; + QEvent *postThreadChangeEvent = new QEvent(PostThreadChangeEvent); + QCoreApplication::postEvent(this, postThreadChangeEvent); + } + return true; + case PostThreadChangeEvent: + // recreate select in new thread + d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); + if (d->readNotifier) { + d->asyncSelect->setReadNotifier(static_cast(d->readNotifier)); + setReadNotificationEnabled(d->readNotifier->isEnabled()); + } + if (d->writeNotifier) { + d->asyncSelect->setWriteNotifier(static_cast(d->writeNotifier)); + setReadNotificationEnabled(d->writeNotifier->isEnabled()); + } + if (d->exceptNotifier) { + d->asyncSelect->setExceptionNotifier(static_cast(d->exceptNotifier)); + setReadNotificationEnabled(d->exceptNotifier->isEnabled()); + } + return true; + } + return QAbstractSocketEngine::event(ev); +} + QAsyncSelect::QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent) : CActive(CActive::EPriorityStandard), m_inSocketEvent(false), @@ -1631,11 +1668,11 @@ void QAsyncSelect::run() m_inSocketEvent = true; m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested //TODO: KSockSelectReadContinuation does what? - if (iReadN && (m_selectBuf() & KSockSelectRead)) { + if (iReadN && ((m_selectBuf() & KSockSelectRead) || iStatus != KErrNone)) { QEvent e(QEvent::SockAct); iReadN->event(&e); } - if (iWriteN && (m_selectBuf() & KSockSelectWrite)) { + if (iWriteN && ((m_selectBuf() & KSockSelectWrite) || iStatus != KErrNone)) { QEvent e(QEvent::SockAct); iWriteN->event(&e); } @@ -1681,7 +1718,8 @@ void QAsyncSelect::IssueRequest() m_selectFlags = selectFlags; } if (m_selectFlags && !IsActive()) { - m_selectBuf() = m_selectFlags; + //always request errors (write notification does not complete on connect errors) + m_selectBuf() = m_selectFlags | KSockSelectExcept; m_socket.Ioctl(KIOctlSelect, iStatus, &m_selectBuf, KSOLSocket); SetActive(); } diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index f36b7dd..8a0b8df 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -135,6 +135,10 @@ public: bool isExceptionNotificationEnabled() const; void setExceptionNotificationEnabled(bool enable); + bool event(QEvent* ev); + + static const QEvent::Type PostThreadChangeEvent = (QEvent::Type)(QEvent::User + 1); + public Q_SLOTS: // TODO: Why do we do this? This is private Qt implementation stuff anyway, no need for it // non-virtual override; -- cgit v0.12 From 640152ac8057f026451da814419511cf04446eca Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 24 Jan 2011 11:58:33 +0000 Subject: Fix deprecated cast from ascii warning Reviewed-by: Aaron Tunney --- src/network/kernel/qhostinfo_symbian.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 7fc40bc..9599274 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -126,7 +126,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // the IPv6 addresses at the end of the address list in results. // Synchronous request. - err = hostResolver.GetByName(qt_QString2TPtrC(aceHostname), nameResult); + err = hostResolver.GetByName(qt_QString2TPtrC(QString::fromLatin1(aceHostname)), nameResult); if (err) { // TODO - Could there be other errors? Symbian docs don't say. if (err = KErrNotFound) { -- cgit v0.12 From 5f41f2b4bbe3f4d3f7e2ccb6c14273c5a308b837 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 25 Jan 2011 10:43:45 +0000 Subject: qnetworkreply test stability on symbian The first few tests could randomly timeout due to delays in starting the WLAN connection. This is addressed by opening the default bearer in initTestCase, and closing it in cleanupTestCase. This will keep the connection active for the duration of the test, instead of activating/deactivating continuously. The first SSL test could randomly timeout due to the delay in fetching the CA certificates from the system (which can be very slow on some phones / SIM cards). This is addressed by preloading them in initTestCase - all the tests will then get system SSL certs from the cache. Reviewed-by: Markus Goetz --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 390d5bf..3e07176 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -65,6 +65,11 @@ #include #include #endif +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif #include @@ -136,6 +141,11 @@ class tst_QNetworkReply: public QObject QSslConfiguration storedSslConfiguration; QList storedExpectedSslErrors; #endif +#ifndef QT_NO_BEARER_MANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif public: tst_QNetworkReply(); @@ -1140,6 +1150,18 @@ void tst_QNetworkReply::initTestCase() #endif QDir::setSearchPaths("srcdir", QStringList() << SRCDIR); +#ifndef QT_NO_OPENSSL + QSslSocket::defaultCaCertificates(); //preload certificates +#endif +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif } void tst_QNetworkReply::cleanupTestCase() @@ -1147,6 +1169,9 @@ void tst_QNetworkReply::cleanupTestCase() #if !defined Q_OS_WIN QFile::remove(wronlyFileName); #endif + if (networkSession && networkSession->isOpen()) { + networkSession->close(); + } } void tst_QNetworkReply::init() -- cgit v0.12 From 00553adc2ab5c38f1870b036d4bec881acb77511 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 25 Jan 2011 13:18:23 +0000 Subject: Fix some qnetworkreply test cases for symbian The unreachable IP test needs a longer timeout than on desktops. The manual construction of a file:// URL was incorrect in the case where SRCDIR is "." - this is changed to the recommended QUrl::fromLocalFile API. Reviewed-by: Markus Goetz --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 3e07176..71a8352 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -5302,7 +5302,7 @@ void tst_QNetworkReply::getFromUnreachableIp() QNetworkReplyPtr reply = manager.get(request); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - QTestEventLoop::instance().enterLoop(5); + QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(reply->error() != QNetworkReply::NoError); @@ -5469,7 +5469,7 @@ void tst_QNetworkReply::synchronousRequest_data() << QString("text/plain"); QTest::newRow("simple-file") - << QUrl(QString::fromLatin1("file:///" SRCDIR "/rfc3252.txt")) + << QUrl::fromLocalFile(SRCDIR "/rfc3252.txt") << QString("file:" SRCDIR "/rfc3252.txt") << true << QString(); -- cgit v0.12 From b36097693f9be745e8da550ea872fd1cda8d7d3a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 25 Jan 2011 13:30:58 +0000 Subject: Handle KErrBadName when connecting to broadcast address Symbian uses KErrBadName to indicate a badly formed socket address. It also returns this error if the address is invalid for the attempted operation, for example calling connect() with a broadcast address. Now handle this error explicitly rather than returning unknown error. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 7 +++++++ src/network/socket/qsymbiansocketengine_p.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 487f45c..8ded9ac 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -626,6 +626,10 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) d->setError(QAbstractSocket::SocketAccessError, d->AccessErrorString); d->socketState = QAbstractSocket::UnconnectedState; break; + case KErrBadName: + d->setError(QAbstractSocket::NetworkError, d->InvalidAddressError); + d->socketState = QAbstractSocket::UnconnectedState; + break; case KErrNotSupported: case KErrBadDescriptor: default: @@ -1306,6 +1310,9 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E case InvalidProxyTypeString: socketErrorString = QSymbianSocketEngine::tr("The proxy type is invalid for this operation"); break; + case InvalidAddressError: + socketErrorString = QSymbianSocketEngine::tr("The address is invalid for this operation"); + break; case UnknownSocketErrorString: socketErrorString = QSymbianSocketEngine::tr("Unknown error"); break; diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 8a0b8df..fb64dba 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -233,6 +233,8 @@ public: PortInuseErrorString, NotSocketErrorString, InvalidProxyTypeString, + //symbian specific + InvalidAddressError, UnknownSocketErrorString = -1 }; -- cgit v0.12 From 54692812331d24939a0263a1625702670503c17a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 25 Jan 2011 13:37:45 +0000 Subject: Suppress warning for an expected error QTcpServer calls accept repeatedly until it fails. So the KErrWouldBlock is an expected error - ignore this so warnings are only emitted for unexpected errors. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 8ded9ac..bee034e 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -743,7 +743,8 @@ int QSymbianSocketEngine::accept() User::WaitForRequest(status); if (status.Int()) { blankSocket.Close(); - qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); + if (status != KErrWouldBlock) + qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); return -1; } -- cgit v0.12 From cdc4ce0acde93b23c7e4941b5c195a8d23ff6900 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 5 Jan 2011 11:07:56 +0000 Subject: Workaround crash when multiple QNetworkAccessManager instances are used Instead of each QNetworkAccessManager owning a QNetworkSession, they now share a QNetworkSession if they have the same QNetworkConfiguration. QNetworkAccessManager now uses passive roaming instead of application level roaming. The state change signal (entering connected state) is used to indicate reconnection instead of being triggered when sending an ALR accept(). This preserves the previous behaviour, as QNAM always accepted the suggested access point from bearer mobility. In the case of multithreaded applications, one QNetworkSession will be created for each thread which uses QNetworkAccessManager, as QNetworkSession is not thread safe. Task-number: QT-4378 Reviewed-by: Markus Goetz Reviewed-by: juhvu --- src/network/access/qnetworkaccessmanager.cpp | 42 +++---------- src/network/access/qnetworkaccessmanager.h | 2 - src/network/access/qnetworkaccessmanager_p.h | 2 +- src/network/access/qnetworkreplyimpl.cpp | 6 +- src/network/bearer/bearer.pri | 6 +- src/network/bearer/qsharednetworksession.cpp | 90 ++++++++++++++++++++++++++++ src/network/bearer/qsharednetworksession_p.h | 81 +++++++++++++++++++++++++ 7 files changed, 188 insertions(+), 41 deletions(-) create mode 100644 src/network/bearer/qsharednetworksession.cpp create mode 100644 src/network/bearer/qsharednetworksession_p.h diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index bec217b..94ce3bc 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -48,6 +48,7 @@ #include "qabstractnetworkcache.h" #include "QtNetwork/qnetworksession.h" +#include "qsharednetworksession_p.h" #include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessftpbackend_p.h" @@ -1343,11 +1344,8 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co initializeSession = false; - if (networkSession) - delete networkSession; - if (!config.isValid()) { - networkSession = 0; + networkSession.clear(); online = false; if (networkAccessible == QNetworkAccessManager::NotAccessible) @@ -1358,18 +1356,12 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co return; } - networkSession = new QNetworkSession(config, q); + networkSession = QSharedNetworkSessionManager::getSession(config); - QObject::connect(networkSession, SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); - QObject::connect(networkSession, SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); - QObject::connect(networkSession, SIGNAL(stateChanged(QNetworkSession::State)), + QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); + QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); - QObject::connect(networkSession, SIGNAL(newConfigurationActivated()), - q, SLOT(_q_networkSessionNewConfigurationActivated())); - QObject::connect(networkSession, - SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)), - q, - SLOT(_q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool))); _q_networkSessionStateChanged(networkSession->state()); } @@ -1379,32 +1371,16 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed() if (networkSession) { networkConfiguration = networkSession->configuration().identifier(); - networkSession->deleteLater(); - networkSession = 0; - } -} - -void QNetworkAccessManagerPrivate::_q_networkSessionNewConfigurationActivated() -{ - Q_Q(QNetworkAccessManager); - - if (networkSession) { - networkSession->accept(); - - emit q->networkSessionConnected(); + networkSession.clear(); } } -void QNetworkAccessManagerPrivate::_q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &, bool) -{ - if (networkSession) - networkSession->migrate(); -} - void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state) { Q_Q(QNetworkAccessManager); + if (state == QNetworkSession::Connected) + emit q->networkSessionConnected(); if (online) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { online = false; diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 95e45f0..9c551a7 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -161,8 +161,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList)) #if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) - Q_PRIVATE_SLOT(d_func(), void _q_networkSessionNewConfigurationActivated()) - Q_PRIVATE_SLOT(d_func(), void _q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) #endif }; diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 2c6ee10..cdc4b3d 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -128,7 +128,7 @@ public: #endif #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *networkSession; + QSharedPointer networkSession; QString networkConfiguration; QNetworkAccessManager::NetworkAccessibility networkAccessible; bool online; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 70c318c..373cb22 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -97,7 +97,7 @@ void QNetworkReplyImplPrivate::_q_startOperation() // state changes. state = WaitingForSession; - QNetworkSession *session = manager->d_func()->networkSession; + QNetworkSession *session = manager->d_func()->networkSession.data(); if (session) { Q_Q(QNetworkReplyImpl); @@ -257,7 +257,7 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() if (manager.isNull()) return; - QNetworkSession *session = manager->d_func()->networkSession; + QNetworkSession *session = manager->d_func()->networkSession.data(); if (!session) return; @@ -693,7 +693,7 @@ void QNetworkReplyImplPrivate::finished() if (!manager.isNull()) { #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *session = manager->d_func()->networkSession; + QNetworkSession *session = manager->d_func()->networkSession.data(); if (session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error diff --git a/src/network/bearer/bearer.pri b/src/network/bearer/bearer.pri index bc5b0b5..d58d5ec 100644 --- a/src/network/bearer/bearer.pri +++ b/src/network/bearer/bearer.pri @@ -7,11 +7,13 @@ HEADERS += bearer/qnetworkconfiguration.h \ bearer/qnetworkconfiguration_p.h \ bearer/qnetworksession_p.h \ bearer/qbearerengine_p.h \ - bearer/qbearerplugin_p.h + bearer/qbearerplugin_p.h \ + bearer/qsharednetworksession_p.h SOURCES += bearer/qnetworksession.cpp \ bearer/qnetworkconfigmanager.cpp \ bearer/qnetworkconfiguration.cpp \ bearer/qnetworkconfigmanager_p.cpp \ bearer/qbearerengine.cpp \ - bearer/qbearerplugin.cpp + bearer/qbearerplugin.cpp \ + bearer/qsharednetworksession.cpp diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp new file mode 100644 index 0000000..51b3a32 --- /dev/null +++ b/src/network/bearer/qsharednetworksession.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsharednetworksession_p.h" +#include "qbearerengine_p.h" +#include + +#ifndef QT_NO_BEARERMANAGEMENT + +QT_BEGIN_NAMESPACE + +QThreadStorage tls; + +inline QSharedNetworkSessionManager* sharedNetworkSessionManager() +{ + QSharedNetworkSessionManager* rv = tls.localData(); + if (!rv) { + rv = new QSharedNetworkSessionManager; + tls.setLocalData(rv); + } + return rv; +} + +QSharedPointer QSharedNetworkSessionManager::getSession(QNetworkConfiguration config) +{ + QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); + //if already have a session, return it + if (m->sessions.contains(config)) { + QSharedPointer p = m->sessions.value(config).toStrongRef(); + if (!p.isNull()) + return p; + } + //otherwise make one + QSharedPointer session(new QNetworkSession(config)); + m->sessions[config] = session; + return session; +} + +void QSharedNetworkSessionManager::setSession(QNetworkConfiguration config, QSharedPointer session) +{ + QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); + m->sessions[config] = session; +} + +uint qHash(const QNetworkConfiguration& config) +{ + return ((uint)config.type()) | (((uint)config.bearerType()) << 8) | (((uint)config.purpose()) << 16); +} + +QT_END_NAMESPACE + +#endif // QT_NO_BEARERMANAGEMENT diff --git a/src/network/bearer/qsharednetworksession_p.h b/src/network/bearer/qsharednetworksession_p.h new file mode 100644 index 0000000..dc84166 --- /dev/null +++ b/src/network/bearer/qsharednetworksession_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSHAREDNETWORKSESSIONPRIVATE_H +#define QSHAREDNETWORKSESSIONPRIVATE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qnetworksession.h" +#include "qnetworkconfiguration.h" +#include +#include +#include +#include + +#ifndef QT_NO_BEARERMANAGEMENT + +QT_BEGIN_NAMESPACE + +class QSharedNetworkSessionManager +{ +public: + static QSharedPointer getSession(QNetworkConfiguration config); + static void setSession(QNetworkConfiguration config, QSharedPointer session); +private: + QHash > sessions; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_BEARERMANAGEMENT + +#endif //QSHAREDNETWORKSESSIONPRIVATE_H + -- cgit v0.12 From c546754be723c35a61a8aa5df066aa8dce053d56 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 17 Jan 2011 12:44:06 +0000 Subject: Fix header not found build error Task-Number: QT-4378 --- src/network/access/qnetworkaccessmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 94ce3bc..7d37375 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -48,7 +48,7 @@ #include "qabstractnetworkcache.h" #include "QtNetwork/qnetworksession.h" -#include "qsharednetworksession_p.h" +#include "QtNetwork/private/qsharednetworksession_p.h" #include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessftpbackend_p.h" -- cgit v0.12 From 07416116e30ec526506c6f2c97be4499b898dda0 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 27 Jan 2011 14:28:46 +0000 Subject: Fix for QNetworkSession::waitForOpened failing on active connection When opening an active session, waitForOpened was failing because the state was Connected rather than Connecting. This is fixed to allow Connected as a state. Reviewed-by: Markus Goetz --- src/network/bearer/qnetworksession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index eac0456..41a8854 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -310,7 +310,7 @@ bool QNetworkSession::waitForOpened(int msecs) if (d->isOpen) return true; - if (d->state != Connecting) + if (d->state != Connecting && d->state != Connected) //state is connected when opening an already active interface return false; QEventLoop loop; -- cgit v0.12 From 85ee65df53ddece16b9d51fae0de1dd36564564a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 28 Jan 2011 17:38:56 +0000 Subject: Fix compile errors when TCP local sockets configured on symbian Reviewed-by: Markus Goetz --- src/network/socket/qlocalserver.cpp | 2 +- src/network/socket/qlocalsocket.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index ef7fc02..6d8b889 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -274,11 +274,11 @@ QLocalSocket *QLocalServer::nextPendingConnection() if (d->pendingConnections.isEmpty()) return 0; QLocalSocket *nextSocket = d->pendingConnections.dequeue(); +#ifndef QT_LOCALSOCKET_TCP #ifdef Q_OS_SYMBIAN if(!d->socketNotifier) return nextSocket; #endif -#ifndef QT_LOCALSOCKET_TCP if (d->pendingConnections.size() <= d->maxPendingConnections) #ifndef Q_OS_WIN d->socketNotifier->setEnabled(true); diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp index 2eb1700..aa11d05 100644 --- a/src/network/socket/qlocalsocket.cpp +++ b/src/network/socket/qlocalsocket.cpp @@ -346,7 +346,7 @@ QLocalSocket::QLocalSocket(QObject * parent) QLocalSocket::~QLocalSocket() { close(); -#ifndef Q_OS_WIN +#if !defined (Q_OS_WIN) && !defined (QT_LOCALSOCKET_TCP) Q_D(QLocalSocket); d->unixSocket.setParent(0); #endif -- cgit v0.12 From 2ff5c6adbca65405d0a760173e5128b98d5d4a40 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 28 Jan 2011 17:39:57 +0000 Subject: Enable QT_LOCALSOCKET_TCP for symbian Reviewed-by: Markus Goetz --- src/network/socket/socket.pri | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index 3eb54a2..32be429 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -30,11 +30,19 @@ symbian:HEADERS += socket/qsymbiansocketengine_p.h !symbian:SOURCES += socket/qnativesocketengine.cpp !symbian:HEADERS += socket/qnativesocketengine_p.h -unix:!symbian:SOURCES += socket/qnativesocketengine_unix.cpp - -unix:SOURCES += \ +unix:!symbian: { + SOURCES += socket/qnativesocketengine_unix.cpp \ socket/qlocalsocket_unix.cpp \ socket/qlocalserver_unix.cpp +} + +symbian: { + SOURCES += socket/qlocalsocket_tcp.cpp \ + socket/qlocalserver_tcp.cpp + + DEFINES += QT_LOCALSOCKET_TCP +} + unix:HEADERS += \ socket/qnet_unix_p.h -- cgit v0.12 From c8a1b65ab2491886ac37a1726b3728e549d505a7 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 28 Jan 2011 18:45:15 +0000 Subject: Implement multicast functions Reviewed-by: Aaron Tunney Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 112 ++++++++++++++++------------ src/network/socket/qsymbiansocketengine_p.h | 5 ++ 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index bee034e..6825374 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -436,40 +436,14 @@ bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, in if (!isValid()) return false; - int n = 0; - int level = SOL_SOCKET; // default + TUint n = 0; + TUint level = KSOLSocket; // default - switch (opt) { - case QAbstractSocketEngine::ReceiveBufferSocketOption: - n = KSORecvBuf; - break; - case QAbstractSocketEngine::SendBufferSocketOption: - n = KSOSendBuf; - break; - case QAbstractSocketEngine::BroadcastSocketOption: - return true; - case QAbstractSocketEngine::NonBlockingSocketOption: - n = KSONonBlockingIO; - break; - case QAbstractSocketEngine::AddressReusable: - level = KSolInetIp; - n = KSoReuseAddr; - break; - case QAbstractSocketEngine::BindExclusively: + if (!QSymbianSocketEnginePrivate::translateSocketOption(opt, n, level)) + return false; + + if (!level && !n) return true; - case QAbstractSocketEngine::ReceiveOutOfBandData: - level = KSolInetTcp; - n = KSoTcpOobInline; - break; - case QAbstractSocketEngine::LowDelayOption: - level = KSolInetTcp; - n = KSoTcpNoDelay; - break; - case QAbstractSocketEngine::KeepAliveOption: - level = KSolInetTcp; - n = KSoTcpKeepAlive; - break; - } return (KErrNone == d->nativeSocket.SetOpt(n, level, v)); } @@ -486,6 +460,24 @@ int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const TUint n; TUint level = KSOLSocket; // default + if (!QSymbianSocketEnginePrivate::translateSocketOption(opt, n, level)) + return false; + + if (!level && !n) + return 1; + + int v = -1; + //GetOpt() is non const + TInt err = d->nativeSocket.GetOpt(n, level, v); + if (!err) + return v; + + return -1; +} + +bool QSymbianSocketEnginePrivate::translateSocketOption(QAbstractSocketEngine::SocketOption opt, TUint &n, TUint &level) +{ + switch (opt) { case QAbstractSocketEngine::ReceiveBufferSocketOption: n = KSORecvBuf; @@ -496,13 +488,14 @@ int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const case QAbstractSocketEngine::NonBlockingSocketOption: n = KSONonBlockingIO; break; - case QAbstractSocketEngine::BroadcastSocketOption: - return true; //symbian doesn't support or require this option case QAbstractSocketEngine::AddressReusable: level = KSolInetIp; n = KSoReuseAddr; break; + case QAbstractSocketEngine::BroadcastSocketOption: case QAbstractSocketEngine::BindExclusively: + level = 0; + n = 0; return true; case QAbstractSocketEngine::ReceiveOutOfBandData: level = KSolInetTcp; @@ -516,17 +509,18 @@ int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const level = KSolInetTcp; n = KSoTcpKeepAlive; break; + case QAbstractSocketEngine::MulticastLoopbackOption: + level = KSolInetIp; + n = KSoIp6MulticastLoop; + break; + case QAbstractSocketEngine::MulticastTtlOption: + level = KSolInetIp; + n = KSoIp6MulticastHops; + break; default: - return -1; + return false; } - - int v = -1; - //GetOpt() is non const - TInt err = d->nativeSocket.GetOpt(n, level, v); - if (!err) - return v; - - return -1; + return true; } qint64 QSymbianSocketEngine::receiveBufferSize() const @@ -1156,15 +1150,37 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool bool QSymbianSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { - //TODO - return false; + Q_D(QSymbianSocketEngine); + return d->multicastGroupMembershipHelper(groupAddress, iface, KSoIp6JoinGroup); } bool QSymbianSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { - //TODO - return false; + Q_D(QSymbianSocketEngine); + return d->multicastGroupMembershipHelper(groupAddress, iface, KSoIp6LeaveGroup); +} + +bool QSymbianSocketEnginePrivate::multicastGroupMembershipHelper(const QHostAddress &groupAddress, + const QNetworkInterface &iface, + TUint operation) +{ + //TODO - untested + //translate address + TPckgBuf option; + Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); + memcpy(option().iAddr.u.iAddr8, ip6.c, 16); + //translate interface + //TODO - can we just use iface.index() ? + TPckgBuf query; + query().iName = qt_QString2TPtrC(iface.name()); + TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); + if (err == KErrNone) + option().iInterface = query().iIndex; + else + option().iInterface = 0; + //join or leave group + return (KErrNone == nativeSocket.SetOpt(operation, KSolInetIp, option)); } QNetworkInterface QSymbianSocketEngine::multicastInterface() const @@ -1175,7 +1191,7 @@ QNetworkInterface QSymbianSocketEngine::multicastInterface() const bool QSymbianSocketEngine::setMulticastInterface(const QNetworkInterface &iface) { - //TODO + //TODO - this is possibly a unix'ism as the RConnection on which the socket was created is probably controlling this return false; } diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index fb64dba..df93fe6 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -254,6 +254,11 @@ public: bool checkProxy(const QHostAddress &address); bool fetchConnectionParameters(); + + bool multicastGroupMembershipHelper(const QHostAddress &groupAddress, + const QNetworkInterface &iface, + TUint operation); + static bool translateSocketOption(QAbstractSocketEngine::SocketOption opt, TUint &n, TUint &level); }; QT_END_NAMESPACE -- cgit v0.12 From c466df7e67b1af663be73fca94bb1f2951ba7371 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 31 Jan 2011 18:35:01 +0000 Subject: Fix for pendingDatagramSize() in symbian socket engine The low level socket option returns the size including IP headers, as there is an option in receive to include headers in the datagram. This is OK for a "size will not exceed" metric for buffer allocation, but Qt relies on it being an accurate size. Open C did this by subtracting 28, but that isn't valid for IPv6 which has a 40 byte header. (we can't tell whether the buffered datagram was received over IPv4 or IPv6) To fix this, do a read with the peek option set, and only care about the size. In future it would be good to not peek, but rather return this buffer to a following call to readDatagram. Reviewed-by: Aaron Tunney --- src/network/socket/qsymbiansocketengine.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 6825374..f2c7b20 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -788,6 +788,20 @@ qint64 QSymbianSocketEngine::pendingDatagramSize() const Q_D(const QSymbianSocketEngine); int nbytes; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); + if (nbytes > 0) { + //nbytes includes IP header, which is of variable length (IPv4 with or without options, IPv6...) + QByteArray next(nbytes,0); + TPtr8 buffer((TUint8*)next.data(), next.size()); + TInetAddr addr; + TRequestStatus status; + //TODO: rather than peek, should we save this for next call to readDatagram? + //what if calls don't match though? + d->nativeSocket.RecvFrom(buffer, addr, KSockReadPeek, status); + User::WaitForRequest(status); + if (status.Int()) + return 0; + return buffer.Length(); + } return qint64(nbytes); } -- cgit v0.12 From f60ed3a2da4889cce6afbb059773a6c070929bb6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 31 Jan 2011 18:50:13 +0000 Subject: Fix low level broadcast test on symbian Broadcast and multicast are optional features for network interfaces on Symbian. WLAN supports both, while IPv4 and IPv6 loopback support only multicast. The test tries to start the bearer, to get an interface that does support broadcast. There is an expect fail for the 0 bytes written case, as this is what happens on symbian if none of the interfaces support broadcast. On the phones which don't have WLAN, this is likely. Reviewed-by: Markus Goetz --- .../tst_platformsocketengine.cpp | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp index 2fb3724..fa21ed8 100644 --- a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -63,6 +63,10 @@ #include #ifdef Q_OS_SYMBIAN +#include +#include +#include +#include #define PLATFORMSOCKETENGINE QSymbianSocketEngine #include #include @@ -310,6 +314,20 @@ void tst_PlatformSocketEngine::udpIPv6LoopbackTest() //--------------------------------------------------------------------------- void tst_PlatformSocketEngine::broadcastTest() { +#ifdef Q_OS_SYMBIAN + //broadcast isn't supported on loopback connections, but is on WLAN +#ifndef QT_NO_BEARERMANAGEMENT + QScopedPointer netConfMan(new QNetworkConfigurationManager()); + QNetworkConfiguration networkConfiguration(netConfMan->defaultConfiguration()); + QScopedPointer networkSession(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + bool ok = networkSession->waitForOpened(30000); + qDebug() << networkSession->isOpen() << networkSession->error() << networkSession->errorString(); + QVERIFY(ok); + } +#endif +#endif #ifdef Q_OS_AIX QSKIP("Broadcast does not work on darko", SkipAll); #endif @@ -327,10 +345,18 @@ void tst_PlatformSocketEngine::broadcastTest() // Broadcast an inappropriate troll message QByteArray trollMessage = "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH."; - QVERIFY(broadcastSocket.writeDatagram(trollMessage.data(), + qint64 written = broadcastSocket.writeDatagram(trollMessage.data(), trollMessage.size(), QHostAddress::Broadcast, - port) == trollMessage.size()); + port); + +#ifdef Q_OS_SYMBIAN + //On symbian, broadcasts return 0 bytes written if none of the interfaces support it. + //Notably the loopback interfaces do not. (though they do support multicast!?) + if (written == 0) + QEXPECT_FAIL("", "No active interface supports broadcast", Abort); +#endif + QCOMPARE((int)written, trollMessage.size()); // Wait until we receive it ourselves #if defined(Q_OS_FREEBSD) -- cgit v0.12 From 2a6d7fcde4092f41230841bbe4c078f2e42166bb Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 1 Feb 2011 11:18:19 +0000 Subject: Change default type for http POST to application/octet-stream When the application did not set the mandatory content-type header for POST requests, Qt was putting in application/x-www-urlencoded. While this is the default for HTML forms, it isn't valid because Qt was not also encoding the data. Reviewed-by: Markus Goetz --- src/network/access/qhttpnetworkrequest.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index d2f3212..d4c735d 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -158,8 +158,10 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request } if (request.d->operation == QHttpNetworkRequest::Post) { // add content type, if not set in the request - if (request.headerField("content-type").isEmpty()) - ba += "Content-Type: application/x-www-form-urlencoded\r\n"; + if (request.headerField("content-type").isEmpty()) { + qWarning("content-type missing in HTTP POST, defaulting to application/octet-stream"); + ba += "Content-Type: application/octet-stream\r\n"; + } if (!request.d->uploadByteDevice && request.d->url.hasQuery()) { QByteArray query = request.d->url.encodedQuery(); ba += "Content-Length: "; -- cgit v0.12 From 2d30fce0c46fb5b98aec428869668bc345eeab8a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 1 Feb 2011 15:52:28 +0000 Subject: Unification of error handling in symbian socket engine Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 79 +++++++++-------------------- 1 file changed, 24 insertions(+), 55 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index f2c7b20..df0675e 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -67,6 +67,7 @@ #include #include +#include #define QNATIVESOCKETENGINE_DEBUG @@ -190,7 +191,6 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so else err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead - //TODO: combine error handling with setError if (err != KErrNone) { switch (err) { case KErrNotSupported: @@ -198,13 +198,8 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString); break; - case KErrNoMemory: - setError(QAbstractSocket::SocketResourceError, ResourceErrorString); - break; - case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AccessErrorString); - break; default: + setError(err); break; } @@ -588,7 +583,6 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) d->nativeSocket.Connect(nativeAddr, status); User::WaitForRequest(status); TInt err = status.Int(); - //TODO: combine with setError(int) //For non blocking connect, KErrAlreadyExists is returned from the second Connect() to indicate //the connection is up. So treat this the same as KErrNone which would be returned from the first //call if it wouldn't block. (e.g. winsock wrapper in the emulator ignores the nonblocking flag) @@ -597,36 +591,8 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) case KErrWouldBlock: d->socketState = QAbstractSocket::ConnectingState; break; - case KErrCouldNotConnect: - d->setError(QAbstractSocket::ConnectionRefusedError, d->ConnectionRefusedErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - break; - case KErrTimedOut: - d->setError(QAbstractSocket::NetworkError, d->ConnectionTimeOutErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - break; - case KErrHostUnreach: - d->setError(QAbstractSocket::NetworkError, d->HostUnreachableErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - break; - case KErrNetUnreach: - d->setError(QAbstractSocket::NetworkError, d->NetworkUnreachableErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - break; - case KErrInUse: - d->setError(QAbstractSocket::NetworkError, d->AddressInuseErrorString); - break; - case KErrPermissionDenied: - d->setError(QAbstractSocket::SocketAccessError, d->AccessErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - break; - case KErrBadName: - d->setError(QAbstractSocket::NetworkError, d->InvalidAddressError); - d->socketState = QAbstractSocket::UnconnectedState; - break; - case KErrNotSupported: - case KErrBadDescriptor: default: + d->setError(err); d->socketState = QAbstractSocket::UnconnectedState; break; } @@ -699,15 +665,7 @@ bool QSymbianSocketEngine::listen() // for a mobile platform TInt err = d->nativeSocket.Listen(50); if (err) { - //TODO: combine with setError(int) - switch (err) { - case KErrInUse: - d->setError(QAbstractSocket::AddressInUseError, - d->PortInuseErrorString); - break; - default: - break; - } + d->setError(err); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEnginePrivate::nativeListen() == false (%s)", @@ -846,9 +804,9 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, TInetAddr addr; d->setPortAndAddress(addr, port, host); TSockXfrLength sentBytes; - TRequestStatus status; //TODO: OMG sync send! + TRequestStatus status; d->nativeSocket.SendTo(buffer, addr, 0, status, sentBytes); - User::WaitForRequest(status); + User::WaitForRequest(status); //Non blocking send TInt err = status.Int(); if (err) { @@ -882,8 +840,10 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() return false; if (!nativeSocket.SubSessionHandle()) { - if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket)) + if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket)) { + setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString); return false; + } } // Determine local address @@ -912,8 +872,8 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() TProtocolDesc protocol; TInt err = nativeSocket.Info(protocol); if (err) { - // ? - // QAbstractSocket::UnknownSocketType; + setError(err); + return false; } else { switch (protocol.iProtocol) { case KProtocolInetTcp: @@ -1052,9 +1012,9 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) TPtr8 buffer((TUint8*)data, (int)maxSize); TSockXfrLength received = 0; - TRequestStatus status; //TODO: OMG sync receive! + TRequestStatus status; d->nativeSocket.RecvOneOrMore(buffer, 0, status, received); - User::WaitForRequest(status); + User::WaitForRequest(status); //Non blocking receive TInt err = status.Int(); int r = received(); @@ -1375,7 +1335,7 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString); break; case KErrPermissionDenied: - setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString); + setError(QAbstractSocket::SocketAccessError, AccessErrorString); break; case KErrNotSupported: setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString); @@ -1383,9 +1343,18 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) case KErrNoMemory: setError(QAbstractSocket::SocketResourceError, ResourceErrorString); break; + case KErrCouldNotConnect: + setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); + break; + case KErrTimedOut: + setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); + break; + case KErrBadName: + setError(QAbstractSocket::NetworkError, InvalidAddressError); + break; default: socketError = QAbstractSocket::NetworkError; - socketErrorString = QString::number(symbianError); + socketErrorString = QSystemError(symbianError, QSystemError::NativeError).toString(); break; } hasSetSocketError = true; -- cgit v0.12 From 4a8d3f4fb3830536a4a873f3c6bbf98fcdcd63a9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 1 Feb 2011 19:55:12 +0000 Subject: Clean up TODO and FIXME that are done Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 34 ++++++++++++++--------------- src/network/socket/qsymbiansocketengine_p.h | 4 ---- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index df0675e..5649a18 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -538,10 +538,21 @@ void QSymbianSocketEngine::setSendBufferSize(qint64 size) setOption(SendBufferSocketOption, size); } +/*! + Connects to the remote host name given by \a name on port \a + port. When this function is called, the upper-level will not + perform a hostname lookup. + + The native socket engine does not support this operation, + but some other socket engines (notably proxy-based ones) do. +*/ bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port) { - // FIXME for engines that support hostnames.. not for us then i guess. - + Q_UNUSED(name); + Q_UNUSED(port); + Q_D(QSymbianSocketEngine); + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QSymbianSocketEnginePrivate::OperationUnsupportedErrorString); return false; } @@ -737,8 +748,6 @@ bool QSymbianSocketEngine::hasPendingDatagrams() const int nbytes; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); return err == KErrNone && nbytes > 0; - //TODO: this is pretty horrible too... - // FIXME why? } qint64 QSymbianSocketEngine::pendingDatagramSize() const @@ -770,9 +779,9 @@ qint64 QSymbianSocketEngine::readDatagram(char *data, qint64 maxSize, Q_D(QSymbianSocketEngine); TPtr8 buffer((TUint8*)data, (int)maxSize); TInetAddr addr; - TRequestStatus status; //TODO: OMG sync receive! + TRequestStatus status; d->nativeSocket.RecvFrom(buffer, addr, 0, status); - User::WaitForRequest(status); + User::WaitForRequest(status); //Non blocking receive if (status.Int()) { d->setError(QAbstractSocket::NetworkError, d->ReceiveDatagramErrorString); @@ -1036,7 +1045,6 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) return qint64(r); } -// FIXME wait vs select int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const { bool readyRead = false; @@ -1062,8 +1070,6 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool //cancel asynchronous notifier (only one IOCTL allowed at a time) if (asyncSelect) asyncSelect->Cancel(); - //TODO: implement - //as above, but checking both read and write status at the same time TPckgBuf selectFlags; selectFlags() = KSockSelectExcept; @@ -1310,7 +1316,6 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E } } -//TODO: use QSystemError class when file engine is merged to master void QSymbianSocketEnginePrivate::setError(TInt symbianError) { switch (symbianError) { @@ -1385,14 +1390,12 @@ bool QReadNotifier::event(QEvent *e) bool QSymbianSocketEngine::isReadNotificationEnabled() const { Q_D(const QSymbianSocketEngine); - // TODO return d->readNotifier && d->readNotifier->isEnabled(); } void QSymbianSocketEngine::setReadNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); - // TODO if (d->readNotifier) { d->readNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { @@ -1437,14 +1440,12 @@ bool QWriteNotifier::event(QEvent *e) bool QSymbianSocketEngine::isWriteNotificationEnabled() const { Q_D(const QSymbianSocketEngine); - // TODO return d->writeNotifier && d->writeNotifier->isEnabled(); } void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); - // TODO if (d->writeNotifier) { d->writeNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { @@ -1488,7 +1489,6 @@ bool QExceptionNotifier::event(QEvent *e) bool QSymbianSocketEngine::isExceptionNotificationEnabled() const { Q_D(const QSymbianSocketEngine); - // TODO return d->exceptNotifier && d->exceptNotifier->isEnabled(); return false; } @@ -1497,7 +1497,6 @@ bool QSymbianSocketEngine::isExceptionNotificationEnabled() const void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); - // TODO if (d->exceptNotifier) { d->exceptNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { @@ -1674,7 +1673,8 @@ void QAsyncSelect::run() // return; m_inSocketEvent = true; m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested - //TODO: KSockSelectReadContinuation does what? + //KSockSelectReadContinuation is for reading datagrams in a mode that doesn't discard when the + //datagram is larger than the read buffer - Qt doesn't need to use this. if (iReadN && ((m_selectBuf() & KSockSelectRead) || iStatus != KErrNone)) { QEvent e(QEvent::SockAct); iReadN->event(&e); diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index df93fe6..a2904ae 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -60,8 +60,6 @@ #include #include #include -// TODO - QT_BEGIN_NAMESPACE @@ -121,7 +119,6 @@ public: int option(SocketOption option) const; bool setOption(SocketOption option, int value); - // FIXME actually implement bool waitForRead(int msecs = 30000, bool *timedOut = 0); bool waitForWrite(int msecs = 30000, bool *timedOut = 0); bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, @@ -244,7 +241,6 @@ public: void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr); void setError(TInt symbianError); - // FIXME int nativeSelect(int timeout, bool selectForRead) const; int nativeSelect(int timeout, bool checkRead, bool checkWrite, bool *selectForRead, bool *selectForWrite) const; -- cgit v0.12 From 027d9f026d3a668638ca6e687c687e0f4aa0cc02 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 2 Feb 2011 14:05:34 +0000 Subject: Add precondition checks to symbian socket engine entry points Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 112 +++++++++++++++++++--------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 5649a18..d6b893a 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -78,6 +78,7 @@ QT_BEGIN_NAMESPACE +#define Q_VOID // Common constructs #define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \ if (!isValid()) { \ @@ -186,9 +187,9 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; TInt err; - if (connection) - err = nativeSocket.Open(socketServer, family, type, protocol, *connection); - else +// if (connection) +// err = nativeSocket.Open(socketServer, family, type, protocol, *connection); +// else err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead if (err != KErrNone) { @@ -296,7 +297,7 @@ bool QSymbianSocketEngine::initialize(QAbstractSocket::SocketType socketType, QA QString protocolStr = QLatin1String("UnknownProtocol"); if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = QLatin1String("IPv4Protocol"); else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = QLatin1String("IPv6Protocol"); - qDebug("QNativeSocketEngine::initialize(type == %s, protocol == %s) failed: %s", + qDebug("QSymbianSocketEngine::initialize(type == %s, protocol == %s) failed: %s", typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), d->socketErrorString.toLatin1().constData()); #endif return false; @@ -323,7 +324,7 @@ bool QSymbianSocketEngine::initialize(QAbstractSocket::SocketType socketType, QA // Make sure we receive out-of-band data if (socketType == QAbstractSocket::TcpSocket && !setOption(ReceiveOutOfBandData, 1)) { - qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); + qWarning("QSymbianSocketEngine::initialize unable to inline out-of-band data"); } @@ -364,7 +365,7 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc // determine socket type and protocol if (!d->fetchConnectionParameters()) { #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEngine::initialize(socketDescriptor == %i) failed: %s", + qDebug("QSymbianSocketEngine::initialize(socketDescriptor == %i) failed: %s", socketDescriptor, d->socketErrorString.toLatin1().constData()); #endif d->socketDescriptor = -1; @@ -392,7 +393,7 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc // Make sure we receive out-of-band data if (d->socketType == QAbstractSocket::TcpSocket && !setOption(ReceiveOutOfBandData, 1)) { - qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); + qWarning("QSymbianSocketEngine::initialize unable to inline out-of-band data"); } } @@ -428,8 +429,7 @@ int QSymbianSocketEngine::socketDescriptor() const bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, int v) { Q_D(QSymbianSocketEngine); - if (!isValid()) - return false; + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setOption(), false); TUint n = 0; TUint level = KSOLSocket; // default @@ -449,8 +449,7 @@ bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, in int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const { Q_D(const QSymbianSocketEngine); - if (!isValid()) - return -1; + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::option(), -1); TUint n; TUint level = KSOLSocket; // default @@ -520,21 +519,25 @@ bool QSymbianSocketEnginePrivate::translateSocketOption(QAbstractSocketEngine::S qint64 QSymbianSocketEngine::receiveBufferSize() const { + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::receiveBufferSize(), -1); return option(ReceiveBufferSocketOption); } void QSymbianSocketEngine::setReceiveBufferSize(qint64 size) { + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setReceiveBufferSize(), Q_VOID); setOption(ReceiveBufferSocketOption, size); } qint64 QSymbianSocketEngine::sendBufferSize() const { + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setSendBufferSize(), -1); return option(SendBufferSocketOption); } void QSymbianSocketEngine::setSendBufferSize(qint64 size) { + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setSendBufferSize(), Q_VOID); setOption(SendBufferSocketOption, size); } @@ -577,6 +580,7 @@ void QSymbianSocketEngine::connectionNotification() bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::connectToHost(), false); #ifdef QNATIVESOCKETENGINE_DEBUG qDebug("QSymbianSocketEngine::connectToHost() : %d ", d->socketDescriptor); @@ -620,7 +624,7 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true", + qDebug("QSymbianSocketEngine::Connect(%s, %i) == true", addr.toString().toLatin1().constData(), port); #endif @@ -632,12 +636,12 @@ bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port) bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QSymbianSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::bind(), false); if (!d->checkProxy(address)) return false; - Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); + Q_CHECK_STATE(QSymbianSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); TInetAddr nativeAddr; d->setPortAndAddress(nativeAddr, port, address); @@ -652,7 +656,7 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) d->setError(err); #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == false (%s)", + qDebug("QSymbianSocketEngine::bind(%s, %i) == false (%s)", address.toString().toLatin1().constData(), port, d->socketErrorString.toLatin1().constData()); #endif @@ -660,7 +664,7 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeBind(%s, %i) == true", + qDebug("QSymbianSocketEngine::bind(%s, %i) == true", address.toString().toLatin1().constData(), port); #endif d->socketState = QAbstractSocket::BoundState; @@ -672,21 +676,24 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) bool QSymbianSocketEngine::listen() { Q_D(QSymbianSocketEngine); - // TODO the value 50 is from the QNativeSocketEngine. Maybe it's a bit too much + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::listen(), false); + Q_CHECK_STATE(QSymbianSocketEngine::listen(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QSymbianSocketEngine::listen(), QAbstractSocket::TcpSocket, false); + // TODO the value 50 is from the QNativeSocketEngine. Maybe it's a bit too much // for a mobile platform TInt err = d->nativeSocket.Listen(50); if (err) { d->setError(err); #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeListen() == false (%s)", + qDebug("QSymbianSocketEngine::listen() == false (%s)", d->socketErrorString.toLatin1().constData()); #endif return false; } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeListen() == true"); + qDebug("QSymbianSocketEngine::listen() == true"); #endif d->socketState = QAbstractSocket::ListeningState; @@ -707,7 +714,7 @@ int QSymbianSocketEngine::accept() if (status.Int()) { blankSocket.Close(); if (status != KErrWouldBlock) - qWarning("QSymbianSocketEnginePrivate::nativeAccept() - error %d", status.Int()); + qWarning("QSymbianSocketEngine::accept() - error %d", status.Int()); return -1; } @@ -724,8 +731,8 @@ int QSymbianSocketEngine::accept() qint64 QSymbianSocketEngine::bytesAvailable() const { Q_D(const QSymbianSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1); - Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, false); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::bytesAvailable(), -1); + Q_CHECK_NOT_STATE(QSymbianSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, false); int nbytes = 0; qint64 available = 0; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes); @@ -734,7 +741,7 @@ qint64 QSymbianSocketEngine::bytesAvailable() const available = (qint64) nbytes; #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeBytesAvailable() == %lli", available); + qDebug("QSymbianSocketEngine::bytesAvailable() == %lli", available); #endif return available; } @@ -742,9 +749,9 @@ qint64 QSymbianSocketEngine::bytesAvailable() const bool QSymbianSocketEngine::hasPendingDatagrams() const { Q_D(const QSymbianSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false); - Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false); - Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::hasPendingDatagrams(), false); + Q_CHECK_NOT_STATE(QSymbianSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false); + Q_CHECK_TYPE(QSymbianSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false); int nbytes; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); return err == KErrNone && nbytes > 0; @@ -753,6 +760,8 @@ bool QSymbianSocketEngine::hasPendingDatagrams() const qint64 QSymbianSocketEngine::pendingDatagramSize() const { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::pendingDatagramSize(), false); + Q_CHECK_TYPE(QSymbianSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false); int nbytes; TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes); if (nbytes > 0) { @@ -777,6 +786,8 @@ qint64 QSymbianSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::readDatagram(), -1); + Q_CHECK_TYPE(QSymbianSocketEngine::readDatagram(), QAbstractSocket::UdpSocket, false); TPtr8 buffer((TUint8*)data, (int)maxSize); TInetAddr addr; TRequestStatus status; @@ -791,7 +802,7 @@ qint64 QSymbianSocketEngine::readDatagram(char *data, qint64 maxSize, #if defined (QNATIVESOCKETENGINE_DEBUG) int len = buffer.Length(); - qDebug("QSymbianSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", + qDebug("QSymbianSocketEngine::receiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", data, qt_prettyDebug(data, qMin(len, ssize_t(16)), len).data(), maxSize, address ? address->toString().toLatin1().constData() : "(nil)", port ? *port : 0, (qint64) len); @@ -807,8 +818,8 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port) { Q_D(QSymbianSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); - Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::writeDatagram(), -1); + Q_CHECK_TYPE(QSymbianSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1); TPtrC8 buffer((TUint8*)data, (int)len); TInetAddr addr; d->setPortAndAddress(addr, port, host); @@ -920,7 +931,7 @@ void QSymbianSocketEngine::close() return; Q_D(QSymbianSocketEngine); #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeClose()"); + qDebug("QSymbianSocketEngine::close()"); #endif if (d->readNotifier) @@ -973,6 +984,8 @@ void QSymbianSocketEngine::close() qint64 QSymbianSocketEngine::write(const char *data, qint64 len) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::write(), -1); + Q_CHECK_STATE(QSymbianSocketEngine::write(), QAbstractSocket::ConnectedState, -1); TPtrC8 buffer((TUint8*)data, (int)len); TSockXfrLength sentBytes = 0; TRequestStatus status; @@ -1002,7 +1015,7 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", + qDebug("QSymbianSocketEngine::write(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin((int) len, 16), (int) len).data(), len, (int) sentBytes()); #endif @@ -1014,10 +1027,8 @@ qint64 QSymbianSocketEngine::write(const char *data, qint64 len) qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) { Q_D(QSymbianSocketEngine); - if (!isValid()) { - qWarning("QSymbianSocketEnginePrivate::nativeRead: Invalid socket"); - return -1; - } + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::read(), -1); + Q_CHECK_STATES(QSymbianSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1); TPtr8 buffer((TUint8*)data, (int)maxSize); TSockXfrLength received = 0; @@ -1037,7 +1048,7 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", + qDebug("QSymbianSocketEngine::read(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), maxSize, r); #endif @@ -1131,6 +1142,9 @@ bool QSymbianSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::joinMulticastGroup(), false); + Q_CHECK_STATE(QSymbianSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QSymbianSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false); return d->multicastGroupMembershipHelper(groupAddress, iface, KSoIp6JoinGroup); } @@ -1138,6 +1152,9 @@ bool QSymbianSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::leaveMulticastGroup(), false); + Q_CHECK_STATE(QSymbianSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QSymbianSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false); return d->multicastGroupMembershipHelper(groupAddress, iface, KSoIp6LeaveGroup); } @@ -1166,12 +1183,18 @@ bool QSymbianSocketEnginePrivate::multicastGroupMembershipHelper(const QHostAddr QNetworkInterface QSymbianSocketEngine::multicastInterface() const { //TODO + const Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::multicastInterface(), QNetworkInterface()); + Q_CHECK_TYPE(QSymbianSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface()); return QNetworkInterface(); } bool QSymbianSocketEngine::setMulticastInterface(const QNetworkInterface &iface) { //TODO - this is possibly a unix'ism as the RConnection on which the socket was created is probably controlling this + Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setMulticastInterface(), false); + Q_CHECK_TYPE(QSymbianSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false); return false; } @@ -1197,7 +1220,7 @@ bool QSymbianSocketEnginePrivate::checkProxy(const QHostAddress &address) if (proxy.type() != QNetworkProxy::DefaultProxy && proxy.type() != QNetworkProxy::NoProxy) { - // QNativeSocketEngine doesn't do proxies + // QSymbianSocketEngine doesn't do proxies setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidProxyTypeString); return false; @@ -1390,12 +1413,14 @@ bool QReadNotifier::event(QEvent *e) bool QSymbianSocketEngine::isReadNotificationEnabled() const { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isReadNotificationEnabled(), false); return d->readNotifier && d->readNotifier->isEnabled(); } void QSymbianSocketEngine::setReadNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setReadNotificationEnabled(), Q_VOID); if (d->readNotifier) { d->readNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { @@ -1440,12 +1465,14 @@ bool QWriteNotifier::event(QEvent *e) bool QSymbianSocketEngine::isWriteNotificationEnabled() const { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isWriteNotificationEnabled(), false); return d->writeNotifier && d->writeNotifier->isEnabled(); } void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setWriteNotificationEnabled(), Q_VOID); if (d->writeNotifier) { d->writeNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { @@ -1489,6 +1516,7 @@ bool QExceptionNotifier::event(QEvent *e) bool QSymbianSocketEngine::isExceptionNotificationEnabled() const { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isExceptionNotificationEnabled(), false); return d->exceptNotifier && d->exceptNotifier->isEnabled(); return false; } @@ -1497,6 +1525,7 @@ bool QSymbianSocketEngine::isExceptionNotificationEnabled() const void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setExceptionNotificationEnabled(), Q_VOID); if (d->exceptNotifier) { d->exceptNotifier->setEnabled(enable); } else if (enable && d->threadData->eventDispatcher) { @@ -1514,6 +1543,9 @@ void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) bool QSymbianSocketEngine::waitForRead(int msecs, bool *timedOut) { Q_D(const QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::waitForRead(), false); + Q_CHECK_NOT_STATE(QSymbianSocketEngine::waitForRead(), + QAbstractSocket::UnconnectedState, false); if (timedOut) *timedOut = false; @@ -1536,6 +1568,9 @@ bool QSymbianSocketEngine::waitForRead(int msecs, bool *timedOut) bool QSymbianSocketEngine::waitForWrite(int msecs, bool *timedOut) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::waitForWrite(), false); + Q_CHECK_NOT_STATE(QSymbianSocketEngine::waitForWrite(), + QAbstractSocket::UnconnectedState, false); if (timedOut) *timedOut = false; @@ -1561,6 +1596,9 @@ bool QSymbianSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWr int msecs, bool *timedOut) { Q_D(QSymbianSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::waitForWrite(), false); + Q_CHECK_NOT_STATE(QSymbianSocketEngine::waitForReadOrWrite(), + QAbstractSocket::UnconnectedState, false); int ret = d->nativeSelect(msecs, checkRead, checkWrite, readyToRead, readyToWrite); -- cgit v0.12 From d0c0aaf859452349c5cd64cbdba4ebb722c7722f Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 12 Jan 2011 15:21:45 +0000 Subject: Fix for using search paths with a dirty path Opening "searchpath:/file" and other non clean paths was failing Reviewed-by: joao --- src/corelib/io/qfilesystemengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index d9d802e..799c109 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -168,7 +168,7 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator)); for (int i = 0; i < paths.count(); i++) { - entry = QFileSystemEntry(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1)); + entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1))); // Recurse! if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true)) return true; -- cgit v0.12 From 97512b51ca8addc4fe1f8b5a4f7af14a13d4fd83 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 3 Feb 2011 12:16:35 +0000 Subject: Fix random crashes when bearer suddenly goes down 1. QNetworkSession being deleted from the closed signal caused data abort or E32User-CBase 49 panics. (both observed) 2. Potential E32User-CBase 46 panic in ConnectionProgressNotifier::StartNotifications() Reviewed-by: Aaron Tunney Reviewed-By: Markus Goetz Task-Number: QTBUG-17196 --- src/network/access/qnetworkaccessmanager.cpp | 7 ++++--- src/network/bearer/qnetworksession.cpp | 3 +++ src/network/bearer/qnetworksession.h | 3 +++ src/plugins/bearer/symbian/qnetworksession_impl.cpp | 6 +++--- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 7d37375..9c5a035 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1358,10 +1358,11 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co networkSession = QSharedNetworkSessionManager::getSession(config); - QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); - QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection); + //QueuedConnection is used to avoid deleting the networkSession inside its closed signal + QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), - q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); _q_networkSessionStateChanged(networkSession->state()); } diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index 41a8854..474ac6d 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -250,6 +250,9 @@ QNetworkSession::QNetworkSession(const QNetworkConfiguration &connectionConfig, } } } + + qRegisterMetaType(); + qRegisterMetaType(); } /*! diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index 717e085..da0c486 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -140,6 +140,9 @@ private: QNetworkSessionPrivate *d; }; +Q_DECLARE_METATYPE(QNetworkSession::State); +Q_DECLARE_METATYPE(QNetworkSession::SessionError); + #ifndef QT_MOBILITY_BEARER QT_END_NAMESPACE #else diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 759c86a..bbaf47b 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -1550,8 +1550,8 @@ void ConnectionProgressNotifier::StartNotifications() { if (!IsActive()) { SetActive(); + iConnection.ProgressNotification(iProgress, iStatus); } - iConnection.ProgressNotification(iProgress, iStatus); } void ConnectionProgressNotifier::StopNotifications() @@ -1567,10 +1567,10 @@ void ConnectionProgressNotifier::DoCancel() void ConnectionProgressNotifier::RunL() { if (iStatus == KErrNone) { - QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError)); - SetActive(); iConnection.ProgressNotification(iProgress, iStatus); + // warning, this object may be deleted in the callback - do nothing after handleSymbianConnectionStatusChange + QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError)); } } -- cgit v0.12 From cb0150aec0099ecc1569b20b58a75cdf9e5a5177 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 27 Jan 2011 14:57:59 +0000 Subject: add qscopedvaluerollback autotest to corelib.pro --- tests/auto/corelib.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/corelib.pro b/tests/auto/corelib.pro index 3451b53..6810f76 100644 --- a/tests/auto/corelib.pro +++ b/tests/auto/corelib.pro @@ -59,6 +59,7 @@ SUBDIRS=\ qresourceengine \ qringbuffer \ qscopedpointer \ + qscopedvaluerollback \ qsemaphore \ qsequentialanimationgroup \ qset \ -- cgit v0.12 From 9d7a1b187a76db52283429e38a0210c1dac82bf5 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 27 Jan 2011 15:02:08 +0000 Subject: Fix GCC compiler warning --- src/corelib/tools/qscopedvaluerollback.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h index d344ed8..e874428 100644 --- a/src/corelib/tools/qscopedvaluerollback.h +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -72,7 +72,7 @@ private: T& varRef; T oldValue; - Q_DISABLE_COPY(QScopedValueRollback); + Q_DISABLE_COPY(QScopedValueRollback) }; QT_END_NAMESPACE -- cgit v0.12 From b9307547c717606e08661cf474eeaf81cc0789e6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 28 Jan 2011 14:52:41 +0100 Subject: Fix for linux build error --- tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp b/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp index fac5702..956253f 100644 --- a/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp +++ b/tests/auto/qscopedvaluerollback/tst_qscopedvaluerollback.cpp @@ -200,4 +200,4 @@ void tst_QScopedValueRollback::earlyExitScope_helper(int exitpoint, int& member) } QTEST_MAIN(tst_QScopedValueRollback) -#include "tst_QScopedValueRollback.moc" +#include "tst_qscopedvaluerollback.moc" -- cgit v0.12 From bf024acae38226a2430d8c82b0f940781e33a7ef Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 7 Feb 2011 17:39:43 +0000 Subject: rebuild configure.exe --- configure.exe | Bin 1326592 -> 1397760 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/configure.exe b/configure.exe index 293d667..9d450b5 100755 Binary files a/configure.exe and b/configure.exe differ -- cgit v0.12 From b1fa3580515e7f10a9bd06b6a9e7733635f95cab Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 8 Feb 2011 16:05:53 +0000 Subject: Workaround public header depending on private in symbian^3 f32file.h (public) depends on e32svr.h (private), and in symbian^3 the private headers have been moved to a different include path. Reviewed-by: axis --- mkspecs/features/qt_functions.prf | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 964e13b..bc1a297 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -46,7 +46,12 @@ defineTest(qtAddLibrary) { } } symbian { - isEqual(LIB_NAME, QtGui) { + isEqual(LIB_NAME, QtCore) { + #workaround for dependency from f32file.h on e32svr.h which has moved location in symbian3 + contains(SYMBIAN_VERSION, Symbian3) { + INCLUDEPATH *= $$OS_LAYER_SYSTEMINCLUDE + } + } else:isEqual(LIB_NAME, QtGui) { # Needed for #include because qs60mainapplication.h includes aknapp.h INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE } else:isEqual(LIB_NAME, QtWebKit) { -- cgit v0.12 From 42adaaa0dffa9df387a145181bc97ee3bb9a4c7b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 16 Feb 2011 13:52:12 +0000 Subject: Fix thread starvation when processEvents() is called in a tight loop One of the qftp test cases calls processEvents() in a tight loop instead of using an event loop. This was causing the application to hang on symbian as it blocked a lower priority system thread and the WLAN connection never completed. Although calling processEvents in a tight loop is bad practice, it works on other OS where thread priorities are dynamic. Reviewed-by: mread --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index b3a3d4d..0b7682c 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -818,6 +818,14 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla CActiveScheduler::Current()->WaitForAnyRequest(); } else { if (thread.RequestCount() == 0) { +#ifdef QT_SYMBIAN_PRIORITY_DROP + if (idleDetectorThread()->hasRun()) { + m_lastIdleRequestTimer.start(); + idleDetectorThread()->kick(); + } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) { + User::AfterHighRes(m_delay); + } +#endif break; } // This one should return without delay. -- cgit v0.12 From 44ef44bc3826c78a10bcf02d3357bf6332c6c3ed Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 17 Feb 2011 13:27:45 +0000 Subject: Explicit network session for QNetworkAccessManager Implemented a tunnel to get the QNetworkSession from QNetworkAccessManager down to the socket engine. This is currently a private API for QNAM. This patch only implements the FTP backend - the other backends are to follow. On Symbian, the native socket engine will extract the native session (RConnection) from the QNetworkSession implementation, and use that to open sockets using the explicitly specified session. When no session is specified on the socket (default for networking usage outside of QNAM) then the socket is opened with no RConnection specified, which allows the IP stack to find any route via an open interface. The QFtp autotest is enhanced to test QFtp with an explicit session as well as implicit connectivity (where a QNetworkSession is opened by the user, and then QFtp is used without a specified connection). This autotest gives better coverage than the FTP test cases in QNetworkReply. Reviewed-by: Markus Goetz --- src/network/access/qftp.cpp | 17 +++++ src/network/access/qnetworkaccessbackend.cpp | 7 +- src/network/access/qnetworkaccessftpbackend.cpp | 4 + src/network/bearer/qnetworksession.cpp | 9 +++ src/network/bearer/qnetworksession_p.h | 11 +++ src/network/socket/qabstractsocket.cpp | 8 ++ src/network/socket/qsymbiansocketengine.cpp | 31 ++++++-- src/network/socket/qsymbiansocketengine_p.h | 5 +- src/network/socket/qtcpserver.cpp | 8 ++ src/network/ssl/qsslsocket.cpp | 4 + .../bearer/symbian/qnetworksession_impl.cpp | 5 ++ src/plugins/bearer/symbian/qnetworksession_impl.h | 3 +- tests/auto/qftp/tst_qftp.cpp | 88 ++++++++++++++++++++-- 13 files changed, 182 insertions(+), 18 deletions(-) diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index ccc20e6..45fc11f 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -319,6 +319,10 @@ void QFtpDTP::connectToHost(const QString & host, quint16 port) socket = 0; } socket = new QTcpSocket(this); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket + socket->setProperty("_q_networksession", property("_q_networksession")); +#endif socket->setObjectName(QLatin1String("QFtpDTP Passive state socket")); connect(socket, SIGNAL(connected()), SLOT(socketConnected())); connect(socket, SIGNAL(readyRead()), SLOT(socketReadyRead())); @@ -331,6 +335,10 @@ void QFtpDTP::connectToHost(const QString & host, quint16 port) int QFtpDTP::setupListener(const QHostAddress &address) { +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket + listener.setProperty("_q_networksession", property("_q_networksession")); +#endif if (!listener.isListening() && !listener.listen(address, 0)) return -1; return listener.serverPort(); @@ -808,6 +816,11 @@ QFtpPI::QFtpPI(QObject *parent) : void QFtpPI::connectToHost(const QString &host, quint16 port) { emit connectState(QFtp::HostLookup); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket & DTP + commandSocket.setProperty("_q_networksession", property("_q_networksession")); + dtp.setProperty("_q_networksession", property("_q_networksession")); +#endif commandSocket.connectToHost(host, port); } @@ -2240,6 +2253,10 @@ void QFtpPrivate::_q_startNextCommand() c->rawCmds.clear(); _q_piFinished(QLatin1String("Proxy set to ") + proxyHost + QLatin1Char(':') + QString::number(proxyPort)); } else if (c->command == QFtp::ConnectToHost) { +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the PI + pi.setProperty("_q_networksession", q->property("_q_networksession")); +#endif if (!proxyHost.isEmpty()) { host = c->rawCmds[0]; port = c->rawCmds[1].toUInt(); diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index fd1fa60..de40256 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -46,7 +46,7 @@ #include "qnetworkreply_p.h" #include "QtCore/qhash.h" #include "QtCore/qmutex.h" -#include "QtNetwork/qnetworksession.h" +#include "QtNetwork/private/qnetworksession_p.h" #include "qnetworkaccesscachebackend_p.h" #include "qabstractnetworkcache.h" @@ -96,6 +96,11 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM QNetworkAccessBackend *backend = (*it)->create(op, request); if (backend) { backend->manager = this; +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the backend + if (networkSession) + backend->setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif return backend; // found a factory that handled our request } ++it; diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index e34e6bb..3ad1961 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -153,6 +153,10 @@ void QNetworkAccessFtpBackend::open() if (!objectCache->requestEntry(cacheKey, this, SLOT(ftpConnectionReady(QNetworkAccessCache::CacheableObject*)))) { ftp = new QNetworkAccessCachedFtpConnection; +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the QFtp + ftp->setProperty("_q_networksession", property("_q_networksession")); +#endif #ifndef QT_NO_NETWORKPROXY if (proxy.type() == QNetworkProxy::FtpCachingProxy) ftp->setProxy(proxy.hostName(), proxy.port()); diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index 553410e..0ddd10a 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -705,6 +705,15 @@ void QNetworkSession::disconnectNotify(const char *signal) d->setALREnabled(false); } +#ifdef Q_OS_SYMBIAN +RConnection* QNetworkSessionPrivate::nativeSession(QNetworkSession &s) +{ + if (!s.d) + return 0; + return s.d->nativeSession(); +} +#endif + #include "moc_qnetworksession.cpp" QT_END_NAMESPACE diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h index 707ad37..e2fcfe6 100644 --- a/src/network/bearer/qnetworksession_p.h +++ b/src/network/bearer/qnetworksession_p.h @@ -55,9 +55,14 @@ #include "qnetworksession.h" #include "qnetworkconfiguration_p.h" +#include "QtCore/qsharedpointer.h" #ifndef QT_NO_BEARERMANAGEMENT +#ifdef Q_OS_SYMBIAN +class RConnection; +#endif + QT_BEGIN_NAMESPACE class Q_NETWORK_EXPORT QNetworkSessionPrivate : public QObject @@ -102,6 +107,10 @@ public: virtual quint64 bytesReceived() const = 0; virtual quint64 activeTime() const = 0; +#ifdef Q_OS_SYMBIAN + static RConnection* nativeSession(QNetworkSession&); + virtual RConnection* nativeSession() = 0; +#endif protected: inline QNetworkConfigurationPrivatePointer privateConfiguration(const QNetworkConfiguration &config) const { @@ -145,6 +154,8 @@ protected: QT_END_NAMESPACE +Q_DECLARE_METATYPE(QSharedPointer) + #endif // QT_NO_BEARERMANAGEMENT #endif // QNETWORKSESSIONPRIVATE_H diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 3462538..af5f027 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -546,6 +546,10 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc resetSocketLayer(); socketEngine = QAbstractSocketEngine::createSocketEngine(q->socketType(), proxyInUse, q); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket engine (if it has been set) + socketEngine->setProperty("_q_networksession", q->property("_q_networksession")); +#endif if (!socketEngine) { socketError = QAbstractSocket::UnsupportedSocketOperationError; q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported")); @@ -1600,6 +1604,10 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock d->resetSocketLayer(); d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket engine (if it has been set) + d->socketEngine->setProperty("_q_networksession", property("_q_networksession")); +#endif if (!d->socketEngine) { d->socketError = UnsupportedSocketOperationError; setErrorString(tr("Operation on socket is not supported")); diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index d6b893a..b9537c1 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -47,6 +47,7 @@ #include "qelapsedtimer.h" #include "qvarlengtharray.h" #include "qnetworkinterface.h" +#include "qnetworksession_p.h" #include #include #include @@ -186,10 +187,26 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so TUint family = KAfInet; // KAfInet6 is only used as an address family, not as a protocol family TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream; TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; + + //Check if there is a user specified session + RConnection *connection = 0; + QVariant v(q->property("_q_networksession")); + if (v.isValid()) { + QSharedPointer s = qvariant_cast >(v); + connection = QNetworkSessionPrivate::nativeSession(*s); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << connection; +#endif + } TInt err; -// if (connection) -// err = nativeSocket.Open(socketServer, family, type, protocol, *connection); -// else + if (connection) { + if (connection->SubSessionHandle()) + err = nativeSocket.Open(socketServer, family, type, protocol, *connection); + else { + setError(QAbstractSocket::NetworkError, SessionNotOpenErrorString); + return false; + } + } else err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead if (err != KErrNone) { @@ -246,7 +263,6 @@ void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : socketDescriptor(-1), socketServer(QSymbianSocketManager::instance().getSocketServer()), - connection(QSymbianSocketManager::instance().defaultConnection()), readNotifier(0), writeNotifier(0), exceptNotifier(0), @@ -1330,9 +1346,12 @@ void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, E case InvalidProxyTypeString: socketErrorString = QSymbianSocketEngine::tr("The proxy type is invalid for this operation"); break; - case InvalidAddressError: + case InvalidAddressErrorString: socketErrorString = QSymbianSocketEngine::tr("The address is invalid for this operation"); break; + case SessionNotOpenErrorString: + socketErrorString = QSymbianSocketEngine::tr("The specified network session is not opened"); + break; case UnknownSocketErrorString: socketErrorString = QSymbianSocketEngine::tr("Unknown error"); break; @@ -1378,7 +1397,7 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); break; case KErrBadName: - setError(QAbstractSocket::NetworkError, InvalidAddressError); + setError(QAbstractSocket::NetworkError, InvalidAddressErrorString); break; default: socketError = QAbstractSocket::NetworkError; diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index a2904ae..bc39450 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -196,8 +196,6 @@ public: mutable RSocket nativeSocket; // From QtCore: RSocketServ& socketServer; - // From QtCore, check lifetime issues, also should be pulling this out of a QNetworkSession somehow: - RConnection *connection; mutable RTimer selectTimer; QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; @@ -231,7 +229,8 @@ public: NotSocketErrorString, InvalidProxyTypeString, //symbian specific - InvalidAddressError, + InvalidAddressErrorString, + SessionNotOpenErrorString, UnknownSocketErrorString = -1 }; diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index e382830..6b012db 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -287,6 +287,10 @@ bool QTcpServer::listen(const QHostAddress &address, quint16 port) delete d->socketEngine; d->socketEngine = QAbstractSocketEngine::createSocketEngine(QAbstractSocket::TcpSocket, proxy, this); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket engine (if it has been set) + d->socketEngine->setProperty("_q_networksession", property("_q_networksession")); +#endif if (!d->socketEngine) { d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError; d->serverSocketErrorString = tr("Operation on socket is not supported"); @@ -412,6 +416,10 @@ bool QTcpServer::setSocketDescriptor(int socketDescriptor) if (d->socketEngine) delete d->socketEngine; d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the socket engine (if it has been set) + d->socketEngine->setProperty("_q_networksession", property("_q_networksession")); +#endif if (!d->socketEngine->initialize(socketDescriptor, QAbstractSocket::ListeningState)) { d->serverSocketError = d->socketEngine->error(); d->serverSocketErrorString = d->socketEngine->errorString(); diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 4252123..39b74d9 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2000,6 +2000,10 @@ void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode) q->setPeerName(QString()); plainSocket = new QTcpSocket(q); +#ifndef QT_NO_BEARERMANAGEMENT + //copy network session down to the plain socket (if it has been set) + plainSocket->setProperty("_q_networksession", q->property("_q_networksession")); +#endif q->connect(plainSocket, SIGNAL(connected()), q, SLOT(_q_connectedSlot()), Qt::DirectConnection); diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 2167dbb..e35c01a 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -1535,6 +1535,11 @@ bool QNetworkSessionPrivateImpl::easyWlanTrueIapId(TUint32 &trueIapId) const } #endif +RConnection* QNetworkSessionPrivateImpl::nativeSession() +{ + return &iConnection; +} + ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection) : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection) { diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index a0e7a2a..f2a8a45 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -111,7 +111,8 @@ public: quint64 bytesWritten() const; quint64 bytesReceived() const; quint64 activeTime() const; - + + RConnection* nativeSession(); #ifdef SNAP_FUNCTIONALITY_AVAILABLE public: // From MMobilityProtocolResp void PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo, diff --git a/tests/auto/qftp/tst_qftp.cpp b/tests/auto/qftp/tst_qftp.cpp index 1b4b503..7e3cd75 100644 --- a/tests/auto/qftp/tst_qftp.cpp +++ b/tests/auto/qftp/tst_qftp.cpp @@ -50,6 +50,10 @@ #include #include #include +#include +#include +#include +#include #include "../network-settings.h" @@ -62,7 +66,9 @@ #define SRCDIR "" #endif - +#ifndef QT_NO_BEARERMANAGEMENT +Q_DECLARE_METATYPE(QNetworkConfiguration) +#endif class tst_QFtp : public QObject { @@ -148,6 +154,10 @@ private: void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete ); QFtp *ftp; +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSessionExplicit; + QSharedPointer networkSessionImplicit; +#endif QList ids; // helper to make sure that all expected signals are emitted int current_id; @@ -186,9 +196,9 @@ private: const int bytesTotal_init = -10; const int bytesDone_init = -10; -tst_QFtp::tst_QFtp() +tst_QFtp::tst_QFtp() : + ftp(0) { - Q_SET_DEFAULT_IAP } tst_QFtp::~tst_QFtp() @@ -199,33 +209,62 @@ void tst_QFtp::initTestCase_data() { QTest::addColumn("setProxy"); QTest::addColumn("proxyType"); + QTest::addColumn("setSession"); - QTest::newRow("WithoutProxy") << false << 0; - QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy); + QTest::newRow("WithoutProxy") << false << 0 << false; + QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy) << false; //### doesn't work well yet. //QTest::newRow("WithHttpProxy") << true << int(QNetworkProxy::HttpProxy); + +#ifndef QT_NO_BEARERMANAGEMENT + QTest::newRow("WithoutProxyWithSession") << false << 0 << true; + QTest::newRow("WithSocks5ProxyAndSession") << true << int(QNetworkProxy::Socks5Proxy) << true; +#endif } void tst_QFtp::initTestCase() { +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager manager; + networkSessionImplicit = QSharedPointer(new QNetworkSession(manager.defaultConfiguration())); + networkSessionImplicit->open(); + QVERIFY(networkSessionImplicit->waitForOpened(60000)); //there may be user prompt on 1st connect +#endif } void tst_QFtp::cleanupTestCase() { +#ifndef QT_NO_BEARERMANAGEMENT + networkSessionExplicit.clear(); + networkSessionImplicit.clear(); +#endif } void tst_QFtp::init() { QFETCH_GLOBAL(bool, setProxy); + QFETCH_GLOBAL(int, proxyType); + QFETCH_GLOBAL(bool, setSession); if (setProxy) { - QFETCH_GLOBAL(int, proxyType); if (proxyType == QNetworkProxy::Socks5Proxy) { QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080)); } else if (proxyType == QNetworkProxy::HttpProxy) { QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128)); } } +#ifndef QT_NO_BEARERMANAGEMENT + if (setSession) { + networkSessionExplicit = networkSessionImplicit; + if (!networkSessionExplicit->isOpen()) { + networkSessionExplicit->open(); + QVERIFY(networkSessionExplicit->waitForOpened(30000)); + } + } else { + networkSessionExplicit.clear(); + } +#endif + delete ftp; ftp = 0; ids.clear(); @@ -266,6 +305,12 @@ void tst_QFtp::cleanup() if (setProxy) { QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy); } + + delete ftp; + ftp = 0; +#ifndef QT_NO_BEARERMANAGEMENT + networkSessionExplicit.clear(); +#endif } void tst_QFtp::connectToHost_data() @@ -289,6 +334,7 @@ void tst_QFtp::connectToHost() QTestEventLoop::instance().enterLoop( 61 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -337,6 +383,7 @@ void tst_QFtp::connectToUnresponsiveHost() QVERIFY( it.value().success == 0 ); delete ftp; + ftp = 0; } void tst_QFtp::login_data() @@ -369,6 +416,7 @@ void tst_QFtp::login() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -415,6 +463,7 @@ void tst_QFtp::close() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -482,6 +531,7 @@ void tst_QFtp::list() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -542,6 +592,7 @@ void tst_QFtp::cd() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) { QFAIL( "Network operation timed out" ); } @@ -617,6 +668,7 @@ void tst_QFtp::get() QTestEventLoop::instance().enterLoop( 50 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -743,6 +795,7 @@ void tst_QFtp::put() break; } delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -775,6 +828,7 @@ void tst_QFtp::put() break; } delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -792,6 +846,7 @@ void tst_QFtp::put() QTestEventLoop::instance().enterLoop( timestep ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -860,6 +915,7 @@ void tst_QFtp::mkdir() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -884,6 +940,7 @@ void tst_QFtp::mkdir() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -903,6 +960,7 @@ void tst_QFtp::mkdir() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -942,6 +1000,7 @@ void tst_QFtp::mkdir2() QVERIFY(commandFinishedSpy.at(3).at(1).toBool()); delete ftp; + ftp = 0; } void tst_QFtp::mkdir2Slot(int id, bool) @@ -1019,6 +1078,7 @@ void tst_QFtp::renameInit( const QString &host, const QString &user, const QStri QTestEventLoop::instance().enterLoop( 50 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1043,6 +1103,7 @@ void tst_QFtp::renameCleanup( const QString &host, const QString &user, const QS QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1087,6 +1148,7 @@ void tst_QFtp::rename() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1273,6 +1335,7 @@ void tst_QFtp::commandSequence() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1330,6 +1393,7 @@ void tst_QFtp::abort() break; } delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1367,6 +1431,7 @@ void tst_QFtp::abort() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1425,6 +1490,7 @@ void tst_QFtp::bytesAvailable() ftp->readAll(); QVERIFY( ftp->bytesAvailable() == 0 ); delete ftp; + ftp = 0; } void tst_QFtp::activeMode() @@ -1497,6 +1563,7 @@ void tst_QFtp::proxy() QTestEventLoop::instance().enterLoop( 50 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) { QFAIL( "Network operation timed out" ); } @@ -1512,7 +1579,6 @@ void tst_QFtp::proxy() } } - void tst_QFtp::binaryAscii() { QString file = "asciifile%1.txt"; @@ -1573,6 +1639,7 @@ void tst_QFtp::binaryAscii() QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) QFAIL( "Network operation timed out" ); @@ -1868,6 +1935,11 @@ void tst_QFtp::dataTransferProgress( qint64 done, qint64 total ) QFtp *tst_QFtp::newFtp() { QFtp *nFtp = new QFtp( this ); +#ifndef QT_NO_BEARERMANAGEMENT + if (networkSessionExplicit) { + nFtp->setProperty("_q_networksession", QVariant::fromValue(networkSessionExplicit)); + } +#endif connect( nFtp, SIGNAL(commandStarted(int)), SLOT(commandStarted(int)) ); connect( nFtp, SIGNAL(commandFinished(int,bool)), @@ -1920,6 +1992,7 @@ bool tst_QFtp::fileExists( const QString &host, quint16 port, const QString &use inFileDirExistsFunction = TRUE; QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) { // ### make this test work qWarning("tst_QFtp::fileExists: Network operation timed out"); @@ -1970,6 +2043,7 @@ bool tst_QFtp::dirExists( const QString &host, quint16 port, const QString &user inFileDirExistsFunction = TRUE; QTestEventLoop::instance().enterLoop( 30 ); delete ftp; + ftp = 0; if ( QTestEventLoop::instance().timeout() ) { // ### make this test work // QFAIL( "Network operation timed out" ); -- cgit v0.12 From 975a51fbe914cf0afd7bde1bf50d1f1f28d12dd7 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 17 Feb 2011 16:02:55 +0000 Subject: Remove open C setdefaultif support from symbian QNetworkSession Qt no longer uses open C sockets Reviewed-by: Markus Goetz --- .../bearer/symbian/qnetworksession_impl.cpp | 68 +--------------------- src/plugins/bearer/symbian/qnetworksession_impl.h | 3 - 2 files changed, 3 insertions(+), 68 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index e35c01a..950997f 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -45,8 +45,6 @@ #include #include #include -#include -#include #include #ifdef SNAP_FUNCTIONALITY_AVAILABLE @@ -63,29 +61,16 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) : CActive(CActive::EPriorityUserInput), engine(engine), - iDynamicUnSetdefaultif(0), ipConnectionNotifier(0), + iSocketServ(qt_symbianGetSocketServer()), ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), - iConnectInBackground(false), isOpening(false), iSocketServ(qt_symbianGetSocketServer()) + iConnectInBackground(false), isOpening(false) { CActiveScheduler::Add(this); #ifdef SNAP_FUNCTIONALITY_AVAILABLE iMobility = NULL; #endif - // Try to load "Open C" dll dynamically and - // try to attach to unsetdefaultif function dynamically. - // This is to avoid build breaks with old OpenC versions. - if (iOpenCLibrary.Load(_L("libc")) == KErrNone) { - iDynamicUnSetdefaultif = (TOpenCUnSetdefaultifFunction)iOpenCLibrary.Lookup(597); - } -#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG - qDebug() << "QNS this : " << QString::number((uint)this) << " - "; - if (iDynamicUnSetdefaultif) - qDebug() << "dynamic unsetdefaultif() is present in PIPS library. "; - else - qDebug() << "dynamic unsetdefaultif() not present in PIPS library. "; -#endif TRAP_IGNORE(iConnectionMonitor.ConnectL()); } @@ -111,16 +96,12 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() // Cancel possible RConnection::Start() Cancel(); - // Close global 'Open C' RConnection - // Clears also possible unsetdefaultif() flags. - setdefaultif(0); QSymbianSocketManager::instance().setDefaultConnection(0); iConnectionMonitor.Close(); - iOpenCLibrary.Close(); #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) - << " - destroyed (and setdefaultif(0))"; + << " - destroyed"; #endif } @@ -524,16 +505,6 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) Cancel(); // closes iConnection - // Close global 'Open C' RConnection. If OpenC supports, - // close the defaultif for good to avoid difficult timing - // and bouncing issues of network going immediately back up - // because of e.g. select() thread etc. - if (iDynamicUnSetdefaultif) { - iDynamicUnSetdefaultif(); - } else { - setdefaultif(0); - } - QSymbianSocketManager::instance().setDefaultConnection(0); // If UserChoice, go down immediately. If some other configuration, // go down immediately if there is no reports expected from the platform; @@ -629,13 +600,6 @@ void QNetworkSessionPrivateImpl::migrate() { #ifdef SNAP_FUNCTIONALITY_AVAILABLE if (iMobility) { - // Close global 'Open C' RConnection. If openC supports, use the 'heavy' - // version to block all subsequent requests. - if (iDynamicUnSetdefaultif) { - iDynamicUnSetdefaultif(); - } else { - setdefaultif(0); - } QSymbianSocketManager::instance().setDefaultConnection(0); // Start migrating to new IAP iMobility->MigrateToPreferredCarrier(); @@ -666,13 +630,6 @@ void QNetworkSessionPrivateImpl::accept() QNetworkConfiguration newActiveConfig = activeConfiguration(iNewRoamingIap); - // Use name of the new IAP to open global 'Open C' RConnection - QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); - ifreq ifr; - memset(&ifr, 0, sizeof(struct ifreq)); - strcpy(ifr.ifr_name, nameAsByteArray.constData()); - setdefaultif(&ifr); - QSymbianSocketManager::instance().setDefaultConnection(&iConnection); newState(QNetworkSession::Connected, iNewRoamingIap); @@ -691,13 +648,6 @@ void QNetworkSessionPrivateImpl::reject() } else { QNetworkConfiguration newActiveConfig = activeConfiguration(iOldRoamingIap); - // Use name of the old IAP to open global 'Open C' RConnection - QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); - ifreq ifr; - memset(&ifr, 0, sizeof(struct ifreq)); - strcpy(ifr.ifr_name, nameAsByteArray.constData()); - setdefaultif(&ifr); - QSymbianSocketManager::instance().setDefaultConnection(&iConnection); newState(QNetworkSession::Connected, iOldRoamingIap); @@ -1080,12 +1030,6 @@ void QNetworkSessionPrivateImpl::RunL() // Connectivity Test, ICT, failed). error = KErrGeneral; } else { - // Use name of the IAP to open global 'Open C' RConnection - ifreq ifr; - memset(&ifr, 0, sizeof(struct ifreq)); - QByteArray nameAsByteArray = newActiveConfig.name().toUtf8(); - strcpy(ifr.ifr_name, nameAsByteArray.constData()); - error = setdefaultif(&ifr); QSymbianSocketManager::instance().setDefaultConnection(&iConnection); } if (error != KErrNone) { @@ -1208,12 +1152,6 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint #endif #ifdef SNAP_FUNCTIONALITY_AVAILABLE - // Use name of the IAP to set default IAP - QByteArray nameAsByteArray = activeConfig.name().toUtf8(); - ifreq ifr; - strcpy(ifr.ifr_name, nameAsByteArray.constData()); - - setdefaultif(&ifr); QSymbianSocketManager::instance().setDefaultConnection(&iConnection); #endif } diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index f2a8a45..5aa142f 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -160,9 +160,6 @@ private: // data QDateTime startTime; - RLibrary iOpenCLibrary; - TOpenCUnSetdefaultifFunction iDynamicUnSetdefaultif; - mutable RSocketServ &iSocketServ; //not owned, shared from QtCore mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; -- cgit v0.12 From f5e7b6c64caa67bf11fa9754114d686da73b22d6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Feb 2011 16:47:39 +0000 Subject: Fix RConnection handle leak in symbian bearer plugin The implementation was opening RConnection handles on top of previous instances, and not closing RConnection handles. Both of these cause a resource leak in the socket server which cannot clean up the connection until the Qt process has exited. After a lot of this (which could be triggered by the QNetworkReply auto test), the socket server may run out of memory resulting in all socket operations failing. Reviewed-by: Markus Goetz --- .../bearer/symbian/qnetworksession_impl.cpp | 95 +++++++++------------- src/plugins/bearer/symbian/qnetworksession_impl.h | 1 + 2 files changed, 40 insertions(+), 56 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 950997f..760c0e7 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -75,32 +75,43 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) TRAP_IGNORE(iConnectionMonitor.ConnectL()); } -QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() +void QNetworkSessionPrivateImpl::closeHandles() { - isOpen = false; - isOpening = false; - // Cancel Connection Progress Notifications first. - // Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start() + // Note: ConnectionNotifier must be destroyed before RConnection::Close() // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification() delete ipConnectionNotifier; ipConnectionNotifier = NULL; #ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iMobility) { - delete iMobility; - iMobility = NULL; - } + // mobility monitor must be deleted before RConnection is closed + delete iMobility; + iMobility = NULL; #endif - // Cancel possible RConnection::Start() + // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress Cancel(); + //close any open connection (note Close twice is safe in case Cancel did it above) + iConnection.Close(); QSymbianSocketManager::instance().setDefaultConnection(0); iConnectionMonitor.Close(); #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) + << " - handles closed"; +#endif + +} + +QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() +{ + isOpen = false; + isOpening = false; + + closeHandles(); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - destroyed"; #endif } @@ -148,7 +159,7 @@ void QNetworkSessionPrivateImpl::configurationAdded(QNetworkConfigurationPrivate #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "configurationAdded IAP: " - << toSymbianConfig(privateConfiguration(config))->numericIdentifier(); + << toSymbianConfig(config)->numericIdentifier(); #endif syncStateWithInterface(); @@ -345,6 +356,7 @@ void QNetworkSessionPrivateImpl::open() iStoppedByUser = false; iClosedByUser = false; + Q_ASSERT(!iConnection.SubSessionHandle()); TInt error = iConnection.Open(iSocketServ); if (error != KErrNone) { // Could not open RConnection @@ -385,8 +397,8 @@ void QNetworkSessionPrivateImpl::open() pref.SetIapId(symbianConfig->numericIdentifier()); #endif - iConnection.Start(pref, iStatus); if (!IsActive()) { + iConnection.Start(pref, iStatus); SetActive(); } // Avoid flip flop of states if the configuration is already @@ -413,8 +425,8 @@ void QNetworkSessionPrivateImpl::open() #else TConnSnapPref snapPref(symbianConfig->numericIdentifier()); #endif - iConnection.Start(snapPref, iStatus); if (!IsActive()) { + iConnection.Start(snapPref, iStatus); SetActive(); } // Avoid flip flop of states if the configuration is already @@ -424,8 +436,8 @@ void QNetworkSessionPrivateImpl::open() } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers(); - iConnection.Start(iStatus); if (!IsActive()) { + iConnection.Start(iStatus); SetActive(); } newState(QNetworkSession::Connecting); @@ -436,9 +448,7 @@ void QNetworkSessionPrivateImpl::open() isOpening = false; iError = QNetworkSession::UnknownSessionError; emit QNetworkSessionPrivate::error(iError); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); syncStateWithInterface(); } } @@ -490,22 +500,11 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) serviceConfig = QNetworkConfiguration(); -#ifdef SNAP_FUNCTIONALITY_AVAILABLE - if (iMobility) { - delete iMobility; - iMobility = NULL; - } -#endif + closeHandles(); - if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) { - ipConnectionNotifier->StopNotifications(); - // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate - iHandleStateNotificationsFromManager = true; - } - - Cancel(); // closes iConnection + // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate + iHandleStateNotificationsFromManager = true; - QSymbianSocketManager::instance().setDefaultConnection(0); // If UserChoice, go down immediately. If some other configuration, // go down immediately if there is no reports expected from the platform; // in practice Connection Monitor is aware of connections only after @@ -701,12 +700,14 @@ void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo* } } -void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) +void QNetworkSessionPrivateImpl::Error(TInt aError) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "roaming Error() occurred, isOpen is: " << isOpen; + << "roaming Error() occurred" << aError << ", isOpen is: " << isOpen; #endif + if (aError == KErrCancel) + return; //avoid recursive deletion if (isOpen) { isOpen = false; isOpening = false; @@ -714,10 +715,7 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::RoamingError; emit QNetworkSessionPrivate::error(iError); - Cancel(); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); QT_TRY { syncStateWithInterface(); // In some cases IAP is still in Connected state when @@ -1037,19 +1035,13 @@ void QNetworkSessionPrivateImpl::RunL() isOpening = false; iError = QNetworkSession::UnknownSessionError; QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } + closeHandles(); if (!newActiveConfig.isValid()) { // No valid configuration, bail out. // Status updates from QNCM won't be received correctly // because there is no configuration to associate them with so transit here. - QSymbianSocketManager::instance().setDefaultConnection(0); - iConnection.Close(); newState(QNetworkSession::Closing); newState(QNetworkSession::Disconnected); - } else { - Cancel(); } QT_TRYCATCH_LEAVING(syncStateWithInterface()); return; @@ -1092,10 +1084,7 @@ void QNetworkSessionPrivateImpl::RunL() serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::InvalidConfigurationError; QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); QT_TRYCATCH_LEAVING(syncStateWithInterface()); break; case KErrCancel: // Connection attempt cancelled @@ -1114,10 +1103,7 @@ void QNetworkSessionPrivateImpl::RunL() iError = QNetworkSession::UnknownSessionError; } QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError)); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); QT_TRYCATCH_LEAVING(syncStateWithInterface()); break; } @@ -1204,10 +1190,7 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint serviceConfig = QNetworkConfiguration(); iError = QNetworkSession::SessionAbortedError; emit QNetworkSessionPrivate::error(iError); - if (ipConnectionNotifier) { - ipConnectionNotifier->StopNotifications(); - } - Cancel(); + closeHandles(); // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate iHandleStateNotificationsFromManager = true; emitSessionClosed = true; // Emit SessionClosed after state change has been reported diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 5aa142f..13980e9 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -150,6 +150,7 @@ private: bool easyWlanTrueIapId(TUint32 &trueIapId) const; #endif + void closeHandles(); private: // data SymbianEngine *engine; -- cgit v0.12 From 5a6365f14006ab50854e41a5927645c7e9966756 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Feb 2011 17:22:32 +0000 Subject: Refactor dangerous multiple inheritance QObject and CBase both expect to be the root class of the object hierarchy so it can cause problems if they are used in multiple inheritance. Refactored the CActive used for starting RConnection into a helper class. Reviewed-by: Markus Goetz --- .../bearer/symbian/qnetworksession_impl.cpp | 82 ++++++++++++++++------ src/plugins/bearer/symbian/qnetworksession_impl.h | 29 ++++++-- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 760c0e7..5325293 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -60,13 +60,12 @@ QT_BEGIN_NAMESPACE QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) -: CActive(CActive::EPriorityUserInput), engine(engine), - iSocketServ(qt_symbianGetSocketServer()), ipConnectionNotifier(0), +: engine(engine), iSocketServ(qt_symbianGetSocketServer()), + ipConnectionNotifier(0), ipConnectionStarter(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false), isOpening(false) { - CActiveScheduler::Add(this); #ifdef SNAP_FUNCTIONALITY_AVAILABLE iMobility = NULL; @@ -90,7 +89,8 @@ void QNetworkSessionPrivateImpl::closeHandles() #endif // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress - Cancel(); + delete ipConnectionStarter; + ipConnectionStarter = 0; //close any open connection (note Close twice is safe in case Cancel did it above) iConnection.Close(); @@ -397,9 +397,9 @@ void QNetworkSessionPrivateImpl::open() pref.SetIapId(symbianConfig->numericIdentifier()); #endif - if (!IsActive()) { - iConnection.Start(pref, iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(pref); } // Avoid flip flop of states if the configuration is already // active. IsOpen/opened() will indicate when ready. @@ -425,9 +425,9 @@ void QNetworkSessionPrivateImpl::open() #else TConnSnapPref snapPref(symbianConfig->numericIdentifier()); #endif - if (!IsActive()) { - iConnection.Start(snapPref, iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(snapPref); } // Avoid flip flop of states if the configuration is already // active. IsOpen/opened() will indicate when ready. @@ -436,9 +436,9 @@ void QNetworkSessionPrivateImpl::open() } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers(); - if (!IsActive()) { - iConnection.Start(iStatus); - SetActive(); + if (!ipConnectionStarter) { + ipConnectionStarter = new ConnectionStarter(*this, iConnection); + ipConnectionStarter->Start(); } newState(QNetworkSession::Connecting); } @@ -1007,13 +1007,14 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia return publicConfig; } -void QNetworkSessionPrivateImpl::RunL() +void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "RConnection::RunL with status code: " << iStatus.Int(); + << "RConnection::Start completed with status code: " << statusCode; #endif - TInt statusCode = iStatus.Int(); + delete ipConnectionStarter; + ipConnectionStarter = 0; switch (statusCode) { case KErrNone: // Connection created successfully @@ -1109,11 +1110,6 @@ void QNetworkSessionPrivateImpl::RunL() } } -void QNetworkSessionPrivateImpl::DoCancel() -{ - iConnection.Close(); -} - // Enters newState if feasible according to current state. // AccessPointId may be given as parameter. If it is zero, state-change is assumed to // concern this session's configuration. If non-zero, the configuration is looked up @@ -1500,6 +1496,50 @@ void ConnectionProgressNotifier::RunL() } } +ConnectionStarter::ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection) + : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection) +{ + CActiveScheduler::Add(this); +} + +ConnectionStarter::~ConnectionStarter() +{ + Cancel(); +} + +void ConnectionStarter::Start() +{ + if (!IsActive()) { + iConnection.Start(iStatus); + SetActive(); + } +} + +void ConnectionStarter::Start(TConnPref &pref) +{ + if (!IsActive()) { + iConnection.Start(pref, iStatus); + SetActive(); + } +} + +void ConnectionStarter::RunL() +{ + iOwner.ConnectionStartComplete(iStatus.Int()); + //note owner deletes on callback +} + +TInt ConnectionStarter::RunError(TInt err) +{ + qWarning() << "ConnectionStarter::RunError" << err; + return KErrNone; +} + +void ConnectionStarter::DoCancel() +{ + iConnection.Close(); +} + QT_END_NAMESPACE #endif //QT_NO_BEARERMANAGEMENT diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 13980e9..2dda456 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -68,11 +68,12 @@ QT_BEGIN_NAMESPACE class ConnectionProgressNotifier; +class ConnectionStarter; class SymbianEngine; typedef void (*TOpenCUnSetdefaultifFunction)(); -class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive +class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate #ifdef SNAP_FUNCTIONALITY_AVAILABLE , public MMobilityProtocolResp #endif @@ -126,7 +127,7 @@ public: // From MMobilityProtocolResp #endif protected: // From CActive - void RunL(); + void ConnectionStartComplete(TInt statusCode); void DoCancel(); private Q_SLOTS: @@ -165,12 +166,13 @@ private: // data mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; ConnectionProgressNotifier* ipConnectionNotifier; - + ConnectionStarter* ipConnectionStarter; + bool iHandleStateNotificationsFromManager; bool iFirstSync; bool iStoppedByUser; bool iClosedByUser; - + #ifdef SNAP_FUNCTIONALITY_AVAILABLE CActiveCommsMobilityApiExt* iMobility; #endif @@ -188,6 +190,7 @@ private: // data bool isOpening; friend class ConnectionProgressNotifier; + friend class ConnectionStarter; }; class ConnectionProgressNotifier : public CActive @@ -210,6 +213,24 @@ private: // Data }; +class ConnectionStarter : public CActive +{ +public: + ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection); + ~ConnectionStarter(); + + void Start(); + void Start(TConnPref &pref); +protected: + void RunL(); + TInt RunError(TInt err); + void DoCancel(); + +private: // Data + QNetworkSessionPrivateImpl &iOwner; + RConnection& iConnection; +}; + QT_END_NAMESPACE #endif //QNETWORKSESSION_IMPL_H -- cgit v0.12 From b2c41f756e1c0abd3f07a2e7256c3ba1be72832a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Feb 2011 10:39:28 +0000 Subject: Implement network session for HTTP backend Reviewed-by: Markus Goetz --- src/network/access/qhttpnetworkconnection.cpp | 23 ++++++++++++++++++++++ src/network/access/qhttpnetworkconnection_p.h | 10 ++++++++++ .../access/qhttpnetworkconnectionchannel.cpp | 9 +++++++++ .../access/qhttpnetworkconnectionchannel_p.h | 3 +++ 4 files changed, 45 insertions(+) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index e94b099..08a8016 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -117,9 +117,14 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate() void QHttpNetworkConnectionPrivate::init() { + Q_Q(QHttpNetworkConnection); for (int i = 0; i < channelCount; i++) { channels[i].setConnection(this->q_func()); channels[i].ssl = encrypt; +#ifndef QT_NO_BEARERMANAGEMENT + //push session down to channels + channels[i].networkSession = networkSession; +#endif channels[i].init(); } } @@ -819,6 +824,23 @@ void QHttpNetworkConnectionPrivate::readMoreLater(QHttpNetworkReply *reply) } } +#ifndef QT_NO_BEARERMANAGEMENT +QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent, QSharedPointer networkSession) + : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) +{ + Q_D(QHttpNetworkConnection); + d->networkSession = networkSession; + d->init(); +} + +QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, QObject *parent, QSharedPointer networkSession) + : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt)), parent) +{ + Q_D(QHttpNetworkConnection); + d->networkSession = networkSession; + d->init(); +} +#else QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent) : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) { @@ -832,6 +854,7 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS Q_D(QHttpNetworkConnection); d->init(); } +#endif QHttpNetworkConnection::~QHttpNetworkConnection() { diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index d4748c1..ad53dec 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -88,8 +89,13 @@ class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject Q_OBJECT public: +#ifndef QT_NO_BEARERMANAGEMENT + QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0, QSharedPointer networkSession = QSharedPointer()); + QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0, QSharedPointer networkSession = QSharedPointer()); +#else QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0); QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0); +#endif ~QHttpNetworkConnection(); //The hostname to which this is connected to. @@ -208,6 +214,10 @@ public: QList highPriorityQueue; QList lowPriorityQueue; +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession; +#endif + friend class QHttpNetworkConnectionChannel; }; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 079f608..3aaa11d 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -54,6 +54,10 @@ # include #endif +#ifndef QT_NO_BEARERMANAGEMENT +#include "private/qnetworksession_p.h" +#endif + QT_BEGIN_NAMESPACE // TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp @@ -91,6 +95,11 @@ void QHttpNetworkConnectionChannel::init() #else socket = new QTcpSocket; #endif +#ifndef QT_NO_BEARERMANAGEMENT + //push session down to socket + if (networkSession) + socket->setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // Set by QNAM anyway, but let's be safe here socket->setProxy(QNetworkProxy::NoProxy); diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 8cbc689..d86f95f 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -116,6 +116,9 @@ public: bool ignoreAllSslErrors; QList ignoreSslErrorsList; #endif +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession; +#endif // HTTP pipelining -> http://en.wikipedia.org/wiki/Http_pipelining enum PipeliningSupport { -- cgit v0.12 From 7f41f062e05c02ddf31ab6b81444f57904614f2a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Feb 2011 15:40:19 +0000 Subject: Fix duplicate calls to _q_startOperation Because of the shared QNetworkSession, we need to disconnect the signals before detaching from the session. Otherwise we may receive signals from an old session after switching configurations. Also, when a session is connected, we get both the state change (connected) and the opened signals from the session. This needs to be distinguished from the roaming->connected state change to avoid getting the networkSessionConnected signal twice. Reviewed-by: Markus Goetz Task-Number: QTBUG-16901 --- src/network/access/qnetworkaccessmanager.cpp | 36 ++++++++++++++++++++++++---- src/network/access/qnetworkaccessmanager_p.h | 2 ++ src/network/access/qnetworkreplyimpl.cpp | 2 +- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index f1c4447..00c5d26 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1344,8 +1344,25 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co initializeSession = false; - if (!config.isValid()) { - networkSession.clear(); + QSharedPointer newSession; + if (config.isValid()) + newSession = QSharedNetworkSessionManager::getSession(config); + + if (networkSession) { + //do nothing if new and old session are the same + if (networkSession == newSession) + return; + //disconnect from old session + QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); + QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); + } + + //switch to new session (null if config was invalid) + networkSession = newSession; + + if (!networkSession) { online = false; if (networkAccessible == QNetworkAccessManager::NotAccessible) @@ -1356,8 +1373,7 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co return; } - networkSession = QSharedNetworkSessionManager::getSession(config); - + //connect to new session QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection); //QueuedConnection is used to avoid deleting the networkSession inside its closed signal QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); @@ -1369,9 +1385,15 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co void QNetworkAccessManagerPrivate::_q_networkSessionClosed() { + Q_Q(QNetworkAccessManager); if (networkSession) { networkConfiguration = networkSession->configuration().identifier(); + //disconnect from old session + QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); + QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); networkSession.clear(); } } @@ -1380,8 +1402,12 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession { Q_Q(QNetworkAccessManager); - if (state == QNetworkSession::Connected) + //Do not emit the networkSessionConnected signal here, except for roaming -> connected + //transition, otherwise it is emitted twice in a row when opening a connection. + if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming) emit q->networkSessionConnected(); + lastSessionState = state; + if (online) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { online = false; diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index cf4d2f3..6dcb6da 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -77,6 +77,7 @@ public: #endif #ifndef QT_NO_BEARERMANAGEMENT networkSession(0), + lastSessionState(QNetworkSession::Invalid), networkAccessible(QNetworkAccessManager::Accessible), online(false), initializeSession(true), @@ -129,6 +130,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession; + QNetworkSession::State lastSessionState; QString networkConfiguration; QNetworkAccessManager::NetworkAccessibility networkAccessible; bool online; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 41a6c62..8f2e64e 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -74,7 +74,7 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() void QNetworkReplyImplPrivate::_q_startOperation() { // ensure this function is only being called once - if (state == Working) { + if (state == Working || state == Finished) { qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); return; } -- cgit v0.12 From b7667461ca80613d018f2258b54b5d1f9195e50d Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Tue, 22 Feb 2011 17:12:40 +0100 Subject: tst_qnetworkreply: Fix httpProxyCommands() on Windows. Reviewed-by: Markus Goetz --- src/network/socket/qhttpsocketengine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 4e628f3..6a025f2 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -743,7 +743,10 @@ void QHttpSocketEngine::emitReadNotification() { Q_D(QHttpSocketEngine); d->readNotificationActivated = true; - if (d->readNotificationEnabled && !d->readNotificationPending) { + // if there is a connection notification pending we have to emit the readNotification + // incase there is connection error. This is only needed for Windows, but it does not + // hurt in other cases. + if ((d->readNotificationEnabled && !d->readNotificationPending) || d->connectionNotificationPending) { d->readNotificationPending = true; QMetaObject::invokeMethod(this, "emitPendingReadNotification", Qt::QueuedConnection); } -- cgit v0.12 From d9753717f322ffdd59017e91541fe27201940169 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 23 Feb 2011 13:52:29 +0000 Subject: Fix compile errors in bearer tests Excluded maemo code from symbian builds. Reviewed-by: Markus Goetz --- tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp | 8 ++++---- .../tst_qnetworkconfigurationmanager.cpp | 8 ++++---- tests/auto/qnetworksession/test/tst_qnetworksession.cpp | 10 ++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp index adcfd93..c31eac7 100644 --- a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp +++ b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp @@ -52,7 +52,7 @@ */ #include -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) #include #include #endif @@ -73,7 +73,7 @@ private slots: void isRoamingAvailable(); private: -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) Maemo::IAPConf *iapconf; Maemo::IAPConf *iapconf2; Maemo::IAPConf *gprsiap; @@ -85,7 +85,7 @@ private: void tst_QNetworkConfiguration::initTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); iapconf->setValue("wlan_wepkey1", "connt"); @@ -158,7 +158,7 @@ void tst_QNetworkConfiguration::initTestCase() void tst_QNetworkConfiguration::cleanupTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf->clear(); delete iapconf; iapconf2->clear(); diff --git a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp index 443fd18..7787608 100644 --- a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp +++ b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp @@ -45,7 +45,7 @@ #include #include -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) #include #include #endif @@ -67,7 +67,7 @@ private slots: void configurationFromIdentifier(); private: -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) Maemo::IAPConf *iapconf; Maemo::IAPConf *iapconf2; Maemo::IAPConf *gprsiap; @@ -79,7 +79,7 @@ private: void tst_QNetworkConfigurationManager::initTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); iapconf->setValue("wlan_wepkey1", "connt"); @@ -153,7 +153,7 @@ void tst_QNetworkConfigurationManager::initTestCase() void tst_QNetworkConfigurationManager::cleanupTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf->clear(); delete iapconf; iapconf2->clear(); diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index 37fc9cd..154f790 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -48,7 +48,7 @@ #include #include -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) #include #include #endif @@ -60,8 +60,6 @@ QT_USE_NAMESPACE Q_DECLARE_METATYPE(QNetworkConfiguration) Q_DECLARE_METATYPE(QNetworkConfiguration::Type); -Q_DECLARE_METATYPE(QNetworkSession::State); -Q_DECLARE_METATYPE(QNetworkSession::SessionError); class tst_QNetworkSession : public QObject { @@ -107,7 +105,7 @@ private: int inProcessSessionManagementCount; -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) Maemo::IAPConf *iapconf; Maemo::IAPConf *iapconf2; Maemo::IAPConf *gprsiap; @@ -144,7 +142,7 @@ void tst_QNetworkSession::initTestCase() testsToRun["userChoiceSession"] = true; testsToRun["sessionOpenCloseStop"] = true; -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); iapconf->setValue("wlan_wepkey1", "connt"); @@ -230,7 +228,7 @@ void tst_QNetworkSession::cleanupTestCase() "inProcessSessionManagement()"); } -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf->clear(); delete iapconf; iapconf2->clear(); -- cgit v0.12 From dc01a7829255a41bda606fb59f546d599b6654ba Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 23 Feb 2011 14:36:07 +0000 Subject: Fix ignored messages in platformsocketengine test Reviewed-by: Markus Goetz --- tests/auto/platformsocketengine/tst_platformsocketengine.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp index 0ecb4ae..184371d 100644 --- a/tests/auto/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -68,10 +68,12 @@ #include #include #define PLATFORMSOCKETENGINE QSymbianSocketEngine +#define PLATFORMSOCKETENGINESTRING "QSymbianSocketEngine" #include #include #else #define PLATFORMSOCKETENGINE QNativeSocketEngine +#define PLATFORMSOCKETENGINESTRING "QNativeSocketEngine" #include #endif @@ -148,10 +150,10 @@ void tst_PlatformSocketEngine::construction() QVERIFY(socketDevice.peerPort() == 0); QVERIFY(socketDevice.error() == QAbstractSocket::UnknownSocketError); - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::bytesAvailable() was called in QAbstractSocket::UnconnectedState"); + QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::bytesAvailable() was called in QAbstractSocket::UnconnectedState"); QVERIFY(socketDevice.bytesAvailable() == 0); - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState"); + QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState"); QVERIFY(!socketDevice.hasPendingDatagrams()); } @@ -664,7 +666,7 @@ void tst_PlatformSocketEngine::invalidSend() PLATFORMSOCKETENGINE socket; QVERIFY(socket.initialize(QAbstractSocket::TcpSocket)); - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::writeDatagram() was" + QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::writeDatagram() was" " called by a socket other than QAbstractSocket::UdpSocket"); QCOMPARE(socket.writeDatagram("hei", 3, QHostAddress::LocalHost, 143), (qlonglong) -1); -- cgit v0.12 From 8d1ee3335f4c1bf262fb3a85fd4cc7e837129b8c Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 23 Feb 2011 15:28:54 +0000 Subject: bugfix: QDir::entryList(Files|Readable) not listing writable files Mistake in the qfilesystemiterator_symbian implementation. Readable without Writable was thought to mean show only read-only files, but this isn't the expected behaviour of QDir[Iterator] Added an autotest, as this was only covered by ssl tests in the network layer. Reviewed-by: joao --- src/corelib/io/qfilesystemiterator_symbian.cpp | 2 -- tests/auto/qdir/tst_qdir.cpp | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfilesystemiterator_symbian.cpp b/src/corelib/io/qfilesystemiterator_symbian.cpp index e316526..0adc26d 100644 --- a/src/corelib/io/qfilesystemiterator_symbian.cpp +++ b/src/corelib/io/qfilesystemiterator_symbian.cpp @@ -88,8 +88,6 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &path, QDir::Fil else if (symbianMask == 0) { if ((filters & QDir::PermissionMask) == QDir::Writable) symbianMask = KEntryAttMatchExclude | KEntryAttReadOnly; - else if ((filters & QDir::PermissionMask) == QDir::Readable) - symbianMask = KEntryAttMatchExclusive | KEntryAttReadOnly; } lastError = dirHandle.Open(fs, qt_QString2TPtrC(absPath), symbianMask); diff --git a/tests/auto/qdir/tst_qdir.cpp b/tests/auto/qdir/tst_qdir.cpp index 2fa0c24..21460be 100644 --- a/tests/auto/qdir/tst_qdir.cpp +++ b/tests/auto/qdir/tst_qdir.cpp @@ -571,6 +571,12 @@ void tst_QDir::entryList_data() << int(QDir::AllEntries | QDir::Writable) << int(QDir::Name) << filterLinks(QString(".,..,directory,linktodirectory.lnk,writable").split(',')); #endif + QTest::newRow("QDir::Files | QDir::Readable") << SRCDIR "entrylist/" << QStringList("*") + << int(QDir::Files | QDir::Readable) << int(QDir::Name) + << filterLinks(QString("file,linktofile.lnk,writable").split(',')); + QTest::newRow("QDir::Dirs | QDir::Readable") << SRCDIR "entrylist/" << QStringList("*") + << int(QDir::Dirs | QDir::Readable) << int(QDir::Name) + << filterLinks(QString(".,..,directory,linktodirectory.lnk").split(',')); QTest::newRow("Namefilters b*") << SRCDIR "entrylist/" << QStringList("d*") << int(QDir::NoFilter) << int(QDir::Name) << filterLinks(QString("directory").split(',')); -- cgit v0.12 From 6a8a70b434c61bc39e4aad0036012e78fa690b1d Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 23 Feb 2011 17:12:44 +0000 Subject: Fix qsslsocket test crashes Convert assertions to failure, increase heap size to allow creating 10MB buffers without std::bad_alloc exception or memory allocation error from openssl. Reviewed-by: Markus Goetz --- tests/auto/qsslsocket/qsslsocket.pro | 2 +- tests/auto/qsslsocket/tst_qsslsocket.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/qsslsocket/qsslsocket.pro b/tests/auto/qsslsocket/qsslsocket.pro index aeeae8f..154f9ca 100644 --- a/tests/auto/qsslsocket/qsslsocket.pro +++ b/tests/auto/qsslsocket/qsslsocket.pro @@ -23,7 +23,7 @@ wince* { DEPLOYMENT += certFiles } else:symbian { DEFINES += QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - TARGET.EPOCHEAPSIZE="0x100 0x1000000" + TARGET.EPOCHEAPSIZE="0x100 0x3000000" TARGET.CAPABILITY=NetworkServices certFiles.files = certs ssl.tar.gz diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp index 8177d29..9a98712 100644 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp @@ -541,7 +541,7 @@ void tst_QSslSocket::sslErrors() } #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - if (output.last() == QSslError::CertificateUntrusted) + if (output.count() && output.last() == QSslError::CertificateUntrusted) output.takeLast(); #endif QCOMPARE(output, expected); @@ -1417,8 +1417,8 @@ protected: // delayed start of encryption QTest::qSleep(100); QSslSocket *socket = server.socket; - Q_ASSERT(socket); - Q_ASSERT(socket->isValid()); + QVERIFY(socket); + QVERIFY(socket->isValid()); socket->ignoreSslErrors(); socket->startServerEncryption(); if (!socket->waitForEncrypted(2000)) -- cgit v0.12 From 88e192419ed928be1239d7a928336332f1d521f4 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 23 Feb 2011 18:20:14 +0000 Subject: Fix symbian test failures for qsslsocket Increased timeout on some unstable test cases. Added a Q_EXPECT_FAIL if we can't connect to a server which is inside firewall. Reviewed-by: Markus Goetz --- tests/auto/qsslsocket/tst_qsslsocket.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp index 9a98712..1c34759 100644 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp @@ -519,6 +519,7 @@ void tst_QSslSocket::sslErrors_data() << (SslErrorList() << QSslError::HostNameMismatch << QSslError::SelfSignedCertificate); + //note this test case does not work outside Nokia network QTest::newRow("imap.trolltech.com") << "imap.trolltech.com" << 993 @@ -533,6 +534,8 @@ void tst_QSslSocket::sslErrors() QSslSocketPtr socket = newSocket(); socket->connectToHostEncrypted(host, port); + if (!socket->waitForConnected()) + QEXPECT_FAIL("imap.trolltech.com", "server not open to internet", Continue); socket->waitForEncrypted(5000); SslErrorList output; @@ -650,7 +653,7 @@ void tst_QSslSocket::sessionCipher() connect(socket, SIGNAL(sslErrors(QList)), this, SLOT(ignoreErrorSlot())); QVERIFY(socket->sessionCipher().isNull()); socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */); - QVERIFY(socket->waitForConnected(5000)); + QVERIFY(socket->waitForConnected(10000)); QVERIFY(socket->sessionCipher().isNull()); socket->startClientEncryption(); QVERIFY(socket->waitForEncrypted(5000)); @@ -684,7 +687,7 @@ void tst_QSslSocket::localCertificate() socket->setPrivateKey(QLatin1String(SRCDIR "certs/fluke.key")); socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted(5000)); + QVERIFY(socket->waitForEncrypted(10000)); } void tst_QSslSocket::mode() @@ -1608,7 +1611,7 @@ void tst_QSslSocket::disconnectFromHostWhenConnecting() QCOMPARE(state, socket->state()); QVERIFY(socket->state() == QAbstractSocket::HostLookupState || socket->state() == QAbstractSocket::ConnectingState); - QVERIFY(socket->waitForDisconnected(5000)); + QVERIFY(socket->waitForDisconnected(10000)); QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState); // we did not call close, so the socket must be still open QVERIFY(socket->isOpen()); -- cgit v0.12 From a722a716641d596b9a799e776e81167a47a261fa Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Feb 2011 16:52:04 +0000 Subject: Fix for read on "connected" UDP sockets Symbian API RecvOneOrMore only supports stream oriented sockets. So for UDP we use RecvFrom instead and discard the source address. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index b9537c1..e3b4a09 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1049,10 +1049,16 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) TPtr8 buffer((TUint8*)data, (int)maxSize); TSockXfrLength received = 0; TRequestStatus status; - d->nativeSocket.RecvOneOrMore(buffer, 0, status, received); + TSockAddr dummy; + if (d->socketType == QAbstractSocket::UdpSocket) { + //RecvOneOrMore() can only be used with stream-interfaced connected sockets; datagram interface sockets will return KErrNotSupported. + d->nativeSocket.RecvFrom(buffer, dummy, 0, status); + } else { + d->nativeSocket.RecvOneOrMore(buffer, 0, status, received); + } User::WaitForRequest(status); //Non blocking receive TInt err = status.Int(); - int r = received(); + int r = buffer.Length(); if (err == KErrWouldBlock) { // No data was available for reading @@ -1064,9 +1070,9 @@ qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize) } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEngine::read(%p \"%s\", %llu) == %i", + qDebug("QSymbianSocketEngine::read(%p \"%s\", %llu) == %i (err = %d)", data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), - maxSize, r); + maxSize, r, err); #endif return qint64(r); -- cgit v0.12 From 37b6d6ef16606c11ba46ef4cb7c96e0989e78d7e Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Feb 2011 17:24:50 +0000 Subject: Make socks5 socket engine push session down to real sockets This ensures the specified QNetworkSession from the QNetworkAccessManager is used to route the packets, when using a SOCKS proxy. Reviewed-by: Markus Goetz --- src/network/socket/qsocks5socketengine.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index ab3d260..91dfdf3 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -556,6 +556,7 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode) udpData = new QSocks5UdpAssociateData; data = udpData; udpData->udpSocket = new QUdpSocket(q); + udpData->udpSocket->setProperty("_q_networksession", q->property("_q_networksession")); udpData->udpSocket->setProxy(QNetworkProxy::NoProxy); QObject::connect(udpData->udpSocket, SIGNAL(readyRead()), q, SLOT(_q_udpSocketReadNotification()), @@ -567,6 +568,7 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode) } data->controlSocket = new QTcpSocket(q); + data->controlSocket->setProperty("_q_networksession", q->property("_q_networksession")); data->controlSocket->setProxy(QNetworkProxy::NoProxy); QObject::connect(data->controlSocket, SIGNAL(connected()), q, SLOT(_q_controlSocketConnected()), Qt::DirectConnection); @@ -1376,6 +1378,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port) d->udpData->associatePort = d->localPort; d->localPort = 0; QUdpSocket dummy; + dummy.setProperty("_q_networksession", property("_q_networksession")); dummy.setProxy(QNetworkProxy::NoProxy); if (!dummy.bind() || writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0 -- cgit v0.12 From 6c57e9a681bf82b9bcb4b0659d151a76ecd1455e Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Feb 2011 17:59:40 +0000 Subject: Change an error code for behavioural compatibility qtcpsocket autotest checks for a specific error Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index e3b4a09..5dec4ee 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -368,7 +368,7 @@ bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::Soc if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) { qWarning("QSymbianSocketEngine::initialize - socket descriptor not found"); - d->setError(QAbstractSocket::SocketResourceError, + d->setError(QAbstractSocket::UnsupportedSocketOperationError, QSymbianSocketEnginePrivate::InvalidSocketErrorString); return false; } -- cgit v0.12 From 8d74ddeba364785bf3d0d0659e5bb91ab950540d Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Feb 2011 18:01:58 +0000 Subject: Do not error socket when writeDatagram would block When starting a connection implicitly, datagrams fail with KErrWouldBlock on S60 5.0 and earlier. On symbian 3, they are dropped without error, but the bytes written is set to 0. Due to an apparent bug in symbian, the first packet is failed/dropped on a UDP socket even if the bearer is up due to existing TCP connection. With blocking sockets or explicit RConnection usage, this doesn't happen. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 5dec4ee..18ce5e0 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -845,8 +845,19 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, User::WaitForRequest(status); //Non blocking send TInt err = status.Int(); +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug("QSymbianSocketEngine::writeDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli (err=%d)", data, + qt_prettyDebug(data, qMin(len, 16), len).data(), len, host.toString().toLatin1().constData(), + port, (qint64) sentBytes(), err); +#endif + if (err) { switch (err) { + case KErrWouldBlock: + // do not error the socket. (otherwise socket layer is reset) + // On symbian^1 and earlier, KErrWouldBlock is returned when interface is not up yet + // On symbian^3, KErrNone is returned but sentBytes = 0 + return 0; case KErrTooBig: d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString); break; @@ -855,13 +866,7 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, } } -#if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QSymbianSocketEnginePrivate::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, - qt_prettyDebug(data, qMin(len, 16), len).data(), len, host.toString().toLatin1().constData(), - port, (qint64) sentBytes()); -#endif - - return qint64(sentBytes()); + return (err < 0) ? -1 : len; } // FIXME check where the native socket engine called that.. -- cgit v0.12 From 45531aceba4d0b2114942c49f4c256b70af58cf8 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Feb 2011 18:22:06 +0000 Subject: Move UDP send length workaround from generic code to symbian engine Symbian workarounds are better in the symbian socket engine than generic layer, where this is possible. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 9 ++++++++- src/network/socket/qudpsocket.cpp | 10 ---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 18ce5e0..dac50d4 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -864,9 +864,16 @@ qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len, default: d->setError(QAbstractSocket::NetworkError, d->SendDatagramErrorString); } + return -1; } - return (err < 0) ? -1 : len; + if (QSysInfo::s60Version() <= QSysInfo::SV_S60_5_0) { + // This is evil hack, but for some reason native RSocket::SendTo returns 0, + // for large datagrams (such as 600 bytes). Based on comments from Open C team + // this should happen only in platforms <= S60 5.0. + return len; + } + return sentBytes(); } // FIXME check where the native socket engine called that.. diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 6a62b12..4334f68 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -504,16 +504,6 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre return -1; qint64 sent = d->socketEngine->writeDatagram(data, size, address, port); -#ifdef Q_OS_SYMBIAN - if( QSysInfo::s60Version() <= QSysInfo::SV_S60_5_0 ) { - // This is evil hack, but for some reason native RSocket::SendTo returns 0, - // for large datagrams (such as 600 bytes). Based on comments from Open C team - // this should happen only in platforms <= S60 5.0. - // As an workaround, we just set sent = size - if( sent == 0 ) - sent = size; - } -#endif d->cachedSocketDescriptor = d->socketEngine->socketDescriptor(); if (sent >= 0) { -- cgit v0.12