diff options
Diffstat (limited to 'src/network')
22 files changed, 632 insertions, 53 deletions
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index 67df526..e31621c 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -97,6 +97,43 @@ QT_BEGIN_NAMESPACE /*! Create a new QNetworkCookie object, initializing the cookie name + and its value to empty QByteArray + + A cookie is only valid if it has a name. However, the value is + opaque to the application and being empty may have significance to + the remote server. +*/ +QNetworkCookie::QNetworkCookie() + : d(new QNetworkCookiePrivate) +{ + qRegisterMetaType<QNetworkCookie>(); + qRegisterMetaType<QList<QNetworkCookie> >(); + + d->name = QByteArray(); + d->value = QByteArray(); +} + +/*! + Create a new QNetworkCookie object, initializing the cookie name + to \a name and its value to empty QByteArray. + + A cookie is only valid if it has a name. However, the value is + opaque to the application and being empty may have significance to + the remote server. +*/ +QNetworkCookie::QNetworkCookie( const QByteArray &name ) + : d(new QNetworkCookiePrivate) +{ + qRegisterMetaType<QNetworkCookie>(); + qRegisterMetaType<QList<QNetworkCookie> >(); + + d->name = name; + d->value = QByteArray(); +} + + +/*! + Create a new QNetworkCookie object, initializing the cookie name to \a name and its value to \a value. A cookie is only valid if it has a name. However, the value is diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h index e8dfab0..9112635 100644 --- a/src/network/access/qnetworkcookie.h +++ b/src/network/access/qnetworkcookie.h @@ -67,7 +67,9 @@ public: Full }; - QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray()); + QNetworkCookie(); + QNetworkCookie(const QByteArray &name ); + QNetworkCookie(const QByteArray &name, const QByteArray &value ); QNetworkCookie(const QNetworkCookie &other); ~QNetworkCookie(); QNetworkCookie &operator=(const QNetworkCookie &other); diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 56b793d..4f9ea52 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -238,6 +238,18 @@ public: }; /*! + Constructs a QNetworkRequest object with empty QUrl. + + \sa url(), setUrl() +*/ +QNetworkRequest::QNetworkRequest() + : d(new QNetworkRequestPrivate) +{ + d->url = QUrl(); +} + + +/*! Constructs a QNetworkRequest object with \a url as the URL to be requested. diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 6f34bce..4c4159d 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -86,7 +86,9 @@ public: AlwaysCache }; - explicit QNetworkRequest(const QUrl &url = QUrl()); + + explicit QNetworkRequest(); + explicit QNetworkRequest(const QUrl &url); QNetworkRequest(const QNetworkRequest &other); ~QNetworkRequest(); QNetworkRequest &operator=(const QNetworkRequest &other); diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 8aa6ff4..bf07aab 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -20,7 +20,8 @@ SOURCES += kernel/qauthenticator.cpp \ kernel/qnetworkproxy.cpp \ kernel/qnetworkinterface.cpp -unix:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp +symbian: SOURCES += kernel/qhostinfo_unix.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 mac:LIBS+= -framework SystemConfiguration diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index f987520..3271deb 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -148,7 +148,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) +#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) && !defined (Q_OS_SYMBIAN) sockaddr_in sa4; #ifndef QT_NO_IPV6 sockaddr_in6 sa6; diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp index 670745b..a339388 100644 --- a/src/network/kernel/qnetworkinterface.cpp +++ b/src/network/kernel/qnetworkinterface.cpp @@ -604,8 +604,13 @@ QDebug operator<<(QDebug debug, const QNetworkInterface &networkInterface) << ", hardware address = " << networkInterface.hardwareAddress() << ", flags = "; flagsDebug(debug, networkInterface.flags()); +#if defined(Q_CC_RVCT) + // RVCT gets confused with << networkInterface.addressEntries(), reason unknown. + debug.nospace() << ")\n"; +#else debug.nospace() << ", entries = " << networkInterface.addressEntries() << ")\n"; +#endif return debug.space(); } #endif diff --git a/src/network/kernel/qnetworkinterface_symbian.cpp b/src/network/kernel/qnetworkinterface_symbian.cpp new file mode 100644 index 0000000..82c673f --- /dev/null +++ b/src/network/kernel/qnetworkinterface_symbian.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +//#define QNETWORKINTERFACE_DEBUG + +//#include "qset.h" +#include "qnetworkinterface.h" +#include "qnetworkinterface_p.h" +//#include <private/qnativesocketengine_p.h> +//#include "qalgorithms.h" + + +#ifndef QT_NO_NETWORKINTERFACE + +#include <in_sock.h> +#include <in_iface.h> +#include <es_sock.h> + +//#include <sys/types.h> +//#include <sys/socket.h> +//#include <errno.h> +//#include <net/if.h> +//#include <qplatformdefs.h> + +QT_BEGIN_NAMESPACE + + +static QNetworkInterface::InterfaceFlags convertFlags( const TSoInetInterfaceInfo& aInfo ) +{ + QNetworkInterface::InterfaceFlags flags = 0; + flags |= (aInfo.iState == EIfUp) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0); + // We do not have separate flag for running in Symbian OS + flags |= (aInfo.iState == EIfUp) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0); + flags |= (aInfo.iFeatures&KIfCanBroadcast) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0); + flags |= (aInfo.iFeatures&KIfIsLoopback) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0); + flags |= (aInfo.iFeatures&KIfIsPointToPoint) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0); + flags |= (aInfo.iFeatures&KIfCanMulticast) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0); + return flags; +} + +QString qstringFromDesc( const TDesC& aData ) +{ + return QString::fromUtf16(aData.Ptr(), aData.Length()); +} + +static QList<QNetworkInterfacePrivate *> interfaceListing() +{ + TInt err( KErrNone ); + QList<QNetworkInterfacePrivate *> 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")); + if( err ) + { + socketServ.Close(); + return interfaces; + } + + // Ask socket to start enumerating interfaces + err = socket.SetOpt( KSoInetEnumInterfaces, KSolInetIfCtrl ); + if( err ) + { + socket.Close(); + socketServ.Close(); + return interfaces; + } + + int ifindex = 0; + TPckgBuf<TSoInetInterfaceInfo> 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() ) + { + TName address; + QNetworkAddressEntry entry; + QNetworkInterfacePrivate *iface = 0; + + iface = new QNetworkInterfacePrivate; + iface->index = ifindex++; + interfaces << iface; + iface->name = qstringFromDesc( info.iName ); + iface->flags = convertFlags( info ); + + if( /*info.iFeatures&KIfHasHardwareAddr &&*/ info.iHwAddr.Family() != KAFUnspec ) + { + for ( TInt i = sizeof(SSockAddr); i < sizeof(SSockAddr) + info.iHwAddr.GetUserLen(); i++ ) + { + address.AppendNumFixedWidth(info.iHwAddr[i], EHex, 2); + if( ( i + 1) < sizeof(SSockAddr) + info.iHwAddr.GetUserLen() ) + address.Append( _L(":") ); + } + address.UpperCase(); + iface->hardwareAddress = qstringFromDesc( address ); + } + + // Get the address of the interface + info.iAddress.Output(address); + entry.setIp( QHostAddress( qstringFromDesc( address ) ) ); + + // Get the interface netmask + // TODO: For some reason netmask is always 0.0.0.0 + //info.iNetMask.Output(address); + //entry.setNetmask( QHostAddress( qstringFromDesc( address ) ) ); + + // Workaround: Let Symbian determine netmask based on IP address class + // TODO: works only for IPv4 + TInetAddr netmask; + netmask.NetMask( info.iAddress ); + netmask.Output(address); + entry.setNetmask( QHostAddress( qstringFromDesc( 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( qstringFromDesc( address ) ) ); + + // Workaround: Let Symbian determine broadcast address based on IP address + // TODO: works only for IPv4 + TInetAddr broadcast; + broadcast.NetBroadcast( info.iAddress ); + broadcast.Output(address); + entry.setBroadcast( QHostAddress( qstringFromDesc( address ) ) ); + } + + // Add new entry to interface address entries + iface->addressEntries << entry; + +#if defined(QNETWORKINTERFACE_DEBUG) + 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\ + hwaddress = %s", + iface->name.toLatin1().constData(), + iface->flags & QNetworkInterface::IsUp, iface->flags & QNetworkInterface::IsRunning, iface->flags & QNetworkInterface::CanBroadcast, + iface->flags & QNetworkInterface::IsLoopBack, iface->flags & QNetworkInterface::IsPointToPoint, iface->flags & QNetworkInterface::CanMulticast, + entry.ip().toString().toLatin1().constData(), entry.netmask().toString().toLatin1().constData(), entry.broadcast().toString().toLatin1().constData(), + iface->hardwareAddress.toLatin1().constData()); +#endif + } + } + socket.Close(); + socketServ.Close(); + return interfaces; +} + +QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan() +{ + return interfaceListing(); +} + +QT_END_NAMESPACE + +#endif // QT_NO_NETWORKINTERFACE diff --git a/src/network/network.pro b/src/network/network.pro index d476b56..59cffd0 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -3,6 +3,13 @@ TARGET = QtNetwork QPRO_PWD = $$PWD DEFINES += QT_BUILD_NETWORK_LIB QT_NO_USING_NAMESPACE +#DEFINES += QLOCALSERVER_DEBUG QLOCALSOCKET_DEBUG +#DEFINES += QNETWORKDISKCACHE_DEBUG +#DEFINES += QSSLSOCKET_DEBUG +#DEFINES += QHOSTINFO_DEBUG +#DEFINES += QABSTRACTSOCKET_DEBUG QNATIVESOCKETENGINE_DEBUG +#DEFINES += QTCPSOCKETENGINE_DEBUG QTCPSOCKET_DEBUG QTCPSERVER_DEBUG QSSLSOCKET_DEBUG +#DEFINES += QUDPSOCKET_DEBUG QUDPSERVER_DEBUG QT = core win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x64000000 @@ -15,3 +22,10 @@ include(socket/socket.pri) include(ssl/ssl.pri) QMAKE_LIBS += $$QMAKE_LIBS_NETWORK + + +symbian { + TARGET.UID3=0x2001B2DE + LIBS += -lesock -linsock +} + diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index f9750f2..8ae247c 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -991,6 +991,7 @@ void QAbstractSocketPrivate::_q_connectToNextAddress() // Wait for a write notification that will eventually call // _q_testConnection(). socketEngine->setWriteNotificationEnabled(true); + socketEngine->setExceptionNotificationEnabled(true); break; } while (state != QAbstractSocket::ConnectedState); } @@ -1049,8 +1050,10 @@ void QAbstractSocketPrivate::_q_abortConnectionAttempt() #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_abortConnectionAttempt() (timed out)"); #endif - if (socketEngine) + if (socketEngine) { socketEngine->setWriteNotificationEnabled(false); + socketEngine->setExceptionNotificationEnabled(false); + } connectTimer->stop(); if (addresses.isEmpty()) { diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index e7d2252..d3ccb69 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -106,6 +106,24 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) ::memcpy(addr.sun_path, fullServerName.toLatin1().data(), fullServerName.toLatin1().size() + 1); +#ifdef Q_OS_SYMBIAN + // In SYMBIAN OS it can currently happen that accept is called twice, + // once from waitForNewConnection and once via QSocketNotfier activity + // + // As an workaround, we set the socket to non blocking so possible + // subsequent call to accept will not block in any case + // + // This change can be removed once more generic fix to select thread + // syncronization problem is implemented. + int flags = fcntl(listenSocket, F_GETFL, 0); + if (-1 == flags + || -1 == (fcntl(listenSocket, F_SETFL, flags | O_NONBLOCK))) { + setError(QLatin1String("QLocalServer::listen")); + closeServer(); + return false; + } +#endif + // bind if(-1 == qBind(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) { setError(QLatin1String("QLocalServer::listen")); diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index 38643f1..2471043 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -282,7 +282,7 @@ void QLocalSocketPrivate::_q_connectToSocket() } ::memcpy(name.sun_path, connectingPathName.toLatin1().data(), connectingPathName.toLatin1().size() + 1); - if (-1 == qConnect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { + if (-1 == qConnect(connectingSocket, (struct sockaddr *)&name, sizeof(name)) && errno != EISCONN) { QString function = QLatin1String("QLocalSocket::connectToServer"); switch (errno) { @@ -300,6 +300,7 @@ void QLocalSocketPrivate::_q_connectToSocket() case ETIMEDOUT: errorOccurred(QLocalSocket::SocketTimeoutError, function); break; + case EINPROGRESS: case EAGAIN: // Try again later, all of the sockets listening are full if (!delayConnect) { @@ -514,9 +515,9 @@ bool QLocalSocket::waitForConnected(int msec) if (state() != ConnectingState) return (state() == ConnectedState); - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(d->connectingSocket, &readfds); + fd_set fds; + FD_ZERO(&fds); + FD_SET(d->connectingSocket, &fds); timeval timeout; timeout.tv_sec = msec / 1000; @@ -532,7 +533,14 @@ bool QLocalSocket::waitForConnected(int msec) timer.start(); while (state() == ConnectingState && (-1 == msec || timer.elapsed() < msec)) { - result = ::select(d->connectingSocket + 1, &readfds, 0, 0, &timeout); +#ifdef Q_OS_SYMBIAN + // On Symbian, ready-to-write is signaled when non-blocking socket + // connect is finised. Is ready-to-read really used on other + // UNIX paltforms when using non-blocking AF_UNIX socket? + result = ::select(d->connectingSocket + 1, 0, &fds, 0, &timeout); +#else + result = ::select(d->connectingSocket + 1, &fds, 0, 0, &timeout); +#endif if (-1 == result && errno != EINTR) { d->errorOccurred( QLocalSocket::UnknownSocketError, QLatin1String("QLocalSocket::waitForConnected")); diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index b25b887..6b2e194 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -381,11 +381,13 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb return false; } + // 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"); - } + } // Set the send and receive buffer sizes to a magic size, found // most optimal for our platforms. @@ -1086,10 +1088,13 @@ protected: bool QExceptionNotifier::event(QEvent *e) { if (e->type() == QEvent::SockAct) { - engine->exceptionNotification(); + if (engine->state() == QAbstractSocket::ConnectingState) + engine->connectionNotification(); + else + engine->exceptionNotification(); return true; } - return QSocketNotifier::event(e); + return QSocketNotifier::event(e); } void QNativeSocketEngine::setReadNotificationEnabled(bool enable) diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 3366f2d..515ad84 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -52,15 +52,22 @@ // // We mean it. // - #include "QtNetwork/qhostaddress.h" #include "private/qabstractsocketengine_p.h" #ifndef Q_OS_WIN #include "qplatformdefs.h" +#else +#include <Winsock2.h> // sockaddr_storage, sockaddr_in +#endif + +#ifdef Q_OS_SYMBIAN +#include <private/qeventdispatcher_symbian_p.h> +#include<unistd.h> #endif QT_BEGIN_NAMESPACE + #ifndef Q_OS_WIN // Almost always the same. If not, specify in qplatformdefs.h. #if !defined(QT_SOCKOPTLEN_T) @@ -76,14 +83,144 @@ static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *a // UnixWare 7 redefines listen -> _listen static inline int qt_socket_listen(int s, int backlog) -{ return ::listen(s, backlog); } +{ + return ::listen(s, backlog); +} #if defined(listen) # undef listen #endif +static inline int qt_socket_connect(int s, const struct sockaddr * addrptr, socklen_t namelen) +{ + return ::connect(s, addrptr, namelen); +} +#if defined(connect) +# undef connect +#endif + +static inline int qt_socket_bind(int s, const struct sockaddr * addrptr, socklen_t namelen) +{ + return ::bind(s, addrptr, namelen); +} +#if defined(bind) +# undef bind +#endif + +static inline int qt_socket_write(int socket, const char *data, qint64 len) +{ + return ::write(socket, data, len); +} +#if defined(write) +# undef write +#endif + +static inline int qt_socket_read(int socket, char *data, qint64 len) +{ + return ::read(socket, data, len); +} +#if defined(read) +# undef read +#endif + +static inline int qt_socket_recv(int socket, void *data, size_t length, int flags) +{ + return ::recv(socket, data, length, flags); +} +#if defined(recv) +# undef recv +#endif + +static inline int qt_socket_recvfrom(int socket, void *data, size_t length, + int flags, struct sockaddr *address, + socklen_t *address_length) +{ + return ::recvfrom(socket, data, length, flags, address, address_length); +} +#if defined(recvfrom) +# undef recvfrom +#endif + +static inline int qt_socket_sendto(int socket, const void *data, size_t length, + int flags, const struct sockaddr *dest_addr, + socklen_t dest_length) +{ + return ::sendto(socket, data, length, flags, dest_addr, dest_length); +} +#if defined(sendto) +# undef sendto +#endif +static inline int qt_socket_close(int socket) +{ + return ::close(socket); +} +#if defined(close) +# undef close +#endif + +static inline int qt_socket_fcntl(int socket, int command, int option) +{ + return ::fcntl(socket, command, option); +} +#if defined(fcntl) +# undef fcntl +#endif + +static inline int qt_socket_ioctl(int socket, int command, char *option) +{ + return ::ioctl(socket, command, option); +} +#if defined(ioctl) +# undef ioctl +#endif + +static inline int qt_socket_getsockname(int socket, struct sockaddr *address, socklen_t *address_len) +{ + return ::getsockname(socket, address, address_len); +} +#if defined(getsockname) +# undef getsockname +#endif + +static inline int qt_socket_getpeername(int socket, struct sockaddr *address, socklen_t *address_len) +{ + return ::getpeername(socket, address, address_len); +} +#if defined(getpeername) +# undef getpeername +#endif + +static inline int qt_socket_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +{ + return ::select(nfds, readfds, writefds, exceptfds, timeout); +} + +#if defined(select) +# undef select +#endif + +static inline int qt_socket_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen) +{ + return ::getsockopt(socket, level, optname, optval, optlen); +} + +#if defined(getsockopt) +# undef getsockopt +#endif + +static inline int qt_socket_setsockopt(int socket, int level, int optname, void *optval, socklen_t optlen) +{ + return ::setsockopt(socket, level, optname, optval, optlen); +} + +#if defined(setsockopt) +# undef setsockopt +#endif + // UnixWare 7 redefines socket -> _socket static inline int qt_socket_socket(int domain, int type, int protocol) -{ return ::socket(domain, type, protocol); } +{ + return ::socket(domain, type, protocol); +} #if defined(socket) # undef socket #endif @@ -177,6 +314,12 @@ public: int socketDescriptor; +#if !defined(QT_NO_IPV6) + struct sockaddr_storage aa; +#else + struct sockaddr_in aa; +#endif + QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; #ifdef Q_OS_WIN diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index cc372a6..a3f62db 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ //#define QNATIVESOCKETENGINE_DEBUG - #include "qnativesocketengine_p.h" #include "qiodevice.h" #include "qhostaddress.h" @@ -59,6 +58,10 @@ #include <arpa/inet.h> #endif +#ifdef Q_OS_SYMBIAN +#include <private/qeventdispatcher_symbian_p.h> +#endif + #if defined QNATIVESOCKETENGINE_DEBUG #include <qstring.h> #include <ctype.h> @@ -100,6 +103,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) 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)) { @@ -108,6 +112,10 @@ static void qt_ignore_sigpipe() 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 } /* @@ -127,7 +135,7 @@ static inline void qt_socket_getPortAndAddress(struct sockaddr *sa, quint16 *por *addr = tmpAddress; #ifndef QT_NO_IPV6IFNAME char scopeid[IFNAMSIZ]; - if (::if_indextoname(sa6->sin6_scope_id, scopeid) > 0) { + if (::if_indextoname(sa6->sin6_scope_id, scopeid)) { addr->setScopeId(QLatin1String(scopeid)); } else #endif @@ -189,7 +197,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc } // Ensure that the socket is closed on exec*(). - ::fcntl(socket, F_SETFD, FD_CLOEXEC); + qt_socket_fcntl(socket, F_SETFD, FD_CLOEXEC); + socketDescriptor = socket; return true; } @@ -227,8 +236,9 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co int v = -1; QT_SOCKOPTLEN_T len = sizeof(v); - if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1) + if (qt_socket_getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1) return v; + return -1; } @@ -255,14 +265,14 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt break; case QNativeSocketEngine::NonBlockingSocketOption: { // Make the socket nonblocking. - int flags = ::fcntl(socketDescriptor, F_GETFL, 0); + int flags = qt_socket_fcntl(socketDescriptor, F_GETFL, 0); if (flags == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed"); #endif return false; } - if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { + if (qt_socket_fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed"); #endif @@ -272,7 +282,9 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return true; } case QNativeSocketEngine::AddressReusable: -#ifdef SO_REUSEPORT +#ifdef Q_OS_SYMBIAN + n = SO_REUSEADDR; +#elif SO_REUSEPORT n = SO_REUSEPORT; #else n = SO_REUSEADDR; @@ -285,11 +297,16 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt break; } - return ::setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0; + return qt_socket_setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0; + } bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) { +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor); +#endif + struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; @@ -328,7 +345,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 // unreachable } - int connectResult = QT_SOCKET_CONNECT(socketDescriptor, sockAddrPtr, sockAddrSize); + int connectResult = qt_socket_connect(socketDescriptor, sockAddrPtr, sockAddrSize); + if (connectResult == -1) { switch (errno) { case EISCONN: @@ -431,7 +449,8 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 // unreachable } - int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize); + int bindResult = qt_socket_bind(socketDescriptor, sockAddrPtr, sockAddrSize); + if (bindResult < 0) { switch(errno) { case EADDRINUSE: @@ -499,8 +518,15 @@ int QNativeSocketEnginePrivate::nativeAccept() #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor); #endif - // Ensure that the socket is closed on exec*() - ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC); + + //check if we have vaild descriptor at all + if(acceptedDescriptor > 0) { + // Ensure that the socket is closed on exec*() + qt_socket_fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC); + } else { + qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0"); + } + return acceptedDescriptor; } @@ -540,7 +566,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const ssize_t readBytes; do { char c; - readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, storagePtr, &storageSize); + readBytes = qt_socket_recvfrom(socketDescriptor, &c, 1, MSG_PEEK, storagePtr, &storageSize); } while (readBytes == -1 && errno == EINTR); // If there's no error, or if our buffer was too small, there must be a @@ -554,16 +580,25 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const return result; } +#ifdef Q_OS_SYMBIAN +qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const +{ + size_t nbytes = 0; + qt_socket_ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes); + return qint64(nbytes-28); +} +#else qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const { QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192); - ssize_t recvResult = -1; + ssize_t recvResult = -1; + for (;;) { // the data written to udpMessagePeekBuffer is discarded, so // this function is still reentrant although it might not look // so. - recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(), - udpMessagePeekBuffer.size(), MSG_PEEK); + recvResult = qt_socket_recv(socketDescriptor, udpMessagePeekBuffer.data(), + udpMessagePeekBuffer.size(), MSG_PEEK); if (recvResult == -1 && errno == EINTR) continue; @@ -572,14 +607,14 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const udpMessagePeekBuffer.resize(udpMessagePeekBuffer.size() * 2); } - + #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %i", recvResult); #endif return qint64(recvResult); } - +#endif qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { @@ -595,7 +630,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS ssize_t recvFromResult = 0; do { char c; - recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, + recvFromResult = qt_socket_recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, 0, (struct sockaddr *)&aa, &sz); } while (recvFromResult == -1 && errno == EINTR); @@ -646,10 +681,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l // ignore the SIGPIPE signal qt_ignore_sigpipe(); - ssize_t sentBytes; do { - sentBytes = ::sendto(socketDescriptor, data, len, + sentBytes = qt_socket_sendto(socketDescriptor, data, len, 0, sockAddrPtr, sockAddrSize); } while (sentBytes == -1 && errno == EINTR); @@ -692,7 +726,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() // Determine local address memset(&sa, 0, sizeof(sa)); - if (::getsockname(socketDescriptor, sockAddrPtr, &sockAddrSize) == 0) { + if (qt_socket_getsockname(socketDescriptor, sockAddrPtr, &sockAddrSize) == 0) { qt_socket_getPortAndAddress(sockAddrPtr, &localPort, &localAddress); // Determine protocol family @@ -716,13 +750,13 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() } // Determine the remote address - if (!::getpeername(socketDescriptor, sockAddrPtr, &sockAddrSize)) + if (!qt_socket_getpeername(socketDescriptor, sockAddrPtr, &sockAddrSize)) qt_socket_getPortAndAddress(sockAddrPtr, &peerPort, &peerAddress); // Determine the socket type (UDP/TCP) int value = 0; QT_SOCKOPTLEN_T valueSize = sizeof(int); - if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) { + if (qt_socket_getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) { if (value == SOCK_STREAM) socketType = QAbstractSocket::TcpSocket; else if (value == SOCK_DGRAM) @@ -753,7 +787,7 @@ void QNativeSocketEnginePrivate::nativeClose() #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEngine::nativeClose()"); #endif - ::close(socketDescriptor); + qt_socket_close(socketDescriptor); } qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) @@ -767,7 +801,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) // of an interrupting signal. ssize_t writtenBytes; do { - writtenBytes = ::write(socketDescriptor, data, len); + writtenBytes = qt_socket_write(socketDescriptor, data, len); } while (writtenBytes < 0 && errno == EINTR); if (writtenBytes < 0) { @@ -809,7 +843,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) ssize_t r = 0; do { - r = ::read(socketDescriptor, data, maxSize); + r = qt_socket_read(socketDescriptor, data, maxSize); } while (r == -1 && errno == EINTR); if (r < 0) { @@ -827,6 +861,9 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) case EIO: setError(QAbstractSocket::NetworkError, ReadErrorString); break; +#ifdef Q_OS_SYMBIAN + case EPIPE: +#endif case ECONNRESET: r = 0; break; @@ -854,18 +891,48 @@ 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 fdexec; + FD_ZERO(&fdexec); + FD_SET(socketDescriptor, &fdexec); +#endif + QTime timer; timer.start(); int retval; do { if (selectForRead) - retval = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); +#ifndef Q_OS_SYMBIAN + retval = qt_socket_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); +#else + retval = qt_socket_select(socketDescriptor + 1, &fds, 0, &fdexec, timeout < 0 ? 0 : &tv); +#endif else - retval = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); +#ifndef Q_OS_SYMBIAN + retval = qt_socket_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); +#else + retval = qt_socket_select(socketDescriptor + 1, 0, &fds, &fdexec, 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, &fdexec); + } + if(selectForExec) { + qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected expectfds ready in fd %d", + selectForRead, retval, errno, socketDescriptor); + } +#endif - if (retval != -1 || errno != EINTR) + if (retval != -1 || errno != EINTR) { break; + } if (timeout > 0) { // recalculate the timeout @@ -896,6 +963,12 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c FD_ZERO(&fdwrite); if (checkWrite) FD_SET(socketDescriptor, &fdwrite); + +#ifdef Q_OS_SYMBIAN + fd_set fdexec; + FD_ZERO(&fdexec); + FD_SET(socketDescriptor, &fdexec); +#endif struct timeval tv; tv.tv_sec = timeout / 1000; @@ -906,9 +979,33 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c int ret; do { - ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); - if (ret != -1 || errno != EINTR) +#ifndef Q_OS_SYMBIAN + ret = qt_socket_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); +#else + ret = qt_socket_select(socketDescriptor + 1, &fdread, &fdwrite, &fdexec, 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, &fdexec); + } + if(selectForExec) { + qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d", + checkRead, checkWrite, ret, errno, socketDescriptor); + if (checkRead) + FD_SET(socketDescriptor, &fdread); + if (checkWrite) + FD_SET(socketDescriptor, &fdwrite); + + if ((ret == -1) && ( errno == ECONNREFUSED || errno == EPIPE )) + ret = 1; + + } +#endif + if (ret != -1 || errno != EINTR) { break; + } if (timeout > 0) { // recalculate the timeout @@ -925,9 +1022,9 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c } while (true); if (ret <= 0) return ret; - *selectForRead = FD_ISSET(socketDescriptor, &fdread); *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite); + return ret; } diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index c41e32d..b6b0e89 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -59,7 +59,11 @@ QT_BEGIN_NAMESPACE +#ifdef Q_OS_SYMBIAN +static const int MaxWriteBufferSize = 4*1024; +#else static const int MaxWriteBufferSize = 128*1024; +#endif //#define QSOCKS5SOCKETLAYER_DEBUG diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 820404d..e46cb4c 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -91,6 +91,13 @@ This enum describes the different flags you can pass to modify the behavior of QUdpSocket::bind(). + + \note On Symbian OS bind flags behaviour depends on process capabilties. + If process has NetworkControl capability, the bind attempt with + ReuseAddressHint will always succeed even the address and port is already + bound by another socket with any flags. If process does not have + NetworkControl capability, the bind attempt to address and port already + bound by another socket will always fail. \value ShareAddress Allow other services to bind to the same address and port. This is useful when multiple processes share @@ -346,6 +353,9 @@ qint64 QUdpSocket::pendingDatagramSize() const as even if they are sent successfully, they are likely to be fragmented by the IP layer before arriving at their final destination. + + \warning In S60 5.0 and earlier versions, the writeDatagram return + value is not reliable for large datagrams. \warning Calling this function on a connected UDP socket may result in an error and no packet being sent. If you are using a @@ -365,6 +375,16 @@ 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) { diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index b1fe64a..dad43d2 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -42,5 +42,3 @@ wince*: { DEFINES += QT_LOCALSOCKET_TCP } - - diff --git a/src/network/ssl/qsslerror.cpp b/src/network/ssl/qsslerror.cpp index daa6533..3096fee 100644 --- a/src/network/ssl/qsslerror.cpp +++ b/src/network/ssl/qsslerror.cpp @@ -110,6 +110,23 @@ public: \sa QSslCertificate */ + +// RVCT compiler in debug build does not like about default values in const- +// So as an workaround we define all constructor overloads here explicitly +QSslError::QSslError() + : d(new QSslErrorPrivate) +{ + d->error = QSslError::NoError; + d->certificate = QSslCertificate(); +} + +QSslError::QSslError(SslError error) + : d(new QSslErrorPrivate) +{ + d->error = error; + d->certificate = QSslCertificate(); +} + QSslError::QSslError(SslError error, const QSslCertificate &certificate) : d(new QSslErrorPrivate) { diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index c120215..50cc142 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -86,8 +86,14 @@ public: UnspecifiedError = -1 }; - QSslError(SslError error = NoError, const QSslCertificate &certificate = QSslCertificate()); + // RVCT compiler in debug build does not like about default values in const- + // So as an workaround we define all constructor overloads here explicitly + QSslError(); + QSslError(SslError error); + QSslError(SslError error, const QSslCertificate &certificate); + QSslError(const QSslError &other); + ~QSslError(); QSslError &operator=(const QSslError &other); bool operator==(const QSslError &other) const; diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index b3be42a..968fdc0 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -77,6 +77,10 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/x509_vfy.h> +#ifdef Q_OS_SYMBIAN +#include <openssl/dsa.h> +#include <openssl/rsa.h> +#endif QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 196e19d..5427370 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -1,6 +1,16 @@ # OpenSSL support; compile in QSslSocket. contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { - include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri) + + +symbian { + TRY_INCLUDEPATHS = $${EPOCROOT}epoc32/include $${EPOCROOT}epoc32/include/stdapis $${EPOCROOT}epoc32/include/stdapis/sys $$OS_LAYER_LIBC_SYSTEMINCLUDE + for(p, TRY_INCLUDEPATHS) { + pp = $$join(p, "", "", "/openssl") + exists($$pp):INCLUDEPATH *= $$pp + } +} else { + include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri) +} HEADERS += ssl/qssl.h \ ssl/qsslcertificate.h \ |