--- /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 <comms-infras/ss_log.h>
+#include <comms-infras/coretiermanagerstates.h>
+#include <comms-infras/coretiermanageractivities.h>
+#include <pcktcs.h>
+
+#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<CPdpMetaConnectionProvider*>(aContentionRequest.iMcpr);
+
+ pdpMcpr->ContentionResolved(aContentionRequest.iPendingCprId, aResult);
+ }
+
+void CPdpContentionManager::ContentionOccured(ESock::CMetaConnectionProviderBase& aMcpr)
+ {
+ CPdpMetaConnectionProvider& pdpMcpr = static_cast<CPdpMetaConnectionProvider&>(aMcpr);
+
+ pdpMcpr.ContentionOccured();
+ }
+
+void CPdpContentionManager::ReportContentionAvailabilityStatus(ESock::CMetaConnectionProviderBase& aMcpr, const ESock::TAvailabilityStatus& aStatus) const
+ {
+ CPdpMetaConnectionProvider& pdpMcpr = static_cast<CPdpMetaConnectionProvider&>(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<CPdpContentionManager*>(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<TEBase::TCancel>())
+ {
+ 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>())
+ {
+ TCFTierStatusProvider::TTierNotificationRegistration* msgTNR = message_cast<TCFTierStatusProvider::TTierNotificationRegistration>(&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<CPDPTierManager> 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);
+ }
+
+