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 | 147 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 163 | ||||
-rw-r--r-- | src/network/socket/qsocks5socketengine.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qudpsocket.cpp | 20 | ||||
-rw-r--r-- | src/network/socket/socket.pri | 2 |
10 files changed, 345 insertions, 48 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 4bb12e6..b6f91e4 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1051,8 +1051,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 d6b1507..35701a7 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -276,6 +276,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 Q_OS_WIN d->socketNotifier->setEnabled(d->pendingConnections.size() <= d->maxPendingConnections); 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..9e3cbde 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -237,7 +237,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 @@ -246,6 +246,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) QLatin1String("QLocalSocket::connectToServer")); return; } +#endif // _q_connectToSocket does the actual connecting d->connectingName = name; @@ -282,7 +283,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 +301,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 +516,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 +534,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 eb031d3..95ffba5 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,14 @@ # include <winsock2.h> #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) @@ -78,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 @@ -212,6 +347,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 75b5a64..5136978 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 } /* @@ -126,7 +134,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 @@ -187,7 +195,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; } @@ -225,8 +234,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; } @@ -253,14 +263,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 @@ -270,7 +280,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; @@ -283,11 +295,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; @@ -326,7 +343,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: @@ -429,7 +447,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: @@ -497,8 +516,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; } @@ -528,7 +554,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 @@ -542,16 +568,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; @@ -560,14 +595,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) { @@ -579,7 +614,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); @@ -630,10 +665,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); @@ -671,7 +705,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 @@ -695,13 +729,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, &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) @@ -732,7 +766,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) @@ -746,7 +780,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) { @@ -788,7 +822,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) { @@ -806,6 +840,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; @@ -833,18 +870,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 @@ -875,6 +942,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; @@ -885,9 +958,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 @@ -904,9 +1001,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 } - - |