diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/ssock/ss_metaconnprov.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/ssock/ss_metaconnprov.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,551 @@ +// Copyright (c) 2005-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: +// + +/** + @file +*/ + +#define SYMBIAN_NETWORKING_UPS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // CommsDat + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif + +#ifdef _DEBUG +// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module +// (if it could happen through user error then you should give it an explicit, documented, category + code) +_LIT(KSpecAssert_ESockSSocksmtcnp, "ESockSSocksmtcnp"); +#endif + +using namespace ESock; +using namespace CommsDat; +using namespace Messages; +using namespace Factories; + +// +//CConfigAccessPointConfig +EXPORT_START_ATTRIBUTE_TABLE_AND_FN(CConfigAccessPointConfig, CConfigAccessPointConfig::EUid, CConfigAccessPointConfig::ETypeId) +END_ATTRIBUTE_TABLE() + +EXPORT_C CConfigAccessPointConfig* CConfigAccessPointConfig::NewL() + { + return new(ELeave) CConfigAccessPointConfig(); + } + +EXPORT_C CConfigAccessPointConfig::~CConfigAccessPointConfig() + { + iLayers.Close(); + iSCprs.Close(); + } + +EXPORT_C void CConfigAccessPointConfig::AppendLayerL(const TConfigAccessPointLayer& aLayer) + { + for (TUint i = 0; i < iLayers.Count(); i++) + if (iLayers[i].Id() == aLayer.Id()) + return; + + iLayers.AppendL(aLayer); + } + +EXPORT_C TBool CConfigAccessPointConfig::LayerExists(const TConfigAccessPointLayer& aLayer) const + { + for (TUint i = 0; i < iLayers.Count(); i++) + if (iLayers[i].Id() == aLayer.Id()) + return ETrue; + + return EFalse; + } + +EXPORT_C void CConfigAccessPointConfig::GetTopLayersL(TUid aSCprUid, RPointerArray& aTopLayers) const + { + for (TUint i = 0; i < iLayers.Count(); i++) + { + if (iLayers[i].SCprUid() == aSCprUid && iLayers[i].TopLevel()) + aTopLayers.AppendL(&iLayers[i]); + } + } + +EXPORT_C const TConfigAccessPointLayer& CConfigAccessPointConfig::GetLayerL(TUint aId) const + { + for (TUint i = 0; i < iLayers.Count(); i++) + if (iLayers[i].Id() == aId) + return iLayers[i]; + + User::Leave(KErrNotFound); + + return iLayers[0]; // this will never be reached. + } + +EXPORT_C TUint CConfigAccessPointConfig::GetLayerCount() const + { + return iLayers.Count(); + } + +EXPORT_C void CConfigAccessPointConfig::AppendSCprL(const TUid& aUid) + { + if (iSCprs.Find(aUid) == KErrNotFound) + iSCprs.AppendL(aUid); + } + +EXPORT_C const RArray& CConfigAccessPointConfig::SCprs() const + { + return iSCprs; + } + +// +//CMetaConnectionProviderBase +EXPORT_C CMetaConnectionProviderBase::CMetaConnectionProviderBase(CMetaConnectionProviderFactoryBase& aFactory, + const TProviderInfo& aProviderInfo, + const MeshMachine::TNodeActivityMap& aActivityMap) +: CMMCommsProviderBase( aFactory,aActivityMap ), + iProviderInfo(aProviderInfo), + iBlockingDestroy(0) +/** +Constructor for CMetaConnectionProviderBase +@param aFactory Parent container for the provider +*/ + { + LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("CMetaConnectionProviderBase %08x:\tcreated [%d], factory Uid %08x"), + this, sizeof(CMetaConnectionProviderBase), Factory().Uid().iUid)); + } + +EXPORT_C CMetaConnectionProviderBase::~CMetaConnectionProviderBase() +/** +Destructor for CMetaConnectionProviderBase. +Once constructed, a meta-CPR should only be destroyed when absolutely not needed any more. It should be the last +thing to die and therefore doesn't need to tell anyone about it. +*/ + { + if (iTierManager) + { + iTierManager->RemoveMetaConnectionProvider(this); + } + + iAccessPointConfig.Close(); + } + +EXPORT_C const TProviderInfo& CMetaConnectionProviderBase::ProviderInfo() const +/** Get the connection information + +@return Const reference to a descriptor with the connection information */ + { + return iProviderInfo; + } + +EXPORT_C void CMetaConnectionProviderBase::SetProviderInfo(const TProviderInfo& aProviderInfo) + { + iProviderInfo = aProviderInfo; + } + +//This fn could be optimised +EXPORT_C void CMetaConnectionProviderBase::ConstructL() + { + CMMCommsProviderBase::ConstructL(); + + RMetaExtensionContainer mec; + mec.Open(); + CleanupClosePushL(mec); + + TProviderInfoExt* providerInfo = new TProviderInfoExt(iProviderInfo); + CleanupStack::PushL(providerInfo); + mec.AppendExtensionL(providerInfo); + CleanupStack::Pop(providerInfo); + + iAccessPointConfig.Close(); + iAccessPointConfig.Open(mec); + CleanupStack::PopAndDestroy(&mec); + + SetAccessPointConfigL(); + } + +EXPORT_C RNodeInterface* CMetaConnectionProviderBase::NewClientInterfaceL(const TClientType& aClientType, TAny* aClientInfo) + { + if (aClientType.Type() & TCFClientType::EServProvider) + { + //For all service providers, use the RMetaServiceProviderInterface (==RNodeAvailabilityProviderInterface) + __ASSERT_DEBUG(aClientInfo, User::Panic(KSpecAssert_ESockSSocksmtcnp, 1)); + const TProviderInfo* pi = static_cast(aClientInfo); + return new (ELeave) RMetaServiceProviderInterface(*pi); + } + else if (aClientType.Flags() & TCFClientType::EAvailabilityProvider) + { + //For all other types that use the EAvailabilityProvider flag use RNodeAvailabilityProviderInterface + return new (ELeave) RNodeAvailabilityProviderInterface(); + } + else if (aClientType.Type() & TCFClientType::EData) //Assume that data client can't be availability provider + { + TUint priority = KMaxTUint; + return new (ELeave) RCFNodePriorityInterface(priority); + } + else + { + return MeshMachine::AMMNodeBase::NewClientInterfaceL(aClientType, aClientInfo); + } + } + +EXPORT_C RMetaServiceProviderInterface* CMetaConnectionProviderBase::FindServiceProvider(TUint aAccessPoint) + { + __ASSERT_DEBUG(aAccessPoint, User::Panic(KSpecAssert_ESockSSocksmtcnp, 2)); //??? + + TClientIter iter = GetClientIter(TClientType(TCFClientType::EServProvider)); + RMetaServiceProviderInterface* serviceProvider; + while ((serviceProvider = static_cast(iter++)) != NULL) + { + TUint ap = serviceProvider->ProviderInfo().APId(); + if (ap == aAccessPoint) + { + return serviceProvider; + } + } + + return NULL; + } + +EXPORT_C void CMetaConnectionProviderBase::SetTierManagerL(CTierManagerBase* aTierManager) + { + //ASSERT(iTierManager==NULL); //This function should be called only once. + if (iTierManager!=aTierManager) + { + aTierManager->AddMetaConnectionProviderL(this); + // Save aTierMaanger pointer only after AddMetaConnectionProviderL. + // If it was not possible to add this MCPR to TM due to OOM, then we do not need TM pointer also. + iTierManager = aTierManager; + } + } + +void CMetaConnectionProviderBase::SetAccessPointConfigL() + { + LOG( ESockLog::Printf(KESockMetaConnectionTag, _L("CMetaConnectionProviderBase %08x:\tSetAccessPointConfigL() - loading access point record"), this) ); + + CMDBSession* dbs = CMDBSession::NewLC(KCDVersion1_2); + CCDAccessPointRecord* apRec = TierManagerUtils::LoadAccessPointRecordL(iProviderInfo.APId(1/*dummy for the overload*/),*dbs); + + CleanupStack::PushL(apRec); + + LOG( ESockLog::Printf(KESockMetaConnectionTag, _L("\t\t\tTier=%d Mcpr=%d SelPol=%d Cpr=%d CprCfg=%d Scpr=%d Proto=%d AppSID=%d Priority=%d"), + static_cast(apRec->iTier), + static_cast(apRec->iMCpr), + static_cast(apRec->iSelectionPolicy), + static_cast(apRec->iCpr), + static_cast(apRec->iCprConfig), + static_cast(apRec->iSCpr), + static_cast(apRec->iProtocol), + static_cast(apRec->iAppSID), + static_cast(apRec->iPriority) ) ); + CCDTierRecord* tierRec = TierManagerUtils::LoadTierRecordL(apRec->iTier,*dbs); + TInt tempTierId = tierRec->iRecordTag; + delete tierRec; + tierRec = NULL; + + TUid tierId = TUid::Uid(tempTierId); + + User::LeaveIfError((tierId==iProviderInfo.TierId())? KErrNone : KErrArgument); + + TUint selectionPolicy = apRec->iSelectionPolicy; + TUint cprConfig = apRec->iCprConfig; + TUint apPriority = (apRec->iPriority.IsNull()) ? KMaxTUint : (TUint)apRec->iPriority; + if(apPriority == 0) + { + LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("Error: Invalid priority value (%d) stored in access point record."),apPriority)); + User::Leave(KErrArgument); + } + + CCDMCprRecord* mcprRec = TierManagerUtils::LoadMCprRecordL(apRec->iMCpr,*dbs); + TUint mCprUid = mcprRec->iMCprUid; + delete mcprRec; + mcprRec = NULL; + + CCDCprRecord* cprRec = TierManagerUtils::LoadCprRecordL(apRec->iCpr,*dbs); + TUint cprUid = cprRec->iCprUid; + delete cprRec; + cprRec = NULL; + + CCDSCprRecord* scprRec = TierManagerUtils::LoadSCprRecordL(apRec->iSCpr,*dbs); + TUint sCprUid = scprRec->iSCprUid; + delete scprRec; + scprRec = NULL; + + CCDProtocolRecord* prtRec = TierManagerUtils::LoadProtocolRecordL(apRec->iProtocol,*dbs); + TUint protocolUid = prtRec->iProtocolUid; + delete prtRec; + prtRec = NULL; + + TUint customSelectionPolicy = TierManagerUtils::ReadCustomSelectionPolicyIdL(iProviderInfo.APId(),*dbs); + TUint appSid = apRec->iAppSID; + + + RMetaExtensionContainer mec; + mec.Open(iAccessPointConfig); + CleanupClosePushL(mec); + + const TDesC& configAPIdList = apRec->iConfigAPIdList; + if (configAPIdList.Length() > 0) + { + RArray tlids; + CleanupClosePushL(tlids); + + CConfigAccessPointConfig *capext = CConfigAccessPointConfig::NewL(); + + CleanupStack::PushL(capext); + mec.AppendExtensionL(capext); + CleanupStack::Pop(capext); + + TierManagerUtils::ParseTLConfigAccessPointIdsL(tlids, apRec->iConfigAPIdList); + + for (TUint i = 0; i < tlids.Count(); i++) + { + /** + Load the top level CAP record from the database, + and save it to the provisioning structure + */ + CCDConfigAccessPointRecord* caprec = TierManagerUtils::LoadConfigAccessPointRecordL(tlids[i], *dbs); + CleanupStack::PushL(caprec); + + CCDSCprRecord* scprRec = TierManagerUtils::LoadSCprRecordL(caprec->iSCpr,*dbs); + TUint capSCprUid = scprRec->iSCprUid; + delete scprRec; + scprRec = NULL; + + CCDProtocolRecord* prtRec = TierManagerUtils::LoadProtocolRecordL(caprec->iProtocol,*dbs); + TUint capProtocolUid = prtRec->iProtocolUid; + TUint capProtocolConfigLoaderUid = prtRec->iProtocolConfigLoaderUid; + delete prtRec; + prtRec = NULL; + + /** + Record SCpr to be started. Needed by Cpr + */ + TUid scprUid = TUid::Uid(capSCprUid); + capext->AppendSCprL(scprUid); + + TConfigAccessPointLayer topLayer(caprec->iRecordTag, TUid::Uid(capSCprUid), + TUid::Uid(capProtocolUid), caprec->iLayerBelow, ETrue); + if(!capext->LayerExists(topLayer)) + { + capext->AppendLayerL(topLayer); + + /** + Load configuration for each protocol using ecom plugin. + */ + if (capProtocolConfigLoaderUid) + { + CProtocolConfigLoader *cfgldr = CProtocolConfigLoader::NewL(dbs, TUid::Uid(capProtocolConfigLoaderUid)); + CleanupStack::PushL(cfgldr); + cfgldr->LoadConfigL(mec, TUid::Uid(capProtocolUid), caprec->iProtocolConfig); + CleanupStack::PopAndDestroy(cfgldr); + } + } + + TUint layerbelow = caprec->iLayerBelow; + CleanupStack::PopAndDestroy(caprec); + caprec = NULL; + + /** + Now load the info for each of it's lower layers. + */ + while (layerbelow != 0) + { + /* Load next layer from the database */ + CCDConfigAccessPointRecord* caprec = TierManagerUtils::LoadConfigAccessPointRecordL(layerbelow, *dbs); + CleanupStack::PushL(caprec); + + CCDProtocolRecord* prtRec = TierManagerUtils::LoadProtocolRecordL(caprec->iProtocol,*dbs); + capProtocolUid = prtRec->iProtocolUid; + capProtocolConfigLoaderUid = prtRec->iProtocolConfigLoaderUid; + delete prtRec; + prtRec = NULL; + + TConfigAccessPointLayer layer(caprec->iRecordTag, TUid::Uid(capSCprUid), + TUid::Uid(capProtocolUid), caprec->iLayerBelow); + + if(!capext->LayerExists(layer)) + { + capext->AppendLayerL(layer); + + if (capProtocolConfigLoaderUid) + { + CProtocolConfigLoader *cfgldr + = CProtocolConfigLoader::NewL(dbs, TUid::Uid(capProtocolConfigLoaderUid)); + CleanupStack::PushL(cfgldr); + TUid capuid = TUid::Uid(capProtocolUid); + cfgldr->LoadConfigL(mec, capuid, caprec->iProtocolConfig); + + CleanupStack::PopAndDestroy(cfgldr); + } + } + + layerbelow = caprec->iLayerBelow; + CleanupStack::PopAndDestroy(caprec); + } + } + + CleanupStack::PopAndDestroy(&tlids); + } + + + TLayerConfig* layerConfig = new(ELeave)TLayerConfig(TUid::Uid(mCprUid), TUid::Uid(cprUid), + TUid::Uid(sCprUid), TUid::Uid(protocolUid), tierId); + CleanupStack::PushL(layerConfig); + mec.AppendExtensionL(layerConfig); + CleanupStack::Pop(layerConfig); + + TLayerSelectionInfo* layerSelectInfo = new(ELeave)TLayerSelectionInfo(selectionPolicy, cprConfig, customSelectionPolicy); + CleanupStack::PushL(layerSelectInfo); + mec.AppendExtensionL(layerSelectInfo); + CleanupStack::Pop(layerSelectInfo); + + TAppSidConfig* appSidConfig = new(ELeave)TAppSidConfig(appSid); + CleanupStack::PushL(appSidConfig); + mec.AppendExtensionL(appSidConfig); + CleanupStack::Pop(appSidConfig); + + TAccessPointPriority* apPriorityExt = new(ELeave)TAccessPointPriority; + CleanupStack::PushL(apPriorityExt); + apPriorityExt->SetPriority(apPriority); + mec.AppendExtensionL(apPriorityExt); + CleanupStack::Pop(apPriorityExt); + + iAccessPointConfig.Close(); + iAccessPointConfig.Open(mec); + CleanupStack::PopAndDestroy(&mec); + + +#ifdef SYMBIAN_NETWORKING_UPS + ShowAccessPointRecordL(dbs, apRec); +#endif + + CleanupStack::PopAndDestroy(apRec); + CleanupStack::PopAndDestroy(dbs); + + LOG( ESockLog::Printf(KESockMetaConnectionTag, _L("\t\t\tTierId=%08x McprUid=%08x CprUid=%08x ScprUid=%08x ProtoUid=%08x"), + tierId.iUid, + layerConfig->MCprUid(), + layerConfig->CprUid(), + layerConfig->SCprUid(), + layerConfig->ProtocolUid() + ) ); + } + + +#ifdef SYMBIAN_NETWORKING_UPS + +EXPORT_C void CMetaConnectionProviderBase::ShowAccessPointRecordL(CommsDat::CMDBSession* /*aSession*/, CommsDat::CCDAccessPointRecord* /*aApRec*/) +/** +Allow derived classes to read fields from the Access Point Record whilst we already have it open. +*/ + { + } + +#endif + + +// +//Factories - Container +CMetaConnectionFactoryContainer* CMetaConnectionFactoryContainer::NewL() +/** Create a new instance of a meta connection factory container +@exception Leaves in out of memory conditions +@return Pointer to new instance of a meta connection factory container +*/ + { + CMetaConnectionFactoryContainer* container = new (ELeave) CMetaConnectionFactoryContainer; + return container; + } + + +CMetaConnectionProviderFactoryBase* CMetaConnectionFactoryContainer::Factory(TInt aIndex) const + { + return static_cast(CCommsFactoryContainer::Factory(aIndex)); + } + +CMetaConnectionFactoryContainer::~CMetaConnectionFactoryContainer() +/** Empty meta connection factory container destructor */ + { + LOG_NODE_DESTROY(KESockMetaConnectionTag, CMetaConnectionFactoryContainer); + } + +CMetaConnectionFactoryContainer::CMetaConnectionFactoryContainer() +:CCommsFactoryContainer((CCommsFactoryContainer::TContaineeType)CMetaConnectionFactoryContainer::EId) +/** Empty meta connection factory container constructor */ + { + LOG_NODE_CREATE(KESockMetaConnectionTag, CMetaConnectionFactoryContainer); + } + +void CMetaConnectionFactoryContainer::ReceivedL(const TRuntimeCtxId& /*aSender*/, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage) + { + (void)aMessage; + + NM_LOG_START_BLOCK(KESockMetaConnectionTag, _L8("CMetaConnectionFactoryContainer:ReceivedL")); + NM_LOG((KESockMetaConnectionTag, _L8("ERROR: KErrNotSupported [this=0x%08x]"), this)); + NM_LOG_MESSAGE(KESockMetaConnectionTag, aMessage); + NM_LOG_END_BLOCK(KESockMetaConnectionTag, _L8("CMetaConnectionFactoryContainer:ReceivedL")); + + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksmtcnp, 3)); //For debug configurations + User::Leave(KErrNotSupported); //For release configurations + } + +// +//Factories +EXPORT_C CMetaConnectionProviderFactoryBase::CMetaConnectionProviderFactoryBase(TUid aFactoryId, CMetaConnectionFactoryContainer& aParentContainer) +/** Meta connection provider factory constructor +@param aFactoryId Unique Integer Identifier of the meta connection provider factory +@param aParentContainer Container to add the factory to */ + : CCommsFactoryBase(aFactoryId, aParentContainer) + { + LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("CMetaConnectionProviderFactoryBase %08x:\tCMetaConnectionProviderFactoryBase(%08x)"), this, aFactoryId)); + } + +EXPORT_C CMetaConnectionProviderFactoryBase::~CMetaConnectionProviderFactoryBase() +/** Empty meta connection factory base destructor */ + { + LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("CMetaConnectionProviderFactoryBase %08x:\t~CMetaConnectionProviderFactoryBase()"), this)); + } + +EXPORT_C ACommsFactoryNodeId* CMetaConnectionProviderFactoryBase::DoCreateObjectL(TFactoryQueryBase& /* aQuery */) + { + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksmtcnp, 4)); + User::Leave(KErrNotSupported); + return NULL; + } + +EXPORT_C void CMetaConnectionProviderFactoryBase::DoPostCreationL(ACommsFactoryNodeId* aObject,TFactoryQueryBase& aQuery) + { //setting tiermanger to MCPR + CMetaConnectionProviderBase* provider = static_cast(aObject); + TMetaConnectionFactoryQuery tempQuery= static_cast(aQuery); + CTierManagerFactoryBase* factory = static_cast((*SockManGlobals::Get()->iTierManagerFactories).FindOrCreateFactoryL(tempQuery.iTierImplUid)); + + if (factory) + { + TAlwaysFindFactoryQuery query; + CTierManagerBase* tierManager = static_cast(factory->Find(query)); + if (tierManager) + provider->SetTierManagerL(tierManager); + } + + } + +