qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp
branchRCL_3
changeset 5 4ea83c148e84
parent 1 5822d84012fb
child 6 4203353e74ea
equal deleted inserted replaced
4:d965ea371a4f 5:4ea83c148e84
    42 #include "qnetworkconfigmanager_s60_p.h"
    42 #include "qnetworkconfigmanager_s60_p.h"
    43 
    43 
    44 #include <commdb.h>
    44 #include <commdb.h>
    45 #include <cdbcols.h>
    45 #include <cdbcols.h>
    46 #include <d32dbms.h>
    46 #include <d32dbms.h>
    47 #include <QEventLoop>
    47 #include <nifvar.h>
    48 #include <QTimer>
    48 #include <QTimer>
    49 #include <QTime>  // For randgen seeding
    49 #include <QTime>  // For randgen seeding
    50 #include <QtCore> // For randgen seeding
    50 #include <QtCore> // For randgen seeding
    51 
    51 
    52 // #define QT_BEARERMGMT_CONFIGMGR_DEBUG
    52 
    53 
    53 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
    54 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
       
    55 #include <QDebug>
    54 #include <QDebug>
    56 #endif
    55 #endif
    57 
    56 
    58 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
    57 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
    59     #include <cmdestination.h>
    58     #include <cmdestination.h>
    68     #include <aputils.h> 
    67     #include <aputils.h> 
    69 #endif
    68 #endif
    70 
    69 
    71 QTM_BEGIN_NAMESPACE
    70 QTM_BEGIN_NAMESPACE
    72 
    71 
    73 static const int KValueThatWillBeAddedToSNAPId = 1000;
    72 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
    73     static const int KValueThatWillBeAddedToSNAPId = 1000;
       
    74 #endif
    74 static const int KUserChoiceIAPId = 0;
    75 static const int KUserChoiceIAPId = 0;
    75 
    76 
    76 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
    77 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
    77     : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0),
    78     : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0),
    78     iFirstUpdate(true), iInitOk(true), iIgnoringUpdates(false),
    79     iFirstUpdate(true), iInitOk(true), iUpdatePending(false),
    79     iTimeToWait(0), iIgnoreEventLoop(0)
    80     iTimeToWait(0)
    80 {
    81 {
    81     CActiveScheduler::Add(this);
    82     CActiveScheduler::Add(this);
    82 
    83 
    83     // Seed the randomgenerator
    84     // Seed the randomgenerator
    84     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
    85     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
    85     iIgnoreEventLoop = new QEventLoop(this);
       
    86 
    86 
    87     registerPlatformCapabilities();
    87     registerPlatformCapabilities();
    88     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
    88     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
    89     if (error != KErrNone) {
    89     if (error != KErrNone) {
    90         iInitOk = false;
    90         iInitOk = false;
   163     CTrapCleanup* cleanup = CTrapCleanup::New();
   163     CTrapCleanup* cleanup = CTrapCleanup::New();
   164     delete ipCommsDB;
   164     delete ipCommsDB;
   165     delete cleanup;
   165     delete cleanup;
   166 }
   166 }
   167 
   167 
       
   168 void QNetworkConfigurationManagerPrivate::delayedConfigurationUpdate()
       
   169 {
       
   170     if (iUpdatePending) {
       
   171 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   172         qDebug("QNCM delayed configuration update (ECommit or ERecover occurred).");
       
   173 #endif
       
   174         TRAPD(error, updateConfigurationsL());
       
   175         if (error == KErrNone) {
       
   176             updateStatesToSnaps();
       
   177         }
       
   178         iUpdatePending = false;
       
   179         // Start monitoring again.
       
   180         if (!IsActive()) {
       
   181             SetActive();
       
   182             // Start waiting for new notification
       
   183             ipCommsDB->RequestNotification(iStatus);
       
   184         }
       
   185     }
       
   186 }
   168 
   187 
   169 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
   188 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
   170 {
   189 {
   171     capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces;
   190     capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces;
   172     capFlags |= QNetworkConfigurationManager::DirectConnectionRouting;
   191     capFlags |= QNetworkConfigurationManager::DirectConnectionRouting;
   227                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   246                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   228                 accessPointConfigurations.insert(cpPriv->id, ptr);
   247                 accessPointConfigurations.insert(cpPriv->id, ptr);
   229                 if (!iFirstUpdate) {
   248                 if (!iFirstUpdate) {
   230                     QNetworkConfiguration item;
   249                     QNetworkConfiguration item;
   231                     item.d = ptr;
   250                     item.d = ptr;
   232                     emit configurationAdded(item);
   251                     // Emit configuration added. Connected slots may throw execptions
       
   252                     // which propagate here --> must be converted to leaves (standard
       
   253                     // std::exception would cause any TRAP trapping this function to terminate
       
   254                     // program).
       
   255                     QT_TRYCATCH_LEAVING(emit configurationAdded(item));
   233                 }
   256                 }
   234             }
   257             }
   235         }
   258         }
   236         CleanupStack::PopAndDestroy(&connectionMethod);
   259         CleanupStack::PopAndDestroy(&connectionMethod);
   237     }
   260     }
   248         QString ident = QString::number(qHash(destination.Id()+KValueThatWillBeAddedToSNAPId)); //TODO: Check if it's ok to add 1000 SNAP Id to prevent SNAP ids overlapping IAP ids
   271         QString ident = QString::number(qHash(destination.Id()+KValueThatWillBeAddedToSNAPId)); //TODO: Check if it's ok to add 1000 SNAP Id to prevent SNAP ids overlapping IAP ids
   249         if (snapConfigurations.contains(ident)) {
   272         if (snapConfigurations.contains(ident)) {
   250             knownSnapConfigs.removeOne(ident);
   273             knownSnapConfigs.removeOne(ident);
   251         } else {
   274         } else {
   252             QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   275             QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   253             CleanupStack::PushL(cpPriv);
       
   254     
   276     
   255             HBufC *pName = destination.NameLC();
   277             HBufC *pName = destination.NameLC();
   256             cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
   278             QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
   257             CleanupStack::PopAndDestroy(pName);
   279             CleanupStack::PopAndDestroy(pName);
   258             pName = NULL;
   280             pName = NULL;
   259     
   281     
   260             cpPriv->isValid = true;
   282             cpPriv->isValid = true;
   261             cpPriv->id = ident;
   283             cpPriv->id = ident;
   270             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   292             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   271             snapConfigurations.insert(ident, ptr);
   293             snapConfigurations.insert(ident, ptr);
   272             if (!iFirstUpdate) {
   294             if (!iFirstUpdate) {
   273                 QNetworkConfiguration item;
   295                 QNetworkConfiguration item;
   274                 item.d = ptr;
   296                 item.d = ptr;
   275                 emit configurationAdded(item);
   297                 QT_TRYCATCH_LEAVING(emit configurationAdded(item));
   276             }
   298             }
   277             
       
   278             CleanupStack::Pop(cpPriv);
       
   279         }
   299         }
   280         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> privSNAP = snapConfigurations.value(ident);
   300         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> privSNAP = snapConfigurations.value(ident);
   281             
   301             
   282         for (int j=0; j < destination.ConnectionMethodCount(); j++) {
   302         for (int j=0; j < destination.ConnectionMethodCount(); j++) {
   283             RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
   303             RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
   295                     ptr.data()->serviceNetworkPtr = privSNAP;
   315                     ptr.data()->serviceNetworkPtr = privSNAP;
   296                     accessPointConfigurations.insert(cpPriv->id, ptr);
   316                     accessPointConfigurations.insert(cpPriv->id, ptr);
   297                     if (!iFirstUpdate) {
   317                     if (!iFirstUpdate) {
   298                         QNetworkConfiguration item;
   318                         QNetworkConfiguration item;
   299                         item.d = ptr;
   319                         item.d = ptr;
   300                         emit configurationAdded(item);
   320                         QT_TRYCATCH_LEAVING(emit configurationAdded(item));
   301                     }
   321                     }
   302                     privSNAP->serviceNetworkMembers.append(ptr);
   322                     privSNAP->serviceNetworkMembers.append(ptr);
   303                 }
   323                 }
   304             } else {
   324             } else {
   305                 knownConfigs.removeOne(iface);
   325                 knownConfigs.removeOne(iface);
   347                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   367                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   348                 accessPointConfigurations.insert(ident, ptr);
   368                 accessPointConfigurations.insert(ident, ptr);
   349                 if (!iFirstUpdate) {
   369                 if (!iFirstUpdate) {
   350                     QNetworkConfiguration item;
   370                     QNetworkConfiguration item;
   351                     item.d = ptr;
   371                     item.d = ptr;
   352                     emit configurationAdded(item);
   372                     QT_TRYCATCH_LEAVING(emit configurationAdded(item));
   353                 }
   373                 }
   354             } else {
   374             } else {
   355                 delete cpPriv;
   375                 delete cpPriv;
   356             }
   376             }
   357         }
   377         }
   358         retVal = pDbTView->GotoNextRecord();
   378         retVal = pDbTView->GotoNextRecord();
   359     }
   379     }
   360     CleanupStack::PopAndDestroy(pDbTView);
   380     CleanupStack::PopAndDestroy(pDbTView);
   361 #endif
   381 #endif
   362     updateActiveAccessPoints();
   382     QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
   363     
   383     
   364     foreach (const QString &oldIface, knownConfigs) {
   384     foreach (const QString &oldIface, knownConfigs) {
   365         //remove non existing IAP
   385         //remove non existing IAP
   366         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
   386         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
   367         priv->isValid = false;
   387         priv->isValid = false;
   368         if (!iFirstUpdate) {
   388         if (!iFirstUpdate) {
   369             QNetworkConfiguration item;
   389             QNetworkConfiguration item;
   370             item.d = priv;
   390             item.d = priv;
   371             emit configurationRemoved(item);
   391             QT_TRYCATCH_LEAVING(emit configurationRemoved(item));
   372         }
   392         }
   373         // Remove non existing IAP from SNAPs
   393         // Remove non existing IAP from SNAPs
   374         foreach (const QString &iface, snapConfigurations.keys()) {
   394         foreach (const QString &iface, snapConfigurations.keys()) {
   375             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface);
   395             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface);
   376             // => Check if one of the IAPs of the SNAP is active
   396             // => Check if one of the IAPs of the SNAP is active
   387         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
   407         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
   388         priv->isValid = false;
   408         priv->isValid = false;
   389         if (!iFirstUpdate) {
   409         if (!iFirstUpdate) {
   390             QNetworkConfiguration item;
   410             QNetworkConfiguration item;
   391             item.d = priv;
   411             item.d = priv;
   392             emit configurationRemoved(item);
   412             QT_TRYCATCH_LEAVING(emit configurationRemoved(item));
   393         }
   413         }
   394     }
   414     }
   395 }
   415 }
   396 
   416 
   397 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
   417 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
   398 QNetworkConfigurationPrivate* QNetworkConfigurationManagerPrivate::configFromConnectionMethodL(
   418 QNetworkConfigurationPrivate* QNetworkConfigurationManagerPrivate::configFromConnectionMethodL(
   399         RCmConnectionMethod& connectionMethod)
   419         RCmConnectionMethod& connectionMethod)
   400 {
   420 {
   401     QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   421     QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
   402     CleanupStack::PushL(cpPriv);
       
   403     
       
   404     TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
   422     TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
   405     QString ident = QString::number(qHash(iapId));
   423     QString ident = QString::number(qHash(iapId));
   406     
   424     
   407     HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
   425     HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
   408     CleanupStack::PushL(pName);
   426     CleanupStack::PushL(pName);
   409     cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
   427     QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
   410     CleanupStack::PopAndDestroy(pName);
   428     CleanupStack::PopAndDestroy(pName);
   411     pName = NULL;
   429     pName = NULL;
   412     
   430     
   413     TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
   431     TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
   414     switch (bearerId) {
   432     switch (bearerId) {
   452         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
   470         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
   453     }
   471     }
   454 
   472 
   455     if (error == KErrNone && pName) {
   473     if (error == KErrNone && pName) {
   456         CleanupStack::PushL(pName);
   474         CleanupStack::PushL(pName);
   457         cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length());
   475         QT_TRYCATCH_LEAVING(cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length()));
   458         CleanupStack::PopAndDestroy(pName);
   476         CleanupStack::PopAndDestroy(pName);
   459         pName = NULL;
   477         pName = NULL;
   460     }
   478     }
   461  
   479  
   462     cpPriv->state = QNetworkConfiguration::Defined;
   480     cpPriv->state = QNetworkConfiguration::Defined;
   471     cpPriv->connectionId = 0;
   489     cpPriv->connectionId = 0;
   472     cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   490     cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
   473     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
   491     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
   474     cpPriv->roamingSupported = false;
   492     cpPriv->roamingSupported = false;
   475     cpPriv->manager = this;
   493     cpPriv->manager = this;
   476     
       
   477     CleanupStack::Pop(cpPriv);
       
   478     return cpPriv;
   494     return cpPriv;
   479 }
   495 }
   480 #else
   496 #else
   481 bool QNetworkConfigurationManagerPrivate::readNetworkConfigurationValuesFromCommsDb(
   497 bool QNetworkConfigurationManagerPrivate::readNetworkConfigurationValuesFromCommsDb(
   482         TUint32 aApId, QNetworkConfigurationPrivate* apNetworkConfiguration)
   498         TUint32 aApId, QNetworkConfigurationPrivate* apNetworkConfiguration)
   505         User::Leave(KErrNotFound);
   521         User::Leave(KErrNotFound);
   506     }
   522     }
   507     
   523     
   508     QString ident = QString::number(qHash(aApId));
   524     QString ident = QString::number(qHash(aApId));
   509     
   525     
   510     apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length());
   526     QT_TRYCATCH_LEAVING(apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length()));
   511     apNetworkConfiguration->isValid = true;
   527     apNetworkConfiguration->isValid = true;
   512     apNetworkConfiguration->id = ident;
   528     apNetworkConfiguration->id = ident;
   513     apNetworkConfiguration->numericId = aApId;
   529     apNetworkConfiguration->numericId = aApId;
   514     apNetworkConfiguration->connectionId = 0;
   530     apNetworkConfiguration->connectionId = 0;
   515     apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
   531     apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
   605     TRequestStatus status;
   621     TRequestStatus status;
   606     TUint connectionCount;
   622     TUint connectionCount;
   607     iConnectionMonitor.GetConnectionCount(connectionCount, status);
   623     iConnectionMonitor.GetConnectionCount(connectionCount, status);
   608     User::WaitForRequest(status);
   624     User::WaitForRequest(status);
   609     
   625     
   610     // Go through all connections and set state of related IAPs to Active
   626     // Go through all connections and set state of related IAPs to Active.
       
   627     // Status needs to be checked carefully, because ConnMon lists also e.g.
       
   628     // WLAN connections that are being currently tried --> we don't want to
       
   629     // state these as active.
   611     TUint connectionId;
   630     TUint connectionId;
   612     TUint subConnectionCount;
   631     TUint subConnectionCount;
   613     TUint apId;
   632     TUint apId;
       
   633     TInt connectionStatus;
   614     if (status.Int() == KErrNone) {
   634     if (status.Int() == KErrNone) {
   615         for (TUint i = 1; i <= connectionCount; i++) {
   635         for (TUint i = 1; i <= connectionCount; i++) {
   616             iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
   636             iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
   617             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
   637             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
   618             User::WaitForRequest(status);
   638             User::WaitForRequest(status);
   619             QString ident = QString::number(qHash(apId));
   639             QString ident = QString::number(qHash(apId));
   620             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   640             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   621             if (priv.data()) {
   641             if (priv.data()) {
   622                 online = true;
   642                 iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
   623                 inactiveConfigs.removeOne(ident);
   643                 User::WaitForRequest(status);          
   624                 priv.data()->connectionId = connectionId;
   644                 if (connectionStatus == KLinkLayerOpen) {
   625                 // Configuration is Active
   645                     online = true;
   626                 changeConfigurationStateTo(priv, QNetworkConfiguration::Active);
   646                     inactiveConfigs.removeOne(ident);
       
   647                     priv.data()->connectionId = connectionId;
       
   648                     // Configuration is Active
       
   649                     changeConfigurationStateTo(priv, QNetworkConfiguration::Active);
       
   650                 }
   627             }
   651             }
   628         }
   652         }
   629     }
   653     }
   630 
   654 
   631     // Make sure that state of rest of the IAPs won't be Active
   655     // Make sure that state of rest of the IAPs won't be Active
   672                     changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered);
   696                     changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered);
   673                 }
   697                 }
   674             }
   698             }
   675         }
   699         }
   676         
   700         
   677         // Make sure that state of rest of the IAPs won't be Discovered or Active
   701         // Make sure that state of rest of the IAPs won't be Active
   678         foreach (const QString &iface, unavailableConfigs) {
   702         foreach (const QString &iface, unavailableConfigs) {
   679             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   703             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   680             if (priv.data()) {
   704             if (priv.data()) {
   681                 // Configuration is Defined
   705                 // Configuration is Defined
   682                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
   706                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered);
   683             }
   707             }
   684         }
   708         }
   685     }
   709     }
   686 
   710 
   687     updateStatesToSnaps();
   711     updateStatesToSnaps();
   805     }
   829     }
   806 }
   830 }
   807 
   831 
   808 void QNetworkConfigurationManagerPrivate::RunL()
   832 void QNetworkConfigurationManagerPrivate::RunL()
   809 {
   833 {
   810     if (iIgnoringUpdates) {
       
   811 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
       
   812         qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
       
   813 #endif
       
   814         return;
       
   815     }
       
   816     if (iStatus != KErrCancel) {
   834     if (iStatus != KErrCancel) {
       
   835 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   836         qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
       
   837 #endif
       
   838         // By default, start relistening notifications. Stop only if interesting event occured.
       
   839         iWaitingCommsDatabaseNotifications = true;
   817         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
   840         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
   818         switch (event) {
   841         switch (event) {
   819         case RDbNotifier::EUnlock:   /** All read locks have been removed.  */
       
   820         case RDbNotifier::ECommit:   /** A transaction has been committed.  */ 
   842         case RDbNotifier::ECommit:   /** A transaction has been committed.  */ 
   821         case RDbNotifier::ERollback: /** A transaction has been rolled back */
       
   822         case RDbNotifier::ERecover:  /** The database has been recovered    */
   843         case RDbNotifier::ERecover:  /** The database has been recovered    */
   823 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
   844             // Mark that there is update pending. No need to ask more events,
   824             qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
   845             // as we know we will be updating anyway when the timer expires.
   825 #endif
   846             if (!iUpdatePending) {
   826             iIgnoringUpdates = true;
   847                 iUpdatePending = true;
   827             // Other events than ECommit get lower priority. In practice with those events,
   848                 iWaitingCommsDatabaseNotifications = false;
   828             // we delay_before_updating methods, whereas
   849                 // Update after random time, so that many processes won't
   829             // with ECommit we _update_before_delaying the reaction to next event.
   850                 // start updating simultaneously
   830             // Few important notes: 1) listening to only ECommit does not seem to be adequate,
   851                 updateConfigurationsAfterRandomTime();
   831             // but updates will be missed. Hence other events are reacted upon too.
   852             }
   832             // 2) RDbNotifier records the most significant event, and that will be returned once
   853             break;           
   833             // we issue new RequestNotification, and hence updates will not be missed even
       
   834             // when we are 'not reacting to them' for few seconds.
       
   835             if (event == RDbNotifier::ECommit) {
       
   836                 TRAPD(error, updateConfigurationsL());
       
   837                 if (error == KErrNone) {
       
   838                     updateStatesToSnaps();
       
   839                 }
       
   840                 waitRandomTime();
       
   841             } else {
       
   842                 waitRandomTime();
       
   843                 TRAPD(error, updateConfigurationsL());
       
   844                 if (error == KErrNone) {
       
   845                     updateStatesToSnaps();
       
   846                 }   
       
   847             }
       
   848             iIgnoringUpdates = false; // Wait time done, allow updating again
       
   849             iWaitingCommsDatabaseNotifications = true;
       
   850             break;
       
   851         default:
   854         default:
   852             // Do nothing
   855             // Do nothing
   853             break;
   856             break;
   854         }
   857         }
   855     }
   858     }
   865 void QNetworkConfigurationManagerPrivate::DoCancel()
   868 void QNetworkConfigurationManagerPrivate::DoCancel()
   866 {
   869 {
   867     ipCommsDB->CancelRequestNotification();
   870     ipCommsDB->CancelRequestNotification();
   868 }
   871 }
   869 
   872 
   870 
       
   871 void QNetworkConfigurationManagerPrivate::EventL(const CConnMonEventBase& aEvent)
   873 void QNetworkConfigurationManagerPrivate::EventL(const CConnMonEventBase& aEvent)
   872 {
   874 {
   873     switch (aEvent.EventType()) {
   875     switch (aEvent.EventType()) {
   874     case EConnMonCreateConnection:
   876     case EConnMonConnectionStatusChange:
   875         {
   877         {
   876         CConnMonCreateConnection* realEvent;
   878         CConnMonConnectionStatusChange* realEvent;
   877         realEvent = (CConnMonCreateConnection*) &aEvent;
   879         realEvent = (CConnMonConnectionStatusChange*) &aEvent;
   878         TUint subConnectionCount = 0;
   880         TInt connectionStatus = realEvent->ConnectionStatus();
   879         TUint apId;            
   881 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
   880         TUint connectionId = realEvent->ConnectionId();
   882         qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId();
   881         TRequestStatus status;
   883 #endif
   882         iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
   884         if (connectionStatus == KConfigDaemonStartingRegistration) {
   883         User::WaitForRequest(status);
   885             TUint connectionId = realEvent->ConnectionId();
   884         QString ident = QString::number(qHash(apId));
   886             TUint subConnectionCount = 0;
   885         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   887             TUint apId;            
   886         if (priv.data()) {
   888             TRequestStatus status;
   887             priv.data()->connectionId = connectionId;
   889             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
   888             // Configuration is Active
   890             User::WaitForRequest(status);
   889             if (changeConfigurationStateTo(priv, QNetworkConfiguration::Active)) {
   891             QString ident = QString::number(qHash(apId));
   890                 updateStatesToSnaps();
   892             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   891             }
   893             if (priv.data()) {
   892             if (!iOnline) {
   894                 priv.data()->connectionId = connectionId;
   893                 iOnline = true;
   895                 QT_TRYCATCH_LEAVING(emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Connecting));
   894                 emit this->onlineStateChanged(iOnline);
   896             }
   895             }
   897         } else if (connectionStatus == KLinkLayerOpen) {
   896         }
   898             // Connection has been successfully opened
   897         }
   899             TUint connectionId = realEvent->ConnectionId();
   898         break;
   900             TUint subConnectionCount = 0;
   899 
   901             TUint apId;            
   900     case EConnMonDeleteConnection:
   902             TRequestStatus status;
   901         {
   903             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
   902         CConnMonDeleteConnection* realEvent;
   904             User::WaitForRequest(status);
   903         realEvent = (CConnMonDeleteConnection*) &aEvent;
   905             QString ident = QString::number(qHash(apId));
   904         TUint connectionId = realEvent->ConnectionId();
   906             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   905         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = dataByConnectionId(connectionId);
   907             if (priv.data()) {
   906         if (priv.data()) {
   908                 priv.data()->connectionId = connectionId;
   907             priv.data()->connectionId = 0;
   909                 // Configuration is Active
   908             // Configuration is either Defined or Discovered
   910                 QT_TRYCATCH_LEAVING(
   909             if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) {
   911                     if (changeConfigurationStateTo(priv, QNetworkConfiguration::Active)) {
   910                 updateStatesToSnaps();
   912                         updateStatesToSnaps();
   911             }
   913                     }
   912         }
   914                     emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Connected);
   913         
   915                     if (!iOnline) {
   914         bool online = false;
   916                         iOnline = true;
   915         foreach (const QString &iface, accessPointConfigurations.keys()) {
   917                         emit this->onlineStateChanged(iOnline);
   916             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   918                     }
   917             if (priv.data()->state == QNetworkConfiguration::Active) {
   919                 );
   918                 online = true;
   920             }
   919                 break;
   921         } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
   920             }
   922             TUint connectionId = realEvent->ConnectionId();
   921         }
   923             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = dataByConnectionId(connectionId);
   922         if (iOnline != online) {
   924             if (priv.data()) {
   923             iOnline = online;
   925                 QT_TRYCATCH_LEAVING(emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Closing));
   924             emit this->onlineStateChanged(iOnline);
   926             }
   925         }
   927         } else if (connectionStatus == KLinkLayerClosed ||
   926         }
   928                    connectionStatus == KConnectionClosed) {
   927         break;
   929             // Connection has been closed. Which of the above events is reported, depends on the Symbian
       
   930             // platform.
       
   931             TUint connectionId = realEvent->ConnectionId();
       
   932             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = dataByConnectionId(connectionId);
       
   933             if (priv.data()) {
       
   934                 // Configuration is either Defined or Discovered
       
   935                 QT_TRYCATCH_LEAVING(
       
   936                     if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) {
       
   937                         updateStatesToSnaps();
       
   938                     }
       
   939                     emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Disconnected);
       
   940                 );
       
   941             }
       
   942             
       
   943             bool online = false;
       
   944             foreach (const QString &iface, accessPointConfigurations.keys()) {
       
   945                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
       
   946                 if (priv.data()->state == QNetworkConfiguration::Active) {
       
   947                     online = true;
       
   948                     break;
       
   949                 }
       
   950             }
       
   951             if (iOnline != online) {
       
   952                 iOnline = online;
       
   953                 QT_TRYCATCH_LEAVING(emit this->onlineStateChanged(iOnline));
       
   954             }
       
   955         }
       
   956         }
       
   957         break;    
   928 
   958 
   929     case EConnMonIapAvailabilityChange:
   959     case EConnMonIapAvailabilityChange:
   930         {
   960         {
   931         CConnMonIapAvailabilityChange* realEvent;
   961         CConnMonIapAvailabilityChange* realEvent;
   932         realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
   962         realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
   935         for ( TUint i = 0; i < iaps.Count(); i++ ) {
   965         for ( TUint i = 0; i < iaps.Count(); i++ ) {
   936             QString ident = QString::number(qHash(iaps.iIap[i].iIapId));
   966             QString ident = QString::number(qHash(iaps.iIap[i].iIapId));
   937             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   967             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
   938             if (priv.data()) {
   968             if (priv.data()) {
   939                 // Configuration is either Discovered or Active 
   969                 // Configuration is either Discovered or Active 
   940                 changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered);
   970                 QT_TRYCATCH_LEAVING(changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered));
   941                 unDiscoveredConfigs.removeOne(ident);
   971                 unDiscoveredConfigs.removeOne(ident);
   942             }
   972             }
   943         }
   973         }
   944         foreach (const QString &iface, unDiscoveredConfigs) {
   974         foreach (const QString &iface, unDiscoveredConfigs) {
   945             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   975             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   946             if (priv.data()) {
   976             if (priv.data()) {
   947                 // Configuration is Defined
   977                 // Configuration is Defined
   948                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
   978                 QT_TRYCATCH_LEAVING(changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined));
   949             }
   979             }
   950         }
   980         }
   951         }
   981         }
   952         break;
   982         break;
   953 
   983 
       
   984     case EConnMonCreateConnection:
       
   985         {
       
   986         // This event is caught to keep connection monitor IDs up-to-date.
       
   987         CConnMonCreateConnection* realEvent;
       
   988         realEvent = (CConnMonCreateConnection*) &aEvent;
       
   989         TUint subConnectionCount = 0;
       
   990         TUint apId;
       
   991         TUint connectionId = realEvent->ConnectionId();
       
   992         TRequestStatus status;
       
   993         iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
       
   994         User::WaitForRequest(status);
       
   995         QString ident = QString::number(qHash(apId));
       
   996         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
       
   997         if (priv.data()) {
       
   998 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   999             qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << priv.data()->connectionId << connectionId << priv->name;
       
  1000 #endif
       
  1001             priv.data()->connectionId = connectionId;
       
  1002         }
       
  1003         }
       
  1004         break;
   954     default:
  1005     default:
   955         // For unrecognized events
  1006         // For unrecognized events
   956         break;
  1007         break;
   957     }
  1008     }
   958 }
  1009 }
   959 
  1010 
   960 // Waits for 1..4 seconds.
  1011 // Sessions may use this function to report configuration state changes,
   961 void QNetworkConfigurationManagerPrivate::waitRandomTime()
  1012 // because on some Symbian platforms (especially Symbian^3) all state changes are not
   962 {
  1013 // reported by the RConnectionMonitor, in particular in relation to stop() call,
   963     iTimeToWait = (qAbs(qrand()) % 5) * 1000;
  1014 // whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
       
  1015 // this data here so that other sessions may benefit from it too (not all sessions necessarily have
       
  1016 // RConnection progress notifiers available but they relay on having e.g. disconnected information from
       
  1017 // manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
       
  1018 void QNetworkConfigurationManagerPrivate::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
       
  1019 {
       
  1020 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1021     qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState;
       
  1022 #endif
       
  1023     switch (newState) {
       
  1024     case QNetworkSession::Disconnected:
       
  1025         {
       
  1026             QString ident = QString::number(qHash(accessPointId));
       
  1027             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
       
  1028             if (priv.data()) {
       
  1029                 // Configuration is either Defined or Discovered
       
  1030                 if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) {
       
  1031                     updateStatesToSnaps();
       
  1032                 }
       
  1033                 emit this->configurationStateChanged(
       
  1034                         priv.data()->numericId, priv.data()->connectionId, QNetworkSession::Disconnected);
       
  1035             }
       
  1036         }
       
  1037         break;
       
  1038     default:
       
  1039         break;
       
  1040     }
       
  1041 }
       
  1042 
       
  1043 // Waits for 2..6 seconds.
       
  1044 void QNetworkConfigurationManagerPrivate::updateConfigurationsAfterRandomTime()
       
  1045 {
       
  1046     iTimeToWait = (qAbs(qrand()) % 68) * 100;
   964     if (iTimeToWait < 1000) {
  1047     if (iTimeToWait < 1000) {
   965         iTimeToWait = 1000;
  1048         iTimeToWait = 1000;
   966     }
  1049     }
   967 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
  1050 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
   968     qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
  1051     qDebug("QNCM waiting random time: %d ms", iTimeToWait);
   969 #endif
  1052 #endif
   970     QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
  1053     QTimer::singleShot(iTimeToWait, this, SLOT(delayedConfigurationUpdate()));
   971     iIgnoreEventLoop->exec();
       
   972 }
  1054 }
   973 
  1055 
   974 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
  1056 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
   975 {
  1057 {
   976     QNetworkConfiguration item;
  1058     QNetworkConfiguration item;
   977     
       
   978     QHash<QString, QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> >::const_iterator i =
  1059     QHash<QString, QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> >::const_iterator i =
   979             accessPointConfigurations.constBegin();
  1060             accessPointConfigurations.constBegin();
   980     while (i != accessPointConfigurations.constEnd()) {
  1061     while (i != accessPointConfigurations.constEnd()) {
   981         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = i.value();
  1062         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = i.value();
   982         if (priv.data()->connectionId == aConnectionId) {
  1063         if (priv.data()->connectionId == aConnectionId) {
   988     return QExplicitlySharedDataPointer<QNetworkConfigurationPrivate>();
  1069     return QExplicitlySharedDataPointer<QNetworkConfigurationPrivate>();
   989 }
  1070 }
   990 
  1071 
   991 AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(QNetworkConfigurationManagerPrivate& owner,
  1072 AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(QNetworkConfigurationManagerPrivate& owner,
   992                                                                RConnectionMonitor& connectionMonitor)
  1073                                                                RConnectionMonitor& connectionMonitor)
   993     : CActive(CActive::EPriorityStandard), iOwner(owner), iConnectionMonitor(connectionMonitor)
  1074     : CActive(CActive::EPriorityHigh), iOwner(owner), iConnectionMonitor(connectionMonitor)
   994 {
  1075 {
   995     CActiveScheduler::Add(this);  
  1076     CActiveScheduler::Add(this);  
   996 }
  1077 }
   997 
  1078 
   998 AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
  1079 AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
  1026 
  1107 
  1027 void AccessPointsAvailabilityScanner::RunL()
  1108 void AccessPointsAvailabilityScanner::RunL()
  1028 {
  1109 {
  1029     if (iStatus.Int() != KErrNone) {
  1110     if (iStatus.Int() != KErrNone) {
  1030         iIapBuf().iCount = 0;
  1111         iIapBuf().iCount = 0;
  1031         iOwner.accessPointScanningReady(false,iIapBuf());
  1112         QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(false,iIapBuf()));
  1032     } else {
  1113     } else {
  1033         iOwner.accessPointScanningReady(true,iIapBuf());
  1114         QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(true,iIapBuf()));
  1034     }
  1115     }
  1035 }
  1116 }
  1036 #include "moc_qnetworkconfigmanager_s60_p.cpp"
  1117 #include "moc_qnetworkconfigmanager_s60_p.cpp"
  1037 QTM_END_NAMESPACE
  1118 QTM_END_NAMESPACE