summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-03-08 18:17:25 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-03-08 18:17:25 (GMT)
commit1500707a35ec95571d3dc1573e54d44420ee9098 (patch)
tree32f4ef849e899c8ae54472c0b9842229e3b42056 /src/network/socket
parentb6cc353adb0613ce41153181b4f08bb81b7acf68 (diff)
parent45531aceba4d0b2114942c49f4c256b70af58cf8 (diff)
downloadQt-1500707a35ec95571d3dc1573e54d44420ee9098.zip
Qt-1500707a35ec95571d3dc1573e54d44420ee9098.tar.gz
Qt-1500707a35ec95571d3dc1573e54d44420ee9098.tar.bz2
Merge branch 'symbian-socket-engine' of scm.dev.troll.no:qt/qt-symbian-network into symbian-socket-engine
Conflicts: src/network/access/qnetworkaccessmanager.cpp tests/auto/qsslsocket/tst_qsslsocket.cpp
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qabstractsocket.cpp18
-rw-r--r--src/network/socket/qabstractsocket_p.h2
-rw-r--r--src/network/socket/qabstractsocketengine.cpp14
-rw-r--r--src/network/socket/qlocalserver.cpp2
-rw-r--r--src/network/socket/qlocalserver_p.h2
-rw-r--r--src/network/socket/qlocalsocket.cpp2
-rw-r--r--src/network/socket/qlocalsocket_p.h2
-rw-r--r--src/network/socket/qnativesocketengine.cpp8
-rw-r--r--src/network/socket/qnativesocketengine_p.h18
-rw-r--r--src/network/socket/qnativesocketengine_symbian.cpp796
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp164
-rw-r--r--src/network/socket/qsocks5socketengine.cpp3
-rw-r--r--src/network/socket/qsymbiansocketengine.cpp1810
-rw-r--r--src/network/socket/qsymbiansocketengine_p.h261
-rw-r--r--src/network/socket/qtcpserver.cpp10
-rw-r--r--src/network/socket/qudpsocket.cpp10
-rw-r--r--src/network/socket/socket.pri23
17 files changed, 2139 insertions, 1006 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 2a942cc..020de42 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -375,6 +375,7 @@
#include <qpointer.h>
#include <qtimer.h>
#include <qelapsedtimer.h>
+#include <qscopedvaluerollback.h>
#ifndef QT_NO_OPENSSL
#include <QtNetwork/qsslsocket.h>
@@ -545,6 +546,10 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
resetSocketLayer();
socketEngine = QAbstractSocketEngine::createSocketEngine(q->socketType(), proxyInUse, q);
+#ifndef QT_NO_BEARERMANAGEMENT
+ //copy network session down to the socket engine (if it has been set)
+ socketEngine->setProperty("_q_networksession", q->property("_q_networksession"));
+#endif
if (!socketEngine) {
socketError = QAbstractSocket::UnsupportedSocketOperationError;
q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported"));
@@ -592,6 +597,7 @@ bool QAbstractSocketPrivate::canReadNotification()
socketEngine->setReadNotificationEnabled(false);
}
}
+ QScopedValueRollback<bool> rsncrollback(readSocketNotifierCalled);
readSocketNotifierCalled = true;
if (!isBuffered)
@@ -605,7 +611,6 @@ bool QAbstractSocketPrivate::canReadNotification()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full");
#endif
- readSocketNotifierCalled = false;
return false;
}
@@ -617,7 +622,6 @@ bool QAbstractSocketPrivate::canReadNotification()
qDebug("QAbstractSocketPrivate::canReadNotification() disconnecting socket");
#endif
q->disconnectFromHost();
- readSocketNotifierCalled = false;
return false;
}
newBytes = readBuffer.size() - newBytes;
@@ -637,9 +641,9 @@ bool QAbstractSocketPrivate::canReadNotification()
;
if (!emittedReadyRead && hasData) {
+ QScopedValueRollback<bool> r(emittedReadyRead);
emittedReadyRead = true;
emit q->readyRead();
- emittedReadyRead = false;
}
// If we were closed as a result of the readyRead() signal,
@@ -648,7 +652,6 @@ bool QAbstractSocketPrivate::canReadNotification()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canReadNotification() socket is closing - returning");
#endif
- readSocketNotifierCalled = false;
return true;
}
@@ -662,7 +665,6 @@ bool QAbstractSocketPrivate::canReadNotification()
socketEngine->setReadNotificationEnabled(readSocketNotifierState);
readSocketNotifierStateSet = false;
}
- readSocketNotifierCalled = false;
return true;
}
@@ -768,9 +770,9 @@ bool QAbstractSocketPrivate::flush()
if (written > 0) {
// Don't emit bytesWritten() recursively.
if (!emittedBytesWritten) {
+ QScopedValueRollback<bool> r(emittedBytesWritten);
emittedBytesWritten = true;
emit q->bytesWritten(written);
- emittedBytesWritten = false;
}
}
@@ -1602,6 +1604,10 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock
d->resetSocketLayer();
d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this);
+#ifndef QT_NO_BEARERMANAGEMENT
+ //copy network session down to the socket engine (if it has been set)
+ d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
+#endif
if (!d->socketEngine) {
d->socketError = UnsupportedSocketOperationError;
setErrorString(tr("Operation on socket is not supported"));
diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index 7e6343e..7662f47 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -59,7 +59,7 @@
#include "QtCore/qtimer.h"
#include "private/qringbuffer_p.h"
#include "private/qiodevice_p.h"
-#include "private/qnativesocketengine_p.h"
+#include "private/qabstractsocketengine_p.h"
#include "qnetworkproxy.h"
QT_BEGIN_NAMESPACE
diff --git a/src/network/socket/qabstractsocketengine.cpp b/src/network/socket/qabstractsocketengine.cpp
index 9fe6959..c29f936 100644
--- a/src/network/socket/qabstractsocketengine.cpp
+++ b/src/network/socket/qabstractsocketengine.cpp
@@ -40,7 +40,13 @@
****************************************************************************/
#include "qabstractsocketengine_p.h"
+
+#ifdef Q_OS_SYMBIAN
+#include "qsymbiansocketengine_p.h"
+#else
#include "qnativesocketengine_p.h"
+#endif
+
#include "qmutex.h"
#include "qnetworkproxy.h"
@@ -113,7 +119,11 @@ QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(QAbstractSocket
return 0;
#endif
+#ifdef Q_OS_SYMBIAN
+ return new QSymbianSocketEngine(parent);
+#else
return new QNativeSocketEngine(parent);
+#endif
}
QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(int socketDescripter, QObject *parent)
@@ -123,7 +133,11 @@ QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(int socketDescr
if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketDescripter, parent))
return ret;
}
+#ifdef Q_OS_SYMBIAN
+ return new QSymbianSocketEngine(parent);
+#else
return new QNativeSocketEngine(parent);
+#endif
}
QAbstractSocket::SocketError QAbstractSocketEngine::error() const
diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp
index 019759c..46822d7b 100644
--- a/src/network/socket/qlocalserver.cpp
+++ b/src/network/socket/qlocalserver.cpp
@@ -274,11 +274,11 @@ QLocalSocket *QLocalServer::nextPendingConnection()
if (d->pendingConnections.isEmpty())
return 0;
QLocalSocket *nextSocket = d->pendingConnections.dequeue();
+#ifndef QT_LOCALSOCKET_TCP
#ifdef Q_OS_SYMBIAN
if(!d->socketNotifier)
return nextSocket;
#endif
-#ifndef QT_LOCALSOCKET_TCP
if (d->pendingConnections.size() <= d->maxPendingConnections)
#ifndef Q_OS_WIN
d->socketNotifier->setEnabled(true);
diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h
index fe10959..8ec3ef0 100644
--- a/src/network/socket/qlocalserver_p.h
+++ b/src/network/socket/qlocalserver_p.h
@@ -65,7 +65,7 @@
# include <qt_windows.h>
# include <private/qwineventnotifier_p.h>
#else
-# include <private/qnativesocketengine_p.h>
+# include <qabstractsocketengine_p.h>
# include <qsocketnotifier.h>
#endif
diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp
index 8fa4b92..6c91d86 100644
--- a/src/network/socket/qlocalsocket.cpp
+++ b/src/network/socket/qlocalsocket.cpp
@@ -346,7 +346,7 @@ QLocalSocket::QLocalSocket(QObject * parent)
QLocalSocket::~QLocalSocket()
{
close();
-#ifndef Q_OS_WIN
+#if !defined (Q_OS_WIN) && !defined (QT_LOCALSOCKET_TCP)
Q_D(QLocalSocket);
d->unixSocket.setParent(0);
#endif
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index b042680..09e50f5 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -67,7 +67,7 @@
# include "private/qringbuffer_p.h"
# include <private/qwineventnotifier_p.h>
#else
-# include "private/qnativesocketengine_p.h"
+# include "private/qabstractsocketengine_p.h"
# include <qtcpsocket.h>
# include <qsocketnotifier.h>
# include <errno.h>
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index 80c8d9a..efa4f6f 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -110,10 +110,6 @@
# include "qtcpserver.h"
#endif
-#ifdef Q_OS_SYMBIAN
-# include <private/qcore_symbian_p.h>
-#endif
-
QT_BEGIN_NAMESPACE
//#define QNATIVESOCKETENGINE_DEBUG
@@ -164,9 +160,6 @@ QT_BEGIN_NAMESPACE
*/
QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() :
socketDescriptor(-1),
-#ifdef Q_OS_SYMBIAN
- socketServer(qt_symbianGetSocketServer()),
-#endif
readNotifier(0),
writeNotifier(0),
exceptNotifier(0)
@@ -394,7 +387,6 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb
// 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");
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 643aa72..a186911 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -60,13 +60,6 @@
# include <winsock2.h>
#endif
-#ifdef Q_OS_SYMBIAN
-#include <private/qeventdispatcher_symbian_p.h>
-#include <unistd.h>
-#include <es_sock.h>
-#include <in_sock.h>
-#endif
-
QT_BEGIN_NAMESPACE
// Use our own defines and structs which we know are correct
@@ -198,12 +191,6 @@ public:
~QNativeSocketEnginePrivate();
int socketDescriptor;
-#ifdef Q_OS_SYMBIAN
- mutable RSocket nativeSocket;
- RSocketServ& socketServer;
- RConnection connection; //TODO: shared ref
- mutable RTimer selectTimer;
-#endif
QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
@@ -241,11 +228,6 @@ public:
UnknownSocketErrorString = -1
};
-#ifdef Q_OS_SYMBIAN
- void getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr);
- void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr);
- void setError(TInt symbianError);
-#endif
void setError(QAbstractSocket::SocketError error, ErrorString errorString) const;
// native functions
diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp
deleted file mode 100644
index d1a0819..0000000
--- a/src/network/socket/qnativesocketengine_symbian.cpp
+++ /dev/null
@@ -1,796 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//#define QNATIVESOCKETENGINE_DEBUG
-#include "qnativesocketengine_p.h"
-#include "private/qnet_unix_p.h"
-#include "qiodevice.h"
-#include "qhostaddress.h"
-#include "qelapsedtimer.h"
-#include "qvarlengtharray.h"
-#include "qnetworkinterface.h"
-#include <es_sock.h>
-#include <in_sock.h>
-#include <QtCore/private/qcore_symbian_p.h>
-#ifndef QT_NO_IPV6IFNAME
-#include <net/if.h>
-#endif
-
-#define QNATIVESOCKETENGINE_DEBUG
-
-#if defined QNATIVESOCKETENGINE_DEBUG
-#include <qstring.h>
-#include <ctype.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-#if defined QNATIVESOCKETENGINE_DEBUG
-
-/*
- Returns a human readable representation of the first \a len
- characters in \a data.
-*/
-static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
-{
- if (!data) return "(null)";
- QByteArray out;
- for (int i = 0; i < len; ++i) {
- char c = data[i];
- if (isprint(c)) {
- out += c;
- } else switch (c) {
- case '\n': out += "\\n"; break;
- case '\r': out += "\\r"; break;
- case '\t': out += "\\t"; break;
- default:
- QString tmp;
- tmp.sprintf("\\%o", c);
- out += tmp.toLatin1();
- }
- }
-
- if (len < maxSize)
- out += "...";
-
- return out;
-}
-#endif
-
-void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr)
-{
-#if !defined(QT_NO_IPV6)
- if (a.Family() == KAfInet6) {
- Q_IPV6ADDR tmp;
- memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp));
- if (addr) {
- QHostAddress tmpAddress;
- tmpAddress.setAddress(tmp);
- *addr = tmpAddress;
-#ifndef QT_NO_IPV6IFNAME
- TPckgBuf<TSoInetIfQuery> query;
- query().iSrcAddr = a;
- TInt err = nativeSocket.GetOpt(KSoInetIfQueryBySrcAddr, KSolInetIfQuery, query);
- if(!err)
- addr->setScopeId(qt_TDesC2QString(query().iName));
- else
-#endif
- addr->setScopeId(QString::number(a.Scope()));
- }
- if (port)
- *port = a.Port();
- return;
- }
-#endif
- if (port)
- *port = a.Port();
- if (addr) {
- QHostAddress tmpAddress;
- tmpAddress.setAddress(a.Address());
- *addr = tmpAddress;
- }
-}
-/*! \internal
-
- Creates and returns a new socket descriptor of type \a socketType
- and \a socketProtocol. Returns -1 on failure.
-*/
-bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType,
- QAbstractSocket::NetworkLayerProtocol socketProtocol)
-{
-#ifndef QT_NO_IPV6
- TUint family = (socketProtocol == QAbstractSocket::IPv6Protocol) ? KAfInet6 : KAfInet;
-#else
- Q_UNUSED(socketProtocol);
- TUint family = KAfInet;
-#endif
- TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream;
- TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp;
- TInt err = nativeSocket.Open(socketServer, family, type, protocol, connection);
-
- if (err != KErrNone) {
- switch (err) {
- case KErrNotSupported:
- case KErrNotFound:
- setError(QAbstractSocket::UnsupportedSocketOperationError,
- ProtocolUnsupportedErrorString);
- break;
- case KErrNoMemory:
- setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
- break;
- case KErrPermissionDenied:
- setError(QAbstractSocket::SocketAccessError, AccessErrorString);
- break;
- default:
- break;
- }
-
- return false;
- }
-
- socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket);
- return true;
-}
-
-/*
- Returns the value of the socket option \a opt.
-*/
-int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
-{
- Q_Q(const QNativeSocketEngine);
- if (!q->isValid())
- return -1;
-
- TUint n;
- TUint level = KSOLSocket; // default
-
- switch (opt) {
- case QNativeSocketEngine::ReceiveBufferSocketOption:
- n = KSORecvBuf;
- break;
- case QNativeSocketEngine::SendBufferSocketOption:
- n = KSOSendBuf;
- break;
- case QNativeSocketEngine::NonBlockingSocketOption:
- n = KSONonBlockingIO;
- break;
- case QNativeSocketEngine::BroadcastSocketOption:
- return true; //symbian doesn't support or require this option
- case QNativeSocketEngine::AddressReusable:
- level = KSolInetIp;
- n = KSoReuseAddr;
- break;
- case QNativeSocketEngine::BindExclusively:
- return true;
- case QNativeSocketEngine::ReceiveOutOfBandData:
- level = KSolInetTcp;
- n = KSoTcpOobInline;
- break;
- case QNativeSocketEngine::LowDelayOption:
- level = KSolInetTcp;
- n = KSoTcpNoDelay;
- break;
- case QNativeSocketEngine::KeepAliveOption:
- level = KSolInetTcp;
- n = KSoTcpKeepAlive;
- break;
- default:
- return -1;
- }
-
- int v = -1;
- //GetOpt() is non const
- TInt err = nativeSocket.GetOpt(n, level, v);
- if (!err)
- return v;
-
- return -1;
-}
-
-
-/*
- Sets the socket option \a opt to \a v.
-*/
-bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
-{
- Q_Q(QNativeSocketEngine);
- if (!q->isValid())
- return false;
-
- int n = 0;
- int level = SOL_SOCKET; // default
-
- switch (opt) {
- case QNativeSocketEngine::ReceiveBufferSocketOption:
- n = KSORecvBuf;
- break;
- case QNativeSocketEngine::SendBufferSocketOption:
- n = KSOSendBuf;
- break;
- case QNativeSocketEngine::BroadcastSocketOption:
- return true;
- case QNativeSocketEngine::NonBlockingSocketOption:
- n = KSONonBlockingIO;
- break;
- case QNativeSocketEngine::AddressReusable:
- level = KSolInetIp;
- n = KSoReuseAddr;
- break;
- case QNativeSocketEngine::BindExclusively:
- return true;
- case QNativeSocketEngine::ReceiveOutOfBandData:
- level = KSolInetTcp;
- n = KSoTcpOobInline;
- break;
- case QNativeSocketEngine::LowDelayOption:
- level = KSolInetTcp;
- n = KSoTcpNoDelay;
- break;
- case QNativeSocketEngine::KeepAliveOption:
- level = KSolInetTcp;
- n = KSoTcpKeepAlive;
- break;
- }
-
- return (KErrNone == nativeSocket.SetOpt(n, level, v));
-}
-
-void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr)
-{
- nativeAddr.SetPort(port);
-#if !defined(QT_NO_IPV6)
- if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
-#ifndef QT_NO_IPV6IFNAME
- TPckgBuf<TSoInetIfQuery> query;
- query().iName = qt_QString2TPtrC(addr.scopeId());
- TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query);
- if(!err)
- nativeAddr.SetScope(query().iIndex);
- else
- nativeAddr.SetScope(0);
-#else
- nativeAddr.SetScope(addr.scopeId().toInt());
-#endif
- Q_IPV6ADDR ip6 = addr.toIPv6Address();
- TIp6Addr v6addr;
- memcpy(v6addr.u.iAddr8, ip6.c, 16);
- nativeAddr.SetAddress(v6addr);
- } else
-#endif
- if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
- nativeAddr.SetAddress(addr.toIPv4Address());
- } else {
- qWarning("unsupported network protocol (%d)", addr.protocol());
- }
-}
-
-bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
-{
-#ifdef QNATIVESOCKETENGINE_DEBUG
- qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
-#endif
-
- TInetAddr nativeAddr;
- setPortAndAddress(nativeAddr, port, addr);
- //TODO: async connect with active object - from here to end of function is a mess
- TRequestStatus status;
- nativeSocket.Connect(nativeAddr, status);
- User::WaitForRequest(status);
- TInt err = status.Int();
- if (err) {
- switch (err) {
- case KErrCouldNotConnect:
- setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
- socketState = QAbstractSocket::UnconnectedState;
- break;
- case KErrTimedOut:
- setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
- break;
- case KErrHostUnreach:
- setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
- socketState = QAbstractSocket::UnconnectedState;
- break;
- case KErrNetUnreach:
- setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
- socketState = QAbstractSocket::UnconnectedState;
- break;
- case KErrInUse:
- setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
- break;
- case KErrPermissionDenied:
- setError(QAbstractSocket::SocketAccessError, AccessErrorString);
- socketState = QAbstractSocket::UnconnectedState;
- break;
- case KErrNotSupported:
- case KErrBadDescriptor:
- socketState = QAbstractSocket::UnconnectedState;
- default:
- break;
- }
-
- if (socketState != QAbstractSocket::ConnectedState) {
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
- addr.toString().toLatin1().constData(), port,
- socketState == QAbstractSocket::ConnectingState
- ? "Connection in progress" : socketErrorString.toLatin1().constData());
-#endif
- return false;
- }
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
- addr.toString().toLatin1().constData(), port);
-#endif
-
- socketState = QAbstractSocket::ConnectedState;
- return true;
-}
-
-bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
-{
- TInetAddr nativeAddr;
- setPortAndAddress(nativeAddr, port, address);
-
- TInt err = nativeSocket.Bind(nativeAddr);
-
- if (err) {
- switch(errno) {
- case KErrInUse:
- setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
- break;
- case KErrPermissionDenied:
- setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
- break;
- case KErrNotSupported:
- setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
- break;
- default:
- break;
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
- address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
-#endif
-
- return false;
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
- address.toString().toLatin1().constData(), port);
-#endif
- socketState = QAbstractSocket::BoundState;
- return true;
-}
-
-bool QNativeSocketEnginePrivate::nativeListen(int backlog)
-{
- TInt err = nativeSocket.Listen(backlog);
- if (err) {
- switch (errno) {
- case KErrInUse:
- setError(QAbstractSocket::AddressInUseError,
- PortInuseErrorString);
- break;
- default:
- break;
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
- backlog, socketErrorString.toLatin1().constData());
-#endif
- return false;
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
-#endif
-
- socketState = QAbstractSocket::ListeningState;
- return true;
-}
-
-int QNativeSocketEnginePrivate::nativeAccept()
-{
- RSocket blankSocket;
- //TODO: this is unbelievably broken, needs to be properly async
- blankSocket.Open(socketServer);
- TRequestStatus status;
- nativeSocket.Accept(blankSocket, status);
- User::WaitForRequest(status);
- if(status.Int()) {
- qWarning("QNativeSocketEnginePrivate::nativeAccept() - error %d", status.Int());
- return 0;
- }
-
- return blankSocket.SubSessionHandle();
-}
-
-qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
-{
- int nbytes = 0;
- qint64 available = 0;
- TInt err = nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes);
- if(err)
- return 0;
- available = (qint64) nbytes;
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available);
-#endif
- return available;
-}
-
-bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
-{
- int nbytes;
- TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes);
- return err == KErrNone && nbytes > 0;
- //TODO: this is pretty horrible too...
-}
-
-qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
-{
- int nbytes;
- TInt err = nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes);
- return qint64(nbytes-28); //TODO: why -28 (open C version had this)?
-}
-
-qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
- QHostAddress *address, quint16 *port)
-{
- TPtr8 buffer((TUint8*)data, (int)maxSize);
- TInetAddr addr;
- TRequestStatus status; //TODO: OMG sync receive!
- nativeSocket.RecvFrom(buffer, addr, 0, status);
- User::WaitForRequest(status);
-
- if (status.Int()) {
- setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
- } else if (port || address) {
- getPortAndAddress(addr, port, address);
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- int len = buffer.Length();
- qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
- data, qt_prettyDebug(data, qMin(len, ssize_t(16)), len).data(), maxSize,
- address ? address->toString().toLatin1().constData() : "(nil)",
- port ? *port : 0, (qint64) len);
-#endif
-
- if (status.Int())
- return -1;
- return qint64(buffer.Length());
-}
-
-qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
- const QHostAddress &host, quint16 port)
-{
- TPtrC8 buffer((TUint8*)data, (int)len);
- TInetAddr addr;
- setPortAndAddress(addr, port, host);
- TSockXfrLength sentBytes;
- TRequestStatus status; //TODO: OMG sync send!
- nativeSocket.SendTo(buffer, addr, 0, status, sentBytes);
- User::WaitForRequest(status);
- TInt err = status.Int();
-
- if (err) {
- switch (err) {
- case KErrTooBig:
- setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
- break;
- default:
- setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
- }
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
- qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(),
- port, (qint64) sentBytes());
-#endif
-
- return qint64(sentBytes());
-}
-
-bool QNativeSocketEnginePrivate::fetchConnectionParameters()
-{
- localPort = 0;
- localAddress.clear();
- peerPort = 0;
- peerAddress.clear();
-
- if (socketDescriptor == -1)
- return false;
-
- if (!nativeSocket.SubSessionHandle()) {
- if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket))
- return false;
- }
-
- // Determine local address
- TSockAddr addr;
- nativeSocket.LocalName(addr);
- getPortAndAddress(addr, &localPort, &localAddress);
-
- // Determine protocol family
- switch (addr.Family()) {
- case KAfInet:
- socketProtocol = QAbstractSocket::IPv4Protocol;
- break;
-#if !defined (QT_NO_IPV6)
- case KAfInet6:
- socketProtocol = QAbstractSocket::IPv6Protocol;
- break;
-#endif
- default:
- socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
- break;
- }
-
- // Determine the remote address
- nativeSocket.RemoteName(addr);
- getPortAndAddress(addr, &peerPort, &peerAddress);
-
- // Determine the socket type (UDP/TCP)
- TProtocolDesc protocol;
- TInt err = nativeSocket.Info(protocol);
- if (err) {
- QAbstractSocket::UnknownSocketType;
- } else {
- switch (protocol.iProtocol) {
- case KProtocolInetTcp:
- socketType = QAbstractSocket::TcpSocket;
- break;
- case KProtocolInetUdp:
- socketType = QAbstractSocket::UdpSocket;
- break;
- default:
- socketType = QAbstractSocket::UnknownSocketType;
- break;
- }
- }
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- QString socketProtocolStr = "UnknownProtocol";
- if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
- else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
-
- QString socketTypeStr = "UnknownSocketType";
- if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
- else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
-
- qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
- " peer == %s:%i, socket == %s - %s",
- localAddress.toString().toLatin1().constData(), localPort,
- peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
- socketProtocolStr.toLatin1().constData());
-#endif
- return true;
-}
-
-void QNativeSocketEnginePrivate::nativeClose()
-{
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEngine::nativeClose()");
-#endif
-
- //TODO: call nativeSocket.Shutdown(EImmediate) in some cases?
- nativeSocket.Close();
- QSymbianSocketManager::instance().removeSocket(nativeSocket);
-}
-
-qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
-{
- Q_Q(QNativeSocketEngine);
- TPtrC8 buffer((TUint8*)data, (int)len);
- TSockXfrLength sentBytes;
- TRequestStatus status; //TODO: OMG sync send!
- nativeSocket.Send(buffer, 0, status, sentBytes);
- User::WaitForRequest(status);
- TInt err = status.Int();
-
- if (err) {
- switch (err) {
- case KErrDisconnected:
- sentBytes = -1;
- setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
- q->close();
- break;
- case KErrTooBig:
- setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
- break;
- case KErrWouldBlock:
- sentBytes = 0;
- default:
- setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
- }
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i",
- data, qt_prettyDebug(data, qMin((int) len, 16),
- (int) len).data(), len, (int) sentBytes());
-#endif
-
- return qint64(sentBytes());
-}
-/*
-*/
-qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
-{
- Q_Q(QNativeSocketEngine);
- if (!q->isValid()) {
- qWarning("QNativeSocketEngine::nativeRead: Invalid socket");
- return -1;
- }
-
- TPtr8 buffer((TUint8*)data, (int)maxSize);
- TSockXfrLength received = 0;
- TRequestStatus status; //TODO: OMG sync receive!
- nativeSocket.RecvOneOrMore(buffer, 0, status, received);
- User::WaitForRequest(status);
- TInt err = status.Int();
- int r = received();
-
- if (err) {
- switch(err) {
- case KErrWouldBlock:
- // No data was available for reading
- r = -2;
- break;
- case KErrDisconnected:
- r = 0;
- break;
- default:
- r = -1;
- //error string is now set in read(), not here in nativeRead()
- break;
- }
- }
-
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i",
- data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(),
- maxSize, r);
-#endif
-
- return qint64(r);
-}
-
-int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
-{
- bool readyRead = false;
- bool readyWrite = false;
- if (selectForRead)
- return nativeSelect(timeout, true, false, &readyRead, &readyWrite);
- else
- return nativeSelect(timeout, false, true, &readyRead, &readyWrite);
-}
-
-/*!
- \internal
- \param timeout timeout in milliseconds
- \param checkRead caller is interested if the socket is ready to read
- \param checkWrite caller is interested if the socket is ready for write
- \param selectForRead (out) should set to true if ready to read
- \param selectForWrite (out) should set to true if ready to write
- \return 0 on timeout, >0 on success, <0 on error
- */
-int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
- bool *selectForRead, bool *selectForWrite) const
-{
- //TODO: implement
- //as above, but checking both read and write status at the same time
- if (!selectTimer.Handle())
- qt_symbian_throwIfError(selectTimer.CreateLocal());
- TRequestStatus timerStat;
- selectTimer.HighRes(timerStat, timeout * 1000);
- TRequestStatus* readStat = 0;
- TRequestStatus* writeStat = 0;
- TRequestStatus* array[3];
- array[0] = &timerStat;
- int count = 1;
- if (checkRead) {
- //TODO: get from read AO
- //readStat = ?
- array[count++] = readStat;
- }
- if (checkWrite) {
- //TODO: get from write AO
- //writeStat = ?
- array[count++] = writeStat;
- }
-
- User::WaitForNRequest(array, count);
- //IMPORTANT - WaitForNRequest only decrements the thread semaphore once, although more than one status may have completed.
- if (timerStat.Int() != KRequestPending) {
- //timed out
- return 0;
- }
- selectTimer.Cancel();
- User::WaitForRequest(timerStat);
-
- if(readStat && readStat->Int() != KRequestPending) {
- Q_ASSERT(checkRead && selectForRead);
- //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive()
- *selectForRead = true;
- }
- if(writeStat && writeStat->Int() != KRequestPending) {
- Q_ASSERT(checkWrite && selectForWrite);
- //TODO: cancel the AO, but call its RunL anyway? looking for an UnsetActive()
- *selectForWrite = true;
- }
- return 1;
-}
-
-bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &iface)
-{
- //TODO
- return false;
-}
-
-bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
- const QNetworkInterface &iface)
-{
- //TODO
- return false;
-}
-
-QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
-{
- //TODO
- return QNetworkInterface();
-}
-
-bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface)
-{
- //TODO
- return false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index c819659..3d850a1 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -65,12 +65,7 @@
#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
@@ -174,11 +169,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
int protocol = AF_INET;
#endif
int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
-#ifdef Q_OS_SYMBIAN
- int socket = ::socket(protocol, type, 0);
-#else
+
int socket = qt_safe_socket(protocol, type, 0);
-#endif
if (socket <= 0) {
switch (errno) {
@@ -320,11 +312,9 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
}
#else // Q_OS_VXWORKS
int onoff = 1;
-#ifdef Q_OS_SYMBIAN
- if (::ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
-#else
+
if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
-#endif
+
#ifdef QNATIVESOCKETENGINE_DEBUG
perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
#endif
@@ -334,7 +324,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
return true;
}
case QNativeSocketEngine::AddressReusable:
-#if defined(SO_REUSEPORT) && !defined(Q_OS_SYMBIAN)
+#if defined(SO_REUSEPORT)
n = SO_REUSEPORT;
#else
n = SO_REUSEADDR;
@@ -427,11 +417,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
} else {
// unreachable
}
-#ifdef Q_OS_SYMBIAN
- int connectResult = ::connect(socketDescriptor, sockAddrPtr, sockAddrSize);
-#else
+
int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
-#endif
if (connectResult == -1) {
switch (errno) {
case EISCONN:
@@ -474,9 +461,6 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
case EBADF:
case EFAULT:
case ENOTSOCK:
-#ifdef Q_OS_SYMBIAN
- case EPIPE:
-#endif
socketState = QAbstractSocket::UnconnectedState;
default:
break;
@@ -575,11 +559,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
bool QNativeSocketEnginePrivate::nativeListen(int backlog)
{
-#ifdef Q_OS_SYMBIAN
- if (::listen(socketDescriptor, backlog) < 0) {
-#else
if (qt_safe_listen(socketDescriptor, backlog) < 0) {
-#endif
switch (errno) {
case EADDRINUSE:
setError(QAbstractSocket::AddressInUseError,
@@ -606,11 +586,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
int QNativeSocketEnginePrivate::nativeAccept()
{
-#ifdef Q_OS_SYMBIAN
- int acceptedDescriptor = ::accept(socketDescriptor, 0, 0);
-#else
int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
-#endif
return acceptedDescriptor;
}
@@ -785,11 +761,7 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
int nbytes = 0;
// gives shorter than true amounts on Unix domain sockets.
qint64 available = 0;
-#ifdef Q_OS_SYMBIAN
- if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
-#else
if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
-#endif
available = (qint64) nbytes;
#if defined (QNATIVESOCKETENGINE_DEBUG)
@@ -808,15 +780,10 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
// Peek 0 bytes into the next message. The size of the message may
// well be 0, so we can't check recvfrom's return value.
ssize_t readBytes;
-#ifdef Q_OS_SYMBIAN
- char c;
- readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize);
-#else
do {
char c;
readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize);
} while (readBytes == -1 && errno == EINTR);
-#endif
// If there's no error, or if our buffer was too small, there must be a
// pending datagram.
@@ -829,14 +796,6 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
return result;
}
-#ifdef Q_OS_SYMBIAN
-qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
-{
- size_t nbytes = 0;
- ::ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes);
- return qint64(nbytes-28);
-}
-#else
qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
{
QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
@@ -863,7 +822,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return qint64(recvResult);
}
-#endif
+
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
QHostAddress *address, quint16 *port)
{
@@ -873,17 +832,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
sz = sizeof(aa);
ssize_t recvFromResult = 0;
-#ifdef Q_OS_SYMBIAN
- char c;
- recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
- 0, &aa.a, &sz);
-#else
do {
char c;
recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
0, &aa.a, &sz);
} while (recvFromResult == -1 && errno == EINTR);
-#endif
if (recvFromResult == -1) {
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
@@ -932,13 +885,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
// ignore the SIGPIPE signal
qt_ignore_sigpipe();
-#ifdef Q_OS_SYMBIAN
- ssize_t sentBytes = ::sendto(socketDescriptor, data, len,
- 0, sockAddrPtr, sockAddrSize);
-#else
ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
0, sockAddrPtr, sockAddrSize);
-#endif
if (sentBytes < 0) {
switch (errno) {
@@ -1036,11 +984,7 @@ void QNativeSocketEnginePrivate::nativeClose()
qDebug("QNativeSocketEngine::nativeClose()");
#endif
-#ifdef Q_OS_SYMBIAN
- ::close(socketDescriptor);
-#else
- qt_safe_close(socketDescriptor);
-#endif
+ qt_safe_close(socketDescriptor);
}
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
@@ -1051,12 +995,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
qt_ignore_sigpipe();
ssize_t writtenBytes;
-#ifdef Q_OS_SYMBIAN
- // Symbian does not support signals natively and Open C returns EINTR when moving to offline
- writtenBytes = ::write(socketDescriptor, data, len);
-#else
writtenBytes = qt_safe_write(socketDescriptor, data, len);
-#endif
if (writtenBytes < 0) {
switch (errno) {
@@ -1096,11 +1035,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
}
ssize_t r = 0;
-#ifdef Q_OS_SYMBIAN
- r = ::read(socketDescriptor, data, maxSize);
-#else
r = qt_safe_read(socketDescriptor, data, maxSize);
-#endif
if (r < 0) {
r = -1;
@@ -1117,9 +1052,6 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
case EIO:
//error string is now set in read(), not here in nativeRead()
break;
-#ifdef Q_OS_SYMBIAN
- case EPIPE:
-#endif
case ECONNRESET:
#if defined(Q_OS_VXWORKS)
case ESHUTDOWN:
@@ -1150,40 +1082,11 @@ 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 fdexception;
- FD_ZERO(&fdexception);
- FD_SET(socketDescriptor, &fdexception);
-#endif
-
int retval;
if (selectForRead)
-#ifdef Q_OS_SYMBIAN
- retval = ::select(socketDescriptor + 1, &fds, 0, &fdexception, timeout < 0 ? 0 : &tv);
-#else
retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
-#endif
else
-#ifdef Q_OS_SYMBIAN
- retval = ::select(socketDescriptor + 1, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
-#else
retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, 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, &fdexception);
- }
- if(selectForExec) {
- qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected exception for fd %d",
- selectForRead, retval, errno, socketDescriptor);
- }
-#endif
return retval;
}
@@ -1201,65 +1104,12 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c
if (checkWrite)
FD_SET(socketDescriptor, &fdwrite);
-#ifdef Q_OS_SYMBIAN
- fd_set fdexception;
- FD_ZERO(&fdexception);
- FD_SET(socketDescriptor, &fdexception);
-#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
- QElapsedTimer timer;
- timer.start();
-
- do {
- ret = ::select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, 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, &fdexception);
- }
- if(selectForExec) {
- qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d",
- checkRead, checkWrite, ret, errno, socketDescriptor);
- if (checkWrite){
- FD_CLR(socketDescriptor, &fdread);
- FD_SET(socketDescriptor, &fdwrite);
- } else if (checkRead)
- FD_SET(socketDescriptor, &fdread);
-
-
- 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;
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index ab3d260..91dfdf3 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -556,6 +556,7 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode)
udpData = new QSocks5UdpAssociateData;
data = udpData;
udpData->udpSocket = new QUdpSocket(q);
+ udpData->udpSocket->setProperty("_q_networksession", q->property("_q_networksession"));
udpData->udpSocket->setProxy(QNetworkProxy::NoProxy);
QObject::connect(udpData->udpSocket, SIGNAL(readyRead()),
q, SLOT(_q_udpSocketReadNotification()),
@@ -567,6 +568,7 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode)
}
data->controlSocket = new QTcpSocket(q);
+ data->controlSocket->setProperty("_q_networksession", q->property("_q_networksession"));
data->controlSocket->setProxy(QNetworkProxy::NoProxy);
QObject::connect(data->controlSocket, SIGNAL(connected()), q, SLOT(_q_controlSocketConnected()),
Qt::DirectConnection);
@@ -1376,6 +1378,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port)
d->udpData->associatePort = d->localPort;
d->localPort = 0;
QUdpSocket dummy;
+ dummy.setProperty("_q_networksession", property("_q_networksession"));
dummy.setProxy(QNetworkProxy::NoProxy);
if (!dummy.bind()
|| writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0
diff --git a/src/network/socket/qsymbiansocketengine.cpp b/src/network/socket/qsymbiansocketengine.cpp
new file mode 100644
index 0000000..dac50d4
--- /dev/null
+++ b/src/network/socket/qsymbiansocketengine.cpp
@@ -0,0 +1,1810 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QNATIVESOCKETENGINE_DEBUG
+#include "qsymbiansocketengine_p.h"
+
+#include "qiodevice.h"
+#include "qhostaddress.h"
+#include "qelapsedtimer.h"
+#include "qvarlengtharray.h"
+#include "qnetworkinterface.h"
+#include "qnetworksession_p.h"
+#include <es_sock.h>
+#include <in_sock.h>
+#include <net/if.h>
+
+#include <private/qcore_symbian_p.h>
+
+#if !defined(QT_NO_NETWORKPROXY)
+# include "qnetworkproxy.h"
+# include "qabstractsocket.h"
+# include "qtcpserver.h"
+#endif
+
+#include <QCoreApplication>
+
+#include <qabstracteventdispatcher.h>
+#include <qsocketnotifier.h>
+#include <qnetworkinterface.h>
+
+#include <private/qthread_p.h>
+#include <private/qobject_p.h>
+#include <private/qsystemerror_p.h>
+
+#define QNATIVESOCKETENGINE_DEBUG
+
+#if defined QNATIVESOCKETENGINE_DEBUG
+#include <qstring.h>
+#include <ctype.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define Q_VOID
+// Common constructs
+#define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \
+ if (!isValid()) { \
+ qWarning(""#function" was called on an uninitialized socket device"); \
+ return returnValue; \
+ } } while (0)
+#define Q_CHECK_INVALID_SOCKETLAYER(function, returnValue) do { \
+ if (isValid()) { \
+ qWarning(""#function" was called on an already initialized socket device"); \
+ return returnValue; \
+ } } while (0)
+#define Q_CHECK_STATE(function, checkState, returnValue) do { \
+ if (d->socketState != (checkState)) { \
+ qWarning(""#function" was not called in "#checkState); \
+ return (returnValue); \
+ } } while (0)
+#define Q_CHECK_NOT_STATE(function, checkState, returnValue) do { \
+ if (d->socketState == (checkState)) { \
+ qWarning(""#function" was called in "#checkState); \
+ return (returnValue); \
+ } } while (0)
+#define Q_CHECK_STATES(function, state1, state2, returnValue) do { \
+ if (d->socketState != (state1) && d->socketState != (state2)) { \
+ qWarning(""#function" was called" \
+ " not in "#state1" or "#state2); \
+ return (returnValue); \
+ } } while (0)
+#define Q_CHECK_TYPE(function, type, returnValue) do { \
+ if (d->socketType != (type)) { \
+ qWarning(#function" was called by a" \
+ " socket other than "#type""); \
+ return (returnValue); \
+ } } while (0)
+
+#if defined QNATIVESOCKETENGINE_DEBUG
+
+/*
+ Returns a human readable representation of the first \a len
+ characters in \a data.
+*/
+static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
+{
+ if (!data) return "(null)";
+ QByteArray out;
+ for (int i = 0; i < len; ++i) {
+ char c = data[i];
+ if (isprint(c)) {
+ out += c;
+ } else switch (c) {
+ case '\n': out += "\\n"; break;
+ case '\r': out += "\\r"; break;
+ case '\t': out += "\\t"; break;
+ default:
+ QString tmp;
+ tmp.sprintf("\\%o", c);
+ out += tmp.toLatin1();
+ }
+ }
+
+ if (len < maxSize)
+ out += "...";
+
+ return out;
+}
+#endif
+
+void QSymbianSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr)
+{
+ if (a.Family() == KAfInet6) {
+ Q_IPV6ADDR tmp;
+ memcpy(&tmp, a.Ip6Address().u.iAddr8, sizeof(tmp));
+ if (addr) {
+ QHostAddress tmpAddress;
+ tmpAddress.setAddress(tmp);
+ *addr = tmpAddress;
+ TPckgBuf<TSoInetIfQuery> query;
+ query().iSrcAddr = a;
+ TInt err = nativeSocket.GetOpt(KSoInetIfQueryBySrcAddr, KSolInetIfQuery, query);
+ if (!err)
+ addr->setScopeId(qt_TDesC2QString(query().iName));
+ else
+ addr->setScopeId(QString::number(a.Scope()));
+ }
+ if (port)
+ *port = a.Port();
+ return;
+ }
+ if (port)
+ *port = a.Port();
+ if (addr) {
+ QHostAddress tmpAddress;
+ tmpAddress.setAddress(a.Address());
+ *addr = tmpAddress;
+ }
+}
+/*! \internal
+
+ Creates and returns a new socket descriptor of type \a socketType
+ and \a socketProtocol. Returns -1 on failure.
+*/
+bool QSymbianSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType,
+ QAbstractSocket::NetworkLayerProtocol socketProtocol)
+{
+ Q_Q(QSymbianSocketEngine);
+ TUint family = KAfInet; // KAfInet6 is only used as an address family, not as a protocol family
+ TUint type = (socketType == QAbstractSocket::UdpSocket) ? KSockDatagram : KSockStream;
+ TUint protocol = (socketType == QAbstractSocket::UdpSocket) ? KProtocolInetUdp : KProtocolInetTcp;
+
+ //Check if there is a user specified session
+ RConnection *connection = 0;
+ QVariant v(q->property("_q_networksession"));
+ if (v.isValid()) {
+ QSharedPointer<QNetworkSession> s = qvariant_cast<QSharedPointer<QNetworkSession> >(v);
+ connection = QNetworkSessionPrivate::nativeSession(*s);
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - _q_networksession was set" << connection;
+#endif
+ }
+ TInt err;
+ if (connection) {
+ if (connection->SubSessionHandle())
+ err = nativeSocket.Open(socketServer, family, type, protocol, *connection);
+ else {
+ setError(QAbstractSocket::NetworkError, SessionNotOpenErrorString);
+ return false;
+ }
+ } else
+ err = nativeSocket.Open(socketServer, family, type, protocol); //TODO: FIXME - deprecated API, make sure we always have a connection instead
+
+ if (err != KErrNone) {
+ switch (err) {
+ case KErrNotSupported:
+ case KErrNotFound:
+ setError(QAbstractSocket::UnsupportedSocketOperationError,
+ ProtocolUnsupportedErrorString);
+ break;
+ default:
+ setError(err);
+ break;
+ }
+
+ return false;
+ }
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << "QSymbianSocketEnginePrivate::createNewSocket - created" << nativeSocket.SubSessionHandle();
+#endif
+ socketDescriptor = QSymbianSocketManager::instance().addSocket(nativeSocket);
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << " - allocated socket descriptor" << socketDescriptor;
+#endif
+ return true;
+}
+
+void QSymbianSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr)
+{
+ nativeAddr.SetPort(port);
+ if (addr == QHostAddress::Any) {
+ //Should allow both IPv4 and IPv6
+ //Listening on "0.0.0.0" accepts ONLY ipv4 connections
+ //Listening on "::" accepts ONLY ipv6 connections
+ nativeAddr.SetFamily(KAFUnspec);
+ } else if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
+ TPckgBuf<TSoInetIfQuery> query;
+ query().iName = qt_QString2TPtrC(addr.scopeId());
+ TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query);
+ if (!err)
+ nativeAddr.SetScope(query().iIndex);
+ else
+ nativeAddr.SetScope(0);
+ Q_IPV6ADDR ip6 = addr.toIPv6Address();
+ TIp6Addr v6addr;
+ memcpy(v6addr.u.iAddr8, ip6.c, 16);
+ nativeAddr.SetAddress(v6addr);
+ } else if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
+ nativeAddr.SetAddress(addr.toIPv4Address());
+ } else {
+ qWarning("unsupported network protocol (%d)", addr.protocol());
+ }
+}
+
+QSymbianSocketEnginePrivate::QSymbianSocketEnginePrivate() :
+ socketDescriptor(-1),
+ socketServer(QSymbianSocketManager::instance().getSocketServer()),
+ readNotifier(0),
+ writeNotifier(0),
+ exceptNotifier(0),
+ asyncSelect(0)
+{
+}
+
+QSymbianSocketEnginePrivate::~QSymbianSocketEnginePrivate()
+{
+}
+
+
+QSymbianSocketEngine::QSymbianSocketEngine(QObject *parent)
+ : QAbstractSocketEngine(*new QSymbianSocketEnginePrivate(), parent)
+{
+}
+
+
+QSymbianSocketEngine::~QSymbianSocketEngine()
+{
+ close();
+ // FIXME what else do we need to free?
+}
+
+/*!
+ Initializes a QSymbianSocketEngine by creating a new socket of type \a
+ socketType and network layer protocol \a protocol. Returns true on
+ success; otherwise returns false.
+
+ If the socket was already initialized, this function closes the
+ socket before reeinitializing it.
+
+ The new socket is non-blocking, and for UDP sockets it's also
+ broadcast enabled.
+*/
+bool QSymbianSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol protocol)
+{
+ Q_D(QSymbianSocketEngine);
+ if (isValid())
+ close();
+
+ // Create the socket
+ if (!d->createNewSocket(socketType, protocol)) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ QString typeStr = QLatin1String("UnknownSocketType");
+ if (socketType == QAbstractSocket::TcpSocket) typeStr = QLatin1String("TcpSocket");
+ else if (socketType == QAbstractSocket::UdpSocket) typeStr = QLatin1String("UdpSocket");
+ QString protocolStr = QLatin1String("UnknownProtocol");
+ if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = QLatin1String("IPv4Protocol");
+ else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = QLatin1String("IPv6Protocol");
+ qDebug("QSymbianSocketEngine::initialize(type == %s, protocol == %s) failed: %s",
+ typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), d->socketErrorString.toLatin1().constData());
+#endif
+ return false;
+ }
+
+ // Make the socket nonblocking.
+ if (!setOption(NonBlockingSocketOption, 1)) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ d->NonBlockingInitFailedErrorString);
+ close();
+ return false;
+ }
+
+ // Set the broadcasting flag if it's a UDP socket.
+ if (socketType == QAbstractSocket::UdpSocket
+ && !setOption(BroadcastSocketOption, 1)) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ d->BroadcastingInitFailedErrorString);
+ close();
+ return false;
+ }
+
+
+ // Make sure we receive out-of-band data
+ if (socketType == QAbstractSocket::TcpSocket
+ && !setOption(ReceiveOutOfBandData, 1)) {
+ qWarning("QSymbianSocketEngine::initialize unable to inline out-of-band data");
+ }
+
+
+ d->socketType = socketType;
+ d->socketProtocol = protocol;
+ return true;
+}
+
+/*! \overload
+
+ Initializes the socket using \a socketDescriptor instead of
+ creating a new one. The socket type and network layer protocol are
+ determined automatically. The socket's state is set to \a
+ socketState.
+
+ If the socket type is either TCP or UDP, it is made non-blocking.
+ UDP sockets are also broadcast enabled.
+ */
+bool QSymbianSocketEngine::initialize(int socketDescriptor, QAbstractSocket::SocketState socketState)
+{
+ Q_D(QSymbianSocketEngine);
+
+ if (isValid())
+ close();
+
+ if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, d->nativeSocket)) {
+ qWarning("QSymbianSocketEngine::initialize - socket descriptor not found");
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ QSymbianSocketEnginePrivate::InvalidSocketErrorString);
+ return false;
+ }
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << "QSymbianSocketEngine::initialize - attached to" << d->nativeSocket.SubSessionHandle() << socketDescriptor;
+#endif
+ Q_ASSERT(d->socketDescriptor == socketDescriptor || d->socketDescriptor == -1);
+ d->socketDescriptor = socketDescriptor;
+
+ // determine socket type and protocol
+ if (!d->fetchConnectionParameters()) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::initialize(socketDescriptor == %i) failed: %s",
+ socketDescriptor, d->socketErrorString.toLatin1().constData());
+#endif
+ d->socketDescriptor = -1;
+ return false;
+ }
+
+ if (d->socketType != QAbstractSocket::UnknownSocketType) {
+ // Make the socket nonblocking.
+ if (!setOption(NonBlockingSocketOption, 1)) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ d->NonBlockingInitFailedErrorString);
+ close();
+ return false;
+ }
+
+ // Set the broadcasting flag if it's a UDP socket.
+ if (d->socketType == QAbstractSocket::UdpSocket
+ && !setOption(BroadcastSocketOption, 1)) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ d->BroadcastingInitFailedErrorString);
+ close();
+ return false;
+ }
+
+ // Make sure we receive out-of-band data
+ if (d->socketType == QAbstractSocket::TcpSocket
+ && !setOption(ReceiveOutOfBandData, 1)) {
+ qWarning("QSymbianSocketEngine::initialize unable to inline out-of-band data");
+ }
+ }
+
+ d->socketState = socketState;
+ return true;
+}
+
+/*!
+ Returns true if the socket is valid; otherwise returns false. A
+ socket is valid if it has not been successfully initialized, or if
+ it has been closed.
+*/
+bool QSymbianSocketEngine::isValid() const
+{
+ Q_D(const QSymbianSocketEngine);
+ return d->socketDescriptor != -1;
+}
+
+
+/*!
+ Returns the native socket descriptor. Any use of this descriptor
+ stands the risk of being non-portable.
+*/
+int QSymbianSocketEngine::socketDescriptor() const
+{
+ Q_D(const QSymbianSocketEngine);
+ return d->socketDescriptor;
+}
+
+/*
+ Sets the socket option \a opt to \a v.
+*/
+bool QSymbianSocketEngine::setOption(QAbstractSocketEngine::SocketOption opt, int v)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setOption(), false);
+
+ TUint n = 0;
+ TUint level = KSOLSocket; // default
+
+ if (!QSymbianSocketEnginePrivate::translateSocketOption(opt, n, level))
+ return false;
+
+ if (!level && !n)
+ return true;
+
+ return (KErrNone == d->nativeSocket.SetOpt(n, level, v));
+}
+
+/*
+ Returns the value of the socket option \a opt.
+*/
+int QSymbianSocketEngine::option(QAbstractSocketEngine::SocketOption opt) const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::option(), -1);
+
+ TUint n;
+ TUint level = KSOLSocket; // default
+
+ if (!QSymbianSocketEnginePrivate::translateSocketOption(opt, n, level))
+ return false;
+
+ if (!level && !n)
+ return 1;
+
+ int v = -1;
+ //GetOpt() is non const
+ TInt err = d->nativeSocket.GetOpt(n, level, v);
+ if (!err)
+ return v;
+
+ return -1;
+}
+
+bool QSymbianSocketEnginePrivate::translateSocketOption(QAbstractSocketEngine::SocketOption opt, TUint &n, TUint &level)
+{
+
+ switch (opt) {
+ case QAbstractSocketEngine::ReceiveBufferSocketOption:
+ n = KSORecvBuf;
+ break;
+ case QAbstractSocketEngine::SendBufferSocketOption:
+ n = KSOSendBuf;
+ break;
+ case QAbstractSocketEngine::NonBlockingSocketOption:
+ n = KSONonBlockingIO;
+ break;
+ case QAbstractSocketEngine::AddressReusable:
+ level = KSolInetIp;
+ n = KSoReuseAddr;
+ break;
+ case QAbstractSocketEngine::BroadcastSocketOption:
+ case QAbstractSocketEngine::BindExclusively:
+ level = 0;
+ n = 0;
+ return true;
+ case QAbstractSocketEngine::ReceiveOutOfBandData:
+ level = KSolInetTcp;
+ n = KSoTcpOobInline;
+ break;
+ case QAbstractSocketEngine::LowDelayOption:
+ level = KSolInetTcp;
+ n = KSoTcpNoDelay;
+ break;
+ case QAbstractSocketEngine::KeepAliveOption:
+ level = KSolInetTcp;
+ n = KSoTcpKeepAlive;
+ break;
+ case QAbstractSocketEngine::MulticastLoopbackOption:
+ level = KSolInetIp;
+ n = KSoIp6MulticastLoop;
+ break;
+ case QAbstractSocketEngine::MulticastTtlOption:
+ level = KSolInetIp;
+ n = KSoIp6MulticastHops;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+qint64 QSymbianSocketEngine::receiveBufferSize() const
+{
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::receiveBufferSize(), -1);
+ return option(ReceiveBufferSocketOption);
+}
+
+void QSymbianSocketEngine::setReceiveBufferSize(qint64 size)
+{
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setReceiveBufferSize(), Q_VOID);
+ setOption(ReceiveBufferSocketOption, size);
+}
+
+qint64 QSymbianSocketEngine::sendBufferSize() const
+{
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setSendBufferSize(), -1);
+ return option(SendBufferSocketOption);
+}
+
+void QSymbianSocketEngine::setSendBufferSize(qint64 size)
+{
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setSendBufferSize(), Q_VOID);
+ setOption(SendBufferSocketOption, size);
+}
+
+/*!
+ Connects to the remote host name given by \a name on port \a
+ port. When this function is called, the upper-level will not
+ perform a hostname lookup.
+
+ The native socket engine does not support this operation,
+ but some other socket engines (notably proxy-based ones) do.
+*/
+bool QSymbianSocketEngine::connectToHostByName(const QString &name, quint16 port)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(port);
+ Q_D(QSymbianSocketEngine);
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ QSymbianSocketEnginePrivate::OperationUnsupportedErrorString);
+ return false;
+}
+
+/*!
+ If there's a connection activity on the socket, process it. Then
+ notify our parent if there really was activity.
+*/
+void QSymbianSocketEngine::connectionNotification()
+{
+ // FIXME check if we really need to do it like that in Symbian
+ Q_D(QSymbianSocketEngine);
+ Q_ASSERT(state() == QAbstractSocket::ConnectingState);
+
+ connectToHost(d->peerAddress, d->peerPort);
+ if (state() != QAbstractSocket::ConnectingState) {
+ // we changed states
+ QAbstractSocketEngine::connectionNotification();
+ }
+}
+
+
+bool QSymbianSocketEngine::connectToHost(const QHostAddress &addr, quint16 port)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::connectToHost(), false);
+
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug("QSymbianSocketEngine::connectToHost() : %d ", d->socketDescriptor);
+#endif
+
+ if (!d->checkProxy(addr))
+ return false;
+
+ d->peerAddress = addr;
+ d->peerPort = port;
+
+ TInetAddr nativeAddr;
+ d->setPortAndAddress(nativeAddr, port, addr);
+ TRequestStatus status;
+ d->nativeSocket.Connect(nativeAddr, status);
+ User::WaitForRequest(status);
+ TInt err = status.Int();
+ //For non blocking connect, KErrAlreadyExists is returned from the second Connect() to indicate
+ //the connection is up. So treat this the same as KErrNone which would be returned from the first
+ //call if it wouldn't block. (e.g. winsock wrapper in the emulator ignores the nonblocking flag)
+ if (err && err != KErrAlreadyExists) {
+ switch (err) {
+ case KErrWouldBlock:
+ d->socketState = QAbstractSocket::ConnectingState;
+ break;
+ default:
+ d->setError(err);
+ d->socketState = QAbstractSocket::UnconnectedState;
+ break;
+ }
+
+ if (d->socketState != QAbstractSocket::ConnectedState) {
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::connectToHost(%s, %i) == false (%s)",
+ addr.toString().toLatin1().constData(), port,
+ d->socketState == QAbstractSocket::ConnectingState
+ ? "Connection in progress" : d->socketErrorString.toLatin1().constData());
+#endif
+ return false;
+ }
+ }
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::Connect(%s, %i) == true",
+ addr.toString().toLatin1().constData(), port);
+#endif
+
+ d->socketState = QAbstractSocket::ConnectedState;
+ d->fetchConnectionParameters();
+ return true;
+}
+
+bool QSymbianSocketEngine::bind(const QHostAddress &address, quint16 port)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::bind(), false);
+
+ if (!d->checkProxy(address))
+ return false;
+
+ Q_CHECK_STATE(QSymbianSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
+
+ TInetAddr nativeAddr;
+ d->setPortAndAddress(nativeAddr, port, address);
+
+ TInt err = d->nativeSocket.Bind(nativeAddr);
+#ifdef __WINS__
+ if (err == KErrArgument) // winsock prt returns wrong error code
+ err = KErrInUse;
+#endif
+
+ if (err) {
+ d->setError(err);
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::bind(%s, %i) == false (%s)",
+ address.toString().toLatin1().constData(), port, d->socketErrorString.toLatin1().constData());
+#endif
+
+ return false;
+ }
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::bind(%s, %i) == true",
+ address.toString().toLatin1().constData(), port);
+#endif
+ d->socketState = QAbstractSocket::BoundState;
+
+ d->fetchConnectionParameters();
+ return true;
+}
+
+bool QSymbianSocketEngine::listen()
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::listen(), false);
+ Q_CHECK_STATE(QSymbianSocketEngine::listen(), QAbstractSocket::BoundState, false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
+ // TODO the value 50 is from the QNativeSocketEngine. Maybe it's a bit too much
+ // for a mobile platform
+ TInt err = d->nativeSocket.Listen(50);
+ if (err) {
+ d->setError(err);
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::listen() == false (%s)",
+ d->socketErrorString.toLatin1().constData());
+#endif
+ return false;
+ }
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::listen() == true");
+#endif
+
+ d->socketState = QAbstractSocket::ListeningState;
+ return true;
+}
+
+int QSymbianSocketEngine::accept()
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::accept(), -1);
+ Q_CHECK_STATE(QSymbianSocketEngine::accept(), QAbstractSocket::ListeningState, false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::accept(), QAbstractSocket::TcpSocket, false);
+ RSocket blankSocket;
+ blankSocket.Open(d->socketServer);
+ TRequestStatus status;
+ d->nativeSocket.Accept(blankSocket, status);
+ User::WaitForRequest(status);
+ if (status.Int()) {
+ blankSocket.Close();
+ if (status != KErrWouldBlock)
+ qWarning("QSymbianSocketEngine::accept() - error %d", status.Int());
+ return -1;
+ }
+
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << "QSymbianSocketEnginePrivate::accept - created" << blankSocket.SubSessionHandle();
+#endif
+ int fd = QSymbianSocketManager::instance().addSocket(blankSocket);
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << " - allocated socket descriptor" << fd;
+#endif
+ return fd;
+}
+
+qint64 QSymbianSocketEngine::bytesAvailable() const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::bytesAvailable(), -1);
+ Q_CHECK_NOT_STATE(QSymbianSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, false);
+ int nbytes = 0;
+ qint64 available = 0;
+ TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending, KSOLSocket, nbytes);
+ if (err)
+ return 0;
+ available = (qint64) nbytes;
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::bytesAvailable() == %lli", available);
+#endif
+ return available;
+}
+
+bool QSymbianSocketEngine::hasPendingDatagrams() const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::hasPendingDatagrams(), false);
+ Q_CHECK_NOT_STATE(QSymbianSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
+ int nbytes;
+ TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes);
+ return err == KErrNone && nbytes > 0;
+}
+
+qint64 QSymbianSocketEngine::pendingDatagramSize() const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::pendingDatagramSize(), false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
+ int nbytes;
+ TInt err = d->nativeSocket.GetOpt(KSOReadBytesPending,KSOLSocket, nbytes);
+ if (nbytes > 0) {
+ //nbytes includes IP header, which is of variable length (IPv4 with or without options, IPv6...)
+ QByteArray next(nbytes,0);
+ TPtr8 buffer((TUint8*)next.data(), next.size());
+ TInetAddr addr;
+ TRequestStatus status;
+ //TODO: rather than peek, should we save this for next call to readDatagram?
+ //what if calls don't match though?
+ d->nativeSocket.RecvFrom(buffer, addr, KSockReadPeek, status);
+ User::WaitForRequest(status);
+ if (status.Int())
+ return 0;
+ return buffer.Length();
+ }
+ return qint64(nbytes);
+}
+
+
+qint64 QSymbianSocketEngine::readDatagram(char *data, qint64 maxSize,
+ QHostAddress *address, quint16 *port)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::readDatagram(), -1);
+ Q_CHECK_TYPE(QSymbianSocketEngine::readDatagram(), QAbstractSocket::UdpSocket, false);
+ TPtr8 buffer((TUint8*)data, (int)maxSize);
+ TInetAddr addr;
+ TRequestStatus status;
+ d->nativeSocket.RecvFrom(buffer, addr, 0, status);
+ User::WaitForRequest(status); //Non blocking receive
+
+ if (status.Int()) {
+ d->setError(QAbstractSocket::NetworkError, d->ReceiveDatagramErrorString);
+ } else if (port || address) {
+ d->getPortAndAddress(addr, port, address);
+ }
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ int len = buffer.Length();
+ qDebug("QSymbianSocketEngine::receiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
+ data, qt_prettyDebug(data, qMin(len, ssize_t(16)), len).data(), maxSize,
+ address ? address->toString().toLatin1().constData() : "(nil)",
+ port ? *port : 0, (qint64) len);
+#endif
+
+ if (status.Int())
+ return -1;
+ return qint64(buffer.Length());
+}
+
+
+qint64 QSymbianSocketEngine::writeDatagram(const char *data, qint64 len,
+ const QHostAddress &host, quint16 port)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::writeDatagram(), -1);
+ Q_CHECK_TYPE(QSymbianSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1);
+ TPtrC8 buffer((TUint8*)data, (int)len);
+ TInetAddr addr;
+ d->setPortAndAddress(addr, port, host);
+ TSockXfrLength sentBytes;
+ TRequestStatus status;
+ d->nativeSocket.SendTo(buffer, addr, 0, status, sentBytes);
+ User::WaitForRequest(status); //Non blocking send
+ TInt err = status.Int();
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::writeDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli (err=%d)", data,
+ qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(),
+ port, (qint64) sentBytes(), err);
+#endif
+
+ if (err) {
+ switch (err) {
+ case KErrWouldBlock:
+ // do not error the socket. (otherwise socket layer is reset)
+ // On symbian^1 and earlier, KErrWouldBlock is returned when interface is not up yet
+ // On symbian^3, KErrNone is returned but sentBytes = 0
+ return 0;
+ case KErrTooBig:
+ d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString);
+ break;
+ default:
+ d->setError(QAbstractSocket::NetworkError, d->SendDatagramErrorString);
+ }
+ return -1;
+ }
+
+ 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.
+ return len;
+ }
+ return sentBytes();
+}
+
+// FIXME check where the native socket engine called that..
+bool QSymbianSocketEnginePrivate::fetchConnectionParameters()
+{
+ localPort = 0;
+ localAddress.clear();
+ peerPort = 0;
+ peerAddress.clear();
+
+ if (socketDescriptor == -1)
+ return false;
+
+ if (!nativeSocket.SubSessionHandle()) {
+ if (!QSymbianSocketManager::instance().lookupSocket(socketDescriptor, nativeSocket)) {
+ setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
+ return false;
+ }
+ }
+
+ // Determine local address
+ TSockAddr addr;
+ nativeSocket.LocalName(addr);
+ getPortAndAddress(addr, &localPort, &localAddress);
+
+ // Determine protocol family
+ switch (addr.Family()) {
+ case KAfInet:
+ socketProtocol = QAbstractSocket::IPv4Protocol;
+ break;
+ case KAfInet6:
+ socketProtocol = QAbstractSocket::IPv6Protocol;
+ break;
+ default:
+ socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
+ break;
+ }
+
+ // Determine the remote address
+ nativeSocket.RemoteName(addr);
+ getPortAndAddress(addr, &peerPort, &peerAddress);
+
+ // Determine the socket type (UDP/TCP)
+ TProtocolDesc protocol;
+ TInt err = nativeSocket.Info(protocol);
+ if (err) {
+ setError(err);
+ return false;
+ } else {
+ switch (protocol.iProtocol) {
+ case KProtocolInetTcp:
+ socketType = QAbstractSocket::TcpSocket;
+ break;
+ case KProtocolInetUdp:
+ socketType = QAbstractSocket::UdpSocket;
+ break;
+ default:
+ socketType = QAbstractSocket::UnknownSocketType;
+ break;
+ }
+ }
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ QString socketProtocolStr = QLatin1String("UnknownProtocol");
+ if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QLatin1String("IPv4Protocol");
+ else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = QLatin1String("IPv6Protocol");
+
+ QString socketTypeStr = QLatin1String("UnknownSocketType");
+ if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QLatin1String("TcpSocket");
+ else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QLatin1String("UdpSocket");
+
+ qDebug("QSymbianSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
+ " peer == %s:%i, socket == %s - %s",
+ localAddress.toString().toLatin1().constData(), localPort,
+ peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
+ socketProtocolStr.toLatin1().constData());
+#endif
+ return true;
+}
+
+void QSymbianSocketEngine::close()
+{
+ if (!isValid())
+ return;
+ Q_D(QSymbianSocketEngine);
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::close()");
+#endif
+
+ if (d->readNotifier)
+ d->readNotifier->setEnabled(false);
+ if (d->writeNotifier)
+ d->writeNotifier->setEnabled(false);
+ if (d->exceptNotifier)
+ d->exceptNotifier->setEnabled(false);
+ if (d->asyncSelect) {
+ d->asyncSelect->deleteLater();
+ d->asyncSelect = 0;
+ }
+
+ //TODO: call nativeSocket.Shutdown(EImmediate) in some cases?
+ if (d->socketType == QAbstractSocket::UdpSocket) {
+ //TODO: Close hangs without this, but only for UDP - why?
+ TRequestStatus stat;
+ d->nativeSocket.Shutdown(RSocket::EImmediate, stat);
+ User::WaitForRequest(stat);
+ }
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << "QSymbianSocketEngine::close - closing socket" << d->nativeSocket.SubSessionHandle() << d->socketDescriptor;
+#endif
+ //remove must come before close to avoid a race where another thread gets the old subsession handle
+ //reused & asserts when calling QSymbianSocketManager::instance->addSocket
+ QSymbianSocketManager::instance().removeSocket(d->nativeSocket);
+ d->nativeSocket.Close();
+ d->socketDescriptor = -1;
+
+ d->socketState = QAbstractSocket::UnconnectedState;
+ d->hasSetSocketError = false;
+ d->localPort = 0;
+ d->localAddress.clear();
+ d->peerPort = 0;
+ d->peerAddress.clear();
+ if (d->readNotifier) {
+ qDeleteInEventHandler(d->readNotifier);
+ d->readNotifier = 0;
+ }
+ if (d->writeNotifier) {
+ qDeleteInEventHandler(d->writeNotifier);
+ d->writeNotifier = 0;
+ }
+ if (d->exceptNotifier) {
+ qDeleteInEventHandler(d->exceptNotifier);
+ d->exceptNotifier = 0;
+ }
+}
+
+qint64 QSymbianSocketEngine::write(const char *data, qint64 len)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::write(), -1);
+ Q_CHECK_STATE(QSymbianSocketEngine::write(), QAbstractSocket::ConnectedState, -1);
+ TPtrC8 buffer((TUint8*)data, (int)len);
+ TSockXfrLength sentBytes = 0;
+ TRequestStatus status;
+ d->nativeSocket.Send(buffer, 0, status, sentBytes);
+ User::WaitForRequest(status); //TODO: on emulator this blocks for write >16kB (non blocking IO not implemented properly?)
+ TInt err = status.Int();
+
+ if (err) {
+ switch (err) {
+ case KErrDisconnected:
+ case KErrEof:
+ sentBytes = -1;
+ d->setError(QAbstractSocket::RemoteHostClosedError, d->RemoteHostClosedErrorString);
+ close();
+ break;
+ case KErrTooBig:
+ d->setError(QAbstractSocket::DatagramTooLargeError, d->DatagramTooLargeErrorString);
+ break;
+ case KErrWouldBlock:
+ break;
+ default:
+ sentBytes = -1;
+ d->setError(err);
+ close();
+ break;
+ }
+ }
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::write(%p \"%s\", %llu) == %i",
+ data, qt_prettyDebug(data, qMin((int) len, 16),
+ (int) len).data(), len, (int) sentBytes());
+#endif
+
+ return qint64(sentBytes());
+}
+/*
+*/
+qint64 QSymbianSocketEngine::read(char *data, qint64 maxSize)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::read(), -1);
+ Q_CHECK_STATES(QSymbianSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1);
+
+ TPtr8 buffer((TUint8*)data, (int)maxSize);
+ TSockXfrLength received = 0;
+ TRequestStatus status;
+ TSockAddr dummy;
+ if (d->socketType == QAbstractSocket::UdpSocket) {
+ //RecvOneOrMore() can only be used with stream-interfaced connected sockets; datagram interface sockets will return KErrNotSupported.
+ d->nativeSocket.RecvFrom(buffer, dummy, 0, status);
+ } else {
+ d->nativeSocket.RecvOneOrMore(buffer, 0, status, received);
+ }
+ User::WaitForRequest(status); //Non blocking receive
+ TInt err = status.Int();
+ int r = buffer.Length();
+
+ if (err == KErrWouldBlock) {
+ // No data was available for reading
+ r = -2;
+ } else if (err != KErrNone) {
+ d->setError(err);
+ close();
+ r = -1;
+ }
+
+#if defined (QNATIVESOCKETENGINE_DEBUG)
+ qDebug("QSymbianSocketEngine::read(%p \"%s\", %llu) == %i (err = %d)",
+ data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(),
+ maxSize, r, err);
+#endif
+
+ return qint64(r);
+}
+
+int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
+{
+ bool readyRead = false;
+ bool readyWrite = false;
+ if (selectForRead)
+ return nativeSelect(timeout, true, false, &readyRead, &readyWrite);
+ else
+ return nativeSelect(timeout, false, true, &readyRead, &readyWrite);
+}
+
+/*!
+ \internal
+ \param timeout timeout in milliseconds
+ \param checkRead caller is interested if the socket is ready to read
+ \param checkWrite caller is interested if the socket is ready for write
+ \param selectForRead (out) should set to true if ready to read
+ \param selectForWrite (out) should set to true if ready to write
+ \return 0 on timeout, >0 on success, <0 on error
+ */
+int QSymbianSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
+ bool *selectForRead, bool *selectForWrite) const
+{
+ //cancel asynchronous notifier (only one IOCTL allowed at a time)
+ if (asyncSelect)
+ asyncSelect->Cancel();
+
+ TPckgBuf<TUint> selectFlags;
+ selectFlags() = KSockSelectExcept;
+ if (checkRead)
+ selectFlags() |= KSockSelectRead;
+ if (checkWrite)
+ selectFlags() |= KSockSelectWrite;
+ TRequestStatus selectStat;
+ nativeSocket.Ioctl(KIOctlSelect, selectStat, &selectFlags, KSOLSocket);
+
+ if (timeout < 0)
+ User::WaitForRequest(selectStat); //negative means no timeout
+ else {
+ if (!selectTimer.Handle())
+ qt_symbian_throwIfError(selectTimer.CreateLocal());
+ TRequestStatus timerStat;
+ selectTimer.HighRes(timerStat, timeout * 1000);
+ User::WaitForRequest(timerStat, selectStat);
+ if (selectStat == KRequestPending) {
+ nativeSocket.CancelIoctl();
+ //CancelIoctl completes the request (most likely with KErrCancel)
+ //We need to wait for this to keep the thread semaphore balanced (or active scheduler will panic)
+ User::WaitForRequest(selectStat);
+ //restart asynchronous notifier (only one IOCTL allowed at a time)
+ if (asyncSelect)
+ asyncSelect->IssueRequest();
+ return 0; //timeout
+ } else {
+ selectTimer.Cancel();
+ User::WaitForRequest(timerStat);
+ }
+ }
+
+ if (selectStat != KErrNone)
+ return selectStat.Int();
+ if (selectFlags() & KSockSelectExcept) {
+ TInt err;
+ nativeSocket.GetOpt(KSOSelectLastError, KSOLSocket, err);
+ //restart asynchronous notifier (only one IOCTL allowed at a time)
+ if (asyncSelect)
+ asyncSelect->IssueRequest(); //TODO: in error case should we restart or not?
+ return err;
+ }
+ if (checkRead && (selectFlags() & KSockSelectRead)) {
+ Q_ASSERT(selectForRead);
+ *selectForRead = true;
+ }
+ if (checkWrite && (selectFlags() & KSockSelectWrite)) {
+ Q_ASSERT(selectForWrite);
+ *selectForWrite = true;
+ }
+ //restart asynchronous notifier (only one IOCTL allowed at a time)
+ if (asyncSelect)
+ asyncSelect->IssueRequest();
+ return 1;
+}
+
+bool QSymbianSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::joinMulticastGroup(), false);
+ Q_CHECK_STATE(QSymbianSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
+ return d->multicastGroupMembershipHelper(groupAddress, iface, KSoIp6JoinGroup);
+}
+
+bool QSymbianSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::leaveMulticastGroup(), false);
+ Q_CHECK_STATE(QSymbianSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false);
+ return d->multicastGroupMembershipHelper(groupAddress, iface, KSoIp6LeaveGroup);
+}
+
+bool QSymbianSocketEnginePrivate::multicastGroupMembershipHelper(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface,
+ TUint operation)
+{
+ //TODO - untested
+ //translate address
+ TPckgBuf<TIp6Mreq> option;
+ Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
+ memcpy(option().iAddr.u.iAddr8, ip6.c, 16);
+ //translate interface
+ //TODO - can we just use iface.index() ?
+ TPckgBuf<TSoInetIfQuery> query;
+ query().iName = qt_QString2TPtrC(iface.name());
+ TInt err = nativeSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query);
+ if (err == KErrNone)
+ option().iInterface = query().iIndex;
+ else
+ option().iInterface = 0;
+ //join or leave group
+ return (KErrNone == nativeSocket.SetOpt(operation, KSolInetIp, option));
+}
+
+QNetworkInterface QSymbianSocketEngine::multicastInterface() const
+{
+ //TODO
+ const Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::multicastInterface(), QNetworkInterface());
+ Q_CHECK_TYPE(QSymbianSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface());
+ return QNetworkInterface();
+}
+
+bool QSymbianSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
+{
+ //TODO - this is possibly a unix'ism as the RConnection on which the socket was created is probably controlling this
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setMulticastInterface(), false);
+ Q_CHECK_TYPE(QSymbianSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false);
+ return false;
+}
+
+bool QSymbianSocketEnginePrivate::checkProxy(const QHostAddress &address)
+{
+ if (address == QHostAddress::LocalHost || address == QHostAddress::LocalHostIPv6)
+ return true;
+
+#if !defined(QT_NO_NETWORKPROXY)
+ QObject *parent = q_func()->parent();
+ QNetworkProxy proxy;
+ if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(parent)) {
+ proxy = socket->proxy();
+ } else if (QTcpServer *server = qobject_cast<QTcpServer *>(parent)) {
+ proxy = server->proxy();
+ } else {
+ // no parent -> no proxy
+ return true;
+ }
+
+ if (proxy.type() == QNetworkProxy::DefaultProxy)
+ proxy = QNetworkProxy::applicationProxy();
+
+ if (proxy.type() != QNetworkProxy::DefaultProxy &&
+ proxy.type() != QNetworkProxy::NoProxy) {
+ // QSymbianSocketEngine doesn't do proxies
+ setError(QAbstractSocket::UnsupportedSocketOperationError,
+ InvalidProxyTypeString);
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+// FIXME this is also in QNativeSocketEngine, unify it
+/*! \internal
+
+ Sets the error and error string if not set already. The only
+ interesting error is the first one that occurred, and not the last
+ one.
+*/
+void QSymbianSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const
+{
+ if (hasSetSocketError) {
+ // Only set socket errors once for one engine; expect the
+ // socket to recreate its engine after an error. Note: There's
+ // one exception: SocketError(11) bypasses this as it's purely
+ // a temporary internal error condition.
+ // Another exception is the way the waitFor*() functions set
+ // an error when a timeout occurs. After the call to setError()
+ // they reset the hasSetSocketError to false
+ return;
+ }
+ if (error != QAbstractSocket::SocketError(11))
+ hasSetSocketError = true;
+
+ socketError = error;
+
+ switch (errorString) {
+ case NonBlockingInitFailedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unable to initialize non-blocking socket");
+ break;
+ case BroadcastingInitFailedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unable to initialize broadcast socket");
+ break;
+ case NoIpV6ErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Attempt to use IPv6 socket on a platform with no IPv6 support");
+ break;
+ case RemoteHostClosedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("The remote host closed the connection");
+ break;
+ case TimeOutErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Network operation timed out");
+ break;
+ case ResourceErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Out of resources");
+ break;
+ case OperationUnsupportedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unsupported socket operation");
+ break;
+ case ProtocolUnsupportedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Protocol type not supported");
+ break;
+ case InvalidSocketErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Invalid socket descriptor");
+ break;
+ case HostUnreachableErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Host unreachable");
+ break;
+ case NetworkUnreachableErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Network unreachable");
+ break;
+ case AccessErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Permission denied");
+ break;
+ case ConnectionTimeOutErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Connection timed out");
+ break;
+ case ConnectionRefusedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Connection refused");
+ break;
+ case AddressInuseErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("The bound address is already in use");
+ break;
+ case AddressNotAvailableErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("The address is not available");
+ break;
+ case AddressProtectedErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("The address is protected");
+ break;
+ case DatagramTooLargeErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Datagram was too large to send");
+ break;
+ case SendDatagramErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unable to send a message");
+ break;
+ case ReceiveDatagramErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unable to receive a message");
+ break;
+ case WriteErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unable to write");
+ break;
+ case ReadErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Network error");
+ break;
+ case PortInuseErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Another socket is already listening on the same port");
+ break;
+ case NotSocketErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Operation on non-socket");
+ break;
+ case InvalidProxyTypeString:
+ socketErrorString = QSymbianSocketEngine::tr("The proxy type is invalid for this operation");
+ break;
+ case InvalidAddressErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("The address is invalid for this operation");
+ break;
+ case SessionNotOpenErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("The specified network session is not opened");
+ break;
+ case UnknownSocketErrorString:
+ socketErrorString = QSymbianSocketEngine::tr("Unknown error");
+ break;
+ }
+}
+
+void QSymbianSocketEnginePrivate::setError(TInt symbianError)
+{
+ switch (symbianError) {
+ case KErrDisconnected:
+ case KErrEof:
+ setError(QAbstractSocket::RemoteHostClosedError,
+ QSymbianSocketEnginePrivate::RemoteHostClosedErrorString);
+ break;
+ case KErrNetUnreach:
+ setError(QAbstractSocket::NetworkError,
+ QSymbianSocketEnginePrivate::NetworkUnreachableErrorString);
+ break;
+ case KErrHostUnreach:
+ setError(QAbstractSocket::NetworkError,
+ QSymbianSocketEnginePrivate::HostUnreachableErrorString);
+ break;
+ case KErrNoProtocolOpt:
+ setError(QAbstractSocket::NetworkError,
+ QSymbianSocketEnginePrivate::ProtocolUnsupportedErrorString);
+ break;
+ case KErrInUse:
+ setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
+ break;
+ case KErrPermissionDenied:
+ setError(QAbstractSocket::SocketAccessError, AccessErrorString);
+ break;
+ case KErrNotSupported:
+ setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
+ break;
+ case KErrNoMemory:
+ setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
+ break;
+ case KErrCouldNotConnect:
+ setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
+ break;
+ case KErrTimedOut:
+ setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
+ break;
+ case KErrBadName:
+ setError(QAbstractSocket::NetworkError, InvalidAddressErrorString);
+ break;
+ default:
+ socketError = QAbstractSocket::NetworkError;
+ socketErrorString = QSystemError(symbianError, QSystemError::NativeError).toString();
+ break;
+ }
+ hasSetSocketError = true;
+}
+
+class QReadNotifier : public QSocketNotifier
+{
+ friend class QAsyncSelect;
+public:
+ QReadNotifier(int fd, QSymbianSocketEngine *parent)
+ : QSocketNotifier(fd, QSocketNotifier::Read, parent)
+ { engine = parent; }
+protected:
+ bool event(QEvent *);
+
+ QSymbianSocketEngine *engine;
+};
+
+bool QReadNotifier::event(QEvent *e)
+{
+ if (e->type() == QEvent::SockAct) {
+ engine->readNotification();
+ return true;
+ }
+ return QSocketNotifier::event(e);
+}
+
+bool QSymbianSocketEngine::isReadNotificationEnabled() const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isReadNotificationEnabled(), false);
+ return d->readNotifier && d->readNotifier->isEnabled();
+}
+
+void QSymbianSocketEngine::setReadNotificationEnabled(bool enable)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setReadNotificationEnabled(), Q_VOID);
+ if (d->readNotifier) {
+ d->readNotifier->setEnabled(enable);
+ } else if (enable && d->threadData->eventDispatcher) {
+ QReadNotifier *rn = new QReadNotifier(d->socketDescriptor, this);
+ d->readNotifier = rn;
+ if (!d->asyncSelect)
+ d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this));
+ d->asyncSelect->setReadNotifier(rn);
+ d->readNotifier->setEnabled(true);
+ }
+ // TODO: what do we do if event dispatcher doesn't exist yet?
+ if (d->asyncSelect)
+ d->asyncSelect->IssueRequest();
+}
+
+
+class QWriteNotifier : public QSocketNotifier
+{
+ friend class QAsyncSelect;
+public:
+ QWriteNotifier(int fd, QSymbianSocketEngine *parent)
+ : QSocketNotifier(fd, QSocketNotifier::Write, parent)
+ { engine = parent; }
+protected:
+ bool event(QEvent *);
+
+ QSymbianSocketEngine *engine;
+};
+
+bool QWriteNotifier::event(QEvent *e)
+{
+ if (e->type() == QEvent::SockAct) {
+ if (engine->state() == QAbstractSocket::ConnectingState)
+ engine->connectionNotification();
+ else
+ engine->writeNotification();
+ return true;
+ }
+ return QSocketNotifier::event(e);
+}
+
+bool QSymbianSocketEngine::isWriteNotificationEnabled() const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isWriteNotificationEnabled(), false);
+ return d->writeNotifier && d->writeNotifier->isEnabled();
+}
+
+void QSymbianSocketEngine::setWriteNotificationEnabled(bool enable)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setWriteNotificationEnabled(), Q_VOID);
+ if (d->writeNotifier) {
+ d->writeNotifier->setEnabled(enable);
+ } else if (enable && d->threadData->eventDispatcher) {
+ QWriteNotifier *wn = new QWriteNotifier(d->socketDescriptor, this);
+ d->writeNotifier = wn;
+ if (!(d->asyncSelect))
+ d->asyncSelect = q_check_ptr(new QAsyncSelect(d->threadData->eventDispatcher, d->nativeSocket, this));
+ d->asyncSelect->setWriteNotifier(wn);
+ d->writeNotifier->setEnabled(true);
+ }
+ // TODO: what do we do if event dispatcher doesn't exist yet?
+ if (d->asyncSelect)
+ d->asyncSelect->IssueRequest();
+}
+
+class QExceptionNotifier : public QSocketNotifier
+{
+ friend class QAsyncSelect;
+public:
+ QExceptionNotifier(int fd, QSymbianSocketEngine *parent)
+ : QSocketNotifier(fd, QSocketNotifier::Exception, parent) { engine = parent; }
+
+protected:
+ bool event(QEvent *);
+
+ QSymbianSocketEngine *engine;
+};
+
+bool QExceptionNotifier::event(QEvent *e)
+{
+ if (e->type() == QEvent::SockAct) {
+ if (engine->state() == QAbstractSocket::ConnectingState)
+ engine->connectionNotification();
+ else
+ engine->exceptionNotification();
+ return true;
+ }
+ return QSocketNotifier::event(e);
+}
+
+bool QSymbianSocketEngine::isExceptionNotificationEnabled() const
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::isExceptionNotificationEnabled(), false);
+ return d->exceptNotifier && d->exceptNotifier->isEnabled();
+ return false;
+}
+
+// FIXME do we really need this for symbian?
+void QSymbianSocketEngine::setExceptionNotificationEnabled(bool enable)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::setExceptionNotificationEnabled(), Q_VOID);
+ if (d->exceptNotifier) {
+ d->exceptNotifier->setEnabled(enable);
+ } else if (enable && d->threadData->eventDispatcher) {
+ QExceptionNotifier *en = new QExceptionNotifier(d->socketDescriptor, this);
+ d->exceptNotifier = en;
+ if (!(d->asyncSelect))
+ d->asyncSelect = q_check_ptr(new QAsyncSelect(d->threadData->eventDispatcher, d->nativeSocket, this));
+ d->asyncSelect->setExceptionNotifier(en);
+ d->writeNotifier->setEnabled(true);
+ }
+ if (d->asyncSelect)
+ d->asyncSelect->IssueRequest();
+}
+
+bool QSymbianSocketEngine::waitForRead(int msecs, bool *timedOut)
+{
+ Q_D(const QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::waitForRead(), false);
+ Q_CHECK_NOT_STATE(QSymbianSocketEngine::waitForRead(),
+ QAbstractSocket::UnconnectedState, false);
+
+ if (timedOut)
+ *timedOut = false;
+
+ int ret = d->nativeSelect(msecs, true);
+ if (ret == 0) {
+ if (timedOut)
+ *timedOut = true;
+ d->setError(QAbstractSocket::SocketTimeoutError,
+ d->TimeOutErrorString);
+ d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
+ return false;
+ } else if (state() == QAbstractSocket::ConnectingState) {
+ connectToHost(d->peerAddress, d->peerPort);
+ }
+
+ return ret > 0;
+}
+
+bool QSymbianSocketEngine::waitForWrite(int msecs, bool *timedOut)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::waitForWrite(), false);
+ Q_CHECK_NOT_STATE(QSymbianSocketEngine::waitForWrite(),
+ QAbstractSocket::UnconnectedState, false);
+
+ if (timedOut)
+ *timedOut = false;
+
+ int ret = d->nativeSelect(msecs, false);
+
+ if (ret == 0) {
+ if (timedOut)
+ *timedOut = true;
+ d->setError(QAbstractSocket::SocketTimeoutError,
+ d->TimeOutErrorString);
+ d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
+ return false;
+ } else if (state() == QAbstractSocket::ConnectingState) {
+ connectToHost(d->peerAddress, d->peerPort);
+ }
+
+ return ret > 0;
+}
+
+bool QSymbianSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
+ bool checkRead, bool checkWrite,
+ int msecs, bool *timedOut)
+{
+ Q_D(QSymbianSocketEngine);
+ Q_CHECK_VALID_SOCKETLAYER(QSymbianSocketEngine::waitForWrite(), false);
+ Q_CHECK_NOT_STATE(QSymbianSocketEngine::waitForReadOrWrite(),
+ QAbstractSocket::UnconnectedState, false);
+
+ int ret = d->nativeSelect(msecs, checkRead, checkWrite, readyToRead, readyToWrite);
+
+ if (ret == 0) {
+ if (timedOut)
+ *timedOut = true;
+ d->setError(QAbstractSocket::SocketTimeoutError,
+ d->TimeOutErrorString);
+ d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
+ return false;
+ } else if (state() == QAbstractSocket::ConnectingState) {
+ connectToHost(d->peerAddress, d->peerPort);
+ }
+
+ return ret > 0;
+}
+
+qint64 QSymbianSocketEngine::bytesToWrite() const
+{
+ // This is what the QNativeSocketEngine does
+ return 0;
+}
+
+//TODO: is defining PostThreadChangeEvent as QEvent::User + 1 safe?
+//TODO: would QMetaObject::invokeMethod(obj, "postThreadChangeSlot", Qt::QueuedConnection) be better?
+//TODO: if QTBUG-16787 is implemented, use that instead
+bool QSymbianSocketEngine::event(QEvent* ev)
+{
+ Q_D(QSymbianSocketEngine);
+ switch (ev->type()) {
+ case QEvent::ThreadChange:
+ if (d->asyncSelect) {
+ delete d->asyncSelect;
+ d->asyncSelect = 0;
+ QEvent *postThreadChangeEvent = new QEvent(PostThreadChangeEvent);
+ QCoreApplication::postEvent(this, postThreadChangeEvent);
+ }
+ return true;
+ case PostThreadChangeEvent:
+ // recreate select in new thread
+ d->asyncSelect = q_check_ptr(new QAsyncSelect(0, d->nativeSocket, this));
+ if (d->readNotifier) {
+ d->asyncSelect->setReadNotifier(static_cast<QReadNotifier*>(d->readNotifier));
+ setReadNotificationEnabled(d->readNotifier->isEnabled());
+ }
+ if (d->writeNotifier) {
+ d->asyncSelect->setWriteNotifier(static_cast<QWriteNotifier*>(d->writeNotifier));
+ setReadNotificationEnabled(d->writeNotifier->isEnabled());
+ }
+ if (d->exceptNotifier) {
+ d->asyncSelect->setExceptionNotifier(static_cast<QExceptionNotifier*>(d->exceptNotifier));
+ setReadNotificationEnabled(d->exceptNotifier->isEnabled());
+ }
+ return true;
+ }
+ return QAbstractSocketEngine::event(ev);
+}
+
+QAsyncSelect::QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent)
+ : CActive(CActive::EPriorityStandard),
+ m_inSocketEvent(false),
+ m_deleteLater(false),
+ m_socket(sock),
+ m_selectFlags(0),
+ engine(parent)
+{
+ CActiveScheduler::Add(this);
+}
+
+QAsyncSelect::~QAsyncSelect()
+{
+ Cancel();
+}
+
+void QAsyncSelect::DoCancel()
+{
+ m_socket.CancelIoctl();
+}
+
+void QAsyncSelect::RunL()
+{
+ QT_TRYCATCH_LEAVING(run());
+}
+
+//RunError is called by the active scheduler if RunL leaves.
+//Typically this will happen if a std::bad_alloc propagates down from the application
+TInt QAsyncSelect::RunError(TInt aError)
+{
+ if (engine) {
+ QT_TRY {
+ engine->d_func()->setError(aError);
+ QEvent e(QEvent::SockAct);
+ if (iExcN)
+ iExcN->event(&e);
+ if (iReadN)
+ iReadN->event(&e);
+ }
+ QT_CATCH(...) {}
+ }
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug() << "QAsyncSelect::RunError" << aError;
+#endif
+ return KErrNone;
+}
+
+void QAsyncSelect::run()
+{
+ //TODO: block when event loop demands it
+ //if (maybeQueueForLater())
+ // return;
+ m_inSocketEvent = true;
+ m_selectBuf() &= m_selectFlags; //the select ioctl reports everything, so mask to only what we requested
+ //KSockSelectReadContinuation is for reading datagrams in a mode that doesn't discard when the
+ //datagram is larger than the read buffer - Qt doesn't need to use this.
+ if (iReadN && ((m_selectBuf() & KSockSelectRead) || iStatus != KErrNone)) {
+ QEvent e(QEvent::SockAct);
+ iReadN->event(&e);
+ }
+ if (iWriteN && ((m_selectBuf() & KSockSelectWrite) || iStatus != KErrNone)) {
+ QEvent e(QEvent::SockAct);
+ iWriteN->event(&e);
+ }
+ if (iExcN && ((m_selectBuf() & KSockSelectExcept) || iStatus != KErrNone)) {
+ QEvent e(QEvent::SockAct);
+ iExcN->event(&e);
+ }
+ m_inSocketEvent = false;
+ if (m_deleteLater) {
+ delete this;
+ return;
+ }
+ // select again (unless disabled by one of the callbacks)
+ IssueRequest();
+}
+
+void QAsyncSelect::deleteLater()
+{
+ if (m_inSocketEvent) {
+ iExcN = 0;
+ iReadN = 0;
+ iWriteN = 0;
+ engine = 0;
+ m_deleteLater = true;
+ } else {
+ delete this;
+ }
+}
+
+void QAsyncSelect::IssueRequest()
+{
+ if (m_inSocketEvent)
+ return; //prevent thrashing during a callback - socket engine enables/disables multiple notifiers
+ TUint selectFlags = 0;
+ if (iReadN && iReadN->isEnabled())
+ selectFlags |= KSockSelectRead;
+ if (iWriteN && iWriteN->isEnabled())
+ selectFlags |= KSockSelectWrite;
+ if (iExcN && iExcN->isEnabled())
+ selectFlags |= KSockSelectExcept;
+ if (selectFlags != m_selectFlags) {
+ Cancel();
+ m_selectFlags = selectFlags;
+ }
+ if (m_selectFlags && !IsActive()) {
+ //always request errors (write notification does not complete on connect errors)
+ m_selectBuf() = m_selectFlags | KSockSelectExcept;
+ m_socket.Ioctl(KIOctlSelect, iStatus, &m_selectBuf, KSOLSocket);
+ SetActive();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/socket/qsymbiansocketengine_p.h b/src/network/socket/qsymbiansocketengine_p.h
new file mode 100644
index 0000000..bc39450
--- /dev/null
+++ b/src/network/socket/qsymbiansocketengine_p.h
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSYMBIANSOCKETENGINE_P_H
+#define QSYMBIANSOCKETENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+#include "QtNetwork/qhostaddress.h"
+#include "private/qabstractsocketengine_p.h"
+#include "qplatformdefs.h"
+
+#include <private/qeventdispatcher_symbian_p.h>
+#include <unistd.h>
+#include <es_sock.h>
+#include <in_sock.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QSymbianSocketEnginePrivate;
+class QNetworkInterface;
+
+class Q_AUTOTEST_EXPORT QSymbianSocketEngine : public QAbstractSocketEngine
+{
+ Q_OBJECT
+ friend class QAsyncSelect;
+public:
+ QSymbianSocketEngine(QObject *parent = 0);
+ ~QSymbianSocketEngine();
+
+ bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol);
+ bool initialize(int socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState);
+
+ int socketDescriptor() const;
+
+ bool isValid() const;
+
+ bool connectToHost(const QHostAddress &address, quint16 port);
+ bool connectToHostByName(const QString &name, quint16 port);
+ bool bind(const QHostAddress &address, quint16 port);
+ bool listen();
+ int accept();
+ void close();
+
+ bool joinMulticastGroup(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface);
+ bool leaveMulticastGroup(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface);
+ QNetworkInterface multicastInterface() const;
+ bool setMulticastInterface(const QNetworkInterface &iface);
+
+ qint64 bytesAvailable() const;
+
+ qint64 read(char *data, qint64 maxlen);
+ qint64 write(const char *data, qint64 len);
+
+ qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
+ quint16 *port = 0);
+ qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr,
+ quint16 port);
+ bool hasPendingDatagrams() const;
+ qint64 pendingDatagramSize() const;
+
+ qint64 bytesToWrite() const;
+
+ qint64 receiveBufferSize() const;
+ void setReceiveBufferSize(qint64 bufferSize);
+
+ qint64 sendBufferSize() const;
+ void setSendBufferSize(qint64 bufferSize);
+
+ int option(SocketOption option) const;
+ bool setOption(SocketOption option, int value);
+
+ bool waitForRead(int msecs = 30000, bool *timedOut = 0);
+ bool waitForWrite(int msecs = 30000, bool *timedOut = 0);
+ bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
+ bool checkRead, bool checkWrite,
+ int msecs = 30000, bool *timedOut = 0);
+
+ bool isReadNotificationEnabled() const;
+ void setReadNotificationEnabled(bool enable);
+ bool isWriteNotificationEnabled() const;
+ void setWriteNotificationEnabled(bool enable);
+ bool isExceptionNotificationEnabled() const;
+ void setExceptionNotificationEnabled(bool enable);
+
+ bool event(QEvent* ev);
+
+ static const QEvent::Type PostThreadChangeEvent = (QEvent::Type)(QEvent::User + 1);
+
+public Q_SLOTS:
+ // TODO: Why do we do this? This is private Qt implementation stuff anyway, no need for it
+ // non-virtual override;
+ void connectionNotification();
+
+private:
+ Q_DECLARE_PRIVATE(QSymbianSocketEngine)
+ Q_DISABLE_COPY(QSymbianSocketEngine)
+};
+
+class QSocketNotifier;
+
+class QReadNotifier;
+class QWriteNotifier;
+class QExceptionNotifier;
+class QAsyncSelect : public CActive
+{
+public:
+ QAsyncSelect(QAbstractEventDispatcher *dispatcher, RSocket& sock, QSymbianSocketEngine *parent);
+ ~QAsyncSelect();
+
+ void deleteLater();
+ void IssueRequest();
+
+ void refresh();
+
+ void setReadNotifier(QReadNotifier *rn) { iReadN = rn; }
+ void setWriteNotifier(QWriteNotifier *wn) { iWriteN = wn; }
+ void setExceptionNotifier(QExceptionNotifier *en) { iExcN = en; }
+
+protected:
+ void DoCancel();
+ void RunL();
+ void run();
+ TInt RunError(TInt aError);
+
+private:
+ QReadNotifier* iReadN;
+ QWriteNotifier* iWriteN;
+ QExceptionNotifier* iExcN;
+ bool m_inSocketEvent;
+ bool m_deleteLater;
+ RSocket &m_socket;
+
+ TUint m_selectFlags;
+ TPckgBuf<TUint> m_selectBuf; //in & out IPC buffer
+ QSymbianSocketEngine *engine;
+};
+
+class QSymbianSocketEnginePrivate : public QAbstractSocketEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QSymbianSocketEngine)
+public:
+ QSymbianSocketEnginePrivate();
+ ~QSymbianSocketEnginePrivate();
+
+ int socketDescriptor;
+ mutable RSocket nativeSocket;
+ // From QtCore:
+ RSocketServ& socketServer;
+ mutable RTimer selectTimer;
+
+ QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
+ QAsyncSelect* asyncSelect;
+
+ // FIXME this is duplicated from qnativesocketengine_p.h
+ enum ErrorString {
+ NonBlockingInitFailedErrorString,
+ BroadcastingInitFailedErrorString,
+ NoIpV6ErrorString,
+ RemoteHostClosedErrorString,
+ TimeOutErrorString,
+ ResourceErrorString,
+ OperationUnsupportedErrorString,
+ ProtocolUnsupportedErrorString,
+ InvalidSocketErrorString,
+ HostUnreachableErrorString,
+ NetworkUnreachableErrorString,
+ AccessErrorString,
+ ConnectionTimeOutErrorString,
+ ConnectionRefusedErrorString,
+ AddressInuseErrorString,
+ AddressNotAvailableErrorString,
+ AddressProtectedErrorString,
+ DatagramTooLargeErrorString,
+ SendDatagramErrorString,
+ ReceiveDatagramErrorString,
+ WriteErrorString,
+ ReadErrorString,
+ PortInuseErrorString,
+ NotSocketErrorString,
+ InvalidProxyTypeString,
+ //symbian specific
+ InvalidAddressErrorString,
+ SessionNotOpenErrorString,
+
+ UnknownSocketErrorString = -1
+ };
+ void setError(QAbstractSocket::SocketError error, ErrorString errorString) const;
+
+ void getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr);
+ void setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr);
+ void setError(TInt symbianError);
+
+ int nativeSelect(int timeout, bool selectForRead) const;
+ int nativeSelect(int timeout, bool checkRead, bool checkWrite,
+ bool *selectForRead, bool *selectForWrite) const;
+
+ bool createNewSocket(QAbstractSocket::SocketType socketType,
+ QAbstractSocket::NetworkLayerProtocol socketProtocol);
+
+ bool checkProxy(const QHostAddress &address);
+ bool fetchConnectionParameters();
+
+ bool multicastGroupMembershipHelper(const QHostAddress &groupAddress,
+ const QNetworkInterface &iface,
+ TUint operation);
+ static bool translateSocketOption(QAbstractSocketEngine::SocketOption opt, TUint &n, TUint &level);
+};
+
+QT_END_NAMESPACE
+
+#endif // QSYMBIANSOCKETENGINE_P_H
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index 98c05dd..6b012db 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -105,7 +105,7 @@
#include "qhostaddress.h"
#include "qlist.h"
#include "qpointer.h"
-#include "qnativesocketengine_p.h"
+#include "qabstractsocketengine_p.h"
#include "qtcpserver.h"
#include "qtcpsocket.h"
#include "qnetworkproxy.h"
@@ -287,6 +287,10 @@ bool QTcpServer::listen(const QHostAddress &address, quint16 port)
delete d->socketEngine;
d->socketEngine = QAbstractSocketEngine::createSocketEngine(QAbstractSocket::TcpSocket, proxy, this);
+#ifndef QT_NO_BEARERMANAGEMENT
+ //copy network session down to the socket engine (if it has been set)
+ d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
+#endif
if (!d->socketEngine) {
d->serverSocketError = QAbstractSocket::UnsupportedSocketOperationError;
d->serverSocketErrorString = tr("Operation on socket is not supported");
@@ -412,6 +416,10 @@ bool QTcpServer::setSocketDescriptor(int socketDescriptor)
if (d->socketEngine)
delete d->socketEngine;
d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this);
+#ifndef QT_NO_BEARERMANAGEMENT
+ //copy network session down to the socket engine (if it has been set)
+ d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
+#endif
if (!d->socketEngine->initialize(socketDescriptor, QAbstractSocket::ListeningState)) {
d->serverSocketError = d->socketEngine->error();
d->serverSocketErrorString = d->socketEngine->errorString();
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index 6a62b12..4334f68 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -504,16 +504,6 @@ 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 f2262fe..32be429 100644
--- a/src/network/socket/socket.pri
+++ b/src/network/socket/socket.pri
@@ -1,7 +1,6 @@
# Qt network socket
HEADERS += socket/qabstractsocketengine_p.h \
- socket/qnativesocketengine_p.h \
socket/qhttpsocketengine_p.h \
socket/qsocks5socketengine_p.h \
socket/qabstractsocket.h \
@@ -15,7 +14,6 @@ HEADERS += socket/qabstractsocketengine_p.h \
socket/qlocalsocket_p.h
SOURCES += socket/qabstractsocketengine.cpp \
- socket/qnativesocketengine.cpp \
socket/qhttpsocketengine.cpp \
socket/qsocks5socketengine.cpp \
socket/qabstractsocket.cpp \
@@ -25,11 +23,26 @@ SOURCES += socket/qabstractsocketengine.cpp \
socket/qlocalsocket.cpp \
socket/qlocalserver.cpp
-unix:!symbian:SOURCES += socket/qnativesocketengine_unix.cpp
-symbian:SOURCES += socket/qnativesocketengine_symbian.cpp
-unix:SOURCES += \
+# On Symbian we use QSymbianSocketEngine
+symbian:SOURCES += socket/qsymbiansocketengine.cpp
+symbian:HEADERS += socket/qsymbiansocketengine_p.h
+# On others we use QNativeSocketEngine
+!symbian:SOURCES += socket/qnativesocketengine.cpp
+!symbian:HEADERS += socket/qnativesocketengine_p.h
+
+unix:!symbian: {
+ SOURCES += socket/qnativesocketengine_unix.cpp \
socket/qlocalsocket_unix.cpp \
socket/qlocalserver_unix.cpp
+}
+
+symbian: {
+ SOURCES += socket/qlocalsocket_tcp.cpp \
+ socket/qlocalserver_tcp.cpp
+
+ DEFINES += QT_LOCALSOCKET_TCP
+}
+
unix:HEADERS += \
socket/qnet_unix_p.h