From 916076bfec520210966f67ae211af65b21a29dac Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 24 Nov 2011 11:40:52 +0000 Subject: Symbian - prefer sessions started by this process to choose proxy When WLAN and 3G connections are both active, the proxy for the wrong connection may have been chosen in the case of plain sockets or QNetworkAccessManager with an invalid configuration. When enumarating active connections to choose a proxy, prefer a connection that was opened by this process. Task-number: QTBUG-22615 Task-number: ou1cimx1#930701 Reviewed-by: mread --- src/corelib/kernel/qcore_symbian_p.cpp | 32 ++++++++++++ src/corelib/kernel/qcore_symbian_p.h | 22 +++++++++ src/network/kernel/qnetworkproxy_symbian.cpp | 27 ++++++++++ .../bearer/symbian/qnetworksession_impl.cpp | 57 +++++++++++++++++----- src/plugins/bearer/symbian/qnetworksession_impl.h | 3 ++ src/s60installs/bwins/QtCoreu.def | 5 +- src/s60installs/eabi/QtCoreu.def | 5 +- 7 files changed, 137 insertions(+), 14 deletions(-) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 4f953a7..65ec3fe 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -246,6 +246,38 @@ RConnection* QSymbianSocketManager::defaultConnection() const return iDefaultConnection; } +void QSymbianSocketManager::addActiveConnection(TUint32 identifier) +{ + QMutexLocker l(&iMutex); + activeConnectionsMap[identifier]++; +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "addActiveConnection" << identifier << activeConnectionsMap[identifier]; +#endif +} + +void QSymbianSocketManager::removeActiveConnection(TUint32 identifier) +{ + QMutexLocker l(&iMutex); + int& val(activeConnectionsMap[identifier]); + Q_ASSERT(val > 0); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "removeActiveConnection" << identifier << val - 1; +#endif + if (val <= 1) + activeConnectionsMap.remove(identifier); + else + val--; +} + +QList QSymbianSocketManager::activeConnections() const +{ + QMutexLocker l(&iMutex); +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "activeConnections" << activeConnectionsMap.keys(); +#endif + return activeConnectionsMap.keys(); +} + Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager); QSymbianSocketManager& QSymbianSocketManager::instance() diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index a8f576d..6176ab5 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -247,6 +247,27 @@ public: /*! \internal + Add an opened connection to the active list + \param an open connection + */ + void addActiveConnection(TUint32 identifier); + + /*! + \internal + Remove a connection from the active list + \param a closed connection + */ + void removeActiveConnection(TUint32 identifier); + + /*! + \internal + Add an opened connection to the active list + \param an open connection + */ + QList activeConnections() const; + + /*! + \internal Gets a reference to the singleton socket manager */ static QSymbianSocketManager& instance(); @@ -258,6 +279,7 @@ private: int iNextSocket; QHash socketMap; QHash reverseSocketMap; + QHash activeConnectionsMap; mutable QMutex iMutex; RSocketServ iSocketServ; RConnection *iDefaultConnection; diff --git a/src/network/kernel/qnetworkproxy_symbian.cpp b/src/network/kernel/qnetworkproxy_symbian.cpp index 73068d6..e96c372 100644 --- a/src/network/kernel/qnetworkproxy_symbian.cpp +++ b/src/network/kernel/qnetworkproxy_symbian.cpp @@ -60,6 +60,7 @@ #include #include #include +#include using namespace CommsDat; @@ -73,6 +74,25 @@ public: void setIapId(TUint32 iapId) { valid = true; id = iapId; } bool isValid() { return valid; } TUint32 iapId() { return id; } + static SymbianIapId fromConfiguration(const QNetworkConfiguration& config) + { + SymbianIapId iapId; + // Note: the following code assumes that the identifier is in format + // I_xxxx where xxxx is the identifier of IAP. This is meant as a + // temporary solution until there is a support for returning + // implementation specific identifier. + const int generalPartLength = 2; + QString idString(config.identifier().mid(generalPartLength)); + bool success; + uint id = idString.toUInt(&success); + if (success) + iapId.setIapId(id); + else + qWarning() << "Failed to convert identifier to access point identifier: " + << config.identifier(); + return iapId; + } + private: bool valid; TUint32 id; @@ -122,9 +142,16 @@ QNetworkConfiguration SymbianProxyQuery::findCurrentConfigurationFromServiceNetw QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfigurationManager& configurationManager) { + QList openConfigurations = QSymbianSocketManager::instance().activeConnections(); QList activeConfigurations = configurationManager.allConfigurations( QNetworkConfiguration::Active); + for (int i = 0; i < activeConfigurations.count(); i++) { + // get first configuration which was opened by this process + if (openConfigurations.contains(SymbianIapId::fromConfiguration(activeConfigurations.at(i)).iapId())) + return activeConfigurations.at(i); + } if (activeConfigurations.count() > 0) { + // get first active configuration opened by any process return activeConfigurations.at(0); } else { // No active configurations, try default one diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index f5f71cf..58ce8fe 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -64,7 +64,7 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) ipConnectionNotifier(0), ipConnectionStarter(0), iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0), - iConnectInBackground(false), isOpening(false) + iConnectInBackground(false), iCurrentIap(0), isOpening(false) { #ifdef SNAP_FUNCTIONALITY_AVAILABLE @@ -77,6 +77,7 @@ QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine) void QNetworkSessionPrivateImpl::closeHandles() { QMutexLocker lock(&mutex); + updateCurrentIap(0); // Cancel Connection Progress Notifications first. // Note: ConnectionNotifier must be destroyed before RConnection::Close() // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification() @@ -637,6 +638,8 @@ void QNetworkSessionPrivateImpl::accept() QSymbianSocketManager::instance().setDefaultConnection(&iConnection); + updateCurrentIap(iNewRoamingIap); + newState(QNetworkSession::Connected, iNewRoamingIap); } #endif @@ -867,19 +870,31 @@ quint64 QNetworkSessionPrivateImpl::activeTime() const return startTime.secsTo(QDateTime::currentDateTime()); } -QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 iapId) const +bool QNetworkSessionPrivateImpl::activeIapId(TUint32& iapId) const { - if (iapId == 0) { - _LIT(KSetting, "IAP\\Id"); - iConnection.GetIntSetting(KSetting, iapId); + if (!iConnection.SubSessionHandle()) + return false; + _LIT(KSetting, "IAP\\Id"); + TInt err = iConnection.GetIntSetting(KSetting, iapId); + if (err != KErrNone) + return false; #ifdef SNAP_FUNCTIONALITY_AVAILABLE - // Check if this is an Easy WLAN configuration. On Symbian^3 RConnection may report - // the used configuration as 'EasyWLAN' IAP ID if someone has just opened the configuration - // from WLAN Scan dialog, _and_ that connection is still up. We need to find the - // real matching configuration. Function alters the Easy WLAN ID to real IAP ID (only if - // easy WLAN): - easyWlanTrueIapId(iapId); + // Check if this is an Easy WLAN configuration. On Symbian^3 RConnection may report + // the used configuration as 'EasyWLAN' IAP ID if someone has just opened the configuration + // from WLAN Scan dialog, _and_ that connection is still up. We need to find the + // real matching configuration. Function alters the Easy WLAN ID to real IAP ID (only if + // easy WLAN): + easyWlanTrueIapId(iapId); #endif + return true; +} + +QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 iapId) const +{ + if (iapId == 0) { + bool ok = activeIapId(iapId); + if (!ok) + return QNetworkConfiguration(); } #ifdef SNAP_FUNCTIONALITY_AVAILABLE @@ -1015,6 +1030,20 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia return publicConfig; } +void QNetworkSessionPrivateImpl::updateCurrentIap(TUint32 iapId) +{ + if (iCurrentIap == iapId) + return; + + if (iCurrentIap != 0) + QSymbianSocketManager::instance().removeActiveConnection(iCurrentIap); + + iCurrentIap = iapId; + + if (iCurrentIap != 0) + QSymbianSocketManager::instance().addActiveConnection(iCurrentIap); +} + void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG @@ -1028,7 +1057,10 @@ void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode) case KErrNone: // Connection created successfully { TInt error = KErrNone; - QNetworkConfiguration newActiveConfig = activeConfiguration(); + TUint32 iapId; + QNetworkConfiguration newActiveConfig; + if (activeIapId(iapId)) + newActiveConfig = activeConfiguration(iapId); if (!newActiveConfig.isValid()) { // RConnection startup was successful but no configuration // was found. That indicates that user has chosen to create a @@ -1038,6 +1070,7 @@ void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode) error = KErrGeneral; } else { QSymbianSocketManager::instance().setDefaultConnection(&iConnection); + updateCurrentIap(iapId); } if (error != KErrNone) { isOpen = false; diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 17a051e..9e02e5b 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.h +++ b/src/plugins/bearer/symbian/qnetworksession_impl.h @@ -143,6 +143,8 @@ private: void handleSymbianConnectionStatusChange(TInt aConnectionStatus, TInt aError, TUint accessPointId = 0); QNetworkConfiguration bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const; QNetworkConfiguration activeConfiguration(TUint32 iapId = 0) const; + bool activeIapId(TUint32 &iapId) const; + void updateCurrentIap(TUint32 iapId); #ifndef QT_NO_NETWORKINTERFACE QNetworkInterface interface(TUint iapId) const; #endif @@ -186,6 +188,7 @@ private: // data TUint32 iOldRoamingIap; TUint32 iNewRoamingIap; + TUint32 iCurrentIap; bool isOpening; diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 08c67e0..cfd2cec 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4885,5 +4885,8 @@ EXPORTS ?updateDir@QFactoryLoader@@QAEXABVQString@@AAVQSettings@@@Z @ 4884 NONAME ; void QFactoryLoader::updateDir(class QString const &, class QSettings &) ?disconnectNotify@QFutureWatcherBase@@MAEXPBD@Z @ 4885 NONAME ; void QFutureWatcherBase::disconnectNotify(char const *) ?maybeQueueForLater@QActiveObject@@QAE_NXZ @ 4886 NONAME ; bool QActiveObject::maybeQueueForLater(void) - ?activeObjectError@QEventDispatcherSymbian@@QAEXH@Z @ 4887 NONAME ; void QEventDispatcherSymbian::activeObjectError(int) + ?activeConnections@QSymbianSocketManager@@QBE?AV?$QList@K@@XZ @ 4887 NONAME ; class QList QSymbianSocketManager::activeConnections(void) const + ?removeActiveConnection@QSymbianSocketManager@@QAEXK@Z @ 4888 NONAME ; void QSymbianSocketManager::removeActiveConnection(unsigned long) + ?addActiveConnection@QSymbianSocketManager@@QAEXK@Z @ 4889 NONAME ; void QSymbianSocketManager::addActiveConnection(unsigned long) + ?activeObjectError@QEventDispatcherSymbian@@QAEXH@Z @ 4890 NONAME ; void QEventDispatcherSymbian::activeObjectError(int) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index d80aecb..44aa48c 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -4165,5 +4165,8 @@ EXPORTS _ZN14QFactoryLoader9updateDirERK7QStringR9QSettings @ 4164 NONAME _ZN23QCoreApplicationPrivate26rebuildInstallLibraryPathsEv @ 4165 NONAME _ZN13QActiveObject18maybeQueueForLaterEv @ 4166 NONAME - _ZN23QEventDispatcherSymbian17activeObjectErrorEi @ 4167 NONAME + _ZN21QSymbianSocketManager19addActiveConnectionEm @ 4167 NONAME + _ZN21QSymbianSocketManager22removeActiveConnectionEm @ 4168 NONAME + _ZN23QEventDispatcherSymbian17activeObjectErrorEi @ 4169 NONAME + _ZNK21QSymbianSocketManager17activeConnectionsEv @ 4170 NONAME -- cgit v0.12