summaryrefslogtreecommitdiff
path: root/src/network/socket/qnativesocketengine_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp330
1 files changed, 290 insertions, 40 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 0a7c6a1aee..cf31832f12 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,15 +59,150 @@
#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
+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
+
#if defined QNATIVESOCKETENGINE_DEBUG
/*
@@ -103,6 +237,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 +246,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 +268,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 +329,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 +377,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 +409,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 +434,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 +456,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 +503,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 +607,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 +676,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 +714,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 +728,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 +762,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return qint64(recvResult);
}
-
+#endif
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
QHostAddress *address, quint16 *port)
{
@@ -609,7 +774,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);
@@ -639,28 +804,27 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
#if !defined(QT_NO_IPV6)
struct sockaddr_in6 sockAddrIPv6;
if (host.protocol() == QAbstractSocket::IPv6Protocol) {
- memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
- sockAddrIPv6.sin6_family = AF_INET6;
- sockAddrIPv6.sin6_port = htons(port);
-
- Q_IPV6ADDR tmp = host.toIPv6Address();
- memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
- sockAddrSize = sizeof(sockAddrIPv6);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
+ memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
+ sockAddrIPv6.sin6_family = AF_INET6;
+ sockAddrIPv6.sin6_port = htons(port);
+
+ Q_IPV6ADDR tmp = host.toIPv6Address();
+ memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
+ sockAddrSize = sizeof(sockAddrIPv6);
+ sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
} else
#endif
if (host.protocol() == QAbstractSocket::IPv4Protocol) {
- memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
- sockAddrIPv4.sin_family = AF_INET;
- sockAddrIPv4.sin_port = htons(port);
- sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
- sockAddrSize = sizeof(sockAddrIPv4);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
+ memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
+ sockAddrIPv4.sin_family = AF_INET;
+ sockAddrIPv4.sin_port = htons(port);
+ sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
+ sockAddrSize = sizeof(sockAddrIPv4);
+ sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
}
// ignore the SIGPIPE signal
qt_ignore_sigpipe();
-
ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
0, sockAddrPtr, sockAddrSize);
@@ -698,7 +862,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 +886,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 +923,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 +937,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 +980,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 +998,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,16 +1031,46 @@ 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_socket_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_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
+
return retval;
}
int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
- bool *selectForRead, bool *selectForWrite) const
+ bool *selectForRead, bool *selectForWrite) const
{
fd_set fdread;
FD_ZERO(&fdread);
@@ -884,17 +1082,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;
}