diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCacheItem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCacheItem.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,1312 @@ +// 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: +// Name : sipprofilecacheitem.cpp +// Part of : SIP Profile Server +// implementation +// Version : 1.0 +// + + + +// INCLUDE FILES +#include "SipProfileCacheItem.h" +#include "SipProfileServerCore.h" +#include "sipextendedconcreteprofileobserver.h" +#include "SipProfileState.h" +#include "SipProfileLog.h" +#include "sipalrmigrationcontroller.h" +#include +#include +#include + +const TInt KSnapRetryCountThreshold = 3; +const TUint32 KDefaultSNAPIdentifier = KMaxTUint32; +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::NewL +// ----------------------------------------------------------------------------- +// +CSIPProfileCacheItem* +CSIPProfileCacheItem::NewL(CSIPProfileServerCore& aCore, + CSIPProfileState* aUnregistered) + { + CSIPProfileCacheItem* self = + CSIPProfileCacheItem::NewLC(aCore, aUnregistered); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::NewLC +// ----------------------------------------------------------------------------- +// +CSIPProfileCacheItem* +CSIPProfileCacheItem::NewLC(CSIPProfileServerCore& aCore, + CSIPProfileState* aUnregistered) + { + CSIPProfileCacheItem* self = + new (ELeave) CSIPProfileCacheItem(aCore, aUnregistered); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::CSIPProfileCacheItem +// ----------------------------------------------------------------------------- +// +CSIPProfileCacheItem::CSIPProfileCacheItem(CSIPProfileServerCore& aCore, + CSIPProfileState* aUnregistered) : + iCacheState(ENormal), + iCurrentState(aUnregistered), + iServerCore(aCore), + iMigrationDisallowed(EFalse), + iDeltaTimer(0), + iDeltaTimerCallBack(DoNewIapFailed, this), + iSnapRetryCounter(0) +#ifdef CPPUNIT_TEST + // Use array granularity 1, so each append allocates memory + , iObservers(1), + iUsers(1), + iObserversWaitedForPermission(1) +#endif + { + iIsRfsInprogress = EFalse; + iDeltaTimerEntry.Set(iDeltaTimerCallBack); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ConstructL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ConstructL() + { + iDeltaTimer = CDeltaTimer::NewL(CActive::EPriorityLow); + } + + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::~CSIPProfileCacheItem +// ----------------------------------------------------------------------------- +// +CSIPProfileCacheItem::~CSIPProfileCacheItem() + { + if (iDeltaTimer) + { + iDeltaTimer->Cancel(); + } + delete iDeltaTimer; + + StopSnapMonitoring(); + + iObservers.Reset(); + iObserversWaitedForPermission.Reset(); + iUsers.Reset(); + delete iQueuedProfile; + delete iProfile; + delete iOldProfile; + delete iProfileWithNewIAP; + delete iProfileWithOldIAP; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IapAvailable +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::IapAvailable(TUint32 aSnapId, TUint32 aNewIapId) + { + iDeltaTimer->Cancel(); + + TRAPD(err, iCurrentState->IapAvailableL(*this, aSnapId, aNewIapId)); + if (err != KErrNone) + { + iServerCore.HandleProfileError(*this, err); + } + } +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::MigrationIsAllowedL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::MigrationIsAllowedL(TUint32 aIapId) + { + iCurrentState->MigrationIsAllowedL(*this, aIapId); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::MigrationIsDisallowedL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::MigrationIsDisallowedL(TUint32 aIapId) + { + iCurrentState->MigrationIsDisallowedL(*this, aIapId); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ErrorOccurred +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ErrorOccurred(TInt aError) + { + HandleError(aError); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::NoNewIapAvailable +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::NoNewIapAvailable() + { + iCurrentState->NoNewIapAvailable(*this); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RefreshIAPsFailed +// This is a fatal error, as profile no longer gets information of new IAPs. +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RefreshIAPsFailed() + { + iProfile->SetLastRegistrationError(KErrNoMemory); + iCurrentState->RefreshIAPsFailed(*this); + SwitchToUnregisteredState(); + PassAlrErrorToClient(KErrNoMemory, Profile().IapId()); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SetProfile +// Set iProfileId only once, then it never changes. +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SetProfile(CSIPConcreteProfile* aProfile) + { + __ASSERT_ALWAYS(aProfile, User::Panic(_L("ProfileCacheItem:SetProfile"), + KErrArgument)); + delete iProfile; + iProfile = aProfile; + + if (iProfileId == 0) + { + iProfileId = iProfile->Id(); + } + + CheckProfileEnabledState(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SetProfileId +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SetProfileId(TUint aProfileId) + { + iProfileId = aProfileId; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ProfileId +// ----------------------------------------------------------------------------- +// +TUint CSIPProfileCacheItem::ProfileId() const + { + return iProfileId; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::Profile +// Return the CSIPConcreteProfile that is most recently registered. +// ----------------------------------------------------------------------------- +// +CSIPConcreteProfile& CSIPProfileCacheItem::Profile() + { + __ASSERT_ALWAYS(iProfile, + User::Panic(_L("ProfileCacheItem:Profile"), KErrNotFound)); + return *iProfile; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::Profile +// ----------------------------------------------------------------------------- +// +const CSIPConcreteProfile& CSIPProfileCacheItem::Profile() const + { + __ASSERT_ALWAYS(iProfile, + User::Panic(_L("ProfileCacheItem:ProfileC"), KErrNotFound)); + return *iProfile; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::LatestProfile +// Return the CSIPConcreteProfile that includes the most recent updates. +// ----------------------------------------------------------------------------- +// +CSIPConcreteProfile& CSIPProfileCacheItem::LatestProfile() + { + return iQueuedProfile ? *iQueuedProfile : Profile(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ReferenceCount +// ----------------------------------------------------------------------------- +// +TUint CSIPProfileCacheItem::ReferenceCount() const + { + return iUsers.Count(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::CacheOldProfile +// If update is done before a previous update completed, it contains also the +// earlier update's changes. Some states queue the update. If a new update +// comes, it is stored and the previous discarded. +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::CacheOldProfile(CSIPConcreteProfile* aNewProfile, + const MSIPExtendedConcreteProfileObserver& aObserver) + { + __ASSERT_ALWAYS(aNewProfile && aNewProfile->Id() == ProfileId(), + User::Panic(_L("ProfileCacheItem:CacheOld"), KErrArgument)); + + if (iCurrentState->CanProfileBeUpdated(*this)) + { + StoreProfileToUpdate(aNewProfile); + return ETrue; + } + + delete iQueuedProfile; + iQueuedProfile = aNewProfile; + iQueuedObserver = &aObserver; + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ClearOldProfile +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ClearOldProfile() + { + delete iOldProfile; + iOldProfile = NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::HasProfileUpdate +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::HasProfileUpdate() const + { + return iOldProfile != NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::UsedProfile +// Return the CSIPConcreteProfile that most recently used profile agent to +// register, deregister or update. +// +// iProfileWithNewIAP and iProfileWithOldIAP exist only during ALR migration, +// and they never exist both at the same time. +// iProfileWithNewIAP exists only in state CSIPProfileStateMigratingToNewIAP and +// iProfileWithOldIAP exists only in state CSIPProfileStateUnregisteringOldIAP. +// +// iOldProfile exists during an update. +// ----------------------------------------------------------------------------- +// +CSIPConcreteProfile& CSIPProfileCacheItem::UsedProfile() + { + return iProfileWithNewIAP ? *iProfileWithNewIAP : + iProfileWithOldIAP ? *iProfileWithOldIAP : + iOldProfile ? *iOldProfile : Profile(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::UsedProfile +// ----------------------------------------------------------------------------- +// +const CSIPConcreteProfile& CSIPProfileCacheItem::UsedProfile() const + { + return iProfileWithNewIAP ? *iProfileWithNewIAP : + iProfileWithOldIAP ? *iProfileWithOldIAP : + iOldProfile ? *iOldProfile : Profile(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::AddObserverL +// Don't add observer to iObserversWaitedForPermission. It has only observers +// that were notified of a new IAP. +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::AddObserverL( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iObservers.AppendL(&aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RemoveObserver +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RemoveObserver( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + TInt index = iObservers.Find(&aObserver); + if (index != KErrNotFound) + { + iObservers.Remove(index); + } + + RemoveFromPendingObservers(aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::Observers +// ----------------------------------------------------------------------------- +// +const RPointerArray& +CSIPProfileCacheItem::Observers() const + { + return iObservers; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsObserverOrUser +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsObserverOrUser( + const MSIPExtendedConcreteProfileObserver& aObserver) const + { + return (iObservers.Find(&aObserver) != KErrNotFound) || IsUser(aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RemoveUser +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RemoveUser( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + TInt index = iUsers.Find(&aObserver); + if (index != KErrNotFound) + { + iUsers.Remove(index); + CheckProfileEnabledState(); + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RemoveAllUsers +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RemoveAllUsers() + { + iUsers.Reset(); + CheckProfileEnabledState(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsUser +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsUser( + const MSIPExtendedConcreteProfileObserver& aObserver) const + { + return iUsers.Find(&aObserver) != KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::MoveToUserL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::MoveToUserL( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iUsers.AppendL(&aObserver); + + CheckProfileEnabledState(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsActiveState +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsActiveState() const + { + return iCacheState == ENormal; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::HasAorL +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::HasAorL(const TDesC8& aAOR) const + { + TUriParser8 otherUriparser; + User::LeaveIfError(otherUriparser.Parse(aAOR)); + TInt err = otherUriparser.Equivalent(iProfile->AORUri8()); + if (err == KErrNoMemory) + { + User::Leave(err); + } + return err == KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::StartRegisterL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::StartRegisterL(CSIPProfileState& aWaitForIAP, + CSIPProfileState& aRegInProg, + TBool aGetIap) + { + TUint32 snapId(0); + PROFILE_DEBUG3("ProfileCacheItem::StartRegisterL - SNAP ID", snapId) + if (aGetIap && IsSNAPConfigured(snapId)) + { + PROFILE_DEBUG3("ProfileCacheItem::StartRegisterL - MONITOR SNAP", snapId) + MonitorSnapL(snapId, aWaitForIAP, aRegInProg); + } + else + { + PROFILE_DEBUG3("ProfileCacheItem::StartRegisterL - REGISTER", snapId) + iCurrentState->RegisterL(*this); + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::EnableL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::EnableL( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iCurrentState->EnableL(*this, aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::EnableSnapInUseL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::EnableSnapInUseL( + const MSIPExtendedConcreteProfileObserver& aObserver, + TUint32 aSnapId) + { + iCurrentState->EnableSnapInUseL(*this, aObserver, aSnapId); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::DisableL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::DisableL( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iCurrentState->DisableL(*this, aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RemoveL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RemoveL() + { + iCacheState = EToBeRemoved; + iCurrentState->RemoveL(*this); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ShutdownInitiated +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ShutdownInitiated() + { + iIsShutdownInitiated = ETrue; + iCurrentState->ShutdownInitiated(*this); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsShutdownInitiated +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsShutdownInitiated() const + { + return iIsShutdownInitiated; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RfsInprogress +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RfsInprogress(TBool aStatus) + { + iIsRfsInprogress = aStatus; + iCurrentState->ShutdownInitiated(*this); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsRfsInprogress +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsRfsInprogress() const + { + return iIsRfsInprogress; + } + +// CSIPProfileCacheItem::CanBePermanentlyRemoved +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::CanBePermanentlyRemoved() const + { + return iCurrentState->CanBePermanentlyRemoved(*this); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::UpdateRegistrationL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::UpdateRegistrationL( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iCurrentState->UpdateRegistrationL(*this, aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RegistrationStatusEvent +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RegistrationStatusEventL( + CSIPConcreteProfile::TStatus aStatus, + TUint32 aStatusId) + { + UsedProfile().SetContextId(aStatusId); + iCurrentState->RegistrationStatusEventL(*this, aStatus); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ChangeStateL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ChangeStateL(CSIPProfileState* aNewState) + { + CSIPConcreteProfile::TStatus newState = aNewState->Name(); + PROFILE_DEBUG5("ProfileCacheItem::ChangeStateL id,old state,new state", + ProfileId(), + iCurrentState->Name(), + newState) + + TBool maySendRegStatusEvent = !iCurrentState->IsAlrState(); + if (!aNewState->IsAlrState()) + { + iProfile->SetStatus(newState); + } + + iCurrentState = aNewState; + iCurrentState->EnterL(*this, maySendRegStatusEvent, iServerCore); + + ResumeL(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ResumeL +// Don't resume if migrating. Resume is only used with SNAP. +// If both a queued update and iMustRefreshIAPs exist, do update first. +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ResumeL() + { + PROFILE_DEBUG3("ProfileCacheItem::ResumeL id", ProfileId()) + + TUint32 snapId(0); + if (!IAPMigrationInProgress()) + { + PROFILE_DEBUG1("ProfileCacheItem::ResumeL SNAP used,not migrating") + + if (iQueuedProfile && iCurrentState->CanProfileBeUpdated(*this)) + { + ResumeQueuedUpdateL(); + } + else if(IsSNAPConfigured(snapId)) + { + PROFILE_DEBUG1("ProfileCacheItem::ResumeL don't resume now") + + // HasProfileUpdate is checked in ShouldRefreshIAPs + if (iMustRefreshIAPs && + iCurrentState->ShouldRefreshIAPs(*this) && + iMigrationController) + { + iMustRefreshIAPs = EFalse; + PROFILE_DEBUG3("Refresh IAPs, snapId=", snapId) + iMigrationController->RefreshIapAvailabilityL(snapId); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SetIAPRefreshReminder +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SetIAPRefreshReminder() + { + iMustRefreshIAPs = ETrue; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::NewIAPFailed +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::NewIAPFailed() + { + PROFILE_DEBUG1("ProfileCacheItem::NewIAPFailed") + + iDeltaTimer->Remove(iDeltaTimerEntry); + + const TInt KIapFailedDelay(1); + + TTimeIntervalMicroSeconds32 interval(KIapFailedDelay); + iDeltaTimer->Queue(interval, iDeltaTimerEntry); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SendUnregisteredStatusEventL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SendUnregisteredStatusEventL() + { + iServerCore.SendUnregisteredStatusEventL(*this); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::HandleProfileError +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::HandleProfileError(TInt aError, + CSIPConcreteProfile& aProfile) + { + PROFILE_DEBUG3("ProfileCacheItem::HandleProfileError", aError) + iServerCore.SIPProfileErrorEvent(aProfile, aError); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::HandleError +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::HandleError(TInt aError) + { + PROFILE_DEBUG4("ProfileCacheItem::HandleError id,err", ProfileId(), aError) + + if (iCurrentState->ErrorOccurred(*this, aError)) + { + PROFILE_DEBUG1("ProfileCacheItem::HandleError go unregistered") + + SwitchToUnregisteredState(); + + if (aError != KErrNone) + { + iProfile->SetLastRegistrationError(aError); + } + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::Compare +// During linear search operations the search term is always passed as the first +// argument and the second argument is an element of the array being searched. +// +// As MSIPProfileAgentObserver calls can lead here, aSearched.iProfileId can be +// a temp id, used in iOldProfile, iProfileWithNewIAP, iProfileWithOldIAP. +// iQueuedProfile has the same profile id as current profile. +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::Compare(const CSIPProfileCacheItem& aSearched, + const CSIPProfileCacheItem& aArrayItem) + { + CSIPConcreteProfile* old = aArrayItem.iOldProfile; + CSIPConcreteProfile* newIap = aArrayItem.iProfileWithNewIAP; + CSIPConcreteProfile* oldIap = aArrayItem.iProfileWithOldIAP; + return (aArrayItem.iProfileId == aSearched.iProfileId) || + (old && old->Id() == aSearched.iProfileId) || + (newIap && newIap->Id() == aSearched.iProfileId) || + (oldIap && oldIap->Id() == aSearched.iProfileId); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ClientAllowsMigrationL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ClientAllowsMigrationL(TUint32 aIapId, + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iCurrentState->ClientAllowsMigrationL(*this, aIapId, aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ClientDisallowsMigrationL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ClientDisallowsMigrationL(TUint32 aIapId, + const MSIPExtendedConcreteProfileObserver& aObserver) + { + iCurrentState->ClientDisallowsMigrationL(*this, aIapId, aObserver); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SetClientPermission +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SetClientPermission(TUint32 aIapId, + const MSIPExtendedConcreteProfileObserver* aObserver, + TBool aAllowMigration) + { + PROFILE_DEBUG5("ProfileCacheItem::SetClientPermission id,iap,allow", + ProfileId(), + aIapId, + aAllowMigration) + PROFILE_DEBUG3("pending observers=", iObserversWaitedForPermission.Count()) + + if (!aAllowMigration) + { + iMigrationDisallowed = ETrue; + } + if (aObserver) + { + RemoveFromPendingObservers(*aObserver); + } + + if (iObserversWaitedForPermission.Count() == 0 && iMigrationController) + { + PROFILE_DEBUG3("ProfileCacheItem::SetClientPermission allow", + !iMigrationDisallowed) + iMigrationController->SetMigrationPermission(*this, + !iMigrationDisallowed, + aIapId); + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsSNAPConfigured +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsSNAPConfigured(TUint32& aSnapId) const + { + TBool Val = (UsedProfile().ExtensionParameter(KSIPSnapId, aSnapId) == KErrNone); + + PROFILE_DEBUG3("Exceptional SNAP Entry verifier :", KDefaultSNAPIdentifier) + if(Val && aSnapId == KDefaultSNAPIdentifier) + { + PROFILE_DEBUG3("Snap ID Found to be :", aSnapId) + TRAPD(err, DefaultSNAPL(aSnapId)); + if(err) + { + Val = EFalse; + } + } + PROFILE_DEBUG3("ProfileCacheItem::IsSNAPConfigured; return SNAP ID Value = ", aSnapId) + PROFILE_DEBUG3("ProfileCacheItem::IsSNAPConfigured; return Value = ", Val) + return Val; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::PassMigrationStartedToClientL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::PassMigrationStartedToClientL(TUint32 aSnapId, + TUint32 aIapId) + { + iServerCore.MigrationStartedL(*this, aSnapId, aIapId); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::PassAlrErrorToClient +// ----------------------------------------------------------------------------- +// +TInt CSIPProfileCacheItem::PassAlrErrorToClient(TInt aError, TUint32 aIapId) + { + TUint32 snapId(0); + if (!IsSNAPConfigured(snapId)) + { + return KErrNotFound; + } + return iServerCore.PassAlrErrorToClient(*this, aError, snapId, aIapId); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::HandleNewIapL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::HandleNewIapL(TUint32 aSnapId, + TUint32 aIapId, + TBool aRegistrationExists, + CSIPProfileState& aWaitForPermission) + { + PROFILE_DEBUG5("ProfileCacheItem::HandleNewIapL id,snap,iap", + ProfileId(), + aSnapId, + aIapId) + PROFILE_DEBUG3("reg exists=", aRegistrationExists) + + TUint32 snapId(0); + __ASSERT_ALWAYS(IsSNAPConfigured(snapId), User::Leave(KErrNotFound)); + __ASSERT_ALWAYS(aSnapId == snapId, User::Leave(KErrArgument)); + + iMigrationDisallowed = EFalse; + + // SetMigrationPermission can syncronously lead to MigrationIs(Dis)AllowedL + // so enter state first. + ChangeStateL(&aWaitForPermission); + if (aRegistrationExists) + { + // Don't wait (dis)allow to an earlier IAP + iObserversWaitedForPermission.Reset(); + + for (TInt i = 0; i < iObservers.Count(); ++i) + { + if (iObservers[i]->IapAvailableL(ProfileId(), aSnapId, aIapId)) + { + iObserversWaitedForPermission.AppendL(iObservers[i]); + } + } + PROFILE_DEBUG3("pending count=", iObserversWaitedForPermission.Count()) + if (iObserversWaitedForPermission.Count() == 0) + { + iMigrationController->SetMigrationPermission(*this, ETrue, aIapId); + } + } + else + { + // Don't pass IAP-Available, MigrationStarted or MigrationCompleted to + // clients. This profile's clients are not asked for permission, but + // another profile with same SNAP can disallow migration. + __ASSERT_ALWAYS(!iProfileWithNewIAP, User::Leave(KErrNotFound)); + iMigrationController->SetMigrationPermission(*this, ETrue, aIapId); + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::MonitorSnapL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::MonitorSnapL(TUint32 aSnapId, + CSIPProfileState& aWaitForIAP, + CSIPProfileState& aRegInProg) + { + if (iMigrationController && iMigrationController->SnapId() != aSnapId) + { + // Stop monitoring the old SNAP id + StopSnapMonitoring(); + } + + if (!iMigrationController) + { + iMigrationController = &iServerCore.MigrationControllerL(aSnapId); + TUint32 iapId = iMigrationController->AttachProfileL(*this); + if (iapId) + { + // Initial IAP obtained + aRegInProg.RegisterWithIapL(*this, iapId, aRegInProg); + } + else + { + // No IAP available yet + ChangeStateL(&aWaitForIAP); + } + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ProfileRegisteredL +// If initial registration, don't pass MigrationCompleted. +// ----------------------------------------------------------------------------- +// +void +CSIPProfileCacheItem::ProfileRegisteredL(TBool aMigrating) + { + TUint32 snapId(0); + if (IsSNAPConfigured(snapId)) + { + __ASSERT_ALWAYS(iMigrationController != NULL, + User::Leave(KErrNotFound)); + + TInt err = iMigrationController->SetIapAcceptance(*this, ETrue); + if (err != KErrNone) + { + iServerCore.HandleProfileError(*this, err); + return; + } + if (aMigrating) + { + iServerCore.MigrationCompletedL(*this, snapId, Profile().IapId()); + } + // Send notification of the updated IAP + iServerCore.SendProfileUpdatedEventL(*this, Profile()); + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RegistrationEnded +// Can use the same profile id, as TerminateHandling cleared earlier profile +// from Profile Agent. +// If client uses SetClientPermission later, migration controller ignores it +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RegistrationEnded() + { + PROFILE_DEBUG3("ProfileCacheItem::RegistrationEnded id", ProfileId()) + + // If this has already been done, does nothing. + iMigrationController->SetMigrationPermission(*this, ETrue); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::CheckProfileEnabledState +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::CheckProfileEnabledState() + { + UsedProfile().SetEnabled(iUsers.Count() > 0); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsReferred +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IsReferred() const + { + return ReferenceCount() > 0 || Profile().IsAutoRegistrationEnabled(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ProceedUpdatingProfileL +// If updating SNAP, de-register old SNAP's profile, then register new SNAP's +// profile. CSIPProfileStateUnregistered::EnterL calls StartRegisterL, ending +// old SNAP monitoring and starts monitoring new SNAP. +// ----------------------------------------------------------------------------- +// +void +CSIPProfileCacheItem::ProceedUpdatingProfileL(CSIPProfileState& aUnregInProg) + { + if (HasProfileUpdate() && !IAPMigrationInProgress()) + { + if (IsSnapIdUpdated(Profile())) + { + aUnregInProg.StartDeregisterL(*this, aUnregInProg); + } + else + { + if (aUnregInProg.DoUpdateL(Profile(), *iOldProfile)) + { + ChangeStateL(&aUnregInProg); + } + else + { + ClearOldProfile(); + // Update is complete, resume any pending action + ResumeL(); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::StopSnapMonitoring +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::StopSnapMonitoring() + { + if (iMigrationController) + { + iMigrationController->DetachProfile(*this); + iMigrationController = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::CloneProfileL +// Use a new profile id for the new IAP, so Profile Agent treats it as different +// profile from the old IAP. +// ----------------------------------------------------------------------------- +// +CSIPConcreteProfile& CSIPProfileCacheItem::CloneProfileL(TUint aIapId) + { + PROFILE_DEBUG4("ProfileCacheItem::CloneProfileL id,iap", + ProfileId(), + aIapId) + __ASSERT_ALWAYS(!iProfileWithNewIAP, User::Leave(KErrAlreadyExists)); + + CSIPConcreteProfile* profile = Profile().CloneL(); + CleanupStack::PushL(profile); + profile->SetId(iServerCore.GenerateProfileIdL()); + profile->SetStorageId(Profile().StorageId()); + + // Use the same Contact user-part as the existing profile. + // CSIPConcreteProfile::CloneL generated a new one. + const TDesC8* user(NULL); + User::LeaveIfError(Profile().ExtensionParameter( + KSIPContactHeaderUser, user)); + profile->SetExtensionParameterL(KSIPContactHeaderUser, *user); + CleanupStack::Pop(profile); + profile->SetIapId(aIapId); + + iProfileWithNewIAP = profile; + return *iProfileWithNewIAP; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ClearMigrationProfiles +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ClearMigrationProfiles() + { + delete iProfileWithNewIAP; + iProfileWithNewIAP = NULL; + delete iProfileWithOldIAP; + iProfileWithOldIAP = NULL; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::UseProfileWithNewIAP +// The new IAP works. Prepare to de-register the old IAP. +// ----------------------------------------------------------------------------- +// +CSIPConcreteProfile& CSIPProfileCacheItem::UseProfileWithNewIAP() + { + __ASSERT_ALWAYS(!iProfileWithOldIAP, + User::Panic(KNullDesC, KErrAlreadyExists)); + __ASSERT_ALWAYS(iProfileWithNewIAP != NULL, + User::Panic(KNullDesC, KErrNotFound)); + + PROFILE_DEBUG4("ProfileCacheItem::UseProfileWithNewIAP Swapping Id1, Id2", + iProfile->Id(), iProfileWithNewIAP->Id() ) + + iProfileWithNewIAP->SetStatus( CSIPConcreteProfile::ERegistered ); + + // Swap profile id's. Only the original id can be passed to clients. + TUint32 originalId( iProfile->Id() ); + iProfile->SetId( iProfileWithNewIAP->Id() ); + iProfileWithNewIAP->SetId( originalId ); + + iProfileWithOldIAP = iProfile; + iProfile = iProfileWithNewIAP; + iProfileWithNewIAP = NULL; + + return *iProfileWithOldIAP; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IAPMigrationInProgress +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::IAPMigrationInProgress() const + { + return iProfileWithNewIAP || iProfileWithOldIAP; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::StoreProfileToUpdate +// ----------------------------------------------------------------------------- +// +void +CSIPProfileCacheItem::StoreProfileToUpdate(CSIPConcreteProfile* aNewProfile) + { + PROFILE_DEBUG3("ProfileCacheItem::StoreProfileToUpdate id", ProfileId()) + + if (!iOldProfile) + { + iOldProfile = iProfile; + iProfile = NULL; + } + SetProfile(aNewProfile); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ResumeQueuedUpdateL +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ResumeQueuedUpdateL() + { + PROFILE_DEBUG3("ProfileCacheItem::ResumeQueuedUpdateL id", ProfileId()) + __ASSERT_ALWAYS(iQueuedProfile != NULL && iQueuedObserver != NULL, + User::Leave(KErrNotFound)); + __ASSERT_ALWAYS(!IAPMigrationInProgress(), User::Leave(KErrNotReady)); + + CSIPConcreteProfile* profile = iQueuedProfile; + TUint32 snapId(0); + if (!IsSnapIdUpdated(*profile) && IsSNAPConfigured(snapId)) + { + // Use the current IAP id + profile->SetIapId(UsedProfile().IapId()); + } + const MSIPExtendedConcreteProfileObserver* obs = iQueuedObserver; + iQueuedProfile = NULL; + iQueuedObserver = NULL; + StoreProfileToUpdate(profile); + + iServerCore.UpdateRegistrationL(ProfileId(), *obs); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::IsSnapIdUpdated +// ----------------------------------------------------------------------------- +// +TBool +CSIPProfileCacheItem::IsSnapIdUpdated(CSIPConcreteProfile& aNewProfile) const + { + TUint32 currentSnapId(0); + IsSNAPConfigured(currentSnapId); + + TUint32 newSnapId(0); + TBool res(EFalse); + + res = (aNewProfile.ExtensionParameter(KSIPSnapId, newSnapId) == KErrNone && + newSnapId != currentSnapId); + PROFILE_DEBUG3("Exceptional SNAP Entry verifier :", KDefaultSNAPIdentifier) + if(res && newSnapId == KDefaultSNAPIdentifier) + { + res=EFalse; + } + PROFILE_DEBUG3("CSIPProfileCacheItem::IsSnapIdUpdated CurrentSNAPID",currentSnapId) + PROFILE_DEBUG3("CSIPProfileCacheItem::IsSnapIdUpdated NewSNAPID",newSnapId) + return res; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::RemoveFromPendingObservers +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::RemoveFromPendingObservers( + const MSIPExtendedConcreteProfileObserver& aObserver) + { + TInt index = iObserversWaitedForPermission.Find(&aObserver); + if (index != KErrNotFound) + { + iObserversWaitedForPermission.Remove(index); + } + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::DoNewIapFailed +// Ignore SetIapAcceptance return value, as already handling error (IAP failed). +// ----------------------------------------------------------------------------- +// +TInt CSIPProfileCacheItem::DoNewIapFailed(TAny* aPtr) + { + __ASSERT_DEBUG(aPtr, User::Panic(_L("ProfileCacheItem:DoNewIapFailed"), + KErrArgument)); + PROFILE_DEBUG1("ProfileCacheItem::DoNewIapFailed") + + if ( !aPtr ) + { + return KErrArgument; + } + + CSIPProfileCacheItem* self = static_cast(aPtr); + self->iMigrationController->ResetFlags(); + self->iMigrationController->SetIapAcceptance(*self, EFalse); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SwitchToUnregisteredState +// Enter unregistered state. Don't use ChangeStateL to avoid loop where profile +// would register again (if auto-registration on). +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SwitchToUnregisteredState() + { + CSIPProfileState& unregistered = iServerCore.UnregisteredState(); + iProfile->SetStatus(unregistered.Name()); + iCurrentState = &unregistered; + SetSnapRetryCounter(0); + + // No need to monitor SNAP anymore. + StopSnapMonitoring(); + RemoveAllUsers(); + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SetSnapRetryCounter +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::SetSnapRetryCounter(TInt aCounter) + { + PROFILE_DEBUG3("CSIPProfileCacheItem::SetSnapRetryCounter counter", + aCounter) + iSnapRetryCounter = aCounter; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SnapRetryCounter +// ----------------------------------------------------------------------------- +// +TInt CSIPProfileCacheItem::SnapRetryCounter() const + { + PROFILE_DEBUG3("CSIPProfileCacheItem::SnapRetryCounter counter", + iSnapRetryCounter) + return iSnapRetryCounter; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::SnapRetryCountReached +// ----------------------------------------------------------------------------- +// +TBool CSIPProfileCacheItem::SnapRetryCountReached() const + { + TBool reached = iSnapRetryCounter >= KSnapRetryCountThreshold; + PROFILE_DEBUG3("CSIPProfileCacheItem::SnapRetryCountReached reached", + reached) + return reached; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::OfferedIapRejected +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::OfferedIapRejected() + { + PROFILE_DEBUG3("CSIPProfileCacheItem::OfferedIapRejected, status", + iProfile->Status()) + + HandleError( KErrCancel ); + + // State is informed as ERegistrationInProgress to get registration + // error event event in client. + iServerCore.SendErrorEvent( + *this, CSIPConcreteProfile::ERegistrationInProgress, KErrCancel ); + } +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::ResetShutdownvariable +// ----------------------------------------------------------------------------- +// +void CSIPProfileCacheItem::ResetShutdownvariable() + { + iIsShutdownInitiated = EFalse; + } + +// ----------------------------------------------------------------------------- +// CSIPProfileCacheItem::DefaultSNAPL +// This function will return the ID of the default SNAP. +// ----------------------------------------------------------------------------- +// + +void CSIPProfileCacheItem::DefaultSNAPL(TUint32& aSnapId) const + + { + RCmManager cmManager; + cmManager.OpenL(); + CleanupClosePushL(cmManager); + TCmDefConnValue defConn; + cmManager.ReadDefConnL( defConn ); + aSnapId = defConn.iId; + PROFILE_DEBUG3("CSIPProfileCacheItem::DefaultSNAPL with Value: ", aSnapId) + CleanupStack::PopAndDestroy(); + }