summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qabstractsocket.cpp3
-rw-r--r--src/network/socket/qlocalserver.cpp4
-rw-r--r--src/network/socket/qlocalserver_unix.cpp18
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp21
-rw-r--r--src/network/socket/qnativesocketengine.cpp11
-rw-r--r--src/network/socket/qnativesocketengine_p.h147
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp163
-rw-r--r--src/network/socket/qsocks5socketengine.cpp4
-rw-r--r--src/network/socket/qudpsocket.cpp20
-rw-r--r--src/network/socket/socket.pri2
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
}
-
-