From 5c7c12602f10be7625ee38efb31e1a8b5cb66c5b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 21 Sep 2010 17:42:14 +0100 Subject: Prototype socket manager To enable passing socket handles around as integers, need a two way mapping with RSocket. It's in corelib because of QSocketNotifier. This is also a convenient place to host the global RSocketServ session. Reviewed-By: Markus Goetz --- src/corelib/io/io.pri | 2 +- src/corelib/kernel/qcore_symbian_p.cpp | 72 ++++++++++++++++++++++++++++++++++ src/corelib/kernel/qcore_symbian_p.h | 67 +++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index cfb40bc..6cf55e7 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -95,6 +95,6 @@ win32 { SOURCES += io/qfilesystemwatcher_symbian.cpp HEADERS += io/qfilesystemwatcher_symbian_p.h INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE - LIBS += -lplatformenv + LIBS += -lplatformenv -lesock } } diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index df1c1ef..29996a4 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -210,4 +210,76 @@ Q_CORE_EXPORT RFs& qt_s60GetRFs() return qt_s60_RFsSession()->GetRFs(); } +QSymbianSocketManager::QSymbianSocketManager() : + iNextSocket(0) +{ + qt_symbian_throwIfError(iSocketServ.Connect()); + qt_symbian_throwIfError(iSocketServ.ShareAuto()); +} + +QSymbianSocketManager::~QSymbianSocketManager() +{ + iSocketServ.Close(); + if(!socketMap.isEmpty()) { + qWarning("leaked %d sockets on exit", socketMap.count()); + } +} + +RSocketServ& QSymbianSocketManager::getSocketServer() { + return iSocketServ; +} + +int QSymbianSocketManager::addSocket(RSocket* sock) { + QMutexLocker l(&iMutex); + Q_ASSERT(!socketMap.contains(sock)); + if(socketMap.contains(sock)) + return socketMap.value(sock); + // allocate socket number + int guard = 0; + while(reverseSocketMap.contains(iNextSocket)) { + iNextSocket++; + iNextSocket %= max_sockets; + guard++; + if(guard > max_sockets) + return -1; + } + int id = iNextSocket; + + socketMap[sock] = id; + reverseSocketMap[id] = sock; + return id + socket_offset; +} + +bool QSymbianSocketManager::removeSocket(RSocket* sock) { + QMutexLocker l(&iMutex); + if(!socketMap.contains(sock)) + return false; + int id = socketMap.value(sock); + socketMap.remove(sock); + reverseSocketMap.remove(id); + return true; +} + +int QSymbianSocketManager::lookupSocket(RSocket* sock) const { + QMutexLocker l(&iMutex); + if(!socketMap.contains(sock)) + return -1; + int id = socketMap.value(sock); + return id + socket_offset; +} + +RSocket* QSymbianSocketManager::lookupSocket(int fd) const { + QMutexLocker l(&iMutex); + int id = fd + socket_offset; + if(!reverseSocketMap.contains(id)) + return 0; + return reverseSocketMap.value(id); +} + +Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager); + +QSymbianSocketManager& QSymbianSocketManager::instance() +{ + return *(qt_symbianSocketManager()); +} QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index 4a515ce..b6cba6e 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -55,10 +55,12 @@ #include #include +#include #include #include #include #include +#include #define QT_LSTRING2(x) L##x #define QT_LSTRING(x) QT_LSTRING2(x) @@ -154,10 +156,75 @@ enum S60PluginFuncOrdinals Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal); Q_CORE_EXPORT RFs& qt_s60GetRFs(); +Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer(); // Defined in qlocale_symbian.cpp. Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code); +/*! + \internal + This class exists in QtCore for the benefit of QSocketNotifier, which uses integer + file descriptors in its public API. + So we need a way to map between int and RSocket. + Additionally, it is used to host the global RSocketServ session +*/ +class Q_CORE_EXPORT QSymbianSocketManager +{ +public: + QSymbianSocketManager(); + ~QSymbianSocketManager(); + + /*! + \internal + \return handle to the socket server + */ + RSocketServ& getSocketServer(); + /*! + \internal + Adds a symbian socket to the global map + \param an open socket + \return pseudo file descriptor, -1 if out of resources + */ + int addSocket(RSocket *sock); + /*! + \internal + Removes a symbian socket from the global map + \param an open socket + \return true if the socket was in the map + */ + bool removeSocket(RSocket *sock); + /*! + \internal + Get pseudo file descriptor for a socket + \param an open socket + \return integer handle, or -1 if not in map + */ + int lookupSocket(RSocket *sock) const; + /*! + \internal + Get socket for a pseudo file descriptor + \param an open socket fd + \return socket handle or NULL if not in map + */ + RSocket *lookupSocket(int fd) const; + + /*! + \internal + Gets a reference to the singleton socket manager + */ + static QSymbianSocketManager& instance(); +private: + int allocateSocket(); + + const static int max_sockets = 0x20000; //covers all TCP and UDP ports, probably run out of memory first + const static int socket_offset = 0x40000000; //hacky way of separating sockets from file descriptors + int iNextSocket; + QHash socketMap; + QHash reverseSocketMap; + mutable QMutex iMutex; + RSocketServ iSocketServ; +}; + QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12