From 3a5603966467a878e5b305517598589590cb8b10 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 21 Sep 2010 15:20:10 +0100 Subject: Skeleton code for symbian native socket engine Taken the unix native socket engine, and converted each call from the posix version to the symbian version. There are many TODOs as this is quite incomplete. Reviewed-By: Markus Goetz --- src/network/socket/qnativesocketengine_p.h | 9 + src/network/socket/qnativesocketengine_symbian.cpp | 756 +++++++++++++++++++++ src/network/socket/socket.pri | 4 +- 3 files changed, 768 insertions(+), 1 deletion(-) create mode 100644 src/network/socket/qnativesocketengine_symbian.cpp diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 9baacf0..72ebd9f 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -63,6 +63,7 @@ #ifdef Q_OS_SYMBIAN #include #include +#include #endif QT_BEGIN_NAMESPACE @@ -196,6 +197,11 @@ public: ~QNativeSocketEnginePrivate(); int socketDescriptor; +#ifdef Q_OS_SYMBIAN + mutable RSocket nativeSocket; + RSocketServ socketServer; //TODO: shared ref + RConnection connection; //TODO: shared ref +#endif QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; @@ -233,6 +239,9 @@ public: UnknownSocketErrorString = -1 }; +#ifdef Q_OS_SYMBIAN + void setError(TInt symbianError); +#endif void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; // native functions diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp new file mode 100644 index 0000000..f2aeee9 --- /dev/null +++ b/src/network/socket/qnativesocketengine_symbian.cpp @@ -0,0 +1,756 @@ +/**************************************************************************** +** +** 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 +#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 + +static void qt_ignore_sigpipe() +{ +#ifndef Q_NO_POSIX_SIGNALS + // Set to ignore SIGPIPE once only. + static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0); + if (atom.testAndSetRelaxed(0, 1)) { + struct sigaction noaction; + memset(&noaction, 0, sizeof(noaction)); + noaction.sa_handler = SIG_IGN; + ::sigaction(SIGPIPE, &noaction, 0); + } +#else + // Posix signals are not supported by the underlying platform + // so we don't need to ignore sigpipe signal explicitly +#endif +} + +/* + Extracts the port and address from a sockaddr, and stores them in + \a port and \a addr if they are non-null. +*/ +static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr) +{ +#if !defined(QT_NO_IPV6) + if (s->a.sa_family == AF_INET6) { + Q_IPV6ADDR tmp; + memcpy(&tmp, &s->a6.sin6_addr, sizeof(tmp)); + if (addr) { + QHostAddress tmpAddress; + tmpAddress.setAddress(tmp); + *addr = tmpAddress; +#ifndef QT_NO_IPV6IFNAME + char scopeid[IFNAMSIZ]; + if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) { + addr->setScopeId(QLatin1String(scopeid)); + } else +#endif + addr->setScopeId(QString::number(s->a6.sin6_scope_id)); + } + if (port) + *port = ntohs(s->a6.sin6_port); + return; + } +#endif + if (port) + *port = ntohs(s->a4.sin_port); + if (addr) { + QHostAddress tmpAddress; + tmpAddress.setAddress(ntohl(s->a4.sin_addr.s_addr)); + *addr = tmpAddress; + } +} + +static inline void qt_socket_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 + char scopeid[IFNAMSIZ]; + //TODO: rather than using posix api, the symbian way is + //to use GetOpt with TSoInetIfQuery and KSoInetIfQueryByIndex + //which means this should be in a member function to have access to the nativeSocket + if (::if_indextoname(a.Scope(), scopeid)) { + addr->setScopeId(QLatin1String(scopeid)); + } 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()); //TODO: byte order ok? + *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; + } + + socketDescriptor = nativeSocket.SubSessionHandle(); //TODO + 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: + n = SO_BROADCAST; //TODO + break; + case QNativeSocketEngine::AddressReusable: + n = SO_REUSEADDR; //TODO + break; + case QNativeSocketEngine::BindExclusively: + return true; + case QNativeSocketEngine::ReceiveOutOfBandData: + n = SO_OOBINLINE; //TODO + 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: + n = SO_BROADCAST; //TODO + break; + case QNativeSocketEngine::NonBlockingSocketOption: + n = KSONonBlockingIO; + break; + case QNativeSocketEngine::AddressReusable: + n = SO_REUSEADDR; //TODO + break; + case QNativeSocketEngine::BindExclusively: + return true; + case QNativeSocketEngine::ReceiveOutOfBandData: + n = SO_OOBINLINE; //TODO + break; + case QNativeSocketEngine::LowDelayOption: + level = KSolInetTcp; + n = KSoTcpNoDelay; + break; + case QNativeSocketEngine::KeepAliveOption: + level = KSolInetTcp; + n = KSoTcpKeepAlive; + break; + } + + return (KErrNone == nativeSocket.SetOpt(n, level, v)); +} + +static TInetAddr qt_QHostAddressToTInetAddr(const QHostAddress &addr) +{ + TInetAddr nativeAddr; +#if !defined(QT_NO_IPV6) + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { +#ifndef QT_NO_IPV6IFNAME + nativeAddr.SetScope(::if_nametoindex(addr.scopeId().toLatin1().data())); //TODO - if_nametoindex +#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()); + } + return nativeAddr; +} + +bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) +{ +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); +#endif + + TInetAddr nativeAddr = qt_QHostAddressToTInetAddr(addr); + nativeAddr.SetPort(port); + //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 = qt_QHostAddressToTInetAddr(address); + nativeAddr.SetPort(port); + + 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; + } + + return blankSocket.SubSessionHandle(); +} + +qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const +{ + int nbytes = 0; + qint64 available = 0; + 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)? +} + +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) { + qt_socket_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 = qt_QHostAddressToTInetAddr(host); + TSockXfrLength sentBytes; + addr.SetPort(port); + 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; + + //TODO: work out how to initialise nativeSocket from socketDescriptor + + // Determine local address + TSockAddr addr; + nativeSocket.LocalName(addr); + qt_socket_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); + qt_socket_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(); +} + +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 +{ +//TODO: implement +} + +int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) const +{ + //TODO: implement +} + +QT_END_NAMESPACE diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index 2bafe13..f2262fe 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -25,7 +25,9 @@ SOURCES += socket/qabstractsocketengine.cpp \ socket/qlocalsocket.cpp \ socket/qlocalserver.cpp -unix:SOURCES += socket/qnativesocketengine_unix.cpp \ +unix:!symbian:SOURCES += socket/qnativesocketengine_unix.cpp +symbian:SOURCES += socket/qnativesocketengine_symbian.cpp +unix:SOURCES += \ socket/qlocalsocket_unix.cpp \ socket/qlocalserver_unix.cpp unix:HEADERS += \ -- cgit v0.12 From 5c7c12602f10be7625ee38efb31e1a8b5cb66c5b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 21 Sep 2010 17:42:14 +0100 Subject: Prototype socket manager To enable passing socket handles around as integers, need a two way mapping with RSocket. It's in corelib because of QSocketNotifier. This is also a convenient place to host the global RSocketServ session. Reviewed-By: Markus Goetz --- src/corelib/io/io.pri | 2 +- src/corelib/kernel/qcore_symbian_p.cpp | 72 ++++++++++++++++++++++++++++++++++ src/corelib/kernel/qcore_symbian_p.h | 67 +++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index cfb40bc..6cf55e7 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -95,6 +95,6 @@ win32 { SOURCES += io/qfilesystemwatcher_symbian.cpp HEADERS += io/qfilesystemwatcher_symbian_p.h INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE - LIBS += -lplatformenv + LIBS += -lplatformenv -lesock } } diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index df1c1ef..29996a4 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -210,4 +210,76 @@ Q_CORE_EXPORT RFs& qt_s60GetRFs() return qt_s60_RFsSession()->GetRFs(); } +QSymbianSocketManager::QSymbianSocketManager() : + iNextSocket(0) +{ + qt_symbian_throwIfError(iSocketServ.Connect()); + qt_symbian_throwIfError(iSocketServ.ShareAuto()); +} + +QSymbianSocketManager::~QSymbianSocketManager() +{ + iSocketServ.Close(); + if(!socketMap.isEmpty()) { + qWarning("leaked %d sockets on exit", socketMap.count()); + } +} + +RSocketServ& QSymbianSocketManager::getSocketServer() { + return iSocketServ; +} + +int QSymbianSocketManager::addSocket(RSocket* sock) { + QMutexLocker l(&iMutex); + Q_ASSERT(!socketMap.contains(sock)); + if(socketMap.contains(sock)) + return socketMap.value(sock); + // allocate socket number + int guard = 0; + while(reverseSocketMap.contains(iNextSocket)) { + iNextSocket++; + iNextSocket %= max_sockets; + guard++; + if(guard > max_sockets) + return -1; + } + int id = iNextSocket; + + socketMap[sock] = id; + reverseSocketMap[id] = sock; + return id + socket_offset; +} + +bool QSymbianSocketManager::removeSocket(RSocket* sock) { + QMutexLocker l(&iMutex); + if(!socketMap.contains(sock)) + return false; + int id = socketMap.value(sock); + socketMap.remove(sock); + reverseSocketMap.remove(id); + return true; +} + +int QSymbianSocketManager::lookupSocket(RSocket* sock) const { + QMutexLocker l(&iMutex); + if(!socketMap.contains(sock)) + return -1; + int id = socketMap.value(sock); + return id + socket_offset; +} + +RSocket* QSymbianSocketManager::lookupSocket(int fd) const { + QMutexLocker l(&iMutex); + int id = fd + socket_offset; + if(!reverseSocketMap.contains(id)) + return 0; + return reverseSocketMap.value(id); +} + +Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager); + +QSymbianSocketManager& QSymbianSocketManager::instance() +{ + return *(qt_symbianSocketManager()); +} QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index 4a515ce..b6cba6e 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -55,10 +55,12 @@ #include #include +#include #include #include #include #include +#include #define QT_LSTRING2(x) L##x #define QT_LSTRING(x) QT_LSTRING2(x) @@ -154,10 +156,75 @@ enum S60PluginFuncOrdinals Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal); Q_CORE_EXPORT RFs& qt_s60GetRFs(); +Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer(); // Defined in qlocale_symbian.cpp. Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code); +/*! + \internal + This class exists in QtCore for the benefit of QSocketNotifier, which uses integer + file descriptors in its public API. + So we need a way to map between int and RSocket. + Additionally, it is used to host the global RSocketServ session +*/ +class Q_CORE_EXPORT QSymbianSocketManager +{ +public: + QSymbianSocketManager(); + ~QSymbianSocketManager(); + + /*! + \internal + \return handle to the socket server + */ + RSocketServ& getSocketServer(); + /*! + \internal + Adds a symbian socket to the global map + \param an open socket + \return pseudo file descriptor, -1 if out of resources + */ + int addSocket(RSocket *sock); + /*! + \internal + Removes a symbian socket from the global map + \param an open socket + \return true if the socket was in the map + */ + bool removeSocket(RSocket *sock); + /*! + \internal + Get pseudo file descriptor for a socket + \param an open socket + \return integer handle, or -1 if not in map + */ + int lookupSocket(RSocket *sock) const; + /*! + \internal + Get socket for a pseudo file descriptor + \param an open socket fd + \return socket handle or NULL if not in map + */ + RSocket *lookupSocket(int fd) const; + + /*! + \internal + Gets a reference to the singleton socket manager + */ + static QSymbianSocketManager& instance(); +private: + int allocateSocket(); + + const static int max_sockets = 0x20000; //covers all TCP and UDP ports, probably run out of memory first + const static int socket_offset = 0x40000000; //hacky way of separating sockets from file descriptors + int iNextSocket; + QHash socketMap; + QHash reverseSocketMap; + mutable QMutex iMutex; + RSocketServ iSocketServ; +}; + QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12 From 9470dfb8b116cde0d08670d05ded530bad264c6c Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 22 Sep 2010 12:04:01 +0100 Subject: Address some of the easier TODOs in native socket engine Reviewed-By: Markus Goetz --- src/network/socket/qnativesocketengine_p.h | 4 + src/network/socket/qnativesocketengine_symbian.cpp | 187 +++++++++++---------- 2 files changed, 105 insertions(+), 86 deletions(-) diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 72ebd9f..ceecfeb 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -64,6 +64,7 @@ #include #include #include +#include #endif QT_BEGIN_NAMESPACE @@ -201,6 +202,7 @@ public: mutable RSocket nativeSocket; RSocketServ socketServer; //TODO: shared ref RConnection connection; //TODO: shared ref + mutable RTimer selectTimer; #endif QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; @@ -240,6 +242,8 @@ public: }; #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; diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp index f2aeee9..788e58a 100644 --- a/src/network/socket/qnativesocketengine_symbian.cpp +++ b/src/network/socket/qnativesocketengine_symbian.cpp @@ -48,6 +48,7 @@ #include "qvarlengtharray.h" #include #include +#include #ifndef QT_NO_IPV6IFNAME #include #endif @@ -93,60 +94,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) } #endif -static void qt_ignore_sigpipe() -{ -#ifndef Q_NO_POSIX_SIGNALS - // Set to ignore SIGPIPE once only. - static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0); - if (atom.testAndSetRelaxed(0, 1)) { - struct sigaction noaction; - memset(&noaction, 0, sizeof(noaction)); - noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); - } -#else - // Posix signals are not supported by the underlying platform - // so we don't need to ignore sigpipe signal explicitly -#endif -} - -/* - Extracts the port and address from a sockaddr, and stores them in - \a port and \a addr if they are non-null. -*/ -static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr) -{ -#if !defined(QT_NO_IPV6) - if (s->a.sa_family == AF_INET6) { - Q_IPV6ADDR tmp; - memcpy(&tmp, &s->a6.sin6_addr, sizeof(tmp)); - if (addr) { - QHostAddress tmpAddress; - tmpAddress.setAddress(tmp); - *addr = tmpAddress; -#ifndef QT_NO_IPV6IFNAME - char scopeid[IFNAMSIZ]; - if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) { - addr->setScopeId(QLatin1String(scopeid)); - } else -#endif - addr->setScopeId(QString::number(s->a6.sin6_scope_id)); - } - if (port) - *port = ntohs(s->a6.sin6_port); - return; - } -#endif - if (port) - *port = ntohs(s->a4.sin_port); - if (addr) { - QHostAddress tmpAddress; - tmpAddress.setAddress(ntohl(s->a4.sin_addr.s_addr)); - *addr = tmpAddress; - } -} - -static inline void qt_socket_getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) +void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) { #if !defined(QT_NO_IPV6) if (a.Family() == KAfInet6) { @@ -157,13 +105,12 @@ static inline void qt_socket_getPortAndAddress(const TInetAddr& a, quint16 *port tmpAddress.setAddress(tmp); *addr = tmpAddress; #ifndef QT_NO_IPV6IFNAME - char scopeid[IFNAMSIZ]; - //TODO: rather than using posix api, the symbian way is - //to use GetOpt with TSoInetIfQuery and KSoInetIfQueryByIndex - //which means this should be in a member function to have access to the nativeSocket - if (::if_indextoname(a.Scope(), scopeid)) { - addr->setScopeId(QLatin1String(scopeid)); - } else + 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())); } @@ -176,7 +123,7 @@ static inline void qt_socket_getPortAndAddress(const TInetAddr& a, quint16 *port *port = a.Port(); if (addr) { QHostAddress tmpAddress; - tmpAddress.setAddress(a.Address()); //TODO: byte order ok? + tmpAddress.setAddress(a.Address()); *addr = tmpAddress; } } @@ -218,7 +165,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return false; } - socketDescriptor = nativeSocket.SubSessionHandle(); //TODO + socketDescriptor = QSymbianSocketManager::instance().addSocket(&nativeSocket); return true; } @@ -245,15 +192,16 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co n = KSONonBlockingIO; break; case QNativeSocketEngine::BroadcastSocketOption: - n = SO_BROADCAST; //TODO - break; + return true; //symbian doesn't support or require this option case QNativeSocketEngine::AddressReusable: - n = SO_REUSEADDR; //TODO + level = KSolInetIp; + n = KSoReuseAddr; break; case QNativeSocketEngine::BindExclusively: return true; case QNativeSocketEngine::ReceiveOutOfBandData: - n = SO_OOBINLINE; //TODO + level = KSolInetTcp; + n = KSoTcpOobInline; break; case QNativeSocketEngine::LowDelayOption: level = KSolInetTcp; @@ -297,18 +245,19 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt n = KSOSendBuf; break; case QNativeSocketEngine::BroadcastSocketOption: - n = SO_BROADCAST; //TODO - break; + return true; case QNativeSocketEngine::NonBlockingSocketOption: n = KSONonBlockingIO; break; case QNativeSocketEngine::AddressReusable: - n = SO_REUSEADDR; //TODO + level = KSolInetIp; + n = KSoReuseAddr; break; case QNativeSocketEngine::BindExclusively: return true; case QNativeSocketEngine::ReceiveOutOfBandData: - n = SO_OOBINLINE; //TODO + level = KSolInetTcp; + n = KSoTcpOobInline; break; case QNativeSocketEngine::LowDelayOption: level = KSolInetTcp; @@ -323,13 +272,19 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return (KErrNone == nativeSocket.SetOpt(n, level, v)); } -static TInetAddr qt_QHostAddressToTInetAddr(const QHostAddress &addr) +void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) { - TInetAddr nativeAddr; + nativeAddr.SetPort(port); #if !defined(QT_NO_IPV6) if (addr.protocol() == QAbstractSocket::IPv6Protocol) { #ifndef QT_NO_IPV6IFNAME - nativeAddr.SetScope(::if_nametoindex(addr.scopeId().toLatin1().data())); //TODO - if_nametoindex + 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 @@ -344,7 +299,6 @@ static TInetAddr qt_QHostAddressToTInetAddr(const QHostAddress &addr) } else { qWarning("unsupported network protocol (%d)", addr.protocol()); } - return nativeAddr; } bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) @@ -353,8 +307,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); #endif - TInetAddr nativeAddr = qt_QHostAddressToTInetAddr(addr); - nativeAddr.SetPort(port); + 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); @@ -413,8 +367,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) { - TInetAddr nativeAddr = qt_QHostAddressToTInetAddr(address); - nativeAddr.SetPort(port); + TInetAddr nativeAddr; + setPortAndAddress(nativeAddr, port, address); TInt err = nativeSocket.Bind(nativeAddr); @@ -535,7 +489,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS if (status.Int()) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); } else if (port || address) { - qt_socket_getPortAndAddress(addr, port, address); + getPortAndAddress(addr, port, address); } #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -555,9 +509,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l const QHostAddress &host, quint16 port) { TPtrC8 buffer((TUint8*)data, (int)len); - TInetAddr addr = qt_QHostAddressToTInetAddr(host); + TInetAddr addr; + setPortAndAddress(addr, port, host); TSockXfrLength sentBytes; - addr.SetPort(port); TRequestStatus status; //TODO: OMG sync send! nativeSocket.SendTo(buffer, addr, 0, status, sentBytes); User::WaitForRequest(status); @@ -592,12 +546,17 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() if (socketDescriptor == -1) return false; - //TODO: work out how to initialise nativeSocket from socketDescriptor + if (!nativeSocket.SubSessionHandle()) { + RSocket *s = QSymbianSocketManager::instance().lookupSocket(socketDescriptor); + if (!s) + return false; + nativeSocket = *s; //TODO: badwrongfun (address is different, so this is broken) + } // Determine local address TSockAddr addr; nativeSocket.LocalName(addr); - qt_socket_getPortAndAddress(addr, &localPort, &localAddress); + getPortAndAddress(addr, &localPort, &localAddress); // Determine protocol family switch (addr.Family()) { @@ -616,7 +575,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() // Determine the remote address nativeSocket.RemoteName(addr); - qt_socket_getPortAndAddress(addr, &peerPort, &peerAddress); + getPortAndAddress(addr, &peerPort, &peerAddress); // Determine the socket type (UDP/TCP) TProtocolDesc protocol; @@ -662,6 +621,7 @@ void QNativeSocketEnginePrivate::nativeClose() //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? nativeSocket.Close(); + QSymbianSocketManager::instance().removeSocket(&nativeSocket); } qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) @@ -744,13 +704,68 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const { -//TODO: implement + 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; + } + + 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; } QT_END_NAMESPACE -- cgit v0.12 From de55502a960a1044770aa840d7e443343b3c436b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 6 Dec 2010 12:36:13 +0000 Subject: Add socket manager to corelib This class stores socket handles so they can be passed around as integers. Also, it owns the global RSocketServ used throughout the application. Reason for this not being in QtNetwork is that QtCore exports some socket related classes. Reviewed-by: Markus Goetz --- src/corelib/kernel/qcore_symbian_p.cpp | 27 +++++++++++++++++++++------ src/corelib/kernel/qcore_symbian_p.h | 34 +++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 29996a4..809dc30 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -203,6 +203,11 @@ private: RFs iFs; }; +uint qHash(const RSubSessionBase& key) +{ + return qHash(key.SubSessionHandle()); +} + Q_GLOBAL_STATIC(QS60RFsSession, qt_s60_RFsSession); Q_CORE_EXPORT RFs& qt_s60GetRFs() @@ -229,7 +234,8 @@ RSocketServ& QSymbianSocketManager::getSocketServer() { return iSocketServ; } -int QSymbianSocketManager::addSocket(RSocket* sock) { +int QSymbianSocketManager::addSocket(const RSocket& socket) { + QHashableSocket sock(static_cast(socket)); QMutexLocker l(&iMutex); Q_ASSERT(!socketMap.contains(sock)); if(socketMap.contains(sock)) @@ -250,7 +256,8 @@ int QSymbianSocketManager::addSocket(RSocket* sock) { return id + socket_offset; } -bool QSymbianSocketManager::removeSocket(RSocket* sock) { +bool QSymbianSocketManager::removeSocket(const RSocket &socket) { + QHashableSocket sock(static_cast(socket)); QMutexLocker l(&iMutex); if(!socketMap.contains(sock)) return false; @@ -260,7 +267,8 @@ bool QSymbianSocketManager::removeSocket(RSocket* sock) { return true; } -int QSymbianSocketManager::lookupSocket(RSocket* sock) const { +int QSymbianSocketManager::lookupSocket(const RSocket& socket) const { + QHashableSocket sock(static_cast(socket)); QMutexLocker l(&iMutex); if(!socketMap.contains(sock)) return -1; @@ -268,12 +276,13 @@ int QSymbianSocketManager::lookupSocket(RSocket* sock) const { return id + socket_offset; } -RSocket* QSymbianSocketManager::lookupSocket(int fd) const { +bool QSymbianSocketManager::lookupSocket(int fd, RSocket& socket) const { QMutexLocker l(&iMutex); int id = fd + socket_offset; if(!reverseSocketMap.contains(id)) - return 0; - return reverseSocketMap.value(id); + return false; + socket = reverseSocketMap.value(id); + return true; } Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager); @@ -282,4 +291,10 @@ QSymbianSocketManager& QSymbianSocketManager::instance() { return *(qt_symbianSocketManager()); } + +Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer() +{ + return QSymbianSocketManager::instance().getSocketServer(); +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index b6cba6e..8ffa247 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -161,6 +161,25 @@ Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer(); // Defined in qlocale_symbian.cpp. Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code); +//Wrapper for RSocket so it can be used as a key in QHash or QMap +class QHashableSocket : public RSocket +{ +public: + bool operator==(const QHashableSocket &other) const + { + return SubSessionHandle() == other.SubSessionHandle() + && Session().Handle() == other.Session().Handle(); + } + bool operator<(const QHashableSocket &other) const + { + if(Session().Handle() == other.Session().Handle()) + return SubSessionHandle() < other.SubSessionHandle(); + return Session().Handle() < other.Session().Handle(); + } +}; + +uint qHash(const RSubSessionBase& key); + /*! \internal This class exists in QtCore for the benefit of QSocketNotifier, which uses integer @@ -185,28 +204,29 @@ public: \param an open socket \return pseudo file descriptor, -1 if out of resources */ - int addSocket(RSocket *sock); + int addSocket(const RSocket &sock); /*! \internal Removes a symbian socket from the global map \param an open socket \return true if the socket was in the map */ - bool removeSocket(RSocket *sock); + bool removeSocket(const RSocket &sock); /*! \internal Get pseudo file descriptor for a socket \param an open socket \return integer handle, or -1 if not in map */ - int lookupSocket(RSocket *sock) const; + int lookupSocket(const RSocket &sock) const; /*! \internal Get socket for a pseudo file descriptor \param an open socket fd - \return socket handle or NULL if not in map + \param sock (out) socket handle + \return true on success or false if not in map */ - RSocket *lookupSocket(int fd) const; + bool lookupSocket(int fd, RSocket& sock) const; /*! \internal @@ -219,8 +239,8 @@ private: const static int max_sockets = 0x20000; //covers all TCP and UDP ports, probably run out of memory first const static int socket_offset = 0x40000000; //hacky way of separating sockets from file descriptors int iNextSocket; - QHash socketMap; - QHash reverseSocketMap; + QHash socketMap; + QHash reverseSocketMap; mutable QMutex iMutex; RSocketServ iSocketServ; }; -- cgit v0.12 From 7ec11a51d564c85d46ddee270cf7c743a2cbd320 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 6 Dec 2010 14:02:02 +0000 Subject: Use socket manager in QtNetwork Store/Retrieve sockets in the socket manager Use the shared socket server instance from QtCore Also, add 4 stub functions for multicast groups (new in master) to fix link error Reviewed-by: Markus Goetz --- src/network/socket/qnativesocketengine.cpp | 17 +++++++---- src/network/socket/qnativesocketengine_p.h | 2 +- src/network/socket/qnativesocketengine_symbian.cpp | 35 ++++++++++++++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index df73b9c..00d36b4 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -110,6 +110,10 @@ # include "qtcpserver.h" #endif +#ifdef Q_OS_SYMBIAN +# include +#endif + QT_BEGIN_NAMESPACE //#define QNATIVESOCKETENGINE_DEBUG @@ -158,12 +162,15 @@ QT_BEGIN_NAMESPACE concurrent QNativeSocketEngine. This is safe, because WSAStartup and WSACleanup are reference counted. */ -QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() +QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() : + socketDescriptor(-1), +#ifdef Q_OS_SYMBIAN + socketServer(qt_symbianGetSocketServer()), +#endif + readNotifier(0), + writeNotifier(0), + exceptNotifier(0) { - socketDescriptor = -1; - readNotifier = 0; - writeNotifier = 0; - exceptNotifier = 0; } /*! \internal diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index ceecfeb..c017065 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -200,7 +200,7 @@ public: int socketDescriptor; #ifdef Q_OS_SYMBIAN mutable RSocket nativeSocket; - RSocketServ socketServer; //TODO: shared ref + RSocketServ& socketServer; RConnection connection; //TODO: shared ref mutable RTimer selectTimer; #endif diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp index 788e58a..d1a0819 100644 --- a/src/network/socket/qnativesocketengine_symbian.cpp +++ b/src/network/socket/qnativesocketengine_symbian.cpp @@ -46,6 +46,7 @@ #include "qhostaddress.h" #include "qelapsedtimer.h" #include "qvarlengtharray.h" +#include "qnetworkinterface.h" #include #include #include @@ -165,7 +166,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return false; } - socketDescriptor = QSymbianSocketManager::instance().addSocket(&nativeSocket); + socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket); return true; } @@ -547,10 +548,8 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() return false; if (!nativeSocket.SubSessionHandle()) { - RSocket *s = QSymbianSocketManager::instance().lookupSocket(socketDescriptor); - if (!s) + if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket)) return false; - nativeSocket = *s; //TODO: badwrongfun (address is different, so this is broken) } // Determine local address @@ -621,7 +620,7 @@ void QNativeSocketEnginePrivate::nativeClose() //TODO: call nativeSocket.Shutdown(EImmediate) in some cases? nativeSocket.Close(); - QSymbianSocketManager::instance().removeSocket(&nativeSocket); + QSymbianSocketManager::instance().removeSocket(nativeSocket); } qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) @@ -768,4 +767,30 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c 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 -- cgit v0.12 From 8dacbccfd89006d1571b3b6ab6e96ea13e74f455 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 6 Dec 2010 15:47:40 +0000 Subject: Set preferences in socket server Connect() Tell the socket server we intend to use this session mainly for IP This allows the socket server to optimise this session for IP usage. Reviewed-by: Markus Goetz --- src/corelib/kernel/qcore_symbian_p.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 809dc30..b6688f7 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -44,6 +44,7 @@ #include #include "qcore_symbian_p.h" #include +#include QT_BEGIN_NAMESPACE @@ -218,7 +219,11 @@ Q_CORE_EXPORT RFs& qt_s60GetRFs() QSymbianSocketManager::QSymbianSocketManager() : iNextSocket(0) { - qt_symbian_throwIfError(iSocketServ.Connect()); + TSessionPref preferences; + // ### 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)); qt_symbian_throwIfError(iSocketServ.ShareAuto()); } -- cgit v0.12 From 5ef1fb5823a25cd4b27029701f7d707c82750acb Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 6 Dec 2010 15:57:59 +0000 Subject: Use shared socket server session everywhere Converted uses of RSocketServ in QtNetwork and the symbian bearer plugin to use the shared session from QtCore instead of creating their own Reviewed-by: Markus Goetz --- src/network/kernel/qnetworkinterface_symbian.cpp | 13 ++----------- src/plugins/bearer/symbian/qnetworksession_impl.cpp | 18 +++--------------- src/plugins/bearer/symbian/qnetworksession_impl.h | 2 +- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/network/kernel/qnetworkinterface_symbian.cpp b/src/network/kernel/qnetworkinterface_symbian.cpp index 7942461..751664e 100644 --- a/src/network/kernel/qnetworkinterface_symbian.cpp +++ b/src/network/kernel/qnetworkinterface_symbian.cpp @@ -44,6 +44,7 @@ #include "qnetworkinterface.h" #include "qnetworkinterface_p.h" #include "../corelib/kernel/qcore_symbian_p.h" +#include #ifndef QT_NO_NETWORKINTERFACE @@ -72,17 +73,10 @@ static QList interfaceListing() TInt err(KErrNone); QList interfaces; - // Connect to Native socket server - RSocketServ socketServ; - err = socketServ.Connect(); - if (err) - return interfaces; - // Open dummy socket for interface queries RSocket socket; - err = socket.Open(socketServ, _L("udp")); + err = socket.Open(qt_symbianGetSocketServer(), _L("udp")); if (err) { - socketServ.Close(); return interfaces; } @@ -90,7 +84,6 @@ static QList interfaceListing() err = socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl); if (err) { socket.Close(); - socketServ.Close(); return interfaces; } @@ -176,7 +169,6 @@ static QList interfaceListing() err = socket.SetOpt(KSoInetEnumRoutes, KSolInetRtCtrl); if (err) { socket.Close(); - socketServ.Close(); // return what we have // up to this moment return interfaces; @@ -223,7 +215,6 @@ static QList interfaceListing() } socket.Close(); - socketServ.Close(); return interfaces; } diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 53a5b4d..cfb55bf 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #ifdef SNAP_FUNCTIONALITY_AVAILABLE #include @@ -65,7 +66,7 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) iDynamicUnSetdefaultif(0), ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), - iConnectInBackground(false), isOpening(false) + iConnectInBackground(false), isOpening(false), iSocketServ(qt_symbianGetSocketServer()) { CActiveScheduler::Add(this); @@ -109,7 +110,6 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() // Cancel possible RConnection::Start() Cancel(); - iSocketServ.Close(); // Close global 'Open C' RConnection // Clears also possible unsetdefaultif() flags. @@ -363,20 +363,9 @@ void QNetworkSessionPrivateImpl::open() iStoppedByUser = false; iClosedByUser = false; - TInt error = iSocketServ.Connect(); - if (error != KErrNone) { - // Could not open RSocketServ - newState(QNetworkSession::Invalid); - iError = QNetworkSession::UnknownSessionError; - emit QNetworkSessionPrivate::error(iError); - syncStateWithInterface(); - return; - } - - error = iConnection.Open(iSocketServ); + TInt error = iConnection.Open(iSocketServ); if (error != KErrNone) { // Could not open RConnection - iSocketServ.Close(); newState(QNetworkSession::Invalid); iError = QNetworkSession::UnknownSessionError; emit QNetworkSessionPrivate::error(iError); @@ -533,7 +522,6 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) } Cancel(); // closes iConnection - iSocketServ.Close(); // Close global 'Open C' RConnection. If OpenC supports, // close the defaultif for good to avoid difficult timing diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 8e3e997..1101d1e 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -162,7 +162,7 @@ private: // data RLibrary iOpenCLibrary; TOpenCUnSetdefaultifFunction iDynamicUnSetdefaultif; - mutable RSocketServ iSocketServ; + mutable RSocketServ &iSocketServ; //not owned, shared from QtCore mutable RConnection iConnection; mutable RConnectionMonitor iConnectionMonitor; ConnectionProgressNotifier* ipConnectionNotifier; -- cgit v0.12 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 From 849ad907d49e6f6866dc81c0e3a94514bdc69b40 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 8 Mar 2011 18:46:00 +0000 Subject: Fix compile error introduced by merge Basically the same as f86e014bb6f2754bfed33106021a809ca8c2ce73. The declarations were appearing twice in the header file after merging Reviewed-by: Trust Me --- src/network/bearer/qnetworksession.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index c08a9bf..688f37e 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -140,9 +140,6 @@ private: QNetworkSessionPrivate *d; }; -Q_DECLARE_METATYPE(QNetworkSession::State); -Q_DECLARE_METATYPE(QNetworkSession::SessionError); - #ifndef QT_MOBILITY_BEARER QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkSession::State) -- cgit v0.12 From 5a488f8022626e71681ae42662aa9d4785ce6027 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Feb 2011 19:32:55 +0000 Subject: Fix http proxy connections hanging on network error The http socket engine was hiding errors other than RemoteHostClosedError. This caused problems, because for other errors, the low level socket is still closed in the native socket engine. By not emitting the read notification, the error was never informed to QAbstractSocket and as a result, the application never gets the disconnected signal. Reviewed-by: Martin Petersson --- src/network/socket/qhttpsocketengine.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 6a025f2..598efb6 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -704,11 +704,10 @@ void QHttpSocketEngine::slotSocketError(QAbstractSocket::SocketError error) d->state = None; setError(error, d->socket->errorString()); - if (error == QAbstractSocket::RemoteHostClosedError) { - emitReadNotification(); - } else { + if (error != QAbstractSocket::RemoteHostClosedError) qDebug() << "QHttpSocketEngine::slotSocketError: got weird error =" << error; - } + //read notification needs to always be emitted, otherwise the higher layer doesn't get the disconnected signal + emitReadNotification(); } void QHttpSocketEngine::slotSocketStateChanged(QAbstractSocket::SocketState state) -- cgit v0.12 From 9530b97c6024ac69011ceb70dde06f5c71bd31d9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 1 Mar 2011 16:22:33 +0000 Subject: QTcpSocket autotest fixes 1. Don't crash if qt-test-server isn't found, fail instead 2. symbian: 200ms is too short for the timeout test when using proxies, extended to 1000ms 3. Don't crash when the disconnectWhileConnectingNoEventLoop fails used a QScopedPointer with custom cleanup to shutdown the thread tidily. 4. Fast fail for downloadBigFile test if the connection is lost before the download is complete. This uses the disconnected signal to exit the event loop early. Previously on this type of failure it took 10 minutes for the event loop to time out. Reviewed-by: Markus Goetz --- tests/auto/qtcpsocket/tst_qtcpsocket.cpp | 33 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index 21092c4..b0ecbda 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -336,7 +336,9 @@ void tst_QTcpSocket::init() QFETCH_GLOBAL(bool, setProxy); if (setProxy) { QFETCH_GLOBAL(int, proxyType); - QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(); + QList addresses = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses(); + QVERIFY2(addresses.count() > 0, "failed to get ip address for test server"); + QString fluke = addresses.first().toString(); QNetworkProxy proxy; switch (proxyType) { @@ -606,7 +608,7 @@ void tst_QTcpSocket::timeoutConnect() // Port 1357 is configured to drop packets on the test server socket->connectToHost(address, 1357); QVERIFY(timer.elapsed() < 50); - QVERIFY(!socket->waitForConnected(200)); + QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication QCOMPARE(socket->state(), QTcpSocket::UnconnectedState); QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError)); @@ -1035,7 +1037,7 @@ public: : server(0), ok(false), quit(false) { } - ~ReceiverThread() { /*delete server;*/ terminate(); wait(); } + ~ReceiverThread() { } bool listen() { @@ -1047,6 +1049,14 @@ public: return true; } + static void cleanup(void *ptr) + { + ReceiverThread* self = reinterpret_cast(ptr); + self->quit = true; + self->wait(30000); + delete self; + } + protected: void run() { @@ -1093,18 +1103,16 @@ void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop() { QFETCH(QByteArray, data); - ReceiverThread thread; - QVERIFY(thread.listen()); - thread.start(); + QScopedPointer thread (new ReceiverThread); + QVERIFY(thread->listen()); + thread->start(); // proceed to the connect-write-disconnect QTcpSocket *socket = newSocket(); - socket->connectToHost("127.0.0.1", thread.serverPort); + socket->connectToHost("127.0.0.1", thread->serverPort); if (!data.isEmpty()) socket->write(data); if (socket->state() == QAbstractSocket::ConnectedState) { - thread.quit = true; - thread.wait(); QSKIP("localhost connections are immediate, test case is invalid", SkipSingle); } @@ -1130,9 +1138,9 @@ void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop() delete socket; // check if the other side received everything ok - QVERIFY(thread.wait(30000)); - QVERIFY(thread.ok); - QCOMPARE(thread.receivedData, data); + QVERIFY(thread->wait(30000)); + QVERIFY(thread->ok); + QCOMPARE(thread->receivedData, data); } //---------------------------------------------------------------------------------- @@ -1194,6 +1202,7 @@ void tst_QTcpSocket::downloadBigFile() connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot())); connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot())); + connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot())); tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80); -- cgit v0.12 From 270b878729068f42f862c7d04bb8a13915801ba3 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 2 Mar 2011 17:56:00 +0000 Subject: Thread safety - close RTimer handle when moving threads RTimer is only usable in the thread it was created. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index dac50d4..fa6aedd 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1665,16 +1665,26 @@ qint64 QSymbianSocketEngine::bytesToWrite() const bool QSymbianSocketEngine::event(QEvent* ev) { Q_D(QSymbianSocketEngine); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::event"; +#endif switch (ev->type()) { case QEvent::ThreadChange: +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "ThreadChange"; +#endif if (d->asyncSelect) { delete d->asyncSelect; d->asyncSelect = 0; QEvent *postThreadChangeEvent = new QEvent(PostThreadChangeEvent); QCoreApplication::postEvent(this, postThreadChangeEvent); } + d->selectTimer.Close(); return true; case PostThreadChangeEvent: +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "PostThreadChangeEvent"; +#endif // recreate select in new thread d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); if (d->readNotifier) { -- cgit v0.12 From dc9ddf8e30800aab375587563b377068bbe99532 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 2 Mar 2011 17:59:49 +0000 Subject: Fix crash Reviewed-by: Markus Goetz --- src/network/socket/qtcpserver.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index 6b012db..5a60764 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -287,15 +287,15 @@ 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"); return false; } +#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(QAbstractSocket::TcpSocket, proto)) { d->serverSocketError = d->socketEngine->error(); d->serverSocketErrorString = d->socketEngine->errorString(); -- cgit v0.12 From 76342796aa83761a854fd8c0b477af0a1afc62c4 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 4 Mar 2011 18:56:55 +0000 Subject: Move some network tests from gui.pro to network.pro These network tests have no dependency on the QtGui dll, so I have moved them to the network autotest group. In some cases this was not stated in the tests' .pro files. The gui autotest group still has a network test (qtcpsocket), but this has a dependency on QtGui for one test case (which uses QMessageBox) Reviewed-by: Markus Goetz --- tests/auto/gui.pro | 5 ----- tests/auto/network.pro | 5 +++++ tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro | 1 + tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro | 1 + tests/auto/qnetworkreply/test/test.pro | 1 + 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 07dc5ef..356a98d 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -113,9 +113,6 @@ SUBDIRS=\ qmouseevent_modal \ qmovie \ qnetworkaccessmanager_and_qprogressdialog \ - qnetworkcachemetadata \ - qnetworkdiskcache \ - qnetworkreply \ qpaintengine \ qpainterpath \ qpainterpathstroker \ @@ -168,7 +165,6 @@ SUBDIRS=\ qtabbar \ qtableview \ qtablewidget \ - qtcpserver \ qtcpsocket \ qtessellator \ qtextblock \ @@ -195,7 +191,6 @@ SUBDIRS=\ qtreeview \ qtreewidget \ qtreewidgetitemiterator \ - qudpsocket \ qundogroup \ qundostack \ qvectornd \ diff --git a/tests/auto/network.pro b/tests/auto/network.pro index 50c4487..e4cecce 100644 --- a/tests/auto/network.pro +++ b/tests/auto/network.pro @@ -19,12 +19,15 @@ SUBDIRS=\ platformsocketengine \ qnetworkaccessmanager \ qnetworkaddressentry \ + qnetworkcachemetadata \ qnetworkconfiguration \ qnetworkconfigurationmanager \ qnetworkcookie \ qnetworkcookiejar \ + qnetworkdiskcache \ qnetworkinterface \ qnetworkproxy \ + qnetworkreply \ qnetworkrequest \ qnetworksession \ qobjectperformance \ @@ -37,6 +40,8 @@ SUBDIRS=\ qsslsocket \ qsslsocket_onDemandCertificates_member \ qsslsocket_onDemandCertificates_static \ + qtcpserver \ + qudpsocket \ # qnetworkproxyfactory \ # Uses a hardcoded proxy configuration !contains(QT_CONFIG, private_tests): SUBDIRS -= \ diff --git a/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro b/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro index 77ad347..ae0941e 100644 --- a/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro +++ b/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro @@ -1,4 +1,5 @@ load(qttest_p4) +QT -= gui QT += network SOURCES += tst_qnetworkcachemetadata.cpp diff --git a/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro b/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro index 3b13087..c05171d 100644 --- a/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro +++ b/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro @@ -1,4 +1,5 @@ load(qttest_p4) +QT -= gui QT += network SOURCES += tst_qnetworkdiskcache.cpp diff --git a/tests/auto/qnetworkreply/test/test.pro b/tests/auto/qnetworkreply/test/test.pro index 12fdf04..80b879a 100644 --- a/tests/auto/qnetworkreply/test/test.pro +++ b/tests/auto/qnetworkreply/test/test.pro @@ -1,4 +1,5 @@ load(qttest_p4) +QT -= gui SOURCES += ../tst_qnetworkreply.cpp TARGET = ../tst_qnetworkreply -- cgit v0.12 From 3d34e2e49399446b45a343dcff917afef748520b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 4 Mar 2011 19:06:05 +0000 Subject: Fix link error in qsocketnotifier test Reviewed-by: Markus Goetz --- tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp b/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp index 0b7e7ef..5594dc3 100644 --- a/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp +++ b/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp @@ -46,7 +46,13 @@ #include #include #include +#ifdef Q_OS_SYMBIAN +#include +#define NATIVESOCKETENGINE QSymbianSocketEngine +#else #include +#define NATIVESOCKETENGINE QNativeSocketEngine +#endif class tst_QSocketNotifier : public QObject { @@ -71,10 +77,10 @@ class UnexpectedDisconnectTester : public QObject { Q_OBJECT public: - QNativeSocketEngine *readEnd1, *readEnd2; + NATIVESOCKETENGINE *readEnd1, *readEnd2; int sequence; - UnexpectedDisconnectTester(QNativeSocketEngine *s1, QNativeSocketEngine *s2) + UnexpectedDisconnectTester(NATIVESOCKETENGINE *s1, NATIVESOCKETENGINE *s2) : readEnd1(s1), readEnd2(s2), sequence(0) { QSocketNotifier *notifier1 = @@ -124,7 +130,7 @@ void tst_QSocketNotifier::unexpectedDisconnection() QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost, 0)); - QNativeSocketEngine readEnd1; + NATIVESOCKETENGINE readEnd1; readEnd1.initialize(QAbstractSocket::TcpSocket); bool b = readEnd1.connectToHost(server.serverAddress(), server.serverPort()); QVERIFY(readEnd1.waitForWrite()); @@ -135,7 +141,7 @@ void tst_QSocketNotifier::unexpectedDisconnection() QTcpSocket *writeEnd1 = server.nextPendingConnection(); QVERIFY(writeEnd1 != 0); - QNativeSocketEngine readEnd2; + NATIVESOCKETENGINE readEnd2; readEnd2.initialize(QAbstractSocket::TcpSocket); b = readEnd2.connectToHost(server.serverAddress(), server.serverPort()); QVERIFY(readEnd2.waitForWrite()); -- cgit v0.12 From 81ab8365e53389936bcaff07c82a2891ec63c4e5 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 7 Mar 2011 17:14:02 +0000 Subject: Reduce excessive timeout in tst_qtcpsocket Timeout of 5000 seconds (which was probably intended to be 5000ms) reduced to a more reasonable 60 seconds, to prevent the test from hanging in case of errors in the proxy server. Reviewed-by: Markus Goetz --- tests/auto/qtcpsocket/tst_qtcpsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index b0ecbda..40ca531 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -1389,7 +1389,7 @@ void tst_QTcpSocket::flush() connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot())); socket->connectToHost(QtNetworkSettings::serverName(), 143); - enterLoop(5000); + enterLoop(60); QVERIFY(socket->isOpen()); socket->write("1 LOGOUT\r\n"); -- cgit v0.12 From a99cc33345c32a7e210dbffa2c5c56ee13dd83c1 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 8 Mar 2011 13:20:40 +0000 Subject: tst_qtcpsocket stabilisation Increased heap size to avoid OOM Increased timeouts in the timeoutConnect test, as these randomly fail at least in debug builds with 50ms (symbian threads have a 20ms timeslice for round robin scheduling of equal priority threads, so that could be related) Skip the setSocketDescriptor test on symbian, since native sockets are not ints, open c sockets are not supported, and we decided not to support RSocket adoption unless it's specifically requested. Reviewed-by: Markus Goetz --- tests/auto/qtcpsocket/test/test.pro | 2 +- tests/auto/qtcpsocket/tst_qtcpsocket.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/auto/qtcpsocket/test/test.pro b/tests/auto/qtcpsocket/test/test.pro index c4369df..5dde565 100644 --- a/tests/auto/qtcpsocket/test/test.pro +++ b/tests/auto/qtcpsocket/test/test.pro @@ -11,7 +11,7 @@ wince*: { QT += network vxworks:QT -= gui -symbian: TARGET.EPOCHEAPSIZE="0x100 0x1000000" +symbian: TARGET.EPOCHEAPSIZE="0x100 0x3000000" TARGET = tst_qtcpsocket diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index 40ca531..b21de49 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -445,6 +445,9 @@ void tst_QTcpSocket::setInvalidSocketDescriptor() void tst_QTcpSocket::setSocketDescriptor() { +#ifdef Q_OS_SYMBIAN + QSKIP("adopting open c socket handles is not supported", SkipAll); +#else QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; // this test doesn't make sense with proxies @@ -485,6 +488,7 @@ void tst_QTcpSocket::setSocketDescriptor() #ifdef Q_OS_WIN delete dummy; #endif +#endif } //---------------------------------------------------------------------------------- @@ -607,14 +611,14 @@ void tst_QTcpSocket::timeoutConnect() // Port 1357 is configured to drop packets on the test server socket->connectToHost(address, 1357); - QVERIFY(timer.elapsed() < 50); + QVERIFY(timer.elapsed() < 150); QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication QCOMPARE(socket->state(), QTcpSocket::UnconnectedState); QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError)); timer.start(); socket->connectToHost(address, 1357); - QVERIFY(timer.elapsed() < 50); + QVERIFY(timer.elapsed() < 150); QTimer::singleShot(50, &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); -- cgit v0.12 From f89c25376651a87501e0c5980d289992b0fbe1c8 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 8 Mar 2011 15:41:59 +0000 Subject: Handle errors returned through select in the waitForXXX socket functions Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index fa6aedd..ed7962c 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1141,6 +1141,9 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool //restart asynchronous notifier (only one IOCTL allowed at a time) if (asyncSelect) asyncSelect->IssueRequest(); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select timeout"; +#endif return 0; //timeout } else { selectTimer.Cancel(); @@ -1148,11 +1151,20 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool } } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select status" << selectStat.Int() << (int)selectFlags(); +#endif if (selectStat != KErrNone) return selectStat.Int(); if (selectFlags() & KSockSelectExcept) { TInt err; nativeSocket.GetOpt(KSOSelectLastError, KSOLSocket, err); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select last error" << err; +#endif + //TODO: avoidable cast? + //set the error here, because read won't always return the same error again as select. + const_cast(this)->setError(err); //restart asynchronous notifier (only one IOCTL allowed at a time) if (asyncSelect) asyncSelect->IssueRequest(); //TODO: in error case should we restart or not? @@ -1381,6 +1393,7 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) switch (symbianError) { case KErrDisconnected: case KErrEof: + case KErrConnectionTerminated: //interface stopped externally - RConnection::Stop(EStopAuthoritative) setError(QAbstractSocket::RemoteHostClosedError, QSymbianSocketEnginePrivate::RemoteHostClosedErrorString); break; -- cgit v0.12 From 0b0247e675e3e8054e41de41c716d8f915e18629 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 8 Mar 2011 14:17:47 +0000 Subject: tst_qtcpsocket - skip proxies for localhost testing There is no point to test the proxy setting for connections to localhost, because the proxy is bypassed anyway. Skipping running the same test case multiple times makes this test complete a bit faster. Reviewed-by: Markus Goetz --- tests/auto/qtcpsocket/tst_qtcpsocket.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index b21de49..b972130 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -981,6 +981,9 @@ void tst_QTcpSocket::disconnectWhileConnecting_data() void tst_QTcpSocket::disconnectWhileConnecting() { QFETCH(QByteArray, data); + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); @@ -1106,6 +1109,9 @@ void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop_data() void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop() { QFETCH(QByteArray, data); + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QScopedPointer thread (new ReceiverThread); QVERIFY(thread->listen()); @@ -1646,6 +1652,9 @@ private slots: //---------------------------------------------------------------------------------- void tst_QTcpSocket::remoteCloseError() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case RemoteCloseErrorServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); @@ -1956,6 +1965,9 @@ void tst_QTcpSocket::linuxKernelBugLocalSocket() //---------------------------------------------------------------------------------- void tst_QTcpSocket::abortiveClose() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); connect(&server, SIGNAL(newConnection()), this, SLOT(exitLoopSlot())); @@ -1994,6 +2006,9 @@ void tst_QTcpSocket::abortiveClose_abortSlot() //---------------------------------------------------------------------------------- void tst_QTcpSocket::localAddressEmptyOnBSD() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); @@ -2264,6 +2279,9 @@ void tst_QTcpSocket::moveToThread0() void tst_QTcpSocket::increaseReadBufferSize() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QTcpSocket *active = newSocket(); connect(active, SIGNAL(readyRead()), SLOT(exitLoopSlot())); -- cgit v0.12 From 28100e436bb662756c2cb0be471785bcd2dbef83 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 8 Mar 2011 18:01:54 +0000 Subject: tst_qudpsocket - add a non localhost test case The echo test case uses the UDP echo service on the qt-test-server Reviewed-by: Markus Goetz --- tests/auto/qudpsocket/tst_qudpsocket.cpp | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/auto/qudpsocket/tst_qudpsocket.cpp b/tests/auto/qudpsocket/tst_qudpsocket.cpp index 6ba55b2..e6fe068 100644 --- a/tests/auto/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/qudpsocket/tst_qudpsocket.cpp @@ -108,6 +108,8 @@ private slots: void setMulticastInterface(); void multicast_data(); void multicast(); + void echo_data(); + void echo(); protected slots: void empty_readyReadSlot(); @@ -1095,5 +1097,55 @@ void tst_QUdpSocket::multicast() QVERIFY2(receiver.leaveMulticastGroup(groupAddress), qPrintable(receiver.errorString())); } +void tst_QUdpSocket::echo_data() +{ + QTest::addColumn("connect"); + QTest::newRow("writeDatagram") << false; + QTest::newRow("write") << true; +} + +void tst_QUdpSocket::echo() +{ + QFETCH(bool, connect); + QHostInfo info = QHostInfo::fromName(QtNetworkSettings::serverName()); + QVERIFY(info.addresses().count()); + QHostAddress remote = info.addresses().first(); + + QUdpSocket sock; + if (connect) { + sock.connectToHost(remote, 7); + } else { + sock.bind(); + } + QByteArray out(30, 'x'); + QByteArray in; + int successes = 0; + for (int i=0;i<20;i++) { + if (connect) { + sock.write(out); + } else { + sock.writeDatagram(out, remote, 7); + } + if (sock.waitForReadyRead(1000)) { + while (sock.hasPendingDatagrams()) { + QHostAddress from; + quint16 port; + if (connect) { + in = sock.read(sock.pendingDatagramSize()); + } else { + in.resize(sock.pendingDatagramSize()); + sock.readDatagram(in.data(), in.length(), &from, &port); + } + if (in==out) + successes++; + } + } + if (!sock.isValid()) + QFAIL(sock.errorString().toLatin1().constData()); + qDebug() << "packets in" << successes << "out" << i; + } + QVERIFY(successes >= 18); +} + QTEST_MAIN(tst_QUdpSocket) #include "tst_qudpsocket.moc" -- cgit v0.12 From 0b646f2336a17aa6ae1cb4da89cba71c1adfd5ed Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 9 Mar 2011 13:46:57 +0000 Subject: Network session support for proxy socket engines The proxy socket engines forward the network session to the "real" socket they use natively. Reviewed-by: Markus Goetz --- src/network/socket/qhttpsocketengine.cpp | 3 +++ src/network/socket/qsocks5socketengine.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 598efb6..c580b03 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -72,6 +72,9 @@ bool QHttpSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSo setProtocol(protocol); setSocketType(type); d->socket = new QTcpSocket(this); +#ifndef QT_NO_BEARERMANAGEMENT + d->socket->setProperty("_q_networkSession", property("_q_networkSession")); +#endif // Explicitly disable proxying on the proxy socket itself to avoid // unwanted recursion. diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index 91dfdf3..16c0faa 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -556,7 +556,9 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode) udpData = new QSocks5UdpAssociateData; data = udpData; udpData->udpSocket = new QUdpSocket(q); +#ifndef QT_NO_BEARERMANAGEMENT udpData->udpSocket->setProperty("_q_networksession", q->property("_q_networksession")); +#endif udpData->udpSocket->setProxy(QNetworkProxy::NoProxy); QObject::connect(udpData->udpSocket, SIGNAL(readyRead()), q, SLOT(_q_udpSocketReadNotification()), @@ -568,7 +570,9 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode) } data->controlSocket = new QTcpSocket(q); +#ifndef QT_NO_BEARERMANAGEMENT data->controlSocket->setProperty("_q_networksession", q->property("_q_networksession")); +#endif data->controlSocket->setProxy(QNetworkProxy::NoProxy); QObject::connect(data->controlSocket, SIGNAL(connected()), q, SLOT(_q_controlSocketConnected()), Qt::DirectConnection); @@ -1378,7 +1382,9 @@ bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port) d->udpData->associatePort = d->localPort; d->localPort = 0; QUdpSocket dummy; +#ifndef QT_NO_BEARERMANAGEMENT dummy.setProperty("_q_networksession", property("_q_networksession")); +#endif dummy.setProxy(QNetworkProxy::NoProxy); if (!dummy.bind() || writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0 -- cgit v0.12 From f2d8211aa530c6aca65bd52fd4cc57ef74f927c0 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 9 Mar 2011 17:22:35 +0000 Subject: Add debug logging to QHttpThreadDelegate Activated by defining QHTTPTHREADDELEGATE_DEBUG Reviewed-by: Markus Goetz --- src/network/access/qhttpthreaddelegate.cpp | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index b5cf00a..2cd5979 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +//#define QHTTPTHREADDELEGATE_DEBUG #include "qhttpthreaddelegate_p.h" #include @@ -196,6 +197,9 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) : // This is invoked as BlockingQueuedConnection from QNetworkAccessHttpBackend in the user thread void QHttpThreadDelegate::startRequestSynchronously() { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::startRequestSynchronously() thread=" << QThread::currentThreadId(); +#endif synchronous = true; QEventLoop synchronousRequestLoop; @@ -210,12 +214,18 @@ void QHttpThreadDelegate::startRequestSynchronously() connections.localData()->releaseEntry(cacheKey); connections.setLocalData(0); +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::startRequestSynchronously() thread=" << QThread::currentThreadId() << "finished"; +#endif } // This is invoked as QueuedConnection from QNetworkAccessHttpBackend in the user thread void QHttpThreadDelegate::startRequest() { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::startRequest() thread=" << QThread::currentThreadId(); +#endif // Check QThreadStorage for the QNetworkAccessCache // If not there, create this connection cache if (!connections.hasLocalData()) { @@ -300,6 +310,9 @@ void QHttpThreadDelegate::startRequest() // This gets called from the user thread or by the synchronous HTTP timeout timer void QHttpThreadDelegate::abortRequest() { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous; +#endif if (httpReply) { delete httpReply; httpReply = 0; @@ -329,6 +342,9 @@ void QHttpThreadDelegate::finishedSlot() qWarning() << "QHttpThreadDelegate::finishedSlot: HTTP reply had already been deleted, internal problem. Please report."; return; } +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::finishedSlot() thread=" << QThread::currentThreadId() << "result=" << httpReply->statusCode(); +#endif // If there is still some data left emit that now while (httpReply->readAnyAvailable()) { @@ -358,6 +374,9 @@ void QHttpThreadDelegate::finishedSlot() void QHttpThreadDelegate::synchronousFinishedSlot() { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::synchronousFinishedSlot() thread=" << QThread::currentThreadId() << "result=" << httpReply->statusCode(); +#endif if (httpReply->statusCode() >= 400) { // it's an error reply QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply", @@ -379,6 +398,9 @@ void QHttpThreadDelegate::finishedWithErrorSlot(QNetworkReply::NetworkError erro qWarning() << "QHttpThreadDelegate::finishedWithErrorSlot: HTTP reply had already been deleted, internal problem. Please report."; return; } +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::finishedWithErrorSlot() thread=" << QThread::currentThreadId() << "error=" << errorCode << detail; +#endif #ifndef QT_NO_OPENSSL if (ssl) @@ -396,6 +418,9 @@ void QHttpThreadDelegate::finishedWithErrorSlot(QNetworkReply::NetworkError erro void QHttpThreadDelegate::synchronousFinishedWithErrorSlot(QNetworkReply::NetworkError errorCode, const QString &detail) { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::synchronousFinishedWithErrorSlot() thread=" << QThread::currentThreadId() << "error=" << errorCode << detail; +#endif incomingErrorCode = errorCode; incomingErrorDetail = detail; @@ -411,6 +436,10 @@ static void downloadBufferDeleter(char *ptr) void QHttpThreadDelegate::headerChangedSlot() { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::headerChangedSlot() thread=" << QThread::currentThreadId(); +#endif + #ifndef QT_NO_OPENSSL if (ssl) emit sslConfigurationChanged(httpReply->sslConfiguration()); @@ -443,6 +472,9 @@ void QHttpThreadDelegate::headerChangedSlot() void QHttpThreadDelegate::synchronousHeaderChangedSlot() { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::synchronousHeaderChangedSlot() thread=" << QThread::currentThreadId(); +#endif // Store the information we need in this object, the QNetworkAccessHttpBackend will later read it incomingHeaders = httpReply->header(); incomingStatusCode = httpReply->statusCode(); @@ -487,6 +519,9 @@ void QHttpThreadDelegate::sslErrorsSlot(const QList &errors) void QHttpThreadDelegate::synchronousAuthenticationRequiredSlot(const QHttpNetworkRequest &request, QAuthenticator *a) { Q_UNUSED(request); +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::synchronousAuthenticationRequiredSlot() thread=" << QThread::currentThreadId(); +#endif // Ask the credential cache QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), a); @@ -502,6 +537,9 @@ void QHttpThreadDelegate::synchronousAuthenticationRequiredSlot(const QHttpNetwo #ifndef QT_NO_NETWORKPROXY void QHttpThreadDelegate::synchronousProxyAuthenticationRequiredSlot(const QNetworkProxy &p, QAuthenticator *a) { +#ifdef QHTTPTHREADDELEGATE_DEBUG + qDebug() << "QHttpThreadDelegate::synchronousProxyAuthenticationRequiredSlot() thread=" << QThread::currentThreadId(); +#endif // Ask the credential cache QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedProxyCredentials(p, a); if (!credential.isNull()) { -- cgit v0.12 From 7b34e64198cbcdb8d738c9da11abe08c0ac880ac Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 9 Mar 2011 17:33:17 +0000 Subject: Fix synchronous http deadlock when aborted by internal timeout QHttpThreadDelegate::abortRequest was deleting itself, but not exiting the event loop. For the synchronous usage, both these are incorrect. Without exiting the event loop, the main thread waits forever. If it deletes itself, then the main thread will access the deleted memory on return (the delegate->incomingErrorCode class member) which can crash with frequency depending on heap implementation. With this change, abort acts more like the synchronousFinishedWithErrorSlot. Reviewed-by: Markus Goetz --- src/network/access/qhttpthreaddelegate.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 2cd5979..d75f12c 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -191,6 +191,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) : , downloadBuffer(0) , httpConnection(0) , httpReply(0) + , synchronousRequestLoop(0) { } @@ -316,12 +317,16 @@ void QHttpThreadDelegate::abortRequest() if (httpReply) { delete httpReply; httpReply = 0; - this->deleteLater(); } // Got aborted by the timeout timer - if (synchronous) + if (synchronous) { incomingErrorCode = QNetworkReply::TimeoutError; + QMetaObject::invokeMethod(synchronousRequestLoop, "quit", Qt::QueuedConnection); + } else { + //only delete this for asynchronous mode or QNetworkAccessHttpBackend will crash - see QNetworkAccessHttpBackend::postRequest() + this->deleteLater(); + } } void QHttpThreadDelegate::readyReadSlot() -- cgit v0.12 From ef53143777ccbd73799e597792a46b2676932cc2 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 9 Mar 2011 17:41:38 +0000 Subject: Bearer support for threaded http backend Reviewed-by: Markus Goetz --- src/network/access/qhttpthreaddelegate.cpp | 9 +++++++++ src/network/access/qhttpthreaddelegate_p.h | 3 +++ src/network/access/qnetworkaccesshttpbackend.cpp | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index d75f12c..6d6fadd 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -142,8 +142,13 @@ class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection, { // Q_OBJECT public: +#ifdef QT_NO_BEARERMANAGEMENT QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt) : QHttpNetworkConnection(hostName, port, encrypt) +#else + QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt, QSharedPointer networkSession) + : QHttpNetworkConnection(hostName, port, encrypt, /*parent=*/0, networkSession) +#endif { setExpires(true); setShareable(true); @@ -250,7 +255,11 @@ void QHttpThreadDelegate::startRequest() if (httpConnection == 0) { // no entry in cache; create an object // the http object is actually a QHttpNetworkConnection +#ifdef QT_NO_BEARERMANAGEMENT httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl); +#else + httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl, networkSession); +#endif #ifndef QT_NO_OPENSSL // Set the QSslConfiguration from this QNetworkRequest. if (ssl) { diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h index 086a35d..2e86df3 100644 --- a/src/network/access/qhttpthreaddelegate_p.h +++ b/src/network/access/qhttpthreaddelegate_p.h @@ -110,6 +110,9 @@ public: qint64 incomingContentLength; QNetworkReply::NetworkError incomingErrorCode; QString incomingErrorDetail; +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession; +#endif protected: // The zerocopy download buffer, if used: diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 4908e0a..8a29a31 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -47,6 +47,7 @@ #include "qabstractnetworkcache.h" #include "qnetworkrequest.h" #include "qnetworkreply.h" +#include "QtNetwork/private/qnetworksession_p.h" #include "qnetworkrequest_p.h" #include "qnetworkcookie_p.h" #include "QtCore/qdatetime.h" @@ -519,6 +520,11 @@ void QNetworkAccessHttpBackend::postRequest() // Create the HTTP thread delegate QHttpThreadDelegate *delegate = new QHttpThreadDelegate; +#ifndef Q_NO_BEARERMANAGEMENT + QVariant v(property("_q_networksession")); + if (v.isValid()) + delegate->networkSession = qvariant_cast >(v); +#endif // For the synchronous HTTP, this is the normal way the delegate gets deleted // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished -- cgit v0.12 From 132566afcf2357cc3c77d940f22567d83951f21d Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 10 Mar 2011 14:40:01 +0000 Subject: Fix network session use with the localhost optimisation in QNAB QNetworkAccessBackend has an optimisation to not start the bearer when the destination is localhost. On symbian, if the bearer is specified but not started, then socket creation will fail. To fix this, delay pushing the network session until start() is called, at which point we know if the localhost optmisation will be applied or not. When using localhost, don't specify any network session - symbian socket engine will create the socket successfully in thie case. Reviewed-by: Markus Goetz --- src/network/access/qnetworkaccessbackend.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 8f5a3da..6220abe 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -96,11 +96,6 @@ 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; @@ -374,6 +369,8 @@ bool QNetworkAccessBackend::start() if (manager->networkSession->isOpen() && manager->networkSession->state() == QNetworkSession::Connected) { + //copy network session down to the backend + setProperty("_q_networksession", QVariant::fromValue(manager->networkSession)); open(); return true; } -- cgit v0.12 From 99baeb5b6b2c6d0b2724709ae8caa789e5ad5895 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 10 Mar 2011 18:16:05 +0000 Subject: Fixes for QTcpServer autotest Set symbian capabilities in the two sub .pro files Enable IPv6 test on symbian Disable tests that use open C functions on socket descriptors When bearer management is enabled, start the network interface at start of the test. Reviewed-by: Markus Goetz --- .../qtcpserver/crashingServer/crashingServer.pro | 1 + tests/auto/qtcpserver/qtcpserver.pro | 2 -- tests/auto/qtcpserver/test/test.pro | 7 +++-- tests/auto/qtcpserver/tst_qtcpserver.cpp | 34 ++++++++++++++++++---- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/tests/auto/qtcpserver/crashingServer/crashingServer.pro b/tests/auto/qtcpserver/crashingServer/crashingServer.pro index 0bea655..700e952 100644 --- a/tests/auto/qtcpserver/crashingServer/crashingServer.pro +++ b/tests/auto/qtcpserver/crashingServer/crashingServer.pro @@ -6,3 +6,4 @@ DESTDIR = ./ # This means the auto test works on some machines for MinGW. No dialog stalls # the application. win32-g++*:CONFIG += console +symbian: TARGET.CAPABILITY += NetworkServices ReadUserData diff --git a/tests/auto/qtcpserver/qtcpserver.pro b/tests/auto/qtcpserver/qtcpserver.pro index a3744a2..e123cfe 100644 --- a/tests/auto/qtcpserver/qtcpserver.pro +++ b/tests/auto/qtcpserver/qtcpserver.pro @@ -1,6 +1,4 @@ TEMPLATE = subdirs SUBDIRS = test crashingServer -symbian: TARGET.CAPABILITY = NetworkServices - diff --git a/tests/auto/qtcpserver/test/test.pro b/tests/auto/qtcpserver/test/test.pro index e91ba20..65e1d82 100644 --- a/tests/auto/qtcpserver/test/test.pro +++ b/tests/auto/qtcpserver/test/test.pro @@ -13,9 +13,10 @@ wince*: { } symbian { - crashApp.files = $$QT_BUILD_TREE/examples/widgets/wiggly/$${BUILD_DIR}/crashingServer.exe - crashApp.path = . - DEPLOYMENT += crashApp + crashApp.files = $$QT_BUILD_TREE/examples/widgets/wiggly/$${BUILD_DIR}/crashingServer.exe + crashApp.path = . + DEPLOYMENT += crashApp + TARGET.CAPABILITY += NetworkServices ReadUserData } TARGET = ../tst_qtcpserver diff --git a/tests/auto/qtcpserver/tst_qtcpserver.cpp b/tests/auto/qtcpserver/tst_qtcpserver.cpp index 3d377a4..cff2fe5 100644 --- a/tests/auto/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/qtcpserver/tst_qtcpserver.cpp @@ -70,6 +70,9 @@ Q_DECLARE_METATYPE(QNetworkProxy) Q_DECLARE_METATYPE(QList) +#include +#include +#include #include "../network-settings.h" //TESTED_CLASS= @@ -86,6 +89,7 @@ public: public slots: void initTestCase_data(); + void initTestCase(); void init(); void cleanup(); private slots: @@ -107,6 +111,11 @@ private slots: void proxyFactory(); void qtbug14268_peek(); + +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkSession *networkSession; +#endif }; // Testing get/set functions @@ -141,6 +150,16 @@ void tst_QTcpServer::initTestCase_data() QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy); } +void tst_QTcpServer::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager man; + networkSession = new QNetworkSession(man.defaultConfiguration(), this); + networkSession->open(); + QVERIFY(networkSession->waitForOpened()); +#endif +} + void tst_QTcpServer::init() { QFETCH_GLOBAL(bool, setProxy); @@ -190,7 +209,7 @@ void tst_QTcpServer::clientServerLoop() QTcpSocket client; QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.serverAddress() == QHostAddress::Any)) + if (!(server.serverAddress() == QHostAddress::Any) && !(server.serverAddress() == QHostAddress::AnyIPv6)) serverAddress = server.serverAddress(); client.connectToHost(serverAddress, server.serverPort()); @@ -222,9 +241,6 @@ void tst_QTcpServer::clientServerLoop() //---------------------------------------------------------------------------------- void tst_QTcpServer::ipv6Server() { -#if defined(Q_OS_SYMBIAN) - QSKIP("Symbian: IPv6 is not yet supported", SkipAll); -#endif //### need to enter the event loop for the server to get the connection ?? ( windows) QTcpServer server; if (!server.listen(QHostAddress::LocalHostIPv6, 8944)) { @@ -244,6 +260,8 @@ void tst_QTcpServer::ipv6Server() QTcpSocket *serverSocket = 0; QVERIFY((serverSocket = server.nextPendingConnection())); + serverSocket->close(); + delete serverSocket; } //---------------------------------------------------------------------------------- @@ -379,7 +397,8 @@ void tst_QTcpServer::setSocketDescriptor() QTcpServer server; QVERIFY(!server.setSocketDescriptor(42)); QCOMPARE(server.serverError(), QAbstractSocket::UnsupportedSocketOperationError); - +#ifndef Q_OS_SYMBIAN + //adopting Open C sockets is not supported, neither is adopting externally created RSocket #ifdef Q_OS_WIN // ensure winsock is started WSADATA wsaData; @@ -402,6 +421,7 @@ void tst_QTcpServer::setSocketDescriptor() #ifdef Q_OS_WIN WSACleanup(); #endif +#endif } //---------------------------------------------------------------------------------- @@ -493,6 +513,9 @@ void tst_QTcpServer::addressReusable() void tst_QTcpServer::setNewSocketDescriptorBlocking() { +#ifdef Q_OS_SYMBIAN + QSKIP("open C ioctls on Qt sockets not supported", SkipAll); +#else QFETCH_GLOBAL(bool, setProxy); if (setProxy) { QFETCH_GLOBAL(int, proxyType); @@ -507,6 +530,7 @@ void tst_QTcpServer::setNewSocketDescriptorBlocking() socket.connectToHost(QHostAddress::LocalHost, server.serverPort()); QVERIFY(server.waitForNewConnection(5000)); QVERIFY(server.ok); +#endif } void tst_QTcpServer::invalidProxy_data() -- cgit v0.12 From a2c9031817a7faaab62b15b8976a1c8664e108d6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 10 Mar 2011 18:20:53 +0000 Subject: QSymbianSocketEngine - return expected error code from bind In the unix socket engine, EADDRNOTAVAIL is returned by the native call when attempting to bind to a non existant interface. On symbian, the generic KErrNotFound is returned. Specifically for bind() convert KErrNotFound to the expected error code QAbstractSocket::SocketAddressNotAvailableError which is relied on by autotest (and possibly but unlikely, existing applications) Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index ed7962c..491b515 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -669,7 +669,15 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) #endif if (err) { - d->setError(err); + switch (err) { + case KErrNotFound: + // the specified interface was not found - use the error code expected + d->setError(QAbstractSocket::SocketAddressNotAvailableError, QSymbianSocketEnginePrivate::AddressNotAvailableErrorString); + break; + default: + d->setError(err); + break; + } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QSymbianSocketEngine::bind(%s, %i) == false (%s)", -- cgit v0.12 From 7f75862d6e8dbfb714a04ecd5047b4ec1714a3cf Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 14 Mar 2011 15:46:59 +0100 Subject: QLocalServer: Fix compilation --- src/network/socket/qlocalserver_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h index 8ec3ef0..1ee5df2 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 -- cgit v0.12 From 76487301421c2b127f564564e32c0c90a7b89ea2 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 14 Mar 2011 16:20:55 +0100 Subject: QSymbianSocketEngine: Compile fix --- 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 491b515..db98ade 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -47,7 +47,7 @@ #include "qelapsedtimer.h" #include "qvarlengtharray.h" #include "qnetworkinterface.h" -#include "qnetworksession_p.h" +#include #include #include #include -- cgit v0.12 From 479f234ec89db7e5916c27a7eac234d2ee8833c1 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 11 Mar 2011 16:21:52 +0000 Subject: Remove indirection through fake socket notifier in symbian socket engine Instead of creating socket notifiers and sending faked events to them, call the engine's notification functions directly. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 218 +++++++--------------------- src/network/socket/qsymbiansocketengine_p.h | 11 +- 2 files changed, 58 insertions(+), 171 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index db98ade..be04b56 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -70,8 +70,6 @@ #include #include -#define QNATIVESOCKETENGINE_DEBUG - #if defined QNATIVESOCKETENGINE_DEBUG #include #include @@ -263,9 +261,9 @@ void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() : socketDescriptor(-1), socketServer(QSymbianSocketManager::instance().getSocketServer()), - readNotifier(0), - writeNotifier(0), - exceptNotifier(0), + readNotificationsEnabled(false), + writeNotificationsEnabled(false), + exceptNotificationsEnabled(false), asyncSelect(0) { } @@ -970,12 +968,9 @@ void QSymbianSocketEngine::close() qDebug("QSymbianSocketEngine::close()"); #endif - if (d->readNotifier) - d->readNotifier->setEnabled(false); - if (d->writeNotifier) - d->writeNotifier->setEnabled(false); - if (d->exceptNotifier) - d->exceptNotifier->setEnabled(false); + d->readNotificationsEnabled = false; + d->writeNotificationsEnabled = false; + d->exceptNotificationsEnabled = false; if (d->asyncSelect) { d->asyncSelect->deleteLater(); d->asyncSelect = 0; @@ -1003,18 +998,6 @@ void QSymbianSocketEngine::close() 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) @@ -1446,136 +1429,55 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) hasSetSocketError = true; } -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); Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isReadNotificationEnabled(), false); - return d->readNotifier && d->readNotifier->isEnabled(); + return d->readNotificationsEnabled; } 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) { - 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); - } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::setReadNotificationEnabled" << enable << "socket" << d->socketDescriptor; +#endif + d->readNotificationsEnabled = enable; + if (enable && d->threadData->eventDispatcher && !d->asyncSelect) + d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); // 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::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); Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isWriteNotificationEnabled(), false); - return d->writeNotifier && d->writeNotifier->isEnabled(); + return d->writeNotificationsEnabled; } 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) { - QWriteNotifier *wn = new QWriteNotifier(d->socketDescriptor, this); - d->writeNotifier = 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); - } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::setWriteNotificationEnabled" << enable << "socket" << d->socketDescriptor; +#endif + d->writeNotificationsEnabled = enable; + if (enable && d->threadData->eventDispatcher && !d->asyncSelect) + d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); // 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); -} - bool QSymbianSocketEngine::isExceptionNotificationEnabled() const { Q_D(const QSymbianSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isExceptionNotificationEnabled(), false); - return d->exceptNotifier && d->exceptNotifier->isEnabled(); + return d->exceptNotificationsEnabled; return false; } @@ -1584,16 +1486,12 @@ 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) { - 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); - } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::setExceptionNotificationEnabled" << enable << "socket" << d->socketDescriptor; +#endif + d->exceptNotificationsEnabled = enable; + if (enable && d->threadData->eventDispatcher && !d->asyncSelect) + d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); if (d->asyncSelect) d->asyncSelect->IssueRequest(); } @@ -1692,7 +1590,7 @@ bool QSymbianSocketEngine::event(QEvent* ev) switch (ev->type()) { case QEvent::ThreadChange: #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "ThreadChange"; + qDebug() << "ThreadChange" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; #endif if (d->asyncSelect) { delete d->asyncSelect; @@ -1704,22 +1602,11 @@ bool QSymbianSocketEngine::event(QEvent* ev) return true; case PostThreadChangeEvent: #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "PostThreadChangeEvent"; + qDebug() << "PostThreadChangeEvent" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; #endif // 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()); - } + d->asyncSelect->IssueRequest(); return true; } return QAbstractSocketEngine::event(ev); @@ -1758,11 +1645,10 @@ 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); + if (engine->isExceptionNotificationEnabled()) + engine->exceptionNotification(); + if (engine->isReadNotificationEnabled()) + engine->readNotification(); } QT_CATCH(...) {} } @@ -1781,17 +1667,20 @@ void QAsyncSelect::run() m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested //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); + if (engine && engine->isReadNotificationEnabled() + && ((m_selectBuf() & KSockSelectRead) || iStatus != KErrNone)) { + engine->readNotification(); } - if (iWriteN && ((m_selectBuf() & KSockSelectWrite) || iStatus != KErrNone)) { - QEvent e(QEvent::SockAct); - iWriteN->event(&e); + if (engine && engine->isWriteNotificationEnabled() + && ((m_selectBuf() & KSockSelectWrite) || iStatus != KErrNone)) { + if (engine->state() == QAbstractSocket::ConnectingState) + engine->connectionNotification(); + else + engine->writeNotification(); } - if (iExcN && ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone)) { - QEvent e(QEvent::SockAct); - iExcN->event(&e); + if (engine && engine->isExceptionNotificationEnabled() + && ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone)) { + engine->exceptionNotification(); } m_inSocketEvent = false; if (m_deleteLater) { @@ -1805,9 +1694,6 @@ void QAsyncSelect::run() void QAsyncSelect::deleteLater() { if (m_inSocketEvent) { - iExcN = 0; - iReadN = 0; - iWriteN = 0; engine = 0; m_deleteLater = true; } else { @@ -1820,13 +1706,16 @@ 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()) + if (engine->isReadNotificationEnabled()) selectFlags |= KSockSelectRead; - if (iWriteN && iWriteN->isEnabled()) + if (engine->isWriteNotificationEnabled()) selectFlags |= KSockSelectWrite; - if (iExcN && iExcN->isEnabled()) + if (engine->isExceptionNotificationEnabled()) selectFlags |= KSockSelectExcept; if (selectFlags != m_selectFlags) { +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QAsyncSelect::IssueRequest() - select flags" << m_selectFlags << "->" << selectFlags; +#endif Cancel(); m_selectFlags = selectFlags; } @@ -1836,6 +1725,9 @@ void QAsyncSelect::IssueRequest() m_socket.Ioctl(KIOctlSelect, iStatus, &m_selectBuf, KSOLSocket); SetActive(); } +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QAsyncSelect::IssueRequest() - IsActive" << IsActive(); +#endif } QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index bc39450..432e4dc 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -162,10 +162,6 @@ public: 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(); @@ -173,9 +169,6 @@ protected: TInt RunError(TInt aError); private: - QReadNotifier* iReadN; - QWriteNotifier* iWriteN; - QExceptionNotifier* iExcN; bool m_inSocketEvent; bool m_deleteLater; RSocket &m_socket; @@ -198,7 +191,9 @@ public: RSocketServ& socketServer; mutable RTimer selectTimer; - QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; + bool readNotificationsEnabled; + bool writeNotificationsEnabled; + bool exceptNotificationsEnabled; QAsyncSelect* asyncSelect; // FIXME this is duplicated from qnativesocketengine_p.h -- cgit v0.12 From 230ef5e3ad8bb4dadef7dbf2c8bf41156bf30130 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 11 Mar 2011 16:59:48 +0000 Subject: tst_QNetworkReply::ioGetFromBuiltinHttp issues The https:limited subtest was too slow and didn't fail in the expected place (it was expected to be too fast) Both limited test cases timed out when debug enabled in the socket engine, so the timeout is increased from 11->30 seconds Reviewed-by: Markus Goetz --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 7fde3f8..ffe7ea4 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -3846,7 +3846,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTime loopTime; loopTime.start(); - QTestEventLoop::instance().enterLoop(11); + QTestEventLoop::instance().enterLoop(30); const int elapsedTime = loopTime.elapsed(); server.wait(); reader.wrapUp(); @@ -3878,10 +3878,9 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() const int minRate = rate * 1024 * (100-allowedDeviation) / 100; const int maxRate = rate * 1024 * (100+allowedDeviation) / 100; qDebug() << minRate << "<="<< server.transferRate << "<=" << maxRate << "?"; - QVERIFY(server.transferRate >= minRate); QEXPECT_FAIL("http+limited", "Limiting is broken right now, check QTBUG-15065", Continue); QEXPECT_FAIL("https+limited", "Limiting is broken right now, check QTBUG-15065", Continue); - QVERIFY(server.transferRate <= maxRate); + QVERIFY(server.transferRate >= minRate && server.transferRate <= maxRate); } } -- cgit v0.12 From b24711c377d5d0eab17d729d3d1291771410b846 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 11 Mar 2011 19:19:07 +0000 Subject: Fix capabilities in qtpcsocket autotest Moved from the subdirs pro file to the executable pro files. Reviewed-by: Markus Goetz --- tests/auto/qtcpsocket/qtcpsocket.pro | 1 - tests/auto/qtcpsocket/stressTest/stressTest.pro | 1 + tests/auto/qtcpsocket/test/test.pro | 5 ++++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/auto/qtcpsocket/qtcpsocket.pro b/tests/auto/qtcpsocket/qtcpsocket.pro index 8b1f664..5dfff5b 100644 --- a/tests/auto/qtcpsocket/qtcpsocket.pro +++ b/tests/auto/qtcpsocket/qtcpsocket.pro @@ -6,4 +6,3 @@ wince*|symbian|vxworks* : SUBDIRS = test requires(contains(QT_CONFIG,private_tests)) -symbian: TARGET.CAPABILITY = NetworkServices diff --git a/tests/auto/qtcpsocket/stressTest/stressTest.pro b/tests/auto/qtcpsocket/stressTest/stressTest.pro index 9a653c6..adf0217 100644 --- a/tests/auto/qtcpsocket/stressTest/stressTest.pro +++ b/tests/auto/qtcpsocket/stressTest/stressTest.pro @@ -9,4 +9,5 @@ DESTDIR = ./ MOC_DIR = .moc/ TMP_DIR = .tmp/ +symbian: TARGET.CAPABILITY = NetworkServices diff --git a/tests/auto/qtcpsocket/test/test.pro b/tests/auto/qtcpsocket/test/test.pro index 5dde565..f4207d6 100644 --- a/tests/auto/qtcpsocket/test/test.pro +++ b/tests/auto/qtcpsocket/test/test.pro @@ -11,7 +11,10 @@ wince*: { QT += network vxworks:QT -= gui -symbian: TARGET.EPOCHEAPSIZE="0x100 0x3000000" +symbian: { + TARGET.EPOCHEAPSIZE="0x100 0x3000000" + TARGET.CAPABILITY = NetworkServices +} TARGET = tst_qtcpsocket -- cgit v0.12 From cec4faf5b0eb2d5f55c4651c1a8e6137808c21c7 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 11 Mar 2011 19:40:32 +0000 Subject: Fix for server.listen getting IPv6 address Reviewed-by: Markus Goetz --- tests/auto/qtcpsocket/tst_qtcpsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index b972130..6852e29 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -1432,7 +1432,7 @@ void tst_QTcpSocket::dontCloseOnTimeout() QVERIFY(server.listen()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.serverAddress() == QHostAddress::Any)) + if (!(server.serverAddress() == QHostAddress::Any) && !(server.serverAddress() == QHostAddress::AnyIPv6)) serverAddress = server.serverAddress(); QTcpSocket *socket = newSocket(); -- cgit v0.12 From 76a18d2eab6b94929f79dc0c4bec59caaaa8d270 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 14 Mar 2011 16:17:10 +0000 Subject: Enable IPv6 test in QNetworkInterface autotest IPv6 test was skipped for symbian, now enabled it. Also start the default bearer before testing, so there are interfaces other than loopback available to test. Reviewed-by: Markus Goetz --- .../qnetworkinterface/tst_qnetworkinterface.cpp | 38 ++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp index 0d7c68e..c630eca 100644 --- a/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp +++ b/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include "../network-settings.h" //TESTED_FILES=qnetworkinterface.cpp qnetworkinterface.h qnetworkinterface_unix.cpp qnetworkinterface_win.cpp @@ -58,23 +60,52 @@ public: virtual ~tst_QNetworkInterface(); private slots: + void initTestCase(); + void cleanupTestCase(); void dump(); void loopbackIPv4(); void loopbackIPv6(); void localAddress(); void interfaceFromXXX(); void copyInvalidInterface(); + +private: +#ifndef QT_NO_BEARER_MANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif }; tst_QNetworkInterface::tst_QNetworkInterface() { - Q_SET_DEFAULT_IAP } tst_QNetworkInterface::~tst_QNetworkInterface() { } +void tst_QNetworkInterface::initTestCase() +{ +#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_QNetworkInterface::cleanupTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + if (networkSession && networkSession->isOpen()) { + networkSession->close(); + } +#endif +} void tst_QNetworkInterface::dump() { @@ -127,10 +158,6 @@ void tst_QNetworkInterface::loopbackIPv4() void tst_QNetworkInterface::loopbackIPv6() { -#ifdef Q_OS_SYMBIAN - QSKIP( "Symbian: IPv6 is not yet supported", SkipAll ); -#else - QList all = QNetworkInterface::allAddresses(); bool loopbackfound = false; @@ -144,7 +171,6 @@ void tst_QNetworkInterface::loopbackIPv6() anyIPv6 = true; QVERIFY(!anyIPv6 || loopbackfound); -#endif } void tst_QNetworkInterface::localAddress() -- cgit v0.12 From 981ca30f216b4655b4c171aba5bcb37890cb92b1 Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Tue, 15 Mar 2011 12:25:28 +0100 Subject: SSL: fix compilation on Windows Reviewed-by: Markus Goetz --- src/network/ssl/qsslsocket_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 7b92f95..4662c56 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE typedef OSStatus (*PtrSecTrustSettingsCopyCertificates)(int, CFArrayRef*); typedef OSStatus (*PtrSecTrustCopyAnchorCertificates)(CFArrayRef*); #elif defined(Q_OS_WIN) +#include #include #ifndef HCRYPTPROV_LEGACY #define HCRYPTPROV_LEGACY HCRYPTPROV -- cgit v0.12 From 86b1e68285a4dae855a5826f76728cee347d1af2 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 15 Mar 2011 15:21:39 +0100 Subject: tst_qhostinfo: Fixes Reviewed-by: Peter Hartmann --- tests/auto/qhostinfo/tst_qhostinfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qhostinfo/tst_qhostinfo.cpp b/tests/auto/qhostinfo/tst_qhostinfo.cpp index ee2fe0d..8be8dcb 100644 --- a/tests/auto/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/qhostinfo/tst_qhostinfo.cpp @@ -291,6 +291,7 @@ void tst_QHostInfo::lookupIPv6_data() QTest::addColumn("err"); QTest::newRow("ip6") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError); + QTest::newRow("ip6") << "ipv6.google.com" << "2A00:1450:8007:0:0:0:0:63" << int(QHostInfo::NoError); // avoid using real IPv6 addresses here because this will do a DNS query // real addresses are between 2000:: and 3fff:ffff:ffff:ffff:ffff:ffff:ffff @@ -337,7 +338,7 @@ void tst_QHostInfo::reverseLookup_data() // ### Use internal DNS instead. Discussed with Andreas. //QTest::newRow("classical.hexago.com") << QString("2001:5c0:0:2::24") << QStringList(QString("classical.hexago.com")) << 0; - QTest::newRow("origin.cisco.com") << QString("12.159.148.94") << QStringList(QString("origin.cisco.com")) << 0; + QTest::newRow("gitorious.org") << QString("87.238.52.168") << QStringList(QString("gitorious.org")) << 0; QTest::newRow("bogus-name") << QString("1::2::3::4") << QStringList() << 1; } -- cgit v0.12 From 59c7740c9d45a88713db20efbfcfbdaf3873b60c Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 15 Mar 2011 18:47:11 +0000 Subject: Make creating sockets with an explicit network session thread safe Added a mutex to QNetworkSessionPrivate Lock the mutex in the symbian bearer plugin for functions that change the validity of the RConnection. Added factory functions to open an RSocket or RHostResolver, which lock the mutex before the esock function calls. If there is no RConnection, then KErrNotReady is returned (the same as when there is an RConnection but it has not been started). Task-number: QTBUG-18143 Reviewed-by: Markus Goetz --- src/network/bearer/qnetworksession.cpp | 31 ++++++++++++++++++++++ src/network/bearer/qnetworksession_p.h | 9 +++++++ src/network/socket/qsymbiansocketengine.cpp | 14 +++------- .../bearer/symbian/qnetworksession_impl.cpp | 3 +++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index 6106550..21e64d9 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -44,10 +44,16 @@ #include #include +#include #include "qnetworkconfigmanager_p.h" #include "qnetworksession_p.h" +#ifdef Q_OS_SYMBIAN +#include +#include +#endif + #ifndef QT_NO_BEARERMANAGEMENT QT_BEGIN_NAMESPACE @@ -710,8 +716,33 @@ RConnection* QNetworkSessionPrivate::nativeSession(QNetworkSession &s) { if (!s.d) return 0; + if (s.thread() != QThread::currentThread()) + qWarning("QNetworkSessionPrivate::nativeSession called in wrong thread"); return s.d->nativeSession(); } + +TInt QNetworkSessionPrivate::nativeOpenSocket(QNetworkSession& s, RSocket& sock, TUint family, TUint type, TUint protocol) +{ + if (!s.d) + return 0; + QMutexLocker lock(&(s.d->mutex)); + RConnection *con = s.d->nativeSession(); + if (!con || !con->SubSessionHandle()) + return KErrNotReady; + return sock.Open(qt_symbianGetSocketServer(), family, type, protocol, *con); +} + +TInt QNetworkSessionPrivate::nativeOpenHostResolver(QNetworkSession& s, RHostResolver& resolver, TUint family, TUint protocol) +{ + if (!s.d) + return 0; + QMutexLocker lock(&(s.d->mutex)); + RConnection *con = s.d->nativeSession(); + if (!con || !con->SubSessionHandle()) + return KErrNotReady; + return resolver.Open(qt_symbianGetSocketServer(), family, protocol, *con); +} + #endif #include "moc_qnetworksession.cpp" diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h index e2fcfe6..b359f80 100644 --- a/src/network/bearer/qnetworksession_p.h +++ b/src/network/bearer/qnetworksession_p.h @@ -61,6 +61,8 @@ #ifdef Q_OS_SYMBIAN class RConnection; +class RSocket; +class RHostResolver; #endif QT_BEGIN_NAMESPACE @@ -108,8 +110,13 @@ public: virtual quint64 activeTime() const = 0; #ifdef Q_OS_SYMBIAN + // get internal RConnection (not thread safe, call only from thread that owns the QNetworkSession) static RConnection* nativeSession(QNetworkSession&); virtual RConnection* nativeSession() = 0; + // open socket using the internal RConnection (thread safe) + static TInt nativeOpenSocket(QNetworkSession& session, RSocket& socket, TUint family, TUint type, TUint protocol); + // open host resolver using the internal RConnection (thread safe) + static TInt nativeOpenHostResolver(QNetworkSession& session, RHostResolver& resolver, TUint family, TUint protocol); #endif protected: inline QNetworkConfigurationPrivatePointer privateConfiguration(const QNetworkConfiguration &config) const @@ -150,6 +157,8 @@ protected: QNetworkSession::State state; bool isOpen; + + QMutex mutex; }; QT_END_NAMESPACE diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index be04b56..688f724 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -189,21 +189,13 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so //Check if there is a user specified session RConnection *connection = 0; QVariant v(q->property("_q_networksession")); + TInt err; if (v.isValid()) { QSharedPointer s = qvariant_cast >(v); - connection = QNetworkSessionPrivate::nativeSession(*s); + err = QNetworkSessionPrivate::nativeOpenSocket(*s, nativeSocket, family, type, protocol); #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << connection; + qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << err; #endif - } - TInt err; - 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 diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 5325293..a9bd414 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -76,6 +76,7 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) void QNetworkSessionPrivateImpl::closeHandles() { + QMutexLocker lock(&mutex); // Cancel Connection Progress Notifications first. // Note: ConnectionNotifier must be destroyed before RConnection::Close() // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification() @@ -317,6 +318,7 @@ QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const void QNetworkSessionPrivateImpl::open() { + QMutexLocker lock(&mutex); #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "open() called, session state is: " << state << " and isOpen is: " @@ -526,6 +528,7 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) void QNetworkSessionPrivateImpl::stop() { + QMutexLocker lock(&mutex); #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "stop() called, session state is: " << state << " and isOpen is : " -- cgit v0.12 From 8f239f0b0cb7faa580ba66197f56fb3d8109aaf7 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 16 Mar 2011 13:00:43 +0000 Subject: Implement IPv6 in symbian QNetworkInterface For IPv6 interfaces, the network mask is reported correctly, so we use that. For IPv4 interfaces, the network mask is reported as 0.0.0.0 so the existing workaround to get the netmask from routes is used. For loopback interfaces, the mask can be statically determined. Skip checking the routes if proper masks were reported for all the interfaces. Added a helper function for converting TInetAddr -> QHostAddress using the constructors that take binary data. (better than conversion to/from strings) Task-number: QTBUG-18137 Reviewed-by: Markus Goetz --- src/network/kernel/qnetworkinterface_symbian.cpp | 128 +++++++++++++++-------- 1 file changed, 83 insertions(+), 45 deletions(-) diff --git a/src/network/kernel/qnetworkinterface_symbian.cpp b/src/network/kernel/qnetworkinterface_symbian.cpp index 42a041c..7767f54 100644 --- a/src/network/kernel/qnetworkinterface_symbian.cpp +++ b/src/network/kernel/qnetworkinterface_symbian.cpp @@ -67,10 +67,24 @@ static QNetworkInterface::InterfaceFlags convertFlags(const TSoInetInterfaceInfo return flags; } +//TODO: share this, at least QHostInfo needs to do the same thing +static QHostAddress qt_QHostAddressFromTInetAddr(const TInetAddr& addr) +{ + //TODO: do we want to call v4 mapped addresses v4 or v6 outside of this file? + if (addr.IsV4Mapped() || addr.Family() == KAfInet) { + //convert v4 host address + return QHostAddress(addr.Address()); + } else { + //convert v6 host address + return QHostAddress((quint8 *)(addr.Ip6Address().u.iAddr8)); + } +} + static QList interfaceListing() { TInt err(KErrNone); QList interfaces; + QList addressesWithEstimatedNetmasks; // Open dummy socket for interface queries RSocket socket; @@ -90,8 +104,7 @@ static QList interfaceListing() TPckgBuf infoPckg; TSoInetInterfaceInfo &info = infoPckg(); while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, infoPckg) == KErrNone) { - // Do not include IPv6 addresses because netmask and broadcast address cannot be determined correctly - if (info.iName != KNullDesC && info.iAddress.IsV4Mapped()) { + if (info.iName != KNullDesC) { TName address; QNetworkAddressEntry entry; QNetworkInterfacePrivate *iface = 0; @@ -113,40 +126,58 @@ static QList interfaceListing() } // Get the address of the interface - info.iAddress.Output(address); - entry.setIp(QHostAddress(qt_TDesC2QString(address))); + entry.setIp(qt_QHostAddressFromTInetAddr(info.iAddress)); + +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << "address is" << info.iAddress.Family() << entry.ip(); + qDebug() << "netmask is" << info.iNetMask.Family() << qt_QHostAddressFromTInetAddr( info.iNetMask ); +#endif // Get the interface netmask - // For some reason netmask is always 0.0.0.0 - // info.iNetMask.Output(address); - // entry.setNetmask( QHostAddress( qt_TDesC2QString( address ) ) ); - - // Workaround: Let Symbian determine netmask based on IP address class - // TODO: Works only for IPv4 - Task: 259128 Implement IPv6 support - TInetAddr netmask; - netmask.NetMask(info.iAddress); - netmask.Output(address); - entry.setNetmask(QHostAddress(qt_TDesC2QString(address))); - - // Get the interface broadcast address - if (iface->flags & QNetworkInterface::CanBroadcast) { - // For some reason broadcast address is always 0.0.0.0 - // info.iBrdAddr.Output(address); - // entry.setBroadcast( QHostAddress( qt_TDesC2QString( address ) ) ); - - // Workaround: Let Symbian determine broadcast address based on IP address - // TODO: Works only for IPv4 - Task: 259128 Implement IPv6 support - TInetAddr broadcast; - broadcast.NetBroadcast(info.iAddress); - broadcast.Output(address); - entry.setBroadcast(QHostAddress(qt_TDesC2QString(address))); + if (info.iNetMask.IsUnspecified()) { + // For some reason netmask is always 0.0.0.0 for IPv4 interfaces + // and loopback interfaces (which we statically know) + if (info.iAddress.IsV4Mapped()) { + if (info.iFeatures & KIfIsLoopback) { + entry.setPrefixLength(32); + } else { + // Workaround: Let Symbian determine netmask based on IP address class (IPv4 only API) + TInetAddr netmask; + netmask.NetMask(info.iAddress); + entry.setNetmask(QHostAddress(netmask.Address())); //binary convert v4 address + addressesWithEstimatedNetmasks << entry.ip(); +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << "address class determined netmask" << entry.netmask(); +#endif + } + } else { + // For IPv6 interfaces + if (info.iFeatures & KIfIsLoopback) { + entry.setPrefixLength(128); + } else if (info.iNetMask.IsUnspecified()) { + //Don't see this error for IPv6, but try to handle it if it happens + entry.setPrefixLength(64); //most common +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << "total guess netmask" << entry.netmask(); +#endif + addressesWithEstimatedNetmasks << entry.ip(); + } + } + } else { + //Expected code path for IPv6 non loopback interfaces (IPv4 could come here if symbian is fixed) + entry.setNetmask(qt_QHostAddressFromTInetAddr(info.iNetMask)); +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << "reported netmask" << entry.netmask(); +#endif } + // broadcast address is determined from the netmask in postProcess() + // Add new entry to interface address entries iface->addressEntries << entry; #if defined(QNETWORKINTERFACE_DEBUG) - printf("\n Found network interface %s, interface flags:\n\ + qDebug("\n Found network interface %s, interface flags:\n\ IsUp = %d, IsRunning = %d, CanBroadcast = %d,\n\ IsLoopBack = %d, IsPointToPoint = %d, CanMulticast = %d, \n\ ip = %s, netmask = %s, broadcast = %s,\n\ @@ -160,8 +191,14 @@ static QList interfaceListing() } } + // if we didn't have to guess any netmasks, then we're done. + if (addressesWithEstimatedNetmasks.isEmpty()) { + socket.Close(); + return interfaces; + } + // we will try to use routing info to detect more precisely - // netmask and then ::postProcess() should calculate + // estimated netmasks and then ::postProcess() should calculate // broadcast addresses // use dummy socket to start enumerating routes @@ -176,16 +213,21 @@ static QList interfaceListing() TSoInetRouteInfo routeInfo; TPckg routeInfoPkg(routeInfo); while (socket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, routeInfoPkg) == KErrNone) { - TName address; - // get interface address - routeInfo.iIfAddr.Output(address); - QHostAddress ifAddr(qt_TDesC2QString(address)); + QHostAddress ifAddr(qt_QHostAddressFromTInetAddr(routeInfo.iIfAddr)); if (ifAddr.isNull()) continue; + if (!addressesWithEstimatedNetmasks.contains(ifAddr)) { +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << "skipping route from" << ifAddr << "because it wasn't an estimated netmask"; +#endif + continue; + } - routeInfo.iDstAddr.Output(address); - QHostAddress destination(qt_TDesC2QString(address)); + QHostAddress destination(qt_QHostAddressFromTInetAddr(routeInfo.iDstAddr)); +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << "route from" << ifAddr << "to" << destination; +#endif if (destination.isNull() || destination != ifAddr) continue; @@ -196,17 +238,13 @@ static QList interfaceListing() QNetworkAddressEntry entry = iface->addressEntries.at(eindex); if (entry.ip() != ifAddr) { continue; - } else if (entry.ip().protocol() != QAbstractSocket::IPv4Protocol) { - // skip if not IPv4 address (e.g. IPv6) - // as results not reliable on Symbian - continue; - } else { - routeInfo.iNetMask.Output(address); - QHostAddress netmask(qt_TDesC2QString(address)); + } else if (!routeInfo.iNetMask.IsUnspecified()) { + //the route may also return 0.0.0.0 netmask, in which case don't use it. + QHostAddress netmask(qt_QHostAddressFromTInetAddr(routeInfo.iNetMask)); entry.setNetmask(netmask); - // NULL boradcast address for - // ::postProcess to have effect - entry.setBroadcast(QHostAddress()); +#if defined(QNETWORKINTERFACE_DEBUG) + qDebug() << " - route netmask" << routeInfo.iNetMask.Family() << netmask << " (using route determined netmask)"; +#endif iface->addressEntries.replace(eindex, entry); } } -- cgit v0.12 From 6f7076d6fe80f656d8d2f7f1b005dc138b05bef3 Mon Sep 17 00:00:00 2001 From: Aaron Tunney Date: Wed, 9 Mar 2011 14:26:43 +0000 Subject: Implementation of async DNS lookup. Reviewed-by: Shane Kearns --- src/network/kernel/qhostinfo.cpp | 53 ++++- src/network/kernel/qhostinfo_p.h | 115 ++++++++++- src/network/kernel/qhostinfo_symbian.cpp | 323 ++++++++++++++++++++++++++++++- 3 files changed, 473 insertions(+), 18 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 5ec6041..7a15a05 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -56,10 +56,14 @@ QT_BEGIN_NAMESPACE -Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) - //#define QHOSTINFO_DEBUG +#ifndef Q_OS_SYMBIAN +Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) +#else +Q_GLOBAL_STATIC(QSymbianHostInfoLookupManger, theHostInfoLookupManager) +#endif + /*! \class QHostInfo \brief The QHostInfo class provides static functions for host name lookups. @@ -152,6 +156,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, qDebug("QHostInfo::lookupHost(\"%s\", %p, %s)", name.toLatin1().constData(), receiver, member ? member + 1 : 0); #endif + if (!QAbstractEventDispatcher::instance(QThread::currentThread())) { qWarning("QHostInfo::lookupHost() called with no event dispatcher"); return -1; @@ -172,7 +177,9 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, return id; } +#ifndef Q_OS_SYMBIAN QHostInfoLookupManager *manager = theHostInfoLookupManager(); + if (manager) { // the application is still alive if (manager->cache.isEnabled()) { @@ -187,11 +194,38 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, return id; } } + // cache is not enabled or it was not in the cache, do normal lookup QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id); QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); manager->scheduleLookup(runnable); } +#else + QSymbianHostInfoLookupManger *manager = theHostInfoLookupManager(); + + if (manager) { + // the application is still alive + if (manager->cache.isEnabled()) { + // check cache first + bool valid = false; + QHostInfo info = manager->cache.get(name, &valid); + if (valid) { + info.setLookupId(id); + QHostInfoResult result; + QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + result.emitResultsReady(info); + return id; + } + } + + // cache is not enabled or it was not in the cache, do normal lookup + QSymbianHostResolver *symbianResolver = 0; + QT_TRAP_THROWING(symbianResolver = new QSymbianHostResolver(name, id)); + QObject::connect(&symbianResolver->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + manager->scheduleLookup(symbianResolver); + } +#endif + return id; } @@ -225,7 +259,7 @@ QHostInfo QHostInfo::fromName(const QString &name) #endif QHostInfo hostInfo = QHostInfoAgent::fromName(name); - QHostInfoLookupManager *manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); manager->cache.put(name, hostInfo); return hostInfo; } @@ -406,6 +440,7 @@ void QHostInfo::setErrorString(const QString &str) \sa hostName() */ +#ifndef Q_OS_SYMBIAN QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i) { setAutoDelete(true); @@ -632,6 +667,7 @@ void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r) finishedLookups.append(r); work(); } +#endif // This function returns immediately when we had a result in the cache, else it will later emit a signal QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id) @@ -640,7 +676,7 @@ QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *id = -1; // check cache - QHostInfoLookupManager* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); if (manager && manager->cache.isEnabled()) { QHostInfo info = manager->cache.get(name, valid); if (*valid) { @@ -657,7 +693,7 @@ QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char void qt_qhostinfo_clear_cache() { - QHostInfoLookupManager* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); if (manager) { manager->clear(); } @@ -665,7 +701,7 @@ void qt_qhostinfo_clear_cache() void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) { - QHostInfoLookupManager* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); if (manager) { manager->cache.setEnabled(e); } @@ -733,4 +769,9 @@ void QHostInfoCache::clear() cache.clear(); } +QAbstractHostInfoLookupManger* QAbstractHostInfoLookupManger::globalInstance() +{ + return theHostInfoLookupManager(); +} + QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index b568ec2..ec7a63e 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -69,9 +69,18 @@ #include #include +#include + +#ifdef Q_OS_SYMBIAN +// Symbian Headers +#include +#include +#endif + QT_BEGIN_NAMESPACE + class QHostInfoResult : public QObject { Q_OBJECT @@ -91,6 +100,12 @@ class QHostInfoAgent : public QObject Q_OBJECT public: static QHostInfo fromName(const QString &hostName); + static QHostInfo fromName(const QString &hostName, QSharedPointer networkSession); + +#ifdef Q_OS_SYMBIAN + static int lookupHost(const QString &name, QObject *receiver, const char *member); + static void abortHostLookup(int lookupId); +#endif }; class QHostInfoPrivate @@ -151,7 +166,25 @@ public: QHostInfoResult resultEmitter; }; -class QHostInfoLookupManager : public QObject + +class QAbstractHostInfoLookupManger : public QObject +{ + Q_OBJECT + +public: + ~QAbstractHostInfoLookupManger() {} + virtual void clear() = 0; + + QHostInfoCache cache; + +protected: + QAbstractHostInfoLookupManger() {} + static QAbstractHostInfoLookupManger* globalInstance(); + +}; + +#ifndef Q_OS_SYMBIAN +class QHostInfoLookupManager : public QAbstractInfoLookupManager { Q_OBJECT public: @@ -169,8 +202,6 @@ public: void lookupFinished(QHostInfoRunnable *r); bool wasAborted(int id); - QHostInfoCache cache; - friend class QHostInfoRunnable; protected: QList currentLookups; // in progress @@ -189,6 +220,84 @@ private slots: void waitForThreadPoolDone() { threadPool.waitForDone(); } }; +#else + +class QSymbianHostResolver : public CActive +{ +public: + QSymbianHostResolver(const QString &hostName, int id); + ~QSymbianHostResolver(); + + QHostInfo requestHostLookup(); + int id(); + + QHostInfoResult resultEmitter; + +private: + void DoCancel(); + void RunL(); + void run(); + TInt RunError(TInt aError); + + void processNameResults(); + void processAddressResults(); + +private: + int iId; + + const QString iHostName; + + RSocketServ& iSocketServ; + RHostResolver iHostResolver; + + TRequestStatus iStatus; + + TNameEntry iNameResult; + QHostAddress iAddress; + + QHostInfo iResults; + + enum { + EIdle, + EGetByName, + EGetByAddress + } iState; +}; + +class QSymbianHostInfoLookupManger : public QAbstractHostInfoLookupManger +{ + Q_OBJECT +public: + QSymbianHostInfoLookupManger(); + ~QSymbianHostInfoLookupManger(); + + static QSymbianHostInfoLookupManger* globalInstance(); + + int id(); + void clear(); + + // called from QHostInfo + void scheduleLookup(QSymbianHostResolver *r); + void abortLookup(int id); + + // called from QSymbianHostResolver + void lookupFinished(QSymbianHostResolver *r); + +private: + void runNextLookup(); + + static const int KMaxConcurrentLookups = 5; + + RPointerArray iCurrentLookups; + RPointerArray iScheduledLookups; + RPointerArray iFinishedLookups; + + QMutex mutex; +}; +#endif + + + QT_END_NAMESPACE #endif // QHOSTINFO_P_H diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 9599274..2b582bd 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -41,10 +41,6 @@ //#define QHOSTINFO_DEBUG -// Symbian Headers -#include -#include - // Qt Headers #include #include @@ -54,11 +50,13 @@ #include "qhostinfo_p.h" #include +#include QT_BEGIN_NAMESPACE -QHostInfo QHostInfoAgent::fromName(const QString &hostName) + +QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer networkSession) { QHostInfo results; @@ -66,12 +64,20 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) RSocketServ socketServ(qt_symbianGetSocketServer()); RHostResolver hostResolver; + + // TODO - check if networkSession is null + // RConnection connection = magicalApi(networkSession); + // int err = connection.Open(blah, blah); + // if (err) { + // do something; + // } + // 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)); + results.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); return results; } @@ -99,7 +105,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Symbian error code: %1").arg(err)); + results.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); } return results; @@ -134,7 +140,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) results.setErrorString(tr("Host not found")); } else { results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Symbian error code: %1").arg(err)); + results.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); } return results; @@ -156,7 +162,8 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) hostAdd = nameResult().iAddr; hostAdd.Output(ipAddr); - if (ipAddr.Length() > 0) { + // Ensure that record is valid (not an alias and with length greater than 0) + if (!(nameResult().iFlags & TNameRecord::EAlias) && (ipAddr.Length() > 0)) { if (nameResult().iAddr.Family() == KAfInet) { // IPv4 - prepend hostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); @@ -173,6 +180,13 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } +QHostInfo QHostInfoAgent::fromName(const QString &hostName) +{ + // null shared pointer + QSharedPointer networkSession; + return fromName(hostName, networkSession); +} + QString QHostInfo::localHostName() { // Connect to ESOCK @@ -201,4 +215,295 @@ QString QHostInfo::localDomainName() return QString(); } + +QSymbianHostResolver::QSymbianHostResolver(const QString &hostName, int identifier) + : CActive(CActive::EPriorityStandard), iId(identifier), iHostName(hostName), + iSocketServ(qt_symbianGetSocketServer()) +{ + CActiveScheduler::Add(this); +} + +QSymbianHostResolver::~QSymbianHostResolver() +{ + Cancel(); + iHostResolver.Close(); +} + +// Async equivalent to QHostInfoAgent::fromName() +QHostInfo QSymbianHostResolver::requestHostLookup() +{ + +#if defined(QHOSTINFO_DEBUG) + qDebug("QHostInfoAgent::fromName(%s) looking up...", + hostName.toLatin1().constData()); +#endif + + int err = iHostResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp); + if (err) { + // What are we doing with iResults?? + iResults.setError(QHostInfo::UnknownError); + iResults.setErrorString(QObject::tr("Symbian error code: %1").arg(err)); + + iHostResolver.Close(); + return iResults; + } + + if (iAddress.setAddress(iHostName)) { + // Reverse lookup + + TInetAddr IpAdd; + IpAdd.Input(qt_QString2TPtrC(iHostName)); + + // Asynchronous request. + iHostResolver.GetByAddress(IpAdd, iNameResult, iStatus); // <---- ASYNC + iState = EGetByAddress; + + } else { + + // IDN support + QByteArray aceHostname = QUrl::toAce(iHostName); + iResults.setHostName(iHostName); + if (aceHostname.isEmpty()) { + iResults.setError(QHostInfo::HostNotFound); + iResults.setErrorString(iHostName.isEmpty() ? + QCoreApplication::translate("QHostInfoAgent", "No host name given") : + QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); + + iHostResolver.Close(); + return iResults; + } + + // Asynchronous request. + iHostResolver.GetByName(qt_QString2TPtrC(QString::fromLatin1(aceHostname)), iNameResult, iStatus); + iState = EGetByName; + } + + SetActive(); + + return iResults; +} + +void QSymbianHostResolver::DoCancel() +{ + QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + manager->lookupFinished(this); + iHostResolver.Cancel(); +} + +void QSymbianHostResolver::RunL() +{ + QT_TRYCATCH_LEAVING(run()); +} + +void QSymbianHostResolver::run() +{ + if (iState == EGetByName) + processNameResults(); + else if (iState == EGetByAddress) + processAddressResults(); + + iState = EIdle; + + QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + manager->lookupFinished(this); + + resultEmitter.emitResultsReady(iResults); + + delete this; +} + +TInt QSymbianHostResolver::RunError(TInt aError) +{ + QT_TRY { + iState = EIdle; + + QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + manager->lookupFinished(this); + + iResults.setError(QHostInfo::UnknownError); + iResults.setErrorString(QSystemError(aError,QSystemError::NativeError).toString()); + + resultEmitter.emitResultsReady(iResults); + } + QT_CATCH(...) {} + + delete this; + + return KErrNone; +} + +void QSymbianHostResolver::processNameResults() +{ + TInt err = iStatus.Int(); + if (err < 0) { + // TODO - Could there be other errors? Symbian docs don't say. + if (err = KErrNotFound) { + iResults.setError(QHostInfo::HostNotFound); + iResults.setErrorString(QObject::tr("Host not found")); + } else { + iResults.setError(QHostInfo::UnknownError); + iResults.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); + } + + iHostResolver.Close(); + return; + } + + QList hostAddresses; + + TInetAddr hostAdd = iNameResult().iAddr; + // 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) + hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + + // Check if there's more than one IP address linkd to this name + while (iHostResolver.Next(iNameResult) == KErrNone) { + hostAdd = iNameResult().iAddr; + hostAdd.Output(ipAddr); + + // Ensure that record is valid (not an alias and with length greater than 0) + if (!(iNameResult().iFlags & TNameRecord::EAlias) && (ipAddr.Length() > 0)) { + if (iNameResult().iAddr.Family() == KAfInet) { + // IPv4 - prepend + hostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); + } else { + // IPv6 - append + hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + } + } + } + + iResults.setAddresses(hostAddresses); +} + +void QSymbianHostResolver::processAddressResults() +{ + TInt err = iStatus.Int(); + + if (err < 0) { + // TODO - Could there be other errors? Symbian docs don't say. + if (err = KErrNotFound) { + iResults.setError(QHostInfo::HostNotFound); + iResults.setErrorString(QObject::tr("Host not found")); + } else { + iResults.setError(QHostInfo::UnknownError); + iResults.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); + } + + return; + } + + iResults.setHostName(qt_TDesC2QString(iNameResult().iName)); + iResults.setAddresses(QList() << iAddress); +} + + +int QSymbianHostResolver::id() +{ + return iId; +} + +QSymbianHostInfoLookupManger::QSymbianHostInfoLookupManger() +{ +} + +QSymbianHostInfoLookupManger::~QSymbianHostInfoLookupManger() +{ + iCurrentLookups.Close(); + iScheduledLookups.Close(); +} + +void QSymbianHostInfoLookupManger::clear() +{ + QMutexLocker locker(&mutex); + iCurrentLookups.ResetAndDestroy(); + iScheduledLookups.ResetAndDestroy(); +} + +void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) +{ + QMutexLocker locker(&mutex); + + // remove finished lookup from array and destroy + TInt count = iCurrentLookups.Count(); + for (TInt i = 0; i < count; i++) { + if (iCurrentLookups[i]->id() == r->id()) { + iCurrentLookups.Remove(i); + break; + } + } + + runNextLookup(); +} + +void QSymbianHostInfoLookupManger::runNextLookup() +{ + // check to see if there are any scheduled lookups + if (iScheduledLookups.Count() > 0) { + // if so, move one to the current lookups and run it + // FIFO + QSymbianHostResolver* hostResolver = iScheduledLookups[0]; + iCurrentLookups.Append(hostResolver); + iScheduledLookups.Remove(0); + hostResolver->requestHostLookup(); + } +} + +// called from QHostInfo +void QSymbianHostInfoLookupManger::scheduleLookup(QSymbianHostResolver* r) +{ + QMutexLocker locker(&mutex); + + // Check to see if we have space on the current lookups pool. + if (iCurrentLookups.Count() >= KMaxConcurrentLookups) { + // If no, schedule for later. + iScheduledLookups.Append(r); + return; + } else { + // If yes, add it to the current lookups. + iCurrentLookups.Append(r); + + // ... and trigger the async call. + r->requestHostLookup(); + } +} + +void QSymbianHostInfoLookupManger::abortLookup(int id) +{ + QMutexLocker locker(&mutex); + + int i = 0; + // Find the aborted lookup by ID. + // First in the current lookups. + for (i = 0; i < iCurrentLookups.Count(); i++) { + if (id = iCurrentLookups[i]->id()) { + QSymbianHostResolver* r = iCurrentLookups[i]; + iCurrentLookups.Remove(i); + r->Cancel(); + runNextLookup(); + return; + } + } + // Then in the scheduled lookups. + for (i = 0; i < iScheduledLookups.Count(); i++) { + if (id = iScheduledLookups[i]->id()) { + QSymbianHostResolver* r = iScheduledLookups[i]; + iScheduledLookups.Remove(i); + delete r; + return; + } + } +} + + +QSymbianHostInfoLookupManger* QSymbianHostInfoLookupManger::globalInstance() +{ + return static_cast + (QAbstractHostInfoLookupManger::globalInstance()); +} + QT_END_NAMESPACE -- cgit v0.12 From 13f415e7d54ef8e2aaccabfb04f29ccfde0520df Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 16 Mar 2011 18:50:02 +0000 Subject: Make tst_QEventLoop::processEventsExcludeSocket stricter The test was only checking that the socket event is not processed when excluded. I have added an additional test that a further call with socket events included results in the deferred socket event being processed. i.e. makes sure events are deferred to later and not lost. Also fixed capabilities of the autotest, so this test case can run. Reviewed-by: Markus Goetz --- tests/auto/qeventloop/qeventloop.pro | 1 + tests/auto/qeventloop/tst_qeventloop.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/tests/auto/qeventloop/qeventloop.pro b/tests/auto/qeventloop/qeventloop.pro index f6c24ae..e7489fa 100644 --- a/tests/auto/qeventloop/qeventloop.pro +++ b/tests/auto/qeventloop/qeventloop.pro @@ -5,3 +5,4 @@ QT += network win32:!wince*:LIBS += -luser32 +symbian:TARGET.CAPABILITY += NetworkServices \ No newline at end of file diff --git a/tests/auto/qeventloop/tst_qeventloop.cpp b/tests/auto/qeventloop/tst_qeventloop.cpp index 6860f19..aad8390 100644 --- a/tests/auto/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/qeventloop/tst_qeventloop.cpp @@ -604,6 +604,7 @@ public slots: serverSocket->flush(); QCoreApplication::processEvents(QEventLoop::ExcludeSocketNotifiers); testResult = dataArrived; + QCoreApplication::processEvents(); //check the deferred event is processed serverSocket->close(); QThread::currentThread()->exit(0); } @@ -620,9 +621,11 @@ public: if (tester->init()) exec(); testResult = tester->testResult; + dataArrived = tester->dataArrived; delete tester; } bool testResult; + bool dataArrived; }; void tst_QEventLoop::processEventsExcludeSocket() @@ -631,6 +634,7 @@ void tst_QEventLoop::processEventsExcludeSocket() thread.start(); QVERIFY(thread.wait()); QVERIFY(!thread.testResult); + QVERIFY(thread.dataArrived); } class TimerReceiver : public QObject -- cgit v0.12 From 1adef92e1b1ba9872c9676efd701eb0fd0a3a907 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 16 Mar 2011 18:59:45 +0000 Subject: Implement QEventLoop::ExcludeSocketNotifiers for symbian socket engine As the symbian socket engine is driven by an active object in the QtNetwork dll, this needs to hook into the event dispatcher in the QtCore dll. The QActiveObject base class is now a private export from QtCore The method of deferring socket events now works with any kind of QActiveObject, and not only the QSocketActiveObject (which handles "open C" sockets) The base class has a new function, to check if socket events are blocked. If so, it adds the active object to the deferred queue. The derived class should return from it's RunL in this case, which will be called again later. (same usage as the maybeQueueForLater function) reactivateAndComplete function in the event dispatcher is changed to complete the active object again with the same status code as originally. Previously it always used KErrNone, which is not ok for QAsyncSelect as it needs to check the error code from the asynchronous call. Reviewed-by: Markus Goetz Reviewed-by: mread --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 79 +++++++++++++++---------- src/corelib/kernel/qeventdispatcher_symbian_p.h | 13 ++-- src/network/socket/qsymbiansocketengine.cpp | 28 +++++---- src/network/socket/qsymbiansocketengine_p.h | 4 +- 4 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index b074ab4..a95e7d5 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -134,7 +134,7 @@ private: * The QCompleteDeferredAOs class is a special object that runs after all others, which will * reactivate the objects that were previously not run. */ -inline QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher) +QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher) : CActive(priority), m_dispatcher(dispatcher), m_hasAlreadyRun(false), @@ -166,12 +166,25 @@ bool QActiveObject::maybeQueueForLater() } } +bool QActiveObject::maybeDeferSocketEvent() +{ + Q_ASSERT(!m_hasRunAgain); + Q_ASSERT(m_dispatcher); + if (!m_dispatcher->areSocketEventsBlocked()) { + return false; + } + m_hasRunAgain = true; + m_dispatcher->addDeferredSocketActiveObject(this); + return true; +} + void QActiveObject::reactivateAndComplete() { + TInt error = iStatus.Int(); iStatus = KRequestPending; SetActive(); TRequestStatus *status = &iStatus; - QEventDispatcherSymbian::RequestComplete(status, KErrNone); + QEventDispatcherSymbian::RequestComplete(status, error); m_hasRunAgain = false; m_hasAlreadyRun = false; @@ -634,10 +647,28 @@ void QSocketActiveObject::DoCancel() void QSocketActiveObject::RunL() { + if (maybeDeferSocketEvent()) + return; if (maybeQueueForLater()) return; - QT_TRYCATCH_LEAVING(m_dispatcher->socketFired(this)); + QT_TRYCATCH_LEAVING(run()); +} + +void QSocketActiveObject::run() +{ + QEvent e(QEvent::SockAct); + m_inSocketEvent = true; + QCoreApplication::sendEvent(m_notifier, &e); + m_inSocketEvent = false; + + if (m_deleteLater) { + delete this; + } else { + iStatus = KRequestPending; + SetActive(); + m_dispatcher->reactivateSocketNotifier(m_notifier); + } } void QSocketActiveObject::deleteLater() @@ -912,27 +943,6 @@ void QEventDispatcherSymbian::timerFired(int timerId) return; } -void QEventDispatcherSymbian::socketFired(QSocketActiveObject *socketAO) -{ - if (m_noSocketEvents) { - m_deferredSocketEvents.append(socketAO); - return; - } - - QEvent e(QEvent::SockAct); - socketAO->m_inSocketEvent = true; - QCoreApplication::sendEvent(socketAO->m_notifier, &e); - socketAO->m_inSocketEvent = false; - - if (socketAO->m_deleteLater) { - delete socketAO; - } else { - socketAO->iStatus = KRequestPending; - socketAO->SetActive(); - reactivateSocketNotifier(socketAO->m_notifier); - } -} - void QEventDispatcherSymbian::wakeUpWasCalled() { // The reactivation should happen in RunL, right before the call to this function. @@ -993,6 +1003,12 @@ inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *obje inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object) { m_deferredActiveObjects.removeAll(object); + m_deferredSocketEvents.removeAll(object); +} + +inline void QEventDispatcherSymbian::addDeferredSocketActiveObject(QActiveObject *object) +{ + m_deferredSocketEvents.append(object); } void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion() @@ -1018,7 +1034,8 @@ bool QEventDispatcherSymbian::sendDeferredSocketEvents() bool sentAnyEvents = false; while (!m_deferredSocketEvents.isEmpty()) { sentAnyEvents = true; - socketFired(m_deferredSocketEvents.takeFirst()); + QActiveObject *object = m_deferredSocketEvents.takeFirst(); + object->reactivateAndComplete(); } return sentAnyEvents; @@ -1037,17 +1054,18 @@ bool QEventDispatcherSymbian::hasPendingEvents() void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier ) { - //TODO: just need to be able to do something when event loop has sockets disabled -/* QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); + //note - this is only for "open C" file descriptors + //for native sockets, an active object in the symbian socket engine handles this + 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 - /* + //note - this is only for "open C" file descriptors + //for native sockets, an active object in the symbian socket engine handles this if (m_selectThread) m_selectThread->cancelSocketEvents(notifier); if (m_notifiers.contains(notifier)) { @@ -1056,7 +1074,6 @@ void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notif sockObj->deleteLater(); m_notifiers.remove(notifier); } - */ } void QEventDispatcherSymbian::reactivateSocketNotifier(QSocketNotifier *notifier) diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index bf28144..e07d475 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -77,13 +77,14 @@ QT_BEGIN_NAMESPACE class QEventDispatcherSymbian; class QTimerActiveObject; -class Q_AUTOTEST_EXPORT QActiveObject : public CActive +class Q_CORE_EXPORT QActiveObject : public CActive { public: QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher); ~QActiveObject(); bool maybeQueueForLater(); + bool maybeDeferSocketEvent(); void reactivateAndComplete(); @@ -176,6 +177,7 @@ public: protected: void DoCancel(); void RunL(); + void run(); private: QSocketNotifier *m_notifier; @@ -244,7 +246,6 @@ public: void closingDown(); void timerFired(int timerId); - void socketFired(QSocketActiveObject *socketAO); void wakeUpWasCalled(); void reactivateSocketNotifier(QSocketNotifier *notifier); @@ -256,6 +257,9 @@ public: inline int iterationCount() const { return m_iterationCount; } + void addDeferredSocketActiveObject(QActiveObject *object); + inline bool areSocketEventsBlocked() const { return m_noSocketEvents; } + static void RequestComplete(TRequestStatus *&status, TInt reason); static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason); @@ -281,8 +285,9 @@ private: unsigned char m_iterationCount; bool m_insideTimerEvent; bool m_noSocketEvents; - QList m_deferredSocketEvents; - + //deferred until socket events are enabled + QList m_deferredSocketEvents; + //deferred until idle QList m_deferredActiveObjects; int m_delay; diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 688f724..07b2e5a 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -63,6 +63,7 @@ #include #include +#include #include #include @@ -187,7 +188,6 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp; //Check if there is a user specified session - RConnection *connection = 0; QVariant v(q->property("_q_networksession")); TInt err; if (v.isValid()) { @@ -1437,7 +1437,9 @@ void QSymbianSocketEngine::setReadNotificationEnabled(bool enable) #endif d->readNotificationsEnabled = enable; if (enable && d->threadData->eventDispatcher && !d->asyncSelect) - d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); + d->asyncSelect = q_check_ptr( + new QAsyncSelect(static_cast(d->threadData->eventDispatcher), + d->nativeSocket, this)); // TODO: what do we do if event dispatcher doesn't exist yet? if (d->asyncSelect) d->asyncSelect->IssueRequest(); @@ -1459,7 +1461,9 @@ void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) #endif d->writeNotificationsEnabled = enable; if (enable && d->threadData->eventDispatcher && !d->asyncSelect) - d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); + d->asyncSelect = q_check_ptr( + new QAsyncSelect(static_cast(d->threadData->eventDispatcher), + d->nativeSocket, this)); // TODO: what do we do if event dispatcher doesn't exist yet? if (d->asyncSelect) d->asyncSelect->IssueRequest(); @@ -1483,7 +1487,9 @@ void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) #endif d->exceptNotificationsEnabled = enable; if (enable && d->threadData->eventDispatcher && !d->asyncSelect) - d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); + d->asyncSelect = q_check_ptr( + new QAsyncSelect(static_cast(d->threadData->eventDispatcher), + d->nativeSocket, this)); if (d->asyncSelect) d->asyncSelect->IssueRequest(); } @@ -1597,15 +1603,17 @@ bool QSymbianSocketEngine::event(QEvent* ev) qDebug() << "PostThreadChangeEvent" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; #endif // recreate select in new thread - d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this)); + d->asyncSelect = q_check_ptr( + new QAsyncSelect(static_cast(d->threadData->eventDispatcher), + d->nativeSocket, this)); d->asyncSelect->IssueRequest(); return true; } return QAbstractSocketEngine::event(ev); } -QAsyncSelect::QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent) - : CActive(CActive::EPriorityStandard), +QAsyncSelect::QAsyncSelect(QEventDispatcherSymbian *dispatcher, RSocket& sock, QSymbianSocketEngine *parent) + : QActiveObject(CActive::EPriorityStandard, dispatcher), m_inSocketEvent(false), m_deleteLater(false), m_socket(sock), @@ -1652,9 +1660,9 @@ TInt QAsyncSelect::RunError(TInt aError) void QAsyncSelect::run() { - //TODO: block when event loop demands it - //if (maybeQueueForLater()) - // return; + //when event loop disabled socket events, defer until later + if (maybeDeferSocketEvent()) + return; m_inSocketEvent = true; m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested //KSockSelectReadContinuation is for reading datagrams in a mode that doesn't discard when the diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index 432e4dc..bbe1269 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -151,10 +151,10 @@ class QSocketNotifier; class QReadNotifier; class QWriteNotifier; class QExceptionNotifier; -class QAsyncSelect : public CActive +class QAsyncSelect : public QActiveObject { public: - QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent); + QAsyncSelect(QEventDispatcherSymbian *dispatcher, RSocket& sock, QSymbianSocketEngine *parent); ~QAsyncSelect(); void deleteLater(); -- cgit v0.12 From 2e2c3aab63b066aa2321792e6adeab76d12c77d1 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 17 Mar 2011 14:55:20 +0000 Subject: tst_qudpsocket - fix capabilities Reviewed-by: Trust Me --- tests/auto/qudpsocket/clientserver/clientserver.pro | 2 +- tests/auto/qudpsocket/qudpsocket.pro | 2 -- tests/auto/qudpsocket/test/test.pro | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/auto/qudpsocket/clientserver/clientserver.pro b/tests/auto/qudpsocket/clientserver/clientserver.pro index 5fe65b3..6da1486 100644 --- a/tests/auto/qudpsocket/clientserver/clientserver.pro +++ b/tests/auto/qudpsocket/clientserver/clientserver.pro @@ -5,4 +5,4 @@ CONFIG -= app_bundle TARGET = clientserver DESTDIR = ./ - +symbian: TARGET.CAPABILITY += NetworkServices diff --git a/tests/auto/qudpsocket/qudpsocket.pro b/tests/auto/qudpsocket/qudpsocket.pro index 8fd3545..4ddb717 100644 --- a/tests/auto/qudpsocket/qudpsocket.pro +++ b/tests/auto/qudpsocket/qudpsocket.pro @@ -1,6 +1,4 @@ TEMPLATE = subdirs SUBDIRS = test clientserver -symbian: TARGET.CAPABILITY = NetworkServices - diff --git a/tests/auto/qudpsocket/test/test.pro b/tests/auto/qudpsocket/test/test.pro index 7e5ffe4..b68d30c 100644 --- a/tests/auto/qudpsocket/test/test.pro +++ b/tests/auto/qudpsocket/test/test.pro @@ -22,4 +22,4 @@ wince*|symbian: { TARGET = tst_qudpsocket - +symbian: TARGET.CAPABILITY += NetworkServices -- cgit v0.12 From 690ca356c52f0e4f83f5b6cb4b54fdc6db2af5ba Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 17 Mar 2011 16:12:08 +0100 Subject: QHostInfo: Compile fix for non-Symbian --- src/network/kernel/qhostinfo_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index ec7a63e..72175f0 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -184,7 +184,7 @@ protected: }; #ifndef Q_OS_SYMBIAN -class QHostInfoLookupManager : public QAbstractInfoLookupManager +class QHostInfoLookupManager : public QAbstractHostInfoLookupManger { Q_OBJECT public: -- cgit v0.12 From b35009bab4d4353aa82830f4f7f8c29700b2bd08 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Mar 2011 11:21:08 +0000 Subject: Fix "wrong lookup id" warning from QAbstractSocket Symbian host info implementation was using default constructor for the results, which sets the id to -1, and storing the id seperately. Changed this to use the constructor that specifies the id, and use the id inside the results instead of storing it separately (just a change to the accessor function) Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 2 -- src/network/kernel/qhostinfo_symbian.cpp | 28 +++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 72175f0..79fad84 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -243,8 +243,6 @@ private: void processAddressResults(); private: - int iId; - const QString iHostName; RSocketServ& iSocketServ; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 2b582bd..ad5f38a 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -217,14 +217,17 @@ QString QHostInfo::localDomainName() QSymbianHostResolver::QSymbianHostResolver(const QString &hostName, int identifier) - : CActive(CActive::EPriorityStandard), iId(identifier), iHostName(hostName), - iSocketServ(qt_symbianGetSocketServer()) + : CActive(CActive::EPriorityStandard), iHostName(hostName), + iSocketServ(qt_symbianGetSocketServer()), iResults(identifier) { CActiveScheduler::Add(this); } QSymbianHostResolver::~QSymbianHostResolver() { +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostInfoLookupManger::~QSymbianHostResolver" << id(); +#endif Cancel(); iHostResolver.Close(); } @@ -234,8 +237,8 @@ QHostInfo QSymbianHostResolver::requestHostLookup() { #if defined(QHOSTINFO_DEBUG) - qDebug("QHostInfoAgent::fromName(%s) looking up...", - hostName.toLatin1().constData()); + qDebug("QSymbianHostResolver::requestHostLookup(%s) looking up... (id = %d)", + iHostName.toLatin1().constData(), id()); #endif int err = iHostResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp); @@ -404,7 +407,7 @@ void QSymbianHostResolver::processAddressResults() int QSymbianHostResolver::id() { - return iId; + return iResults.lookupId(); } QSymbianHostInfoLookupManger::QSymbianHostInfoLookupManger() @@ -428,6 +431,9 @@ void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) { QMutexLocker locker(&mutex); +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostInfoLookupManger::lookupFinished" << r->id() << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); +#endif // remove finished lookup from array and destroy TInt count = iCurrentLookups.Count(); for (TInt i = 0; i < count; i++) { @@ -442,6 +448,9 @@ void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) void QSymbianHostInfoLookupManger::runNextLookup() { +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostInfoLookupManger::runNextLookup" << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); +#endif // check to see if there are any scheduled lookups if (iScheduledLookups.Count() > 0) { // if so, move one to the current lookups and run it @@ -458,10 +467,16 @@ void QSymbianHostInfoLookupManger::scheduleLookup(QSymbianHostResolver* r) { QMutexLocker locker(&mutex); +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostInfoLookupManger::scheduleLookup" << r->id() << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); +#endif // Check to see if we have space on the current lookups pool. if (iCurrentLookups.Count() >= KMaxConcurrentLookups) { // If no, schedule for later. iScheduledLookups.Append(r); +#if defined(QHOSTINFO_DEBUG) + qDebug(" - scheduled"); +#endif return; } else { // If yes, add it to the current lookups. @@ -476,6 +491,9 @@ void QSymbianHostInfoLookupManger::abortLookup(int id) { QMutexLocker locker(&mutex); +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostInfoLookupManger::abortLookup" << id << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); +#endif int i = 0; // Find the aborted lookup by ID. // First in the current lookups. -- cgit v0.12 From 0679abb6b4f85878cb64fce2089ba926e3b9400c Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Mar 2011 11:30:35 +0000 Subject: handle errors in QSymbianHostResolver::requestHostLookup It was hanging because although the error flags were set, the callback was not emitted and nothing was done with the return value from the function. Now, it sets the state to error, and self completes - so that the completion through RunL is used as normal. Because the state is error, the processing of name/address is skipped and the error string is not rewritten. Note, error being detected at this point is only common when using an explicit network session (as RHostResolver::Open can fail if the RConnection is in the wrong state) Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 5 ++- src/network/kernel/qhostinfo_symbian.cpp | 64 +++++++++++++++++--------------- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 79fad84..909bd03 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -228,7 +228,7 @@ public: QSymbianHostResolver(const QString &hostName, int id); ~QSymbianHostResolver(); - QHostInfo requestHostLookup(); + void requestHostLookup(); int id(); QHostInfoResult resultEmitter; @@ -258,7 +258,8 @@ private: enum { EIdle, EGetByName, - EGetByAddress + EGetByAddress, + EError } iState; }; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index ad5f38a..54ec33c 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -233,7 +233,7 @@ QSymbianHostResolver::~QSymbianHostResolver() } // Async equivalent to QHostInfoAgent::fromName() -QHostInfo QSymbianHostResolver::requestHostLookup() +void QSymbianHostResolver::requestHostLookup() { #if defined(QHOSTINFO_DEBUG) @@ -245,45 +245,51 @@ QHostInfo QSymbianHostResolver::requestHostLookup() if (err) { // What are we doing with iResults?? iResults.setError(QHostInfo::UnknownError); - iResults.setErrorString(QObject::tr("Symbian error code: %1").arg(err)); + iResults.setErrorString(QSystemError(err, QSystemError::NativeError).toString()); - iHostResolver.Close(); - return iResults; - } + } else { - if (iAddress.setAddress(iHostName)) { - // Reverse lookup + if (iAddress.setAddress(iHostName)) { + // Reverse lookup - TInetAddr IpAdd; - IpAdd.Input(qt_QString2TPtrC(iHostName)); + TInetAddr IpAdd; + IpAdd.Input(qt_QString2TPtrC(iHostName)); - // Asynchronous request. - iHostResolver.GetByAddress(IpAdd, iNameResult, iStatus); // <---- ASYNC - iState = EGetByAddress; + // Asynchronous request. + iHostResolver.GetByAddress(IpAdd, iNameResult, iStatus); // <---- ASYNC + iState = EGetByAddress; - } else { + } else { - // IDN support - QByteArray aceHostname = QUrl::toAce(iHostName); - iResults.setHostName(iHostName); - if (aceHostname.isEmpty()) { - iResults.setError(QHostInfo::HostNotFound); - iResults.setErrorString(iHostName.isEmpty() ? - QCoreApplication::translate("QHostInfoAgent", "No host name given") : - QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); + // IDN support + QByteArray aceHostname = QUrl::toAce(iHostName); + iResults.setHostName(iHostName); + if (aceHostname.isEmpty()) { + iResults.setError(QHostInfo::HostNotFound); + iResults.setErrorString(iHostName.isEmpty() ? + QCoreApplication::translate("QHostInfoAgent", "No host name given") : + QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); - iHostResolver.Close(); - return iResults; - } + err = KErrArgument; + } else { - // Asynchronous request. - iHostResolver.GetByName(qt_QString2TPtrC(QString::fromLatin1(aceHostname)), iNameResult, iStatus); - iState = EGetByName; + // Asynchronous request. + iHostResolver.GetByName(qt_QString2TPtrC(QString::fromLatin1(aceHostname)), iNameResult, iStatus); + iState = EGetByName; + } + } } - SetActive(); + if (err) { + iHostResolver.Close(); - return iResults; + //self complete so that RunL can inform manager without causing recursion + iState = EError; + iStatus = KRequestPending; + SetActive(); + TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, err); + } } void QSymbianHostResolver::DoCancel() -- cgit v0.12 From e29e13ff537a92f7d2afe34893d8bae8a6788bed Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 18 Mar 2011 11:45:52 +0000 Subject: Add explicit network session support for async QHostInfo Pass the shared network session pointer into the QSymbianHostResolver (which maintains a reference for its lifetime). This is used to open the RHostResolver handle, in order to get a host resolver which is associated with a particular session. The session is obtained from the _q_networksession property of the QAbstractSocket, as in the symbian socket engine Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo.cpp | 10 +++++++++- src/network/kernel/qhostinfo_p.h | 3 ++- src/network/kernel/qhostinfo_symbian.cpp | 18 +++++++++++++++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 7a15a05..1ae0bbd 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #ifdef Q_OS_UNIX # include @@ -219,8 +220,15 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, } // cache is not enabled or it was not in the cache, do normal lookup +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession; + QVariant v(receiver->property("_q_networksession")); + if (v.isValid()) + networkSession = qvariant_cast< QSharedPointer >(v); +#endif + QSymbianHostResolver *symbianResolver = 0; - QT_TRAP_THROWING(symbianResolver = new QSymbianHostResolver(name, id)); + QT_TRAP_THROWING(symbianResolver = new QSymbianHostResolver(name, id, networkSession)); QObject::connect(&symbianResolver->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); manager->scheduleLookup(symbianResolver); } diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 909bd03..e3f7f19 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -225,7 +225,7 @@ private slots: class QSymbianHostResolver : public CActive { public: - QSymbianHostResolver(const QString &hostName, int id); + QSymbianHostResolver(const QString &hostName, int id, QSharedPointer networkSession); ~QSymbianHostResolver(); void requestHostLookup(); @@ -247,6 +247,7 @@ private: RSocketServ& iSocketServ; RHostResolver iHostResolver; + QSharedPointer iNetworkSession; TRequestStatus iStatus; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 54ec33c..12e59c6 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -51,6 +51,7 @@ #include "qhostinfo_p.h" #include #include +#include QT_BEGIN_NAMESPACE @@ -216,9 +217,9 @@ QString QHostInfo::localDomainName() } -QSymbianHostResolver::QSymbianHostResolver(const QString &hostName, int identifier) +QSymbianHostResolver::QSymbianHostResolver(const QString &hostName, int identifier, QSharedPointer networkSession) : CActive(CActive::EPriorityStandard), iHostName(hostName), - iSocketServ(qt_symbianGetSocketServer()), iResults(identifier) + iSocketServ(qt_symbianGetSocketServer()), iNetworkSession(networkSession), iResults(identifier) { CActiveScheduler::Add(this); } @@ -241,7 +242,18 @@ void QSymbianHostResolver::requestHostLookup() iHostName.toLatin1().constData(), id()); #endif - int err = iHostResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp); + int err; + if (iNetworkSession) { + err = QNetworkSessionPrivate::nativeOpenHostResolver(*iNetworkSession, iHostResolver, KAfInet, KProtocolInetUdp); +#if defined(QHOSTINFO_DEBUG) + qDebug("using resolver from session (err = %d)", err); +#endif + } else { + err = iHostResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp); +#if defined(QHOSTINFO_DEBUG) + qDebug("using default resolver (err = %d)", err); +#endif + } if (err) { // What are we doing with iResults?? iResults.setError(QHostInfo::UnknownError); -- cgit v0.12 From 67c6737c6702506b5b09fd84389e20ba539cc000 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Mar 2011 17:12:56 +0000 Subject: Fix bugs where = used instead of == Reviewed-by: Aaron Tunney --- src/network/kernel/qhostinfo_symbian.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 12e59c6..347bf67 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -101,7 +101,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointerid()) { + if (id == iCurrentLookups[i]->id()) { QSymbianHostResolver* r = iCurrentLookups[i]; iCurrentLookups.Remove(i); r->Cancel(); @@ -526,7 +526,7 @@ void QSymbianHostInfoLookupManger::abortLookup(int id) } // Then in the scheduled lookups. for (i = 0; i < iScheduledLookups.Count(); i++) { - if (id = iScheduledLookups[i]->id()) { + if (id == iScheduledLookups[i]->id()) { QSymbianHostResolver* r = iScheduledLookups[i]; iScheduledLookups.Remove(i); delete r; -- cgit v0.12 From 40fc1a3ca3b7050f317513cf69dd89a01479e098 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Mar 2011 18:53:42 +0000 Subject: Implement network session support for synchronous QHostInfo Private API, QHostInfoPrivate::fromName, which is called from QAbstractSocket when the network session property is set. Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo.cpp | 14 ++++++++++++++ src/network/kernel/qhostinfo_p.h | 5 +++++ src/network/kernel/qhostinfo_symbian.cpp | 15 +++++---------- src/network/socket/qabstractsocket.cpp | 9 +++++++++ 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 1ae0bbd..aff55d9 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -272,6 +272,20 @@ QHostInfo QHostInfo::fromName(const QString &name) return hostInfo; } +#ifndef QT_NO_BEARERMANAGEMENT +QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointer session) +{ +#if defined QHOSTINFO_DEBUG + qDebug("QHostInfoPrivate::fromName(\"%s\") with session %p",name.toLatin1().constData(), session.data()); +#endif + + QHostInfo hostInfo = QHostInfoAgent::fromName(name, session); + QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); + manager->cache.put(name, hostInfo); + return hostInfo; +} +#endif + /*! \enum QHostInfo::HostInfoError diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index e3f7f19..a40104a 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -70,6 +70,7 @@ #include #include +#include #ifdef Q_OS_SYMBIAN // Symbian Headers @@ -117,6 +118,10 @@ public: lookupId(0) { } +#ifndef QT_NO_BEARERMANAGEMENT + //not a public API yet + static QHostInfo fromName(const QString &hostName, QSharedPointer networkSession); +#endif QHostInfo::HostInfoError err; QString errorStr; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 347bf67..65c3d62 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -66,16 +66,11 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer #include @@ -1786,6 +1787,14 @@ bool QAbstractSocket::waitForConnected(int msecs) #endif QHostInfo::abortHostLookup(d->hostLookupId); d->hostLookupId = -1; +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession; + QVariant v(property("_q_networksession")); + if (v.isValid()) { + networkSession = qvariant_cast< QSharedPointer >(v); + d->_q_startConnecting(QHostInfoPrivate::fromName(d->hostName, networkSession)); + } else +#endif d->_q_startConnecting(QHostInfo::fromName(d->hostName)); } if (state() == UnconnectedState) -- cgit v0.12 From c9edb126e6f01e54dfbb1e952b253b2490d26e88 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Mar 2011 18:56:13 +0000 Subject: Fix SetActive being called twice Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_symbian.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 65c3d62..ca76b12 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -292,8 +292,6 @@ void QSymbianHostResolver::requestHostLookup() //self complete so that RunL can inform manager without causing recursion iState = EError; - iStatus = KRequestPending; - SetActive(); TRequestStatus* stat = &iStatus; User::RequestComplete(stat, err); } -- cgit v0.12 From 919e282ff62171654dd60875fe1c058f36a14584 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Mar 2011 18:57:16 +0000 Subject: Fix a deadlock in symbian QHostInfo when aborting DoCancel was calling lookupFinished, which tries to acquire a mutex again that was already acquired in abortLookup (causing a deadlock). This call is un-necessary, as Cancel was only called from the destructor and from abortLookup - in neither case is this wanted. The run and RunError functions explicitly call lookupFinished. This fixes hang in autotests when attempting to lookup a bad host name. Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_symbian.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index ca76b12..c969748 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -299,8 +299,6 @@ void QSymbianHostResolver::requestHostLookup() void QSymbianHostResolver::DoCancel() { - QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); - manager->lookupFinished(this); iHostResolver.Cancel(); } @@ -512,7 +510,7 @@ void QSymbianHostInfoLookupManger::abortLookup(int id) if (id == iCurrentLookups[i]->id()) { QSymbianHostResolver* r = iCurrentLookups[i]; iCurrentLookups.Remove(i); - r->Cancel(); + delete r; //cancels via destructor runNextLookup(); return; } -- cgit v0.12 From 32a43ac64aee529c55af77edbbe34c54cb8f5e52 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Mar 2011 19:03:56 +0000 Subject: Report correct error from QSymbianSocketEngine::nativeSelect Sometimes the error is in the return code from the ioctl, other times it is in the select last error getopt. Treat both error sources the same way and call setError. Return code has higher priority. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 07b2e5a..58e8d9f 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1137,14 +1137,14 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool #ifdef QNATIVESOCKETENGINE_DEBUG qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select status" << selectStat.Int() << (int)selectFlags(); #endif - if (selectStat != KErrNone) - return selectStat.Int(); - if (selectFlags() & KSockSelectExcept) { - TInt err; + TInt err = selectStat.Int(); + if (!err && (selectFlags() & KSockSelectExcept)) { nativeSocket.GetOpt(KSOSelectLastError, KSOLSocket, err); #ifdef QNATIVESOCKETENGINE_DEBUG qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select last error" << err; #endif + } + if (err) { //TODO: avoidable cast? //set the error here, because read won't always return the same error again as select. const_cast(this)->setError(err); -- cgit v0.12 From 3c94f70a2e2c8e9f6a6cfc952837f18568c9bc4c Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 21 Mar 2011 20:07:32 +0000 Subject: Fix crashing debug message When testing the socks5 socket engine, it closes the socket from within _q_controlSocketError. Frequently a data abort occurs after this when printing the debug message. Moved the debug message before emitting the signal to avoid this. Reviewed-by: Markus Goetz --- src/network/socket/qabstractsocket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 801556e..9c96e1c 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -752,11 +752,11 @@ bool QAbstractSocketPrivate::flush() if (written < 0) { socketError = socketEngine->error(); q->setErrorString(socketEngine->errorString()); - emit q->error(socketError); - // an unexpected error so close the socket. #if defined (QABSTRACTSOCKET_DEBUG) qDebug() << "QAbstractSocketPrivate::flush() write error, aborting." << socketEngine->errorString(); #endif + emit q->error(socketError); + // an unexpected error so close the socket. q->abort(); return false; } -- cgit v0.12 From 747d43b89c9230d12a81e77e390f4f422f5255db Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 22 Mar 2011 12:17:05 +0100 Subject: QHostInfo: Fix compilation with non-symbian Reviewed-by: Shane Kearns --- src/network/kernel/qhostinfo.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index aff55d9..3413c9b 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -286,6 +286,15 @@ QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointer networkSession) +{ + return QHostInfoAgent::fromName(hostName); +} +#endif + + /*! \enum QHostInfo::HostInfoError -- cgit v0.12 From 3f4dca824126a2d5e7d31e122a16118b79ef78d8 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Mar 2011 11:55:15 +0000 Subject: Fixes to QSystemError 1. KErrNotReady message changed to have one file and one network example 2. Format error for the generic error code was generating a QWARN Reviewed-by: Markus Goetz --- src/corelib/kernel/qsystemerror.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp index 953ed95..5cf8fc6 100644 --- a/src/corelib/kernel/qsystemerror.cpp +++ b/src/corelib/kernel/qsystemerror.cpp @@ -154,7 +154,7 @@ static QString symbianErrorString(int errorCode) case KErrInUse: return QLatin1String("in use"); case KErrNotReady: - return QLatin1String("not ready (e.g. FS dismounted, no memory card)"); + return QLatin1String("not ready (e.g. FS dismounted, network down)"); case KErrCorrupt: return QLatin1String("corrupt"); case KErrAccessDenied: @@ -190,7 +190,7 @@ static QString symbianErrorString(int errorCode) case KErrPermissionDenied: return QLatin1String("permission denied"); default: - return QString(QLatin1String("symbian error %d")).arg(errorCode); + return QString(QLatin1String("symbian error %1")).arg(errorCode); } } #endif -- cgit v0.12 From f31dfc682402396e35dffd8952eb5ced8f6b4030 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Mar 2011 17:46:39 +0000 Subject: Fix event loop hangs caused by async QHostInfo Declaring iStatus in a derived class hides the iStatus in CActive. This confuses the active scheduler (which is using CActive::iStatus) and would in a normal symbian application have caused a stray signal panic. However as Qt's event loop integration uses CActiveScheduler::RunIfReady instead of the normal CActiveScheduler::Start the panic does not happen. Instead the thread semaphore gets messed up and causes problems. Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index a40104a..bff5fc4 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -254,8 +254,6 @@ private: RHostResolver iHostResolver; QSharedPointer iNetworkSession; - TRequestStatus iStatus; - TNameEntry iNameResult; QHostAddress iAddress; -- cgit v0.12 From 1831e7f802d1bdba33f320c21f29df02d647ead8 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Mar 2011 17:59:05 +0000 Subject: Ensure parameters of async function calls stay in scope Calling symbian asynchronous functions with parameters on the stack, even "in" parameters is unsafe. If the server is blocked on another operation, then it will not read the parameters until later (at which time the stack is invalid) Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 4 ++++ src/network/kernel/qhostinfo_symbian.cpp | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index bff5fc4..71c191f 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -249,12 +249,16 @@ private: private: const QString iHostName; + QString iEncodedHostName; + TPtrC iHostNamePtr; RSocketServ& iSocketServ; RHostResolver iHostResolver; QSharedPointer iNetworkSession; TNameEntry iNameResult; + TInetAddr IpAdd; + QHostAddress iAddress; QHostInfo iResults; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index c969748..c1457fd 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -259,7 +259,6 @@ void QSymbianHostResolver::requestHostLookup() if (iAddress.setAddress(iHostName)) { // Reverse lookup - TInetAddr IpAdd; IpAdd.Input(qt_QString2TPtrC(iHostName)); // Asynchronous request. @@ -279,9 +278,11 @@ void QSymbianHostResolver::requestHostLookup() err = KErrArgument; } else { + iEncodedHostName = QString::fromLatin1(aceHostname); + iHostNamePtr.Set(qt_QString2TPtrC(iEncodedHostName)); // Asynchronous request. - iHostResolver.GetByName(qt_QString2TPtrC(QString::fromLatin1(aceHostname)), iNameResult, iStatus); + iHostResolver.GetByName(iHostNamePtr, iNameResult, iStatus); iState = EGetByName; } } -- cgit v0.12 From 4f74076095add88c936e729838c9205abfe04bd0 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Mar 2011 18:09:13 +0000 Subject: Ensure QSymbianHostResolver::DoCancel does correct thing based on state If a host resolver async call in progress, cancel it. Otherwise don't. Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_symbian.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index c1457fd..fdb0fbc 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -300,7 +300,16 @@ void QSymbianHostResolver::requestHostLookup() void QSymbianHostResolver::DoCancel() { - iHostResolver.Cancel(); +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostResolver::DoCancel" << QThread::currentThreadId() << id() << (int)iState << this; +#endif + if (iState == EGetByAddress || iState == EGetByName) { + //these states have made an async request to host resolver + iHostResolver.Cancel(); + } else { + //for the self completing states there is nothing to cancel + Q_ASSERT(iState == EError); + } } void QSymbianHostResolver::RunL() -- cgit v0.12 From 999f44f06702513747844bcc0809597134be5e78 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Mar 2011 18:16:45 +0000 Subject: use QList instead of RPointerArray For maintainability, it's better to use Qt's container classes Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 5 ++-- src/network/kernel/qhostinfo_symbian.cpp | 49 ++++++++++++++++---------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 71c191f..a7e83da 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -295,9 +295,8 @@ private: static const int KMaxConcurrentLookups = 5; - RPointerArray iCurrentLookups; - RPointerArray iScheduledLookups; - RPointerArray iFinishedLookups; + QList iCurrentLookups; + QList iScheduledLookups; QMutex mutex; }; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index fdb0fbc..5998a72 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -435,15 +435,18 @@ QSymbianHostInfoLookupManger::QSymbianHostInfoLookupManger() QSymbianHostInfoLookupManger::~QSymbianHostInfoLookupManger() { - iCurrentLookups.Close(); - iScheduledLookups.Close(); } void QSymbianHostInfoLookupManger::clear() { QMutexLocker locker(&mutex); - iCurrentLookups.ResetAndDestroy(); - iScheduledLookups.ResetAndDestroy(); +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostInfoLookupManger::clear" << QThread::currentThreadId(); +#endif + //TODO: these aren't deleted because of thread unsafety, but that is a behaviour difference + //qDeleteAll(iCurrentLookups); + //qDeleteAll(iScheduledLookups); + cache.clear(); } void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) @@ -451,13 +454,13 @@ void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::lookupFinished" << r->id() << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); + qDebug() << "QSymbianHostInfoLookupManger::lookupFinished" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // remove finished lookup from array and destroy - TInt count = iCurrentLookups.Count(); + TInt count = iCurrentLookups.count(); for (TInt i = 0; i < count; i++) { if (iCurrentLookups[i]->id() == r->id()) { - iCurrentLookups.Remove(i); + iCurrentLookups.removeAt(i); break; } } @@ -468,15 +471,14 @@ void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) void QSymbianHostInfoLookupManger::runNextLookup() { #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::runNextLookup" << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); + qDebug() << "QSymbianHostInfoLookupManger::runNextLookup" << QThread::currentThreadId() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // check to see if there are any scheduled lookups - if (iScheduledLookups.Count() > 0) { + if (iScheduledLookups.count() > 0) { // if so, move one to the current lookups and run it // FIFO - QSymbianHostResolver* hostResolver = iScheduledLookups[0]; - iCurrentLookups.Append(hostResolver); - iScheduledLookups.Remove(0); + QSymbianHostResolver* hostResolver = iScheduledLookups.takeFirst(); + iCurrentLookups.append(hostResolver); hostResolver->requestHostLookup(); } } @@ -487,19 +489,19 @@ void QSymbianHostInfoLookupManger::scheduleLookup(QSymbianHostResolver* r) QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::scheduleLookup" << r->id() << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); + qDebug() << "QSymbianHostInfoLookupManger::scheduleLookup" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // Check to see if we have space on the current lookups pool. - if (iCurrentLookups.Count() >= KMaxConcurrentLookups) { + if (iCurrentLookups.count() >= KMaxConcurrentLookups) { // If no, schedule for later. - iScheduledLookups.Append(r); + iScheduledLookups.append(r); #if defined(QHOSTINFO_DEBUG) qDebug(" - scheduled"); #endif return; } else { // If yes, add it to the current lookups. - iCurrentLookups.Append(r); + iCurrentLookups.append(r); // ... and trigger the async call. r->requestHostLookup(); @@ -511,32 +513,31 @@ void QSymbianHostInfoLookupManger::abortLookup(int id) QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::abortLookup" << id << "current" << iCurrentLookups.Count() << "queued" << iScheduledLookups.Count(); + qDebug() << "QSymbianHostInfoLookupManger::abortLookup" << QThread::currentThreadId() << id << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif int i = 0; // Find the aborted lookup by ID. // First in the current lookups. - for (i = 0; i < iCurrentLookups.Count(); i++) { + for (i = 0; i < iCurrentLookups.count(); i++) { if (id == iCurrentLookups[i]->id()) { - QSymbianHostResolver* r = iCurrentLookups[i]; - iCurrentLookups.Remove(i); + QSymbianHostResolver* r = iCurrentLookups.at(i); + iCurrentLookups.removeAt(i); delete r; //cancels via destructor runNextLookup(); return; } } // Then in the scheduled lookups. - for (i = 0; i < iScheduledLookups.Count(); i++) { + for (i = 0; i < iScheduledLookups.count(); i++) { if (id == iScheduledLookups[i]->id()) { - QSymbianHostResolver* r = iScheduledLookups[i]; - iScheduledLookups.Remove(i); + QSymbianHostResolver* r = iScheduledLookups.at(i); + iScheduledLookups.removeAt(i); delete r; return; } } } - QSymbianHostInfoLookupManger* QSymbianHostInfoLookupManger::globalInstance() { return static_cast -- cgit v0.12 From aacdf24477bbcddd6492c3bac3d903555f09297a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 22 Mar 2011 18:19:17 +0000 Subject: Fix bugs in tst_qnetworkreply It used a unix way to delete local servers. Changed this to the cross platform QLocalServer::removeServer API It reported XPASS on symbian due to SRCDIR being a relative path not absolute. (added a check for this, as SRCDIR could be relative on windows) Also fixed a couple of compiler warnings Reviewed-by: Martin Petersson --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index ffe7ea4..f8a9530 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -1542,7 +1542,7 @@ void tst_QNetworkReply::getErrors() QNetworkRequest request(url); #if defined(Q_OS_WIN) || defined (Q_OS_SYMBIAN) - if (qstrcmp(QTest::currentDataTag(), "empty-scheme-host") == 0) + if (qstrcmp(QTest::currentDataTag(), "empty-scheme-host") == 0 && QFileInfo(url).isAbsolute()) QTest::ignoreMessage(QtWarningMsg, "QNetworkAccessFileBackendFactory: URL has no schema set, use file:// for files"); #endif @@ -1561,7 +1561,8 @@ void tst_QNetworkReply::getErrors() QFETCH(int, error); #if defined(Q_OS_WIN) || defined (Q_OS_SYMBIAN) - QEXPECT_FAIL("empty-scheme-host", "this is expected to fail on Windows and Symbian, QTBUG-17731", Abort); + if (QFileInfo(url).isAbsolute()) + QEXPECT_FAIL("empty-scheme-host", "this is expected to fail on Windows and Symbian, QTBUG-17731", Abort); #endif QEXPECT_FAIL("ftp-is-dir", "QFtp cannot provide enough detail", Abort); // the line below is not necessary @@ -3210,8 +3211,7 @@ void tst_QNetworkReply::ioPutToFileFromLocalSocket() QString socketname = "networkreplytest"; QLocalServer server; if (!server.listen(socketname)) { - if (QFile::exists(server.fullServerName())) - QFile::remove(server.fullServerName()); + QLocalServer::removeServer(socketname); QVERIFY(server.listen(socketname)); } QLocalSocket active; @@ -3256,7 +3256,7 @@ void tst_QNetworkReply::ioPutToFileFromProcess() { #if defined(Q_OS_WINCE) || defined (Q_OS_SYMBIAN) QSKIP("Currently no stdin/out supported for Windows CE / Symbian OS", SkipAll); -#endif +#else #ifdef Q_OS_WIN if (qstrcmp(QTest::currentDataTag(), "small") == 0) @@ -3294,6 +3294,7 @@ void tst_QNetworkReply::ioPutToFileFromProcess() QByteArray contents = file.readAll(); QCOMPARE(contents, data); #endif +#endif } void tst_QNetworkReply::ioPutToFtpFromFile_data() @@ -5088,7 +5089,7 @@ void tst_QNetworkReply::getFromHttpIntoBuffer() // FIXME we really need to consolidate all those server implementations class GetFromHttpIntoBuffer2Server : QObject { - Q_OBJECT; + Q_OBJECT qint64 dataSize; qint64 dataSent; QTcpServer server; -- cgit v0.12 From 263be570b498847e0762831a5e6a29e1056b4b57 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 23 Mar 2011 13:29:25 +0000 Subject: Update Symbian .def files --- src/s60installs/bwins/QtCoreu.def | 28 ++++++++++- src/s60installs/bwins/QtGuiu.def | 26 ++++++++++ src/s60installs/bwins/QtNetworku.def | 5 ++ src/s60installs/bwins/QtTestu.def | 89 ++++++++++++++++++++++++++++++++++ src/s60installs/eabi/QtCoreu.def | 30 +++++++++++- src/s60installs/eabi/QtGuiu.def | 20 ++++++++ src/s60installs/eabi/QtNetworku.def | 5 ++ src/s60installs/eabi/QtTestu.def | 94 ++++++++++++++++++++++++++++++++++++ 8 files changed, 293 insertions(+), 4 deletions(-) diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index dd7d588..33f22ee 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -1380,7 +1380,7 @@ EXPORTS ?create@QAbstractFileEngine@@SAPAV1@ABVQString@@@Z @ 1379 NONAME ; class QAbstractFileEngine * QAbstractFileEngine::create(class QString const &) ?create@QNonContiguousByteDeviceFactory@@SAPAVQNonContiguousByteDevice@@PAVQByteArray@@@Z @ 1380 NONAME ; class QNonContiguousByteDevice * QNonContiguousByteDeviceFactory::create(class QByteArray *) ?create@QNonContiguousByteDeviceFactory@@SAPAVQNonContiguousByteDevice@@PAVQIODevice@@@Z @ 1381 NONAME ; class QNonContiguousByteDevice * QNonContiguousByteDeviceFactory::create(class QIODevice *) - ?create@QNonContiguousByteDeviceFactory@@SAPAVQNonContiguousByteDevice@@PAVQRingBuffer@@@Z @ 1382 NONAME ; class QNonContiguousByteDevice * QNonContiguousByteDeviceFactory::create(class QRingBuffer *) + ?create@QNonContiguousByteDeviceFactory@@SAPAVQNonContiguousByteDevice@@PAVQRingBuffer@@@Z @ 1382 NONAME ABSENT ; class QNonContiguousByteDevice * QNonContiguousByteDeviceFactory::create(class QRingBuffer *) ?create@QSharedMemory@@QAE_NHW4AccessMode@1@@Z @ 1383 NONAME ; bool QSharedMemory::create(int, enum QSharedMemory::AccessMode) ?create@QTextCodecPlugin@@EAEPAVQTextCodec@@ABVQString@@@Z @ 1384 NONAME ; class QTextCodec * QTextCodecPlugin::create(class QString const &) ?create@QVariant@@IAEXHPBX@Z @ 1385 NONAME ; void QVariant::create(int, void const *) @@ -3572,7 +3572,7 @@ EXPORTS ?skipWhiteSpace@QTextStream@@QAEXXZ @ 3571 NONAME ; void QTextStream::skipWhiteSpace(void) ?sleep@QThread@@KAXK@Z @ 3572 NONAME ; void QThread::sleep(unsigned long) ?socket@QSocketNotifier@@QBEHXZ @ 3573 NONAME ; int QSocketNotifier::socket(void) const - ?socketFired@QEventDispatcherSymbian@@QAEXPAVQSocketActiveObject@@@Z @ 3574 NONAME ; void QEventDispatcherSymbian::socketFired(class QSocketActiveObject *) + ?socketFired@QEventDispatcherSymbian@@QAEXPAVQSocketActiveObject@@@Z @ 3574 NONAME ABSENT ; void QEventDispatcherSymbian::socketFired(class QSocketActiveObject *) ?sort@QAbstractItemModel@@UAEXHW4SortOrder@Qt@@@Z @ 3575 NONAME ; void QAbstractItemModel::sort(int, enum Qt::SortOrder) ?sorting@QDir@@QBE?AV?$QFlags@W4SortFlag@QDir@@@@XZ @ 3576 NONAME ; class QFlags QDir::sorting(void) const ?sourceState@QAbstractTransition@@QBEPAVQState@@XZ @ 3577 NONAME ; class QState * QAbstractTransition::sourceState(void) const @@ -4605,4 +4605,28 @@ EXPORTS ?hasError@QXmlStreamWriter@@QBE_NXZ @ 4604 NONAME ; bool QXmlStreamWriter::hasError(void) const ?revision@QMetaProperty@@QBEHXZ @ 4605 NONAME ; int QMetaProperty::revision(void) const ?revision@QMetaMethod@@QBEHXZ @ 4606 NONAME ; int QMetaMethod::revision(void) const + gzungetc @ 4607 NONAME + ?addSocket@QSymbianSocketManager@@QAEHABVRSocket@@@Z @ 4608 NONAME ; int QSymbianSocketManager::addSocket(class RSocket const &) + ??0QActiveObject@@QAE@HPAVQEventDispatcherSymbian@@@Z @ 4609 NONAME ; QActiveObject::QActiveObject(int, class QEventDispatcherSymbian *) + ?setDefaultConnection@QSymbianSocketManager@@QAEXPAVRConnection@@@Z @ 4610 NONAME ; void QSymbianSocketManager::setDefaultConnection(class RConnection *) + ?reactivateAndComplete@QActiveObject@@QAEXXZ @ 4611 NONAME ; void QActiveObject::reactivateAndComplete(void) + ?defaultConnection@QSymbianSocketManager@@QBEPAVRConnection@@XZ @ 4612 NONAME ; class RConnection * QSymbianSocketManager::defaultConnection(void) const + ?qt_symbianGetSocketServer@@YAAAVRSocketServ@@XZ @ 4613 NONAME ; class RSocketServ & qt_symbianGetSocketServer(void) + ?maybeQueueForLater@QActiveObject@@QAE_NXZ @ 4614 NONAME ; bool QActiveObject::maybeQueueForLater(void) + ??_EQActiveObject@@UAE@I@Z @ 4615 NONAME ; QActiveObject::~QActiveObject(unsigned int) + ?lookupSocket@QSymbianSocketManager@@QBE_NHAAVRSocket@@@Z @ 4616 NONAME ; bool QSymbianSocketManager::lookupSocket(int, class RSocket &) const + ?wait@QActiveObject@@SA_NPAVCActive@@H@Z @ 4617 NONAME ; bool QActiveObject::wait(class CActive *, int) + ?instance@QSymbianSocketManager@@SAAAV1@XZ @ 4618 NONAME ; class QSymbianSocketManager & QSymbianSocketManager::instance(void) + ??0QSymbianSocketManager@@QAE@XZ @ 4619 NONAME ; QSymbianSocketManager::QSymbianSocketManager(void) + ?create@QNonContiguousByteDeviceFactory@@SAPAVQNonContiguousByteDevice@@V?$QSharedPointer@VQRingBuffer@@@@@Z @ 4620 NONAME ; class QNonContiguousByteDevice * QNonContiguousByteDeviceFactory::create(class QSharedPointer) + ??1QSymbianSocketManager@@QAE@XZ @ 4621 NONAME ; QSymbianSocketManager::~QSymbianSocketManager(void) + ?isResetDisabled@QNonContiguousByteDevice@@QAE_NXZ @ 4622 NONAME ; bool QNonContiguousByteDevice::isResetDisabled(void) + ??1QActiveObject@@UAE@XZ @ 4623 NONAME ; QActiveObject::~QActiveObject(void) + ?wait@QActiveObject@@SA_NV?$QList@PAVCActive@@@@H@Z @ 4624 NONAME ; bool QActiveObject::wait(class QList, int) + ?maybeDeferSocketEvent@QActiveObject@@QAE_NXZ @ 4625 NONAME ; bool QActiveObject::maybeDeferSocketEvent(void) + ?lookupSocket@QSymbianSocketManager@@QBEHABVRSocket@@@Z @ 4626 NONAME ; int QSymbianSocketManager::lookupSocket(class RSocket const &) const + ?areSocketEventsBlocked@QEventDispatcherSymbian@@QBE_NXZ @ 4627 NONAME ; bool QEventDispatcherSymbian::areSocketEventsBlocked(void) const + ?addDeferredSocketActiveObject@QEventDispatcherSymbian@@QAEXPAVQActiveObject@@@Z @ 4628 NONAME ; void QEventDispatcherSymbian::addDeferredSocketActiveObject(class QActiveObject *) + ?getSocketServer@QSymbianSocketManager@@QAEAAVRSocketServ@@XZ @ 4629 NONAME ; class RSocketServ & QSymbianSocketManager::getSocketServer(void) + ?removeSocket@QSymbianSocketManager@@QAE_NABVRSocket@@@Z @ 4630 NONAME ; bool QSymbianSocketManager::removeSocket(class RSocket const &) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 9b4c0f7..f711475 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -13149,3 +13149,29 @@ EXPORTS ?ProcessCommandParametersL@QS60MainAppUi@@UAEHW4TApaCommand@@AAV?$TBuf@$0BAA@@@ABVTDesC8@@@Z @ 13148 NONAME ; int QS60MainAppUi::ProcessCommandParametersL(enum TApaCommand, class TBuf<256> &, class TDesC8 const &) ?openFile@QFileOpenEvent@@QBE_NAAVQFile@@V?$QFlags@W4OpenModeFlag@QIODevice@@@@@Z @ 13149 NONAME ; bool QFileOpenEvent::openFile(class QFile &, class QFlags) const ??0QFileOpenEvent@@QAE@ABVRFile@@@Z @ 13150 NONAME ; QFileOpenEvent::QFileOpenEvent(class RFile const &) + ?tr@QInternalMimeData@@SA?AVQString@@PBD0H@Z @ 13151 NONAME ; class QString QInternalMimeData::tr(char const *, char const *, int) + ?assignedInputContext@QWidgetPrivate@@QBEPAVQInputContext@@XZ @ 13152 NONAME ; class QInputContext * QWidgetPrivate::assignedInputContext(void) const + ?formatsHelper@QInternalMimeData@@SA?AVQStringList@@PBVQMimeData@@@Z @ 13153 NONAME ; class QStringList QInternalMimeData::formatsHelper(class QMimeData const *) + ??_EQInternalMimeData@@UAE@I@Z @ 13154 NONAME ; QInternalMimeData::~QInternalMimeData(unsigned int) + ?hasFormatHelper@QInternalMimeData@@SA_NABVQString@@PBVQMimeData@@@Z @ 13155 NONAME ; bool QInternalMimeData::hasFormatHelper(class QString const &, class QMimeData const *) + ?renderDataHelper@QInternalMimeData@@SA?AVQByteArray@@ABVQString@@PBVQMimeData@@@Z @ 13156 NONAME ; class QByteArray QInternalMimeData::renderDataHelper(class QString const &, class QMimeData const *) + ?setLineHeight@QTextBlockFormat@@QAEXMH@Z @ 13157 NONAME ; void QTextBlockFormat::setLineHeight(float, int) + ?trUtf8@QInternalMimeData@@SA?AVQString@@PBD0H@Z @ 13158 NONAME ; class QString QInternalMimeData::trUtf8(char const *, char const *, int) + ?staticMetaObject@QInternalMimeData@@2UQMetaObject@@B @ 13159 NONAME ; struct QMetaObject const QInternalMimeData::staticMetaObject + ?lineHeight@QTextBlockFormat@@QBEMMM@Z @ 13160 NONAME ; float QTextBlockFormat::lineHeight(float, float) const + ?qt_metacast@QInternalMimeData@@UAEPAXPBD@Z @ 13161 NONAME ; void * QInternalMimeData::qt_metacast(char const *) + ?lineHeightType@QTextBlockFormat@@QBEHXZ @ 13162 NONAME ; int QTextBlockFormat::lineHeightType(void) const + ?qt_metacall@QInternalMimeData@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 13163 NONAME ; int QInternalMimeData::qt_metacall(enum QMetaObject::Call, int, void * *) + ?getStaticMetaObject@QInternalMimeData@@SAABUQMetaObject@@XZ @ 13164 NONAME ; struct QMetaObject const & QInternalMimeData::getStaticMetaObject(void) + ??0QInternalMimeData@@QAE@XZ @ 13165 NONAME ; QInternalMimeData::QInternalMimeData(void) + ?updateMicroFocus@QLineControl@@IAEXXZ @ 13166 NONAME ; void QLineControl::updateMicroFocus(void) + ?formats@QInternalMimeData@@UBE?AVQStringList@@XZ @ 13167 NONAME ; class QStringList QInternalMimeData::formats(void) const + ?lineHeight@QTextBlockFormat@@QBEMXZ @ 13168 NONAME ; float QTextBlockFormat::lineHeight(void) const + ?trUtf8@QInternalMimeData@@SA?AVQString@@PBD0@Z @ 13169 NONAME ; class QString QInternalMimeData::trUtf8(char const *, char const *) + ??1QInternalMimeData@@UAE@XZ @ 13170 NONAME ; QInternalMimeData::~QInternalMimeData(void) + ?hasFormat@QInternalMimeData@@UBE_NABVQString@@@Z @ 13171 NONAME ; bool QInternalMimeData::hasFormat(class QString const &) const + ?canReadData@QInternalMimeData@@SA_NABVQString@@@Z @ 13172 NONAME ; bool QInternalMimeData::canReadData(class QString const &) + ?tr@QInternalMimeData@@SA?AVQString@@PBD0@Z @ 13173 NONAME ; class QString QInternalMimeData::tr(char const *, char const *) + ?metaObject@QInternalMimeData@@UBEPBUQMetaObject@@XZ @ 13174 NONAME ; struct QMetaObject const * QInternalMimeData::metaObject(void) const + ?retrieveData@QInternalMimeData@@MBE?AVQVariant@@ABVQString@@W4Type@2@@Z @ 13175 NONAME ; class QVariant QInternalMimeData::retrieveData(class QString const &, enum QVariant::Type) const + diff --git a/src/s60installs/bwins/QtNetworku.def b/src/s60installs/bwins/QtNetworku.def index b01324c..3f8f6d2 100644 --- a/src/s60installs/bwins/QtNetworku.def +++ b/src/s60installs/bwins/QtNetworku.def @@ -1159,4 +1159,9 @@ EXPORTS ?engines@QNetworkConfigurationManagerPrivate@@QBE?AV?$QList@PAVQBearerEngine@@@@XZ @ 1158 NONAME ; class QList QNetworkConfigurationManagerPrivate::engines(void) const ?isOnline@QNetworkConfigurationManagerPrivate@@QBE_NXZ @ 1159 NONAME ; bool QNetworkConfigurationManagerPrivate::isOnline(void) const ?startPolling@QNetworkConfigurationManagerPrivate@@AAEXXZ @ 1160 NONAME ; void QNetworkConfigurationManagerPrivate::startPolling(void) + ?peerVerifyName@QSslSocket@@QBE?AVQString@@XZ @ 1161 NONAME ; class QString QSslSocket::peerVerifyName(void) const + ?setPeerVerifyName@QSslSocket@@QAEXABVQString@@@Z @ 1162 NONAME ; void QSslSocket::setPeerVerifyName(class QString const &) + ?nativeSession@QNetworkSessionPrivate@@SAPAVRConnection@@AAVQNetworkSession@@@Z @ 1163 NONAME ; class RConnection * QNetworkSessionPrivate::nativeSession(class QNetworkSession &) + ?nativeOpenSocket@QNetworkSessionPrivate@@SAHAAVQNetworkSession@@AAVRSocket@@III@Z @ 1164 NONAME ; int QNetworkSessionPrivate::nativeOpenSocket(class QNetworkSession &, class RSocket &, unsigned int, unsigned int, unsigned int) + ?nativeOpenHostResolver@QNetworkSessionPrivate@@SAHAAVQNetworkSession@@AAVRHostResolver@@II@Z @ 1165 NONAME ; int QNetworkSessionPrivate::nativeOpenHostResolver(class QNetworkSession &, class RHostResolver &, unsigned int, unsigned int) diff --git a/src/s60installs/bwins/QtTestu.def b/src/s60installs/bwins/QtTestu.def index a7bb9cd..239eb1f 100644 --- a/src/s60installs/bwins/QtTestu.def +++ b/src/s60installs/bwins/QtTestu.def @@ -77,4 +77,93 @@ EXPORTS ?staticMetaObject@QTestEventLoop@@2UQMetaObject@@B @ 76 NONAME ; struct QMetaObject const QTestEventLoop::staticMetaObject ?setBenchmarkResult@QTest@@YAXMW4QBenchmarkMetric@1@@Z @ 77 NONAME ; void QTest::setBenchmarkResult(float, enum QTest::QBenchmarkMetric) ?endBenchmarkMeasurement@QTest@@YA_KXZ @ 78 NONAME ; unsigned long long QTest::endBenchmarkMeasurement(void) + ?addXFail@QTestLog@@SAXPBD0H@Z @ 79 NONAME ; void QTestLog::addXFail(char const *, char const *, int) + ?leaveTestFunction@QTestLog@@SAXXZ @ 80 NONAME ; void QTestLog::leaveTestFunction(void) + ?setCurrentTestFunction@QTestResult@@SAXPBD@Z @ 81 NONAME ; void QTestResult::setCurrentTestFunction(char const *) + ?currentTestObjectName@QTestResult@@SAPBDXZ @ 82 NONAME ; char const * QTestResult::currentTestObjectName(void) + ?allDataPassed@QTestResult@@SA_NXZ @ 83 NONAME ; bool QTestResult::allDataPassed(void) + ?redirectOutput@QTestLog@@SAXPBD@Z @ 84 NONAME ; void QTestLog::redirectOutput(char const *) + ?testData@QTestTable@@QBEPAVQTestData@@H@Z @ 85 NONAME ; class QTestData * QTestTable::testData(int) const + ?isEmpty@QTestTable@@QBE_NXZ @ 86 NONAME ; bool QTestTable::isEmpty(void) const + ?logMode@QTestLog@@SA?AW4LogMode@1@XZ @ 87 NONAME ; enum QTestLog::LogMode QTestLog::logMode(void) + ?dataCount@QTestTable@@QBEHXZ @ 88 NONAME ; int QTestTable::dataCount(void) const + ?addFailure@QTestResult@@SAXPBD0H@Z @ 89 NONAME ; void QTestResult::addFailure(char const *, char const *, int) + ?setCurrentTestData@QTestResult@@SAXPAVQTestData@@@Z @ 90 NONAME ; void QTestResult::setCurrentTestData(class QTestData *) + ?setMode@QBenchmarkGlobalData@@QAEXW4Mode@1@@Z @ 91 NONAME ; void QBenchmarkGlobalData::setMode(enum QBenchmarkGlobalData::Mode) + ??1QTestTable@@QAE@XZ @ 92 NONAME ; QTestTable::~QTestTable(void) + ?setLogMode@QTestLog@@SAXW4LogMode@1@@Z @ 93 NONAME ; void QTestLog::setLogMode(enum QTestLog::LogMode) + ?addBenchmarkResult@QTestLog@@SAXABVQBenchmarkResult@@@Z @ 94 NONAME ; void QTestLog::addBenchmarkResult(class QBenchmarkResult const &) + ?setVerboseLevel@QTestLog@@SAXH@Z @ 95 NONAME ; void QTestLog::setVerboseLevel(int) + ??0QBenchmarkGlobalData@@QAE@XZ @ 96 NONAME ; QBenchmarkGlobalData::QBenchmarkGlobalData(void) + ?stopLogging@QTestLog@@SAXXZ @ 97 NONAME ; void QTestLog::stopLogging(void) + ?setCurrentGlobalTestData@QTestResult@@SAXPAVQTestData@@@Z @ 98 NONAME ; void QTestResult::setCurrentGlobalTestData(class QTestData *) + ?currentTestLocation@QTestResult@@SA?AW4TestLocation@1@XZ @ 99 NONAME ; enum QTestResult::TestLocation QTestResult::currentTestLocation(void) + ?currentTestFunction@QTestResult@@SAPBDXZ @ 100 NONAME ; char const * QTestResult::currentTestFunction(void) + ?dataTag@QTestTable@@QBEPBDH@Z @ 101 NONAME ; char const * QTestTable::dataTag(int) const + ?expectFail@QTestResult@@SA_NPBD0W4TestFailMode@QTest@@0H@Z @ 102 NONAME ; bool QTestResult::expectFail(char const *, char const *, enum QTest::TestFailMode, char const *, int) + ?currentDataTag@QTestResult@@SAPBDXZ @ 103 NONAME ; char const * QTestResult::currentDataTag(void) + ??0QTestTable@@QAE@XZ @ 104 NONAME ; QTestTable::QTestTable(void) + ?setFlushMode@QTestLog@@SAXW4FlushMode@1@@Z @ 105 NONAME ; void QTestLog::setFlushMode(enum QTestLog::FlushMode) + ?setCurrentTestObject@QTestResult@@SAXPBD@Z @ 106 NONAME ; void QTestResult::setCurrentTestObject(char const *) + ?beginDataRun@QBenchmarkTestMethodData@@QAEXXZ @ 107 NONAME ; void QBenchmarkTestMethodData::beginDataRun(void) + ?qtest_qParseArgs@QTest@@YAXHQAPAD_N@Z @ 108 NONAME ; void QTest::qtest_qParseArgs(int, char * * const, bool) + ?enterTestFunction@QTestLog@@SAXPBD@Z @ 109 NONAME ; void QTestLog::enterTestFunction(char const *) + ?clearGlobalTestTable@QTestTable@@SAXXZ @ 110 NONAME ; void QTestTable::clearGlobalTestTable(void) + ?addPass@QTestLog@@SAXPBD@Z @ 111 NONAME ; void QTestLog::addPass(char const *) + ?printUnhandledIgnoreMessages@QTestLog@@SAXXZ @ 112 NONAME ; void QTestLog::printUnhandledIgnoreMessages(void) + ?addColumn@QTestTable@@QAEXHPBD@Z @ 113 NONAME ; void QTestTable::addColumn(int, char const *) + ?setSkipCurrentTest@QTestResult@@SAX_N@Z @ 114 NONAME ; void QTestResult::setSkipCurrentTest(bool) + ?currentTestFailed@QTestResult@@SA_NXZ @ 115 NONAME ; bool QTestResult::currentTestFailed(void) + ?createMeasurer@QBenchmarkGlobalData@@QAEPAVQBenchmarkMeasurerBase@@XZ @ 116 NONAME ; class QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer(void) + ?startLogging@QTestLog@@SAXXZ @ 117 NONAME ; void QTestLog::startLogging(void) + ?printAvailableFunctions@QTest@@3_NA @ 118 NONAME ; bool QTest::printAvailableFunctions + ?testFailed@QTestResult@@SA_NXZ @ 119 NONAME ; bool QTestResult::testFailed(void) + ?current@QBenchmarkTestMethodData@@2PAV1@A @ 120 NONAME ; class QBenchmarkTestMethodData * QBenchmarkTestMethodData::current + ?currentGlobalDataTag@QTestResult@@SAPBDXZ @ 121 NONAME ; char const * QTestResult::currentGlobalDataTag(void) + ?adjustIterationCount@QBenchmarkTestMethodData@@QAEHH@Z @ 122 NONAME ; int QBenchmarkTestMethodData::adjustIterationCount(int) + ?current@QBenchmarkGlobalData@@2PAV1@A @ 123 NONAME ; class QBenchmarkGlobalData * QBenchmarkGlobalData::current + ?warn@QTestLog@@SAXPBD@Z @ 124 NONAME ; void QTestLog::warn(char const *) + ?testFunctions@QTest@@3VQStringList@@A @ 125 NONAME ; class QStringList QTest::testFunctions + ?elementTypeId@QTestTable@@QBEHH@Z @ 126 NONAME ; int QTestTable::elementTypeId(int) const + ?ignoreMessage@QTestResult@@SAXW4QtMsgType@@PBD@Z @ 127 NONAME ; void QTestResult::ignoreMessage(enum QtMsgType, char const *) + ?globalTestTable@QTestTable@@SAPAV1@XZ @ 128 NONAME ; class QTestTable * QTestTable::globalTestTable(void) + ??0QBenchmarkTestMethodData@@QAE@XZ @ 129 NONAME ; QBenchmarkTestMethodData::QBenchmarkTestMethodData(void) + ?currentTestTable@QTestTable@@SAPAV1@XZ @ 130 NONAME ; class QTestTable * QTestTable::currentTestTable(void) + ?addFail@QTestLog@@SAXPBD0H@Z @ 131 NONAME ; void QTestLog::addFail(char const *, char const *, int) + ?endDataRun@QBenchmarkTestMethodData@@QAEXXZ @ 132 NONAME ; void QBenchmarkTestMethodData::endDataRun(void) + ?resultsAccepted@QBenchmarkTestMethodData@@QBE_NXZ @ 133 NONAME ; bool QBenchmarkTestMethodData::resultsAccepted(void) const + ?verify@QTestResult@@SA_N_NPBD11H@Z @ 134 NONAME ; bool QTestResult::verify(bool, char const *, char const *, char const *, int) + ??1QBenchmarkTestMethodData@@QAE@XZ @ 135 NONAME ; QBenchmarkTestMethodData::~QBenchmarkTestMethodData(void) + ?addIgnoreMessage@QTestLog@@SAXW4QtMsgType@@PBD@Z @ 136 NONAME ; void QTestLog::addIgnoreMessage(enum QtMsgType, char const *) + ?newData@QTestTable@@QAEPAVQTestData@@PBD@Z @ 137 NONAME ; class QTestData * QTestTable::newData(char const *) + ?reset@QTestResult@@SAXXZ @ 138 NONAME ; void QTestResult::reset(void) + ?currentTestData@QTestResult@@SAPAVQTestData@@XZ @ 139 NONAME ; class QTestData * QTestResult::currentTestData(void) + ?skipCurrentTest@QTestResult@@SA_NXZ @ 140 NONAME ; bool QTestResult::skipCurrentTest(void) + ?outputFileName@QTestLog@@SAPBDXZ @ 141 NONAME ; char const * QTestLog::outputFileName(void) + ?adjustMedianIterationCount@QBenchmarkGlobalData@@QAEHXZ @ 142 NONAME ; int QBenchmarkGlobalData::adjustMedianIterationCount(void) + ??0QTestLog@@AAE@XZ @ 143 NONAME ; QTestLog::QTestLog(void) + ?compare@QTestResult@@SA_N_NPBDPAD2111H@Z @ 144 NONAME ; bool QTestResult::compare(bool, char const *, char *, char *, char const *, char const *, char const *, int) + ?elementCount@QTestTable@@QBEHXZ @ 145 NONAME ; int QTestTable::elementCount(void) const + ?setResult@QBenchmarkTestMethodData@@QAEXMW4QBenchmarkMetric@QTest@@_N@Z @ 146 NONAME ; void QBenchmarkTestMethodData::setResult(float, enum QTest::QBenchmarkMetric, bool) + ?finishedCurrentTestFunction@QTestResult@@SAXXZ @ 147 NONAME ; void QTestResult::finishedCurrentTestFunction(void) + ?setCurrentTestLocation@QTestResult@@SAXW4TestLocation@1@@Z @ 148 NONAME ; void QTestResult::setCurrentTestLocation(enum QTestResult::TestLocation) + ?currentGlobalTestData@QTestResult@@SAPAVQTestData@@XZ @ 149 NONAME ; class QTestData * QTestResult::currentGlobalTestData(void) + ?mode@QBenchmarkGlobalData@@QBE?AW4Mode@1@XZ @ 150 NONAME ; enum QBenchmarkGlobalData::Mode QBenchmarkGlobalData::mode(void) const + ?setMaxWarnings@QTestLog@@SAXH@Z @ 151 NONAME ; void QTestLog::setMaxWarnings(int) + ?failCount@QTestResult@@SAHXZ @ 152 NONAME ; int QTestResult::failCount(void) + ?verboseLevel@QTestLog@@SAHXZ @ 153 NONAME ; int QTestLog::verboseLevel(void) + ?passCount@QTestResult@@SAHXZ @ 154 NONAME ; int QTestResult::passCount(void) + ?indexOf@QTestTable@@QBEHPBD@Z @ 155 NONAME ; int QTestTable::indexOf(char const *) const + ?compare@QTestResult@@SA_N_NPBD1H@Z @ 156 NONAME ; bool QTestResult::compare(bool, char const *, char const *, int) + ?startLogging@QTestLog@@SAXI@Z @ 157 NONAME ; void QTestLog::startLogging(unsigned int) + ?addSkip@QTestLog@@SAXPBDW4SkipMode@QTest@@0H@Z @ 158 NONAME ; void QTestLog::addSkip(char const *, enum QTest::SkipMode, char const *, int) + ?testTags@QTest@@3VQStringList@@A @ 159 NONAME ; class QStringList QTest::testTags + ??1QTestLog@@AAE@XZ @ 160 NONAME ; QTestLog::~QTestLog(void) + ?unhandledIgnoreMessages@QTestLog@@SAHXZ @ 161 NONAME ; int QTestLog::unhandledIgnoreMessages(void) + ?info@QTestLog@@SAXPBD0H@Z @ 162 NONAME ; void QTestLog::info(char const *, char const *, int) + ??1QBenchmarkGlobalData@@QAE@XZ @ 163 NONAME ; QBenchmarkGlobalData::~QBenchmarkGlobalData(void) + ?isBenchmark@QBenchmarkTestMethodData@@QBE_NXZ @ 164 NONAME ; bool QBenchmarkTestMethodData::isBenchmark(void) const + ?addSkip@QTestResult@@SAXPBDW4SkipMode@QTest@@0H@Z @ 165 NONAME ; void QTestResult::addSkip(char const *, enum QTest::SkipMode, char const *, int) + ?skipCount@QTestResult@@SAHXZ @ 166 NONAME ; int QTestResult::skipCount(void) + ?addXPass@QTestLog@@SAXPBD0H@Z @ 167 NONAME ; void QTestLog::addXPass(char const *, char const *, int) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 207447f..c514fbd 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -1282,7 +1282,7 @@ EXPORTS _ZN23QEventDispatcherSymbian10startingUpEv @ 1281 NONAME _ZN23QEventDispatcherSymbian10timerFiredEi @ 1282 NONAME _ZN23QEventDispatcherSymbian11closingDownEv @ 1283 NONAME - _ZN23QEventDispatcherSymbian11socketFiredEP19QSocketActiveObject @ 1284 NONAME + _ZN23QEventDispatcherSymbian11socketFiredEP19QSocketActiveObject @ 1284 NONAME ABSENT _ZN23QEventDispatcherSymbian13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE @ 1285 NONAME _ZN23QEventDispatcherSymbian13registerTimerEiiP7QObject @ 1286 NONAME _ZN23QEventDispatcherSymbian15unregisterTimerEi @ 1287 NONAME @@ -1439,7 +1439,7 @@ EXPORTS _ZN31QAbstractEventDispatcherPrivate4initEv @ 1438 NONAME _ZN31QNonContiguousByteDeviceFactory4wrapEP24QNonContiguousByteDevice @ 1439 NONAME _ZN31QNonContiguousByteDeviceFactory6createEP10QByteArray @ 1440 NONAME - _ZN31QNonContiguousByteDeviceFactory6createEP11QRingBuffer @ 1441 NONAME + _ZN31QNonContiguousByteDeviceFactory6createEP11QRingBuffer @ 1441 NONAME ABSENT _ZN31QNonContiguousByteDeviceFactory6createEP9QIODevice @ 1442 NONAME _ZN4QDir10setCurrentERK7QString @ 1443 NONAME _ZN4QDir10setSortingE6QFlagsINS_8SortFlagEE @ 1444 NONAME @@ -3806,4 +3806,30 @@ EXPORTS _ZNK13QElapsedTimer12nsecsElapsedEv @ 3805 NONAME _ZNK11QMetaMethod8revisionEv @ 3806 NONAME _ZNK13QMetaProperty8revisionEv @ 3807 NONAME + _Z25qt_symbianGetSocketServerv @ 3808 NONAME + _ZN13QActiveObject18maybeQueueForLaterEv @ 3809 NONAME + _ZN13QActiveObject21maybeDeferSocketEventEv @ 3810 NONAME + _ZN13QActiveObject21reactivateAndCompleteEv @ 3811 NONAME + _ZN13QActiveObject4waitE5QListIP7CActiveEi @ 3812 NONAME + _ZN13QActiveObject4waitEP7CActivei @ 3813 NONAME + _ZN13QActiveObjectC2EiP23QEventDispatcherSymbian @ 3814 NONAME + _ZN13QActiveObjectD0Ev @ 3815 NONAME + _ZN13QActiveObjectD1Ev @ 3816 NONAME + _ZN13QActiveObjectD2Ev @ 3817 NONAME + _ZN21QSymbianSocketManager12removeSocketERK7RSocket @ 3818 NONAME + _ZN21QSymbianSocketManager15getSocketServerEv @ 3819 NONAME + _ZN21QSymbianSocketManager20setDefaultConnectionEP11RConnection @ 3820 NONAME + _ZN21QSymbianSocketManager8instanceEv @ 3821 NONAME + _ZN21QSymbianSocketManager9addSocketERK7RSocket @ 3822 NONAME + _ZN21QSymbianSocketManagerC1Ev @ 3823 NONAME + _ZN21QSymbianSocketManagerC2Ev @ 3824 NONAME + _ZN21QSymbianSocketManagerD1Ev @ 3825 NONAME + _ZN21QSymbianSocketManagerD2Ev @ 3826 NONAME + _ZN31QNonContiguousByteDeviceFactory6createE14QSharedPointerI11QRingBufferE @ 3827 NONAME + _ZNK21QSymbianSocketManager12lookupSocketERK7RSocket @ 3828 NONAME + _ZNK21QSymbianSocketManager12lookupSocketEiR7RSocket @ 3829 NONAME + _ZNK21QSymbianSocketManager17defaultConnectionEv @ 3830 NONAME + _ZTI13QActiveObject @ 3831 NONAME + _ZTV13QActiveObject @ 3832 NONAME + gzungetc @ 3833 NONAME diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 722dee8..c28bfb5 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12337,4 +12337,24 @@ EXPORTS _ZN12QTextControl23setWordSelectionEnabledEb @ 12336 NONAME _ZNK12QTextControl13isDragEnabledEv @ 12337 NONAME _ZNK12QTextControl22isWordSelectionEnabledEv @ 12338 NONAME + _ZN12QLineControl16updateMicroFocusEv @ 12339 NONAME + _ZN17QInternalMimeData11canReadDataERK7QString @ 12340 NONAME + _ZN17QInternalMimeData11qt_metacallEN11QMetaObject4CallEiPPv @ 12341 NONAME + _ZN17QInternalMimeData11qt_metacastEPKc @ 12342 NONAME + _ZN17QInternalMimeData13formatsHelperEPK9QMimeData @ 12343 NONAME + _ZN17QInternalMimeData15hasFormatHelperERK7QStringPK9QMimeData @ 12344 NONAME + _ZN17QInternalMimeData16renderDataHelperERK7QStringPK9QMimeData @ 12345 NONAME + _ZN17QInternalMimeData16staticMetaObjectE @ 12346 NONAME DATA 16 + _ZN17QInternalMimeData19getStaticMetaObjectEv @ 12347 NONAME + _ZN17QInternalMimeDataC2Ev @ 12348 NONAME + _ZN17QInternalMimeDataD0Ev @ 12349 NONAME + _ZN17QInternalMimeDataD1Ev @ 12350 NONAME + _ZN17QInternalMimeDataD2Ev @ 12351 NONAME + _ZNK14QWidgetPrivate20assignedInputContextEv @ 12352 NONAME + _ZNK17QInternalMimeData10metaObjectEv @ 12353 NONAME + _ZNK17QInternalMimeData12retrieveDataERK7QStringN8QVariant4TypeE @ 12354 NONAME + _ZNK17QInternalMimeData7formatsEv @ 12355 NONAME + _ZNK17QInternalMimeData9hasFormatERK7QString @ 12356 NONAME + _ZTI17QInternalMimeData @ 12357 NONAME + _ZTV17QInternalMimeData @ 12358 NONAME diff --git a/src/s60installs/eabi/QtNetworku.def b/src/s60installs/eabi/QtNetworku.def index 9b989a7..672ae84 100644 --- a/src/s60installs/eabi/QtNetworku.def +++ b/src/s60installs/eabi/QtNetworku.def @@ -1181,4 +1181,9 @@ EXPORTS _ZNK35QNetworkConfigurationManagerPrivate27configurationFromIdentifierERK7QString @ 1180 NONAME _ZNK35QNetworkConfigurationManagerPrivate7enginesEv @ 1181 NONAME _ZNK35QNetworkConfigurationManagerPrivate8isOnlineEv @ 1182 NONAME + _ZN10QSslSocket17setPeerVerifyNameERK7QString @ 1183 NONAME + _ZN22QNetworkSessionPrivate13nativeSessionER15QNetworkSession @ 1184 NONAME + _ZN22QNetworkSessionPrivate16nativeOpenSocketER15QNetworkSessionR7RSocketjjj @ 1185 NONAME + _ZN22QNetworkSessionPrivate22nativeOpenHostResolverER15QNetworkSessionR13RHostResolverjj @ 1186 NONAME + _ZNK10QSslSocket14peerVerifyNameEv @ 1187 NONAME diff --git a/src/s60installs/eabi/QtTestu.def b/src/s60installs/eabi/QtTestu.def index 5cb95ba..370466b 100644 --- a/src/s60installs/eabi/QtTestu.def +++ b/src/s60installs/eabi/QtTestu.def @@ -70,4 +70,98 @@ EXPORTS _ZTI14QTestEventLoop @ 69 NONAME _ZTV14QTestEventLoop @ 70 NONAME _ZN5QTest18setBenchmarkResultEfNS_16QBenchmarkMetricE @ 71 NONAME + _ZN10QTestTable15globalTestTableEv @ 72 NONAME + _ZN10QTestTable16currentTestTableEv @ 73 NONAME + _ZN10QTestTable20clearGlobalTestTableEv @ 74 NONAME + _ZN10QTestTable7newDataEPKc @ 75 NONAME + _ZN10QTestTable9addColumnEiPKc @ 76 NONAME + _ZN10QTestTableC1Ev @ 77 NONAME + _ZN10QTestTableC2Ev @ 78 NONAME + _ZN10QTestTableD1Ev @ 79 NONAME + _ZN10QTestTableD2Ev @ 80 NONAME + _ZN11QTestResult10addFailureEPKcS1_i @ 81 NONAME + _ZN11QTestResult10expectFailEPKcS1_N5QTest12TestFailModeES1_i @ 82 NONAME + _ZN11QTestResult10testFailedEv @ 83 NONAME + _ZN11QTestResult13allDataPassedEv @ 84 NONAME + _ZN11QTestResult13ignoreMessageE9QtMsgTypePKc @ 85 NONAME + _ZN11QTestResult14currentDataTagEv @ 86 NONAME + _ZN11QTestResult15currentTestDataEv @ 87 NONAME + _ZN11QTestResult15skipCurrentTestEv @ 88 NONAME + _ZN11QTestResult17currentTestFailedEv @ 89 NONAME + _ZN11QTestResult18setCurrentTestDataEP9QTestData @ 90 NONAME + _ZN11QTestResult18setSkipCurrentTestEb @ 91 NONAME + _ZN11QTestResult19currentTestFunctionEv @ 92 NONAME + _ZN11QTestResult19currentTestLocationEv @ 93 NONAME + _ZN11QTestResult20currentGlobalDataTagEv @ 94 NONAME + _ZN11QTestResult20setCurrentTestObjectEPKc @ 95 NONAME + _ZN11QTestResult21currentGlobalTestDataEv @ 96 NONAME + _ZN11QTestResult21currentTestObjectNameEv @ 97 NONAME + _ZN11QTestResult22setCurrentTestFunctionEPKc @ 98 NONAME + _ZN11QTestResult22setCurrentTestLocationENS_12TestLocationE @ 99 NONAME + _ZN11QTestResult24setCurrentGlobalTestDataEP9QTestData @ 100 NONAME + _ZN11QTestResult27finishedCurrentTestFunctionEv @ 101 NONAME + _ZN11QTestResult5resetEv @ 102 NONAME + _ZN11QTestResult6verifyEbPKcS1_S1_i @ 103 NONAME + _ZN11QTestResult7addSkipEPKcN5QTest8SkipModeES1_i @ 104 NONAME + _ZN11QTestResult7compareEbPKcPcS2_S1_S1_S1_i @ 105 NONAME + _ZN11QTestResult7compareEbPKcS1_i @ 106 NONAME + _ZN11QTestResult9failCountEv @ 107 NONAME + _ZN11QTestResult9passCountEv @ 108 NONAME + _ZN11QTestResult9skipCountEv @ 109 NONAME + _ZN20QBenchmarkGlobalData14createMeasurerEv @ 110 NONAME + _ZN20QBenchmarkGlobalData26adjustMedianIterationCountEv @ 111 NONAME + _ZN20QBenchmarkGlobalData7currentE @ 112 NONAME DATA 4 + _ZN20QBenchmarkGlobalData7setModeENS_4ModeE @ 113 NONAME + _ZN20QBenchmarkGlobalDataC1Ev @ 114 NONAME + _ZN20QBenchmarkGlobalDataC2Ev @ 115 NONAME + _ZN20QBenchmarkGlobalDataD1Ev @ 116 NONAME + _ZN20QBenchmarkGlobalDataD2Ev @ 117 NONAME + _ZN24QBenchmarkTestMethodData10endDataRunEv @ 118 NONAME + _ZN24QBenchmarkTestMethodData12beginDataRunEv @ 119 NONAME + _ZN24QBenchmarkTestMethodData20adjustIterationCountEi @ 120 NONAME + _ZN24QBenchmarkTestMethodData7currentE @ 121 NONAME DATA 4 + _ZN24QBenchmarkTestMethodData9setResultEfN5QTest16QBenchmarkMetricEb @ 122 NONAME + _ZN24QBenchmarkTestMethodDataC1Ev @ 123 NONAME + _ZN24QBenchmarkTestMethodDataC2Ev @ 124 NONAME + _ZN24QBenchmarkTestMethodDataD1Ev @ 125 NONAME + _ZN24QBenchmarkTestMethodDataD2Ev @ 126 NONAME + _ZN5QTest13testFunctionsE @ 127 NONAME DATA 4 + _ZN5QTest16qtest_qParseArgsEiPPcb @ 128 NONAME + _ZN5QTest23printAvailableFunctionsE @ 129 NONAME DATA 1 + _ZN5QTest8testTagsE @ 130 NONAME DATA 4 + _ZN8QTestLog10setLogModeENS_7LogModeE @ 131 NONAME + _ZN8QTestLog11stopLoggingEv @ 132 NONAME + _ZN8QTestLog12setFlushModeENS_9FlushModeE @ 133 NONAME + _ZN8QTestLog12startLoggingEj @ 134 NONAME + _ZN8QTestLog12startLoggingEv @ 135 NONAME + _ZN8QTestLog12verboseLevelEv @ 136 NONAME + _ZN8QTestLog14outputFileNameEv @ 137 NONAME + _ZN8QTestLog14redirectOutputEPKc @ 138 NONAME + _ZN8QTestLog14setMaxWarningsEi @ 139 NONAME + _ZN8QTestLog15setVerboseLevelEi @ 140 NONAME + _ZN8QTestLog16addIgnoreMessageE9QtMsgTypePKc @ 141 NONAME + _ZN8QTestLog17enterTestFunctionEPKc @ 142 NONAME + _ZN8QTestLog17leaveTestFunctionEv @ 143 NONAME + _ZN8QTestLog18addBenchmarkResultERK16QBenchmarkResult @ 144 NONAME + _ZN8QTestLog23unhandledIgnoreMessagesEv @ 145 NONAME + _ZN8QTestLog28printUnhandledIgnoreMessagesEv @ 146 NONAME + _ZN8QTestLog4infoEPKcS1_i @ 147 NONAME + _ZN8QTestLog4warnEPKc @ 148 NONAME + _ZN8QTestLog7addFailEPKcS1_i @ 149 NONAME + _ZN8QTestLog7addPassEPKc @ 150 NONAME + _ZN8QTestLog7addSkipEPKcN5QTest8SkipModeES1_i @ 151 NONAME + _ZN8QTestLog7logModeEv @ 152 NONAME + _ZN8QTestLog8addXFailEPKcS1_i @ 153 NONAME + _ZN8QTestLog8addXPassEPKcS1_i @ 154 NONAME + _ZN8QTestLogC1Ev @ 155 NONAME + _ZN8QTestLogC2Ev @ 156 NONAME + _ZN8QTestLogD1Ev @ 157 NONAME + _ZN8QTestLogD2Ev @ 158 NONAME + _ZNK10QTestTable12elementCountEv @ 159 NONAME + _ZNK10QTestTable13elementTypeIdEi @ 160 NONAME + _ZNK10QTestTable7dataTagEi @ 161 NONAME + _ZNK10QTestTable7indexOfEPKc @ 162 NONAME + _ZNK10QTestTable7isEmptyEv @ 163 NONAME + _ZNK10QTestTable8testDataEi @ 164 NONAME + _ZNK10QTestTable9dataCountEv @ 165 NONAME -- cgit v0.12 From 7d3832891e8229051d7ddc420cd0a323a4f5d17a Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 23 Mar 2011 16:09:31 +0100 Subject: tst_qnetworkreply: Use proper Content-Type Reviewed-by: Peter Hartmann --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index f8a9530..a5f1577 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -1768,6 +1768,7 @@ void tst_QNetworkReply::postToHttp() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply; QFETCH(QByteArray, data); @@ -1794,6 +1795,7 @@ void tst_QNetworkReply::postToHttpSynchronous() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); request.setAttribute( QNetworkRequest::SynchronousRequestAttribute, @@ -3408,6 +3410,8 @@ void tst_QNetworkReply::ioPostToHttpFromFile() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); + QNetworkReplyPtr reply = manager.post(request, &sourceFile); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -3484,8 +3488,10 @@ void tst_QNetworkReply::ioPostToHttpFromSocket() socketpair.endPoints[0]->write(data); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); + manager.setProxy(proxy); - QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), socketpair.endPoints[1]); + QNetworkReplyPtr reply = manager.post(request, socketpair.endPoints[1]); socketpair.endPoints[0]->close(); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -3558,6 +3564,7 @@ void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); request.setAttribute( QNetworkRequest::SynchronousRequestAttribute, true); @@ -3587,7 +3594,8 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileToEnd() QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; QNetworkRequest request(url); - QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), &sourceFile); + request.setRawHeader("Content-Type", "application/octet-stream"); + QNetworkReplyPtr reply = manager.post(request, &sourceFile); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), @@ -3613,6 +3621,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileFiveBytes() QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); // only send 5 bytes request.setHeader(QNetworkRequest::ContentLengthHeader, 5); QVERIFY(request.header(QNetworkRequest::ContentLengthHeader).isValid()); @@ -3673,6 +3682,7 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag() QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); // disallow buffering request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, true); request.setHeader(QNetworkRequest::ContentLengthHeader, data.size()); @@ -3735,6 +3745,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() // create the request QUrl url = QUrl(QString("https://127.0.0.1:%1/").arg(server.serverPort())); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply = manager.post(request, &sourceFile); QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64))); connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -3956,6 +3967,7 @@ void tst_QNetworkReply::ioPostToHttpEmptyUploadProgress() // create the request QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort())); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply = manager.post(request, &buffer); QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64))); connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -4302,6 +4314,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp() QByteArray data = cookieString.toLatin1() + '\n'; QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply; RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); @@ -4329,7 +4342,7 @@ void tst_QNetworkReply::receiveCookiesFromHttpSynchronous() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi"); QNetworkRequest request(url); - + request.setRawHeader("Content-Type", "application/octet-stream"); request.setAttribute( QNetworkRequest::SynchronousRequestAttribute, true); -- cgit v0.12 From 10d81f9a815f889ebf693f89eaf381299d7ccfc2 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 25 Mar 2011 10:30:17 +0100 Subject: QHostInfo: Don't mess with addr family ordering Reviewed-by: Aaron Tunney --- src/network/kernel/qhostinfo_symbian.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 5998a72..02bef40 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -160,13 +160,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer 0)) { - if (nameResult().iAddr.Family() == KAfInet) { - // IPv4 - prepend - hostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); - } else { - // IPv6 - append - hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); - } + hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); } } @@ -389,13 +383,7 @@ void QSymbianHostResolver::processNameResults() // Ensure that record is valid (not an alias and with length greater than 0) if (!(iNameResult().iFlags & TNameRecord::EAlias) && (ipAddr.Length() > 0)) { - if (iNameResult().iAddr.Family() == KAfInet) { - // IPv4 - prepend - hostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); - } else { - // IPv6 - append - hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); - } + hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); } } -- cgit v0.12 From be5e7924ec7bd6cccd626f931f55e2687910ad13 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Mar 2011 13:33:54 +0000 Subject: Fix for tst_QEventLoop::processEventsExcludeSocket Depending on the OS scheduling, the TCP data sent and flushed may not have been looped back to trigger the socket's ready to read notification before the test called processEvents. This caused a failure on CI system windows 7. Added a short delay before processEvents to allow the OS to catch up. Reviewed-By: Markus Goetz --- tests/auto/qeventloop/tst_qeventloop.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qeventloop/tst_qeventloop.cpp b/tests/auto/qeventloop/tst_qeventloop.cpp index aad8390..fa2a34e 100644 --- a/tests/auto/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/qeventloop/tst_qeventloop.cpp @@ -602,6 +602,7 @@ public slots: QTcpSocket *serverSocket = server->nextPendingConnection(); serverSocket->write(data, size); serverSocket->flush(); + QTest::qSleep(200); //allow the TCP/IP stack time to loopback the data, so our socket is ready to read QCoreApplication::processEvents(QEventLoop::ExcludeSocketNotifiers); testResult = dataArrived; QCoreApplication::processEvents(); //check the deferred event is processed -- cgit v0.12 From ffab45eeec38416631a2c95148dbbedb8add2d7c Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Mar 2011 17:03:59 +0000 Subject: Fix new http multipart test case on symbian The new test added three reference data files required by the test, but these were not being included in the sis file. Reviewed-by: mread --- tests/auto/qnetworkreply/test/test.pro | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/auto/qnetworkreply/test/test.pro b/tests/auto/qnetworkreply/test/test.pro index 80b879a..d1f6707 100644 --- a/tests/auto/qnetworkreply/test/test.pro +++ b/tests/auto/qnetworkreply/test/test.pro @@ -16,21 +16,18 @@ win32 { QT = core network RESOURCES += ../qnetworkreply.qrc -wince*: { - addFiles.files = ../empty ../rfc3252.txt ../resource - addFiles.path = . - DEPLOYMENT += addFiles -} - -symbian:{ - addFiles.files = ../empty ../rfc3252.txt ../resource ../bigfile +symbian|wince*:{ + # For cross compiled targets, reference data files need to be deployed + addFiles.files = ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg addFiles.path = . DEPLOYMENT += addFiles certFiles.files = ../certs certFiles.path = . DEPLOYMENT += certFiles +} +symbian:{ # Symbian toolchain does not support correct include semantics INCLUDEPATH+=..\\..\\..\\..\\include\\QtNetwork\\private # bigfile test case requires more heap -- cgit v0.12 From 41ffab6b5b2d9f5a578109a4ea6ca0c5df58a3eb Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 12:54:29 +0100 Subject: Update DEF files --- src/s60installs/bwins/QtCoreu.def | 40 +++++++++++++++++++++++++++-- src/s60installs/bwins/QtGuiu.def | 6 +++++ src/s60installs/bwins/QtNetworku.def | 31 ++++++++++++++++++++++ src/s60installs/eabi/QtCoreu.def | 30 ++++++++++++++++++++++ src/s60installs/eabi/QtGuiu.def | 50 ++++++++++++++++++++++++++---------- src/s60installs/eabi/QtNetworku.def | 32 +++++++++++++++++++++++ src/s60installs/eabi/QtOpenVGu.def | 4 +++ 7 files changed, 178 insertions(+), 15 deletions(-) diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 8265f98..f6d4271 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -1375,7 +1375,7 @@ EXPORTS ?count@QStringRef@@QBEHXZ @ 1374 NONAME ; int QStringRef::count(void) const ?countriesForLanguage@QLocale@@SA?AV?$QList@W4Country@QLocale@@@@W4Language@1@@Z @ 1375 NONAME ; class QList QLocale::countriesForLanguage(enum QLocale::Language) ?country@QLocale@@QBE?AW4Country@1@XZ @ 1376 NONAME ; enum QLocale::Country QLocale::country(void) const - ?countryId@QLocalePrivate@@QBEIXZ @ 1377 NONAME ; unsigned int QLocalePrivate::countryId(void) const + ?countryId@QLocalePrivate@@QBEIXZ @ 1377 NONAME ABSENT ; unsigned int QLocalePrivate::countryId(void) const ?countryToString@QLocale@@SA?AVQString@@W4Country@1@@Z @ 1378 NONAME ; class QString QLocale::countryToString(enum QLocale::Country) ?create@QAbstractFileEngine@@SAPAV1@ABVQString@@@Z @ 1379 NONAME ; class QAbstractFileEngine * QAbstractFileEngine::create(class QString const &) ?create@QNonContiguousByteDeviceFactory@@SAPAVQNonContiguousByteDevice@@PAVQByteArray@@@Z @ 1380 NONAME ; class QNonContiguousByteDevice * QNonContiguousByteDeviceFactory::create(class QByteArray *) @@ -2331,7 +2331,7 @@ EXPORTS ?killTimer@QObject@@QAEXH@Z @ 2330 NONAME ; void QObject::killTimer(int) ?killTimer@QTimer@@AAEXH@Z @ 2331 NONAME ; void QTimer::killTimer(int) ?language@QLocale@@QBE?AW4Language@1@XZ @ 2332 NONAME ; enum QLocale::Language QLocale::language(void) const - ?languageId@QLocalePrivate@@QBEIXZ @ 2333 NONAME ; unsigned int QLocalePrivate::languageId(void) const + ?languageId@QLocalePrivate@@QBEIXZ @ 2333 NONAME ABSENT ; unsigned int QLocalePrivate::languageId(void) const ?languageToString@QLocale@@SA?AVQString@@W4Language@1@@Z @ 2334 NONAME ; class QString QLocale::languageToString(enum QLocale::Language) ?lastIndexIn@QRegExp@@QBEHABVQString@@HW4CaretMode@1@@Z @ 2335 NONAME ; int QRegExp::lastIndexIn(class QString const &, int, enum QRegExp::CaretMode) const ?lastIndexOf@QByteArray@@QBEHABV1@H@Z @ 2336 NONAME ; int QByteArray::lastIndexOf(class QByteArray const &, int) const @@ -4631,3 +4631,39 @@ EXPORTS ?removeSocket@QSymbianSocketManager@@QAE_NABVRSocket@@@Z @ 4630 NONAME ; bool QSymbianSocketManager::removeSocket(class RSocket const &) ?started@QAnimationDriver@@MAEXXZ @ 4631 NONAME ; void QAnimationDriver::started(void) ?stopped@QAnimationDriver@@MAEXXZ @ 4632 NONAME ; void QAnimationDriver::stopped(void) + ?toCurrencyString@QLocale@@QBE?AVQString@@NABV2@@Z @ 4633 NONAME ; class QString QLocale::toCurrencyString(double, class QString const &) const + ?quoteString@QLocale@@QBE?AVQString@@ABVQStringRef@@W4QuotationStyle@1@@Z @ 4634 NONAME ; class QString QLocale::quoteString(class QStringRef const &, enum QLocale::QuotationStyle) const + ?toCurrencyString@QLocale@@QBE?AVQString@@FABV2@@Z @ 4635 NONAME ; class QString QLocale::toCurrencyString(short, class QString const &) const + ?countryCode@QLocalePrivate@@QBE?AVQString@@XZ @ 4636 NONAME ; class QString QLocalePrivate::countryCode(void) const + ?toCurrencyString@QLocale@@QBE?AVQString@@IABV2@@Z @ 4637 NONAME ; class QString QLocale::toCurrencyString(unsigned int, class QString const &) const + ?longLongToString@QLocalePrivate@@SA?AVQString@@VQChar@@000_JHHHI@Z @ 4638 NONAME ; class QString QLocalePrivate::longLongToString(class QChar, class QChar, class QChar, class QChar, long long, int, int, int, unsigned int) + ?codeToScript@QLocalePrivate@@SA?AW4Script@QLocale@@ABVQString@@@Z @ 4639 NONAME ; enum QLocale::Script QLocalePrivate::codeToScript(class QString const &) + ?bcp47Name@QLocale@@QBE?AVQString@@XZ @ 4640 NONAME ; class QString QLocale::bcp47Name(void) const + ?quoteString@QLocale@@QBE?AVQString@@ABV2@W4QuotationStyle@1@@Z @ 4641 NONAME ; class QString QLocale::quoteString(class QString const &, enum QLocale::QuotationStyle) const + ?unsLongLongToString@QLocalePrivate@@SA?AVQString@@VQChar@@00_KHHHI@Z @ 4642 NONAME ; class QString QLocalePrivate::unsLongLongToString(class QChar, class QChar, class QChar, unsigned long long, int, int, int, unsigned int) + ?toCurrencyString@QLocale@@QBE?AVQString@@_KABV2@@Z @ 4643 NONAME ; class QString QLocale::toCurrencyString(unsigned long long, class QString const &) const + ?firstDayOfWeek@QLocale@@QBE?AW4DayOfWeek@Qt@@XZ @ 4644 NONAME ; enum Qt::DayOfWeek QLocale::firstDayOfWeek(void) const + ?createSeparatedList@QLocale@@QBE?AVQString@@ABVQStringList@@@Z @ 4645 NONAME ; class QString QLocale::createSeparatedList(class QStringList const &) const + ?codeToCountry@QLocalePrivate@@SA?AW4Country@QLocale@@ABVQString@@@Z @ 4646 NONAME ; enum QLocale::Country QLocalePrivate::codeToCountry(class QString const &) + ?scriptCode@QLocalePrivate@@QBE?AVQString@@XZ @ 4647 NONAME ; class QString QLocalePrivate::scriptCode(void) const + ?scriptToString@QLocale@@SA?AVQString@@W4Script@1@@Z @ 4648 NONAME ; class QString QLocale::scriptToString(enum QLocale::Script) + ?script@QLocale@@QBE?AW4Script@1@XZ @ 4649 NONAME ; enum QLocale::Script QLocale::script(void) const + ?codeToLanguage@QLocalePrivate@@SA?AW4Language@QLocale@@ABVQString@@@Z @ 4650 NONAME ; enum QLocale::Language QLocalePrivate::codeToLanguage(class QString const &) + ?weekdays@QLocale@@QBE?AV?$QList@W4DayOfWeek@Qt@@@@XZ @ 4651 NONAME ; class QList QLocale::weekdays(void) const + ?getLangAndCountry@QLocalePrivate@@SAXABVQString@@AAW4Language@QLocale@@AAW4Script@4@AAW4Country@4@@Z @ 4652 NONAME ; void QLocalePrivate::getLangAndCountry(class QString const &, enum QLocale::Language &, enum QLocale::Script &, enum QLocale::Country &) + ?bcp47Name@QLocalePrivate@@QBE?AVQString@@XZ @ 4653 NONAME ; class QString QLocalePrivate::bcp47Name(void) const + ?toCurrencyString@QLocale@@QBE?AVQString@@HABV2@@Z @ 4654 NONAME ; class QString QLocale::toCurrencyString(int, class QString const &) const + ?matchingLocales@QLocale@@SA?AVQStringList@@W4Language@1@W4Script@1@W4Country@1@@Z @ 4655 NONAME ; class QStringList QLocale::matchingLocales(enum QLocale::Language, enum QLocale::Script, enum QLocale::Country) + ?languageCode@QLocalePrivate@@QBE?AVQString@@XZ @ 4656 NONAME ; class QString QLocalePrivate::languageCode(void) const + ?toCurrencyString@QLocale@@QBE?AVQString@@GABV2@@Z @ 4657 NONAME ; class QString QLocale::toCurrencyString(unsigned short, class QString const &) const + ?doubleToString@QLocalePrivate@@SA?AVQString@@VQChar@@00000NHW4DoubleForm@1@HI@Z @ 4658 NONAME ; class QString QLocalePrivate::doubleToString(class QChar, class QChar, class QChar, class QChar, class QChar, class QChar, double, int, enum QLocalePrivate::DoubleForm, int, unsigned int) + ?currencySymbol@QLocale@@QBE?AVQString@@W4CurrencySymbolFormat@1@@Z @ 4659 NONAME ; class QString QLocale::currencySymbol(enum QLocale::CurrencySymbolFormat) const + ?uiLanguages@QLocale@@QBE?AVQStringList@@XZ @ 4660 NONAME ; class QStringList QLocale::uiLanguages(void) const + ?findLocale@QLocalePrivate@@SAPBU1@W4Language@QLocale@@W4Script@3@W4Country@3@@Z @ 4661 NONAME ; struct QLocalePrivate const * QLocalePrivate::findLocale(enum QLocale::Language, enum QLocale::Script, enum QLocale::Country) + ?load@QTranslator@@QAE_NABVQLocale@@ABVQString@@111@Z @ 4662 NONAME ; bool QTranslator::load(class QLocale const &, class QString const &, class QString const &, class QString const &, class QString const &) + ??0QLocale@@QAE@W4Language@0@W4Script@0@W4Country@0@@Z @ 4663 NONAME ; QLocale::QLocale(enum QLocale::Language, enum QLocale::Script, enum QLocale::Country) + ?languageId@QLocalePrivate@@QBEGXZ @ 4664 NONAME ; unsigned short QLocalePrivate::languageId(void) const + ?countryId@QLocalePrivate@@QBEGXZ @ 4665 NONAME ; unsigned short QLocalePrivate::countryId(void) const + ?toCurrencyString@QLocale@@QBE?AVQString@@_JABV2@@Z @ 4666 NONAME ; class QString QLocale::toCurrencyString(long long, class QString const &) const + ?toCurrencyString@QLocale@@QBE?AVQString@@MABV2@@Z @ 4667 NONAME ; class QString QLocale::toCurrencyString(float, class QString const &) const + diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 0c3d1a2..0be8a53 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -13203,3 +13203,9 @@ EXPORTS ?byteCount@QVolatileImage@@QBEHXZ @ 13202 NONAME ; int QVolatileImage::byteCount(void) const ??0QVolatileImage@@QAE@ABV0@@Z @ 13203 NONAME ; QVolatileImage::QVolatileImage(class QVolatileImage const &) ?depth@QVolatileImage@@QBEHXZ @ 13204 NONAME ; int QVolatileImage::depth(void) const + ?setTabsClosable@QMdiArea@@QAEX_N@Z @ 13205 NONAME ; void QMdiArea::setTabsClosable(bool) + ?qt_s60_setPartialScreenInputMode@@YAX_N@Z @ 13206 NONAME ; void qt_s60_setPartialScreenInputMode(bool) + ?setTabsMovable@QMdiArea@@QAEX_N@Z @ 13207 NONAME ; void QMdiArea::setTabsMovable(bool) + ?tabsMovable@QMdiArea@@QBE_NXZ @ 13208 NONAME ; bool QMdiArea::tabsMovable(void) const + ?tabsClosable@QMdiArea@@QBE_NXZ @ 13209 NONAME ; bool QMdiArea::tabsClosable(void) const + diff --git a/src/s60installs/bwins/QtNetworku.def b/src/s60installs/bwins/QtNetworku.def index 3f8f6d2..dbe43d7 100644 --- a/src/s60installs/bwins/QtNetworku.def +++ b/src/s60installs/bwins/QtNetworku.def @@ -1164,4 +1164,35 @@ EXPORTS ?nativeSession@QNetworkSessionPrivate@@SAPAVRConnection@@AAVQNetworkSession@@@Z @ 1163 NONAME ; class RConnection * QNetworkSessionPrivate::nativeSession(class QNetworkSession &) ?nativeOpenSocket@QNetworkSessionPrivate@@SAHAAVQNetworkSession@@AAVRSocket@@III@Z @ 1164 NONAME ; int QNetworkSessionPrivate::nativeOpenSocket(class QNetworkSession &, class RSocket &, unsigned int, unsigned int, unsigned int) ?nativeOpenHostResolver@QNetworkSessionPrivate@@SAHAAVQNetworkSession@@AAVRHostResolver@@II@Z @ 1165 NONAME ; int QNetworkSessionPrivate::nativeOpenHostResolver(class QNetworkSession &, class RHostResolver &, unsigned int, unsigned int) + ??_EQHttpMultiPart@@UAE@I@Z @ 1166 NONAME ; QHttpMultiPart::~QHttpMultiPart(unsigned int) + ??1QHttpPart@@QAE@XZ @ 1167 NONAME ; QHttpPart::~QHttpPart(void) + ?trUtf8@QHttpMultiPart@@SA?AVQString@@PBD0@Z @ 1168 NONAME ; class QString QHttpMultiPart::trUtf8(char const *, char const *) + ??0QHttpPart@@QAE@ABV0@@Z @ 1169 NONAME ; QHttpPart::QHttpPart(class QHttpPart const &) + ?setBody@QHttpPart@@QAEXABVQByteArray@@@Z @ 1170 NONAME ; void QHttpPart::setBody(class QByteArray const &) + ?trUtf8@QHttpMultiPart@@SA?AVQString@@PBD0H@Z @ 1171 NONAME ; class QString QHttpMultiPart::trUtf8(char const *, char const *, int) + ?staticMetaObject@QHttpMultiPart@@2UQMetaObject@@B @ 1172 NONAME ; struct QMetaObject const QHttpMultiPart::staticMetaObject + ??4QHttpPart@@QAEAAV0@ABV0@@Z @ 1173 NONAME ; class QHttpPart & QHttpPart::operator=(class QHttpPart const &) + ?append@QHttpMultiPart@@QAEXABVQHttpPart@@@Z @ 1174 NONAME ; void QHttpMultiPart::append(class QHttpPart const &) + ?setContentType@QHttpMultiPart@@QAEXW4ContentType@1@@Z @ 1175 NONAME ; void QHttpMultiPart::setContentType(enum QHttpMultiPart::ContentType) + ?d_func@QHttpMultiPart@@AAEPAVQHttpMultiPartPrivate@@XZ @ 1176 NONAME ; class QHttpMultiPartPrivate * QHttpMultiPart::d_func(void) + ??9QHttpPart@@QBE_NABV0@@Z @ 1177 NONAME ; bool QHttpPart::operator!=(class QHttpPart const &) const + ??0QHttpMultiPart@@QAE@W4ContentType@0@PAVQObject@@@Z @ 1178 NONAME ; QHttpMultiPart::QHttpMultiPart(enum QHttpMultiPart::ContentType, class QObject *) + ??0QHttpPart@@QAE@XZ @ 1179 NONAME ; QHttpPart::QHttpPart(void) + ?post@QNetworkAccessManager@@QAEPAVQNetworkReply@@ABVQNetworkRequest@@PAVQHttpMultiPart@@@Z @ 1180 NONAME ; class QNetworkReply * QNetworkAccessManager::post(class QNetworkRequest const &, class QHttpMultiPart *) + ??0QHttpMultiPart@@QAE@PAVQObject@@@Z @ 1181 NONAME ; QHttpMultiPart::QHttpMultiPart(class QObject *) + ??8QHttpPart@@QBE_NABV0@@Z @ 1182 NONAME ; bool QHttpPart::operator==(class QHttpPart const &) const + ?setBodyDevice@QHttpPart@@QAEXPAVQIODevice@@@Z @ 1183 NONAME ; void QHttpPart::setBodyDevice(class QIODevice *) + ?getStaticMetaObject@QHttpMultiPart@@SAABUQMetaObject@@XZ @ 1184 NONAME ; struct QMetaObject const & QHttpMultiPart::getStaticMetaObject(void) + ?qt_metacast@QHttpMultiPart@@UAEPAXPBD@Z @ 1185 NONAME ; void * QHttpMultiPart::qt_metacast(char const *) + ?put@QNetworkAccessManager@@QAEPAVQNetworkReply@@ABVQNetworkRequest@@PAVQHttpMultiPart@@@Z @ 1186 NONAME ; class QNetworkReply * QNetworkAccessManager::put(class QNetworkRequest const &, class QHttpMultiPart *) + ?tr@QHttpMultiPart@@SA?AVQString@@PBD0@Z @ 1187 NONAME ; class QString QHttpMultiPart::tr(char const *, char const *) + ?qt_metacall@QHttpMultiPart@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1188 NONAME ; int QHttpMultiPart::qt_metacall(enum QMetaObject::Call, int, void * *) + ?boundary@QHttpMultiPart@@QBE?AVQByteArray@@XZ @ 1189 NONAME ; class QByteArray QHttpMultiPart::boundary(void) const + ?setRawHeader@QHttpPart@@QAEXABVQByteArray@@0@Z @ 1190 NONAME ; void QHttpPart::setRawHeader(class QByteArray const &, class QByteArray const &) + ?metaObject@QHttpMultiPart@@UBEPBUQMetaObject@@XZ @ 1191 NONAME ; struct QMetaObject const * QHttpMultiPart::metaObject(void) const + ?setHeader@QHttpPart@@QAEXW4KnownHeaders@QNetworkRequest@@ABVQVariant@@@Z @ 1192 NONAME ; void QHttpPart::setHeader(enum QNetworkRequest::KnownHeaders, class QVariant const &) + ??1QHttpMultiPart@@UAE@XZ @ 1193 NONAME ; QHttpMultiPart::~QHttpMultiPart(void) + ?d_func@QHttpMultiPart@@ABEPBVQHttpMultiPartPrivate@@XZ @ 1194 NONAME ; class QHttpMultiPartPrivate const * QHttpMultiPart::d_func(void) const + ?tr@QHttpMultiPart@@SA?AVQString@@PBD0H@Z @ 1195 NONAME ; class QString QHttpMultiPart::tr(char const *, char const *, int) + ?setBoundary@QHttpMultiPart@@QAEXABVQByteArray@@@Z @ 1196 NONAME ; void QHttpMultiPart::setBoundary(class QByteArray const &) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index c5dd0ac..1bf52b1 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3834,3 +3834,33 @@ EXPORTS gzungetc @ 3833 NONAME _ZN16QAnimationDriverC1EP7QObject @ 3834 NONAME _ZN16QAnimationDriverC1ER23QAnimationDriverPrivateP7QObject @ 3835 NONAME + _ZN11QTranslator4loadERK7QLocaleRK7QStringS5_S5_S5_ @ 3836 NONAME + _ZN14QLocalePrivate10findLocaleEN7QLocale8LanguageENS0_6ScriptENS0_7CountryE @ 3837 NONAME + _ZN14QLocalePrivate12codeToScriptERK7QString @ 3838 NONAME + _ZN14QLocalePrivate13codeToCountryERK7QString @ 3839 NONAME + _ZN14QLocalePrivate14codeToLanguageERK7QString @ 3840 NONAME + _ZN14QLocalePrivate14doubleToStringE5QCharS0_S0_S0_S0_S0_diNS_10DoubleFormEij @ 3841 NONAME + _ZN14QLocalePrivate16longLongToStringE5QCharS0_S0_S0_xiiij @ 3842 NONAME + _ZN14QLocalePrivate17getLangAndCountryERK7QStringRN7QLocale8LanguageERNS3_6ScriptERNS3_7CountryE @ 3843 NONAME + _ZN14QLocalePrivate19unsLongLongToStringE5QCharS0_S0_yiiij @ 3844 NONAME + _ZN7QLocale14scriptToStringENS_6ScriptE @ 3845 NONAME + _ZN7QLocale15matchingLocalesENS_8LanguageENS_6ScriptENS_7CountryE @ 3846 NONAME + _ZN7QLocaleC1ENS_8LanguageENS_6ScriptENS_7CountryE @ 3847 NONAME + _ZN7QLocaleC2ENS_8LanguageENS_6ScriptENS_7CountryE @ 3848 NONAME + _ZNK14QLocalePrivate10scriptCodeEv @ 3849 NONAME + _ZNK14QLocalePrivate11countryCodeEv @ 3850 NONAME + _ZNK14QLocalePrivate12languageCodeEv @ 3851 NONAME + _ZNK14QLocalePrivate9bcp47NameEv @ 3852 NONAME + _ZNK7QLocale11quoteStringERK10QStringRefNS_14QuotationStyleE @ 3853 NONAME + _ZNK7QLocale11quoteStringERK7QStringNS_14QuotationStyleE @ 3854 NONAME + _ZNK7QLocale11uiLanguagesEv @ 3855 NONAME + _ZNK7QLocale14currencySymbolENS_20CurrencySymbolFormatE @ 3856 NONAME + _ZNK7QLocale14firstDayOfWeekEv @ 3857 NONAME + _ZNK7QLocale16toCurrencyStringEdRK7QString @ 3858 NONAME + _ZNK7QLocale16toCurrencyStringExRK7QString @ 3859 NONAME + _ZNK7QLocale16toCurrencyStringEyRK7QString @ 3860 NONAME + _ZNK7QLocale19createSeparatedListERK11QStringList @ 3861 NONAME + _ZNK7QLocale6scriptEv @ 3862 NONAME + _ZNK7QLocale8weekdaysEv @ 3863 NONAME + _ZNK7QLocale9bcp47NameEv @ 3864 NONAME + diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 561e332..2ffb98e 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12360,17 +12360,41 @@ EXPORTS _ZN14QVolatileImageD2Ev @ 12359 NONAME _ZN14QVolatileImageaSERKS_ @ 12360 NONAME _ZN15QGraphicsSystem22releaseCachedResourcesEv @ 12361 NONAME - _ZNK14QVolatileImage12bytesPerLineEv @ 12374 NONAME - _ZNK14QVolatileImage13endDataAccessEb @ 12375 NONAME - _ZNK14QVolatileImage15beginDataAccessEv @ 12376 NONAME - _ZNK14QVolatileImage15hasAlphaChannelEv @ 12377 NONAME - _ZNK14QVolatileImage20duplicateNativeImageEv @ 12378 NONAME - _ZNK14QVolatileImage5depthEv @ 12379 NONAME - _ZNK14QVolatileImage5widthEv @ 12380 NONAME - _ZNK14QVolatileImage6formatEv @ 12381 NONAME - _ZNK14QVolatileImage6heightEv @ 12382 NONAME - _ZNK14QVolatileImage6isNullEv @ 12383 NONAME - _ZNK14QVolatileImage7toImageEv @ 12384 NONAME - _ZNK14QVolatileImage9byteCountEv @ 12385 NONAME - _ZNK14QVolatileImage9constBitsEv @ 12386 NONAME + _Z32qt_s60_setPartialScreenInputModeb @ 12362 NONAME + _ZN17QInternalMimeData11canReadDataERK7QString @ 12363 NONAME + _ZN17QInternalMimeData11qt_metacallEN11QMetaObject4CallEiPPv @ 12364 NONAME + _ZN17QInternalMimeData11qt_metacastEPKc @ 12365 NONAME + _ZN17QInternalMimeData13formatsHelperEPK9QMimeData @ 12366 NONAME + _ZN17QInternalMimeData15hasFormatHelperERK7QStringPK9QMimeData @ 12367 NONAME + _ZN17QInternalMimeData16renderDataHelperERK7QStringPK9QMimeData @ 12368 NONAME + _ZN17QInternalMimeData16staticMetaObjectE @ 12369 NONAME DATA 16 + _ZN17QInternalMimeData19getStaticMetaObjectEv @ 12370 NONAME + _ZN17QInternalMimeDataC2Ev @ 12371 NONAME + _ZN17QInternalMimeDataD0Ev @ 12372 NONAME + _ZN17QInternalMimeDataD1Ev @ 12373 NONAME + _ZN17QInternalMimeDataD2Ev @ 12374 NONAME + _ZN8QMdiArea14setTabsMovableEb @ 12375 NONAME + _ZN8QMdiArea15setTabsClosableEb @ 12376 NONAME + _ZNK14QVolatileImage12bytesPerLineEv @ 12377 NONAME + _ZNK14QVolatileImage13endDataAccessEb @ 12378 NONAME + _ZNK14QVolatileImage15beginDataAccessEv @ 12379 NONAME + _ZNK14QVolatileImage15hasAlphaChannelEv @ 12380 NONAME + _ZNK14QVolatileImage20duplicateNativeImageEv @ 12381 NONAME + _ZNK14QVolatileImage5depthEv @ 12382 NONAME + _ZNK14QVolatileImage5widthEv @ 12383 NONAME + _ZNK14QVolatileImage6formatEv @ 12384 NONAME + _ZNK14QVolatileImage6heightEv @ 12385 NONAME + _ZNK14QVolatileImage6isNullEv @ 12386 NONAME + _ZNK14QVolatileImage7toImageEv @ 12387 NONAME + _ZNK14QVolatileImage9byteCountEv @ 12388 NONAME + _ZNK14QVolatileImage9constBitsEv @ 12389 NONAME + _ZNK14QWidgetPrivate20assignedInputContextEv @ 12390 NONAME + _ZNK17QInternalMimeData10metaObjectEv @ 12391 NONAME + _ZNK17QInternalMimeData12retrieveDataERK7QStringN8QVariant4TypeE @ 12392 NONAME + _ZNK17QInternalMimeData7formatsEv @ 12393 NONAME + _ZNK17QInternalMimeData9hasFormatERK7QString @ 12394 NONAME + _ZNK8QMdiArea11tabsMovableEv @ 12395 NONAME + _ZNK8QMdiArea12tabsClosableEv @ 12396 NONAME + _ZTI17QInternalMimeData @ 12397 NONAME + _ZTV17QInternalMimeData @ 12398 NONAME diff --git a/src/s60installs/eabi/QtNetworku.def b/src/s60installs/eabi/QtNetworku.def index 672ae84..47d251d 100644 --- a/src/s60installs/eabi/QtNetworku.def +++ b/src/s60installs/eabi/QtNetworku.def @@ -1186,4 +1186,36 @@ EXPORTS _ZN22QNetworkSessionPrivate16nativeOpenSocketER15QNetworkSessionR7RSocketjjj @ 1185 NONAME _ZN22QNetworkSessionPrivate22nativeOpenHostResolverER15QNetworkSessionR13RHostResolverjj @ 1186 NONAME _ZNK10QSslSocket14peerVerifyNameEv @ 1187 NONAME + _ZN14QHttpMultiPart11qt_metacallEN11QMetaObject4CallEiPPv @ 1188 NONAME + _ZN14QHttpMultiPart11qt_metacastEPKc @ 1189 NONAME + _ZN14QHttpMultiPart11setBoundaryERK10QByteArray @ 1190 NONAME + _ZN14QHttpMultiPart14setContentTypeENS_11ContentTypeE @ 1191 NONAME + _ZN14QHttpMultiPart16staticMetaObjectE @ 1192 NONAME DATA 16 + _ZN14QHttpMultiPart19getStaticMetaObjectEv @ 1193 NONAME + _ZN14QHttpMultiPart6appendERK9QHttpPart @ 1194 NONAME + _ZN14QHttpMultiPartC1ENS_11ContentTypeEP7QObject @ 1195 NONAME + _ZN14QHttpMultiPartC1EP7QObject @ 1196 NONAME + _ZN14QHttpMultiPartC2ENS_11ContentTypeEP7QObject @ 1197 NONAME + _ZN14QHttpMultiPartC2EP7QObject @ 1198 NONAME + _ZN14QHttpMultiPartD0Ev @ 1199 NONAME + _ZN14QHttpMultiPartD1Ev @ 1200 NONAME + _ZN14QHttpMultiPartD2Ev @ 1201 NONAME + _ZN21QNetworkAccessManager3putERK15QNetworkRequestP14QHttpMultiPart @ 1202 NONAME + _ZN21QNetworkAccessManager4postERK15QNetworkRequestP14QHttpMultiPart @ 1203 NONAME + _ZN9QHttpPart12setRawHeaderERK10QByteArrayS2_ @ 1204 NONAME + _ZN9QHttpPart13setBodyDeviceEP9QIODevice @ 1205 NONAME + _ZN9QHttpPart7setBodyERK10QByteArray @ 1206 NONAME + _ZN9QHttpPart9setHeaderEN15QNetworkRequest12KnownHeadersERK8QVariant @ 1207 NONAME + _ZN9QHttpPartC1ERKS_ @ 1208 NONAME + _ZN9QHttpPartC1Ev @ 1209 NONAME + _ZN9QHttpPartC2ERKS_ @ 1210 NONAME + _ZN9QHttpPartC2Ev @ 1211 NONAME + _ZN9QHttpPartD1Ev @ 1212 NONAME + _ZN9QHttpPartD2Ev @ 1213 NONAME + _ZN9QHttpPartaSERKS_ @ 1214 NONAME + _ZNK14QHttpMultiPart10metaObjectEv @ 1215 NONAME + _ZNK14QHttpMultiPart8boundaryEv @ 1216 NONAME + _ZNK9QHttpParteqERKS_ @ 1217 NONAME + _ZTI14QHttpMultiPart @ 1218 NONAME + _ZTV14QHttpMultiPart @ 1219 NONAME diff --git a/src/s60installs/eabi/QtOpenVGu.def b/src/s60installs/eabi/QtOpenVGu.def index e05cc79..72f11fc 100644 --- a/src/s60installs/eabi/QtOpenVGu.def +++ b/src/s60installs/eabi/QtOpenVGu.def @@ -209,4 +209,8 @@ EXPORTS _ZN13QVGPixmapData12updateSerialEv @ 208 NONAME ABSENT _ZN13QVGPixmapData4copyEPK11QPixmapDataRK5QRect @ 209 NONAME ABSENT _ZNK13QVGPixmapData11idealFormatEP6QImage6QFlagsIN2Qt19ImageConversionFlagEE @ 210 NONAME ABSENT + _ZN13QVGPixmapData24releaseNativeImageHandleEv @ 211 NONAME + _ZN13QVGPixmapData25initFromNativeImageHandleEPvRK7QString @ 212 NONAME + _ZN13QVGPixmapData35createFromNativeImageHandleProviderEv @ 213 NONAME + _ZNK13QVGPixmapData14ensureReadbackEb @ 214 NONAME -- cgit v0.12 From bcbce977fa7a0d61de5f17e6727eba5a823bc3bb Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 25 Mar 2011 18:07:15 +0000 Subject: Performance: use select poll for timeout of 0ms A timer of 0ms completes on the next kernel tick (up to 0.999ms) There is a poll GetOpt we can use instead that doesn't require using a timer to cancel the select ioctl. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 67 ++++++++++++++++------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 58e8d9f..af755a9 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1105,39 +1105,46 @@ int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool selectFlags() |= KSockSelectRead; if (checkWrite) 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(); -#ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select timeout"; -#endif - return 0; //timeout - } else { - selectTimer.Cancel(); - User::WaitForRequest(timerStat); + TInt err; + if (timeout == 0) { + //if timeout is zero, poll + err = nativeSocket.GetOpt(KSOSelectPoll, KSOLSocket, selectFlags); + } else { + 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(); + #ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select timeout"; + #endif + return 0; //timeout + } else { + selectTimer.Cancel(); + User::WaitForRequest(timerStat); + } } + + #ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select status" << selectStat.Int() << (int)selectFlags(); + #endif + err = selectStat.Int(); } -#ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "QSymbianSocketEnginePrivate::nativeSelect: select status" << selectStat.Int() << (int)selectFlags(); -#endif - TInt err = selectStat.Int(); if (!err && (selectFlags() & KSockSelectExcept)) { nativeSocket.GetOpt(KSOSelectLastError, KSOLSocket, err); #ifdef QNATIVESOCKETENGINE_DEBUG -- cgit v0.12 From a970c3334bba3b7e1e27fa8b1b4ad4e4724ce015 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 15:58:34 +0100 Subject: Bearer support for autotests Start default bearer when running network self test Fix typo in qnetworkreply test Reviewed-by: Markus Goetz --- tests/auto/networkselftest/tst_networkselftest.cpp | 26 ++++++++++++++++++++++ tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/auto/networkselftest/tst_networkselftest.cpp b/tests/auto/networkselftest/tst_networkselftest.cpp index 64de64a..ed070d7 100644 --- a/tests/auto/networkselftest/tst_networkselftest.cpp +++ b/tests/auto/networkselftest/tst_networkselftest.cpp @@ -44,6 +44,12 @@ #include +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif + #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir // Current path (C:\private\) contains only ascii chars @@ -64,6 +70,7 @@ public: QHostAddress serverIpAddress(); private slots: + void initTestCase(); void hostTest(); void dnsResolution_data(); void dnsResolution(); @@ -91,6 +98,12 @@ private slots: // ssl supported test void supportsSsl(); +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif }; class Chat @@ -354,6 +367,19 @@ QHostAddress tst_NetworkSelfTest::serverIpAddress() return cachedIpAddress; } +void tst_NetworkSelfTest::initTestCase() +{ +#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_NetworkSelfTest::hostTest() { // this is a localhost self-test diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 4b8dc3b..11f4fc3 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -143,7 +143,7 @@ class tst_QNetworkReply: public QObject QSslConfiguration storedSslConfiguration; QList storedExpectedSslErrors; #endif -#ifndef QT_NO_BEARER_MANAGEMENT +#ifndef QT_NO_BEARERMANAGEMENT QNetworkConfigurationManager *netConfMan; QNetworkConfiguration networkConfiguration; QScopedPointer networkSession; -- cgit v0.12 From aa67255608d7b752fcdd6fcbabf518dbdbf4f98e Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 16:02:10 +0100 Subject: Symbian workaround for networkselftest The frox ftp proxy closes connections using TCP RST instead of a normal TCP FIN. On symbian, this causes the received but unacknowledged preceding packet to be discarded (the "221 Goodbye" ftp response). As QNAM and QFTP don't care about this, the network self test won't either. (only for symbian, as windows and unix TCP/IP stacks retain the unacknowledged packet in the receive queue) Reviewed-by: Markus Goetz --- tests/auto/networkselftest/tst_networkselftest.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/auto/networkselftest/tst_networkselftest.cpp b/tests/auto/networkselftest/tst_networkselftest.cpp index ed070d7..f40ea3e 100644 --- a/tests/auto/networkselftest/tst_networkselftest.cpp +++ b/tests/auto/networkselftest/tst_networkselftest.cpp @@ -495,7 +495,8 @@ void tst_NetworkSelfTest::fileLineEndingTest() static QList ftpChat(const QByteArray &userSuffix = QByteArray()) { - return QList() << Chat::expect("220") + QList rv; + rv << Chat::expect("220") << Chat::discardUntil("\r\n") << Chat::send("USER anonymous" + userSuffix + "\r\n") << Chat::expect("331") @@ -530,10 +531,15 @@ static QList ftpChat(const QByteArray &userSuffix = QByteArray()) // << Chat::send("SIZE nonASCII/german_\344\366\374\304\326\334\337\r\n") // << Chat::expect("213 40\r\n") - << Chat::send("QUIT\r\n") - << Chat::expect("221") - << Chat::discardUntil("\r\n") - << Chat::RemoteDisconnect; + << Chat::send("QUIT\r\n"); +#ifdef Q_OS_SYMBIAN + if (userSuffix.length() == 0) // received but unacknowledged packets are discarded by TCP RST, so this doesn't work with frox proxy +#endif + rv << Chat::expect("221") + << Chat::discardUntil("\r\n"); + + rv << Chat::RemoteDisconnect; + return rv; } void tst_NetworkSelfTest::ftpServer() -- cgit v0.12 From b58eb992f162efc9db6cada9f037f7a0acbe5c57 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 17:53:45 +0100 Subject: Ensure shared network session deleted from correct thread Due to threaded http, the shared QNetworkSession can have its last reference removed from a http delegate thread. To avoid this deadlocking use a deleteLater custom deleter so that the QNS is deleted from the thread it has affinity for. Reviewed-by: Markus Goetz --- src/network/bearer/qsharednetworksession.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp index 28ca173..fcb0128 100644 --- a/src/network/bearer/qsharednetworksession.cpp +++ b/src/network/bearer/qsharednetworksession.cpp @@ -59,6 +59,11 @@ inline QSharedNetworkSessionManager* sharedNetworkSessionManager() return rv; } +static void doDeleteLater(QObject* obj) +{ + obj->deleteLater(); +} + QSharedPointer QSharedNetworkSessionManager::getSession(QNetworkConfiguration config) { QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); @@ -69,7 +74,7 @@ QSharedPointer QSharedNetworkSessionManager::getSession(QNetwor return p; } //otherwise make one - QSharedPointer session(new QNetworkSession(config)); + QSharedPointer session(new QNetworkSession(config), doDeleteLater); m->sessions[config] = session; return session; } -- cgit v0.12 From 917a1a04d7a507dbab4ae9e9983507870232a821 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 18:32:57 +0100 Subject: Make qhttpnetworkconnection autotest work with the new test server Loosen requirements for generated error pages (these vary with exact version and locale of the web server). Don't care what the length is, but if a content-length header is sent then it should match the size of the error page data. (apache2 does send content-length for errors) Don't fail the gzip test if the server doesn't send a content-length header. That's a server bug rather than Qt. (apache2 doesn't send) Reviewed-by: Markus Goetz --- .../tst_qhttpnetworkconnection.cpp | 48 ++++++++++++++-------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 0b72139..ba1f8c8 100644 --- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -195,8 +195,8 @@ void tst_QHttpNetworkConnection::head() QCOMPARE(reply->statusCode(), statusCode); QCOMPARE(reply->reasonPhrase(), statusString); - // only check it if it is set - if (reply->contentLength() != -1) + // only check it if it is set and expected + if (reply->contentLength() != -1 && contentLength != -1) QCOMPARE(reply->contentLength(), qint64(contentLength)); QVERIFY(reply->isFinished()); @@ -219,8 +219,8 @@ void tst_QHttpNetworkConnection::get_data() QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962; QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962; - QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << 997 + QtNetworkSettings::serverName().size(); - QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << 930 + QtNetworkSettings::serverName().size(); + QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1; + QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1; } void tst_QHttpNetworkConnection::get() @@ -255,8 +255,8 @@ void tst_QHttpNetworkConnection::get() QCOMPARE(reply->statusCode(), statusCode); QCOMPARE(reply->reasonPhrase(), statusString); - // only check it if it is set - if (reply->contentLength() != -1) + // only check it if it is set and expected + if (reply->contentLength() != -1 && contentLength != -1) QCOMPARE(reply->contentLength(), qint64(contentLength)); stopWatch.start(); @@ -270,7 +270,12 @@ void tst_QHttpNetworkConnection::get() } while (!reply->isFinished()); QVERIFY(reply->isFinished()); - QCOMPARE(ba.size(), downloadSize); + //do not require server generated error pages to be a fixed size + if (downloadSize != -1) + QCOMPARE(ba.size(), downloadSize); + //but check against content length if it was sent + if (reply->contentLength() != -1) + QCOMPARE(ba.size(), (int)reply->contentLength()); delete reply; } @@ -385,7 +390,7 @@ void tst_QHttpNetworkConnection::post_data() QTest::addColumn("downloadSize"); QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7; - QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << 997 + QtNetworkSettings::serverName().size(); + QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1; } void tst_QHttpNetworkConnection::post() @@ -429,13 +434,16 @@ void tst_QHttpNetworkConnection::post() QCOMPARE(reply->reasonPhrase(), statusString); qint64 cLen = reply->contentLength(); - if (cLen==-1) { - // HTTP 1.1 server may respond with chunked encoding and in that - // case contentLength is not present in reply -> verify that it is the case - QByteArray transferEnc = reply->headerField("Transfer-Encoding"); - QCOMPARE(transferEnc, QByteArray("chunked")); - } else { - QCOMPARE(cLen, qint64(contentLength)); + if (contentLength != -1) { + // only check the content length if test expected it to be set + if (cLen==-1) { + // HTTP 1.1 server may respond with chunked encoding and in that + // case contentLength is not present in reply -> verify that it is the case + QByteArray transferEnc = reply->headerField("Transfer-Encoding"); + QCOMPARE(transferEnc, QByteArray("chunked")); + } else { + QCOMPARE(cLen, qint64(contentLength)); + } } stopWatch.start(); @@ -449,7 +457,12 @@ void tst_QHttpNetworkConnection::post() } while (!reply->isFinished()); QVERIFY(reply->isFinished()); - QCOMPARE(ba.size(), downloadSize); + //don't require fixed size for generated error pages + if (downloadSize != -1) + QCOMPARE(ba.size(), downloadSize); + //but do compare with content length if possible + if (cLen != -1) + QCOMPARE(ba.size(), (int)cLen); delete reply; } @@ -630,7 +643,8 @@ void tst_QHttpNetworkConnection::compression() QCOMPARE(reply->statusCode(), statusCode); QCOMPARE(reply->reasonPhrase(), statusString); bool isLengthOk = (reply->contentLength() == qint64(contentLength) - || reply->contentLength() == qint64(downloadSize)); + || reply->contentLength() == qint64(downloadSize) + || reply->contentLength() == -1); //apache2 does not send content-length for compressed pages QVERIFY(isLengthOk); -- cgit v0.12 From 8c3c9742abb2d59daa0b9f8f18bd52d9f2bbdbbe Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 18:37:19 +0100 Subject: Add bearer startup to qabstractnetworkcache autotest This avoids the test starting and stopping the WLAN for each test case Reviewed-by: Markus Goetz --- .../tst_qabstractnetworkcache.cpp | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp index db0d0a7..76e6711 100644 --- a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp +++ b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp @@ -45,6 +45,12 @@ #include "../../shared/util.h" #include "../network-settings.h" +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif + #define TESTFILE QString("http://%1/qtest/cgi-bin/").arg(QtNetworkSettings::serverName()) class tst_QAbstractNetworkCache : public QObject @@ -56,6 +62,7 @@ public: virtual ~tst_QAbstractNetworkCache(); private slots: + void initTestCase(); void expires_data(); void expires(); void expiresSynchronous_data(); @@ -81,6 +88,12 @@ private slots: private: void check(); void checkSynchronous(); + +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif }; class NetworkDiskCache : public QNetworkDiskCache @@ -124,6 +137,19 @@ static bool AlwaysFalse = false; Q_DECLARE_METATYPE(QNetworkRequest::CacheLoadControl) +void tst_QAbstractNetworkCache::initTestCase() +{ +#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_QAbstractNetworkCache::expires_data() { QTest::addColumn("cacheLoadControl"); -- cgit v0.12 From da83fb86defd4e9773d56640e87da32c1e8c7f82 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 18:47:12 +0100 Subject: Remove 2 QSKIP from tst_qnetworkdiskcache Skipped because of open C bug, but these tests are passing in N8 with symbian socket & file engines Reviewed-by: Markus Goetz --- tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index e974fcc..9e06cc4 100644 --- a/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -309,9 +309,6 @@ void tst_QNetworkDiskCache::data_data() // public QIODevice* data(QUrl const& url) void tst_QNetworkDiskCache::data() { -#ifdef Q_OS_SYMBIAN - QSKIP("Due to mmap(...) bug in Open C [Temtrack DEF142242]", SkipAll); -#endif QFETCH(QNetworkCacheMetaData, data); SubQNetworkDiskCache cache; QUrl url(EXAMPLE_URL); @@ -388,9 +385,6 @@ void tst_QNetworkDiskCache::setCacheDirectory() // public void updateMetaData(QNetworkCacheMetaData const& metaData) void tst_QNetworkDiskCache::updateMetaData() { -#ifdef Q_OS_SYMBIAN - QSKIP("Due to mmap(...) bug in Open C [Temtrack DEF142242]", SkipAll); -#endif QUrl url(EXAMPLE_URL); SubQNetworkDiskCache cache; cache.setupWithOne(url); -- cgit v0.12 From 2c09d9c463aeff4888e7b694351d15cbb760ccdf Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 28 Mar 2011 19:49:12 +0100 Subject: Fix ssl autotest .pro files ReadUserData needed to avoid platsec warnings accessing cert store. Removed incorrect deployment from the two new on demand tests. Reviewed-by: Markus Goetz --- tests/auto/qsslsocket/qsslsocket.pro | 2 +- .../qsslsocket_onDemandCertificates_member.pro | 10 +--------- .../qsslsocket_onDemandCertificates_static.pro | 10 +--------- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/tests/auto/qsslsocket/qsslsocket.pro b/tests/auto/qsslsocket/qsslsocket.pro index 154f9ca..77517e0 100644 --- a/tests/auto/qsslsocket/qsslsocket.pro +++ b/tests/auto/qsslsocket/qsslsocket.pro @@ -24,7 +24,7 @@ wince* { } else:symbian { DEFINES += QSSLSOCKET_CERTUNTRUSTED_WORKAROUND TARGET.EPOCHEAPSIZE="0x100 0x3000000" - TARGET.CAPABILITY=NetworkServices + TARGET.CAPABILITY=NetworkServices ReadUserData certFiles.files = certs ssl.tar.gz certFiles.path = . diff --git a/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro index ea62865..53020eb 100644 --- a/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro +++ b/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro @@ -17,17 +17,9 @@ win32 { wince* { DEFINES += SRCDIR=\\\"./\\\" - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles } else:symbian { TARGET.EPOCHEAPSIZE="0x100 0x1000000" - TARGET.CAPABILITY=NetworkServices - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles + TARGET.CAPABILITY=NetworkServices ReadUserData INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE # Needed for e32svr.h in S^3 envs } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro index 13990cb..3452a92 100644 --- a/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro +++ b/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro @@ -17,17 +17,9 @@ win32 { wince* { DEFINES += SRCDIR=\\\"./\\\" - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles } else:symbian { TARGET.EPOCHEAPSIZE="0x100 0x1000000" - TARGET.CAPABILITY=NetworkServices - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles + TARGET.CAPABILITY=NetworkServices ReadUserData INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE # Needed for e32svr.h in S^3 envs } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" -- cgit v0.12 From 6022cd668435d1dda127e26e71de01982c7441a3 Mon Sep 17 00:00:00 2001 From: Aaron Tunney Date: Wed, 30 Mar 2011 16:46:10 +0100 Subject: Ayschronous Next() change for DNS resolution. Reviewed-By: Shane Kearns --- src/network/kernel/qhostinfo_p.h | 12 +++- src/network/kernel/qhostinfo_symbian.cpp | 116 ++++++++++++++++++------------- 2 files changed, 77 insertions(+), 51 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index a7e83da..ab3e809 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -236,6 +236,8 @@ public: void requestHostLookup(); int id(); + void returnResults(); + QHostInfoResult resultEmitter; private: @@ -244,10 +246,13 @@ private: void run(); TInt RunError(TInt aError); - void processNameResults(); - void processAddressResults(); + void processNameResult(); + void nextNameResult(); + void processAddressResult(); private: + int iId; + const QString iHostName; QString iEncodedHostName; TPtrC iHostNamePtr; @@ -263,10 +268,13 @@ private: QHostInfo iResults; + QList iHostAddresses; + enum { EIdle, EGetByName, EGetByAddress, + EGetMoreNames, EError } iState; }; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 02bef40..70ee5b8 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -53,9 +53,12 @@ #include #include -QT_BEGIN_NAMESPACE - +// Header does not exist in the S60 5.0 SDK +//#include +const TInt KErrDndNameNotFound = -5120; // Returned when no data found for GetByName +const TInt KErrDndAddrNotFound = -5121; // Returned when no data found for GetByAddr +QT_BEGIN_NAMESPACE QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer networkSession) { @@ -88,15 +91,14 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer 0)) { + if (!(nameResult().iFlags & TNameRecord::EAlias) && !(hostAdd.IsUnspecified())) { hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); } } @@ -244,7 +246,6 @@ void QSymbianHostResolver::requestHostLookup() #endif } if (err) { - // What are we doing with iResults?? iResults.setError(QHostInfo::UnknownError); iResults.setErrorString(QSystemError(err, QSystemError::NativeError).toString()); @@ -252,7 +253,6 @@ void QSymbianHostResolver::requestHostLookup() if (iAddress.setAddress(iHostName)) { // Reverse lookup - IpAdd.Input(qt_QString2TPtrC(iHostName)); // Asynchronous request. @@ -297,7 +297,7 @@ void QSymbianHostResolver::DoCancel() #if defined(QHOSTINFO_DEBUG) qDebug() << "QSymbianHostResolver::DoCancel" << QThread::currentThreadId() << id() << (int)iState << this; #endif - if (iState == EGetByAddress || iState == EGetByName) { + if (iState == EGetByAddress || iState == EGetByName || iState == EGetMoreNames) { //these states have made an async request to host resolver iHostResolver.Cancel(); } else { @@ -313,11 +313,25 @@ void QSymbianHostResolver::RunL() void QSymbianHostResolver::run() { - if (iState == EGetByName) - processNameResults(); - else if (iState == EGetByAddress) - processAddressResults(); + switch (iState) { + case EGetByName: + processNameResult(); + break; + case EGetByAddress: + processAddressResult(); + break; + case EError: + returnResults(); + break; + default: + iResults.setError(QHostInfo::UnknownError); + iResults.setErrorString(QSystemError(KErrCorrupt,QSystemError::NativeError).toString()); + returnResults(); + } +} +void QSymbianHostResolver::returnResults() +{ iState = EIdle; QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); @@ -348,55 +362,57 @@ TInt QSymbianHostResolver::RunError(TInt aError) return KErrNone; } -void QSymbianHostResolver::processNameResults() +void QSymbianHostResolver::processNameResult() { - TInt err = iStatus.Int(); - if (err < 0) { - // TODO - Could there be other errors? Symbian docs don't say. - if (err == KErrNotFound) { - iResults.setError(QHostInfo::HostNotFound); - iResults.setErrorString(QObject::tr("Host not found")); - } else { - iResults.setError(QHostInfo::UnknownError); - iResults.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); - } - - iHostResolver.Close(); - return; - } - - QList hostAddresses; - - TInetAddr hostAdd = iNameResult().iAddr; - // 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) - hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + if (iStatus.Int() == KErrNone) { + TInetAddr hostAdd = iNameResult().iAddr; + // 39 is the maximum length of an IPv6 address. + TBuf<39> ipAddr; - // Check if there's more than one IP address linkd to this name - while (iHostResolver.Next(iNameResult) == KErrNone) { - hostAdd = iNameResult().iAddr; hostAdd.Output(ipAddr); // Ensure that record is valid (not an alias and with length greater than 0) - if (!(iNameResult().iFlags & TNameRecord::EAlias) && (ipAddr.Length() > 0)) { - hostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + if (!(iNameResult().iFlags & TNameRecord::EAlias) && !(hostAdd.IsUnspecified())) { + if (iNameResult().iAddr.Family() == KAfInet) { + // IPv4 - prepend + iHostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); + } else { + // IPv6 - append + iHostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); + } } - } - iResults.setAddresses(hostAddresses); + iState = EGetByName; + iHostResolver.Next(iNameResult, iStatus); + SetActive(); + } + else if (iStatus.Int() == KErrDndNameNotFound) { + // No more addresses, so return the results (or an error if there aren't any). + if (iHostAddresses.count() > 0) { + iResults.setAddresses(iHostAddresses); + } else { + iState = EError; + iResults.setError(QHostInfo::HostNotFound); + iResults.setErrorString(QObject::tr("Host not found")); + } + returnResults(); + } + else { + // Unknown error + iState = EError; + iResults.setError(QHostInfo::UnknownError); + iResults.setErrorString(QSystemError(iStatus.Int(),QSystemError::NativeError).toString()); + returnResults(); + } } -void QSymbianHostResolver::processAddressResults() +void QSymbianHostResolver::processAddressResult() { TInt err = iStatus.Int(); if (err < 0) { // TODO - Could there be other errors? Symbian docs don't say. - if (err == KErrNotFound) { + if (err == KErrDndAddrNotFound) { iResults.setError(QHostInfo::HostNotFound); iResults.setErrorString(QObject::tr("Host not found")); } else { @@ -404,11 +420,13 @@ void QSymbianHostResolver::processAddressResults() iResults.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); } + returnResults(); return; } iResults.setHostName(qt_TDesC2QString(iNameResult().iName)); iResults.setAddresses(QList() << iAddress); + returnResults(); } -- cgit v0.12 From 591081142ce34435b4935d048a392c5727484c16 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 31 Mar 2011 15:37:13 +0100 Subject: Fix error handling in qhostinfo_symbian De-duplicate error handling into a helper function. RHostResolver can return a few different errors at the end of the list, so treat these benign ones the same. When Next() gives an error, return any results we already obtained. Reviewed-by: Aaron Tunney --- src/network/kernel/qhostinfo_symbian.cpp | 96 ++++++++++++++------------------ 1 file changed, 42 insertions(+), 54 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 70ee5b8..73fed16 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -60,6 +60,25 @@ const TInt KErrDndAddrNotFound = -5121; // Returned when no data found for GetBy QT_BEGIN_NAMESPACE +static void setError_helper(QHostInfo &info, TInt symbianError) +{ + switch (symbianError) { + case KErrDndNameNotFound: + case KErrDndAddrNotFound: + case KErrNotFound: + case KErrEof: + // various "no more results" error codes + info.setError(QHostInfo::HostNotFound); + info.setErrorString(QObject::tr("Host not found")); + break; + default: + // Unknown error + info.setError(QHostInfo::UnknownError); + info.setErrorString(QSystemError(symbianError, QSystemError::NativeError).toString()); + break; + } +} + QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer networkSession) { QHostInfo results; @@ -75,9 +94,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer() << address); } - - results.setHostName(qt_TDesC2QString(nameResult().iName)); - results.setAddresses(QList() << address); return results; } @@ -132,15 +140,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointerlookupFinished(this); - iResults.setError(QHostInfo::UnknownError); - iResults.setErrorString(QSystemError(aError,QSystemError::NativeError).toString()); + setError_helper(iResults, aError); resultEmitter.emitResultsReady(iResults); } @@ -386,24 +389,19 @@ void QSymbianHostResolver::processNameResult() iHostResolver.Next(iNameResult, iStatus); SetActive(); } - else if (iStatus.Int() == KErrDndNameNotFound) { + else { // No more addresses, so return the results (or an error if there aren't any). +#if defined(QHOSTINFO_DEBUG) + qDebug() << "QSymbianHostResolver::processNameResult with err=" << iStatus.Int() << "count=" << iHostAddresses.count(); +#endif if (iHostAddresses.count() > 0) { iResults.setAddresses(iHostAddresses); } else { iState = EError; - iResults.setError(QHostInfo::HostNotFound); - iResults.setErrorString(QObject::tr("Host not found")); + setError_helper(iResults, iStatus.Int()); } returnResults(); } - else { - // Unknown error - iState = EError; - iResults.setError(QHostInfo::UnknownError); - iResults.setErrorString(QSystemError(iStatus.Int(),QSystemError::NativeError).toString()); - returnResults(); - } } void QSymbianHostResolver::processAddressResult() @@ -411,21 +409,11 @@ void QSymbianHostResolver::processAddressResult() TInt err = iStatus.Int(); if (err < 0) { - // TODO - Could there be other errors? Symbian docs don't say. - if (err == KErrDndAddrNotFound) { - iResults.setError(QHostInfo::HostNotFound); - iResults.setErrorString(QObject::tr("Host not found")); - } else { - iResults.setError(QHostInfo::UnknownError); - iResults.setErrorString(QSystemError(err,QSystemError::NativeError).toString()); - } - - returnResults(); - return; + setError_helper(iResults, err); + } else { + iResults.setHostName(qt_TDesC2QString(iNameResult().iName)); + iResults.setAddresses(QList() << iAddress); } - - iResults.setHostName(qt_TDesC2QString(iNameResult().iName)); - iResults.setAddresses(QList() << iAddress); returnResults(); } -- cgit v0.12 From 00121f3184ade624ca9cbb2524222dcab9f67342 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 29 Mar 2011 11:55:58 +0100 Subject: Add partial upgrade rules for Qt's plugins Allows testing of plugins such as bearer without needing to reinstall all of Qt. Equivalent to the rules in qbase.pri for the normal DLLs Reviewed-by: Miikka Heikkinen --- src/plugins/qpluginbase.pri | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index 45e3976..bcf473f 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -19,4 +19,23 @@ symbian: { TARGET.CAPABILITY = All -Tcb TARGET = $${TARGET}$${QT_LIBINFIX} load(armcc_warnings) + + # Make partial upgrade SIS file for Qt plugin dll's + # Partial upgrade SIS file + vendorinfo = \ + "; Localised Vendor name" \ + "%{\"Nokia\"}" \ + " " \ + "; Unique Vendor name" \ + ":\"Nokia, Qt\"" \ + " " + isEmpty(QT_LIBINFIX): PARTIAL_UPGRADE_UID = 0x2001E61C + else: PARTIAL_UPGRADE_UID = 0xE001E61C + + pu_header = "; Partial upgrade package for testing $${TARGET} changes without reinstalling everything" \ + "$${LITERAL_HASH}{\"$${TARGET}\"}, ($$PARTIAL_UPGRADE_UID), $${QT_MAJOR_VERSION},$${QT_MINOR_VERSION},$${QT_PATCH_VERSION}, TYPE=PU" + partial_upgrade.pkg_prerules = pu_header vendorinfo + partial_upgrade.files = $$QMAKE_LIBDIR_QT/$${TARGET}.dll + partial_upgrade.path = c:/sys/bin + DEPLOYMENT += partial_upgrade } -- cgit v0.12 From f7a6e37cab7a68451b176d22acf34ed41d4f1d79 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 29 Mar 2011 11:58:32 +0100 Subject: Fix deadlock in QNetworkSession::stop The mutex added needs to be recursive, as stop calls close internally, which also needs to lock the mutex. Reviewed-by: Markus Goetz --- src/network/bearer/qnetworksession_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h index b359f80..a92b7ce 100644 --- a/src/network/bearer/qnetworksession_p.h +++ b/src/network/bearer/qnetworksession_p.h @@ -75,7 +75,7 @@ class Q_NETWORK_EXPORT QNetworkSessionPrivate : public QObject public: QNetworkSessionPrivate() : QObject(), - state(QNetworkSession::Invalid), isOpen(false) + state(QNetworkSession::Invalid), isOpen(false), mutex(QMutex::Recursive) {} virtual ~QNetworkSessionPrivate() {} -- cgit v0.12 From e1f5699f262d52e72d6855440cfc1c2919b74163 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 30 Mar 2011 16:39:14 +0100 Subject: Don't reinitialise udp socket when IP versions don't match An IPv6 socket can send to IPv4 addresses when in a dual mode stack. On symbian, autobinded sockets have the ::0 local address rather than 0.0.0.0 - this check was causing the socket to be destroyed and recreated with every call to writeDatagram. Reviewed-by: Markus Goetz --- src/network/socket/qudpsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 4334f68..dc473c6 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -202,7 +202,7 @@ bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, qui #endif // now check if the socket engine is initialized and to the right type - if (!socketEngine || !socketEngine->isValid() || socketEngine->protocol() != proto) { + if (!socketEngine || !socketEngine->isValid()) { resolveProxy(remoteAddress.toString(), bindPort); if (!initSocketLayer(address->protocol())) return false; -- cgit v0.12 From 989ca02a932cf7c90e8d29c18dd72415e46afb81 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 30 Mar 2011 16:48:51 +0100 Subject: Fix assert fail when debug log is enabled Enough debug logging allows time for the proxy server to close the http connection after sending a 407 response. This errors the connection, but then the queued _q_startNextRequest is immediately run, causing an assertion failure. Changed this to a soft failure which allows the error to propagate rather than crashing. Test case is tst_qnetworkreply::ioPostToHttpFromSocket Reviewed-by: Markus Goetz --- src/network/access/qhttpnetworkconnectionchannel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index a6d6172..6fbc6f8 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -842,7 +842,10 @@ void QHttpNetworkConnectionChannel::handleStatus() bool QHttpNetworkConnectionChannel::resetUploadData() { - Q_ASSERT(reply); + if (!reply) { + //this happens if server closes connection while QHttpNetworkConnectionPrivate::_q_startNextRequest is pending + return false; + } QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); if (!uploadByteDevice) return true; -- cgit v0.12 From cd907ff4656c8819f5aa19979ea6da25fc5947e6 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 30 Mar 2011 17:06:07 +0100 Subject: Fix multicast group membership Although symbian's multicast support is incomplete, this is enough to pass the QUdpSocket test case. (no IGMP/MLD support in the OS) Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 36 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index af755a9..52f6b68 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1198,22 +1198,32 @@ bool QSymbianSocketEnginePrivate::multicastGroupMembershipHelper(const QHostAddr const QNetworkInterface &iface, TUint operation) { - //TODO - untested +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug() << "QSymbianSocketEnginePrivate::multicastGroupMembershipHelper" << groupAddress << iface << operation; +#endif //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; + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); + memcpy(option().iAddr.u.iAddr8, ip6.c, 16); + } else { + TInetAddr wrapped; + wrapped.SetAddress(groupAddress.toIPv4Address()); + wrapped.ConvertToV4Mapped(); + option().iAddr = wrapped.Ip6Address(); + } + option().iInterface = iface.index(); //join or leave group - return (KErrNone == nativeSocket.SetOpt(operation, KSolInetIp, option)); + TInt err = nativeSocket.SetOpt(operation, KSolInetIp, option); +#if defined (QNATIVESOCKETENGINE_DEBUG) + qDebug() << "address" << qt_prettyDebug((const char *)(option().iAddr.u.iAddr8), 16, 16); + qDebug() << "interface" << option().iInterface; + qDebug() << "error" << err; +#endif + if (err) { + setError(err); + } + return (KErrNone == err); } QNetworkInterface QSymbianSocketEngine::multicastInterface() const -- cgit v0.12 From 1d8f8bc70e4f056e4e110a779d483c186fc2ad19 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 31 Mar 2011 12:19:45 +0100 Subject: Update address reporting code When an IP6 address contains a valid IP4 address, report the address in IP4 format (this is needed for SOCKS5 socket engine) When binding Any or AnyIPv6, create a dual mode socket (KAfUnspec), but report the local address as being the same as what the user requested. (by default, symbian returns ::0 for the dual mode socket, which causes problems for SOCKS and UDP code) The intent is that most applications written for IP4 can work transparently in an IP6 environment. QTcpServer or QUdpSocket can accept either IP4 or IP6 from the same socket. Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 39 +++++++++++++---------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 52f6b68..165316d 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -147,7 +147,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr) { - if (a.Family() == KAfInet6) { + if (a.Family() == KAfInet6 && !a.IsV4Compat() && !a.IsV4Mapped()) { Q_IPV6ADDR tmp; memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp)); if (addr) { @@ -226,12 +226,7 @@ bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType so void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr) { nativeAddr.SetPort(port); - 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) { + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { TPckgBuf query; query().iName = qt_QString2TPtrC(addr.scopeId()); TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query); @@ -274,7 +269,6 @@ QSymbianSocketEngine::QSymbianSocketEngine(QObject *parent) QSymbianSocketEngine::~QSymbianSocketEngine() { close(); - // FIXME what else do we need to free? } /*! @@ -650,7 +644,15 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) Q_CHECK_STATE(QSymbianSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); TInetAddr nativeAddr; - d->setPortAndAddress(nativeAddr, port, address); + if (address == QHostAddress::Any || address == QHostAddress::AnyIPv6) { + //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); + nativeAddr.SetPort(port); + } else { + d->setPortAndAddress(nativeAddr, port, address); + } TInt err = d->nativeSocket.Bind(nativeAddr); #ifdef __WINS__ @@ -684,6 +686,11 @@ bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port) d->socketState = QAbstractSocket::BoundState; d->fetchConnectionParameters(); + + // When we bind to unspecified address (to get a dual mode socket), report back the + // same type of address that was requested. This is required for SOCKS proxy to work. + if (nativeAddr.Family() == KAFUnspec) + d->localAddress = address; return true; } @@ -693,8 +700,6 @@ bool QSymbianSocketEngine::listen() 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); @@ -898,17 +903,7 @@ bool QSymbianSocketEnginePrivate::fetchConnectionParameters() getPortAndAddress(addr, &localPort, &localAddress); // Determine protocol family - switch (addr.Family()) { - case KAfInet: - socketProtocol = QAbstractSocket::IPv4Protocol; - break; - case KAfInet6: - socketProtocol = QAbstractSocket::IPv6Protocol; - break; - default: - socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol; - break; - } + socketProtocol = localAddress.protocol(); // Determine the remote address nativeSocket.RemoteName(addr); -- cgit v0.12 From a04905c2bb5caac9c9c0a3d0928f6fdfb4600cb9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 1 Apr 2011 11:08:39 +0100 Subject: Implement cache support for the async resolver Add additional check when starting a queued request, as the cache may have been populated while the request was queued. Put completed requests in the cache (note cache code internally discards errored results and only caches successful results) Reviewed-by: Aaron Tunney Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 2 +- src/network/kernel/qhostinfo_symbian.cpp | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index ab3e809..ceec04d 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -274,7 +274,7 @@ private: EIdle, EGetByName, EGetByAddress, - EGetMoreNames, + ECompleteFromCache, EError } iState; }; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 73fed16..a38a845 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -108,6 +108,9 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointercache.isEnabled()) { + //check if name has been put in the cache while this request was queued + bool valid; + QHostInfo cachedResult = manager->cache.get(iHostName, &valid); + if (valid) { +#if defined(QHOSTINFO_DEBUG) + qDebug("...found in cache"); +#endif + iResults = cachedResult; + iState = ECompleteFromCache; + SetActive(); + TRequestStatus* stat = &iStatus; + User::RequestComplete(stat, KErrNone); + return; + } + } + int err; if (iNetworkSession) { err = QNetworkSessionPrivate::nativeOpenHostResolver(*iNetworkSession, iHostResolver, KAfInet, KProtocolInetUdp); @@ -295,12 +316,12 @@ void QSymbianHostResolver::DoCancel() #if defined(QHOSTINFO_DEBUG) qDebug() << "QSymbianHostResolver::DoCancel" << QThread::currentThreadId() << id() << (int)iState << this; #endif - if (iState == EGetByAddress || iState == EGetByName || iState == EGetMoreNames) { + if (iState == EGetByAddress || iState == EGetByName) { //these states have made an async request to host resolver iHostResolver.Cancel(); } else { //for the self completing states there is nothing to cancel - Q_ASSERT(iState == EError); + Q_ASSERT(iState == EError || iState == ECompleteFromCache); } } @@ -318,6 +339,7 @@ void QSymbianHostResolver::run() case EGetByAddress: processAddressResult(); break; + case ECompleteFromCache: case EError: returnResults(); break; @@ -339,6 +361,9 @@ void QSymbianHostResolver::returnResults() iState = EIdle; QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + if (manager->cache.isEnabled()) { + manager->cache.put(iHostName, iResults); + } manager->lookupFinished(this); resultEmitter.emitResultsReady(iResults); -- cgit v0.12 From 108dbea7145c941ba39f3958596cd1f348a2a049 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 4 Apr 2011 17:32:20 +0100 Subject: Add test case for thread safety of the QHostInfo async API The existing threadSafety test only tested calling the blocking API from multiple threads. As the asynchronous API may be implemented in a different way, it should be tested separately. Create 10 threads, each of which queues 10 async name lookups. Reviewed-by: Markus Goetz --- tests/auto/qhostinfo/tst_qhostinfo.cpp | 53 +++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/tests/auto/qhostinfo/tst_qhostinfo.cpp b/tests/auto/qhostinfo/tst_qhostinfo.cpp index 8be8dcb..7b2fc55 100644 --- a/tests/auto/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/qhostinfo/tst_qhostinfo.cpp @@ -126,6 +126,7 @@ private slots: void raceCondition(); void threadSafety(); + void threadSafetyAsynchronousAPI(); void multipleSameLookups(); void multipleDifferentLookups_data(); @@ -419,7 +420,7 @@ protected: void tst_QHostInfo::threadSafety() { const int nattempts = 5; -#if defined(Q_OS_WINCE) +#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) const int runs = 10; #else const int runs = 100; @@ -433,6 +434,56 @@ void tst_QHostInfo::threadSafety() } } +class LookupReceiver : public QObject +{ + Q_OBJECT +public slots: + void start(); + void resultsReady(const QHostInfo&); +public: + QHostInfo result; + int numrequests; +}; + +void LookupReceiver::start() +{ + for (int i=0;iquit(); +} + +void tst_QHostInfo::threadSafetyAsynchronousAPI() +{ + const int nattempts = 10; + const int lookupsperthread = 10; + QList threads; + QList receivers; + for (int i = 0; i < nattempts; ++i) { + QThread* thread = new QThread; + LookupReceiver* receiver = new LookupReceiver; + receiver->numrequests = lookupsperthread; + receivers.append(receiver); + receiver->moveToThread(thread); + connect(thread, SIGNAL(started()), receiver, SLOT(start())); + thread->start(); + threads.append(thread); + } + for (int k = threads.count() - 1; k >= 0; --k) + QVERIFY(threads.at(k)->wait(60000)); + foreach (LookupReceiver* receiver, receivers) { + QCOMPARE(receiver->result.error(), QHostInfo::NoError); + QCOMPARE(receiver->result.addresses().at(0).toString(), QString("87.238.50.178")); + QCOMPARE(receiver->numrequests, 0); + } +} + // this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all, // not about getting correct IPs void tst_QHostInfo::multipleSameLookups() -- cgit v0.12 From 3b395c6e45ed4f73503586e6b9a80bb11844d315 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 4 Apr 2011 17:48:27 +0100 Subject: Fix typo in class name Manger -> Manager Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo.cpp | 16 +++++++------- src/network/kernel/qhostinfo_p.h | 18 +++++++-------- src/network/kernel/qhostinfo_symbian.cpp | 38 ++++++++++++++++---------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 3413c9b..a16d4ca 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE #ifndef Q_OS_SYMBIAN Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) #else -Q_GLOBAL_STATIC(QSymbianHostInfoLookupManger, theHostInfoLookupManager) +Q_GLOBAL_STATIC(QSymbianHostInfoLookupManager, theHostInfoLookupManager) #endif /*! @@ -202,7 +202,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, manager->scheduleLookup(runnable); } #else - QSymbianHostInfoLookupManger *manager = theHostInfoLookupManager(); + QSymbianHostInfoLookupManager *manager = theHostInfoLookupManager(); if (manager) { // the application is still alive @@ -267,7 +267,7 @@ QHostInfo QHostInfo::fromName(const QString &name) #endif QHostInfo hostInfo = QHostInfoAgent::fromName(name); - QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); manager->cache.put(name, hostInfo); return hostInfo; } @@ -280,7 +280,7 @@ QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointercache.put(name, hostInfo); return hostInfo; } @@ -707,7 +707,7 @@ QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *id = -1; // check cache - QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); if (manager && manager->cache.isEnabled()) { QHostInfo info = manager->cache.get(name, valid); if (*valid) { @@ -724,7 +724,7 @@ QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char void qt_qhostinfo_clear_cache() { - QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); if (manager) { manager->clear(); } @@ -732,7 +732,7 @@ void qt_qhostinfo_clear_cache() void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) { - QAbstractHostInfoLookupManger* manager = theHostInfoLookupManager(); + QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); if (manager) { manager->cache.setEnabled(e); } @@ -800,7 +800,7 @@ void QHostInfoCache::clear() cache.clear(); } -QAbstractHostInfoLookupManger* QAbstractHostInfoLookupManger::globalInstance() +QAbstractHostInfoLookupManager* QAbstractHostInfoLookupManager::globalInstance() { return theHostInfoLookupManager(); } diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index ceec04d..bae6efa 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -172,24 +172,24 @@ public: }; -class QAbstractHostInfoLookupManger : public QObject +class QAbstractHostInfoLookupManager : public QObject { Q_OBJECT public: - ~QAbstractHostInfoLookupManger() {} + ~QAbstractHostInfoLookupManager() {} virtual void clear() = 0; QHostInfoCache cache; protected: - QAbstractHostInfoLookupManger() {} - static QAbstractHostInfoLookupManger* globalInstance(); + QAbstractHostInfoLookupManager() {} + static QAbstractHostInfoLookupManager* globalInstance(); }; #ifndef Q_OS_SYMBIAN -class QHostInfoLookupManager : public QAbstractHostInfoLookupManger +class QHostInfoLookupManager : public QAbstractHostInfoLookupManager { Q_OBJECT public: @@ -279,14 +279,14 @@ private: } iState; }; -class QSymbianHostInfoLookupManger : public QAbstractHostInfoLookupManger +class QSymbianHostInfoLookupManager : public QAbstractHostInfoLookupManager { Q_OBJECT public: - QSymbianHostInfoLookupManger(); - ~QSymbianHostInfoLookupManger(); + QSymbianHostInfoLookupManager(); + ~QSymbianHostInfoLookupManager(); - static QSymbianHostInfoLookupManger* globalInstance(); + static QSymbianHostInfoLookupManager* globalInstance(); int id(); void clear(); diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index a38a845..ded2416 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -221,7 +221,7 @@ QSymbianHostResolver::QSymbianHostResolver(const QString &hostName, int identifi QSymbianHostResolver::~QSymbianHostResolver() { #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::~QSymbianHostResolver" << id(); + qDebug() << "QSymbianHostInfoLookupManager::~QSymbianHostResolver" << id(); #endif Cancel(); iHostResolver.Close(); @@ -236,7 +236,7 @@ void QSymbianHostResolver::requestHostLookup() iHostName.toLatin1().constData(), id()); #endif - QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + QSymbianHostInfoLookupManager *manager = QSymbianHostInfoLookupManager::globalInstance(); if (manager->cache.isEnabled()) { //check if name has been put in the cache while this request was queued bool valid; @@ -360,7 +360,7 @@ void QSymbianHostResolver::returnResults() #endif iState = EIdle; - QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + QSymbianHostInfoLookupManager *manager = QSymbianHostInfoLookupManager::globalInstance(); if (manager->cache.isEnabled()) { manager->cache.put(iHostName, iResults); } @@ -376,7 +376,7 @@ TInt QSymbianHostResolver::RunError(TInt aError) QT_TRY { iState = EIdle; - QSymbianHostInfoLookupManger *manager = QSymbianHostInfoLookupManger::globalInstance(); + QSymbianHostInfoLookupManager *manager = QSymbianHostInfoLookupManager::globalInstance(); manager->lookupFinished(this); setError_helper(iResults, aError); @@ -448,19 +448,19 @@ int QSymbianHostResolver::id() return iResults.lookupId(); } -QSymbianHostInfoLookupManger::QSymbianHostInfoLookupManger() +QSymbianHostInfoLookupManager::QSymbianHostInfoLookupManager() { } -QSymbianHostInfoLookupManger::~QSymbianHostInfoLookupManger() +QSymbianHostInfoLookupManager::~QSymbianHostInfoLookupManager() { } -void QSymbianHostInfoLookupManger::clear() +void QSymbianHostInfoLookupManager::clear() { QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::clear" << QThread::currentThreadId(); + qDebug() << "QSymbianHostInfoLookupManager::clear" << QThread::currentThreadId(); #endif //TODO: these aren't deleted because of thread unsafety, but that is a behaviour difference //qDeleteAll(iCurrentLookups); @@ -468,12 +468,12 @@ void QSymbianHostInfoLookupManger::clear() cache.clear(); } -void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) +void QSymbianHostInfoLookupManager::lookupFinished(QSymbianHostResolver *r) { QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::lookupFinished" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); + qDebug() << "QSymbianHostInfoLookupManager::lookupFinished" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // remove finished lookup from array and destroy TInt count = iCurrentLookups.count(); @@ -487,10 +487,10 @@ void QSymbianHostInfoLookupManger::lookupFinished(QSymbianHostResolver *r) runNextLookup(); } -void QSymbianHostInfoLookupManger::runNextLookup() +void QSymbianHostInfoLookupManager::runNextLookup() { #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::runNextLookup" << QThread::currentThreadId() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); + qDebug() << "QSymbianHostInfoLookupManager::runNextLookup" << QThread::currentThreadId() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // check to see if there are any scheduled lookups if (iScheduledLookups.count() > 0) { @@ -503,12 +503,12 @@ void QSymbianHostInfoLookupManger::runNextLookup() } // called from QHostInfo -void QSymbianHostInfoLookupManger::scheduleLookup(QSymbianHostResolver* r) +void QSymbianHostInfoLookupManager::scheduleLookup(QSymbianHostResolver* r) { QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::scheduleLookup" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); + qDebug() << "QSymbianHostInfoLookupManager::scheduleLookup" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // Check to see if we have space on the current lookups pool. if (iCurrentLookups.count() >= KMaxConcurrentLookups) { @@ -527,12 +527,12 @@ void QSymbianHostInfoLookupManger::scheduleLookup(QSymbianHostResolver* r) } } -void QSymbianHostInfoLookupManger::abortLookup(int id) +void QSymbianHostInfoLookupManager::abortLookup(int id) { QMutexLocker locker(&mutex); #if defined(QHOSTINFO_DEBUG) - qDebug() << "QSymbianHostInfoLookupManger::abortLookup" << QThread::currentThreadId() << id << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); + qDebug() << "QSymbianHostInfoLookupManager::abortLookup" << QThread::currentThreadId() << id << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif int i = 0; // Find the aborted lookup by ID. @@ -557,10 +557,10 @@ void QSymbianHostInfoLookupManger::abortLookup(int id) } } -QSymbianHostInfoLookupManger* QSymbianHostInfoLookupManger::globalInstance() +QSymbianHostInfoLookupManager* QSymbianHostInfoLookupManager::globalInstance() { - return static_cast - (QAbstractHostInfoLookupManger::globalInstance()); + return static_cast + (QAbstractHostInfoLookupManager::globalInstance()); } QT_END_NAMESPACE -- cgit v0.12 From a0ca845cd32178d789f4eeff602b283a290842b8 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 4 Apr 2011 18:26:00 +0100 Subject: Thread safety for QHostInfo symbian implementation Each thread needs at least one current request if it has any queued requests, this is to stop the queue stalling. When starting a queued request, start it in the same thread it belongs to When aborting a request from the wrong thread, just detach it (it will complete normally but the slot isn't connected, and then delete itself) Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_p.h | 2 ++ src/network/kernel/qhostinfo_symbian.cpp | 54 ++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index bae6efa..8da0692 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -234,6 +234,7 @@ public: ~QSymbianHostResolver(); void requestHostLookup(); + void abortHostLookup(); int id(); void returnResults(); @@ -301,6 +302,7 @@ public: private: void runNextLookup(); + // this is true for single threaded use, with multiple threads the max is ((number of threads) + KMaxConcurrentLookups - 1) static const int KMaxConcurrentLookups = 5; QList iCurrentLookups; diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index ded2416..dcfc490 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -311,6 +311,23 @@ void QSymbianHostResolver::requestHostLookup() } } +void QSymbianHostResolver::abortHostLookup() +{ + if (resultEmitter.thread() == QThread::currentThread()) { +#ifdef QHOSTINFO_DEBUG + qDebug("QSymbianHostResolver::abortHostLookup - deleting %d", id()); +#endif + //normal case, abort from same thread it was started + delete this; //will cancel outstanding request + } else { +#ifdef QHOSTINFO_DEBUG + qDebug("QSymbianHostResolver::abortHostLookup - detaching %d", id()); +#endif + //abort from different thread, carry on but don't report the results + resultEmitter.disconnect(); + } +} + void QSymbianHostResolver::DoCancel() { #if defined(QHOSTINFO_DEBUG) @@ -462,9 +479,10 @@ void QSymbianHostInfoLookupManager::clear() #if defined(QHOSTINFO_DEBUG) qDebug() << "QSymbianHostInfoLookupManager::clear" << QThread::currentThreadId(); #endif - //TODO: these aren't deleted because of thread unsafety, but that is a behaviour difference - //qDeleteAll(iCurrentLookups); - //qDeleteAll(iScheduledLookups); + foreach (QSymbianHostResolver *hr, iCurrentLookups) + hr->abortHostLookup(); + iCurrentLookups.clear(); + qDeleteAll(iScheduledLookups); cache.clear(); } @@ -493,12 +511,17 @@ void QSymbianHostInfoLookupManager::runNextLookup() qDebug() << "QSymbianHostInfoLookupManager::runNextLookup" << QThread::currentThreadId() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // check to see if there are any scheduled lookups - if (iScheduledLookups.count() > 0) { - // if so, move one to the current lookups and run it - // FIFO - QSymbianHostResolver* hostResolver = iScheduledLookups.takeFirst(); - iCurrentLookups.append(hostResolver); - hostResolver->requestHostLookup(); + for (int i=0; iresultEmitter.thread() == QThread::currentThread()) { + // if so, move one to the current lookups and run it + iCurrentLookups.append(hostResolver); + iScheduledLookups.removeAt(i); + hostResolver->requestHostLookup(); + // if spare capacity, try to start another one + if (iCurrentLookups.count() >= KMaxConcurrentLookups) + break; + } } } @@ -511,7 +534,18 @@ void QSymbianHostInfoLookupManager::scheduleLookup(QSymbianHostResolver* r) qDebug() << "QSymbianHostInfoLookupManager::scheduleLookup" << QThread::currentThreadId() << r->id() << "current" << iCurrentLookups.count() << "queued" << iScheduledLookups.count(); #endif // Check to see if we have space on the current lookups pool. + bool defer = false; if (iCurrentLookups.count() >= KMaxConcurrentLookups) { + // busy, defer unless there are no request in this thread + // at least one active request per thread with queued requests is needed + for (int i=0; i < iCurrentLookups.count();i++) { + if (iCurrentLookups.at(i)->resultEmitter.thread() == QThread::currentThread()) { + defer = true; + break; + } + } + } + if (defer) { // If no, schedule for later. iScheduledLookups.append(r); #if defined(QHOSTINFO_DEBUG) @@ -541,7 +575,7 @@ void QSymbianHostInfoLookupManager::abortLookup(int id) if (id == iCurrentLookups[i]->id()) { QSymbianHostResolver* r = iCurrentLookups.at(i); iCurrentLookups.removeAt(i); - delete r; //cancels via destructor + r->abortHostLookup(); runNextLookup(); return; } -- cgit v0.12 From 4aef1e1dd1ec5ccfdf56d91975185ff96a51701b Mon Sep 17 00:00:00 2001 From: Aaron Tunney Date: Tue, 5 Apr 2011 11:45:24 +0100 Subject: Updating comment in QHostInfo::localDomainName Updating comment to indicate that the feature isn't supported on Symbian. Reviewed-by: Shane Kearns --- 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 dcfc490..40ede54 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -206,7 +206,9 @@ QString QHostInfo::localHostName() QString QHostInfo::localDomainName() { - // TODO - fill with code. + // This concept does not exist on Symbian OS because the device can be on + // multiple networks with multiple "local domain" names. + // For now, return a null string. return QString(); } -- cgit v0.12 From dc474b5d19f66dc3ede087ae6fa8ec6f9245477e Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 5 Apr 2011 15:17:52 +0100 Subject: Add autotests for QHostInfo::abortHostLookup Test calling the abort from the same thread or from a different thread. The different thread is to check thread safety of the API. Reviewed-by: Markus Goetz --- tests/auto/qhostinfo/tst_qhostinfo.cpp | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/auto/qhostinfo/tst_qhostinfo.cpp b/tests/auto/qhostinfo/tst_qhostinfo.cpp index 7b2fc55..0e9319f 100644 --- a/tests/auto/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/qhostinfo/tst_qhostinfo.cpp @@ -134,6 +134,8 @@ private slots: void cache(); + void abortHostLookup(); + void abortHostLookupInDifferentThread(); protected slots: void resultsReady(const QHostInfo &); @@ -583,5 +585,52 @@ void tst_QHostInfo::resultsReady(const QHostInfo &hi) QMetaObject::invokeMethod(&QTestEventLoop::instance(), "exitLoop", Qt::QueuedConnection); } +void tst_QHostInfo::abortHostLookup() +{ + //reset counter + lookupsDoneCounter = 0; + bool valid = false; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("qt.nokia.com", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(!valid); + //it is assumed that the DNS request/response in the backend is slower than it takes to call abort + QHostInfo::abortHostLookup(id); + QTestEventLoop::instance().enterLoop(5); + QCOMPARE(lookupsDoneCounter, 0); +} + +class LookupAborter : public QObject +{ + Q_OBJECT +public slots: + void abort() + { + QHostInfo::abortHostLookup(id); + QThread::currentThread()->quit(); + } +public: + int id; +}; + +void tst_QHostInfo::abortHostLookupInDifferentThread() +{ + //reset counter + lookupsDoneCounter = 0; + bool valid = false; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("qt.nokia.com", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(!valid); + QThread thread; + LookupAborter aborter; + aborter.id = id; + aborter.moveToThread(&thread); + connect(&thread, SIGNAL(started()), &aborter, SLOT(abort())); + //it is assumed that the DNS request/response in the backend is slower than it takes to schedule the thread and call abort + thread.start(); + QVERIFY(thread.wait(5000)); + QTestEventLoop::instance().enterLoop(5); + QCOMPARE(lookupsDoneCounter, 0); +} + QTEST_MAIN(tst_QHostInfo) #include "tst_qhostinfo.moc" -- cgit v0.12 From 3915dd40b967fbf96a53820a8130342280a5b299 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 5 Apr 2011 16:30:19 +0100 Subject: QHostInfo symbian backend finalisation For reverse lookups, don't report errors, instead just return the IP address as a string for the host name (for behavioural compability with the windows and unix backends) Don't sort IP4 addresses before IP6 addresses for the same host. The symbian host resolver internally sorts the list so the usable addresses are returned first. (usable means has a valid route) Task-number: QTBUG-18135 Reviewed-by: Markus Goetz --- src/network/kernel/qhostinfo_symbian.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/network/kernel/qhostinfo_symbian.cpp b/src/network/kernel/qhostinfo_symbian.cpp index 40ede54..2a8de1d 100644 --- a/src/network/kernel/qhostinfo_symbian.cpp +++ b/src/network/kernel/qhostinfo_symbian.cpp @@ -117,11 +117,13 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer() << address); } + results.setAddresses(QList() << address); return results; } @@ -188,8 +190,7 @@ QString QHostInfo::localHostName() RSocketServ socketServ(qt_symbianGetSocketServer()); RHostResolver hostResolver; - // Will return both IPv4 and IPv6 - // TODO: Pass RHostResolver.Open() the global RConnection + // RConnection not required to get the host name int err = hostResolver.Open(socketServ, KAfInet, KProtocolInetUdp); if (err) return QString(); @@ -420,13 +421,7 @@ void QSymbianHostResolver::processNameResult() // Ensure that record is valid (not an alias and with length greater than 0) if (!(iNameResult().iFlags & TNameRecord::EAlias) && !(hostAdd.IsUnspecified())) { - if (iNameResult().iAddr.Family() == KAfInet) { - // IPv4 - prepend - iHostAddresses.prepend(QHostAddress(qt_TDesC2QString(ipAddr))); - } else { - // IPv6 - append - iHostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); - } + iHostAddresses.append(QHostAddress(qt_TDesC2QString(ipAddr))); } iState = EGetByName; @@ -453,11 +448,13 @@ void QSymbianHostResolver::processAddressResult() TInt err = iStatus.Int(); if (err < 0) { - setError_helper(iResults, err); + //For behavioural compatibility with Qt 4.7, don't report errors on reverse lookup, + //return the address as a string (same as unix/windows backends) + iResults.setHostName(iAddress.toString()); } else { iResults.setHostName(qt_TDesC2QString(iNameResult().iName)); - iResults.setAddresses(QList() << iAddress); } + iResults.setAddresses(QList() << iAddress); returnResults(); } @@ -523,6 +520,7 @@ void QSymbianHostInfoLookupManager::runNextLookup() // if spare capacity, try to start another one if (iCurrentLookups.count() >= KMaxConcurrentLookups) break; + i--; //compensate for removeAt } } } -- cgit v0.12 From 76ef8d709b7bb0458153df85f60b39937664811b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 5 Apr 2011 16:37:08 +0100 Subject: QHostInfo autotest fixes related to symbian 1. start default network at start of test (this makes the test faster and more reliable, as the network can be stopped automatically if we don't use a network session) 2. remove unnecessary ifdef from the ipv4 data 3. add new IPv6 test hosts to the ipv6 data 4. extend ipv6 timeout to match the ipv4 timeout 5. check error in LookupThread::run() to avoid test crashing on failure 6. extend timeout for multipleDifferentLookups (uncached DNS is SLOW) 7. enable IPv6 lookups on symbian statically (don't use the broken POSIX functions) Reviewed-by: Markus Goetz --- tests/auto/qhostinfo/tst_qhostinfo.cpp | 49 +++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/tests/auto/qhostinfo/tst_qhostinfo.cpp b/tests/auto/qhostinfo/tst_qhostinfo.cpp index 0e9319f..af0631e 100644 --- a/tests/auto/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/qhostinfo/tst_qhostinfo.cpp @@ -62,6 +62,12 @@ #include #include +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif + #include #include #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) @@ -145,6 +151,11 @@ private: bool lookupDone; int lookupsDoneCounter; QHostInfo lookupResults; +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif }; // Testing get/set functions @@ -185,6 +196,21 @@ tst_QHostInfo::~tst_QHostInfo() void tst_QHostInfo::initTestCase() { +#ifndef QT_NO_BEARERMANAGEMENT + //start the default network + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif + +#ifdef Q_OS_SYMBIAN + ipv6Available = true; + ipv6LookupsAvailable = true; +#else ipv6Available = false; ipv6LookupsAvailable = false; #if !defined(QT_NO_GETADDRINFO) @@ -207,6 +233,7 @@ void tst_QHostInfo::initTestCase() } } #endif +#endif QTcpServer server; if (server.listen(QHostAddress("::1"))) { @@ -240,18 +267,14 @@ void tst_QHostInfo::lookupIPv4_data() QTest::addColumn("addresses"); QTest::addColumn("err"); -#ifdef Q_OS_SYMBIAN // Test server lookup QTest::newRow("lookup_01") << QtNetworkSettings::serverName() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError); - QTest::newRow("literal_ip4") << QtNetworkSettings::serverIP().toString() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError); - QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError); -#else QTest::newRow("empty") << "" << "" << int(QHostInfo::HostNotFound); QTest::newRow("single_ip4") << "lupinella.troll.no" << lupinellaIp << int(QHostInfo::NoError); QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError); QTest::newRow("literal_ip4") << lupinellaIp << lupinellaIp << int(QHostInfo::NoError); -#endif + QTest::newRow("notfound") << "this-name-does-not-exist-hopefully." << "" << int(QHostInfo::HostNotFound); QTest::newRow("idn-ace") << "xn--alqualond-34a.troll.no" << "10.3.3.55" << int(QHostInfo::NoError); @@ -293,8 +316,11 @@ void tst_QHostInfo::lookupIPv6_data() QTest::addColumn("addresses"); QTest::addColumn("err"); - QTest::newRow("ip6") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError); - QTest::newRow("ip6") << "ipv6.google.com" << "2A00:1450:8007:0:0:0:0:63" << int(QHostInfo::NoError); + QTest::newRow("ipv6-net") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError); + QTest::newRow("ipv6-test") << "ipv6-test.dev.troll.no" << "2001:638:a00:2:0:0:0:2" << int(QHostInfo::NoError); + QTest::newRow("dns6-test") << "dns6-test-dev.troll.no" << "2001:470:1f01:115:0:0:0:10" << int(QHostInfo::NoError); + QTest::newRow("multi-dns6") << "multi-dns6-test-dev.troll.no" << "2001:470:1f01:115:0:0:0:11 2001:470:1f01:115:0:0:0:12" << int(QHostInfo::NoError); + QTest::newRow("dns46-test") << "dns46-test-dev.troll.no" << "10.3.4.90 2001:470:1f01:115:0:0:0:13" << int(QHostInfo::NoError); // avoid using real IPv6 addresses here because this will do a DNS query // real addresses are between 2000:: and 3fff:ffff:ffff:ffff:ffff:ffff:ffff @@ -314,7 +340,7 @@ void tst_QHostInfo::lookupIPv6() lookupDone = false; QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(const QHostInfo&))); - QTestEventLoop::instance().enterLoop(3); + QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(lookupDone); @@ -415,6 +441,8 @@ protected: inline void run() { QHostInfo info = QHostInfo::fromName("qt.nokia.com"); + QCOMPARE(info.error(), QHostInfo::NoError); + QVERIFY(info.addresses().count() > 0); QCOMPARE(info.addresses().at(0).toString(), QString("87.238.50.178")); } }; @@ -532,8 +560,9 @@ void tst_QHostInfo::multipleDifferentLookups() QElapsedTimer timer; timer.start(); - while (timer.elapsed() < 10000 && lookupsDoneCounter < repeats*COUNT) { + while (timer.elapsed() < 60000 && lookupsDoneCounter < repeats*COUNT) { QTestEventLoop::instance().enterLoop(2); + //qDebug() << "t:" << timer.elapsed(); } QCOMPARE(lookupsDoneCounter, repeats*COUNT); } @@ -574,7 +603,7 @@ void tst_QHostInfo::cache() QVERIFY(result.addresses().isEmpty()); // the slot should have been called 2 times. - QVERIFY(lookupsDoneCounter == 2); + QCOMPARE(lookupsDoneCounter, 2); } void tst_QHostInfo::resultsReady(const QHostInfo &hi) -- cgit v0.12 From 397e139774eaaee88dc44cd47d296646ec03aed7 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 6 Apr 2011 12:16:36 +0200 Subject: tst_qtcpserver: Add a mapped v4 addr test Reviewed-by: Shane Kearns --- tests/auto/qtcpserver/tst_qtcpserver.cpp | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/auto/qtcpserver/tst_qtcpserver.cpp b/tests/auto/qtcpserver/tst_qtcpserver.cpp index cff2fe5..9cddc00 100644 --- a/tests/auto/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/qtcpserver/tst_qtcpserver.cpp @@ -97,6 +97,7 @@ private slots: void constructing(); void clientServerLoop(); void ipv6Server(); + void ipv6ServerMapped(); void crashTests(); void maxPendingConnections(); void listenError(); @@ -265,6 +266,40 @@ void tst_QTcpServer::ipv6Server() } //---------------------------------------------------------------------------------- +void tst_QTcpServer::ipv6ServerMapped() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + QTcpServer server; + QVERIFY(server.listen(QHostAddress::LocalHost)); + + // let's try the normal case + QTcpSocket client1; + client1.connectToHost("127.0.0.1", server.serverPort()); + QVERIFY(server.waitForNewConnection(5000)); + delete server.nextPendingConnection(); + + // let's try the mapped one in the nice format + QTcpSocket client2; + client2.connectToHost("::ffff:127.0.0.1", server.serverPort()); + QVERIFY(server.waitForNewConnection(5000)); + delete server.nextPendingConnection(); + + // let's try the mapped in hex format + QTcpSocket client3; + client3.connectToHost("::ffff:7F00:0001", server.serverPort()); + QVERIFY(server.waitForNewConnection(5000)); + delete server.nextPendingConnection(); + + // However connecting to the v6 localhost should not work + QTcpSocket client4; + client4.connectToHost("::1", server.serverPort()); + QVERIFY(!server.waitForNewConnection(5000)); +} + +//---------------------------------------------------------------------------------- void tst_QTcpServer::crashTests() { QTcpServer server; -- cgit v0.12 From 31c588cfe42c387aef8c541fe1e6d50e9ff51560 Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Wed, 6 Apr 2011 12:32:36 +0200 Subject: tst_qnetworkreply: skip ioGetFromBuiltinHttp test. Reviewed-by: Markus Goetz --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 11f4fc3..10fce94 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -4265,6 +4265,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp_data() void tst_QNetworkReply::ioGetFromBuiltinHttp() { + QSKIP("Limiting is broken right now, check QTBUG-15065", SkipAll); QFETCH(bool, https); QFETCH(int, bufferSize); -- cgit v0.12 From a951fb79139498774d021759d0466b4b2ff50e68 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 7 Apr 2011 11:25:08 +0100 Subject: QUdpSocket autotest updates 1. Start the default bearer, when Qt is built with bearer management 2. Allow server sockets to have IPv6 any addresses 3. Broadcasting test - broadcast on each valid broadcast address 4. Enable IPv6 tests on symbian 5. writeDatagram test - workaround symbian having a smaller recieve buffer for UDP packets than the maximum packet size it can send. 6. Add QEXPECT_FAIL for some multicast tests on symbian, the OS support for multicast is incomplete. 7. Choke the echo test, as the test server shuts down the echo service for 10 seconds when receiving packets too fast. 8. For manual testing, added the FORCE_SESSION macro to test behaviour of UDP sockets when they have an explicit network session associated Reviewed-by: Markus Goetz --- tests/auto/qudpsocket/tst_qudpsocket.cpp | 191 +++++++++++++++++++++++++++---- 1 file changed, 168 insertions(+), 23 deletions(-) diff --git a/tests/auto/qudpsocket/tst_qudpsocket.cpp b/tests/auto/qudpsocket/tst_qudpsocket.cpp index e6fe068..2c8049f 100644 --- a/tests/auto/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/qudpsocket/tst_qudpsocket.cpp @@ -55,9 +55,15 @@ #include #include "../network-settings.h" +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif + Q_DECLARE_METATYPE(QHostAddress) Q_DECLARE_METATYPE(QNetworkInterface) - +Q_DECLARE_METATYPE(QSharedPointer) //TESTED_CLASS= //TESTED_FILES= @@ -114,6 +120,13 @@ private slots: protected slots: void empty_readyReadSlot(); void empty_connectedSlot(); + +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QSharedPointer networkSession; +#endif }; tst_QUdpSocket::tst_QUdpSocket() @@ -132,6 +145,16 @@ void tst_QUdpSocket::initTestCase_data() QTest::newRow("WithoutProxy") << false << 0; QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy); + +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession = QSharedPointer(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif } void tst_QUdpSocket::init() @@ -156,6 +179,9 @@ void tst_QUdpSocket::cleanup() void tst_QUdpSocket::constructing() { QUdpSocket socket; +#ifdef FORCE_SESSION + socket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(socket.isSequential()); QVERIFY(!socket.isOpen()); @@ -173,6 +199,9 @@ void tst_QUdpSocket::constructing() void tst_QUdpSocket::unconnectedServerAndClientTest() { QUdpSocket serverSocket; +#ifdef FORCE_SESSION + serverSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif qRegisterMetaType("QAbstractSocket::SocketState"); @@ -183,11 +212,14 @@ void tst_QUdpSocket::unconnectedServerAndClientTest() const char *message[] = {"Yo mista", "Yo", "Wassap"}; QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(serverSocket.localAddress() == QHostAddress::Any)) + if (!(serverSocket.localAddress() == QHostAddress::Any || serverSocket.localAddress() == QHostAddress::AnyIPv6)) serverAddress = serverSocket.localAddress(); for (int i = 0; i < 3; ++i) { QUdpSocket clientSocket; +#ifdef FORCE_SESSION + clientSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QCOMPARE(int(clientSocket.writeDatagram(message[i], strlen(message[i]), serverAddress, serverSocket.localPort())), int(strlen(message[i]))); @@ -218,8 +250,21 @@ void tst_QUdpSocket::broadcasting() #endif const char *message[] = {"Yo mista", "", "Yo", "Wassap"}; + QList broadcastAddresses; + foreach (QNetworkInterface iface, QNetworkInterface::allInterfaces()) { + if ((iface.flags() & QNetworkInterface::CanBroadcast) + && iface.flags() & QNetworkInterface::IsUp) { + for (int i=0;i("qint64"); qRegisterMetaType("QAbstractSocket::SocketError"); @@ -475,8 +552,16 @@ void tst_QUdpSocket::writeDatagram() QCOMPARE(*static_cast(bytesspy.at(0).at(0).constData()), qint64(i * 1024)); QCOMPARE(errorspy.count(), 0); - if (!server.waitForReadyRead(5000)) + if (!server.waitForReadyRead(5000)) { +#ifdef Q_OS_SYMBIAN + //symbian receive buffer for datagrams is ~30k, but it can send datagrams up to the maximum 64k... + if (i > 28) { + i = 64; + continue; + } +#endif QSKIP(QString("UDP packet lost at size %1, unable to complete the test.").arg(i * 1024).toLatin1().data(), SkipSingle); + } QCOMPARE(server.pendingDatagramSize(), qint64(i * 1024)); QCOMPARE(server.readDatagram(0, 0), qint64(0)); } @@ -501,14 +586,21 @@ void tst_QUdpSocket::performance() #endif // Q_OS_SYMBIAN QUdpSocket server; +#ifdef FORCE_SESSION + server.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(server.bind(), server.errorString().toLatin1().constData()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.localAddress() == QHostAddress::Any)) + if (!(server.localAddress() == QHostAddress::Any || server.localAddress() == QHostAddress::AnyIPv6)) serverAddress = server.localAddress(); QUdpSocket client; +#ifdef FORCE_SESSION + client.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif client.connectToHost(serverAddress, server.localPort()); + QVERIFY(client.waitForConnected(10000)); QTime stopWatch; stopWatch.start(); @@ -548,8 +640,14 @@ void tst_QUdpSocket::bindMode() } QUdpSocket socket; +#ifdef FORCE_SESSION + socket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(socket.bind(), socket.errorString().toLatin1().constData()); QUdpSocket socket2; +#ifdef FORCE_SESSION + socket2.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(!socket2.bind(socket.localPort())); #if defined(Q_OS_SYMBIAN) if(RProcess().HasCapability(ECapabilityNetworkControl)) { @@ -619,16 +717,12 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer_data() QTest::addColumn("bind"); QTest::addColumn("peerAddress"); QHostAddress localhost(QHostAddress::LocalHost); -#if !defined(Q_OS_SYMBIAN) QHostAddress remote = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(); -#endif QTest::newRow("localhost-unbound") << false << localhost; QTest::newRow("localhost-bound") << true << localhost; -#if !defined(Q_OS_SYMBIAN) QTest::newRow("remote-unbound") << false << remote; QTest::newRow("remote-bound") << true << remote; -#endif } void tst_QUdpSocket::writeDatagramToNonExistingPeer() @@ -639,6 +733,9 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer() quint16 peerPort = 33533 + int(bind); QUdpSocket sUdp; +#ifdef FORCE_SESSION + sUdp.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QSignalSpy sReadyReadSpy(&sUdp, SIGNAL(readyRead())); if (bind) QVERIFY(sUdp.bind()); @@ -651,14 +748,10 @@ void tst_QUdpSocket::writeToNonExistingPeer_data() { QTest::addColumn("peerAddress"); QHostAddress localhost(QHostAddress::LocalHost); -#if !defined(Q_OS_SYMBIAN) QHostAddress remote = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(); -#endif // write (required to be connected) QTest::newRow("localhost") << localhost; -#if !defined(Q_OS_SYMBIAN) QTest::newRow("remote") << remote; -#endif } void tst_QUdpSocket::writeToNonExistingPeer() @@ -669,9 +762,13 @@ void tst_QUdpSocket::writeToNonExistingPeer() qRegisterMetaType("QAbstractSocket::SocketError"); QUdpSocket sConnected; +#ifdef FORCE_SESSION + sConnected.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QSignalSpy sConnectedReadyReadSpy(&sConnected, SIGNAL(readyRead())); QSignalSpy sConnectedErrorSpy(&sConnected, SIGNAL(error(QAbstractSocket::SocketError))); sConnected.connectToHost(peerAddress, peerPort, QIODevice::ReadWrite); + QVERIFY(sConnected.waitForConnected(10000)); // the first write succeeds... QCOMPARE(sConnected.write("", 1), qint64(1)); @@ -845,12 +942,18 @@ void tst_QUdpSocket::zeroLengthDatagram() return; QUdpSocket receiver; +#ifdef FORCE_SESSION + receiver.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(receiver.bind()); QVERIFY(!receiver.waitForReadyRead(100)); QVERIFY(!receiver.hasPendingDatagrams()); QUdpSocket sender; +#ifdef FORCE_SESSION + sender.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QCOMPARE(sender.writeDatagram(QByteArray(), QHostAddress::LocalHost, receiver.localPort()), qint64(0)); QVERIFY(receiver.waitForReadyRead(1000)); @@ -892,6 +995,9 @@ void tst_QUdpSocket::multicastTtlOption() } QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // bind, but ignore the result, we are only interested in initializing the socket (void) udpSocket.bind(bindAddress, 0); udpSocket.setSocketOption(QUdpSocket::MulticastTtlOption, ttl); @@ -931,6 +1037,9 @@ void tst_QUdpSocket::multicastLoopbackOption() } QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // bind, but ignore the result, we are only interested in initializing the socket (void) udpSocket.bind(bindAddress, 0); udpSocket.setSocketOption(QUdpSocket::MulticastLoopbackOption, loopback); @@ -951,6 +1060,9 @@ void tst_QUdpSocket::multicastJoinBeforeBind() QFETCH(QHostAddress, groupAddress); QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // cannot join group before binding QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::joinMulticastGroup() called on a QUdpSocket when not in QUdpSocket::BoundState"); QVERIFY(!udpSocket.joinMulticastGroup(groupAddress)); @@ -972,8 +1084,16 @@ void tst_QUdpSocket::multicastLeaveAfterClose() } QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif +#ifdef Q_OS_SYMBIAN + QVERIFY2(udpSocket.bind(), + qPrintable(udpSocket.errorString())); +#else QVERIFY2(udpSocket.bind(groupAddress, 0), qPrintable(udpSocket.errorString())); +#endif QVERIFY2(udpSocket.joinMulticastGroup(groupAddress), qPrintable(udpSocket.errorString())); udpSocket.close(); @@ -997,6 +1117,9 @@ void tst_QUdpSocket::setMulticastInterface_data() void tst_QUdpSocket::setMulticastInterface() { +#ifdef Q_OS_SYMBIAN + QSKIP("Symbian has no IPV6_MULTICAST_IF equivalent", SkipAll); +#else QFETCH_GLOBAL(bool, setProxy); QFETCH(QNetworkInterface, iface); QFETCH(QHostAddress, address); @@ -1019,6 +1142,7 @@ void tst_QUdpSocket::setMulticastInterface() } else { QVERIFY(!iface2.isValid()); } +#endif } void tst_QUdpSocket::multicast_data() @@ -1058,8 +1182,17 @@ void tst_QUdpSocket::multicast() } QUdpSocket receiver; +#ifdef FORCE_SESSION + receiver.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // bind first, then verify that we can join the multicast group +#ifdef Q_OS_SYMBIAN + if (!setProxy) { + QEXPECT_FAIL("same bind, group ipv4 address", "bind to group address not supported on symbian", Abort); + QEXPECT_FAIL("same bind, group ipv6 address", "bind to group address not supported on symbian", Abort); + } +#endif QVERIFY2(receiver.bind(bindAddress, 0) == bindResult, qPrintable(receiver.errorString())); if (!bindResult) @@ -1077,6 +1210,10 @@ void tst_QUdpSocket::multicast() << QByteArray("cdef"); QUdpSocket sender; +#ifdef FORCE_SESSION + sender.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif + sender.bind(); foreach (const QByteArray &datagram, datagrams) { QCOMPARE(int(sender.writeDatagram(datagram, groupAddress, receiver.localPort())), int(datagram.size())); @@ -1092,6 +1229,9 @@ void tst_QUdpSocket::multicast() receiver.readDatagram(datagram.data(), datagram.size(), 0, 0); receivedDatagrams << datagram; } +#ifdef Q_OS_SYMBIAN + QEXPECT_FAIL("valid bind, group ipv4 address", "IPv4 multicast not supported on symbian", Abort); +#endif QCOMPARE(receivedDatagrams, datagrams); QVERIFY2(receiver.leaveMulticastGroup(groupAddress), qPrintable(receiver.errorString())); @@ -1112,15 +1252,19 @@ void tst_QUdpSocket::echo() QHostAddress remote = info.addresses().first(); QUdpSocket sock; +#ifdef FORCE_SESSION + sock.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif if (connect) { sock.connectToHost(remote, 7); + QVERIFY(sock.waitForConnected(10000)); } else { sock.bind(); } QByteArray out(30, 'x'); QByteArray in; int successes = 0; - for (int i=0;i<20;i++) { + for (int i=0;i<10;i++) { if (connect) { sock.write(out); } else { @@ -1143,8 +1287,9 @@ void tst_QUdpSocket::echo() if (!sock.isValid()) QFAIL(sock.errorString().toLatin1().constData()); qDebug() << "packets in" << successes << "out" << i; + QTest::qWait(50); //choke to avoid triggering flood/DDoS protections on echo service } - QVERIFY(successes >= 18); + QVERIFY(successes >= 9); } QTEST_MAIN(tst_QUdpSocket) -- cgit v0.12 From 847df81a5680fe4d71196d0afe5e68e41ae49700 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 7 Apr 2011 15:10:31 +0100 Subject: Implement support for sockets started before the event loop If there is no event loop when a socket notification is enabled, then invoke the method via a queued connection so that it is run again when the event loop is started. This covers sockets created and having an asynchronous API called before calling QCoreApplication::exec(). Reviewed-by: Markus Goetz --- src/network/socket/qsymbiansocketengine.cpp | 69 +++++++++++------------------ src/network/socket/qsymbiansocketengine_p.h | 2 +- tests/auto/qtcpsocket/tst_qtcpsocket.cpp | 45 ++++++++++++++++++- 3 files changed, 72 insertions(+), 44 deletions(-) diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp index 165316d..f1b2982 100644 --- a/src/network/socket/qsymbiansocketengine.cpp +++ b/src/network/socket/qsymbiansocketengine.cpp @@ -1433,6 +1433,26 @@ void QSymbianSocketEnginePrivate::setError(TInt symbianError) hasSetSocketError = true; } +void QSymbianSocketEngine::startNotifications() +{ + Q_D(QSymbianSocketEngine); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QSymbianSocketEngine::startNotifications" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; +#endif + if (!d->asyncSelect && (d->readNotificationsEnabled || d->writeNotificationsEnabled || d->exceptNotificationsEnabled)) { + if (d->threadData->eventDispatcher) { + d->asyncSelect = q_check_ptr(new QAsyncSelect( + static_cast (d->threadData->eventDispatcher), d->nativeSocket, + this)); + } else { + // call again when event dispatcher has been created + QMetaObject::invokeMethod(this, "startNotifications", Qt::QueuedConnection); + } + } + if (d->asyncSelect) + d->asyncSelect->IssueRequest(); +} + bool QSymbianSocketEngine::isReadNotificationEnabled() const { Q_D(const QSymbianSocketEngine); @@ -1448,13 +1468,7 @@ void QSymbianSocketEngine::setReadNotificationEnabled(bool enable) qDebug() << "QSymbianSocketEngine::setReadNotificationEnabled" << enable << "socket" << d->socketDescriptor; #endif d->readNotificationsEnabled = enable; - if (enable && d->threadData->eventDispatcher && !d->asyncSelect) - d->asyncSelect = q_check_ptr( - new QAsyncSelect(static_cast(d->threadData->eventDispatcher), - d->nativeSocket, this)); - // TODO: what do we do if event dispatcher doesn't exist yet? - if (d->asyncSelect) - d->asyncSelect->IssueRequest(); + startNotifications(); } bool QSymbianSocketEngine::isWriteNotificationEnabled() const @@ -1472,13 +1486,7 @@ void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable) qDebug() << "QSymbianSocketEngine::setWriteNotificationEnabled" << enable << "socket" << d->socketDescriptor; #endif d->writeNotificationsEnabled = enable; - if (enable && d->threadData->eventDispatcher && !d->asyncSelect) - d->asyncSelect = q_check_ptr( - new QAsyncSelect(static_cast(d->threadData->eventDispatcher), - d->nativeSocket, this)); - // TODO: what do we do if event dispatcher doesn't exist yet? - if (d->asyncSelect) - d->asyncSelect->IssueRequest(); + startNotifications(); } bool QSymbianSocketEngine::isExceptionNotificationEnabled() const @@ -1489,7 +1497,6 @@ bool QSymbianSocketEngine::isExceptionNotificationEnabled() const return false; } -// FIXME do we really need this for symbian? void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) { Q_D(QSymbianSocketEngine); @@ -1498,12 +1505,7 @@ void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable) qDebug() << "QSymbianSocketEngine::setExceptionNotificationEnabled" << enable << "socket" << d->socketDescriptor; #endif d->exceptNotificationsEnabled = enable; - if (enable && d->threadData->eventDispatcher && !d->asyncSelect) - d->asyncSelect = q_check_ptr( - new QAsyncSelect(static_cast(d->threadData->eventDispatcher), - d->nativeSocket, this)); - if (d->asyncSelect) - d->asyncSelect->IssueRequest(); + startNotifications(); } bool QSymbianSocketEngine::waitForRead(int msecs, bool *timedOut) @@ -1588,38 +1590,21 @@ 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); + if (ev->type() == QEvent::ThreadChange) { #ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "QSymbianSocketEngine::event"; -#endif - switch (ev->type()) { - case QEvent::ThreadChange: -#ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "ThreadChange" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; + qDebug() << "QSymbianSocketEngine::event - ThreadChange" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; #endif if (d->asyncSelect) { delete d->asyncSelect; d->asyncSelect = 0; - QEvent *postThreadChangeEvent = new QEvent(PostThreadChangeEvent); - QCoreApplication::postEvent(this, postThreadChangeEvent); + // recreate select in new thread (because it is queued, the method is called in the new thread context) + QMetaObject::invokeMethod(this, "startNotifications", Qt::QueuedConnection); } d->selectTimer.Close(); return true; - case PostThreadChangeEvent: -#ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "PostThreadChangeEvent" << d->readNotificationsEnabled << d->writeNotificationsEnabled << d->exceptNotificationsEnabled; -#endif - // recreate select in new thread - d->asyncSelect = q_check_ptr( - new QAsyncSelect(static_cast(d->threadData->eventDispatcher), - d->nativeSocket, this)); - d->asyncSelect->IssueRequest(); - return true; } return QAbstractSocketEngine::event(ev); } diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h index bbe1269..85ab54a 100644 --- a/src/network/socket/qsymbiansocketengine_p.h +++ b/src/network/socket/qsymbiansocketengine_p.h @@ -134,7 +134,7 @@ public: bool event(QEvent* ev); - static const QEvent::Type PostThreadChangeEvent = (QEvent::Type)(QEvent::User + 1); + Q_INVOKABLE void startNotifications(); public Q_SLOTS: // TODO: Why do we do this? This is private Qt implementation stuff anyway, no need for it diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index 6852e29..623e02b 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -106,6 +106,7 @@ Q_DECLARE_METATYPE(QList) //TESTED_FILES= QT_FORWARD_DECLARE_CLASS(QTcpSocket) +QT_FORWARD_DECLARE_CLASS(SocketPair) class tst_QTcpSocket : public QObject { @@ -138,6 +139,7 @@ public slots: void init(); void cleanup(); private slots: + void socketsConstructedBeforeEventLoop(); void constructing(); void setInvalidSocketDescriptor(); void setSocketDescriptor(); @@ -221,6 +223,8 @@ protected slots: void abortiveClose_abortSlot(); void remoteCloseErrorSlot(); void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth); + void earlySocketBytesSent(qint64 bytes); + void earlySocketReadyRead(); private: QByteArray expectedReplyIMAP(); @@ -243,6 +247,10 @@ private: bool gotClosedSignal; int numConnections; static int loopLevel; + + SocketPair *earlyConstructedSockets; + int earlyBytesWrittenCount; + int earlyReadyReadCount; }; enum ProxyTests { @@ -296,8 +304,16 @@ public: tst_QTcpSocket::tst_QTcpSocket() { - Q_SET_DEFAULT_IAP tmpSocket = 0; + + //This code relates to the socketsConstructedBeforeEventLoop test case + earlyConstructedSockets = new SocketPair; + QVERIFY(earlyConstructedSockets->create()); + earlyBytesWrittenCount = 0; + earlyReadyReadCount = 0; + connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead())); + connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64))); + earlyConstructedSockets->endPoints[1]->write("hello work"); } tst_QTcpSocket::~tst_QTcpSocket() @@ -399,6 +415,33 @@ void tst_QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthent //---------------------------------------------------------------------------------- +void tst_QTcpSocket::socketsConstructedBeforeEventLoop() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH_GLOBAL(bool, ssl); + if (setProxy || ssl) + return; + //This test checks that sockets constructed before QCoreApplication::exec() still emit signals + //see construction code in the tst_QTcpSocket constructor + enterLoop(3); + QCOMPARE(earlyBytesWrittenCount, 1); + QCOMPARE(earlyReadyReadCount, 1); + earlyConstructedSockets->endPoints[0]->close(); + earlyConstructedSockets->endPoints[1]->close(); +} + +void tst_QTcpSocket::earlySocketBytesSent(qint64 bytes) +{ + earlyBytesWrittenCount++; +} + +void tst_QTcpSocket::earlySocketReadyRead() +{ + earlyReadyReadCount++; +} + +//---------------------------------------------------------------------------------- + void tst_QTcpSocket::constructing() { QTcpSocket *socket = newSocket(); -- cgit v0.12 From 2cafc79ff4b4521a594031cd1db0229aa594f84e Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 12 Apr 2011 12:51:22 +0200 Subject: Revert "HTTP caching internals: fix logic for PreferNetwork and PreferCache" This reverts commit e5d27e7aeac984e46f3aa8de20160cc00fc63155. Conflicts: tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp --- src/network/access/qnetworkaccesshttpbackend.cpp | 7 +---- .../tst_qabstractnetworkcache.cpp | 33 +++++++++------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index b0ca9e0..9de5d84 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -263,11 +263,6 @@ bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &http httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified)); if (CacheLoadControlAttribute == QNetworkRequest::PreferNetwork) { - // PreferNetwork == send request with "If-None-Match" and "If-Modified-Since" header, - // which will return a 304 Not Modifed if resource has not been changed. - // We might read from cache later, if receiving a 304. - return false; - } else if (CacheLoadControlAttribute == QNetworkRequest::PreferCache) { it = cacheHeaders.findRawHeader("Cache-Control"); if (it != cacheHeaders.rawHeaders.constEnd()) { QHash cacheControl = parseHttpOptionHeader(it->second); @@ -1156,7 +1151,7 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo attributes.insert(QNetworkRequest::HttpStatusCodeAttribute, statusCode); attributes.insert(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); } else { - // this is the server telling us the resource has not changed, keep the attributes intact + // this is a redirection, keep the attributes intact attributes = oldMetaData.attributes(); } metaData.setAttributes(attributes); diff --git a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp index 4a66d4d..da57d1b 100644 --- a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp +++ b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp @@ -156,19 +156,16 @@ void tst_QAbstractNetworkCache::expires_data() // Server sending Expires header, QTest::addColumn("url"); QTest::addColumn("fetchFromCache"); - // httpcachetest_expires304.cgi will send a 304 upon receiving a If-Modified-Since header QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires304.cgi" << AlwaysFalse; - QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires304.cgi" << false; // neither Last-Modified nor ETag given + QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires304.cgi" << true; QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires304.cgi" << AlwaysTrue; - QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_expires304.cgi" << true; // we know the expiration date, so we can read from cache + QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_expires304.cgi" << true; - // httpcachetest_expires500.cgi will send a 500 upon receiving a If-Modified-Since header QTest::newRow("500-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires500.cgi" << AlwaysFalse; - QTest::newRow("500-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires500.cgi" << false; // neither Last-Modified nor ETag given + QTest::newRow("500-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires500.cgi" << true; QTest::newRow("500-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires500.cgi" << AlwaysTrue; - QTest::newRow("500-3") << QNetworkRequest::PreferCache << "httpcachetest_expires500.cgi" << true; // we know the expiration date, so we can read from cache + QTest::newRow("500-3") << QNetworkRequest::PreferCache << "httpcachetest_expires500.cgi" << true; - // httpcachetest_expires200.cgi will always send a 200 header QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_expires200.cgi" << AlwaysFalse; QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_expires200.cgi" << false; QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_expires200.cgi" << AlwaysTrue; @@ -196,17 +193,15 @@ void tst_QAbstractNetworkCache::lastModified_data() QTest::addColumn("url"); QTest::addColumn("fetchFromCache"); - // httpcachetest_lastModified304.cgi will send a 304 upon receiving a If-Modified-Since header QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_lastModified304.cgi" << AlwaysFalse; - QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified304.cgi" << true; // we know the last modified date, so we can send If-Modified-Since and get 304, then we can read from cache + QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified304.cgi" << true; QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_lastModified304.cgi" << AlwaysTrue; - QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified304.cgi" << true; // we know the last modified date, so we can send If-Modified-Since and get 304, then we can read from cache + QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified304.cgi" << true; - // httpcachetest_lastModified200.cgi will always send a 200 header QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_lastModified200.cgi" << AlwaysFalse; - QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified200.cgi" << false; // we won't get a 304 (although sending If-Modified-Since), so we cannot read from cache + QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_lastModified200.cgi" << false; QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_lastModified200.cgi" << AlwaysTrue; - QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified200.cgi" << false; // we won't get a 304 (although sending If-Modified-Since), so we cannot read from cache + QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_lastModified200.cgi" << false; } void tst_QAbstractNetworkCache::lastModified() @@ -231,14 +226,14 @@ void tst_QAbstractNetworkCache::etag_data() QTest::addColumn("fetchFromCache"); QTest::newRow("304-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_etag304.cgi" << AlwaysFalse; - QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag304.cgi" << true; // we will send If-None-Match and get 304 + QTest::newRow("304-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag304.cgi" << true; QTest::newRow("304-2") << QNetworkRequest::AlwaysCache << "httpcachetest_etag304.cgi" << AlwaysTrue; - QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_etag304.cgi" << true; // we don't have expiration information, but will get 304, as with PreferNetwork + QTest::newRow("304-3") << QNetworkRequest::PreferCache << "httpcachetest_etag304.cgi" << true; QTest::newRow("200-0") << QNetworkRequest::AlwaysNetwork << "httpcachetest_etag200.cgi" << AlwaysFalse; - QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag200.cgi" << false; // we will send If-None-Match and get 200 + QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_etag200.cgi" << false; QTest::newRow("200-2") << QNetworkRequest::AlwaysCache << "httpcachetest_etag200.cgi" << AlwaysTrue; - QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_etag200.cgi" << false; // we don't have expiration information, and will get 200, as with PreferNetwork + QTest::newRow("200-3") << QNetworkRequest::PreferCache << "httpcachetest_etag200.cgi" << false; } void tst_QAbstractNetworkCache::etag() @@ -278,8 +273,8 @@ void tst_QAbstractNetworkCache::cacheControl_data() // see QTBUG-7060 //QTest::newRow("nokia-boston") << QNetworkRequest::PreferNetwork << "http://waplabdc.nokia-boston.com/browser/users/venkat/cache/Cache_directives/private_1b.asp" << true; - QTest::newRow("304-2b") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << false; // script always returns 200, so we cannot load from cache - QTest::newRow("304-4b") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true; // we got expiry information + QTest::newRow("304-2b") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true; + QTest::newRow("304-4b") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol200.cgi?private, max-age=1000" << true; } void tst_QAbstractNetworkCache::cacheControl() -- cgit v0.12 From 61e7617f4afdd5cc1956de9ee2c7172ba95956d0 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 12 Apr 2011 12:14:15 +0100 Subject: Fix regression with Qt::AutoConnection Change df9491b302f6404ad2ccc6dc2eb3377176d994c6 optimised auto connections by comparing thread ID rather than comparing TLS addresses. However it was implemented on a branch that didn't have the native symbian threads. So merging the two branches caused a regression without merge conflicts. Reviewed-by: mread --- src/corelib/thread/qthread_symbian.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 1474b36..15e6898 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -113,6 +113,7 @@ QThreadData *QThreadData::current() } data->deref(); } + data->threadId = QThread::currentThreadId(); if (!QCoreApplicationPrivate::theMainThread) QCoreApplicationPrivate::theMainThread = data->thread; } @@ -312,6 +313,7 @@ void *QThreadPrivate::start(void *arg) // attribute of the thread again once the app gains control in run() User::SetCritical(User::EProcessCritical); + data->threadId = QThread::currentThreadId(); set_thread_data(data); { -- cgit v0.12 From 46163663e956b988719563eae18773a2dedd424e Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Tue, 12 Apr 2011 14:48:13 +0200 Subject: Added support for libICU for collation and toLower/toUpper. This patch uses icu to do string collation via QString::localeAwareCompare function and for QString::toLower/toUpper - which is important e.g. for turkish locales where uppercased 'i' is not a latin 'I'. Based on the patch by Harald Fernengel Reviewed-by: Harald Fernengel Reviewed-by: Zeno Albisser --- config.tests/unix/icu/icu.cpp | 54 +++++++++ config.tests/unix/icu/icu.pro | 4 + configure | 34 +++++- src/corelib/tools/qlocale.cpp | 14 +++ src/corelib/tools/qlocale_icu.cpp | 224 +++++++++++++++++++++++++++++++++++++ src/corelib/tools/qstring.cpp | 35 +++++- src/corelib/tools/tools.pri | 5 + tests/auto/qstring/qstring.pro | 2 + tests/auto/qstring/tst_qstring.cpp | 55 +++++++++ 9 files changed, 425 insertions(+), 2 deletions(-) create mode 100644 config.tests/unix/icu/icu.cpp create mode 100644 config.tests/unix/icu/icu.pro create mode 100644 src/corelib/tools/qlocale_icu.cpp diff --git a/config.tests/unix/icu/icu.cpp b/config.tests/unix/icu/icu.cpp new file mode 100644 index 0000000..f03b160 --- /dev/null +++ b/config.tests/unix/icu/icu.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** 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 config.tests 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 + +int main(int, char **) +{ + UErrorCode status = U_ZERO_ERROR; + UCollator *collator = ucol_open("ru_RU", &status); + if (U_FAILURE(status)) + return 0; + ucol_close(collator); + return 0; +} diff --git a/config.tests/unix/icu/icu.pro b/config.tests/unix/icu/icu.pro new file mode 100644 index 0000000..8e58334 --- /dev/null +++ b/config.tests/unix/icu/icu.pro @@ -0,0 +1,4 @@ +SOURCES = icu.cpp +CONFIG -= qt dylib app_bundle +unix:LIBS += -licuuc -licui18n +win32:LIBS += -licuin diff --git a/configure b/configure index 4d25ec2..bf67205 100755 --- a/configure +++ b/configure @@ -832,6 +832,7 @@ CFG_PULSEAUDIO=auto CFG_COREWLAN=auto CFG_ICD=auto CFG_NOPROCESS=no +CFG_ICU=auto # initalize variables used for installation QT_INSTALL_PREFIX= @@ -1040,7 +1041,7 @@ while [ "$#" -gt 0 ]; do VAL=no ;; #Qt style yes options - -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-declarative-debug|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles) + -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-declarative-debug|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu) VAR=`echo $1 | sed "s,^-\(.*\),\1,"` VAL=yes ;; @@ -2376,6 +2377,13 @@ while [ "$#" -gt 0 ]; do QT_CFLAGS_FPU=$VAL fi ;; + icu) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_ICU="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; *) UNKNOWN_OPT=yes ;; @@ -5679,6 +5687,25 @@ if [ "$PLATFORM_X11" = "yes" -o "$PLATFORM_QWS" = "yes" -o "$PLATFORM_QPA" = "ye CFG_ICD=no fi + # auto-detect libicu support + if [ "$CFG_ICU" != "no" ]; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/icu "ICU" $L_FLAGS $I_FLAGS $l_FLAGS; then + [ "$CFG_ICU" = "auto" ] && CFG_ICU=yes + else + if [ "$CFG_ICU" = "auto" ]; then + CFG_ICU=no + elif [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then + # CFG_ICU is "yes" + + echo "The ICU library support cannot be enabled." + echo " Turn on verbose messaging (-v) to $0 to see the final report." + echo " If you believe this message is in error you may use the continue" + echo " switch (-continue) to $0 to continue." + exit 101 + fi + fi + fi + # Auto-detect PulseAudio support if [ "$CFG_PULSEAUDIO" != "no" ]; then if [ -n "$PKG_CONFIG" ]; then @@ -7337,6 +7364,10 @@ if [ "$CFG_ICD" = "yes" ]; then QT_CONFIG="$QT_CONFIG icd" fi +if [ "$CFG_ICU" = "yes" ]; then + QT_CONFIG="$QT_CONFIG icu" +fi + # # Some Qt modules are too advanced in C++ for some old compilers # Detect here the platforms where they are known to work. @@ -8727,6 +8758,7 @@ if [ "$PLATFORM_MAC" = "yes" ]; then echo "CoreWlan support ....... $CFG_COREWLAN" fi echo "ICD support ............ $CFG_ICD" +echo "libICU support ......... $CFG_ICU" echo [ "$CFG_PTMALLOC" != "no" ] && echo "Use ptmalloc ........... $CFG_PTMALLOC" diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index d986b9b..5c4085a 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -86,6 +86,10 @@ static QLocalePrivate *system_lp = 0; Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate) #endif +#ifdef QT_USE_ICU +extern bool qt_initIcu(const QString &localeName); +#endif + /****************************************************************************** ** Helpers for accessing Qt locale database */ @@ -520,6 +524,12 @@ void QLocalePrivate::updateSystemPrivate() res = sys_locale->query(QSystemLocale::PositiveSign, QVariant()); if (!res.isNull()) system_lp->m_plus = res.toString().at(0).unicode(); + +#ifdef QT_USE_ICU + if (!default_lp) + qt_initIcu(system_lp->bcp47Name()); +#endif + } #endif @@ -879,6 +889,10 @@ void QLocale::setDefault(const QLocale &locale) { default_lp = locale.d(); default_number_options = locale.numberOptions(); + +#ifdef QT_USE_ICU + qt_initIcu(locale.bcp47Name()); +#endif } /*! diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/tools/qlocale_icu.cpp new file mode 100644 index 0000000..0e283dd --- /dev/null +++ b/src/corelib/tools/qlocale_icu.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** 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 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 "qglobal.h" +#include "qlibrary.h" +#include "qdebug.h" + +#include "unicode/uversion.h" +#include "unicode/ucol.h" + +QT_BEGIN_NAMESPACE + +typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status); +typedef void (*Ptr_ucol_close)(UCollator *coll); +typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength); +typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode); + +static Ptr_ucol_open ptr_ucol_open = 0; +static Ptr_ucol_strcoll ptr_ucol_strcoll = 0; +static Ptr_ucol_close ptr_ucol_close = 0; +static Ptr_u_strToCase ptr_u_strToUpper = 0; +static Ptr_u_strToCase ptr_u_strToLower = 0; + +enum LibLoadStatus +{ + ErrorLoading = -1, + NotLoaded = 0, + Loaded = 1 +}; + +static LibLoadStatus status = NotLoaded; + +static UCollator *icuCollator = 0; + +#define STRINGIFY2(x) #x +#define STRINGIFY(x) STRINGIFY2(x) + +bool qt_initIcu(const QString &localeString) +{ + if (status == ErrorLoading) + return false; + + if (status == NotLoaded) { + + // resolve libicui18n + QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT)); + if (!lib.load()) { + qWarning() << "Unable to load library icui18n" << lib.errorString(); + status = ErrorLoading; + return false; + } + + ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open"); + ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close"); + ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll"); + + if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) { + // try again with decorated symbol names + ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX)); + ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX)); + ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX)); + } + + if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) { + ptr_ucol_open = 0; + ptr_ucol_close = 0; + ptr_ucol_strcoll = 0; + + qWarning("Unable to find symbols in icui18n"); + status = ErrorLoading; + return false; + } + + // resolve libicuuc + QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT)); + if (!ucLib.load()) { + qWarning() << "Unable to load library icuuc" << ucLib.errorString(); + status = ErrorLoading; + return false; + } + + ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper"); + ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower"); + + if (!ptr_u_strToUpper || !ptr_u_strToLower) { + ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX)); + ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX)); + } + + if (!ptr_u_strToUpper || !ptr_u_strToLower) { + ptr_u_strToUpper = 0; + ptr_u_strToLower = 0; + + qWarning("Unable to find symbols in icuuc"); + status = ErrorLoading; + return false; + } + + // success :) + status = Loaded; + } + + if (icuCollator) { + ptr_ucol_close(icuCollator); + icuCollator = 0; + } + + UErrorCode icuStatus = U_ZERO_ERROR; + icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus); + + if (!icuCollator) { + qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus); + return false; + } + + return true; +} + +bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result) +{ + Q_ASSERT(result); + Q_ASSERT(source); + Q_ASSERT(target); + + if (!icuCollator) + return false; + + *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast(source), int32_t(sourceLength), + reinterpret_cast(target), int32_t(targetLength)); + + return true; +} + +// caseFunc can either be u_strToUpper or u_strToLower +static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc) +{ + Q_ASSERT(out); + + if (!icuCollator) + return false; + + QString result(str.size(), Qt::Uninitialized); + + UErrorCode status = U_ZERO_ERROR; + + int32_t size = caseFunc(reinterpret_cast(result.data()), result.size(), + reinterpret_cast(str.constData()), str.size(), + locale.bcp47Name().toLatin1().constData(), &status); + + if (U_FAILURE(status)) + return false; + + if (size < result.size()) { + result.resize(size); + } else if (size > result.size()) { + // the resulting string is larger than our source string + result.resize(size); + + status = U_ZERO_ERROR; + size = caseFunc(reinterpret_cast(result.data()), result.size(), + reinterpret_cast(str.constData()), str.size(), + locale.bcp47Name().toLatin1().constData(), &status); + + if (U_FAILURE(status)) + return false; + + // if the sizes don't match now, we give up. + if (size != result.size()) + return false; + } + + *out = result; + return true; +} + +bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale) +{ + return qt_u_strToCase(str, out, locale, ptr_u_strToUpper); +} + +bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale) +{ + return qt_u_strToCase(str, out, locale, ptr_u_strToLower); +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b7272ec..5493ba9 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -106,6 +106,14 @@ QTextCodec *QString::codecForCStrings; static QHash *asciiCache = 0; #endif +#ifdef QT_USE_ICU +// qlocale_icu.cpp +extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result); +extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale); +extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale); +#endif + + // internal int qFindString(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); @@ -431,7 +439,6 @@ const QString::Null QString::null = { }; \ingroup shared \ingroup string-processing - QString stores a string of 16-bit \l{QChar}s, where each QChar corresponds one Unicode 4.0 character. (Unicode characters with code values above 65535 are stored using surrogate pairs, @@ -4829,6 +4836,14 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, TPtrC p2 = TPtrC16(reinterpret_cast(data2), length2); return p1.CompareC(p2); #elif defined(Q_OS_UNIX) +# if defined(QT_USE_ICU) + int res; + if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) { + if (res == 0) + res = ucstrcmp(data1, length1, data2, length2); + return res; + } // else fall through +# endif // declared in int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2)); if (delta == 0) @@ -4964,6 +4979,15 @@ QString QString::toLower() const if (!d->size) return *this; +#ifdef QT_USE_ICU + { + QString result; + if (qt_u_strToLower(*this, &result, QLocale())) + return result; + // else fall through and use Qt's toUpper + } +#endif + const ushort *e = d->data + d->size; // this avoids one out of bounds check in the loop @@ -5055,6 +5079,15 @@ QString QString::toUpper() const if (!d->size) return *this; +#ifdef QT_USE_ICU + { + QString result; + if (qt_u_strToUpper(*this, &result, QLocale())) + return result; + // else fall through and use Qt's toUpper + } +#endif + const ushort *e = d->data + d->size; // this avoids one out of bounds check in the loop diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 849dc63..0c2cf16 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -97,6 +97,11 @@ else:SOURCES += tools/qelapsedtimer_generic.cpp contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri) else:include($$PWD/../../3rdparty/zlib_dependency.pri) +contains(QT_CONFIG,icu) { + SOURCES += tools/qlocale_icu.cpp + DEFINES += QT_USE_ICU +} + DEFINES += HB_EXPORT=Q_CORE_EXPORT INCLUDEPATH += ../3rdparty/harfbuzz/src HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h diff --git a/tests/auto/qstring/qstring.pro b/tests/auto/qstring/qstring.pro index e980042..1c123ad 100644 --- a/tests/auto/qstring/qstring.pro +++ b/tests/auto/qstring/qstring.pro @@ -7,3 +7,5 @@ QT = core DEFINES += QT_NO_CAST_TO_ASCII CONFIG += parallel_test + +contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp index 25e16fe..3d80e80 100644 --- a/tests/auto/qstring/tst_qstring.cpp +++ b/tests/auto/qstring/tst_qstring.cpp @@ -222,6 +222,8 @@ private slots: void task262677remove(); void QTBUG10404_compareRef(); void QTBUG9281_arg_locale(); + + void toUpperLower_icu(); }; typedef QList IntList; @@ -1603,6 +1605,11 @@ void tst_QString::toUpper() QCOMPARE( lower.toUpper(), upper); +#ifdef QT_USE_ICU + // test doesn't work with ICU support, since QChar is unaware of any locale + QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); + QVERIFY(false); +#else for (int i = 0; i < 65536; ++i) { QString str(1, QChar(i)); QString upper = str.toUpper(); @@ -1610,6 +1617,7 @@ void tst_QString::toUpper() if (upper.length() == 1) QVERIFY(upper == QString(1, QChar(i).toUpper())); } +#endif } void tst_QString::toLower() @@ -1641,6 +1649,11 @@ void tst_QString::toLower() upper += QChar(QChar::lowSurrogate(0x10400)); QCOMPARE( upper.toLower(), lower); +#ifdef QT_USE_ICU + // test doesn't work with ICU support, since QChar is unaware of any locale + QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); + QVERIFY(false); +#else for (int i = 0; i < 65536; ++i) { QString str(1, QChar(i)); QString lower = str.toLower(); @@ -1648,6 +1661,7 @@ void tst_QString::toLower() if (lower.length() == 1) QVERIFY(str.toLower() == QString(1, QChar(i).toLower())); } +#endif } void tst_QString::trimmed() @@ -4352,6 +4366,8 @@ void tst_QString::localeAwareCompare() #elif defined (Q_WS_MAC) QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll); +#elif defined(QT_USE_ICU) + QLocale::setDefault(QLocale(locale)); #else if (!locale.isEmpty()) { const char *newLocale = setlocale(LC_ALL, locale.toLatin1()); @@ -4363,6 +4379,11 @@ void tst_QString::localeAwareCompare() } #endif +#ifdef QT_USE_ICU + // ### for c1, ICU disagrees with libc on how to compare + QEXPECT_FAIL("c1", "ICU disagrees with test", Abort); +#endif + int testres = QString::localeAwareCompare(s1, s2); if (result < 0) { QVERIFY(testres < 0); @@ -5065,6 +5086,40 @@ void tst_QString::QTBUG9281_arg_locale() QLocale::setDefault(QLocale::C); } +void tst_QString::toUpperLower_icu() +{ +#ifndef QT_USE_ICU + QSKIP("Qt was built without ICU support", SkipAll); +#endif + + QString s = QString::fromLatin1("i"); + + QCOMPARE(s.toUpper(), QString::fromLatin1("I")); + QCOMPARE(s.toLower(), QString::fromLatin1("i")); + + QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); + + // turkish locale has a capital I with a dot (U+0130, utf8 c4b0) + + QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0")); + QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s); + + // nothing should happen here + QCOMPARE(s.toLower(), s); + QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I")); + + // U+0131, utf8 c4b1 is the lower-case i without a dot + QString sup = QString::fromUtf8("\xc4\xb1"); + + QCOMPARE(sup.toUpper(), QString::fromLatin1("I")); + QCOMPARE(QString::fromLatin1("I").toLower(), sup); + + // nothing should happen here + QCOMPARE(sup.toLower(), sup); + QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i")); + + // the cleanup function will restore the default locale +} QTEST_APPLESS_MAIN(tst_QString) -- cgit v0.12 From 6f1efe75dac53377b92d779818b43a34add92f02 Mon Sep 17 00:00:00 2001 From: mread Date: Tue, 12 Apr 2011 15:07:11 +0100 Subject: Applying the QTBUG-17986 fix to Symbian This change takes the QTBUG-17986 fix, which deletes QThreadData for adopted threads that have created QEventLoops, and applies it to qthread_symbian.cpp, which didn't exist at the time of the original fix. One complication is that Symbian uses a separate thread to monitor adopted thread lifetime, as there is no API to intercept thread exit to have cleanup code run within the context of the thread. However the cleanup for the thread involes deleting active objects that were created in the adopted thread, not the monitor thread. If these active objects are completed but not run, their cancellation could deadlock. In particular the wake up active object in the event dispatcher is typically in this state. We deal with it by detecting the situation and re-completing/cancelling the active object in the adopted thread monitor thread, which prevents deadlock and allows correct operation of the monitor thread. It is possible for this problem to affect other active objects owned by the event dispatcher. They symptom would be that finished signals from adopted threads are not sent, or they arrive much later than they should. Task-number: QTBUG-18622 Reviewed-by: Shane Kearns --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 10 ++++++++++ src/corelib/kernel/qeventdispatcher_symbian_p.h | 3 +++ src/corelib/thread/qthread_symbian.cpp | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 79f2596..471028e 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -194,6 +194,7 @@ void QActiveObject::reactivateAndComplete() QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher) : QActiveObject(WAKE_UP_PRIORITY, dispatcher) { + m_hostThreadId = RThread().Id(); CActiveScheduler::Add(this); iStatus = KRequestPending; SetActive(); @@ -209,6 +210,15 @@ void QWakeUpActiveObject::DoCancel() if (iStatus.Int() == KRequestPending) { TRequestStatus *status = &iStatus; QEventDispatcherSymbian::RequestComplete(status, KErrNone); + } else if (IsActive() && m_hostThreadId != RThread().Id()) { + // This is being cancelled in the adopted monitor thread, which can happen if an adopted thread with + // an event loop has exited. The event loop creates an event dispatcher with this active object, which may be complete but not run on exit. + // We force a cancellation in this thread, because a) the object cannot be deleted while active and b) without a cancellation + // the thread semaphore will be one count down. + // It is possible for this problem to affect other active objects. They symptom would be that finished signals + // from adopted threads are not sent, or they arrive much later than they should. + TRequestStatus *status = &iStatus; + User::RequestComplete(status, KErrNone); } } diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index e07d475..6e04bb1 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -110,6 +110,9 @@ public: protected: void DoCancel(); void RunL(); + +private: + TThreadId m_hostThreadId; }; struct SymbianTimerInfo : public QSharedData diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 15e6898..5d8b5cb 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -113,6 +113,7 @@ QThreadData *QThreadData::current() } data->deref(); } + data->isAdopted = true; data->threadId = QThread::currentThreadId(); if (!QCoreApplicationPrivate::theMainThread) QCoreApplicationPrivate::theMainThread = data->thread; @@ -257,6 +258,13 @@ QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0; void QCAdoptedThreadMonitor::RunL() { + if (data->isAdopted) { + QThread *thread = data->thread; + Q_ASSERT(thread); + QThreadPrivate *thread_p = static_cast(QObjectPrivate::get(thread)); + Q_ASSERT(!thread_p->finished); + thread_p->finish(thread); + } data->deref(); QCAddAdoptedThread::threadDied(); delete this; -- cgit v0.12 From 2e7e8a2b805b868eade36cc44fa14bf8ca2f8c2f Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Thu, 14 Apr 2011 11:04:10 +0200 Subject: QNativeWifiEngine: Fix problem with wifi polling on Windows On some Windows machines the wifi detection in QNativeWifiEngine::available does not work as WlanOpenHandle still succeed altough there is no WLAN card. So instead we can detect this using the WlanEnumInterfaces in requestUpdate() instead. Task-number: QTBUG-17219 Reviewed-by: Xizhi Zhu --- src/plugins/bearer/nativewifi/qnativewifiengine.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp index 16c2239..d5beeff 100644 --- a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp +++ b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp @@ -501,6 +501,11 @@ void QNativeWifiEngine::requestUpdate() return; } + if (interfaceList->dwNumberOfItems == 0) { + local_WlanFreeMemory(interfaceList); + return; + } + bool requested = false; for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { result = local_WlanScan(handle, &interfaceList->InterfaceInfo[i].InterfaceGuid, 0, 0, 0); -- cgit v0.12 From 78d47f520b2c4acdf782d39311063f5d44376913 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 14 Apr 2011 13:08:53 +0200 Subject: QLocale: Fixed double to currency string conversion on Mac. This also fixes the autotest failure on mac with macDefaultLocale test. Reviewed-by: trustme --- src/corelib/tools/qlocale_mac.mm | 2 +- tests/auto/qlocale/tst_qlocale.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm index 29d9a53..52005e0 100644 --- a/src/corelib/tools/qlocale_mac.mm +++ b/src/corelib/tools/qlocale_mac.mm @@ -318,7 +318,7 @@ static QString macFormatCurrency(const QSystemLocale::CurrencyToStringArgument & break; } case QVariant::Double: { - double v = arg.value.toInt(); + double v = arg.value.toDouble(); value = CFNumberCreate(NULL, kCFNumberDoubleType, &v); break; } diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index cabf12e..2b7eaae 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -1130,10 +1130,10 @@ void tst_QLocale::macDefaultLocale() const QString timeString = locale.toString(QTime(1,2,3), QLocale::LongFormat); QVERIFY(timeString.contains(QString("1:02:03"))); - QCOMPARE(locale.toCurrencyString(qulonglong(1234)), QString("$1,234")); - QCOMPARE(locale.toCurrencyString(qlonglong(-1234)), QString("$-1,234")); + QCOMPARE(locale.toCurrencyString(qulonglong(1234)), QString("$1,234.00")); + QCOMPARE(locale.toCurrencyString(qlonglong(-1234)), QString("($1,234.00)")); QCOMPARE(locale.toCurrencyString(double(1234.56)), QString("$1,234.56")); - QCOMPARE(locale.toCurrencyString(double(-1234.56)), QString("$-1,234.56")); + QCOMPARE(locale.toCurrencyString(double(-1234.56)), QString("($1,234.56)")); // Depending on the configured time zone, the time string might not // contain a GMT specifier. (Sometimes it just names the zone, like "CEST") -- cgit v0.12 From ba172a10765bb2a5474155675485848cb730e625 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Thu, 14 Apr 2011 11:24:05 +0200 Subject: HTTP+SSL: use default SSL configuration, and avoid setting it explctly do not use a null configuration, but a default configuration in QNetworkRequest by default. In addition, setting an SSL configuration explicitly will cause the on-demand loading of root certs to be disabled (because it could be that the user has set the CA certificates explicitly). Reviewed-by: Markus Goetz --- src/network/access/qhttpthreaddelegate.cpp | 2 +- src/network/access/qnetworkrequest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 7a17a7f..8084078 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -267,7 +267,7 @@ void QHttpThreadDelegate::startRequest() #endif #ifndef QT_NO_OPENSSL // Set the QSslConfiguration from this QNetworkRequest. - if (ssl) { + if (ssl && incomingSslConfiguration != QSslConfiguration::defaultConfiguration()) { httpConnection->setSslConfiguration(incomingSslConfiguration); } #endif diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 665ee28..338969a 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -524,7 +524,7 @@ void QNetworkRequest::setAttribute(Attribute code, const QVariant &value) QSslConfiguration QNetworkRequest::sslConfiguration() const { if (!d->sslConfiguration) - d->sslConfiguration = new QSslConfiguration; + d->sslConfiguration = new QSslConfiguration(QSslConfiguration::defaultConfiguration()); return *d->sslConfiguration; } -- cgit v0.12 From 56c0278fd5035d358340724c2ed9969d5332b313 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 15 Apr 2011 10:19:55 +0200 Subject: QSslConfiguration: fix equals operator --- src/network/ssl/qsslconfiguration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index c8dbaed..70d7dd8 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -164,7 +164,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const d->privateKey == other.d->privateKey && d->sessionCipher == other.d->sessionCipher && d->ciphers == other.d->ciphers && - d->caCertificates == d->caCertificates && + d->caCertificates == other.d->caCertificates && d->protocol == other.d->protocol && d->peerVerifyMode == other.d->peerVerifyMode && d->peerVerifyDepth == other.d->peerVerifyDepth; -- cgit v0.12 From b0a01659ee47752d905b2c30bf9027ced8b1f86c Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Mon, 18 Apr 2011 14:47:55 +0200 Subject: Revert "QNativeWifiEngine: Fix problem with wifi polling on Windows" This reverts commit 2e7e8a2b805b868eade36cc44fa14bf8ca2f8c2f. This broke the QNetworkconfigurationManager auto tests. Reviewed-by: Peter Hartmann --- src/plugins/bearer/nativewifi/qnativewifiengine.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp index d5beeff..16c2239 100644 --- a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp +++ b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp @@ -501,11 +501,6 @@ void QNativeWifiEngine::requestUpdate() return; } - if (interfaceList->dwNumberOfItems == 0) { - local_WlanFreeMemory(interfaceList); - return; - } - bool requested = false; for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { result = local_WlanScan(handle, &interfaceList->InterfaceInfo[i].InterfaceGuid, 0, 0, 0); -- cgit v0.12 From 8bc3b7cc5d7ee52962e06a1d4fdbbfb439cfa416 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 19 Apr 2011 12:15:21 +0100 Subject: Fix qfile autotest hanging in CI system The test machine is configured to pop up dialogs in case of CRT assertion failures. The CRT has a debug assert whenever an invalid file handle is used, while the test is expecting to get the EBADF return code. Due to some behaviour change in windows 7 (maybe SP1), we need to call _CrtSetReportMode in addition to setting an error handler. Reviewed-By: mread --- tests/auto/qfile/tst_qfile.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index 79539c9..688a92d 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -3294,13 +3294,18 @@ public: static void ignore_invalid_parameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {} AutoIgnoreInvalidParameter() { - old = _set_invalid_parameter_handler(ignore_invalid_parameter); + oldHandler = _set_invalid_parameter_handler(ignore_invalid_parameter); + //also disable the abort/retry/ignore popup + oldReportMode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); } ~AutoIgnoreInvalidParameter() { - _set_invalid_parameter_handler(old); + //restore previous settings + _set_invalid_parameter_handler(oldHandler); + _CrtSetReportMode(_CRT_ASSERT, oldReportMode); } - _invalid_parameter_handler old; + _invalid_parameter_handler oldHandler; + int oldReportMode; #endif }; -- cgit v0.12 From 5888b7d01c05c03bc06a6672a4a8be30bc4192f5 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 19 Apr 2011 14:37:05 +0100 Subject: Fix compile error with QT_NO_OPENSSL --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 146d2f3..f509cea 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -93,7 +93,9 @@ Q_DECLARE_METATYPE(QNetworkReply::NetworkError) Q_DECLARE_METATYPE(QBuffer*) Q_DECLARE_METATYPE(QHttpMultiPart *) Q_DECLARE_METATYPE(QList) // for multiparts +#ifndef QT_NO_OPENSSL Q_DECLARE_METATYPE(QSslConfiguration) +#endif class QNetworkReplyPtr: public QSharedPointer { -- cgit v0.12 From 7a9ed6a1983e318bfb14f0b2db41b3a4e1415529 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 19 Apr 2011 11:38:06 +0200 Subject: QNetworkCookie: do not access date string out of bounds --- src/network/access/qnetworkcookie.cpp | 2 +- tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index c2a6925..52eb345 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -737,7 +737,7 @@ static QDateTime parseDateString(const QByteArray &dateString) // 4 digit Year if (isNum && year == -1 - && dateString.length() >= at + 3) { + && dateString.length() > at + 3) { if (isNumber(dateString[at + 1]) && isNumber(dateString[at + 2]) && isNumber(dateString[at + 3])) { diff --git a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp index 91dfe47..e0c477b 100644 --- a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp +++ b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp @@ -707,6 +707,7 @@ void tst_QNetworkCookie::parseMultipleCookies_data() cookie.setDomain("!@#$%^&*();:."); // the ';' is actually problematic, because it is a separator list = QList(); QTest::newRow("domain-non-alpha-numeric") << "NonAlphNumDomName=NonAlphNumDomValue; domain=!@#$%^&*()" << list; + QTest::newRow("expiration-3digit1") << "a=b; expires=123" << list; // used to ASSERT } void tst_QNetworkCookie::parseMultipleCookies() -- cgit v0.12