--- a/qtmobility/src/bearer/qnetworksession_s60_p.cpp Thu Jul 15 19:34:35 2010 +0300
+++ b/qtmobility/src/bearer/qnetworksession_s60_p.cpp Thu Aug 19 10:43:30 2010 +0300
@@ -55,8 +55,8 @@
: CActive(CActive::EPriorityUserInput), state(QNetworkSession::Invalid),
isOpen(false), iDynamicUnSetdefaultif(0), ipConnectionNotifier(0),
iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false),
- iClosedByUser(false), iDeprecatedConnectionId(0), iError(QNetworkSession::UnknownSessionError),
- iALREnabled(0), iConnectInBackground(false)
+ iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0),
+ iConnectInBackground(false), isOpening(false)
{
CActiveScheduler::Add(this);
@@ -72,9 +72,9 @@
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNS this : " << QString::number((uint)this) << " - ";
if (iDynamicUnSetdefaultif)
- qDebug() << "dynamic setdefaultif() resolution succeeded. ";
+ qDebug() << "dynamic unsetdefaultif() is present in PIPS library. ";
else
- qDebug() << "dynamic setdefaultif() resolution failed. ";
+ qDebug() << "dynamic unsetdefaultif() not present in PIPS library. ";
#endif
TRAP_IGNORE(iConnectionMonitor.ConnectL());
@@ -83,6 +83,7 @@
QNetworkSessionPrivate::~QNetworkSessionPrivate()
{
isOpen = false;
+ isOpening = false;
// Cancel Connection Progress Notifications first.
// Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start()
@@ -107,6 +108,9 @@
iConnectionMonitor.Close();
iOpenCLibrary.Close();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - destroyed (and setdefaultif(0))";
+#endif
}
void QNetworkSessionPrivate::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState)
@@ -114,18 +118,12 @@
if (iHandleStateNotificationsFromManager) {
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNS this : " << QString::number((uint)this) << " - "
- << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId)
- << "configurationStateChanged connMon ID : " << QString::number(connMonId)
- << " : to a state: " << newState
- << " whereas my current state is: " << state;
+ << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId)
+ << "connMon ID : " << QString::number(connMonId) << " : to a state: " << newState
+ << "whereas my current state is: " << state;
+#else
+ Q_UNUSED(connMonId);
#endif
- if (connMonId == iDeprecatedConnectionId) {
-#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
- qDebug() << "QNS this : " << QString::number((uint)this) << " - "
- << "however status update from manager ignored because it related to already closed connection.";
-#endif
- return;
- }
this->newState(newState, accessPointId);
}
}
@@ -144,13 +142,29 @@
}
}
+void QNetworkSessionPrivate::configurationAdded(const QNetworkConfiguration& config)
+{
+ Q_UNUSED(config);
+ // If session is based on service network, some other app may create new access points
+ // to the SNAP --> synchronize session's state with that of interface's.
+ if (!publicConfig.d.data() || publicConfig.type() != QNetworkConfiguration::ServiceNetwork) {
+ return;
+ }
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configurationAdded IAP: " << QString::number(config.d.data()->numericId);
+#endif
+ syncStateWithInterface();
+}
+
+// Function sets the state of the session to match the state
+// of the underlying interface (the configuration this session is based on)
void QNetworkSessionPrivate::syncStateWithInterface()
{
- if (!publicConfig.d) {
+ if (!publicConfig.d || !publicConfig.d.data()) {
return;
}
-
- if (iFirstSync && publicConfig.d.data()) {
+ if (iFirstSync) {
QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager), SIGNAL(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)),
this, SLOT(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)));
// Listen to configuration removals, so that in case the configuration
@@ -158,50 +172,35 @@
QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager),
SIGNAL(configurationRemoved(QNetworkConfiguration)),
this, SLOT(configurationRemoved(QNetworkConfiguration)));
+ // Connect to configuration additions, so that in case a configuration is added
+ // in a SNAP this session is based on, the session knows to synch its state with its
+ // interface.
+ QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager),
+ SIGNAL(configurationAdded(QNetworkConfiguration)),
+ this, SLOT(configurationAdded(QNetworkConfiguration)));
}
// Start listening IAP state changes from QNetworkConfigurationManagerPrivate
iHandleStateNotificationsFromManager = true;
- // Check open connections to see if there is already
- // an open connection to selected IAP or SNAP
- TUint count;
- TRequestStatus status;
- iConnectionMonitor.GetConnectionCount(count, status);
- User::WaitForRequest(status);
- if (status.Int() != KErrNone) {
- return;
- }
-
- TUint numSubConnections;
- TUint connectionId;
- for (TUint i = 1; i <= count; i++) {
- TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
- if (ret == KErrNone) {
- TUint apId;
- iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
- User::WaitForRequest(status);
- if (status.Int() == KErrNone) {
- TInt connectionStatus;
- iConnectionMonitor.GetIntAttribute(connectionId, 0, KConnectionStatus, connectionStatus, status);
- User::WaitForRequest(status);
- if (connectionStatus == KLinkLayerOpen) {
- if (state != QNetworkSession::Closing) {
- if (newState(QNetworkSession::Connected, apId)) {
- return;
- }
- }
- }
- }
- }
- }
-
- if (state != QNetworkSession::Connected) {
- if ((publicConfig.d.data()->state & QNetworkConfiguration::Discovered) ==
- QNetworkConfiguration::Discovered) {
- newState(QNetworkSession::Disconnected);
- } else {
- newState(QNetworkSession::NotAvailable);
- }
+ // Check what is the state of the configuration this session is based on
+ // and set the session in appropriate state.
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "syncStateWithInterface() state of publicConfig is: " << publicConfig.d.data()->state;
+#endif
+ switch (publicConfig.d.data()->state) {
+ case QNetworkConfiguration::Active:
+ newState(QNetworkSession::Connected);
+ break;
+ case QNetworkConfiguration::Discovered:
+ newState(QNetworkSession::Disconnected);
+ break;
+ case QNetworkConfiguration::Defined:
+ newState(QNetworkSession::NotAvailable);
+ break;
+ case QNetworkConfiguration::Undefined:
+ default:
+ newState(QNetworkSession::Invalid);
}
}
@@ -245,6 +244,15 @@
QNetworkInterface QNetworkSessionPrivate::currentInterface() const
{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "currentInterface() requested, state: " << state
+ << "publicConfig validity: " << publicConfig.isValid();
+ if (activeInterface.isValid())
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "interface is: " << activeInterface.humanReadableName();
+#endif
+
if (!publicConfig.isValid() || state != QNetworkSession::Connected) {
return QNetworkInterface();
}
@@ -302,10 +310,11 @@
<< "open() called, session state is: " << state << " and isOpen is: "
<< isOpen;
#endif
- if (isOpen || (state == QNetworkSession::Connecting)) {
+ if (isOpen || isOpening)
return;
- }
+ isOpening = true;
+
// Stop handling IAP state change signals from QNetworkConfigurationManagerPrivate
// => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
iHandleStateNotificationsFromManager = false;
@@ -333,7 +342,6 @@
// Clear possible previous states
iStoppedByUser = false;
iClosedByUser = false;
- iDeprecatedConnectionId = 0;
TInt error = iSocketServ.Connect();
if (error != KErrNone) {
@@ -366,7 +374,7 @@
}
if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-#ifdef OCC_FUNCTIONALITY_AVAILABLE
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
// With One Click Connectivity (Symbian^3 onwards) it is possible
// to connect silently, without any popups.
TConnPrefList pref;
@@ -385,9 +393,13 @@
if (!IsActive()) {
SetActive();
}
- newState(QNetworkSession::Connecting);
+ // Avoid flip flop of states if the configuration is already
+ // active. IsOpen/opened() will indicate when ready.
+ if (state != QNetworkSession::Connected) {
+ newState(QNetworkSession::Connecting);
+ }
} else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
-#ifdef OCC_FUNCTIONALITY_AVAILABLE
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_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.
@@ -406,7 +418,11 @@
if (!IsActive()) {
SetActive();
}
- newState(QNetworkSession::Connecting);
+ // Avoid flip flop of states if the configuration is already
+ // active. IsOpen/opened() will indicate when ready.
+ if (state != QNetworkSession::Connected) {
+ newState(QNetworkSession::Connecting);
+ }
} else if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
iKnownConfigsBeforeConnectionStart = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
iConnection.Start(iStatus);
@@ -418,6 +434,7 @@
if (error != KErrNone) {
isOpen = false;
+ isOpening = false;
iError = QNetworkSession::UnknownSessionError;
emit q->error(iError);
if (ipConnectionNotifier) {
@@ -470,12 +487,8 @@
// when reporting.
iClosedByUser = true;
isOpen = false;
+ isOpening = 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();
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
@@ -512,15 +525,9 @@
// 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;
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "going disconnected right away, since either UserChoice or Connecting";
#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);
}
@@ -581,6 +588,7 @@
#endif
// Since we are open, use RConnection to stop the interface
isOpen = false;
+ isOpening = false;
iStoppedByUser = true;
newState(QNetworkSession::Closing);
if (ipConnectionNotifier) {
@@ -590,6 +598,7 @@
}
iConnection.Stop(RConnection::EStopAuthoritative);
isOpen = true;
+ isOpening = false;
close(false);
emit q->closed();
}
@@ -721,6 +730,7 @@
#endif
if (isOpen) {
isOpen = false;
+ isOpening = false;
activeConfig = QNetworkConfiguration();
serviceConfig = QNetworkConfiguration();
iError = QNetworkSession::RoamingError;
@@ -870,6 +880,13 @@
if (iapId == 0) {
_LIT(KSetting, "IAP\\Id");
iConnection.GetIntSetting(KSetting, iapId);
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(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):
+ ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->easyWlanTrueIapId(iapId);
+#endif
}
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
@@ -900,7 +917,7 @@
}
}
} else {
-#ifdef OCC_FUNCTIONALITY_AVAILABLE
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_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.
@@ -938,7 +955,7 @@
qDebug() << "QNS this : " << QString::number((uint)this) << " - "
<< "configuration was not found, returning invalid.";
#endif
-#endif // OCC_FUNCTIONALITY_AVAILABLE
+#endif
// Given IAP Id was not found from known IAPs array
return QNetworkConfiguration();
}
@@ -1001,6 +1018,11 @@
TInt error = KErrNone;
QNetworkConfiguration newActiveConfig = activeConfiguration();
if (!newActiveConfig.isValid()) {
+ // RConnection startup was successfull but no configuration
+ // was found. That indicates that user has chosen to create a
+ // new WLAN configuration (from scan results), but that new
+ // configuration does not have access to Internet (Internet
+ // Connectivity Test, ICT, failed).
error = KErrGeneral;
} else {
// Use name of the IAP to open global 'Open C' RConnection
@@ -1010,15 +1032,24 @@
strcpy(ifr.ifr_name, nameAsByteArray.constData());
error = setdefaultif(&ifr);
}
-
if (error != KErrNone) {
isOpen = false;
+ isOpening = false;
iError = QNetworkSession::UnknownSessionError;
QT_TRYCATCH_LEAVING(emit q->error(iError));
- Cancel();
if (ipConnectionNotifier) {
ipConnectionNotifier->StopNotifications();
}
+ if (!newActiveConfig.isValid()) {
+ // No valid configuration, bail out.
+ // Status updates from QNCM won't be received correctly
+ // because there is no configuration to associate them with so transit here.
+ iConnection.Close();
+ newState(QNetworkSession::Closing);
+ newState(QNetworkSession::Disconnected);
+ } else {
+ Cancel();
+ }
QT_TRYCATCH_LEAVING(syncStateWithInterface());
return;
}
@@ -1030,6 +1061,7 @@
}
#endif
isOpen = true;
+ isOpening = false;
activeConfig = newActiveConfig;
activeInterface = interface(activeConfig.d.data()->numericId);
if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
@@ -1048,6 +1080,7 @@
break;
case KErrNotFound: // Connection failed
isOpen = false;
+ isOpening = false;
activeConfig = QNetworkConfiguration();
serviceConfig = QNetworkConfiguration();
iError = QNetworkSession::InvalidConfigurationError;
@@ -1062,9 +1095,12 @@
case KErrAlreadyExists: // Connection already exists
default:
isOpen = false;
+ isOpening = false;
activeConfig = QNetworkConfiguration();
serviceConfig = QNetworkConfiguration();
- if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+ if (statusCode == KErrCancel) {
+ iError = QNetworkSession::SessionAbortedError;
+ } else if (publicConfig.state() == QNetworkConfiguration::Undefined ||
publicConfig.state() == QNetworkConfiguration::Defined) {
iError = QNetworkSession::InvalidConfigurationError;
} else {
@@ -1127,6 +1163,12 @@
return false;
}
+ // Make sure that some lagging 'connecting' state-changes do not overwrite
+ // if we are already connected (may righfully still happen with roaming though).
+ if (state == QNetworkSession::Connected && newState == QNetworkSession::Connecting) {
+ return false;
+ }
+
bool emitSessionClosed = false;
// If we abruptly go down and user hasn't closed the session, we've been aborted.
@@ -1140,6 +1182,7 @@
// application or session stops connection or when network drops
// unexpectedly).
isOpen = false;
+ isOpening = false;
activeConfig = QNetworkConfiguration();
serviceConfig = QNetworkConfiguration();
iError = QNetworkSession::SessionAbortedError;
@@ -1216,7 +1259,7 @@
}
}
}
-#ifdef OCC_FUNCTIONALITY_AVAILABLE
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_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) {
@@ -1233,20 +1276,12 @@
#endif
}
}
-
if (emitSessionClosed) {
emit q->closed();
}
if (state == QNetworkSession::Disconnected) {
- // 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;
-#ifdef OCC_FUNCTIONALITY_AVAILABLE
// Just in case clear activeConfiguration.
activeConfig = QNetworkConfiguration();
-#endif
}
return retVal;
}