wlanutilities/wlanqtutilities/base/src/wlanqtutils_p.cpp
author William Roberts <williamr@symbian.org>
Fri, 11 Jun 2010 16:27:29 +0100
branchGCC_SURGE
changeset 34 30a5f517c615
parent 19 10810c91db26
child 31 e8f4211554fb
permissions -rw-r--r--
Branch for GCC_SURGE fixes

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*/

#include "wlanqtutilswlanap.h"
#include "wlanqtutilswlaniap.h"
#include "wlanqtutilsactiveconn.h"
#include "wlanqtutilscmmwrapper.h"
#include "wlanqtutilsconmonwrapper.h"
#include "wlanqtutilsesockwrapper.h"
#include "wlanqtutilsconntestwrapper.h"

#include "wlanqtutils.h"
#include "wlanqtutils_p.h"

#ifdef WLANQTUTILS_NO_OST_TRACES_FLAG
#include <opensystemtrace.h>
#else
#include "OstTraceDefinitions.h"
#endif
#ifdef OST_TRACE_COMPILER_IN_USE
#include "wlanqtutils_pTraces.h"
#endif


WlanQtUtilsPrivate::WlanQtUtilsPrivate(WlanQtUtils *publicPtr) :
    q_ptr(publicPtr),
    wlanScanList_(),
    wlanIapList_(),
    toBeTestedIapId_(WlanQtUtilsInvalidIapId),
    connectingIapId_(WlanQtUtilsInvalidIapId),
    activeConnection_(NULL)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_WLANQTUTILSPRIVATE_ENTRY, this );
    
    // Let's allocate memory for wrapper objects.
    // Engine is set as a parent for wrapper objects.
    cmmWrapper_ = new CmmWrapper(this);
    conMonWrapper_ = new ConMonWrapper(this);
    esockWrapper_ = new EsockWrapper(this);
    connTestWrapper_ = new ConnTestWrapper(this);
    
    // Make all connections.
    // Todo: having these as signals from the wrappers doesn't bring much benefit
    // -> could be optimized as normal callbacks
    connect(
        conMonWrapper_,
        SIGNAL(availableWlanApsFromWrapper(QList<WlanQtUtilsWlanAp *>&)),
        this,
        SLOT(updateAvailableWlanAps(QList<WlanQtUtilsWlanAp *>&)));

    connect(
        esockWrapper_,
        SIGNAL(connectionStatusFromWrapper(bool)),
        this,
        SLOT(updateConnectionStatus(bool)));

    connect(
        connTestWrapper_,
        SIGNAL(connectivityTestResult(bool)),
        this,
        SLOT(updateConnectivityTestResult(bool)));

    connect(
        conMonWrapper_,
        SIGNAL(connCreatedEventFromWrapper(uint)),
        this,
        SLOT(addActiveConnection(uint)));

    connect(
        conMonWrapper_,
        SIGNAL(connDeletedEventFromWrapper(uint)),
        this,
        SLOT(removeActiveConnection(uint)));
    
    connect(
        conMonWrapper_,
        SIGNAL(connStatusEventFromWrapper(uint, WlanQtUtilsConnectionStatus)),
        this,
        SLOT(updateActiveConnection(uint, WlanQtUtilsConnectionStatus)));

    // Fetch the initial IAP configuration
    fetchIaps();

    // Retrieve initial status of active connections and update IAPs, if needed.
    activeConnection_ = conMonWrapper_->activeConnection();
    if (activeConnection_ != NULL) {
        updateIapConnectionStatuses(activeConnection_->iapId(), activeConnection_->connectionStatus());
    }

    // TODO: error handling

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_WLANQTUTILSPRIVATE_EXIT, this );
}

WlanQtUtilsPrivate::~WlanQtUtilsPrivate()
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_WLANQTUTILSPRIVATEDESTR_ENTRY, this );
    
    // Delete WLAN scan list
    for (int i = 0; i < wlanScanList_.count(); i++) {
        delete wlanScanList_[i];
    }
    wlanScanList_.clear();
    
    delete activeConnection_;
    
    delete cmmWrapper_;
    delete conMonWrapper_;
    delete esockWrapper_;
    delete connTestWrapper_;

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_WLANQTUTILSPRIVATEDESTR_EXIT, this );
}

void WlanQtUtilsPrivate::availableWlanAps(
    QList<WlanQtUtilsWlanIap *> &wlanIapList,
    QList<WlanQtUtilsWlanAp *> &wlanApList)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_AVAILABLEWLANAPS_ENTRY, this );
    
    wlanIapList.clear();
    wlanApList.clear();
    
    // Add possible connected or connecting IAP as the first item in the list
    int activeIapId = WlanQtUtilsInvalidIapId;
    if (activeConnection_ != NULL) {
        activeIapId = activeConnection_->iapId();
    } else if (connectingIapId_ != WlanQtUtilsInvalidIapId) {
        activeIapId = connectingIapId_;
    }
    if (wlanIapList_.contains(activeIapId)) {
        wlanIapList_[activeIapId]->setSignalStrength(WlanQtUtilsWlanSignalStrengthMax);
        wlanIapList_[activeIapId]->setConnectionStatus(WlanQtUtilsConnectionStatusConnected);
        wlanIapList.append(wlanIapList_[activeIapId]);
    }
    
    // Todo: IAPs with same SSID and security mode? probably we want to show only one of them?
    
    // Match IAPs against WLAN scan results
    foreach (WlanQtUtilsWlanIap *iap, wlanIapList_) {
        foreach (WlanQtUtilsWlanAp *scanAp, wlanScanList_) {
            // Todo: security mode check
            if (iap->ssid() == scanAp->ssid()) {
                // IAP found, add it to caller's list of known IAPs (signal strength needs to be
                // updated manually since the IAP in our list does not have that information yet)
                iap->setSignalStrength(scanAp->signalStrength());
                if (iap->id() != activeIapId) {
                    wlanIapList.append(iap);
                } // else: connected IAP, added as the first item in the list already
                break;
            }
        }
    }

    // Go through the scan results to find unknown APs
    for (int i = 0; i < wlanScanList_.count(); i++) {
        // Skip networks with empty SSID (hidden networks are handled by UI currently)
        if (wlanScanList_[i]->ssid().isEmpty() == FALSE) {
            // Check whether an IAP with these parameters exists in any SNAP (in which case this
            // network should not be shown as available in this SNAP)
            if (wlanIapExists(wlanScanList_[i]->ssid(), wlanScanList_[i]->securityMode()) == false) {
                // No IAP found in any SNAP, copy the AP to caller's list of unknown APs
                wlanApList.append(wlanScanList_[i]);
            }
        }
    }
    
    // Sort APs by their SSIDs.
    QMap<QString, WlanQtUtilsWlanAp *> wlanApMap;
    // Loop the AP list copying the keys (lower case SSID) and elements
    // into the map.
    for (int i = 0; i < wlanApList.count(); i++ ) {
        wlanApMap.insertMulti(wlanApList[i]->ssid().toLower(), wlanApList[i]);
    }
    wlanApList = wlanApMap.values();

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_AVAILABLEWLANAPS_EXIT, this );
}

int WlanQtUtilsPrivate::createWlanIap(const WlanQtUtilsWlanAp *wlanAp)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_CREATEWLANIAP_ENTRY, this );
    
    // Create the new IAP. Store its ID, because we need to run ICT for it later
    WlanQtUtilsWlanIap *newIap = cmmWrapper_->createWlanIap(wlanAp);
    toBeTestedIapId_ = newIap->id();
    wlanIapList_.insert(newIap->id(), newIap);
    
    OstTrace1(
        TRACE_API,
        WLANQTUTILSPRIVATE_CREATEWLANIAP,
        "WlanQtUtilsPrivate::createWlanIap;New IAP ID=%d", toBeTestedIapId_ );
    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_CREATEWLANIAP_EXIT, this );
    return toBeTestedIapId_;
}

void WlanQtUtilsPrivate::connectIap(int iapId)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_CONNECTIAP_ENTRY, this );
    OstTrace1( TRACE_API, WLANQTUTILSPRIVATE_CONNECTIAP, "WlanQtUtilsPrivate::connectIap;IAP ID=%d", iapId );
    
    Q_ASSERT(activeConnection_ == NULL);
    connectingIapId_ = iapId;
    esockWrapper_->connectIap(iapId);

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_CONNECTIAP_EXIT, this );
}

void WlanQtUtilsPrivate::disconnectIap(int iapId)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_DISCONNECTIAP_ENTRY, this );
    OstTrace1( TRACE_API, WLANQTUTILSPRIVATE_DISCONNECTIAP, "WlanQtUtilsPrivate::disconnectIap;IAP ID=%d", iapId );
    
    Q_ASSERT(activeConnection_ != NULL);
    Q_ASSERT(activeConnection_->iapId() == iapId);
    Q_ASSERT(wlanIapList_.contains(iapId));
    
    // Todo: IAP may have been opened by someone else... how to know when to disconnect RConnection?    
    esockWrapper_->disconnectIap();
    
    // In order to close connection even if there are other users for the IAP, close also via ConMon
    conMonWrapper_->disconnectIap(iapId);
    // Change status of the IAP to non-connected
    wlanIapList_[iapId]->setConnectionStatus(WlanQtUtilsConnectionStatusDisconnected);

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_DISCONNECTIAP_EXIT, this );
}

WlanQtUtilsIap *WlanQtUtilsPrivate::iap(int iapId) const
{
    if (wlanIapList_.contains(iapId)) {
        return wlanIapList_.value(iapId);
    }
    // else: no match
    return NULL;
}

bool WlanQtUtilsPrivate::masterWlan() const
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_MASTERWLAN_ENTRY, this );
    
    // TODO: Add actual implementation, this is just temporary dummy for testing wlanentryplugin!

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_MASTERWLAN_EXIT, this );
    return true;
}

void WlanQtUtilsPrivate::setMasterWlan(bool enabled)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_SETMASTERWLAN_ENTRY, this );
    
    // TODO: Add actual implementation.
    (void)enabled;

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_SETMASTERWLAN_EXIT, this );
}

int WlanQtUtilsPrivate::connectedWlanId() const
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_CONNECTEDWLANID_ENTRY, this );

    int retVal = WlanQtUtilsInvalidIapId;
    if (activeConnection_ != NULL) {
        retVal = activeConnection_->iapId();
    }
    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_CONNECTEDWLANID_EXIT, this );
    return retVal;
}

void WlanQtUtilsPrivate::scanWlans()
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_SCANWLANS_ENTRY, this );

    // Just forward the request to wrapper, which triggers a single WLAN scan
    conMonWrapper_->scanAvailableWlanAPs();

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_SCANWLANS_EXIT, this );
}

void WlanQtUtilsPrivate::updateAvailableWlanAps(QList<WlanQtUtilsWlanAp *> &availableWlanList)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_UPDATEAVAILABLEWLANAPS_ENTRY, this );
    
    // Old results are removed
    wlanScanList_.clear();
    // Copy available WLAN's to engine's scan result list (duplicates are removed)
    for (int i = 0; i < availableWlanList.count(); i++) {
        bool duplicate = false;
        for (int j = 0; j < wlanScanList_.count(); j++) {
            if (availableWlanList[i]->ssid() == wlanScanList_[j]->ssid()
                && availableWlanList[i]->securityMode() == wlanScanList_[j]->securityMode()) {
                duplicate = true;
                break;
            }
        }
        if (duplicate == false) {
            wlanScanList_.append(availableWlanList[i]);
        }
        // Todo: else deallocate?
    }

    // the information is forwarded to the UI
    emit q_ptr->wlanScanReady();

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_UPDATEAVAILABLEWLANAPS_EXIT, this );
}

void WlanQtUtilsPrivate::updateConnectionStatus(bool isOpened)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_UPDATECONNECTIONSTATUS_ENTRY, this );    
    OstTrace1(
        TRACE_API,
        WLANQTUTILSPRIVATE_UPDATECONNECTIONSTATUS,
        "WlanQtUtilsPrivate::updateConnectionStatus;isOpened=%d", isOpened );
    
    if (isOpened == false) {
        // Opening failed, update connection statuses, but don't inform UI about
        // connection closing here. It is done always in removeActiveConnection().
        if (activeConnection_ != NULL) {
            activeConnection_->setConnectionStatus(WlanQtUtilsConnectionStatusDisconnected);
        }
        updateIapConnectionStatuses(connectingIapId_, WlanQtUtilsConnectionStatusDisconnected);
    } else {
        // Opening succeeded, update connection statuses and inform UI
        if (activeConnection_ != NULL) {
            activeConnection_->setConnectionStatus(WlanQtUtilsConnectionStatusConnected);
        }
        updateIapConnectionStatuses(connectingIapId_, WlanQtUtilsConnectionStatusConnected);
        emit q_ptr->wlanNetworkOpened(connectingIapId_);

        // Start ICT, if needed
        if (connectingIapId_ == toBeTestedIapId_) {
            WlanQtUtilsIap *iap = WlanQtUtilsPrivate::iap(toBeTestedIapId_);
            connTestWrapper_->startConnectivityTest(toBeTestedIapId_, iap->networkId());
        }
    }
    // IAP is no more in connecting state
    connectingIapId_ = WlanQtUtilsInvalidIapId;

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_UPDATECONNECTIONSTATUS_EXIT, this );
}

void WlanQtUtilsPrivate::updateConnectivityTestResult(bool result)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_UPDATECONNECTIVITYTESTRESULT_ENTRY, this );
    OstTrace1(
        TRACE_API,
        WLANQTUTILSPRIVATE_UPDATECONNECTIVITYTESTRESULT,
        "WlanQtUtilsPrivate::updateConnectivityTestResult;result=%d", result );
    
    if (result == true) {
        // Move the tested IAP to Internet SNAP since the test passed
        Q_ASSERT(toBeTestedIapId_ != WlanQtUtilsInvalidIapId);
        cmmWrapper_->moveIapToInternetSnap(toBeTestedIapId_);
    } // else: do nothing, IAP remains to be uncategorized
    else
    {
        // TODO: Remove this. This is needed now since the connectivity test fails
        // and thus the IAP is not shown correctly.
        cmmWrapper_->moveIapToInternetSnap(toBeTestedIapId_);

    }
    // This IAP is now tested
    toBeTestedIapId_ = WlanQtUtilsInvalidIapId;

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_UPDATECONNECTIVITYTESTRESULT_EXIT, this );
}

void WlanQtUtilsPrivate::addActiveConnection(uint connectionId)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_ADDACTIVECONNECTION_ENTRY, this );
    OstTrace1(
        TRACE_API,
        WLANQTUTILSPRIVATE_ADDACTIVECONNECTION,
        "WlanQtUtilsPrivate::addActiveConnection;connectionId=%u", connectionId );

    Q_ASSERT(activeConnection_ == NULL);
    activeConnection_ = conMonWrapper_->connectionInfo(connectionId);
    Q_ASSERT(wlanIapList_.contains(activeConnection_->iapId()));
    updateIapConnectionStatuses(activeConnection_->iapId(), activeConnection_->connectionStatus());

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_ADDACTIVECONNECTION_EXIT, this );
}

void WlanQtUtilsPrivate::removeActiveConnection(uint connectionId)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_REMOVEACTIVECONNECTION_ENTRY, this );
    OstTrace1(
        TRACE_API,
        WLANQTUTILSPRIVATE_REMOVEACTIVECONNECTION,
        "WlanQtUtilsPrivate::removeActiveConnection;connectionId=%u", connectionId );
    
    Q_ASSERT(activeConnection_ != NULL);
    if (activeConnection_->connectionId() == connectionId) {
        // Connection is closed, update connection statuses and inform UI.
        // wlanNetworkClosed is sent from here (and only from here), because, in some cases,
        // connection may be removed without any connection status updates.
        int closedIapId = activeConnection_->iapId();
        updateIapConnectionStatuses(activeConnection_->iapId(), WlanQtUtilsConnectionStatusDisconnected);
        delete activeConnection_;
        activeConnection_ = NULL;
        emit q_ptr->wlanNetworkClosed(closedIapId);
    }

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_REMOVEACTIVECONNECTION_EXIT, this );
}

void WlanQtUtilsPrivate::updateActiveConnection(uint connectionId, WlanQtUtilsConnectionStatus connectionStatus)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_UPDATEACTIVECONNECTION_ENTRY, this );
    OstTraceExt2(
        TRACE_API,
        WLANQTUTILSPRIVATE_UPDATEACTIVECONNECTION,
        "WlanQtUtilsPrivate::updateActiveConnection;connectionId=%u;connectionStatus=%u", connectionId, connectionStatus );
    
    Q_ASSERT(activeConnection_ != NULL);
    if (activeConnection_->connectionId() == connectionId
        && activeConnection_->connectionStatus() != connectionStatus) {
        // Update connection statuses and inform UI, if necessary
        activeConnection_->setConnectionStatus(connectionStatus);
        updateIapConnectionStatuses(activeConnection_->iapId(), connectionStatus);
        if (connectionStatus == WlanQtUtilsConnectionStatusConnected) {
            emit q_ptr->wlanNetworkOpened(activeConnection_->iapId());
        }
        // Do not inform UI about connection closing here. It is done always in
        // removeActiveConnection(), because that may occur without any connection status updates.
    } // else: connection status did not change

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_UPDATEACTIVECONNECTION_EXIT, this );
}

int WlanQtUtilsPrivate::fetchIaps()
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_FETCHIAPS_ENTRY, this );
    
    QList<WlanQtUtilsIap *> list;
    int error = 0; 
    // Read the IAP list and store WLAN IAPs in our internal map data structure
    error = cmmWrapper_->fetchIaps(list);    
    foreach (WlanQtUtilsIap *iap, list) {
        if (iap->bearerType() == WlanQtUtilsBearerTypeWlan) {
            // Notice that insertMulti not used, because IAP IDs should be unique
            wlanIapList_.insert(iap->id(), qobject_cast<WlanQtUtilsWlanIap *>(iap));            
        }
    }
        
    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_FETCHIAPS_EXIT, this );
    return error;
}

bool WlanQtUtilsPrivate::wlanIapExists(QString ssid, WlanQtUtilsWlanSecMode secMode)
{    
    foreach (WlanQtUtilsWlanIap *iap, wlanIapList_) {
        // todo: secmode
        (void)secMode;
        if (iap->ssid() == ssid) {
            return true;
        }
    }
    
    return false;
}

void WlanQtUtilsPrivate::updateIapConnectionStatuses(int iapId, WlanQtUtilsConnectionStatus status)
{
    OstTraceFunctionEntry1( WLANQTUTILSPRIVATE_UPDATEIAPCONNECTIONSTATUSES_ENTRY, this );
    
    const WlanQtUtilsWlanIap *referenceIap = qobject_cast<WlanQtUtilsWlanIap *>(iap(iapId));
    foreach (WlanQtUtilsWlanIap *iap, wlanIapList_) {
        // todo: security mode checking
        if (iap->id() == referenceIap->id() || iap->ssid() == referenceIap->ssid()) {
            iap->setConnectionStatus(status);
        }
    }

    OstTraceFunctionExit1( WLANQTUTILSPRIVATE_UPDATEIAPCONNECTIONSTATUSES_EXIT, this );
}