qtmobility/src/bearer/qnetworksession_s60_p.cpp
branchRCL_3
changeset 9 5d007b20cfd0
parent 8 885c2596c964
child 10 cd2778e5acfe
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <qmobilityglobal.h>
       
    43 #include "qnetworksession_s60_p.h"
       
    44 #include "qnetworkconfiguration_s60_p.h"
       
    45 #include "qnetworkconfigmanager_s60_p.h"
       
    46 #include <es_enum.h>
       
    47 #include <es_sock.h>
       
    48 #include <in_sock.h>
       
    49 #include <stdapis/sys/socket.h>
       
    50 #include <stdapis/net/if.h>
       
    51 
       
    52 QTM_BEGIN_NAMESPACE
       
    53 
       
    54 QNetworkSessionPrivate::QNetworkSessionPrivate()
       
    55     : CActive(CActive::EPriorityUserInput), state(QNetworkSession::Invalid),
       
    56       isOpen(false), iDynamicUnSetdefaultif(0), ipConnectionNotifier(0),
       
    57       iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false),
       
    58       iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0),
       
    59       iConnectInBackground(false), isOpening(false)
       
    60 {
       
    61     CActiveScheduler::Add(this);
       
    62 
       
    63 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
    64     iMobility = NULL;
       
    65 #endif
       
    66     // Try to load "Open C" dll dynamically and
       
    67     // try to attach to unsetdefaultif function dynamically.
       
    68     // This is to avoid build breaks with old OpenC versions.
       
    69     if (iOpenCLibrary.Load(_L("libc")) == KErrNone) {
       
    70         iDynamicUnSetdefaultif = (TOpenCUnSetdefaultifFunction)iOpenCLibrary.Lookup(597);
       
    71     }
       
    72 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
    73     qDebug() << "QNS this : " << QString::number((uint)this) << " - ";
       
    74     if (iDynamicUnSetdefaultif)
       
    75         qDebug() << "dynamic unsetdefaultif() is present in PIPS library. ";
       
    76     else
       
    77         qDebug() << "dynamic unsetdefaultif() not present in PIPS library. ";
       
    78 #endif
       
    79 
       
    80     TRAP_IGNORE(iConnectionMonitor.ConnectL());
       
    81 }
       
    82 
       
    83 QNetworkSessionPrivate::~QNetworkSessionPrivate()
       
    84 {
       
    85     isOpen = false;
       
    86     isOpening = false;
       
    87 
       
    88     // Cancel Connection Progress Notifications first.
       
    89     // Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start()
       
    90     //       => deleting ipConnectionNotifier results RConnection::CancelProgressNotification()
       
    91     delete ipConnectionNotifier;
       
    92     ipConnectionNotifier = NULL;
       
    93 
       
    94 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
    95     if (iMobility) {
       
    96         delete iMobility;
       
    97         iMobility = NULL;
       
    98     }
       
    99 #endif
       
   100 
       
   101     // Cancel possible RConnection::Start()
       
   102     Cancel();
       
   103     iSocketServ.Close();
       
   104     
       
   105     // Close global 'Open C' RConnection
       
   106     // Clears also possible unsetdefaultif() flags.
       
   107     setdefaultif(0);
       
   108     
       
   109     iConnectionMonitor.Close();
       
   110     iOpenCLibrary.Close();
       
   111 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   112     qDebug() << "QNS this : " << QString::number((uint)this) << " - destroyed (and setdefaultif(0))";
       
   113 #endif
       
   114 }
       
   115 
       
   116 void QNetworkSessionPrivate::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState)
       
   117 {
       
   118     if (iHandleStateNotificationsFromManager) {
       
   119 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   120         qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   121                  << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId)
       
   122                  << "connMon ID : " << QString::number(connMonId) << " : to a state: " << newState
       
   123                  << "whereas my current state is: " << state;
       
   124 #else
       
   125       Q_UNUSED(connMonId);
       
   126 #endif
       
   127         this->newState(newState, accessPointId);
       
   128     }
       
   129 }
       
   130 
       
   131 void QNetworkSessionPrivate::configurationRemoved(const QNetworkConfiguration& config)
       
   132 {
       
   133     if (!publicConfig.d.data()) {
       
   134         return;
       
   135     }
       
   136     if (config.d.data()->numericId == publicConfig.d.data()->numericId) {
       
   137 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   138         qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   139                  << "configurationRemoved IAP: " << QString::number(publicConfig.d.data()->numericId) << " : going to State: Invalid";
       
   140 #endif
       
   141         this->newState(QNetworkSession::Invalid, publicConfig.d.data()->numericId);
       
   142     }
       
   143 }
       
   144 
       
   145 void QNetworkSessionPrivate::configurationAdded(const QNetworkConfiguration& config)
       
   146 {
       
   147     Q_UNUSED(config);
       
   148     // If session is based on service network, some other app may create new access points
       
   149     // to the SNAP --> synchronize session's state with that of interface's.
       
   150     if (!publicConfig.d.data() || publicConfig.type() != QNetworkConfiguration::ServiceNetwork) {
       
   151         return;
       
   152     }
       
   153 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   154         qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   155                  << "configurationAdded IAP: " << QString::number(config.d.data()->numericId);
       
   156 #endif
       
   157         syncStateWithInterface();
       
   158 }
       
   159 
       
   160 // Function sets the state of the session to match the state
       
   161 // of the underlying interface (the configuration this session is based on)
       
   162 void QNetworkSessionPrivate::syncStateWithInterface()
       
   163 {
       
   164     if (!publicConfig.d || !publicConfig.d.data()) {
       
   165         return;
       
   166     }
       
   167     if (iFirstSync) {
       
   168         QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager), SIGNAL(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)),
       
   169                          this, SLOT(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)));
       
   170         // Listen to configuration removals, so that in case the configuration
       
   171         // this session is based on is removed, session knows to enter Invalid -state.
       
   172         QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager),
       
   173                          SIGNAL(configurationRemoved(QNetworkConfiguration)),
       
   174                          this, SLOT(configurationRemoved(QNetworkConfiguration)));
       
   175         // Connect to configuration additions, so that in case a configuration is added
       
   176         // in a SNAP this session is based on, the session knows to synch its state with its
       
   177         // interface.
       
   178         QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager),
       
   179                          SIGNAL(configurationAdded(QNetworkConfiguration)),
       
   180                          this, SLOT(configurationAdded(QNetworkConfiguration)));
       
   181     }
       
   182     // Start listening IAP state changes from QNetworkConfigurationManagerPrivate
       
   183     iHandleStateNotificationsFromManager = true;    
       
   184 
       
   185     // Check what is the state of the configuration this session is based on
       
   186     // and set the session in appropriate state.
       
   187 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   188     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   189              << "syncStateWithInterface() state of publicConfig is: " << publicConfig.d.data()->state;
       
   190 #endif
       
   191     switch (publicConfig.d.data()->state) {
       
   192     case QNetworkConfiguration::Active:
       
   193         newState(QNetworkSession::Connected);
       
   194         break;
       
   195     case QNetworkConfiguration::Discovered:
       
   196         newState(QNetworkSession::Disconnected);
       
   197         break;
       
   198     case QNetworkConfiguration::Defined:
       
   199         newState(QNetworkSession::NotAvailable);
       
   200         break;
       
   201     case QNetworkConfiguration::Undefined:
       
   202     default:
       
   203         newState(QNetworkSession::Invalid);
       
   204     }
       
   205 }
       
   206 
       
   207 QNetworkInterface QNetworkSessionPrivate::interface(TUint iapId) const
       
   208 {
       
   209     QString interfaceName;
       
   210 
       
   211     TSoInetInterfaceInfo ifinfo;
       
   212     TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);
       
   213     TSoInetIfQuery ifquery;
       
   214     TPckg<TSoInetIfQuery> ifquerypkg(ifquery);
       
   215  
       
   216     // Open dummy socket for interface queries
       
   217     RSocket socket;
       
   218     TInt retVal = socket.Open(iSocketServ, _L("udp"));
       
   219     if (retVal != KErrNone) {
       
   220         return QNetworkInterface();
       
   221     }
       
   222  
       
   223     // Start enumerating interfaces
       
   224     socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
       
   225     while(socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {
       
   226         ifquery.iName = ifinfo.iName;
       
   227         TInt err = socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);
       
   228         if(err == KErrNone && ifquery.iZone[1] == iapId) { // IAP ID is index 1 of iZone
       
   229             if(ifinfo.iAddress.Address() > 0) {
       
   230                 interfaceName = QString::fromUtf16(ifinfo.iName.Ptr(),ifinfo.iName.Length());
       
   231                 break;
       
   232             }
       
   233         }
       
   234     }
       
   235  
       
   236     socket.Close();
       
   237  
       
   238     if (interfaceName.isEmpty()) {
       
   239         return QNetworkInterface();
       
   240     }
       
   241  
       
   242     return QNetworkInterface::interfaceFromName(interfaceName);
       
   243 }
       
   244 
       
   245 QNetworkInterface QNetworkSessionPrivate::currentInterface() const
       
   246 {
       
   247 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   248     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   249              << "currentInterface() requested, state: " << state
       
   250              << "publicConfig validity: " << publicConfig.isValid();
       
   251     if (activeInterface.isValid())
       
   252         qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   253                  << "interface is: " << activeInterface.humanReadableName();
       
   254 #endif
       
   255 
       
   256     if (!publicConfig.isValid() || state != QNetworkSession::Connected) {
       
   257         return QNetworkInterface();
       
   258     }
       
   259     
       
   260     return activeInterface;
       
   261 }
       
   262 
       
   263 QVariant QNetworkSessionPrivate::sessionProperty(const QString& key) const
       
   264 {
       
   265     if (key == "ConnectInBackground") {
       
   266         return QVariant(iConnectInBackground);
       
   267     }
       
   268     return QVariant();
       
   269 }
       
   270 
       
   271 void QNetworkSessionPrivate::setSessionProperty(const QString& key, const QVariant& value)
       
   272 {
       
   273     // Valid value means adding property, invalid means removing it.
       
   274     if (key == "ConnectInBackground") {
       
   275         if (value.isValid()) {
       
   276             iConnectInBackground = value.toBool();
       
   277         } else {
       
   278             iConnectInBackground = EFalse;
       
   279         }
       
   280     }
       
   281 }
       
   282 
       
   283 QString QNetworkSessionPrivate::errorString() const
       
   284 {
       
   285     switch (iError) {
       
   286     case QNetworkSession::UnknownSessionError:
       
   287         return tr("Unknown session error.");
       
   288     case QNetworkSession::SessionAbortedError:
       
   289         return tr("The session was aborted by the user or system.");
       
   290     case QNetworkSession::OperationNotSupportedError:
       
   291         return tr("The requested operation is not supported by the system.");
       
   292     case QNetworkSession::InvalidConfigurationError:
       
   293         return tr("The specified configuration cannot be used.");
       
   294     case QNetworkSession::RoamingError:
       
   295         return tr("Roaming was aborted or is not possible.");
       
   296     }
       
   297  
       
   298     return QString();
       
   299 }
       
   300 
       
   301 QNetworkSession::SessionError QNetworkSessionPrivate::error() const
       
   302 {
       
   303     return iError;
       
   304 }
       
   305 
       
   306 void QNetworkSessionPrivate::open()
       
   307 {
       
   308 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   309         qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   310                 << "open() called, session state is: " << state << " and isOpen is: "
       
   311                 << isOpen;
       
   312 #endif
       
   313     if (isOpen || isOpening)
       
   314         return;
       
   315     
       
   316     isOpening = true;
       
   317 
       
   318     // Stop handling IAP state change signals from QNetworkConfigurationManagerPrivate
       
   319     // => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
       
   320     iHandleStateNotificationsFromManager = false;
       
   321 
       
   322     // Configuration may have been invalidated after session creation by platform
       
   323     // (e.g. configuration has been deleted).
       
   324     if (!publicConfig.isValid()) {
       
   325         newState(QNetworkSession::Invalid);
       
   326         iError = QNetworkSession::InvalidConfigurationError;
       
   327         emit q->error(iError);
       
   328         return;
       
   329     }
       
   330     // If opening a undefined configuration, session emits error and enters
       
   331     // NotAvailable -state. Note that we will try ones in 'defined' state to avoid excessive
       
   332     // need for WLAN scans (via updateConfigurations()), because user may have walked
       
   333     // into a WLAN range, but periodic background scan has not occurred yet -->
       
   334     // we don't want to force application to make frequent updateConfigurations() calls
       
   335     // to be able to try if e.g. home WLAN is available.
       
   336     if (publicConfig.state() == QNetworkConfiguration::Undefined) {
       
   337         newState(QNetworkSession::NotAvailable);
       
   338         iError = QNetworkSession::InvalidConfigurationError;
       
   339         emit q->error(iError);
       
   340         return;
       
   341     }
       
   342     // Clear possible previous states
       
   343     iStoppedByUser = false;
       
   344     iClosedByUser = false;
       
   345 
       
   346     TInt error = iSocketServ.Connect();
       
   347     if (error != KErrNone) {
       
   348         // Could not open RSocketServ
       
   349         newState(QNetworkSession::Invalid);
       
   350         iError = QNetworkSession::UnknownSessionError;
       
   351         emit q->error(iError);
       
   352         syncStateWithInterface();    
       
   353         return;
       
   354     }
       
   355     
       
   356     error = iConnection.Open(iSocketServ);
       
   357     if (error != KErrNone) {
       
   358         // Could not open RConnection
       
   359         iSocketServ.Close();
       
   360         newState(QNetworkSession::Invalid);
       
   361         iError = QNetworkSession::UnknownSessionError;
       
   362         emit q->error(iError);
       
   363         syncStateWithInterface();    
       
   364         return;
       
   365     }
       
   366     
       
   367     // Use RConnection::ProgressNotification for IAP/SNAP monitoring
       
   368     // (<=> ConnectionProgressNotifier uses RConnection::ProgressNotification)
       
   369     if (!ipConnectionNotifier) {
       
   370         ipConnectionNotifier = new ConnectionProgressNotifier(*this,iConnection);
       
   371     }
       
   372     if (ipConnectionNotifier) {
       
   373         ipConnectionNotifier->StartNotifications();
       
   374     }
       
   375     
       
   376     if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
       
   377 #if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
       
   378             // With One Click Connectivity (Symbian^3 onwards) it is possible
       
   379             // to connect silently, without any popups.
       
   380             TConnPrefList pref;
       
   381             TExtendedConnPref prefs;
       
   382             prefs.SetIapId(publicConfig.d.data()->numericId);
       
   383             if (iConnectInBackground) {
       
   384                 prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent );
       
   385             }
       
   386             pref.AppendL(&prefs);
       
   387 #else
       
   388             TCommDbConnPref pref;
       
   389             pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
       
   390             pref.SetIapId(publicConfig.d.data()->numericId);
       
   391 #endif
       
   392             iConnection.Start(pref, iStatus);
       
   393             if (!IsActive()) {
       
   394                 SetActive();
       
   395             }
       
   396             // Avoid flip flop of states if the configuration is already
       
   397             // active. IsOpen/opened() will indicate when ready.
       
   398             if (state != QNetworkSession::Connected) {
       
   399                 newState(QNetworkSession::Connecting);
       
   400             }
       
   401     } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
       
   402 #if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
       
   403         // On Symbian^3 if service network is not reachable, it triggers a UI (aka EasyWLAN) where
       
   404         // user can create new IAPs. To detect this, we need to store the number of IAPs
       
   405         // there was before connection was started.
       
   406         iKnownConfigsBeforeConnectionStart = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
       
   407         TConnPrefList snapPref;
       
   408         TExtendedConnPref prefs;
       
   409         prefs.SetSnapId(publicConfig.d.data()->numericId);
       
   410         if (iConnectInBackground) {
       
   411             prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent );
       
   412         }
       
   413         snapPref.AppendL(&prefs);
       
   414 #else
       
   415         TConnSnapPref snapPref(publicConfig.d.data()->numericId);
       
   416 #endif
       
   417         iConnection.Start(snapPref, iStatus);
       
   418         if (!IsActive()) {
       
   419             SetActive();
       
   420         }
       
   421         // Avoid flip flop of states if the configuration is already
       
   422         // active. IsOpen/opened() will indicate when ready.
       
   423         if (state != QNetworkSession::Connected) {
       
   424             newState(QNetworkSession::Connecting);
       
   425         }
       
   426     } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
   427         iKnownConfigsBeforeConnectionStart = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
       
   428         iConnection.Start(iStatus);
       
   429         if (!IsActive()) {
       
   430             SetActive();
       
   431         }
       
   432         newState(QNetworkSession::Connecting);
       
   433     }
       
   434  
       
   435     if (error != KErrNone) {
       
   436         isOpen = false;
       
   437         isOpening = false;
       
   438         iError = QNetworkSession::UnknownSessionError;
       
   439         emit q->error(iError);
       
   440         if (ipConnectionNotifier) {
       
   441             ipConnectionNotifier->StopNotifications();
       
   442         }
       
   443         syncStateWithInterface();    
       
   444     }
       
   445 }
       
   446 
       
   447 TUint QNetworkSessionPrivate::iapClientCount(TUint aIAPId) const
       
   448 {
       
   449     TRequestStatus status;
       
   450     TUint connectionCount;
       
   451     iConnectionMonitor.GetConnectionCount(connectionCount, status);
       
   452     User::WaitForRequest(status);
       
   453     if (status.Int() == KErrNone) {
       
   454         for (TUint i = 1; i <= connectionCount; i++) {
       
   455             TUint connectionId;
       
   456             TUint subConnectionCount;
       
   457             iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
       
   458             TUint apId;
       
   459             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
       
   460             User::WaitForRequest(status);
       
   461             if (apId == aIAPId) {
       
   462                 TConnMonClientEnumBuf buf;
       
   463                 iConnectionMonitor.GetPckgAttribute(connectionId, 0, KClientInfo, buf, status);
       
   464                 User::WaitForRequest(status);
       
   465                 if (status.Int() == KErrNone) {
       
   466                     return buf().iCount;
       
   467                 }
       
   468             }
       
   469         }
       
   470     }
       
   471     return 0;
       
   472 }
       
   473 
       
   474 void QNetworkSessionPrivate::close(bool allowSignals)
       
   475 {
       
   476 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   477     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   478             << "close() called, session state is: " << state << " and isOpen is : "
       
   479             << isOpen;
       
   480 #endif
       
   481 
       
   482     if (!isOpen && state != QNetworkSession::Connecting) {
       
   483         return;
       
   484     }
       
   485     // Mark this session as closed-by-user so that we are able to report
       
   486     // distinguish between stop() and close() state transitions
       
   487     // when reporting.
       
   488     iClosedByUser = true;
       
   489     isOpen = false;
       
   490     isOpening = false;
       
   491 
       
   492     serviceConfig = QNetworkConfiguration();
       
   493     
       
   494 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   495     if (iMobility) {
       
   496         delete iMobility;
       
   497         iMobility = NULL;
       
   498     }
       
   499 #endif
       
   500 
       
   501     if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) {
       
   502         ipConnectionNotifier->StopNotifications();
       
   503         // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
       
   504         iHandleStateNotificationsFromManager = true;
       
   505     }
       
   506     
       
   507     Cancel(); // closes iConnection
       
   508     iSocketServ.Close();
       
   509     
       
   510     // Close global 'Open C' RConnection. If OpenC supports,
       
   511     // close the defaultif for good to avoid difficult timing
       
   512     // and bouncing issues of network going immediately back up
       
   513     //  because of e.g. select() thread etc.
       
   514     if (iDynamicUnSetdefaultif) {
       
   515         iDynamicUnSetdefaultif();
       
   516     } else {
       
   517         setdefaultif(0);
       
   518     }
       
   519 
       
   520     // If UserChoice, go down immediately. If some other configuration,
       
   521     // go down immediately if there is no reports expected from the platform;
       
   522     // in practice Connection Monitor is aware of connections only after
       
   523     // KFinishedSelection event, and hence reports only after that event, but
       
   524     // that does not seem to be trusted on all Symbian versions --> safest
       
   525     // to go down.
       
   526     if (publicConfig.type() == QNetworkConfiguration::UserChoice || state == QNetworkSession::Connecting) {
       
   527 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   528         qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   529                  << "going disconnected right away, since either UserChoice or Connecting";
       
   530 #endif
       
   531         newState(QNetworkSession::Closing);
       
   532         newState(QNetworkSession::Disconnected);
       
   533     }
       
   534     if (allowSignals) {
       
   535         emit q->closed();
       
   536     }
       
   537 }
       
   538 
       
   539 void QNetworkSessionPrivate::stop()
       
   540 {
       
   541 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   542     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   543             << "stop() called, session state is: " << state << " and isOpen is : "
       
   544             << isOpen;
       
   545 #endif
       
   546     if (!isOpen &&
       
   547         publicConfig.isValid() &&
       
   548         publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
       
   549 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   550     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   551             << "since session is not open, using RConnectionMonitor to stop() the interface";
       
   552 #endif
       
   553         iStoppedByUser = true;
       
   554         // If the publicConfig is type of IAP, enumerate through connections at
       
   555         // connection monitor. If publicConfig is active in that list, stop it.
       
   556         // Otherwise there is nothing to stop. Note: because this QNetworkSession is not open,
       
   557         // activeConfig is not usable.
       
   558         TUint count;
       
   559         TRequestStatus status;
       
   560         iConnectionMonitor.GetConnectionCount(count, status);
       
   561         User::WaitForRequest(status);
       
   562         if (status.Int() != KErrNone) {
       
   563             return;
       
   564         }
       
   565         TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f
       
   566         TUint connectionId;
       
   567         for (TUint i = 1; i <= count; ++i) {
       
   568             // Get (connection monitor's assigned) connection ID
       
   569             TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);            
       
   570             if (ret == KErrNone) {
       
   571                 // See if connection Id matches with our Id. If so, stop() it.
       
   572                 if (publicConfig.d.data()->connectionId == connectionId) {
       
   573                     ret = iConnectionMonitor.SetBoolAttribute(connectionId,
       
   574                                                               0, // subConnectionId don't care
       
   575                                                               KConnectionStop,
       
   576                                                               ETrue);
       
   577                 }
       
   578             }
       
   579             // Enter disconnected state right away since the session is not even open.
       
   580             // Symbian^3 connection monitor does not emit KLinkLayerClosed when
       
   581             // connection is stopped via connection monitor.
       
   582             newState(QNetworkSession::Disconnected);
       
   583         }
       
   584     } else if (isOpen) {
       
   585 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   586     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   587             << "since session is open, using RConnection to stop() the interface";
       
   588 #endif
       
   589         // Since we are open, use RConnection to stop the interface
       
   590         isOpen = false;
       
   591         isOpening = false;
       
   592         iStoppedByUser = true;
       
   593         newState(QNetworkSession::Closing);
       
   594         if (ipConnectionNotifier) {
       
   595             ipConnectionNotifier->StopNotifications();
       
   596             // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
       
   597             iHandleStateNotificationsFromManager = true;
       
   598         }
       
   599         iConnection.Stop(RConnection::EStopAuthoritative);
       
   600         isOpen = true;
       
   601         isOpening = false;
       
   602         close(false);
       
   603         emit q->closed();
       
   604     }
       
   605 }
       
   606 
       
   607 void QNetworkSessionPrivate::migrate()
       
   608 {
       
   609 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   610     if (iMobility) {
       
   611         // Close global 'Open C' RConnection. If openC supports, use the 'heavy'
       
   612         // version to block all subsequent requests.
       
   613         if (iDynamicUnSetdefaultif) {
       
   614             iDynamicUnSetdefaultif();
       
   615         } else {
       
   616             setdefaultif(0);
       
   617         }
       
   618         // Start migrating to new IAP
       
   619         iMobility->MigrateToPreferredCarrier();
       
   620     }
       
   621 #endif
       
   622 }
       
   623 
       
   624 void QNetworkSessionPrivate::ignore()
       
   625 {
       
   626 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   627     if (iMobility) {
       
   628         iMobility->IgnorePreferredCarrier();
       
   629 
       
   630         if (!iALRUpgradingConnection) {
       
   631             newState(QNetworkSession::Disconnected);
       
   632         } else {
       
   633             newState(QNetworkSession::Connected,iOldRoamingIap);
       
   634         }
       
   635     }
       
   636 #endif
       
   637 }
       
   638 
       
   639 void QNetworkSessionPrivate::accept()
       
   640 {
       
   641 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   642     if (iMobility) {
       
   643         iMobility->NewCarrierAccepted();
       
   644 
       
   645         QNetworkConfiguration newActiveConfig = activeConfiguration(iNewRoamingIap);
       
   646 
       
   647         // Use name of the new IAP to open global 'Open C' RConnection
       
   648         QByteArray nameAsByteArray = newActiveConfig.name().toUtf8();
       
   649         ifreq ifr;
       
   650         memset(&ifr, 0, sizeof(struct ifreq));
       
   651         strcpy(ifr.ifr_name, nameAsByteArray.constData());
       
   652         setdefaultif(&ifr);
       
   653 
       
   654         newState(QNetworkSession::Connected, iNewRoamingIap);
       
   655     }
       
   656 #endif
       
   657 }
       
   658 
       
   659 void QNetworkSessionPrivate::reject()
       
   660 {
       
   661 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   662     if (iMobility) {
       
   663         iMobility->NewCarrierRejected();
       
   664 
       
   665         if (!iALRUpgradingConnection) {
       
   666             newState(QNetworkSession::Disconnected);
       
   667         } else {
       
   668             QNetworkConfiguration newActiveConfig = activeConfiguration(iOldRoamingIap);
       
   669 
       
   670             // Use name of the old IAP to open global 'Open C' RConnection
       
   671             QByteArray nameAsByteArray = newActiveConfig.name().toUtf8();
       
   672             ifreq ifr;
       
   673             memset(&ifr, 0, sizeof(struct ifreq));
       
   674             strcpy(ifr.ifr_name, nameAsByteArray.constData());
       
   675             setdefaultif(&ifr);
       
   676 
       
   677             newState(QNetworkSession::Connected, iOldRoamingIap);
       
   678         }
       
   679     }
       
   680 #endif
       
   681 }
       
   682 
       
   683 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   684 void QNetworkSessionPrivate::PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
       
   685                                                        TAccessPointInfo aNewAPInfo,
       
   686                                                        TBool aIsUpgrade,
       
   687                                                        TBool aIsSeamless)
       
   688 {
       
   689     iOldRoamingIap = aOldAPInfo.AccessPoint();
       
   690     iNewRoamingIap = aNewAPInfo.AccessPoint();
       
   691     newState(QNetworkSession::Roaming);
       
   692     if (iALREnabled > 0) {
       
   693         iALRUpgradingConnection = aIsUpgrade;
       
   694         QList<QNetworkConfiguration> configs = publicConfig.children();
       
   695         for (int i=0; i < configs.count(); i++) {
       
   696             if (configs[i].d.data()->numericId == aNewAPInfo.AccessPoint()) {
       
   697                 // Any slot connected to the signal might throw an std::exception,
       
   698                 // which must not propagate into Symbian code (this function is a callback
       
   699                 // from platform). We could convert exception to a symbian Leave, but since the
       
   700                 // prototype of this function bans this (no trailing 'L'), we just catch
       
   701                 // and drop.
       
   702                 QT_TRY {
       
   703                     emit q->preferredConfigurationChanged(configs[i],aIsSeamless);
       
   704                 }
       
   705                 QT_CATCH (std::exception&) {}
       
   706             }
       
   707         }
       
   708     } else {
       
   709         migrate();
       
   710     }
       
   711 }
       
   712 
       
   713 void QNetworkSessionPrivate::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*/, TBool /*aIsSeamless*/)
       
   714 {
       
   715     if (iALREnabled > 0) {
       
   716         QT_TRY {
       
   717             emit q->newConfigurationActivated();
       
   718         }
       
   719         QT_CATCH (std::exception&) {}
       
   720     } else {
       
   721         accept();
       
   722     }
       
   723 }
       
   724 
       
   725 void QNetworkSessionPrivate::Error(TInt /*aError*/)
       
   726 {
       
   727 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   728     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   729             << "roaming Error() occured, isOpen is: " << isOpen;
       
   730 #endif
       
   731     if (isOpen) {
       
   732         isOpen = false;
       
   733         isOpening = false;
       
   734         activeConfig = QNetworkConfiguration();
       
   735         serviceConfig = QNetworkConfiguration();
       
   736         iError = QNetworkSession::RoamingError;
       
   737         emit q->error(iError);
       
   738         Cancel();
       
   739         if (ipConnectionNotifier) {
       
   740             ipConnectionNotifier->StopNotifications();
       
   741         }
       
   742         QT_TRY {
       
   743             syncStateWithInterface();
       
   744             // In some cases IAP is still in Connected state when
       
   745             // syncStateWithInterface(); is called
       
   746             // => Following call makes sure that Session state
       
   747             //    changes immediately to Disconnected.
       
   748             newState(QNetworkSession::Disconnected);
       
   749             emit q->closed();
       
   750         }
       
   751         QT_CATCH (std::exception&) {}
       
   752     } else if (iStoppedByUser) {
       
   753         // If the user of this session has called the stop() and
       
   754         // configuration is based on internet SNAP, this needs to be
       
   755         // done here because platform might roam.
       
   756         QT_TRY {
       
   757             newState(QNetworkSession::Disconnected);
       
   758         }
       
   759         QT_CATCH (std::exception&) {}
       
   760     }
       
   761 }
       
   762 #endif
       
   763 
       
   764 void QNetworkSessionPrivate::setALREnabled(bool enabled)
       
   765 {
       
   766     if (enabled) {
       
   767         iALREnabled++;
       
   768     } else {
       
   769         iALREnabled--;
       
   770     }
       
   771 }
       
   772 
       
   773 QNetworkConfiguration QNetworkSessionPrivate::bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const
       
   774 {
       
   775     QNetworkConfiguration config;
       
   776     QList<QNetworkConfiguration> subConfigurations = snapConfig.children();
       
   777     for (int i = 0; i < subConfigurations.count(); i++ ) {
       
   778         if (subConfigurations[i].state() == QNetworkConfiguration::Active) {
       
   779             config = subConfigurations[i];
       
   780             break;
       
   781         } else if (!config.isValid() && subConfigurations[i].state() == QNetworkConfiguration::Discovered) {
       
   782             config = subConfigurations[i];
       
   783         }
       
   784     }
       
   785     if (!config.isValid() && subConfigurations.count() > 0) {
       
   786         config = subConfigurations[0];
       
   787     }
       
   788     return config;
       
   789 }
       
   790 
       
   791 quint64 QNetworkSessionPrivate::bytesWritten() const
       
   792 {
       
   793     return transferredData(KUplinkData);
       
   794 }
       
   795 
       
   796 quint64 QNetworkSessionPrivate::bytesReceived() const
       
   797 {
       
   798     return transferredData(KDownlinkData);
       
   799 }
       
   800 
       
   801 quint64 QNetworkSessionPrivate::transferredData(TUint dataType) const
       
   802 {
       
   803     if (!publicConfig.isValid()) {
       
   804         return 0;
       
   805     }
       
   806     
       
   807     QNetworkConfiguration config;
       
   808     if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
   809         if (serviceConfig.isValid()) {
       
   810             config = serviceConfig;
       
   811         } else {
       
   812             if (activeConfig.isValid()) {
       
   813                 config = activeConfig;
       
   814             }
       
   815         }
       
   816     } else {
       
   817         config = publicConfig;
       
   818     }
       
   819 
       
   820     if (!config.isValid()) {
       
   821         return 0;
       
   822     }
       
   823     
       
   824     TUint count;
       
   825     TRequestStatus status;
       
   826     iConnectionMonitor.GetConnectionCount(count, status);
       
   827     User::WaitForRequest(status);
       
   828     if (status.Int() != KErrNone) {
       
   829         return 0;
       
   830     }
       
   831     
       
   832     TUint transferredData = 0;
       
   833     TUint numSubConnections;
       
   834     TUint connectionId;
       
   835     bool configFound;
       
   836     for (TUint i = 1; i <= count; i++) {
       
   837         TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
       
   838         if (ret == KErrNone) {
       
   839             TUint apId;
       
   840             iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
       
   841             User::WaitForRequest(status);
       
   842             if (status.Int() == KErrNone) {
       
   843                 configFound = false;
       
   844                 if (config.type() == QNetworkConfiguration::ServiceNetwork) {
       
   845                     QList<QNetworkConfiguration> configs = config.children();
       
   846                     for (int i=0; i < configs.count(); i++) {
       
   847                         if (configs[i].d.data()->numericId == apId) {
       
   848                             configFound = true;
       
   849                             break;
       
   850                         }
       
   851                     }
       
   852                 } else if (config.d.data()->numericId == apId) {
       
   853                     configFound = true;
       
   854                 }
       
   855                 if (configFound) {
       
   856                     TUint tData;
       
   857                     iConnectionMonitor.GetUintAttribute(connectionId, 0, dataType, tData, status );
       
   858                     User::WaitForRequest(status);
       
   859                     if (status.Int() == KErrNone) {
       
   860                     transferredData += tData;
       
   861                     }
       
   862                 }
       
   863             }
       
   864         }
       
   865     }
       
   866     
       
   867     return transferredData;
       
   868 }
       
   869 
       
   870 quint64 QNetworkSessionPrivate::activeTime() const
       
   871 {
       
   872     if (!isOpen || startTime.isNull()) {
       
   873         return 0;
       
   874     }
       
   875     return startTime.secsTo(QDateTime::currentDateTime());
       
   876 }
       
   877 
       
   878 QNetworkConfiguration QNetworkSessionPrivate::activeConfiguration(TUint32 iapId) const
       
   879 {
       
   880     if (iapId == 0) {
       
   881         _LIT(KSetting, "IAP\\Id");
       
   882         iConnection.GetIntSetting(KSetting, iapId);
       
   883 #if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
       
   884         // Check if this is an Easy WLAN configuration. On Symbian^3 RConnection may report
       
   885         // the used configuration as 'EasyWLAN' IAP ID if someone has just opened the configuration
       
   886         // from WLAN Scan dialog, _and_ that connection is still up. We need to find the
       
   887         // real matching configuration. Function alters the Easy WLAN ID to real IAP ID (only if easy WLAN):
       
   888         ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->easyWlanTrueIapId(iapId);
       
   889 #endif
       
   890     }
       
   891 
       
   892 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   893     if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
       
   894         // Try to search IAP from the used SNAP using IAP Id
       
   895         QList<QNetworkConfiguration> children = publicConfig.children();
       
   896         for (int i=0; i < children.count(); i++) {
       
   897             if (children[i].d.data()->numericId == iapId) {
       
   898                 return children[i];
       
   899             }
       
   900         }
       
   901 
       
   902         // Given IAP Id was not found from the used SNAP
       
   903         // => Try to search matching IAP using mappingName
       
   904         //    mappingName contains:
       
   905         //      1. "Access point name" for "Packet data" Bearer
       
   906         //      2. "WLAN network name" (= SSID) for "Wireless LAN" Bearer
       
   907         //      3. "Dial-up number" for "Data call Bearer" or "High Speed (GSM)" Bearer
       
   908         //    <=> Note: It's possible that in this case reported IAP is
       
   909         //              clone of the one of the IAPs of the used SNAP
       
   910         //              => If mappingName matches, clone has been found
       
   911         QNetworkConfiguration pt;
       
   912         pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)));
       
   913         if (pt.d) {
       
   914             for (int i=0; i < children.count(); i++) {
       
   915                 if (children[i].d.data()->mappingName == pt.d.data()->mappingName) {
       
   916                     return children[i];
       
   917                 }
       
   918             }
       
   919         } else {
       
   920 #if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
       
   921             // On Symbian^3 (only, not earlier or Symbian^4) if the SNAP was not reachable, it triggers
       
   922             // user choice type of activity (EasyWLAN). As a result, a new IAP may be created, and
       
   923             // hence if was not found yet. Therefore update configurations and see if there is something new.
       
   924             // 1. Update knowledge from the databases.
       
   925             ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->updateConfigurations();
       
   926             // 2. Check if new configuration was created during connection creation
       
   927             QList<QString> knownConfigs = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
       
   928 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   929             qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   930                     << "opened configuration was not known beforehand, looking for new.";
       
   931 #endif
       
   932             if (knownConfigs.count() > iKnownConfigsBeforeConnectionStart.count()) {
       
   933                 // Configuration count increased => new configuration was created
       
   934                 // => Search new, created configuration
       
   935                 QString newIapId;
       
   936                 for (int i=0; i < iKnownConfigsBeforeConnectionStart.count(); i++) {
       
   937                     if (knownConfigs[i] != iKnownConfigsBeforeConnectionStart[i]) {
       
   938                         newIapId = knownConfigs[i];
       
   939                         break;
       
   940                     }
       
   941                 }
       
   942                 if (newIapId.isEmpty()) {
       
   943                     newIapId = knownConfigs[knownConfigs.count()-1];
       
   944                 }
       
   945                 pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(newIapId);
       
   946                 if (pt.d) {
       
   947 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   948                     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   949                             << "new configuration was found, name, IAP id: " << pt.name() << pt.identifier();
       
   950 #endif
       
   951                     return pt;
       
   952                 }
       
   953             }
       
   954 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   955             qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
   956                     << "configuration was not found, returning invalid.";
       
   957 #endif
       
   958 #endif
       
   959             // Given IAP Id was not found from known IAPs array
       
   960             return QNetworkConfiguration();
       
   961         }
       
   962         // Matching IAP was not found from used SNAP
       
   963         // => IAP from another SNAP is returned
       
   964         //    (Note: Returned IAP matches to given IAP Id)
       
   965         return pt;
       
   966     }
       
   967 #endif
       
   968     if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
   969         if (publicConfig.d.data()->manager) {
       
   970             QNetworkConfiguration pt;
       
   971             // Try to found User Selected IAP from known IAPs (accessPointConfigurations)
       
   972             pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)));
       
   973             if (pt.d) {
       
   974                 return pt;
       
   975             } else {
       
   976                 // Check if new (WLAN) IAP was created in IAP/SNAP dialog
       
   977                 // 1. Sync internal configurations array to commsdb first
       
   978                 ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->updateConfigurations();
       
   979                 // 2. Check if new configuration was created during connection creation
       
   980                 QList<QString> knownConfigs = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys();
       
   981                 if (knownConfigs.count() > iKnownConfigsBeforeConnectionStart.count()) {
       
   982                     // Configuration count increased => new configuration was created
       
   983                     // => Search new, created configuration
       
   984                     QString newIapId;
       
   985                     for (int i=0; i < iKnownConfigsBeforeConnectionStart.count(); i++) {
       
   986                         if (knownConfigs[i] != iKnownConfigsBeforeConnectionStart[i]) {
       
   987                             newIapId = knownConfigs[i];
       
   988                             break;
       
   989                         }
       
   990                     }
       
   991                     if (newIapId.isEmpty()) {
       
   992                         newIapId = knownConfigs[knownConfigs.count()-1];
       
   993                     }
       
   994                     pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(newIapId);
       
   995                     if (pt.d) {
       
   996                         return pt;
       
   997                     }
       
   998                 }
       
   999             }
       
  1000         }
       
  1001         return QNetworkConfiguration();
       
  1002     }
       
  1003 
       
  1004     return publicConfig;
       
  1005 }
       
  1006 
       
  1007 void QNetworkSessionPrivate::RunL()
       
  1008 {
       
  1009 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1010     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
  1011             << "RConnection::RunL with status code: " << iStatus.Int();
       
  1012 #endif
       
  1013     TInt statusCode = iStatus.Int();
       
  1014 
       
  1015     switch (statusCode) {
       
  1016         case KErrNone: // Connection created successfully
       
  1017             {
       
  1018             TInt error = KErrNone;
       
  1019             QNetworkConfiguration newActiveConfig = activeConfiguration();
       
  1020             if (!newActiveConfig.isValid()) {
       
  1021                 // RConnection startup was successfull but no configuration
       
  1022                 // was found. That indicates that user has chosen to create a
       
  1023                 // new WLAN configuration (from scan results), but that new
       
  1024                 // configuration does not have access to Internet (Internet
       
  1025                 // Connectivity Test, ICT, failed).
       
  1026                 error = KErrGeneral;
       
  1027             } else {
       
  1028                 // Use name of the IAP to open global 'Open C' RConnection
       
  1029                 ifreq ifr;
       
  1030                 memset(&ifr, 0, sizeof(struct ifreq));
       
  1031                 QByteArray nameAsByteArray = newActiveConfig.name().toUtf8();
       
  1032                 strcpy(ifr.ifr_name, nameAsByteArray.constData());
       
  1033                 error = setdefaultif(&ifr);
       
  1034             }
       
  1035             if (error != KErrNone) {
       
  1036                 isOpen = false;
       
  1037                 isOpening = false;
       
  1038                 iError = QNetworkSession::UnknownSessionError;
       
  1039                 QT_TRYCATCH_LEAVING(emit q->error(iError));
       
  1040                 if (ipConnectionNotifier) {
       
  1041                     ipConnectionNotifier->StopNotifications();
       
  1042                 }
       
  1043                 if (!newActiveConfig.isValid()) {
       
  1044                     // No valid configuration, bail out.
       
  1045                     // Status updates from QNCM won't be received correctly
       
  1046                     // because there is no configuration to associate them with so transit here.
       
  1047                     iConnection.Close();
       
  1048                     newState(QNetworkSession::Closing);
       
  1049                     newState(QNetworkSession::Disconnected);
       
  1050                 } else {
       
  1051                     Cancel();
       
  1052                 }
       
  1053                 QT_TRYCATCH_LEAVING(syncStateWithInterface());
       
  1054                 return;
       
  1055             }
       
  1056  
       
  1057 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
  1058             if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
       
  1059                 // Activate ALR monitoring
       
  1060                 iMobility = CActiveCommsMobilityApiExt::NewL(iConnection, *this);
       
  1061             }
       
  1062 #endif
       
  1063             isOpen = true;
       
  1064             isOpening = false;
       
  1065             activeConfig = newActiveConfig;
       
  1066             activeInterface = interface(activeConfig.d.data()->numericId);
       
  1067             if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
  1068                 QNetworkConfiguration pt;
       
  1069                 pt.d = activeConfig.d.data()->serviceNetworkPtr;
       
  1070                 serviceConfig = pt;
       
  1071             }
       
  1072             
       
  1073             startTime = QDateTime::currentDateTime();
       
  1074 
       
  1075             QT_TRYCATCH_LEAVING({
       
  1076                     newState(QNetworkSession::Connected);
       
  1077                     emit quitPendingWaitsForOpened();
       
  1078                 });
       
  1079             }
       
  1080             break;
       
  1081         case KErrNotFound: // Connection failed
       
  1082             isOpen = false;
       
  1083             isOpening = false;
       
  1084             activeConfig = QNetworkConfiguration();
       
  1085             serviceConfig = QNetworkConfiguration();
       
  1086             iError = QNetworkSession::InvalidConfigurationError;
       
  1087             QT_TRYCATCH_LEAVING(emit q->error(iError));
       
  1088             Cancel();
       
  1089             if (ipConnectionNotifier) {
       
  1090                 ipConnectionNotifier->StopNotifications();
       
  1091             }
       
  1092             QT_TRYCATCH_LEAVING(syncStateWithInterface());
       
  1093             break;
       
  1094         case KErrCancel: // Connection attempt cancelled
       
  1095         case KErrAlreadyExists: // Connection already exists
       
  1096         default:
       
  1097             isOpen = false;
       
  1098             isOpening = false;
       
  1099             activeConfig = QNetworkConfiguration();
       
  1100             serviceConfig = QNetworkConfiguration();
       
  1101             if (statusCode == KErrCancel) {
       
  1102                 iError = QNetworkSession::SessionAbortedError;
       
  1103             } else if (publicConfig.state() == QNetworkConfiguration::Undefined ||
       
  1104                 publicConfig.state() == QNetworkConfiguration::Defined) {
       
  1105                 iError = QNetworkSession::InvalidConfigurationError;
       
  1106             } else {
       
  1107                 iError = QNetworkSession::UnknownSessionError;
       
  1108             }
       
  1109             QT_TRYCATCH_LEAVING(emit q->error(iError));
       
  1110             Cancel();
       
  1111             if (ipConnectionNotifier) {
       
  1112                 ipConnectionNotifier->StopNotifications();
       
  1113             }
       
  1114             QT_TRYCATCH_LEAVING(syncStateWithInterface());
       
  1115             break;
       
  1116     }
       
  1117 }
       
  1118 
       
  1119 void QNetworkSessionPrivate::DoCancel()
       
  1120 {
       
  1121     iConnection.Close();
       
  1122 }
       
  1123 
       
  1124 // Enters newState if feasible according to current state.
       
  1125 // AccessPointId may be given as parameter. If it is zero, state-change is assumed to
       
  1126 // concern this session's configuration. If non-zero, the configuration is looked up
       
  1127 // and checked if it matches the configuration this session is based on.
       
  1128 bool QNetworkSessionPrivate::newState(QNetworkSession::State newState, TUint accessPointId)
       
  1129 {
       
  1130 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1131     qDebug() << "QNS this : " << QString::number((uint)this) << " - "
       
  1132              << "NEW STATE, IAP ID : " << QString::number(accessPointId) << " , newState : " << QString::number(newState);
       
  1133 #endif
       
  1134     // Make sure that activeConfig is always updated when SNAP is signaled to be
       
  1135     // connected.
       
  1136     if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork &&
       
  1137         newState == QNetworkSession::Connected) {
       
  1138         activeConfig = activeConfiguration(accessPointId);
       
  1139         activeInterface = interface(activeConfig.d.data()->numericId);
       
  1140     }
       
  1141 
       
  1142     // Make sure that same state is not signaled twice in a row.
       
  1143     if (state == newState) {
       
  1144         return true;
       
  1145     }
       
  1146 
       
  1147     // Make sure that Connecting state does not overwrite Roaming state
       
  1148     if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) {
       
  1149         return false;
       
  1150     }
       
  1151     
       
  1152     // Make sure that Connected state is not reported when Connection is
       
  1153     // already Closing.
       
  1154     // Note: Stopping connection results sometimes KLinkLayerOpen
       
  1155     //       to be reported first (just before KLinkLayerClosed).
       
  1156     if (state == QNetworkSession::Closing && newState == QNetworkSession::Connected) {
       
  1157         return false;
       
  1158     }
       
  1159 
       
  1160     // Make sure that some lagging 'closing' state-changes do not overwrite
       
  1161     // if we are already disconnected or closed.
       
  1162     if (state == QNetworkSession::Disconnected && newState == QNetworkSession::Closing) {
       
  1163         return false;
       
  1164     }
       
  1165 
       
  1166     // Make sure that some lagging 'connecting' state-changes do not overwrite
       
  1167     // if we are already connected (may righfully still happen with roaming though).
       
  1168     if (state == QNetworkSession::Connected && newState == QNetworkSession::Connecting) {
       
  1169         return false;
       
  1170     }
       
  1171 
       
  1172     bool emitSessionClosed = false;
       
  1173 
       
  1174     // If we abruptly go down and user hasn't closed the session, we've been aborted.
       
  1175     // Note that session may be in 'closing' state and not in 'connected' state, because
       
  1176     // depending on platform the platform may report KConfigDaemonStartingDeregistration
       
  1177     // event before KLinkLayerClosed
       
  1178     if ((isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) ||
       
  1179         (isOpen && !iClosedByUser && newState == QNetworkSession::Disconnected)) {
       
  1180         // Active & Connected state should change directly to Disconnected state
       
  1181         // only when something forces connection to close (eg. when another
       
  1182         // application or session stops connection or when network drops
       
  1183         // unexpectedly).
       
  1184         isOpen = false;
       
  1185         isOpening = false;
       
  1186         activeConfig = QNetworkConfiguration();
       
  1187         serviceConfig = QNetworkConfiguration();
       
  1188         iError = QNetworkSession::SessionAbortedError;
       
  1189         emit q->error(iError);
       
  1190         Cancel();
       
  1191         if (ipConnectionNotifier) {
       
  1192             ipConnectionNotifier->StopNotifications();
       
  1193         }
       
  1194         // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
       
  1195         iHandleStateNotificationsFromManager = true;
       
  1196         emitSessionClosed = true; // Emit SessionClosed after state change has been reported
       
  1197     }
       
  1198 
       
  1199     bool retVal = false;
       
  1200     if (accessPointId == 0) {
       
  1201         state = newState;
       
  1202 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1203         qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed A to: " << state;
       
  1204 #endif
       
  1205         emit q->stateChanged(state);
       
  1206         retVal = true;
       
  1207     } else {
       
  1208         if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
       
  1209             if (publicConfig.d.data()->numericId == accessPointId) {
       
  1210                 state = newState;
       
  1211 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1212                 qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed B to: " << state;
       
  1213 #endif
       
  1214                 emit q->stateChanged(state);
       
  1215                 retVal = true;
       
  1216             }
       
  1217         } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isOpen) {
       
  1218             if (activeConfig.d.data()->numericId == accessPointId) {
       
  1219                 state = newState;
       
  1220 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1221                 qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed C to: " << state;
       
  1222 #endif
       
  1223                 emit q->stateChanged(state);
       
  1224                 retVal = true;
       
  1225             }
       
  1226         } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
       
  1227             QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
       
  1228             for (int i = 0; i < subConfigurations.count(); i++) {
       
  1229                 if (subConfigurations[i].d.data()->numericId == accessPointId) {
       
  1230                     if (newState != QNetworkSession::Disconnected) {
       
  1231                         state = newState;
       
  1232 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1233                         qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D  to: " << state;
       
  1234 #endif
       
  1235                         emit q->stateChanged(state);
       
  1236                         retVal = true;
       
  1237                     } else {
       
  1238                         QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
       
  1239                         if ((config.state() == QNetworkConfiguration::Defined) ||
       
  1240                             (config.state() == QNetworkConfiguration::Discovered)) {
       
  1241                             activeConfig = QNetworkConfiguration();
       
  1242                             state = newState;
       
  1243 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1244                             qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E  to: " << state;
       
  1245 #endif
       
  1246                             emit q->stateChanged(state);
       
  1247                             retVal = true;
       
  1248                         } else if (config.state() == QNetworkConfiguration::Active) {
       
  1249                             // Connection to used IAP was closed, but there is another
       
  1250                             // IAP that's active in used SNAP
       
  1251                             // => Change state back to Connected
       
  1252                             state =  QNetworkSession::Connected;
       
  1253                             emit q->stateChanged(state);
       
  1254                             retVal = true;
       
  1255 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1256                             qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed F  to: " << state;
       
  1257 #endif
       
  1258                         }
       
  1259                     }
       
  1260                 }
       
  1261             }
       
  1262 #if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
       
  1263             // If the retVal is not true here, it means that the status update may apply to an IAP outside of
       
  1264             // SNAP (session is based on SNAP but follows IAP outside of it), which may occur on Symbian^3 EasyWlan.
       
  1265             if (retVal == false && activeConfig.d.data() && activeConfig.d.data()->numericId == accessPointId) {
       
  1266 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1267                 qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed G  to: " << state;
       
  1268 #endif
       
  1269                 if (newState == QNetworkSession::Disconnected) {
       
  1270                     activeConfig = QNetworkConfiguration();
       
  1271                 }
       
  1272                 state = newState;
       
  1273                 emit q->stateChanged(state);
       
  1274                 retVal = true;
       
  1275             }
       
  1276 #endif
       
  1277         }
       
  1278     }
       
  1279     if (emitSessionClosed) {
       
  1280         emit q->closed();
       
  1281     }
       
  1282     if (state == QNetworkSession::Disconnected) {
       
  1283         // Just in case clear activeConfiguration.
       
  1284         activeConfig = QNetworkConfiguration();
       
  1285     }
       
  1286     return retVal;
       
  1287 }
       
  1288 
       
  1289 void QNetworkSessionPrivate::handleSymbianConnectionStatusChange(TInt aConnectionStatus,
       
  1290                                                                  TInt aError,
       
  1291                                                                  TUint accessPointId)
       
  1292 {
       
  1293 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1294     qDebug() << "QNS this : " << QString::number((uint)this) << " - " << QString::number(accessPointId) << " , status : " << QString::number(aConnectionStatus);
       
  1295 #endif
       
  1296     switch (aConnectionStatus)
       
  1297         {
       
  1298         // Connection unitialised
       
  1299         case KConnectionUninitialised:
       
  1300             break;
       
  1301 
       
  1302         // Starting connetion selection
       
  1303         case KStartingSelection:
       
  1304             break;
       
  1305 
       
  1306         // Selection finished
       
  1307         case KFinishedSelection:
       
  1308             if (aError == KErrNone)
       
  1309                 {
       
  1310                 break;
       
  1311                 }
       
  1312             else
       
  1313                 {
       
  1314                 // The user pressed e.g. "Cancel" and did not select an IAP
       
  1315                 newState(QNetworkSession::Disconnected,accessPointId);
       
  1316                 }
       
  1317             break;
       
  1318 
       
  1319         // Connection failure
       
  1320         case KConnectionFailure:
       
  1321             newState(QNetworkSession::NotAvailable);
       
  1322             break;
       
  1323 
       
  1324         // Prepearing connection (e.g. dialing)
       
  1325         case KPsdStartingConfiguration:
       
  1326         case KPsdFinishedConfiguration:
       
  1327         case KCsdFinishedDialling:
       
  1328         case KCsdScanningScript:
       
  1329         case KCsdGettingLoginInfo:
       
  1330         case KCsdGotLoginInfo:
       
  1331             break;
       
  1332 
       
  1333         case KConfigDaemonStartingRegistration:
       
  1334         // Creating connection (e.g. GPRS activation)
       
  1335         case KCsdStartingConnect:
       
  1336         case KCsdFinishedConnect:
       
  1337             newState(QNetworkSession::Connecting,accessPointId);
       
  1338             break;
       
  1339 
       
  1340         // Starting log in
       
  1341         case KCsdStartingLogIn:
       
  1342             break;
       
  1343 
       
  1344         // Finished login
       
  1345         case KCsdFinishedLogIn:
       
  1346             break;
       
  1347 
       
  1348         // Connection open
       
  1349         case KConnectionOpen:
       
  1350             break;
       
  1351 
       
  1352         case KLinkLayerOpen:
       
  1353             newState(QNetworkSession::Connected,accessPointId);
       
  1354             break;
       
  1355 
       
  1356         // Connection blocked or suspended
       
  1357         case KDataTransferTemporarilyBlocked:
       
  1358             break;
       
  1359 
       
  1360         case KConfigDaemonStartingDeregistration:
       
  1361         // Hangup or GRPS deactivation
       
  1362         case KConnectionStartingClose:
       
  1363             newState(QNetworkSession::Closing,accessPointId);
       
  1364             break;
       
  1365 
       
  1366         // Connection closed
       
  1367         case KConnectionClosed:
       
  1368         case KLinkLayerClosed:
       
  1369             newState(QNetworkSession::Disconnected,accessPointId);
       
  1370             // Report manager about this to make sure this event
       
  1371             // is received by all interseted parties (mediated by
       
  1372             // manager because it does always receive all events from
       
  1373             // connection monitor).
       
  1374 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1375             qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "reporting disconnection to manager.";
       
  1376 #endif
       
  1377             if (publicConfig.d.data()) {
       
  1378                 ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->configurationStateChangeReport(publicConfig.d.data()->numericId, QNetworkSession::Disconnected);
       
  1379             }
       
  1380             break;
       
  1381         // Unhandled state
       
  1382         default:
       
  1383             break;
       
  1384         }
       
  1385 }
       
  1386 
       
  1387 ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivate& owner, RConnection& connection)
       
  1388     : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection)
       
  1389 {
       
  1390     CActiveScheduler::Add(this);
       
  1391 }
       
  1392 
       
  1393 ConnectionProgressNotifier::~ConnectionProgressNotifier()
       
  1394 {
       
  1395     Cancel();
       
  1396 }
       
  1397 
       
  1398 void ConnectionProgressNotifier::StartNotifications()
       
  1399 {
       
  1400     if (!IsActive()) {
       
  1401         SetActive();
       
  1402     }
       
  1403     iConnection.ProgressNotification(iProgress, iStatus);
       
  1404 }
       
  1405 
       
  1406 void ConnectionProgressNotifier::StopNotifications()
       
  1407 {
       
  1408     Cancel();
       
  1409 }
       
  1410 
       
  1411 void ConnectionProgressNotifier::DoCancel()
       
  1412 {
       
  1413     iConnection.CancelProgressNotification();
       
  1414 }
       
  1415 
       
  1416 void ConnectionProgressNotifier::RunL()
       
  1417 {
       
  1418     if (iStatus == KErrNone) {
       
  1419         QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError));
       
  1420     
       
  1421         SetActive();
       
  1422         iConnection.ProgressNotification(iProgress, iStatus);
       
  1423     }
       
  1424 }
       
  1425 
       
  1426 #include "moc_qnetworksession_s60_p.cpp"
       
  1427 
       
  1428 QTM_END_NAMESPACE