summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2010-09-22 11:04:01 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2010-12-01 15:44:50 (GMT)
commit9470dfb8b116cde0d08670d05ded530bad264c6c (patch)
treeec7f90873c18842d6d8890a05005507b3c55a339 /src/network/socket
parent5c7c12602f10be7625ee38efb31e1a8b5cb66c5b (diff)
downloadQt-9470dfb8b116cde0d08670d05ded530bad264c6c.zip
Qt-9470dfb8b116cde0d08670d05ded530bad264c6c.tar.gz
Qt-9470dfb8b116cde0d08670d05ded530bad264c6c.tar.bz2
Address some of the easier TODOs in native socket engine
Reviewed-By: Markus Goetz
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qnativesocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_symbian.cpp187
2 files changed, 105 insertions, 86 deletions
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 72ebd9f..ceecfeb 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -64,6 +64,7 @@
#include <private/qeventdispatcher_symbian_p.h>
#include <unistd.h>
#include <es_sock.h>
+#include <in_sock.h>
#endif
QT_BEGIN_NAMESPACE
@@ -201,6 +202,7 @@ public:
mutable RSocket nativeSocket;
RSocketServ socketServer; //TODO: shared ref
RConnection connection; //TODO: shared ref
+ mutable RTimer selectTimer;
#endif
QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
@@ -240,6 +242,8 @@ public:
};
#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;
diff --git a/src/network/socket/qnativesocketengine_symbian.cpp b/src/network/socket/qnativesocketengine_symbian.cpp
index f2aeee9..788e58a 100644
--- a/src/network/socket/qnativesocketengine_symbian.cpp
+++ b/src/network/socket/qnativesocketengine_symbian.cpp
@@ -48,6 +48,7 @@
#include "qvarlengtharray.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
@@ -93,60 +94,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
}
#endif
-static void qt_ignore_sigpipe()
-{
-#ifndef Q_NO_POSIX_SIGNALS
- // Set to ignore SIGPIPE once only.
- static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
- if (atom.testAndSetRelaxed(0, 1)) {
- struct sigaction noaction;
- memset(&noaction, 0, sizeof(noaction));
- noaction.sa_handler = SIG_IGN;
- ::sigaction(SIGPIPE, &noaction, 0);
- }
-#else
- // Posix signals are not supported by the underlying platform
- // so we don't need to ignore sigpipe signal explicitly
-#endif
-}
-
-/*
- Extracts the port and address from a sockaddr, and stores them in
- \a port and \a addr if they are non-null.
-*/
-static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr)
-{
-#if !defined(QT_NO_IPV6)
- if (s->a.sa_family == AF_INET6) {
- Q_IPV6ADDR tmp;
- memcpy(&tmp, &s->a6.sin6_addr, sizeof(tmp));
- if (addr) {
- QHostAddress tmpAddress;
- tmpAddress.setAddress(tmp);
- *addr = tmpAddress;
-#ifndef QT_NO_IPV6IFNAME
- char scopeid[IFNAMSIZ];
- if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
- addr->setScopeId(QLatin1String(scopeid));
- } else
-#endif
- addr->setScopeId(QString::number(s->a6.sin6_scope_id));
- }
- if (port)
- *port = ntohs(s->a6.sin6_port);
- return;
- }
-#endif
- if (port)
- *port = ntohs(s->a4.sin_port);
- if (addr) {
- QHostAddress tmpAddress;
- tmpAddress.setAddress(ntohl(s->a4.sin_addr.s_addr));
- *addr = tmpAddress;
- }
-}
-
-static inline void qt_socket_getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr)
+void QNativeSocketEnginePrivate::getPortAndAddress(const TInetAddr& a, quint16 *port, QHostAddress *addr)
{
#if !defined(QT_NO_IPV6)
if (a.Family() == KAfInet6) {
@@ -157,13 +105,12 @@ static inline void qt_socket_getPortAndAddress(const TInetAddr& a, quint16 *port
tmpAddress.setAddress(tmp);
*addr = tmpAddress;
#ifndef QT_NO_IPV6IFNAME
- char scopeid[IFNAMSIZ];
- //TODO: rather than using posix api, the symbian way is
- //to use GetOpt with TSoInetIfQuery and KSoInetIfQueryByIndex
- //which means this should be in a member function to have access to the nativeSocket
- if (::if_indextoname(a.Scope(), scopeid)) {
- addr->setScopeId(QLatin1String(scopeid));
- } else
+ 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()));
}
@@ -176,7 +123,7 @@ static inline void qt_socket_getPortAndAddress(const TInetAddr& a, quint16 *port
*port = a.Port();
if (addr) {
QHostAddress tmpAddress;
- tmpAddress.setAddress(a.Address()); //TODO: byte order ok?
+ tmpAddress.setAddress(a.Address());
*addr = tmpAddress;
}
}
@@ -218,7 +165,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
return false;
}
- socketDescriptor = nativeSocket.SubSessionHandle(); //TODO
+ socketDescriptor = QSymbianSocketManager::instance().addSocket(&nativeSocket);
return true;
}
@@ -245,15 +192,16 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
n = KSONonBlockingIO;
break;
case QNativeSocketEngine::BroadcastSocketOption:
- n = SO_BROADCAST; //TODO
- break;
+ return true; //symbian doesn't support or require this option
case QNativeSocketEngine::AddressReusable:
- n = SO_REUSEADDR; //TODO
+ level = KSolInetIp;
+ n = KSoReuseAddr;
break;
case QNativeSocketEngine::BindExclusively:
return true;
case QNativeSocketEngine::ReceiveOutOfBandData:
- n = SO_OOBINLINE; //TODO
+ level = KSolInetTcp;
+ n = KSoTcpOobInline;
break;
case QNativeSocketEngine::LowDelayOption:
level = KSolInetTcp;
@@ -297,18 +245,19 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
n = KSOSendBuf;
break;
case QNativeSocketEngine::BroadcastSocketOption:
- n = SO_BROADCAST; //TODO
- break;
+ return true;
case QNativeSocketEngine::NonBlockingSocketOption:
n = KSONonBlockingIO;
break;
case QNativeSocketEngine::AddressReusable:
- n = SO_REUSEADDR; //TODO
+ level = KSolInetIp;
+ n = KSoReuseAddr;
break;
case QNativeSocketEngine::BindExclusively:
return true;
case QNativeSocketEngine::ReceiveOutOfBandData:
- n = SO_OOBINLINE; //TODO
+ level = KSolInetTcp;
+ n = KSoTcpOobInline;
break;
case QNativeSocketEngine::LowDelayOption:
level = KSolInetTcp;
@@ -323,13 +272,19 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
return (KErrNone == nativeSocket.SetOpt(n, level, v));
}
-static TInetAddr qt_QHostAddressToTInetAddr(const QHostAddress &addr)
+void QNativeSocketEnginePrivate::setPortAndAddress(TInetAddr& nativeAddr, quint16 port, const QHostAddress &addr)
{
- TInetAddr nativeAddr;
+ nativeAddr.SetPort(port);
#if !defined(QT_NO_IPV6)
if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
#ifndef QT_NO_IPV6IFNAME
- nativeAddr.SetScope(::if_nametoindex(addr.scopeId().toLatin1().data())); //TODO - if_nametoindex
+ 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
@@ -344,7 +299,6 @@ static TInetAddr qt_QHostAddressToTInetAddr(const QHostAddress &addr)
} else {
qWarning("unsupported network protocol (%d)", addr.protocol());
}
- return nativeAddr;
}
bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
@@ -353,8 +307,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
#endif
- TInetAddr nativeAddr = qt_QHostAddressToTInetAddr(addr);
- nativeAddr.SetPort(port);
+ 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);
@@ -413,8 +367,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
{
- TInetAddr nativeAddr = qt_QHostAddressToTInetAddr(address);
- nativeAddr.SetPort(port);
+ TInetAddr nativeAddr;
+ setPortAndAddress(nativeAddr, port, address);
TInt err = nativeSocket.Bind(nativeAddr);
@@ -535,7 +489,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
if (status.Int()) {
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
} else if (port || address) {
- qt_socket_getPortAndAddress(addr, port, address);
+ getPortAndAddress(addr, port, address);
}
#if defined (QNATIVESOCKETENGINE_DEBUG)
@@ -555,9 +509,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
const QHostAddress &host, quint16 port)
{
TPtrC8 buffer((TUint8*)data, (int)len);
- TInetAddr addr = qt_QHostAddressToTInetAddr(host);
+ TInetAddr addr;
+ setPortAndAddress(addr, port, host);
TSockXfrLength sentBytes;
- addr.SetPort(port);
TRequestStatus status; //TODO: OMG sync send!
nativeSocket.SendTo(buffer, addr, 0, status, sentBytes);
User::WaitForRequest(status);
@@ -592,12 +546,17 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
if (socketDescriptor == -1)
return false;
- //TODO: work out how to initialise nativeSocket from socketDescriptor
+ if (!nativeSocket.SubSessionHandle()) {
+ RSocket *s = QSymbianSocketManager::instance().lookupSocket(socketDescriptor);
+ if (!s)
+ return false;
+ nativeSocket = *s; //TODO: badwrongfun (address is different, so this is broken)
+ }
// Determine local address
TSockAddr addr;
nativeSocket.LocalName(addr);
- qt_socket_getPortAndAddress(addr, &localPort, &localAddress);
+ getPortAndAddress(addr, &localPort, &localAddress);
// Determine protocol family
switch (addr.Family()) {
@@ -616,7 +575,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
// Determine the remote address
nativeSocket.RemoteName(addr);
- qt_socket_getPortAndAddress(addr, &peerPort, &peerAddress);
+ getPortAndAddress(addr, &peerPort, &peerAddress);
// Determine the socket type (UDP/TCP)
TProtocolDesc protocol;
@@ -662,6 +621,7 @@ void QNativeSocketEnginePrivate::nativeClose()
//TODO: call nativeSocket.Shutdown(EImmediate) in some cases?
nativeSocket.Close();
+ QSymbianSocketManager::instance().removeSocket(&nativeSocket);
}
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
@@ -744,13 +704,68 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
{
-//TODO: implement
+ 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;
}
QT_END_NAMESPACE