diff -r 000000000000 -r 3553901f7fa8 telephonyprotocols/pdplayer/src/pdptiermanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyprotocols/pdplayer/src/pdptiermanager.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,536 @@ +// Copyright (c) 2008-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 + @internalComponent +*/ + +#include "pdptiermanager.h" +#include "mbmsengine.h" +#include "pdptiermanagerselector.h" +#include +#include +#include +#include + +#include "pdpmcpr.h" + +#ifdef SYMBIAN_TRACE_ENABLE +#define KPDPTierMgrTag KESockMetaConnectionTag +_LIT8(KPDPTierMgrSubTag, "pdptiermgr"); +#endif + +using namespace Messages; +using namespace MeshMachine; +using namespace ESock; +using namespace ConnectionServ; +using namespace NetStateMachine; +using namespace CommsDat; + +namespace PDPTierManagerActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(stateMap) +ACTIVITY_MAP_END_BASE(TMActivities, coreTMActivities) +} + + +CContextTypeChecker::CContextTypeChecker(RPacketService& aPacketService, MContextEventsObserver& aCallback):CActive(EPriorityStandard), + iPacketService(aPacketService), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CContextTypeChecker::~CContextTypeChecker() + { + iContextName = NULL; + } + +void CContextTypeChecker::Start(const TName* aContextName) + { + iContextName = aContextName; + iPacketService.EnumerateContextsInNif(iStatus, *iContextName, iCountInNif); + SetActive(); + } + +void CContextTypeChecker::RunL() + { + User::LeaveIfError(iStatus.Int()); + if (iCountInNif == 1) // This is a primary context + { + iCallback.PrimaryContextAddedL(iContextName); + } + else + { + iCallback.SecondaryContextAdded(iContextName); + } + } + +void CContextTypeChecker::DoCancel() + { + iPacketService.CancelAsyncRequest(EPacketEnumerateContextsInNif); + } + +TInt CContextTypeChecker::RunError(TInt aError) + { + // Report an error + iCallback.ContextTypeCheckingError(iContextName, aError); + return KErrNone; // Make ActiveScheduler happy + } + +CPrimaryContextsMonitor::CPrimaryContextsMonitor(RPacketService& aPacketService, MContentionObserver& aCallback) : CActive(EPriorityStandard), + iPacketService(aPacketService), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CPrimaryContextsMonitor::~CPrimaryContextsMonitor() + { + Cancel(); + iContextMonitors.ResetAndDestroy(); + delete iContextTypeChecker; + iAddedContextsNames.ResetAndDestroy(); + } + +void CPrimaryContextsMonitor::StartL() + { + iContextTypeChecker = new(ELeave) CContextTypeChecker(iPacketService, *this); + iState = EEnumeratingContexts; + iPacketService.EnumerateNifs(iStatus, iInitialNifsCount); + SetActive(); + } + +void CPrimaryContextsMonitor::PrimaryContextAddedL(const TName* aContextName) + { + // Create new status monitor for this context + StartContextStatusMonitoringL(*aContextName); + RemoveContextNameAndCheckNext(aContextName); + } + +void CPrimaryContextsMonitor::SecondaryContextAdded(const TName* aContextName) + { + // This is not a primary context, just delete its name. + RemoveContextNameAndCheckNext(aContextName); + } + +void CPrimaryContextsMonitor::RemoveContextNameAndCheckNext(const TName* aContextName) + { + TInt nameIndex = iAddedContextsNames.Find(aContextName); + __ASSERT_DEBUG(nameIndex != KErrNotFound, User::Invariant()); + delete iAddedContextsNames[nameIndex]; + iAddedContextsNames.Remove(nameIndex); + + if (iAddedContextsNames.Count() > 1) + // Should be more than one here, coz we are waiting for new context added all the time, + // so the last one item is always empty. + { + iContextTypeChecker->Start(iAddedContextsNames[0]); + } + } + +void CPrimaryContextsMonitor::PrimaryContextDeleted(const CContextStatusMonitor* aContextStatusMonitor) + { + if (aContextStatusMonitor->IsPassedThroughActiveState()) + { + iCallback.ContentionResolved(); + } + DeleteContextStatusMonitor(aContextStatusMonitor); + } + +void CPrimaryContextsMonitor::ContextTypeCheckingError(const TName* aContextName, TInt aError) + { + RemoveContextNameAndCheckNext(aContextName); + ProcessError(aError); + } + + +void CPrimaryContextsMonitor::ContextMonitoringError(const CContextStatusMonitor* aContextStatusMonitor, TInt aError) + { + DeleteContextStatusMonitor(aContextStatusMonitor); + ProcessError(aError); + } + +void CPrimaryContextsMonitor::DeleteContextStatusMonitor(const CContextStatusMonitor* aContextStatusMonitor) + { + TInt monitorIndex = iContextMonitors.Find(aContextStatusMonitor); + __ASSERT_DEBUG(monitorIndex != KErrNotFound, User::Invariant()); + delete iContextMonitors[monitorIndex]; + iContextMonitors.Remove(monitorIndex); + } + +void CPrimaryContextsMonitor::ProcessError( + #ifdef _DEBUG + TInt aError + #else //remove compilation warning in release builds + TInt /*aError*/ + #endif + ) + { + __ASSERT_DEBUG(aError != KErrNone, User::Invariant()); + __FLOG_STATIC1(KPDPTierMgrTag, KPDPTierMgrSubTag, _L("PDP context monitoring error: %d"), aError); + } + +void CPrimaryContextsMonitor::RunL() + { + User::LeaveIfError(iStatus.Int()); + SwitchStateL(); + RPacketService::TNifInfoV2Pckg nifInfoV2Pckg(iCurrentNifInfo); + switch(iState) + { + case EGettingInfo: + StartContextStatusMonitoringL(iCurrentNifInfo.iContextName); + iPacketService.GetNifInfo(iStatus, iCurrentNifIndex, nifInfoV2Pckg); + ++iCurrentNifIndex; + SetActive(); + break; + case EListening: + // All functions in RPacketService and RPacketContext, + // that can be used to check if context is primary, are asynchronous. + // We could not call them here, coz can miss some events from NotifyContextAdded + // So subscribe to NotifyContextAdded as soon as possible and check context + // type using CContextTypeChecker active object + TName *contextName = new (ELeave) TName; + CleanupStack::PushL(contextName); + iAddedContextsNames.AppendL(contextName); + CleanupStack::Pop(contextName); + // subscribe to NotifyContextAdded + iPacketService.NotifyContextAdded(iStatus, *contextName); + SetActive(); + // if there are any items in iAddedContextsNames except that one that has been added above, i.e count > 1 + // starting asynchronous context type checking + if (!iContextTypeChecker->IsActive() && iAddedContextsNames.Count()>1) + { + iContextTypeChecker->Start(iAddedContextsNames[0]); + } + break; + } + } +void CPrimaryContextsMonitor::DoCancel() + { + switch(iState) + { + case EEnumeratingContexts: + iPacketService.CancelAsyncRequest(EPacketEnumerateNifs); + break; + case EGettingInfo: + iPacketService.CancelAsyncRequest(EPacketGetNifInfo); + break; + case EListening: + iPacketService.CancelAsyncRequest(EPacketNotifyContextAdded); + break; + } + + } + +TInt CPrimaryContextsMonitor::RunError(TInt aError) + { + // Process an error + ProcessError(aError); + return KErrNone; // Make ActiveScheduler happy + } + + +void CPrimaryContextsMonitor::SwitchStateL() + { + if (iState == EEnumeratingContexts) + { + if (iInitialNifsCount > 0) + { + iState = EGettingInfo; + } + else + { + iState = EListening; + } + } + else if (iState == EGettingInfo && iCurrentNifIndex == iInitialNifsCount) + { + StartContextStatusMonitoringL(iCurrentNifInfo.iContextName); + iState = EListening; + } + } + +void CPrimaryContextsMonitor::StartContextStatusMonitoringL(const TName& aContextName) + { + CContextStatusMonitor* newStatusMonitor = new (ELeave) CContextStatusMonitor(iPacketService, *this); + CleanupStack::PushL(newStatusMonitor); + iContextMonitors.AppendL(newStatusMonitor); + CleanupStack::Pop(newStatusMonitor); + newStatusMonitor->StartL(aContextName); + } + +CContextStatusMonitor::CContextStatusMonitor(RPacketService& aPacketService, MContextEventsObserver& aCallback):CActive(EPriorityStandard), + iPacketService(aPacketService), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CContextStatusMonitor::~CContextStatusMonitor() + { + Cancel(); + iPacketContext.Close(); + } + +TBool CContextStatusMonitor::StartL(const TName& aContextName) + { + iContextName.Copy(aContextName); + User::LeaveIfError(iPacketContext.OpenExistingContext(iPacketService, iContextName)); + iPacketContext.GetStatus(iContextStatus); + + if (iContextStatus == RPacketContext::EStatusDeleted) + { + return EFalse; + } + + if (iContextStatus == RPacketContext::EStatusActive || + iContextStatus == RPacketContext::EStatusSuspended || + iContextStatus == RPacketContext::EStatusDeactivating) + { + iWasActive = ETrue; + } + + iPacketContext.NotifyStatusChange(iStatus, iContextStatus); + SetActive(); + return ETrue; + } + +void CContextStatusMonitor::RunL() + { + User::LeaveIfError(iStatus.Int()); + if (iContextStatus == RPacketContext::EStatusActive) + { + iWasActive = ETrue; + } + + if (iContextStatus == RPacketContext::EStatusDeleted) + { + iPacketContext.CancelAsyncRequest(EPacketContextNotifyStatusChange); + iCallback.PrimaryContextDeleted(this); + } + else + { + iPacketContext.NotifyStatusChange(iStatus, iContextStatus); + SetActive(); + } + } + +void CContextStatusMonitor::DoCancel() + { + iPacketContext.CancelAsyncRequest(EPacketContextNotifyStatusChange); + } + +TInt CContextStatusMonitor::RunError(TInt aError) + { + iCallback.ContextMonitoringError(this, aError); + return KErrNone; + } + +CPdpContentionManager* CPdpContentionManager::NewL(const ESock::CTierManagerBase& aTierManager, RPacketService& aPacketService) + { + CPdpContentionManager* self = new (ELeave) CPdpContentionManager(aTierManager); + CleanupStack::PushL(self); + self->ConstructL(aPacketService); + CleanupStack::Pop(self); + return self; + } + +CPdpContentionManager::CPdpContentionManager(const ESock::CTierManagerBase& aTierManager): +CContentionManager(aTierManager) + { + } + +CPdpContentionManager::~CPdpContentionManager() + { + delete iPrimaryContextsMonitor; + } + +void CPdpContentionManager::ConstructL(RPacketService& aPacketService) + { + iPrimaryContextsMonitor = new (ELeave) CPrimaryContextsMonitor(aPacketService, *this); + } + +void CPdpContentionManager::StartMonitoringL() + { + if (iPrimaryContextsMonitor) + { + iPrimaryContextsMonitor->StartL(); + } + } + +void CPdpContentionManager::ContentionResolved(const TContentionRequestItem& aContentionRequest, TBool aResult) + { + CPdpMetaConnectionProvider* pdpMcpr = static_cast(aContentionRequest.iMcpr); + + pdpMcpr->ContentionResolved(aContentionRequest.iPendingCprId, aResult); + } + +void CPdpContentionManager::ContentionOccured(ESock::CMetaConnectionProviderBase& aMcpr) + { + CPdpMetaConnectionProvider& pdpMcpr = static_cast(aMcpr); + + pdpMcpr.ContentionOccured(); + } + +void CPdpContentionManager::ReportContentionAvailabilityStatus(ESock::CMetaConnectionProviderBase& aMcpr, const ESock::TAvailabilityStatus& aStatus) const + { + CPdpMetaConnectionProvider& pdpMcpr = static_cast(aMcpr); + + pdpMcpr.ReportContentionAvailabilityStatus(aStatus); + } + +/** +The NewL factory function for PDPTierManager. +This function also acts as the single ECom entry point into this object. +@param aFactory The reference to CTierManagerFactoryBase +@return CPDPTierManager* +*/ +CPDPTierManager* CPDPTierManager::NewL(ESock::CTierManagerFactoryBase& aFactory) + { + CPDPTierManager* self = new(ELeave)CPDPTierManager(aFactory, PDPTierManagerActivities::stateMap::Self()); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +/** +Constructor for CPDPTierManager +*/ +CPDPTierManager::CPDPTierManager(ESock::CTierManagerFactoryBase& aFactory, + const MeshMachine::TNodeActivityMap& aActivityMap) + :CCoreTierManager(aFactory,aActivityMap) + { + LOG_NODE_CREATE(KPDPTierMgrTag, CPDPTierManager); + } + +/** +Descructor for CPDPTierManager +*/ +CPDPTierManager::~CPDPTierManager() + { + LOG_NODE_DESTROY(KPDPTierMgrTag, CPDPTierManager); + delete iPdpContentionManager; + iPdpContentionManager = NULL; + if (iMBMSEngine) + { + iMBMSEngine->Cancel(); + delete iMBMSEngine; + iMBMSEngine = NULL; + } + } + +/** +Create selector for this Tier. +@return MProviderSelector* +*/ +MProviderSelector* CPDPTierManager::DoCreateProviderSelectorL(const Meta::SMetaData& aSelectionPreferences) + { + __CFLOG_VAR((KPDPTierMgrTag, KPDPTierMgrSubTag, _L8("CPdpTierManager[%08x]::DoSelectProvider()"), this)); + return TPdpSelectorFactory::NewSelectorL(aSelectionPreferences); + } + +/** +ConstructL function of CPDPTierManager. +This function is used to retrieve tsy name. +@return void +*/ +void CPDPTierManager::ConstructL() + { + __CFLOG_VAR((KPDPTierMgrTag, KPDPTierMgrSubTag, _L8("ConstructL::In CPDPTierManager"))); + iMBMSEngine = CMBMSEngine::NewL(NodeId(), *this); + } + +/** + The PacketServiceAttachedCallbackL is a callback function. + It's called by MBMSEngine when RPacketService has been attached. +*/ +void CPDPTierManager::PacketServiceAttachedCallbackL() + { + if (!iPdpContentionManager) + { + iPdpContentionManager = CPdpContentionManager::NewL(*this, iMBMSEngine->GetRPacketService()); + } + static_cast(iPdpContentionManager)->StartMonitoringL(); + } + +/** +The ReceivedL function for PDPTierManager. +The messages from RConnectionServ are received in ReceivedL function. +@param aCFMessage The reference to Messages::TSignatureBase +@return TInt* +*/ +void CPDPTierManager::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) + { + //TODO I think that the generic TCancel handling will do this - so perhaps remove this and CancelAndRemoveFromRequestList! + if (aMessage.IsMessage()) + { + TRAPD(err, iMBMSEngine->CancelAndRemoveFromRequestListL(aSender)); + if (err == KErrNone) + { + aMessage.ClearMessageId(); + } + else if (err != KErrNotFound) + { + User::Leave(err); + } + // err == KErrNotFound + // Probably this is not cancel for MBMS request but cancel for PDP availability notification request + // It will be processed by core TM then. + } + + if (aMessage.IsMessage()) + { + TCFTierStatusProvider::TTierNotificationRegistration* msgTNR = message_cast(&aMessage); + + const Messages::TNodeSignal::TMessageId requestType = TCFTierStatusProvider::TTierNotificationRegistration::Id(); + CRefCountOwnedParameterBundle* requestBundleOwner = msgTNR->iBundle; + + TRAPD(err, iMBMSEngine->AddToRequestListL(FindClient(aSender), aSender, requestType, requestBundleOwner)); + if (err == KErrNone) + { + aMessage.ClearMessageId(); + } + else if (err != KErrArgument) + { + User::Leave(err); + } + // err == KErrArgument + // Probably this is not MBMS notification request but PDP availability notification request + // It will be processed by core TM then. + } + + TNodeContext ctx(*this, aMessage, aSender, aRecipient); + CCoreTierManager::Received(ctx); + User::LeaveIfError(ctx.iReturn); + } + +TBool CPDPTierManager::HandleContentionL(ESock::CMetaConnectionProviderBase* aMcpr, Messages::TNodeId& aPendingCprId, TUint aPriority) + { + User::LeaveIfNull(iMBMSEngine); + if (!iPdpContentionManager) + { + iPdpContentionManager = CPdpContentionManager::NewL(*this, iMBMSEngine->GetRPacketService()); + } + return iPdpContentionManager->HandleContentionL(aMcpr, aPendingCprId, aPriority); + } + +TBool CPDPTierManager::IsUnavailableDueToContention(const ESock::CMetaConnectionProviderBase* aMetaConnectionProvider) const + { + if (!iPdpContentionManager) + return EFalse; + return iPdpContentionManager->IsUnavailableDueToContention(aMetaConnectionProvider); + } + +