Unsuccessful unlocking of QNetworkConfigurationPrivate mutex
[qt:qt.git] / src / plugins / bearer / symbian / symbianengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the plugins of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial Usage
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file.  Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** If you have questions regarding the use of this file, please contact
37 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "symbianengine.h"
43 #include "qnetworksession_impl.h"
44
45 #include <commdb.h>
46 #include <cdbcols.h>
47 #include <d32dbms.h>
48 #include <nifvar.h>
49 #include <QTimer>
50 #include <QTime>  // For randgen seeding
51 #include <QtCore> // For randgen seeding
52
53
54 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
55 #include <QDebug>
56 #endif
57
58 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
59     #include <cmdestination.h>
60     #include <cmconnectionmethod.h>
61     #include <cmconnectionmethoddef.h>
62     #include <cmpluginwlandef.h>
63     #include <cmpluginpacketdatadef.h>
64     #include <cmplugindialcommondefs.h>
65 #else
66     #include <ApAccessPointItem.h>
67     #include <ApDataHandler.h>
68     #include <ApUtils.h>
69 #endif
70
71 #ifndef QT_NO_BEARERMANAGEMENT
72
73 QT_BEGIN_NAMESPACE
74
75 static const int KUserChoiceIAPId = 0;
76
77 SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
78 :   numericId(0), connectionId(0)
79 {
80 }
81
82 SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate()
83 {
84 }
85
86 SymbianEngine::SymbianEngine(QObject *parent)
87 :   QBearerEngine(parent), CActive(CActive::EPriorityHigh), iFirstUpdate(true), ipCommsDB(0),
88     iInitOk(true), iUpdatePending(false), ipAccessPointsAvailabilityScanner(0)
89 {
90 }
91
92 void SymbianEngine::initialize()
93 {
94     QMutexLocker locker(&mutex);
95
96     CActiveScheduler::Add(this);
97
98     // Seed the randomgenerator
99     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
100
101     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
102     if (error != KErrNone) {
103         iInitOk = false;
104         return;
105     }
106
107     TRAP_IGNORE(iConnectionMonitor.ConnectL());
108 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
109     TRAP_IGNORE(iConnectionMonitor.SetUintAttribute(EBearerIdAll, 0, KBearerGroupThreshold, 1));
110 #endif
111     TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
112
113 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
114     TRAP(error, iCmManager.OpenL());
115     if (error != KErrNone) {
116         iInitOk = false;
117         return;
118     }
119 #endif
120
121     SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
122     cpPriv->name = "UserChoice";
123     cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
124     cpPriv->state = QNetworkConfiguration::Discovered;
125     cpPriv->isValid = true;
126     cpPriv->id = QString::number(qHash(KUserChoiceIAPId));
127     cpPriv->numericId = KUserChoiceIAPId;
128     cpPriv->connectionId = 0;
129     cpPriv->type = QNetworkConfiguration::UserChoice;
130     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
131     cpPriv->roamingSupported = false;
132
133     QNetworkConfigurationPrivatePointer ptr(cpPriv);
134     userChoiceConfigurations.insert(ptr->id, ptr);
135
136     updateConfigurations();
137     updateStatesToSnaps();
138     updateAvailableAccessPoints(); // On first time updates (without WLAN scans)
139     // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
140     startCommsDatabaseNotifications();
141 }
142
143 SymbianEngine::~SymbianEngine()
144 {
145     Cancel();
146
147     //The scanner may be using the connection monitor so it needs to be
148     //deleted first while the handle is still valid.
149     delete ipAccessPointsAvailabilityScanner;
150
151     iConnectionMonitor.CancelNotifications();
152     iConnectionMonitor.Close();
153     
154 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
155     iCmManager.Close();
156 #endif
157     
158     // CCommsDatabase destructor uses cleanup stack. Since QNetworkConfigurationManager
159     // is a global static, but the time we are here, E32Main() has been exited already and
160     // the thread's default cleanup stack has been deleted. Without this line, a
161     // 'E32USER-CBase 69' -panic will occur.
162     CTrapCleanup* cleanup = CTrapCleanup::New();
163     delete ipCommsDB;
164     delete cleanup;
165 }
166
167 void SymbianEngine::delayedConfigurationUpdate()
168 {
169     QMutexLocker locker(&mutex);
170
171     if (iUpdatePending) {
172 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
173         qDebug("QNCM delayed configuration update (ECommit or ERecover occurred).");
174 #endif
175         TRAPD(error, updateConfigurationsL());
176         if (error == KErrNone) {
177             updateStatesToSnaps();
178         }
179         iUpdatePending = false;
180         // Start monitoring again.
181         if (!IsActive()) {
182             SetActive();
183             // Start waiting for new notification
184             ipCommsDB->RequestNotification(iStatus);
185         }
186     }
187 }
188
189 bool SymbianEngine::hasIdentifier(const QString &id)
190 {
191     QMutexLocker locker(&mutex);
192
193     return accessPointConfigurations.contains(id) ||
194            snapConfigurations.contains(id) ||
195            userChoiceConfigurations.contains(id);
196 }
197
198 QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const
199 {
200     QNetworkConfigurationManager::Capabilities capFlags;
201
202     capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces |
203                QNetworkConfigurationManager::DirectConnectionRouting |
204                QNetworkConfigurationManager::SystemSessionSupport |
205                QNetworkConfigurationManager::DataStatistics |
206                QNetworkConfigurationManager::NetworkSessionRequired;
207
208 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
209     capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming |
210                 QNetworkConfigurationManager::ForcedRoaming;
211 #endif
212
213     return capFlags;
214 }
215
216 QNetworkSessionPrivate *SymbianEngine::createSessionBackend()
217 {
218     return new QNetworkSessionPrivateImpl(this);
219 }
220
221 void SymbianEngine::requestUpdate()
222 {
223     QMutexLocker locker(&mutex);
224
225     if (!iInitOk || iUpdateGoingOn) {
226         return;
227     }
228     iUpdateGoingOn = true;
229
230     stopCommsDatabaseNotifications();
231     updateConfigurations(); // Synchronous call
232     updateAvailableAccessPoints(); // Asynchronous call
233 }
234
235 void SymbianEngine::updateConfigurations()
236 {
237     if (!iInitOk)
238         return;
239
240     TRAP_IGNORE(updateConfigurationsL());
241 }
242
243 void SymbianEngine::updateConfigurationsL()
244 {
245     QList<QString> knownConfigs = accessPointConfigurations.keys();
246     QList<QString> knownSnapConfigs = snapConfigurations.keys();
247
248 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
249     // S60 version is >= Series60 3rd Edition Feature Pack 2
250     TInt error = KErrNone;
251     
252     // Loop through all IAPs
253     RArray<TUint32> connectionMethods; // IAPs
254     CleanupClosePushL(connectionMethods);
255     iCmManager.ConnectionMethodL(connectionMethods);
256     for(int i = 0; i < connectionMethods.Count(); i++) {
257         RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]);
258         CleanupClosePushL(connectionMethod);
259         TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
260         QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
261         if (accessPointConfigurations.contains(ident)) {
262             knownConfigs.removeOne(ident);
263         } else {
264             SymbianNetworkConfigurationPrivate* cpPriv = NULL;
265             TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
266             if (error == KErrNone) {
267                 QNetworkConfigurationPrivatePointer ptr(cpPriv);
268                 accessPointConfigurations.insert(ptr->id, ptr);
269                 if (!iFirstUpdate) {
270                     // Emit configuration added. Connected slots may throw execptions
271                     // which propagate here --> must be converted to leaves (standard
272                     // std::exception would cause any TRAP trapping this function to terminate
273                     // program).
274                     QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
275                     updateStatesToSnaps();
276                     mutex.unlock();
277                     QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
278                     mutex.lock();
279                 }
280             }
281         }
282         CleanupStack::PopAndDestroy(&connectionMethod);
283     }
284     CleanupStack::PopAndDestroy(&connectionMethods);
285     
286     // Loop through all SNAPs
287     RArray<TUint32> destinations;
288     CleanupClosePushL(destinations);
289     iCmManager.AllDestinationsL(destinations);
290     for(int i = 0; i < destinations.Count(); i++) {
291         RCmDestination destination;
292
293         // Some destinatsions require ReadDeviceData -capability (MMS/WAP)
294         // The below function will leave in these cases. Don't. Proceed to
295         // next destination (if any).
296         TRAPD(error, destination = iCmManager.DestinationL(destinations[i]));
297         if (error == KErrPermissionDenied) {
298             continue;
299         } else {
300             User::LeaveIfError(error);
301         }
302
303         CleanupClosePushL(destination);
304         QString ident = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX +
305                         QString::number(qHash(destination.Id()));
306         if (snapConfigurations.contains(ident)) {
307             knownSnapConfigs.removeOne(ident);
308         } else {
309             SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
310
311             HBufC *pName = destination.NameLC();
312             QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
313             CleanupStack::PopAndDestroy(pName);
314             pName = NULL;
315
316             cpPriv->isValid = true;
317             cpPriv->id = ident;
318             cpPriv->numericId = destination.Id();
319             cpPriv->connectionId = 0;
320             cpPriv->state = QNetworkConfiguration::Defined;
321             cpPriv->type = QNetworkConfiguration::ServiceNetwork;
322             cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
323             cpPriv->roamingSupported = false;
324
325             QNetworkConfigurationPrivatePointer ptr(cpPriv);
326             snapConfigurations.insert(ident, ptr);
327             if (!iFirstUpdate) {
328                 QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
329                 updateStatesToSnaps();
330                 mutex.unlock();
331                 QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
332                 mutex.lock();
333             }
334         }
335
336         // Loop through all connection methods in this SNAP
337         QMap<unsigned int, QNetworkConfigurationPrivatePointer> connections;
338         for (int j=0; j < destination.ConnectionMethodCount(); j++) {
339             RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
340             CleanupClosePushL(connectionMethod);
341
342             TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
343             QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
344             // Check that IAP can be found from accessPointConfigurations list
345             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
346             if (!ptr) {
347                 SymbianNetworkConfigurationPrivate *cpPriv = NULL;
348                 TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
349                 if (error == KErrNone) {
350                     ptr = QNetworkConfigurationPrivatePointer(cpPriv);
351                     accessPointConfigurations.insert(ptr->id, ptr);
352
353                     if (!iFirstUpdate) {
354                         QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
355                         updateStatesToSnaps();
356                         mutex.unlock();
357                         QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
358                         mutex.lock();
359                     }
360                 }
361             } else {
362                 knownConfigs.removeOne(iface);
363             }
364
365             if (ptr) {
366                 unsigned int priority;
367                 TRAPD(error, priority = destination.PriorityL(connectionMethod));
368                 if (!error)
369                     connections.insert(priority, ptr);
370             }
371
372             CleanupStack::PopAndDestroy(&connectionMethod);
373         }
374
375         QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident);
376         QMutexLocker snapConfigLocker(&privSNAP->mutex);
377
378         if (privSNAP->serviceNetworkMembers != connections) {
379             privSNAP->serviceNetworkMembers = connections;
380
381             // Roaming is supported only if SNAP contains more than one IAP
382             privSNAP->roamingSupported = privSNAP->serviceNetworkMembers.count() > 1;
383
384             snapConfigLocker.unlock();
385
386             updateStatesToSnaps();
387
388             mutex.unlock();
389             QT_TRYCATCH_LEAVING(emit configurationChanged(privSNAP));
390             mutex.lock();
391         }
392
393         CleanupStack::PopAndDestroy(&destination);
394     }
395     CleanupStack::PopAndDestroy(&destinations);
396 #else
397     // S60 version is < Series60 3rd Edition Feature Pack 2
398     CCommsDbTableView* pDbTView = ipCommsDB->OpenTableLC(TPtrC(IAP));
399
400     // Loop through all IAPs
401     TUint32 apId = 0;
402     TInt retVal = pDbTView->GotoFirstRecord();
403     while (retVal == KErrNone) {
404         pDbTView->ReadUintL(TPtrC(COMMDB_ID), apId);
405         QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
406         if (accessPointConfigurations.contains(ident)) {
407             knownConfigs.removeOne(ident);
408         } else {
409             SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
410             if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) {
411                 QNetworkConfigurationPrivatePointer ptr(cpPriv);
412                 accessPointConfigurations.insert(ident, ptr);
413                 if (!iFirstUpdate) {
414                     QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
415                     updateStatesToSnaps();
416                     mutex.unlock();
417                     QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
418                     mutex.lock();
419                 }
420             } else {
421                 delete cpPriv;
422             }
423         }
424         retVal = pDbTView->GotoNextRecord();
425     }
426     CleanupStack::PopAndDestroy(pDbTView);
427 #endif
428
429     QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
430
431     foreach (const QString &oldIface, knownConfigs) {
432         //remove non existing IAP
433         QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface);
434
435         mutex.unlock();
436         emit configurationRemoved(ptr);
437         QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr));
438         mutex.lock();
439
440         // Remove non existing IAP from SNAPs
441         foreach (const QString &iface, snapConfigurations.keys()) {
442             QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface);
443             // => Check if one of the IAPs of the SNAP is active
444             QMutexLocker snapConfigLocker(&ptr2->mutex);
445             QMutableMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr2->serviceNetworkMembers);
446             while (i.hasNext()) {
447                 i.next();
448
449                 if (toSymbianConfig(i.value())->numericIdentifier() ==
450                     toSymbianConfig(ptr)->numericIdentifier()) {
451                     i.remove();
452                     break;
453                 }
454             }
455         }    
456     }
457
458     foreach (const QString &oldIface, knownSnapConfigs) {
459         //remove non existing SNAPs
460         QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface);
461
462         mutex.unlock();
463         emit configurationRemoved(ptr);
464         QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr));
465         mutex.lock();
466     }
467
468     // find default configuration.
469     stopCommsDatabaseNotifications();
470     TRAP_IGNORE(defaultConfig = defaultConfigurationL());
471     startCommsDatabaseNotifications();
472
473 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
474     updateStatesToSnaps();
475 #endif
476 }
477
478 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
479 SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL(
480         RCmConnectionMethod& connectionMethod)
481 {
482     SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
483     TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
484     QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
485     
486     HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
487     CleanupStack::PushL(pName);
488     QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
489     CleanupStack::PopAndDestroy(pName);
490     pName = NULL;
491     
492     TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
493     switch (bearerId) {
494     case KCommDbBearerCSD:
495         cpPriv->bearerType = QNetworkConfiguration::Bearer2G;
496         break;
497     case KCommDbBearerWcdma:
498         cpPriv->bearerType = QNetworkConfiguration::BearerWCDMA;
499         break;
500     case KCommDbBearerLAN:
501         cpPriv->bearerType = QNetworkConfiguration::BearerEthernet;
502         break;
503     case KCommDbBearerVirtual:
504         cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
505         break;
506     case KCommDbBearerPAN:
507         cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
508         break;
509     case KCommDbBearerWLAN:
510         cpPriv->bearerType = QNetworkConfiguration::BearerWLAN;
511         break;
512     default:
513         cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
514         break;
515     }
516     
517     TInt error = KErrNone;
518     TUint32 bearerType = connectionMethod.GetIntAttributeL(CMManager::ECmBearerType);
519     switch (bearerType) {
520     case KUidPacketDataBearerType:
521         // "Packet data" Bearer => Mapping is done using "Access point name"
522         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EPacketDataAPName));
523         break;
524     case KUidWlanBearerType:
525         // "Wireless LAN" Bearer => Mapping is done using "WLAN network name" = SSID
526         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EWlanSSID));
527         break;
528     }
529     if (!pName) {
530         // "Data call" Bearer or "High Speed (GSM)" Bearer => Mapping is done using "Dial-up number"
531         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
532     }
533
534     if (error == KErrNone && pName) {
535         CleanupStack::PushL(pName);
536         QT_TRYCATCH_LEAVING(cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length()));
537         CleanupStack::PopAndDestroy(pName);
538         pName = NULL;
539     }
540  
541     cpPriv->state = QNetworkConfiguration::Defined;
542     TBool isConnected = connectionMethod.GetBoolAttributeL(CMManager::ECmConnected);
543     if (isConnected) {
544         cpPriv->state = QNetworkConfiguration::Active;
545     }
546     
547     cpPriv->isValid = true;
548     cpPriv->id = ident;
549     cpPriv->numericId = iapId;
550     cpPriv->connectionId = 0;
551     cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
552     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
553     cpPriv->roamingSupported = false;
554     return cpPriv;
555 }
556 #else
557 bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb(
558         TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
559 {
560     TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration));
561     if (error != KErrNone) {
562         return false;        
563     }
564     return true;
565 }
566
567 void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL(
568         TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
569 {
570     CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB); 
571     CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC(); 
572     TBuf<KCommsDbSvrMaxColumnNameLength> name;
573     
574     CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB);
575     TUint32 apId = pApUtils->WapIdFromIapIdL(aApId);
576     
577     pDataHandler->AccessPointDataL(apId,*pAPItem);
578     pAPItem->ReadTextL(EApIapName, name);
579     if (name.Compare(_L("Easy WLAN")) == 0) {
580         // "Easy WLAN" won't be accepted to the Configurations list
581         User::Leave(KErrNotFound);
582     }
583     
584     QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(aApId));
585     
586     QT_TRYCATCH_LEAVING(apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length()));
587     apNetworkConfiguration->isValid = true;
588     apNetworkConfiguration->id = ident;
589     apNetworkConfiguration->numericId = aApId;
590     apNetworkConfiguration->connectionId = 0;
591     apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
592     apNetworkConfiguration->type = QNetworkConfiguration::InternetAccessPoint;
593     apNetworkConfiguration->purpose = QNetworkConfiguration::UnknownPurpose;
594     apNetworkConfiguration->roamingSupported = false;
595     switch (pAPItem->BearerTypeL()) {
596     case EApBearerTypeCSD:      
597         apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G;
598         break;
599     case EApBearerTypeGPRS:
600         apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G;
601         break;
602     case EApBearerTypeHSCSD:
603         apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerHSPA;
604         break;
605     case EApBearerTypeCDMA:
606         apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerCDMA2000;
607         break;
608     case EApBearerTypeWLAN:
609         apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerWLAN;
610         break;
611     case EApBearerTypeLAN:
612         apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet;
613         break;
614     case EApBearerTypeLANModem:
615         apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet;
616         break;
617     default:
618         apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerUnknown;
619         break;
620     }
621     
622     CleanupStack::PopAndDestroy(pApUtils);
623     CleanupStack::PopAndDestroy(pAPItem);
624     CleanupStack::PopAndDestroy(pDataHandler);
625 }
626 #endif
627
628 QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration()
629 {
630     QMutexLocker locker(&mutex);
631
632     return defaultConfig;
633 }
634
635 QStringList SymbianEngine::accessPointConfigurationIdentifiers()
636 {
637     QMutexLocker locker(&mutex);
638
639     return accessPointConfigurations.keys();
640 }
641
642 QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL()
643 {
644     QNetworkConfigurationPrivatePointer ptr;
645
646 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
647     // Check Default Connection (SNAP or IAP)
648     TCmDefConnValue defaultConnectionValue;
649     iCmManager.ReadDefConnL(defaultConnectionValue);
650     if (defaultConnectionValue.iType == ECmDefConnDestination) {
651         QString iface = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX +
652                         QString::number(qHash(defaultConnectionValue.iId));
653         ptr = snapConfigurations.value(iface);
654     } else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) {
655         QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
656                         QString::number(qHash(defaultConnectionValue.iId));
657         ptr = accessPointConfigurations.value(iface);
658     }
659 #endif
660     
661     if (ptr) {
662         QMutexLocker configLocker(&ptr->mutex);
663         if (ptr->isValid)
664             return ptr;
665     }
666
667     QString iface = QString::number(qHash(KUserChoiceIAPId));
668     return userChoiceConfigurations.value(iface);
669 }
670
671 void SymbianEngine::updateActiveAccessPoints()
672 {
673     bool online = false;
674     QList<QString> inactiveConfigs = accessPointConfigurations.keys();
675
676     TRequestStatus status;
677     TUint connectionCount;
678     iConnectionMonitor.GetConnectionCount(connectionCount, status);
679     User::WaitForRequest(status);
680     
681     // Go through all connections and set state of related IAPs to Active.
682     // Status needs to be checked carefully, because ConnMon lists also e.g.
683     // WLAN connections that are being currently tried --> we don't want to
684     // state these as active.
685     TUint connectionId;
686     TUint subConnectionCount;
687     TUint apId;
688     TInt connectionStatus;
689     if (status.Int() == KErrNone) {
690         for (TUint i = 1; i <= connectionCount; i++) {
691             iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
692             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
693             User::WaitForRequest(status);
694             QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
695             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
696 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
697             if (!ptr) {
698                 // If IAP was not found, check if the update was about EasyWLAN
699                 ptr = configurationFromEasyWlan(apId, connectionId);
700                 // Change the ident correspondingly
701                 if (ptr) {
702                     ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
703                             QString::number(qHash(toSymbianConfig(ptr)->numericIdentifier()));
704                 }
705             }
706 #endif
707             if (ptr) {
708                 iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
709                 User::WaitForRequest(status);
710
711                 if (connectionStatus == KLinkLayerOpen) {
712                     online = true;
713                     inactiveConfigs.removeOne(ident);
714
715                     ptr->mutex.lock();
716                     toSymbianConfig(ptr)->connectionId = connectionId;
717                     ptr->mutex.unlock();
718
719                     // Configuration is Active
720                     changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
721                 }
722             }
723         }
724     }
725
726     // Make sure that state of rest of the IAPs won't be Active
727     foreach (const QString &iface, inactiveConfigs) {
728         QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
729         if (ptr) {
730             // Configuration is either Defined or Discovered
731             changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
732         }
733     }
734
735     if (iOnline != online) {
736         iOnline = online;
737         mutex.unlock();
738         emit this->onlineStateChanged(online);
739         mutex.lock();
740     }
741 }
742
743 void SymbianEngine::updateAvailableAccessPoints()
744 {
745     if (!ipAccessPointsAvailabilityScanner) {
746         ipAccessPointsAvailabilityScanner = new AccessPointsAvailabilityScanner(*this, iConnectionMonitor);
747     }
748     if (ipAccessPointsAvailabilityScanner) {
749         // Scanning may take a while because WLAN scanning will be done (if device supports WLAN).
750         ipAccessPointsAvailabilityScanner->StartScanning();
751     }
752 }
753
754 void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo)
755 {
756     iUpdateGoingOn = false;
757     if (scanSuccessful) {
758         QList<QString> unavailableConfigs = accessPointConfigurations.keys();
759         
760         // Set state of returned IAPs to Discovered
761         // if state is not already Active
762         for(TUint i=0; i<iapInfo.iCount; i++) {
763             QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
764                             QString::number(qHash(iapInfo.iIap[i].iIapId));
765             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
766             if (ptr) {
767                 unavailableConfigs.removeOne(ident);
768
769                 QMutexLocker configLocker(&ptr->mutex);
770                 if (ptr->state < QNetworkConfiguration::Active) {
771                     // Configuration is either Discovered or Active
772                     changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
773                 }
774             }
775         }
776         
777         // Make sure that state of rest of the IAPs won't be Active
778         foreach (const QString &iface, unavailableConfigs) {
779             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
780             if (ptr) {
781                 // Configuration is Defined
782                 changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
783             }
784         }
785     }
786
787     updateStatesToSnaps();
788     
789     if (!iFirstUpdate) {
790         startCommsDatabaseNotifications();
791         mutex.unlock();
792         emit updateCompleted();
793         mutex.lock();
794     } else {
795         iFirstUpdate = false;
796         if (iScanInQueue) {
797             iScanInQueue = EFalse;
798             updateAvailableAccessPoints();
799         }
800     }
801 }
802
803 void SymbianEngine::updateStatesToSnaps()
804 {
805     // Go through SNAPs and set correct state to SNAPs
806     foreach (const QString &iface, snapConfigurations.keys()) {
807         bool discovered = false;
808         bool active = false;
809         QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
810
811         QMutexLocker snapConfigLocker(&ptr->mutex);
812
813         // => Check if one of the IAPs of the SNAP is discovered or active
814         //    => If one of IAPs is active, also SNAP is active
815         //    => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered
816         QMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr->serviceNetworkMembers);
817         while (i.hasNext()) {
818             i.next();
819
820             const QNetworkConfigurationPrivatePointer child = i.value();
821
822             QMutexLocker configLocker(&child->mutex);
823
824             if ((child->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
825                 active = true;
826                 break;
827             } else if ((child->state & QNetworkConfiguration::Discovered) ==
828                        QNetworkConfiguration::Discovered) {
829                 discovered = true;
830             }
831         }
832         snapConfigLocker.unlock();
833         if (active) {
834             changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
835         } else if (discovered) {
836             changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
837         } else {
838             changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
839         }
840     }    
841 }
842
843 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
844 void SymbianEngine::updateMobileBearerToConfigs(TConnMonBearerInfo bearerInfo)
845 {
846     QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
847         accessPointConfigurations.constBegin();
848     while (i != accessPointConfigurations.constEnd()) {
849         QNetworkConfigurationPrivatePointer ptr = i.value();
850
851         QMutexLocker locker(&ptr->mutex);
852
853         SymbianNetworkConfigurationPrivate *p = toSymbianConfig(ptr);
854
855         if (p->bearerType >= QNetworkConfiguration::Bearer2G &&
856             p->bearerType <= QNetworkConfiguration::BearerHSPA) {
857             switch (bearerInfo) {
858             case EBearerInfoCSD:
859                 p->bearerType = QNetworkConfiguration::Bearer2G;
860                 break;
861             case EBearerInfoWCDMA:
862                 p->bearerType = QNetworkConfiguration::BearerWCDMA;
863                 break;
864             case EBearerInfoCDMA2000:
865                 p->bearerType = QNetworkConfiguration::BearerCDMA2000;
866                 break;
867             case EBearerInfoGPRS:
868                 p->bearerType = QNetworkConfiguration::Bearer2G;
869                 break;
870             case EBearerInfoHSCSD:
871                 p->bearerType = QNetworkConfiguration::Bearer2G;
872                 break;
873             case EBearerInfoEdgeGPRS:
874                 p->bearerType = QNetworkConfiguration::Bearer2G;
875                 break;
876             case EBearerInfoWcdmaCSD:
877                 p->bearerType = QNetworkConfiguration::BearerWCDMA;
878                 break;
879             case EBearerInfoHSDPA:
880                 p->bearerType = QNetworkConfiguration::BearerHSPA;
881                 break;
882             case EBearerInfoHSUPA:
883                 p->bearerType = QNetworkConfiguration::BearerHSPA;
884                 break;
885             case EBearerInfoHSxPA:
886                 p->bearerType = QNetworkConfiguration::BearerHSPA;
887                 break;
888             }
889         }
890
891         ++i;
892     }
893 }
894 #endif
895
896 bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
897                                                QNetworkConfiguration::StateFlags newState)
898 {
899     ptr->mutex.lock();
900     if (newState != ptr->state) {
901         ptr->state = newState;
902         ptr->mutex.unlock();
903
904         mutex.unlock();
905         emit configurationChanged(ptr);
906         mutex.lock();
907
908         return true;
909     } else {
910         ptr->mutex.unlock();
911     }
912     return false;
913 }
914
915 /* changeConfigurationStateAtMinTo function does not overwrite possible better
916  * state (e.g. Discovered state does not overwrite Active state) but
917  * makes sure that state is at minimum given state.
918 */
919 bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
920                                                     QNetworkConfiguration::StateFlags newState)
921 {
922     ptr->mutex.lock();
923     if ((newState | ptr->state) != ptr->state) {
924         ptr->state = (ptr->state | newState);
925         ptr->mutex.unlock();
926
927         mutex.unlock();
928         emit configurationChanged(ptr);
929         mutex.lock();
930
931         return true;
932     } else {
933         ptr->mutex.unlock();
934     }
935     return false;
936 }
937
938 /* changeConfigurationStateAtMaxTo function overwrites possible better
939  * state (e.g. Discovered state overwrites Active state) and
940  * makes sure that state is at maximum given state (e.g. Discovered state
941  * does not overwrite Defined state).
942 */
943 bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
944                                                     QNetworkConfiguration::StateFlags newState)
945 {
946     ptr->mutex.lock();
947     if ((newState & ptr->state) != ptr->state) {
948         ptr->state = (newState & ptr->state);
949         ptr->mutex.unlock();
950
951         mutex.unlock();
952         emit configurationChanged(ptr);
953         mutex.lock();
954
955         return true;
956     } else {
957         ptr->mutex.unlock();
958     }
959     return false;
960 }
961
962 void SymbianEngine::startCommsDatabaseNotifications()
963 {
964     if (!iWaitingCommsDatabaseNotifications) {
965         iWaitingCommsDatabaseNotifications = ETrue;
966         if (!IsActive()) {
967             SetActive();
968             // Start waiting for new notification
969             ipCommsDB->RequestNotification(iStatus);
970         }
971     }
972 }
973
974 void SymbianEngine::stopCommsDatabaseNotifications()
975 {
976     if (iWaitingCommsDatabaseNotifications) {
977         iWaitingCommsDatabaseNotifications = EFalse;
978         Cancel();
979     }
980 }
981
982 void SymbianEngine::RunL()
983 {
984     QMutexLocker locker(&mutex);
985
986     if (iStatus != KErrCancel) {
987         // By default, start relistening notifications. Stop only if interesting event occurred.
988         iWaitingCommsDatabaseNotifications = true;
989         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
990         switch (event) {
991         case RDbNotifier::ECommit:   /** A transaction has been committed.  */
992         case RDbNotifier::ERecover:  /** The database has been recovered    */
993 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
994             qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
995 #endif
996             // Mark that there is update pending. No need to ask more events,
997             // as we know we will be updating anyway when the timer expires.
998             if (!iUpdatePending) {
999                 iUpdatePending = true;
1000                 iWaitingCommsDatabaseNotifications = false;
1001                 // Update after random time, so that many processes won't
1002                 // start updating simultaneously
1003                 updateConfigurationsAfterRandomTime();
1004             }
1005             break;
1006         default:
1007             // Do nothing
1008             break;
1009         }
1010     }
1011
1012     if (iWaitingCommsDatabaseNotifications) {
1013         if (!IsActive()) {
1014             SetActive();
1015             // Start waiting for new notification
1016             ipCommsDB->RequestNotification(iStatus);
1017         }
1018     }
1019 }
1020
1021 void SymbianEngine::DoCancel()
1022 {
1023     QMutexLocker locker(&mutex);
1024
1025     ipCommsDB->CancelRequestNotification();
1026 }
1027
1028 void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
1029 {
1030     QMutexLocker locker(&mutex);
1031
1032     switch (aEvent.EventType()) {
1033 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
1034     case EConnMonBearerInfoChange:
1035         {
1036         CConnMonBearerInfoChange* realEvent;
1037         realEvent = (CConnMonBearerInfoChange*) &aEvent;
1038         TUint connectionId = realEvent->ConnectionId();
1039         if (connectionId == EBearerIdAll) {
1040             //Network level event
1041             TConnMonBearerInfo bearerInfo = (TConnMonBearerInfo)realEvent->BearerInfo();
1042             updateMobileBearerToConfigs(bearerInfo);
1043         }
1044         break;
1045         }
1046 #endif
1047     case EConnMonConnectionStatusChange:
1048         {
1049         CConnMonConnectionStatusChange* realEvent;
1050         realEvent = (CConnMonConnectionStatusChange*) &aEvent;
1051         TInt connectionStatus = realEvent->ConnectionStatus();
1052 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
1053         qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId();
1054 #endif
1055         if (connectionStatus == KConfigDaemonStartingRegistration) {
1056             TUint connectionId = realEvent->ConnectionId();
1057             TUint subConnectionCount = 0;
1058             TUint apId;            
1059             TRequestStatus status;
1060             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
1061             User::WaitForRequest(status);
1062
1063             QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
1064             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
1065 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
1066             if (!ptr) {
1067                 // Check if status was regarding EasyWLAN
1068                 ptr = configurationFromEasyWlan(apId, connectionId);
1069             }
1070 #endif
1071             if (ptr) {
1072                 ptr->mutex.lock();
1073                 toSymbianConfig(ptr)->connectionId = connectionId;
1074                 ptr->mutex.unlock();
1075                 QT_TRYCATCH_LEAVING(
1076                     emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
1077                                                    connectionId, QNetworkSession::Connecting)
1078                 );
1079             }
1080         } else if (connectionStatus == KLinkLayerOpen) {
1081             // Connection has been successfully opened
1082             TUint connectionId = realEvent->ConnectionId();
1083             TUint subConnectionCount = 0;
1084             TUint apId;            
1085             TRequestStatus status;
1086             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
1087             User::WaitForRequest(status);
1088             QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
1089             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
1090 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
1091             if (!ptr) {
1092                 // Check for EasyWLAN
1093                 ptr = configurationFromEasyWlan(apId, connectionId);
1094             }
1095 #endif
1096             if (ptr) {
1097                 ptr->mutex.lock();
1098                 toSymbianConfig(ptr)->connectionId = connectionId;
1099                 ptr->mutex.unlock();
1100
1101                 // Configuration is Active
1102                 QT_TRYCATCH_LEAVING(
1103                     if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) {
1104                         updateStatesToSnaps();
1105                     }
1106                     emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
1107                                                    connectionId, QNetworkSession::Connected);
1108
1109                     if (!iOnline) {
1110                         iOnline = true;
1111                         emit this->onlineStateChanged(iOnline);
1112                     }
1113                 );
1114             }
1115         } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
1116             TUint connectionId = realEvent->ConnectionId();
1117             QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
1118             if (ptr) {
1119                 QT_TRYCATCH_LEAVING(
1120                     emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
1121                                                    connectionId, QNetworkSession::Closing)
1122                 );
1123             }
1124         } else if (connectionStatus == KLinkLayerClosed ||
1125                    connectionStatus == KConnectionClosed) {
1126             // Connection has been closed. Which of the above events is reported, depends on the Symbian
1127             // platform.
1128             TUint connectionId = realEvent->ConnectionId();
1129             QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
1130             if (ptr) {
1131                 // Configuration is either Defined or Discovered
1132                 QT_TRYCATCH_LEAVING(
1133                     if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
1134                         updateStatesToSnaps();
1135                     }
1136                     emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
1137                                                    connectionId, QNetworkSession::Disconnected);
1138                 );
1139             }
1140             
1141             bool online = false;
1142             foreach (const QString &iface, accessPointConfigurations.keys()) {
1143                 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
1144                 QMutexLocker configLocker(&ptr->mutex);
1145                 if (ptr->state == QNetworkConfiguration::Active) {
1146                     online = true;
1147                     break;
1148                 }
1149             }
1150             if (iOnline != online) {
1151                 iOnline = online;
1152                 QT_TRYCATCH_LEAVING(emit this->onlineStateChanged(iOnline));
1153             }
1154         }
1155         }
1156         break;    
1157
1158     case EConnMonIapAvailabilityChange:
1159         {
1160         CConnMonIapAvailabilityChange* realEvent;
1161         realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
1162         TConnMonIapInfo iaps = realEvent->IapAvailability();
1163         QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys();
1164         for ( TUint i = 0; i < iaps.Count(); i++ ) {
1165             QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
1166                             QString::number(qHash(iaps.iIap[i].iIapId));
1167
1168             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
1169             if (ptr) {
1170                 // Configuration is either Discovered or Active 
1171                 QT_TRYCATCH_LEAVING(changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered));
1172                 unDiscoveredConfigs.removeOne(ident);
1173             }
1174         }
1175         foreach (const QString &iface, unDiscoveredConfigs) {
1176             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
1177             if (ptr) {
1178                 // Configuration is Defined
1179                 QT_TRYCATCH_LEAVING(changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined));
1180             }
1181         }
1182         // Something has in IAPs, update states to SNAPs
1183         updateStatesToSnaps();
1184         }
1185         break;
1186
1187     case EConnMonCreateConnection:
1188         {
1189         // This event is caught to keep connection monitor IDs up-to-date.
1190         CConnMonCreateConnection* realEvent;
1191         realEvent = (CConnMonCreateConnection*) &aEvent;
1192         TUint subConnectionCount = 0;
1193         TUint apId;
1194         TUint connectionId = realEvent->ConnectionId();
1195         TRequestStatus status;
1196         iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
1197         User::WaitForRequest(status);
1198         QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
1199         QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
1200 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
1201         if (!ptr) {
1202             // If IAP was not found, check if the update was about EasyWLAN
1203             ptr = configurationFromEasyWlan(apId, connectionId);
1204         }
1205 #endif
1206         if (ptr) {
1207             QMutexLocker configLocker(&ptr->mutex);
1208 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
1209             qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name;
1210 #endif
1211             toSymbianConfig(ptr)->connectionId = connectionId;
1212         }
1213         }
1214         break;
1215     default:
1216         // For unrecognized events
1217         break;
1218     }
1219 }
1220
1221 /*
1222     Returns the network configuration that matches the given SSID.
1223 */
1224 QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromSsid(const QString &ssid)
1225 {
1226     QMutexLocker locker(&mutex);
1227
1228     // Browser through all items and check their name for match
1229     QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i =
1230         accessPointConfigurations.constBegin();
1231     while (i != accessPointConfigurations.constEnd()) {
1232         QNetworkConfigurationPrivatePointer ptr = i.value();
1233
1234         QMutexLocker configLocker(&ptr->mutex);
1235
1236         if (ptr->name == ssid) {
1237 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
1238             qDebug() << "QNCM EasyWlan uses real SSID: " << ssid;
1239 #endif
1240             return ptr;
1241         }
1242         ++i;
1243     }
1244
1245     return QNetworkConfigurationPrivatePointer();
1246 }
1247
1248 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
1249 // Tries to derive configuration from EasyWLAN.
1250 // First checks if the interface brought up was EasyWLAN, then derives the real SSID,
1251 // and looks up configuration based on that one.
1252 QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUint32 apId,
1253                                                                              TUint connectionId)
1254 {
1255     if (apId == iCmManager.EasyWlanIdL()) {
1256         TRequestStatus status;
1257         TBuf<50> easyWlanNetworkName;
1258         iConnectionMonitor.GetStringAttribute( connectionId, 0, KNetworkName,
1259                                                easyWlanNetworkName, status );
1260         User::WaitForRequest(status);
1261         if (status.Int() == KErrNone) {
1262             const QString realSSID = QString::fromUtf16(easyWlanNetworkName.Ptr(),
1263                                                         easyWlanNetworkName.Length());
1264
1265             // Browser through all items and check their name for match
1266             QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i =
1267                 accessPointConfigurations.constBegin();
1268             while (i != accessPointConfigurations.constEnd()) {
1269                 QNetworkConfigurationPrivatePointer ptr = i.value();
1270
1271                 QMutexLocker configLocker(&ptr->mutex);
1272
1273                 if (ptr->name == realSSID) {
1274 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
1275                     qDebug() << "QNCM EasyWlan uses real SSID: " << realSSID;
1276 #endif
1277                     return ptr;
1278                 }
1279                 ++i;
1280             }
1281         }
1282     }
1283     return QNetworkConfigurationPrivatePointer();
1284 }
1285 #endif
1286
1287 // Sessions may use this function to report configuration state changes,
1288 // because on some Symbian platforms (especially Symbian^3) all state changes are not
1289 // reported by the RConnectionMonitor, in particular in relation to stop() call,
1290 // whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
1291 // this data here so that other sessions may benefit from it too (not all sessions necessarily have
1292 // RConnection progress notifiers available but they relay on having e.g. disconnected information from
1293 // manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
1294 void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
1295 {
1296     QMutexLocker locker(&mutex);
1297
1298 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
1299     qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState;
1300 #endif
1301     switch (newState) {
1302     case QNetworkSession::Disconnected:
1303         {
1304             QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
1305                             QString::number(qHash(accessPointId));
1306             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
1307             if (ptr) {
1308                 // Configuration is either Defined or Discovered
1309                 if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
1310                     updateStatesToSnaps();
1311                 }
1312
1313                 locker.unlock();
1314                 emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
1315                                                toSymbianConfig(ptr)->connectionIdentifier(),
1316                                                QNetworkSession::Disconnected);
1317                 locker.relock();
1318             }
1319         }
1320         break;
1321     default:
1322         break;
1323     }
1324 }
1325
1326 // Waits for 2..6 seconds.
1327 void SymbianEngine::updateConfigurationsAfterRandomTime()
1328 {
1329     int iTimeToWait = qMax(1000, (qAbs(qrand()) % 68) * 100);
1330 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
1331     qDebug("QNCM waiting random time: %d ms", iTimeToWait);
1332 #endif
1333     QTimer::singleShot(iTimeToWait, this, SLOT(delayedConfigurationUpdate()));
1334 }
1335
1336 QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
1337 {
1338     QNetworkConfiguration item;
1339     QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
1340             accessPointConfigurations.constBegin();
1341     while (i != accessPointConfigurations.constEnd()) {
1342         QNetworkConfigurationPrivatePointer ptr = i.value();
1343         if (toSymbianConfig(ptr)->connectionIdentifier() == aConnectionId)
1344             return ptr;
1345
1346         ++i;
1347     }
1348
1349     return QNetworkConfigurationPrivatePointer();
1350 }
1351
1352 AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner,
1353                                                                RConnectionMonitor& connectionMonitor)
1354     : CActive(CActive::EPriorityHigh), iOwner(owner), iConnectionMonitor(connectionMonitor)
1355 {
1356     CActiveScheduler::Add(this);  
1357 }
1358
1359 AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
1360 {
1361     Cancel();
1362 }
1363
1364 void AccessPointsAvailabilityScanner::DoCancel()
1365 {
1366     iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute);
1367     iScanActive = EFalse;
1368     iOwner.iScanInQueue = EFalse;
1369 }
1370
1371 void AccessPointsAvailabilityScanner::StartScanning()
1372 {
1373     if (!iScanActive) {
1374         iScanActive = ETrue;
1375         if (iOwner.iFirstUpdate) {
1376             // On first update (the mgr is being instantiated) update only those bearers who
1377             // don't need time-consuming scans (WLAN).
1378             // Note: EBearerIdWCDMA covers also GPRS bearer
1379             iConnectionMonitor.GetPckgAttribute(EBearerIdWCDMA, 0, KIapAvailability, iIapBuf, iStatus);
1380         } else {
1381             iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus);
1382         }
1383
1384         if (!IsActive()) {
1385             SetActive();
1386         }
1387     } else {
1388         // Queue scan for getting WLAN info after first request returns
1389         if (iOwner.iFirstUpdate) {
1390             iOwner.iScanInQueue = ETrue;
1391         }
1392     }
1393 }
1394
1395 void AccessPointsAvailabilityScanner::RunL()
1396 {
1397     QMutexLocker locker(&iOwner.mutex);
1398
1399     iScanActive = EFalse;
1400     if (iStatus.Int() != KErrNone) {
1401         iIapBuf().iCount = 0;
1402         QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(false,iIapBuf()));
1403     } else {
1404         QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(true,iIapBuf()));
1405     }
1406 }
1407
1408 QT_END_NAMESPACE
1409
1410 #endif // QT_NO_BEARERMANAGEMENT