--- a/qtmobility/src/bearer/qnetworksession_s60_p.cpp Wed Jun 09 10:36:00 2010 +0300
+++ b/qtmobility/src/bearer/qnetworksession_s60_p.cpp Mon Jun 21 16:36:26 2010 +0300
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -53,15 +53,29 @@
QNetworkSessionPrivate::QNetworkSessionPrivate()
: CActive(CActive::EPriorityUserInput), state(QNetworkSession::Invalid),
- isOpen(false), ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false),
- iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iDeprecatedConnectionId(0),
- iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false)
+ isOpen(false), iDynamicUnSetdefaultif(0), ipConnectionNotifier(0),
+ iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false),
+ iClosedByUser(false), iDeprecatedConnectionId(0), iError(QNetworkSession::UnknownSessionError),
+ iALREnabled(0), iConnectInBackground(false)
{
CActiveScheduler::Add(this);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
iMobility = NULL;
#endif
+ // Try to load "Open C" dll dynamically and
+ // try to attach to unsetdefaultif function dynamically.
+ // This is to avoid build breaks with old OpenC versions.
+ if (iOpenCLibrary.Load(_L("libc")) == KErrNone) {
+ iDynamicUnSetdefaultif = (TOpenCUnSetdefaultifFunction)iOpenCLibrary.Lookup(597);
+ }
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - ";
+ if (iDynamicUnSetdefaultif)
+ qDebug() << "dynamic setdefaultif() resolution succeeded. ";
+ else
+ qDebug() << "dynamic setdefaultif() resolution failed. ";
+#endif
TRAP_IGNORE(iConnectionMonitor.ConnectL());
}
@@ -76,9 +90,6 @@
delete ipConnectionNotifier;
ipConnectionNotifier = NULL;
- // Cancel possible RConnection::Start()
- Cancel();
-
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (iMobility) {
delete iMobility;
@@ -86,13 +97,16 @@
}
#endif
- iConnection.Close();
+ // Cancel possible RConnection::Start()
+ Cancel();
iSocketServ.Close();
// Close global 'Open C' RConnection
+ // Clears also possible unsetdefaultif() flags.
setdefaultif(0);
iConnectionMonitor.Close();
+ iOpenCLibrary.Close();
}
void QNetworkSessionPrivate::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState)
@@ -352,39 +366,6 @@
}
if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
- // Search through existing connections.
- // If there is already connection which matches to given IAP
- // try to attach to existing connection.
- TBool connected(EFalse);
- TConnectionInfoBuf connInfo;
- TUint count;
- if (iConnection.EnumerateConnections(count) == KErrNone) {
- for (TUint i=1; i<=count; i++) {
- // Note: GetConnectionInfo expects 1-based index.
- if (iConnection.GetConnectionInfo(i, connInfo) == KErrNone) {
- if (connInfo().iIapId == publicConfig.d.data()->numericId) {
- if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) {
- activeConfig = publicConfig;
- activeInterface = interface(activeConfig.d.data()->numericId);
- connected = ETrue;
- startTime = QDateTime::currentDateTime();
- // Use name of the IAP to open global 'Open C' RConnection
- QByteArray nameAsByteArray = publicConfig.name().toUtf8();
- ifreq ifr;
- memset(&ifr, 0, sizeof(struct ifreq));
- strcpy(ifr.ifr_name, nameAsByteArray.constData());
- error = setdefaultif(&ifr);
- isOpen = true;
- // Make sure that state will be Connected
- newState(QNetworkSession::Connected);
- emit quitPendingWaitsForOpened();
- break;
- }
- }
- }
- }
- }
- if (!connected) {
#ifdef OCC_FUNCTIONALITY_AVAILABLE
// With One Click Connectivity (Symbian^3 onwards) it is possible
// to connect silently, without any popups.
@@ -405,9 +386,12 @@
SetActive();
}
newState(QNetworkSession::Connecting);
- }
} else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
#ifdef OCC_FUNCTIONALITY_AVAILABLE
+ // On Symbian^3 if service network is not reachable, it triggers a UI (aka EasyWLAN) where
+ // user can create new IAPs. To detect this, we need to store the number of IAPs
+ // there was before connection was started.
+ iKnownConfigsBeforeConnectionStart = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
TConnPrefList snapPref;
TExtendedConnPref prefs;
prefs.SetSnapId(publicConfig.d.data()->numericId);
@@ -477,19 +461,23 @@
<< "close() called, session state is: " << state << " and isOpen is : "
<< isOpen;
#endif
- if (!isOpen) {
+
+ if (!isOpen && state != QNetworkSession::Connecting) {
return;
}
// Mark this session as closed-by-user so that we are able to report
// distinguish between stop() and close() state transitions
// when reporting.
iClosedByUser = true;
+ isOpen = false;
- isOpen = false;
+#ifndef OCC_FUNCTIONALITY_AVAILABLE
+ // On Symbian^3 we need to keep track of active configuration longer
+ // in case of empty-SNAP-triggered EasyWLAN.
activeConfig = QNetworkConfiguration();
+#endif
serviceConfig = QNetworkConfiguration();
- Cancel();
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (iMobility) {
delete iMobility;
@@ -503,17 +491,39 @@
iHandleStateNotificationsFromManager = true;
}
- iConnection.Close();
+ Cancel(); // closes iConnection
iSocketServ.Close();
- // Close global 'Open C' RConnection
- setdefaultif(0);
+ // Close global 'Open C' RConnection. If OpenC supports,
+ // close the defaultif for good to avoid difficult timing
+ // and bouncing issues of network going immediately back up
+ // because of e.g. select() thread etc.
+ if (iDynamicUnSetdefaultif) {
+ iDynamicUnSetdefaultif();
+ } else {
+ setdefaultif(0);
+ }
- if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ // If UserChoice, go down immediately. If some other configuration,
+ // go down immediately if there is no reports expected from the platform;
+ // in practice Connection Monitor is aware of connections only after
+ // KFinishedSelection event, and hence reports only after that event, but
+ // that does not seem to be trusted on all Symbian versions --> safest
+ // to go down.
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice || state == QNetworkSession::Connecting) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "going Disconnected right away. Deprecating connection monitor ID: " << publicConfig.d.data()->connectionId;
+#endif
+
+ // The connection has gone down, and processing of status updates must be
+ // stopped. Depending on platform, there may come 'connecting/connected' states
+ // considerably later (almost a second). Connection id is an increasing
+ // number, so this does not affect next _real_ 'conneting/connected' states.
+ iDeprecatedConnectionId = publicConfig.d.data()->connectionId;
newState(QNetworkSession::Closing);
newState(QNetworkSession::Disconnected);
}
-
if (allowSignals) {
emit q->closed();
}
@@ -589,8 +599,13 @@
{
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (iMobility) {
- // Close global 'Open C' RConnection
- setdefaultif(0);
+ // Close global 'Open C' RConnection. If openC supports, use the 'heavy'
+ // version to block all subsequent requests.
+ if (iDynamicUnSetdefaultif) {
+ iDynamicUnSetdefaultif();
+ } else {
+ setdefaultif(0);
+ }
// Start migrating to new IAP
iMobility->MigrateToPreferredCarrier();
}
@@ -702,7 +717,7 @@
{
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNS this : " << QString::number((uint)this) << " - "
- << "roaming Error() occured";
+ << "roaming Error() occured, isOpen is: " << isOpen;
#endif
if (isOpen) {
isOpen = false;
@@ -856,7 +871,7 @@
_LIT(KSetting, "IAP\\Id");
iConnection.GetIntSetting(KSetting, iapId);
}
-
+
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
// Try to search IAP from the used SNAP using IAP Id
@@ -877,7 +892,7 @@
// clone of the one of the IAPs of the used SNAP
// => If mappingName matches, clone has been found
QNetworkConfiguration pt;
- pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QString::number(qHash(iapId)));
+ pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)));
if (pt.d) {
for (int i=0; i < children.count(); i++) {
if (children[i].d.data()->mappingName == pt.d.data()->mappingName) {
@@ -885,22 +900,59 @@
}
}
} else {
+#ifdef OCC_FUNCTIONALITY_AVAILABLE
+ // On Symbian^3 (only, not earlier or Symbian^4) if the SNAP was not reachable, it triggers
+ // user choice type of activity (EasyWLAN). As a result, a new IAP may be created, and
+ // hence if was not found yet. Therefore update configurations and see if there is something new.
+ // 1. Update knowledge from the databases.
+ ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->updateConfigurations();
+ // 2. Check if new configuration was created during connection creation
+ QList<QString> knownConfigs = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "opened configuration was not known beforehand, looking for new.";
+#endif
+ if (knownConfigs.count() > iKnownConfigsBeforeConnectionStart.count()) {
+ // Configuration count increased => new configuration was created
+ // => Search new, created configuration
+ QString newIapId;
+ for (int i=0; i < iKnownConfigsBeforeConnectionStart.count(); i++) {
+ if (knownConfigs[i] != iKnownConfigsBeforeConnectionStart[i]) {
+ newIapId = knownConfigs[i];
+ break;
+ }
+ }
+ if (newIapId.isEmpty()) {
+ newIapId = knownConfigs[knownConfigs.count()-1];
+ }
+ pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(newIapId);
+ if (pt.d) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "new configuration was found, name, IAP id: " << pt.name() << pt.identifier();
+#endif
+ return pt;
+ }
+ }
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configuration was not found, returning invalid.";
+#endif
+#endif // OCC_FUNCTIONALITY_AVAILABLE
// Given IAP Id was not found from known IAPs array
return QNetworkConfiguration();
}
-
// Matching IAP was not found from used SNAP
// => IAP from another SNAP is returned
// (Note: Returned IAP matches to given IAP Id)
return pt;
}
#endif
-
if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
if (publicConfig.d.data()->manager) {
QNetworkConfiguration pt;
// Try to found User Selected IAP from known IAPs (accessPointConfigurations)
- pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QString::number(qHash(iapId)));
+ pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)));
if (pt.d) {
return pt;
} else {
@@ -937,6 +989,10 @@
void QNetworkSessionPrivate::RunL()
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "RConnection::RunL with status code: " << iStatus.Int();
+#endif
TInt statusCode = iStatus.Int();
switch (statusCode) {
@@ -1139,6 +1195,7 @@
QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
if ((config.state() == QNetworkConfiguration::Defined) ||
(config.state() == QNetworkConfiguration::Discovered)) {
+ activeConfig = QNetworkConfiguration();
state = newState;
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E to: " << state;
@@ -1159,6 +1216,21 @@
}
}
}
+#ifdef OCC_FUNCTIONALITY_AVAILABLE
+ // If the retVal is not true here, it means that the status update may apply to an IAP outside of
+ // SNAP (session is based on SNAP but follows IAP outside of it), which may occur on Symbian^3 EasyWlan.
+ if (retVal == false && activeConfig.d.data() && activeConfig.d.data()->numericId == accessPointId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed G to: " << state;
+#endif
+ if (newState == QNetworkSession::Disconnected) {
+ activeConfig = QNetworkConfiguration();
+ }
+ state = newState;
+ emit q->stateChanged(state);
+ retVal = true;
+ }
+#endif
}
}
@@ -1171,8 +1243,11 @@
// considerably later (almost a second). Connection id is an increasing
// number, so this does not affect next _real_ 'conneting/connected' states.
iDeprecatedConnectionId = publicConfig.d.data()->connectionId;
+#ifdef OCC_FUNCTIONALITY_AVAILABLE
+ // Just in case clear activeConfiguration.
+ activeConfig = QNetworkConfiguration();
+#endif
}
-
return retVal;
}
@@ -1197,7 +1272,6 @@
case KFinishedSelection:
if (aError == KErrNone)
{
- // The user successfully selected an IAP to be used
break;
}
else