diff options
Diffstat (limited to 'src/network/socket')
-rw-r--r-- | src/network/socket/qabstractsocket.cpp | 3 | ||||
-rw-r--r-- | src/network/socket/qlocalserver.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qlocalserver_unix.cpp | 18 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket_unix.cpp | 21 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine.cpp | 11 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_p.h | 138 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 173 | ||||
-rw-r--r-- | src/network/socket/qsocks5socketengine.cpp | 8 | ||||
-rw-r--r-- | src/network/socket/qtcpserver.cpp | 7 | ||||
-rw-r--r-- | src/network/socket/qudpsocket.cpp | 20 | ||||
-rw-r--r-- | src/network/socket/socket.pri | 2 |
11 files changed, 364 insertions, 41 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index c8ddce0..035d5b6 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1067,8 +1067,9 @@ void QAbstractSocketPrivate::_q_abortConnectionAttempt() #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_abortConnectionAttempt() (timed out)"); #endif - if (socketEngine) + if (socketEngine) { socketEngine->setWriteNotificationEnabled(false); + } connectTimer->stop(); if (addresses.isEmpty()) { diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index 1a50dc4..7bb0b01 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -274,6 +274,10 @@ QLocalSocket *QLocalServer::nextPendingConnection() if (d->pendingConnections.isEmpty()) return 0; QLocalSocket *nextSocket = d->pendingConnections.dequeue(); +#ifdef Q_OS_SYMBIAN + if(!d->socketNotifier) + return nextSocket; +#endif #ifndef QT_LOCALSOCKET_TCP if (d->pendingConnections.size() <= d->maxPendingConnections) #ifndef Q_OS_WIN diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 3df6b6a..14a0c78 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -111,6 +111,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 == QT_SOCKET_BIND(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 08d94ef..835b922 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -242,7 +242,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) QLatin1String("QLocalSocket::connectToServer")); return; } - +#ifndef Q_OS_SYMBIAN // set non blocking so we can try to connect and it wont wait int flags = fcntl(d->connectingSocket, F_GETFL, 0); if (-1 == flags @@ -251,6 +251,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) QLatin1String("QLocalSocket::connectToServer")); return; } +#endif // _q_connectToSocket does the actual connecting d->connectingName = name; @@ -305,10 +306,11 @@ 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) { - delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write); + delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write, q); q->connect(delayConnect, SIGNAL(activated(int)), q, SLOT(_q_connectToSocket())); } if (!connectTimer) { @@ -519,9 +521,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; @@ -537,7 +539,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 aa70b0c..666c86e 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 24dc344..0a5c19d 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -52,7 +52,6 @@ // // We mean it. // - #include "QtNetwork/qhostaddress.h" #include "private/qabstractsocketengine_p.h" #ifndef Q_OS_WIN @@ -61,8 +60,139 @@ # include <winsock2.h> #endif +#ifdef Q_OS_SYMBIAN +#include <private/qeventdispatcher_symbian_p.h> +#include<unistd.h> +#endif + QT_BEGIN_NAMESPACE +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 + // Use our own defines and structs which we know are correct # define QT_SS_MAXSIZE 128 # define QT_SS_ALIGNSIZE (sizeof(qint64)) @@ -183,6 +313,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 6f9ee1a..7584357 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 "private/qnet_unix_p.h" #include "qiodevice.h" @@ -60,12 +59,21 @@ #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> #endif +#ifdef Q_OS_SYMBIAN // ### TODO: Are these headers right? +#include <sys/socket.h> +#include <netinet/in.h> +#else #include <netinet/tcp.h> +#endif QT_BEGIN_NAMESPACE @@ -103,6 +111,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)) { @@ -111,6 +120,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 } /* @@ -129,7 +142,7 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po *addr = tmpAddress; #ifndef QT_NO_IPV6IFNAME char scopeid[IFNAMSIZ]; - if (::if_indextoname(s->a6.sin6_scope_id, scopeid) > 0) { + if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) { addr->setScopeId(QLatin1String(scopeid)); } else #endif @@ -190,7 +203,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; } @@ -237,8 +251,9 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co int v = -1; QT_SOCKOPTLEN_T len = sizeof(v); - if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) + if (qt_socket_getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) return v; + return -1; } @@ -268,14 +283,14 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::NonBlockingSocketOption: { // Make the socket nonblocking. #if !defined(Q_OS_VXWORKS) - 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 @@ -293,7 +308,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; @@ -313,11 +330,15 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt break; } - return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; + return qt_socket_setsockopt(socketDescriptor, level, 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; @@ -356,7 +377,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: @@ -459,7 +481,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: @@ -527,8 +550,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; } @@ -558,7 +588,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const ssize_t readBytes; do { char c; - readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize); + readBytes = qt_socket_recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize); } while (readBytes == -1 && errno == EINTR); // If there's no error, or if our buffer was too small, there must be a @@ -572,16 +602,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; + 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; @@ -597,7 +636,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const return qint64(recvResult); } - +#endif qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { @@ -609,7 +648,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, &aa.a, &sz); } while (recvFromResult == -1 && errno == EINTR); @@ -660,7 +699,6 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l // ignore the SIGPIPE signal qt_ignore_sigpipe(); - ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len, 0, sockAddrPtr, sockAddrSize); @@ -698,7 +736,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() // Determine local address memset(&sa, 0, sizeof(sa)); - if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) { + if (qt_socket_getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) { qt_socket_getPortAndAddress(&sa, &localPort, &localAddress); // Determine protocol family @@ -722,13 +760,13 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() } // Determine the remote address - if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize)) + if (!qt_socket_getpeername(socketDescriptor, &sa.a, &sockAddrSize)) qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress); // Determine the socket type (UDP/TCP) int value = 0; QT_SOCKOPTLEN_T valueSize = sizeof(int); - if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &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) @@ -759,7 +797,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) @@ -773,7 +811,8 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) // of an interrupting signal. ssize_t writtenBytes; do { - writtenBytes = QT_WRITE(socketDescriptor, data, len); + writtenBytes = qt_socket_write(socketDescriptor, data, len); + // writtenBytes = QT_WRITE(socketDescriptor, data, len); ### TODO S60: Should this line be removed or the one above it? } while (writtenBytes < 0 && errno == EINTR); if (writtenBytes < 0) { @@ -815,7 +854,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) { @@ -833,6 +872,9 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) case EIO: setError(QAbstractSocket::NetworkError, ReadErrorString); break; +#ifdef Q_OS_SYMBIAN + case EPIPE: +#endif case ECONNRESET: #if defined(Q_OS_VXWORKS) case ESHUTDOWN: @@ -863,11 +905,40 @@ 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 + int retval; if (selectForRead) +#ifndef Q_OS_SYMBIAN retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); +#else + retval = qt_safe_select(socketDescriptor + 1, &fds, 0, &fdexec, timeout < 0 ? 0 : &tv); +#endif else +#ifndef Q_OS_SYMBIAN retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); +#else + retval = qt_safe_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 + return retval; } @@ -884,17 +955,69 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c 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; 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 + QTime timer; + timer.start(); + + do { + 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; + + } + + 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; - *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 d226f21..25873c6 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 @@ -1844,9 +1848,9 @@ QSocks5SocketEngineHandler::createSocketEngine(QAbstractSocket::SocketType socke QSOCKS5_DEBUG << "not proxying"; return 0; } - QSocks5SocketEngine *engine = new QSocks5SocketEngine(parent); + QScopedPointer<QSocks5SocketEngine> engine(new QSocks5SocketEngine(parent)); engine->setProxy(proxy); - return engine; + return engine.take(); } QAbstractSocketEngine *QSocks5SocketEngineHandler::createSocketEngine(int socketDescriptor, QObject *parent) diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index 2126fef..8bb92b7 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -354,7 +354,12 @@ void QTcpServer::close() if (d->socketEngine) { d->socketEngine->close(); - d->socketEngine->deleteLater(); + QT_TRY { + d->socketEngine->deleteLater(); + } QT_CATCH(const std::bad_alloc &) { + // in out of memory situations, the socketEngine + // will be deleted in ~QTcpServer (it's a child-object of this) + } d->socketEngine = 0; } diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 797becb..32f72df 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -94,6 +94,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 @@ -349,6 +356,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 @@ -368,6 +378,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 17e49d2..2bafe13 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -43,5 +43,3 @@ wince*: { DEFINES += QT_LOCALSOCKET_TCP } - - |