--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkcontrol/ipnetworklayer/src/IPProtoTierManagerSelector.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,883 @@
+// Copyright (c) 2006-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:
+// This is part of an ECOM plug-in
+//
+//
+
+#include "IPProtoTierManagerSelector.h"
+#include "IPProtoTierManagerFactory.h"
+#include "IPProtoMCpr.h"
+#include <comms-infras/ss_log.h>
+#include <ss_glob.h>
+#include <comms-infras/ss_tiermanagerutils.h>
+#include <commsdattypesv1_1.h> // CommsDat
+#include <es_connpref.h> //TConnIdList
+#include <commdbconnpref.h> //TCommDbConnPref & TCommDbConnPrefMulti
+
+#include <comms-infras/esock_params_internal.h> //TConnCSRParams
+#include <comms-infras/ss_mcprnodemessages.h> //RConnPrefList and Iterator
+#include <comms-infras/esock_params.h>
+#include <comms-infras/ss_metaconnprov_internal.h>
+#include <comms-infras/simpleselectorbase.h>
+#include <commsdattypesv1_1_partner.h>
+
+#ifdef _DEBUG
+#define KIpProtoTierMgrTag KESockMetaConnectionTag
+_LIT8(KIpProtoTierMgrSubTag, "ipprototiermgr");
+#endif
+
+using namespace ESock;
+using namespace CommsDat;
+
+const TInt KCommsdatLinkFlag = 0x80000000;
+
+
+//Panic codes
+_LIT(KIpProtoSelectorPanic, "IpProtoSelector");
+enum TIpProtoSelectorPanic
+ {
+ EExpectedAccessPointAwareSystem = 0,
+ EUnExpectedSelectionPreferences = 1,
+ EUnExpectedNumberOfAccessPoints = 2
+ };
+
+TUint FindIPProtoAccessPointForIAPL(TUint aIap, CMDBSession* aDbs)
+ {
+ CCDAccessPointRecord* apRec = static_cast<CCDAccessPointRecord*>(CCDTierRecord::RecordFactoryL(KCDTIdAccessPointRecord));
+ CleanupStack::PushL(apRec);
+ apRec->iCprConfig = aIap;
+ apRec->iTier = CIPProtoTierManagerFactory::iUid | KCommsdatLinkFlag;
+
+ TUint ap = 0;
+ TBool found = apRec->FindL(*aDbs);
+ if (found)
+ {
+ ap = apRec->iRecordTag;
+ }
+ else
+ {
+ ap = TierManagerUtils::ReadDefaultAccessPointL(TUid::Uid(CIPProtoTierManagerFactory::iUid), *aDbs);
+ }
+ CleanupStack::PopAndDestroy(apRec);
+
+ return ap;
+ }
+
+
+CMetaConnectionProviderBase* AIpProtoSelectorBase::FindOrCreateProviderL(TUint aIapToFind, TUint aAccessPointToCreate)
+ {
+ //Find factory
+ TUid mCprUid = TierManagerUtils::ReadMCprUidL(aAccessPointToCreate,*iDbs);
+ CMetaConnectionProviderFactoryBase* factory = static_cast<CMetaConnectionProviderFactoryBase*>(iMetaContainer.FindOrCreateFactoryL(mCprUid));
+
+ //Create the provider
+ TUid tierId = TUid::Uid(iTierRecord->iRecordTag);
+ TUid tierImplUid = TUid::Uid(iTierRecord->iTierImplUid);
+ TProviderInfo providerInfo(tierId,aIapToFind);
+ TMetaConnectionFactoryQuery query(providerInfo,tierImplUid);
+ CMetaConnectionProviderBase* provider = static_cast<CMetaConnectionProviderBase*>(factory->Find(query));
+ if (provider==NULL)
+ {
+ //If this is an attach selection, the provider must be found, so leave with an error
+ if (iSelectionPrefs.Scope()&TSelectionPrefs::ESelectFromExisting)
+ {
+ //For legacy reasons only, we need to return KErrCouldNotConnect instead of KErrNotFound
+ //for leagcy attach (legacy attach uses EConnPrefCommDb).
+ User::Leave(iSelectionPrefs.Prefs().ExtensionId() == TConnPref::EConnPrefCommDb ? KErrCouldNotConnect : KErrNotFound);
+ }
+
+ //For construction of IpProto providers (construction only) we use the instance field of TProviderInfo
+ //to carry the IAP id. The IAP id is necessary fo the provider to initialise itself from the database.
+ TMetaConnectionFactoryQuery query(TProviderInfo(tierId,aAccessPointToCreate,(TAny*)aIapToFind),tierImplUid);
+ provider = static_cast<CMetaConnectionProviderBase*>(factory->CreateObjectL(query));
+ }
+
+ if (!(iSelectionPrefs.Scope()&TSelectionPrefs::ESelectFromExisting))
+ {
+ CIPProtoMetaConnectionProvider *ipprotomcpr = static_cast<CIPProtoMetaConnectionProvider *>(provider);
+ if (ipprotomcpr->iIapLocked)
+ User::Leave(KErrPermissionDenied);
+
+ TSecureId sid;
+ ASubSessionPlatsecApiExt platsecext(iSelectionPrefs.SubSessionUniqueId());
+ if (platsecext.SecureId(sid) == KErrNone)
+ {
+ CCommsDatIapView* iapView = CCommsDatIapView::NewLC(aIapToFind);
+
+ TUint32 iapsid;
+ iapView->GetIntL(KCDTIdIAPAppSid, iapsid);
+
+ if (sid.iId == iapsid && iapsid != 0)
+ ipprotomcpr->iIapLocked = ETrue;
+ CleanupStack::PopAndDestroy(iapView);
+ }
+ }
+ provider->IncrementBlockingDestroy();
+ return provider;
+ }
+
+//
+//CIpProtoProviderSelector
+
+void CIpProtoProviderSelector::RunL()
+ // The dialogue has been presented.
+ // Normally completes with KErrNone or KErrCancel
+ // Could, however, complete with another system error e.g. KErrOutOfMemory
+ {
+ TInt error = iStatus.Int();
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("CIpProtoProviderSelector %08x::\tRunL() Err%d Ap%d"),this, error, SelectedIAP()));
+ User::LeaveIfError(error);
+
+ ASSERT(SelectedIAP()); //Should not be 0 now.
+
+ TConnPref& pref = iSelectionPrefs.Prefs();
+ const TConnIdList& list = static_cast<const TConnIdList&>(pref);
+ TUint accessPoint = list.Get(0);
+
+ //finish the selection which the prompt was for
+ CMetaConnectionProviderBase* ipprotoMCPr = FindOrCreateProviderL(SelectedIAP(), FindIPProtoAccessPointForIAPL(SelectedIAP(), iDbs));
+ TLayerSelectionInfo* selectionInfo = const_cast<TLayerSelectionInfo*>(
+ static_cast<const TLayerSelectionInfo*>(ipprotoMCPr->AccessPointConfig().FindExtension(
+ STypeId::CreateSTypeId(TLayerSelectionInfo::EUid, TLayerSelectionInfo::ETypeId))));
+ __ASSERT_ALWAYS(selectionInfo, User::Panic(_L("ipproto"), CorePanics::KPanicUnexpectedExecutionPath));
+
+ if ((TUint)-1 == selectionInfo->CustomSelectionPolicy())
+ {
+ /*
+ * This means that the default IPProto AP is used from the meshpreface.cfg file,
+ * which has a -1 as the CustomSelectionPolicy (the reason for that is that we don't know
+ * which will be the default IAP, default Link level AP, so that's why we prompted for that).
+ * This is the place and time we know how to overwrite the AccessPoint information of the MCPr
+ * meaning we know the selected IAP. So the -1 value can be overwritten with the selected recordID,
+ * or tagID of the Link level AP.
+ */
+ selectionInfo->iCustomSelectionPolicy = SelectedIAP();
+ selectionInfo->iCprConfig = SelectedIAP();
+ }
+
+ iSelectionNotify.SelectComplete(this,ipprotoMCPr);
+ //iSelectionNotify.SelectComplete(this,FindOrCreateProviderL(SelectedIAP(), FindIPProtoAccessPointForIAPL(SelectedIAP(), iDbs)));
+
+ //store the information that we have already prompted the user
+ TPromptingSelectionPrefsExt* promptingExt = const_cast<TPromptingSelectionPrefsExt*>(
+ static_cast<const TPromptingSelectionPrefsExt*>(iNetworkMCpr->AccessPointConfig().FindExtension(
+ TPromptingSelectionPrefsExt::TypeId())));
+ if (promptingExt == NULL)
+ {
+ /*
+ * the extension is not existing yet on the AccessPointConfig of the NetMCPr. Append a new one
+ * to indicate that we have already prompted the user. So if the configuration contains 2
+ * ConnectionPreferences record without any default IAP and with PROPTING dialog preference then
+ * the prompt dialog won't be invoked in the 2nd time but only during the re-selection, if it's needed.
+ */
+ RMetaExtensionContainer mec;
+ mec.Open(iNetworkMCpr->AccessPointConfig());
+ CleanupClosePushL(mec);
+
+ TConnIdList dummyList;
+ TPromptingSelectionPrefsExt* ext = new (ELeave) TPromptingSelectionPrefsExt(TUid::Uid(iTierRecord->iRecordTag),dummyList); //it's an empty list
+ CleanupStack::PushL(ext);
+ mec.AppendExtensionL(ext);
+ CleanupStack::Pop(ext);
+
+ iNetworkMCpr->AccessPointConfig().Close();
+ iNetworkMCpr->AccessPointConfig().Open(mec);
+ CleanupStack::PopAndDestroy(&mec);
+ }
+ else if (!promptingExt->iPromptingInProgress)
+ {
+ promptingExt->iPromptingInProgress = ETrue;
+ }
+ else
+ {
+ /* the extension is existing already on the AccessPointConfig of the NetMCPr.
+ * This means that this is was the 2nd time we have prompted. Mark the extension
+ * to indicate that we don't have any more choices...
+ */
+ promptingExt->iPromptingInProgress = EFalse;
+ }
+
+ //Complete the selection request
+ iSelectionNotify.SelectComplete(this,NULL);
+ }
+
+TInt CIpProtoProviderSelector::RunError(TInt aError)
+ {
+ iSelectionNotify.Error(this,aError);
+ return KErrNone;
+ }
+
+void CIpProtoProviderSelector::InvokeDialogL(ISelectionNotify& aSelectionNotify,
+ TUint aCprConfig)
+ {
+ TConnectionPrefs prefsForPromt;
+ TierManagerUtils::GetPrefsFromConnPrefRecL(aCprConfig, *iDbs, prefsForPromt);
+
+ PromptUserL(aSelectionNotify, prefsForPromt);
+ }
+
+void CIpProtoProviderSelector::SelectL(ISelectionNotify& aSelectionNotify)
+ {
+ ASSERT(iDbs);
+ ASSERT(iTierRecord);
+ TUint32 defaultAccessPoint = iTierRecord->iDefaultAccessPoint;
+
+ //Must be set
+ __ASSERT_DEBUG(defaultAccessPoint!=0,User::Panic(KIpProtoSelectorPanic,EExpectedAccessPointAwareSystem));
+ User::LeaveIfError(defaultAccessPoint!=0? KErrNone : KErrCorrupt);
+
+ TConnPref& pref = iSelectionPrefs.Prefs();
+ //This selector receives only EConnPrefIdList at this layer
+ __ASSERT_DEBUG(pref.ExtensionId() == TConnPref::EConnPrefIdList, User::Panic(KIpProtoSelectorPanic,EUnExpectedSelectionPreferences));
+
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("CIpProtoProviderSelector %08x::\tSelectL() Using TConnIdList"),this));
+ const TConnIdList& list = static_cast<const TConnIdList&>(pref);
+
+ TUint apElemId = 0;
+ TUint cprConfig = 0;
+ TUint custSelPol = 0;
+
+ TInt count = list.Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ TUint accessPoint = list.Get(i);
+
+ cprConfig = TierManagerUtils::ReadCprConfigL(accessPoint, *iDbs);
+ custSelPol = TierManagerUtils::ReadCustomSelectionPolicyIdL(accessPoint, *iDbs);
+
+ if ( (KCDTIdConnectionPrefsRecord == (KCDMaskShowRecordType & cprConfig)) ||
+ ((TUint)-1 == custSelPol) )
+ {
+ /* 1.)
+ * There is a full TMDBelementID in the cprConfig field of the given AP.
+ * This means that the related ConnPref record is a prompting record so
+ * this AP is a so-called 'prompring AP. Invoke a dialog prompt.
+ *
+ * 2.)
+ * The default IPProto AP is used form the meshpreface.cfg file, where
+ * there isn't any connectionPrefs record in the database. We should invoke
+ * a dialog in this case too to get back the tagID of the Linke level AP, which
+ * is the same as recordID of the used IAP.
+ *
+ */
+
+ TPromptingSelectionPrefsExt* promptingExt = const_cast<TPromptingSelectionPrefsExt*>(
+ static_cast<const TPromptingSelectionPrefsExt*>(iNetworkMCpr->AccessPointConfig().FindExtension(
+ TPromptingSelectionPrefsExt::TypeId())));
+ if (promptingExt)
+ {
+ /* our NetMCPr has a prompting extension already. This can mean 2 things:
+ * 1.) We are still in the selection process and we have 2 prompting APs on
+ * the IPProto level. In this case now (2nd time) don't invoke any further
+ * dialog but store the information in the NetMCPr that we have still 1
+ * possibility for the re-selection scenario.
+ * 2.) This is the re-selection scenario, so we have to invoke the prompt
+ * dialog.
+ */
+
+ if (!iReselection)
+ {
+ //the 1.) paragraph is true
+ TConnIdList list;
+ list.Append(accessPoint);
+
+ promptingExt->iPrefs = list;
+ promptingExt->iTierId = TUid::Uid(iTierRecord->iRecordTag);
+ promptingExt->iPromptingInProgress = ETrue;
+ }
+ else
+ {
+ //the 2.) paragraph is true
+ //invoke a dialog
+ InvokeDialogL(aSelectionNotify, cprConfig);
+ return; //selection will continue in the RunL
+ }
+ }
+ else
+ {
+ //invoke a dialog
+ InvokeDialogL(aSelectionNotify, cprConfig);
+ return; //selection will continue in the RunL
+ }
+ }
+ else
+ {
+ /*
+ * business as usual
+ */
+ TPromptingSelectionPrefsExt* promptingExt = const_cast<TPromptingSelectionPrefsExt*>(
+ static_cast<const TPromptingSelectionPrefsExt*>(iNetworkMCpr->AccessPointConfig().FindExtension(
+ TPromptingSelectionPrefsExt::TypeId())));
+ if (promptingExt != NULL)
+ {
+ /* There is a prompting extension in the AccessPointConfig of our
+ * Network MCPr. This means that there are 2 ConnPref records in the
+ * database. The first one is a prompting one (that's why the extension is there
+ * - to indicate that we have already prompted). But the 2nd record is
+ * not a prompting record, so the mapped IPProto AP is _NOT_ a prompting AP.
+ * Continue the selection as usual, and mark the extension - it's not
+ * needed anymore because if there will be a re-selection we can't use
+ * the extension as the 2nd IPProto AP is not a promting one.
+ */
+ promptingExt->iPromptingInProgress = EFalse;
+ }
+
+ //apElemId = TierManagerUtils::ReadCustomSelectionPolicyIdL(accessPoint,*iDbs);
+ apElemId = TierManagerUtils::ReadCprConfigL(accessPoint,*iDbs);
+ aSelectionNotify.SelectComplete(this,FindOrCreateProviderL(apElemId,accessPoint));
+ }
+ } //for
+
+ //Complete the selection request
+ aSelectionNotify.SelectComplete(this,NULL);
+ }
+
+
+//
+//CIpProtoProviderSelectorConnPrefList
+CIpProtoProviderSelectorConnPrefList::CIpProtoProviderSelectorConnPrefList(const ESock::RConnPrefList& aSelectionPreferences)
+ : AIpProtoSelectorBase()
+ , iSelectionPrefList(aSelectionPreferences)
+ , iTierId(TUid::Uid(CIPProtoTierManagerFactory::iUid))
+ , iLastAccessPoint(0)
+ {
+ }
+
+void CIpProtoProviderSelectorConnPrefList::RunL()
+ // The dialogue has been presented.
+ // Normally completes with KErrNone or KErrCancel
+ // Could, however, complete with another system error e.g. KErrOutOfMemory
+ {
+ TInt error = iStatus.Int();
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("CIpProtoProviderSelector %08x::\tRunL() Err%d Ap%d"),this, error, SelectedIAP()));
+ User::LeaveIfError(error);
+
+ ASSERT(SelectedIAP()); //Should not be 0 now.
+
+ //finish the selection which the prompt was for
+ iSelectionNotify.SelectComplete(this,FindOrCreateProviderL(SelectedIAP(), iLastAccessPoint));
+
+ //--------------------------------------------------
+ //continue the loop which we started in the SelectL
+ //--------------------------------------------------
+ ESock::RConnPrefList::TIter<TConnAPPref> iterAP = iSelectionPrefList.getIter<TConnAPPref>();
+
+ CCDAccessPointRecord* apRec;
+ TUid tierId;
+ TInt cprConfig = 0;
+
+//This iterator runs through all the instances of TConnAPPref
+ while(!iterAP.IsEnd())
+ {
+ //Access point is retrived from preference
+ TUint accessPoint = iterAP->GetAP();
+ //The record relating to this access point is retrived
+ apRec = TierManagerUtils::LoadAccessPointRecordL(accessPoint,*iDbs);
+ //A check is done to confirm the access point is related to this tier
+ //tierId = TUid::Uid(apRec->iTier);
+ tierId = TierManagerUtils::MapElementIdToTagId(apRec->iTier, *iDbs);
+
+ delete apRec;
+ if(iTierId == tierId)
+ {
+ //The iap related to the access point is retrived from the record
+ //This iap must be created at the link layer, within the method
+ //FindOrCreateProviderL the provider created is provisioned with this
+ //iap, this means when the next tier is created the appropriate iap will
+ //be created
+
+ cprConfig = TierManagerUtils::ReadCprConfigL(accessPoint,*iDbs);
+
+ if (KCDTIdConnectionPrefsRecord == (KCDMaskShowRecordType & cprConfig))
+ {
+ /* There is a full TMDBelementID in the cprConfig field of the given AP.
+ * This means that the related ConnPref record is a prompting record so
+ * this AP is a so-called 'prompring AP. As we are in the RunL method
+ * this means that we've invoked already a dilog prompt so here we cannot
+ * invoke another one. Instead store the information that we have still
+ * possibilies in the case of a reconnection.
+ */
+ TConnIdList list;
+ list.Append(accessPoint);
+
+ RMetaExtensionContainer mec;
+ mec.Open(iNetworkMCpr->AccessPointConfig());
+ CleanupClosePushL(mec);
+
+ TPromptingSelectionPrefsExt* ext = new (ELeave) TPromptingSelectionPrefsExt(TUid::Uid(iTierRecord->iRecordTag),list); //it's an empty list
+ CleanupStack::PushL(ext);
+ mec.AppendExtensionL(ext);
+ CleanupStack::Pop(ext);
+
+ iNetworkMCpr->AccessPointConfig().Close();
+ iNetworkMCpr->AccessPointConfig().Open(mec);
+ CleanupStack::PopAndDestroy(&mec);
+ }
+ else
+ {
+ iSelectionNotify.SelectComplete(this,FindOrCreateProviderL(cprConfig, accessPoint));
+ }
+ //The peference is no longer needed so is deleted and removed
+ delete iterAP.Remove();
+ }
+ else
+ {
+ iterAP++;
+ }
+ }
+ iSelectionNotify.SelectComplete(this,NULL);
+ }
+
+TInt CIpProtoProviderSelectorConnPrefList::RunError(TInt aError)
+ {
+ iSelectionNotify.Error(this,aError);
+ return KErrNone;
+ }
+
+void CIpProtoProviderSelectorConnPrefList::SelectL(ISelectionNotify& aSelectionNotify)
+ {
+ iDbs = CMDBSession::NewL(KCDVersion1_2);
+ iTierRecord = TierManagerUtils::LoadTierRecordL(iTierId,*iDbs);
+
+ ASSERT(iTierRecord);
+
+ CCDAccessPointRecord* apRec;
+ TUid tierId;
+
+ ESock::RConnPrefList::TIter<TConnCSRPref> iterCSR = iSelectionPrefList.getIter<TConnCSRPref>();
+ ASSERT(iterCSR[0] != NULL || iterCSR[1] == NULL );
+ iSelectionPrefs.SetScope(iterCSR[0]->Scope());
+ iSelectionPrefs.SetFlags(iterCSR[0]->Flags());
+ iSelectionPrefs.SetSubSessionUniqueId(iterCSR[0]->SubSessionUniqueId());
+
+ TInt cprConfig = 0;
+
+ ESock::RConnPrefList::TIter<TConnAPPref> iterAP = iSelectionPrefList.getIter<TConnAPPref>();
+
+ //This iterator runs through all the instances of TConnAPPref
+ while(!iterAP.IsEnd())
+ {
+ //Access point is retrived from preference
+ TUint accessPoint = iterAP->GetAP();
+ //The record relating to this access point is retrived
+ apRec = TierManagerUtils::LoadAccessPointRecordL(accessPoint,*iDbs);
+ //A check is done to confirm the access point is related to this tier
+ //tierId = TUid::Uid(apRec->iTier);
+ tierId = TierManagerUtils::MapElementIdToTagId(apRec->iTier, *iDbs);
+
+ delete apRec;
+ if(iTierId == tierId)
+ {
+ //The iap related to the access point is retrived from the record
+ //This iap must be created at the link layer, within the method
+ //FindOrCreateProviderL the provider created is provisioned with this
+ //iap, this means when the next tier is created the appropriate iap will
+ //be created
+
+ cprConfig = TierManagerUtils::ReadCprConfigL(accessPoint,*iDbs);
+
+ if (KCDTIdConnectionPrefsRecord == (KCDMaskShowRecordType & cprConfig))
+ {
+ /* There is a full TMDBelementID in the cprConfig field of the given AP.
+ * This means that the related ConnPref record is a prompting record so
+ * this AP is a so-called 'prompring AP. Invoke a dialog prompt.
+ */
+ //invoke a dialog
+
+ TConnectionPrefs prefsForPromt;
+ TierManagerUtils::GetPrefsFromConnPrefRecL(cprConfig, *iDbs, prefsForPromt);
+
+ PromptUserL(aSelectionNotify, prefsForPromt);
+
+ /* Remove the last processed preference so the loop in the
+ * RunL can continue from the beginning of the list
+ */
+ delete iterAP.Remove();
+ iLastAccessPoint = accessPoint;
+ return; //selection will continue in the RunL
+ }
+ else
+ {
+ aSelectionNotify.SelectComplete(this,FindOrCreateProviderL(cprConfig, accessPoint));
+ }
+ //The peference is no longer needed so is deleted and removed
+ delete iterAP.Remove();
+ }
+ else
+ {
+ iterAP++;
+ }
+ }
+ aSelectionNotify.SelectComplete(this,NULL);
+ }
+
+
+//
+//CLinkPrefsSelector
+CLinkPrefsSelector::~CLinkPrefsSelector()
+ {
+ iPrefsList.Reset();
+ iPrefsList.Close();
+ }
+
+void CLinkPrefsSelector::SelectL(ISelectionNotify& aSelectionNotify)
+ {
+ ASSERT(iDbs);
+ ASSERT(iTierRecord);
+ ASSERT(iLegacyMCpr); //This selector depends on the legacy MCpr (client) being set!
+ iSelectionNotify = aSelectionNotify; //Store notify interface for asynch processing
+ TUint32 defaultAccessPoint = iTierRecord->iDefaultAccessPoint;
+
+ //Must be set
+ __ASSERT_DEBUG(defaultAccessPoint!=0,User::Panic(KIpProtoSelectorPanic,EExpectedAccessPointAwareSystem));
+ User::LeaveIfError(defaultAccessPoint!=0? KErrNone : KErrCorrupt);
+
+ if (!iSelectionPrefs.IsEmpty() && iSelectionPrefs.Prefs().ExtensionId() == TConnPref::EConnPrefCommDb)
+ { //There is only ever going to be one AP (Ip layer) as a result of these prefs.
+ //IAP based attach should follow this branch as well and takes the same route as
+ //ordinary selection (at this layer only)
+ TCommDbConnPref connPrefs = static_cast<const TCommDbConnPref&>(iSelectionPrefs.Prefs());
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("CLinkPrefsSelector %08x::\tSelectL() Using TCommDbConnPref, IAP:%d"),this,connPrefs.IapId()));
+ OverrideLegacyPrefs(connPrefs,1);
+ iPrefsList.AppendL(connPrefs);
+ }
+ else if (!iSelectionPrefs.IsEmpty() && iSelectionPrefs.Prefs().ExtensionId() == TConnPref::EConnPrefCommDbMulti)
+ { //There may be multiple APs (Ip layer) as a result of these prefs.
+ const TCommDbMultiConnPref& connPrefsMulti = static_cast<const TCommDbMultiConnPref&>(iSelectionPrefs.Prefs());
+ TInt attempts = const_cast<TCommDbMultiConnPref&>(connPrefsMulti).ConnectionAttempts();
+ ASSERT(attempts >= 0 && attempts <= TCommDbMultiConnPref::KMaxMultiConnPrefCount); //Sanity check
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("CLinkPrefsSelector %08x::\tSelectL() Using TCommDbMultiConnPref, attempts:%d"),this,attempts));
+ //Be careful, TCommDbMultiConnPref takes a special index that starts from 1!
+ for (TInt i = 1; i <= attempts; i++)
+ {
+ TCommDbConnPref connPrefs;
+ User::LeaveIfError(const_cast<TCommDbMultiConnPref&>(connPrefsMulti).GetPreference(i,connPrefs));
+ OverrideLegacyPrefs(connPrefs,i);
+ iPrefsList.AppendL(connPrefs);
+ }
+ }
+ else
+ {
+ //We must have link layer prefs here!
+ User::Panic(KIpProtoSelectorPanic,EUnExpectedSelectionPreferences);
+ }
+
+ //From this point on we attempt to mimic the legacy netcon/nifman selection logic.
+ //All preferences are now stored in the iPrefsList and for our legacy scenarios
+ //the list can not be empty.
+ ASSERT(iPrefsList.Count()>0);
+ User::LeaveIfError(iPrefsList.Count()>0? KErrNone : KErrArgument);
+ ProcessPrefsFromListL();
+ }
+
+void CLinkPrefsSelector::OverrideLegacyPrefs(TCommDbConnPref& aConnPrefs, TInt aRank)
+ {
+ //A short guide to legacy overrides, in chronological order.
+ //1) If direction preferences == ECommDbConnectionDirectionUnknown,
+ //use ECommDbConnectionDirectionOutgoing, otherwise keep the prefs
+ //2) If iap == 0,
+ //GetPreferedIap(direction,attempt)
+ //3) If iap == 0 and ECommDbDialogPrefUnknown,
+ //set the dialog preference to ECommDbDialogPrefPrompt
+ //4) If dialog preference == ECommDbDialogPrefUnknown,
+ //use setting from the CCDTierRecord, otherwise keep the prefs
+ //5) If bearer preferences == ECommDbBearerUnknown,
+ //use the one from the IAP record, oterwise keep the prefs
+ //6) If dialog preference == ECommDbDialogPrefDoNotPrompt and iap == 0,
+ //use default from the CCDTierRecord record
+ //Finally, for multiple preferences, or when the dialog is used,
+ //we disallow (remove) repetitions.
+ //The rest of the legacy selection logic is in the legacy reconnection
+ //activity.
+ if (aConnPrefs.Direction()==ECommDbConnectionDirectionUnknown)
+ {
+ aConnPrefs.SetDirection(ECommDbConnectionDirectionOutgoing);
+ }
+ if (aConnPrefs.IapId()==0)
+ {
+ //Ignore if the record does not exist, aConnPrefs state should not change
+ TRAP_IGNORE(TierManagerUtils::MapRankingAndDirectionToPrefsL(aRank,aConnPrefs.Direction(),aConnPrefs,*iDbs));
+ }
+ if (aConnPrefs.IapId()==0 && aConnPrefs.DialogPreference()==ECommDbDialogPrefUnknown)
+ {
+ aConnPrefs.SetDialogPreference(ECommDbDialogPrefPrompt);
+ }
+ if (aConnPrefs.DialogPreference()==ECommDbDialogPrefUnknown)
+ {
+ TBool promptUser = iTierRecord->iPromptUser;
+ aConnPrefs.SetDialogPreference(promptUser? ECommDbDialogPrefPrompt : ECommDbDialogPrefDoNotPrompt);
+ }
+ if (aConnPrefs.BearerSet()==ECommDbBearerUnknown)
+ {
+ }
+ if (aConnPrefs.IapId()==0 && aConnPrefs.DialogPreference()==ECommDbDialogPrefDoNotPrompt)
+ {
+ aConnPrefs.SetIapId(iTierRecord->iDefaultAccessPoint);
+ }
+ }
+
+
+void CLinkPrefsSelector::ProcessPrefsFromListL()
+ {
+ //There may be more than one preference in the list (usually one or two).
+ //Some of them may have their dialog preference as ECommDbDialogPrefDoNotPrompt,
+ //some may have ECommDbDialogPrefPrompt.
+
+ //To code this selection behaviour as close to the legacy netcon's/nifman's
+ //logic as possible, we have taken the following approach:
+ //1) We select as much from the preference list as possible without invoking a dialog.
+ //2) If the selection is completed (iToBeSelected is empty) we finish, otherwise
+ //3) We prompt for the preferences that need to be prompted for
+ //4) If the dialog failed (has been cancelled, etc) we finish with an error, otherwise
+ //5) If the selection is completed (iToBeSelected is empty) we finish, otherwise
+ //6) We find the NetMCpr and store all remaining iToBeSelected entries in its configuration data
+ //Later, during legacy reconnection, these stored entries will be used by the legacy NetMCpr
+ //to extend its meta tree by nodes that could not be selected here at this time.
+
+ //If there is more than one preference in the queue, we will only ever prompt once, for the first one.
+ ASSERT(iPrefsList.Count());
+
+ //Take the first preference (see above for details)
+ TCommDbConnPref connPrefs = iPrefsList[0];
+ iPrefsList.Remove(0); //We do not want to consider this option again
+
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("CLinkPrefsSelector %08x\tProcessPrefsFromListL DialogPreference: %d"), this, connPrefs.DialogPreference()));
+
+ //We are here only because DialogPreference()!=ECommDbDialogPrefDoNotPrompt
+ if (connPrefs.DialogPreference()==ECommDbDialogPrefDoNotPrompt ||
+ connPrefs.DialogPreference()==ECommDbDialogPrefPromptIfWrongMode)
+ {
+ SetSelectedIAP(connPrefs.IapId());
+ RunL();
+ }
+ else
+ {
+ //We have to involve dialog
+ User::LeaveIfError(iDlgServ.Connect());
+ TConnectionPrefs dialogPrefs;
+ dialogPrefs.iRank = 1;
+ dialogPrefs.iDirection = connPrefs.Direction();
+ dialogPrefs.iBearerSet = connPrefs.BearerSet();
+ // pass in iSelectedAPId directly here, as it's being passed in as a
+ // TUint32& and so IapConnection may wish to modify it.
+ iDlgServ.IapConnection(iSelectedAPId,dialogPrefs,iStatus);
+ SetActive();
+ iUserPromted = ETrue;
+ }
+ }
+
+void CLinkPrefsSelector::RunL()
+ {
+ if (iUserPromted)
+ {
+ TInt error = iStatus.Int();
+ if (error!=KErrNone)
+ {
+ //The dialog has most likely been cancelled, etc
+ //This means no more selection, complete the selection request as it stands
+ iSelectionNotify.Error(this,error);
+ return;
+ }
+ }
+
+ ASSERT(SelectedIAP()); //Must not be 0 now. Check your commsdat if it is.
+ ASSERT(iTierRecord);
+
+ //Report
+ iSelectionNotify.SelectComplete(this,FindOrCreateProviderL(SelectedIAP(),FindIPProtoAccessPointForIAPL(SelectedIAP(), iDbs)));
+
+ //Selection has not finished yet, so decide what to do next
+ if (iPrefsList.Count()>0)
+ {
+ ASSERT(iPrefsList.Count()==1); //Well, in the legacy world you could not have more than two..
+ if (iUserPromted)
+ { //We have already prompted the user, so store the rest of the preferences
+ //into legacy NetMCpr's configuration data.
+ ASSERT(iLegacyMCpr->AccessPointConfig().FindExtension(TDeferredSelectionPrefsExt::TypeId())==NULL);
+
+ RMetaExtensionContainer mec;
+ mec.Open(iLegacyMCpr->AccessPointConfig());
+ CleanupClosePushL(mec);
+
+ TDeferredSelectionPrefsExt* ext = new (ELeave) TDeferredSelectionPrefsExt(TUid::Uid(iTierRecord->iRecordTag),iPrefsList[0]);
+ iPrefsList.Close();
+ CleanupStack::PushL(ext);
+ mec.AppendExtensionL(ext);
+ CleanupStack::Pop(ext);
+
+ iLegacyMCpr->AccessPointConfig().Close();
+ iLegacyMCpr->AccessPointConfig().Open(mec);
+ CleanupStack::PopAndDestroy(&mec);
+ }
+ else
+ {
+ //We have not prompted the user yet and the selection has not finished,
+ //proceed to the next preference.
+ ProcessPrefsFromListL();
+ return;
+ }
+ }
+
+ //Selection has finished, regardless if we have prompted user or not, finish.
+ iSelectionNotify.SelectComplete(this,NULL); //Complete the selection request
+ }
+
+TInt CLinkPrefsSelector::RunError(TInt aError)
+ {
+ //The iSelectionNotify must not be NULL now since it has been set in SelectL
+ iSelectionNotify.Error(this,aError);
+ return KErrNone;
+ }
+
+/**
+
+ Since Ip Proto providers need to carry their IAP's identification, we use two Ids
+ as parameters to this factory function:
+ One is used to find a provider at this layer (IAP id), the other is used to create
+ (and provision) a provider at this layer (for legacy selection it is the default
+ access point).
+*/
+CMetaConnectionProviderBase* CLinkPrefsSelector::FindOrCreateProviderL(TUint aIapToFind, TUint aAccessPointToCreate)
+ {
+ TUid mCprUid = TierManagerUtils::ReadMCprUidL(aAccessPointToCreate,*iDbs);
+ CMetaConnectionProviderFactoryBase* factory = static_cast<CMetaConnectionProviderFactoryBase*>(iMetaContainer.FindOrCreateFactoryL(mCprUid));
+
+ //Create the provider
+ TUid tierId = TUid::Uid(iTierRecord->iRecordTag);
+ TUid tierImplUid = TUid::Uid(iTierRecord->iTierImplUid);
+ TProviderInfo providerInfo(tierId,aIapToFind);
+ TMetaConnectionFactoryQuery query (providerInfo,tierImplUid);
+ CMetaConnectionProviderBase* provider = static_cast<CMetaConnectionProviderBase*>(factory->Find(query));
+ TBool providerCreated(EFalse);
+ if (provider==NULL)
+ {
+ //If this is an attach selection, the provider must be found, so leave with an error
+ if (iSelectionPrefs.Scope()&TSelectionPrefs::ESelectFromExisting)
+ {
+ //For legacy reasons only, we need to return KErrCouldNotConnect instead of KErrNotFound
+ //for leagcy attach (legacy attach uses EConnPrefCommDb).
+ User::Leave(iSelectionPrefs.Prefs().ExtensionId() == TConnPref::EConnPrefCommDb ? KErrCouldNotConnect : KErrNotFound);
+ }
+
+ //For construction of IpProto providers (construction only) we use the instance field of TProviderInfo
+ //to carry the IAP id. The IAP id is necessary fo the provider to initialise itself from the database.
+ TMetaConnectionFactoryQuery query(TProviderInfo(tierId,aAccessPointToCreate,(TAny*)aIapToFind),tierImplUid);
+ provider = static_cast<CMetaConnectionProviderBase*>(factory->CreateObjectL(query));
+ providerCreated = ETrue; // See below - non obvious conditional late CleanupStack::Pop()
+ CleanupStack::PushL(provider);
+ if (aIapToFind != aAccessPointToCreate)
+ {
+ RMetaExtensionContainer mec;
+ mec.Open(provider->AccessPointConfig());
+ CleanupClosePushL(mec);
+
+ //This IpProto provider must always go straight for the lower layer IAP.
+ //For that we need to override the selection policy.
+ TConnIdList list;
+ list.Append(aIapToFind);
+ TUid nextTierId = TierManagerUtils::ReadTierIdL(aIapToFind,*iDbs);
+ TOverridenSelectionPrefsExt* ext = new (ELeave) TOverridenSelectionPrefsExt(nextTierId,TSelectionPrefs(list));
+ CleanupStack::PushL(ext);
+ mec.AppendExtensionL(ext); //The ownership of the extension goes to AccessPointConfig now.
+ CleanupStack::Pop(ext);
+
+ provider->AccessPointConfig().Close();
+ provider->AccessPointConfig().Open(mec);
+ CleanupStack::PopAndDestroy(&mec);
+ }
+ }
+
+ if (!(iSelectionPrefs.Scope()&TSelectionPrefs::ESelectFromExisting))
+ {
+ CIPProtoMetaConnectionProvider *ipprotomcpr = static_cast<CIPProtoMetaConnectionProvider *>(provider);
+ if (ipprotomcpr->iIapLocked)
+ {
+ User::Leave(KErrPermissionDenied);
+ }
+
+ TSecureId sid;
+ ASubSessionPlatsecApiExt platsecext(iSelectionPrefs.SubSessionUniqueId());
+ if (platsecext.SecureId(sid) == KErrNone)
+ {
+ CCommsDatIapView* iapView = CCommsDatIapView::NewLC(aIapToFind);
+
+ TUint32 iapsid;
+ iapView->GetIntL(KCDTIdIAPAppSid, iapsid);
+
+ if (sid.iId == iapsid && iapsid != 0)
+ ipprotomcpr->iIapLocked = ETrue;
+ CleanupStack::PopAndDestroy(iapView);
+ }
+ }
+
+ if (providerCreated)
+ {
+ // New provider may have been created so remove from the cleanup here (after all the leaving methods)
+ // When maintaining/altering code be aware of keeping the cleanup stack balanced
+ CleanupStack::Pop(provider);
+ }
+
+ provider->IncrementBlockingDestroy();
+ return provider;
+ }
+
+
+//
+//TIpProtoProviderSelectorFactory::NewSelectorL - mapping prefs to a selector
+MProviderSelector* TIpProtoProviderSelectorFactory::NewSelectorL(const Meta::SMetaData& aSelectionPreferences)
+ {
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("TIpProtoProviderSelectorFactory::\tNewSelectorL()")));
+ ASSERT(aSelectionPreferences.IsTypeOf(TSelectionPrefs::TypeId()));
+ const ESock::TSelectionPrefs& sp = static_cast<const ESock::TSelectionPrefs&>(aSelectionPreferences);
+ ASimpleSelectorBase* self = NULL;
+ CBase* selfCleanupItem = NULL;
+
+ CMDBSession* dbs = CMDBSession::NewLC(KCDVersion1_2);
+
+
+ // Reveal hidden or private IAP records if a licensee has chosen to protect a record
+ // using one of these flags - the API to do this is public so internal components
+ // have to support the use of such records.
+ dbs->SetAttributeMask( ECDHidden | ECDPrivate );
+
+ TBool prefLegacy = !sp.IsEmpty() && sp.Prefs().ExtensionId()!=TConnPref::EConnPrefSnap && sp.Prefs().ExtensionId()!=TConnPref::EConnPrefIdList;
+
+ //Legacy selection (including legacy attach)
+ if (prefLegacy)
+ {
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("TIpProtoProviderSelectorFactory::\tNewSelectorL() - Legacy selector")));
+ CLinkPrefsSelector* selfLink = new (ELeave) CLinkPrefsSelector(aSelectionPreferences);
+ self = selfLink;
+ selfCleanupItem = selfLink;
+ }
+ else
+ //399 selection
+ {
+ __CFLOG_VAR((KIpProtoTierMgrTag, KIpProtoTierMgrSubTag, _L8("TIpProtoProviderSelectorFactory::\tNewSelectorL() - 399 selector")));
+ CIpProtoProviderSelector* selfIPProto = new (ELeave) CIpProtoProviderSelector(aSelectionPreferences);
+ self = selfIPProto;
+ selfCleanupItem = selfIPProto;
+ }
+
+ CleanupStack::PushL(selfCleanupItem);
+ ASSERT(self->iTierRecord==NULL);
+ self->iTierRecord = TierManagerUtils::LoadTierRecordL(TUid::Uid(CIPProtoTierManagerFactory::iUid),*dbs);
+ CleanupStack::Pop(selfCleanupItem);
+ CleanupStack::Pop(dbs);
+ ASSERT(self->iDbs==NULL);
+ self->iDbs = dbs;
+ return self;
+ }
+
+