--- /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 <sipprofile.h>
+#include <cmmanager.h>
+#include<e32const.h>
+
+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<MSIPExtendedConcreteProfileObserver>&
+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<CSIPProfileCacheItem*>(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();
+ }