realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileServerCore.cpp
changeset 0 307788aac0a8
child 4 dd3853b8dc3f
child 15 8248b03a2669
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileServerCore.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1841 @@
+// Copyright (c) 2007-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        : sipprofileservercore.cpp
+// Part of     : SIP Profile Server
+// implementation
+// Version     : 1.0
+//
+
+
+
+// INCLUDE FILES
+#include "SipProfileServerCore.h"
+#include "SipProfileCSServer.h"
+#include "sipextendedconcreteprofileobserver.h"
+#include "SIPProfileStorage.h"
+#include "SipProfileStorageSecureBackup.h"
+#include "SipProfileCacheItem.h"
+#include "SipProfileCacheCleanupItem.h"
+#include "sipconcreteprofile.h"
+#include "sipprofileplugins.h"
+#include "sipplugindirector.h"
+#include "SipProfileStateUnregistered.h"
+#include "SipProfileStateRegistered.h"
+#include "SipProfileStateRegInProg.h"
+#include "SipProfileStateUnregInProg.h"
+#include "sipprofilestatewaitforiap.h"
+#include "sipprofilestatewaitforpermission.h"
+#include "sipprofilestatemigratingtonewiap.h"
+#include "sipprofilestateunregisteringoldiap.h"
+#include "SipProfileLog.h"
+#include "sipalrhandler.h"
+#include "sipalrmigrationcontroller.h"
+#include "sipmanagedprofile.h"
+#include "sipprofile.h"
+#include "sipprofilecs.h"
+#include "SIPProfileStorageIndex.h"
+#include <siperr.h>
+#include <sipsystemstatemonitor.h>
+#include <random.h>
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSIPProfileServerCore* CSIPProfileServerCore::NewL()
+    {
+    CSIPProfileServerCore* self = CSIPProfileServerCore::NewLC();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSIPProfileServerCore* CSIPProfileServerCore::NewLC()
+    {
+    CSIPProfileServerCore* self = new(ELeave)CSIPProfileServerCore();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CSIPProfileServerCore
+// -----------------------------------------------------------------------------
+//
+CSIPProfileServerCore::CSIPProfileServerCore() :
+	iBackupInProgress(EFalse)
+#ifdef CPPUNIT_TEST
+    // Set the array granularity to 1, so they allocate memory for every append    
+    , iProfileCache(1),
+    iObservers(1),
+    iMigrationControllers(1)
+#endif
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ConstructL()
+    {
+    User::LeaveIfError(iFs.Connect());
+
+    iFindEntry = CSIPProfileCacheItem::NewL(*this, iUnregistered);
+
+    iPluginDirector = CSIPPluginDirector::NewL(*this);
+
+    iUnregistered = CSIPProfileStateUnregistered::NewL(*iPluginDirector);
+    iRegistered = CSIPProfileStateRegistered::NewL(*iPluginDirector);
+    iUnregInProg = CSIPProfileStateUnregInProg::NewL(*iPluginDirector);
+    iRegInProg = CSIPProfileStateRegInProg::NewL(*iPluginDirector);
+    iWaitForIAP = CSIPProfileStateWaitForIAP::NewL(*iPluginDirector);
+    iWaitForPermission =
+    	CSIPProfileStateWaitForPermission::NewL(*iPluginDirector);
+    iMigratingToNewIAP =
+    	CSIPProfileStateMigratingToNewIAP::NewL(*iPluginDirector);
+    iUnregisteringOldIAP =
+    	CSIPProfileStateUnregisteringOldIAP::NewL(*iPluginDirector);
+
+    iUnregistered->SetNeighbourStates(*iRegInProg, *iWaitForIAP);
+    iRegistered->SetNeighbourStates(*iUnregInProg,
+    								*iUnregistered,
+    								*iRegInProg,
+    								*iWaitForPermission);
+    iUnregInProg->SetNeighbourStates(*iUnregistered, *iRegistered);
+    iRegInProg->SetNeighbourStates(*iRegistered,
+    							   *iUnregistered,
+    							   *iUnregInProg,
+    							   *iWaitForIAP,
+    							   *iWaitForPermission);
+    iWaitForIAP->SetNeighbourStates(*iWaitForPermission,
+    								*iRegInProg,
+    								*iUnregInProg,
+    								*iUnregistered);
+    iWaitForPermission->SetNeighbourStates(*iWaitForIAP,
+    	*iMigratingToNewIAP,
+    	*iRegInProg,
+    	*iRegistered,
+    	*iUnregInProg,
+    	*iUnregistered);
+    iMigratingToNewIAP->SetNeighbourStates(*iUnregisteringOldIAP,
+    									   *iWaitForIAP,
+    									   *iRegistered,
+    									   *iUnregInProg,
+    									   *iUnregistered);
+	iUnregisteringOldIAP->SetNeighbourStates(*iRegistered, *iUnregInProg);
+	
+	LoadSystemStateMonitorL();
+	
+	iAlrHandler = CSipAlrHandler::NewL(*this,iSystemStateMonitor);
+
+    LoadProfilesL(EFalse);
+
+    iNotify = CSIPProfileStorageSecureBackup::NewL(this);
+    
+    iServer = CSIPProfileCSServer::NewL(*this);
+	
+	iOfflineEventReceived = EFalse;
+    
+    PROFILE_DEBUG1("ProfileServer started")
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::~CSIPProfileServerCore
+// -----------------------------------------------------------------------------
+//
+CSIPProfileServerCore::~CSIPProfileServerCore()
+    {
+    // If the monitor plug-in is deleted later in destructor, leaks memory.
+    if (iSystemStateMonitor)
+    	{
+    	iSystemStateMonitor->StopMonitoring( 
+    	    CSipSystemStateMonitor::ESystemState, 0, *this);
+    	delete iSystemStateMonitor;
+    	}
+    
+    delete iServer;    
+    
+    iObservers.Reset();
+
+	// Profile cache entries use migration controllers, so delete entries first
+    iProfileCache.ResetAndDestroy();
+
+	// Migration controllers use ALR handler, so delete controllers first
+	iMigrationControllers.ResetAndDestroy();
+	delete iAlrHandler;
+
+    delete iProfileStorage;
+    delete iPluginDirector;
+    delete iProfilePlugins;
+    delete iFindEntry;
+
+    delete iUnregistered;
+    delete iRegistered;
+    delete iUnregInProg;
+    delete iRegInProg;
+    delete iWaitForIAP;
+    delete iWaitForPermission;
+    delete iMigratingToNewIAP;
+    delete iUnregisteringOldIAP;
+
+    delete iNotify;
+
+    iFs.Close();
+
+    PROFILE_DEBUG1("ProfileServer stopped")
+    
+#ifdef _BullseyeCoverage
+    // Store coverage measurement
+    cov_write();
+#endif
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SIPProfileStatusEvent
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SIPProfileStatusEvent(CSIPConcreteProfile& aProfile,
+												  TUint32 aContextId)
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfile.Id());
+    TRAPD(err, SIPProfileStatusEventL(aProfile.Id(), aContextId));
+
+    if (err != KErrNone)
+        {
+		if (item)
+        	{
+        	HandleAsyncError(*item,
+        					 CSIPConcreteProfile::ERegistrationInProgress,
+        					 err);
+        	}
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SIPProfileStatusEventL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SIPProfileStatusEventL(TUint32 aProfileId,
+    											   TUint32 aContextId)
+    {
+    PROFILE_DEBUG4("ProfileServerCore::SIPProfileStatusEventL id,ctxId",
+    			   aProfileId, aContextId)
+
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfileId);
+    if (item)
+    	{
+		// In MigratingToNewIAP state, only profile in use is new IAP's register
+    	CSIPConcreteProfile::TStatus status;
+        iPluginDirector->State(status, item->UsedProfile());
+
+        item->RegistrationStatusEventL(status, aContextId);
+
+        if (!item->IsActiveState() )
+        	{
+        	if (status == CSIPConcreteProfile::ERegistered)
+        		item->RemoveL();
+        	else
+        	if (item->CanBePermanentlyRemoved())
+        		{
+        		RemoveProfileItem(aProfileId);
+            	delete item;
+				item = NULL;
+            	PROFILE_DEBUG3(
+            	"ProfileServerCore::SIPProfileStatusEventL(removed) id",
+                	aProfileId)
+            	}
+        		
+        	}
+        if (item && item->IsRfsInprogress())
+            {
+            CSIPConcreteProfile::TStatus status;
+            TInt count = iProfileCache.Count();
+            for (TInt i = 0; i < iProfileCache.Count(); i++)
+                {
+                iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
+                if (status == CSIPConcreteProfile::EUnregistered)
+                    count--;
+                }
+            if (!count)
+                {
+                iSystemStateMonitor->EventProcessingCompleted(
+								CSipSystemStateMonitor::ERfsState, 0, *this);
+                }
+            }
+        }
+		
+		if (iOfflineEventReceived)
+        {
+        CSIPConcreteProfile::TStatus status;
+        TInt count = iProfileCache.Count();
+        for (TInt i = 0; i < iProfileCache.Count(); i++)
+            {
+            iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
+            if (status == CSIPConcreteProfile::EUnregistered)
+                count--;
+            }
+        if (!count)
+            {
+            iSystemStateMonitor->EventProcessingCompleted(CSipSystemStateMonitor::ESystemState, 0, *this);
+            }
+        }
+		
+    CheckServerStatus();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SIPProfileErrorEvent
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SIPProfileErrorEvent(CSIPConcreteProfile& aProfile,
+    											 TInt aError)
+    {
+    PROFILE_DEBUG4("ProfileServerCore::SIPProfileErrorEvent id,err", 
+                   aProfile.Id(), aError)
+
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfile.Id());
+    if (item)
+    	{
+    	CSIPConcreteProfile::TStatus status = ValidateErrorStatus(*item);
+        HandleAsyncError(*item, status, aError);
+        iPluginDirector->StartTimerForCleanup();
+    	}
+
+    CheckServerStatus();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProceedRegistration
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::ProceedRegistration
+		(CSIPConcreteProfile& aProfile, TInt aError)
+    {
+    PROFILE_DEBUG4("ProfileServerCore::ProceedRegistration id, err", aProfile.Id(), aError)
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfile.Id());
+    if (!item)
+    	{
+    	return EFalse;
+    	}
+
+    if ( ShouldChangeIap(item->UsedProfile(), aError) && 
+    	 !item->SnapRetryCountReached() )
+        {
+        PROFILE_DEBUG1("CSIPProfileServerCore::ProceedRegistration, IAP should be changed")
+        // If IAP should be changed, handle this like an error, so the profile
+        // can ask for a new IAP.
+        SIPProfileErrorEvent(item->UsedProfile(), aError);
+        
+        // Return false so that the profile agent does not retry registration
+        // with old IAP.
+        return EFalse;
+        }
+	PROFILE_DEBUG1("CSIPProfileServerCore::ProceedRegistration, IAP should NOT be changed")        
+        
+    if (!item->IsActiveState())
+        {
+        PROFILE_DEBUG1("ProceedRegistration, profile removed")
+        return EFalse;
+        }
+    if (item->ReferenceCount() == 0)
+    	{
+    	if (!item->LatestProfile().IsAutoRegistrationEnabled())
+            {
+            PROFILE_DEBUG1("ProceedRegistration, profile not used")
+            return EFalse;
+            }
+    	if (item->HasProfileUpdate())
+            {
+            PROFILE_DEBUG1("ProceedRegistration, profile updated, not used")
+            return EFalse;
+            }
+    	}
+
+    PROFILE_DEBUG1("ProceedRegistration, profile untouched")
+    return ETrue;    
+    }    
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::GetFailedProfilesL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::GetFailedProfilesL(const TSIPProfileTypeInfo& aType,
+    RPointerArray<CSIPConcreteProfile>& aFailedProfiles) const
+    {
+    for (TInt i = 0; i < iProfileCache.Count(); i++)
+        {
+        const CSIPConcreteProfile& profile = iProfileCache[i]->Profile();
+
+        if (profile.ProfileType().iSIPProfileClass == aType.iSIPProfileClass &&
+        	profile.ProfileType().iSIPProfileName  == aType.iSIPProfileName &&
+            (profile.IsEnabled() || profile.IsAutoRegistrationEnabled()) &&
+             profile.Status() == CSIPConcreteProfile::EUnregistered &&
+             profile.LastRegistrationError() != KErrNone)
+        	{
+        	aFailedProfiles.AppendL(&profile);
+        	}
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::HandleProfileError
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::HandleProfileError(CSIPProfileCacheItem& aItem,
+											    TInt aOwnError)
+	{
+    iPluginDirector->TerminateHandling(aItem.UsedProfile());
+    return aItem.HandleError(aOwnError);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SystemVariableUpdated
+// If a system shutdown event is received, initiate de-registering each profile
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SystemVariableUpdated( 
+    CSipSystemStateMonitor::TSystemVariable aVariable,
+    TInt /*aObjectId*/,
+    TInt aValue )
+    {
+    PROFILE_DEBUG3("CSIPProfileServerCore::SystemVariableUpdated System State changed to value", aValue)
+    
+    //If the SystemState is Offline, turn the boolean variable to true so that Profile-Server
+    //can indicate System State monitor that event processing is completed, provided all the 
+    //profiles have got deregistered
+    if (CSipSystemStateMonitor::ESystemOffline == aValue)
+        iOfflineEventReceived = ETrue;
+    
+	if ( aVariable == CSipSystemStateMonitor::ESystemState &&
+	     (aValue == CSipSystemStateMonitor::ESystemShuttingDown || 
+	     aValue == CSipSystemStateMonitor::ESystemOffline
+			 ))
+	    {    
+        for (TInt i = 0; i < iProfileCache.Count(); i++)
+            {
+            iProfileCache[i]->ShutdownInitiated();
+            }	    
+	    }
+	//If the System State is Online, register all the profiles in always on mode
+	else if(aVariable == CSipSystemStateMonitor::ESystemState && 
+		aValue == CSipSystemStateMonitor::ESystemOnline)
+		{
+		iOfflineEventReceived = EFalse;
+		for (TInt i = 0; i < iProfileCache.Count(); i++)
+		    {
+		    iProfileCache[i]->ResetShutdownvariable();
+		    CSIPProfileCacheItem* item = iProfileCache[i];
+		    if (item->Profile().IsAutoRegistrationEnabled())
+		        {
+                TRAPD(err, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+		        if (err != KErrNone)
+		            {
+		            HandleAsyncError(*item,CSIPConcreteProfile::ERegistrationInProgress,err);
+		            }
+				}
+			}
+		}
+	else if(aVariable == CSipSystemStateMonitor::ERfsState)
+	    {
+	    if(aValue == CSipSystemStateMonitor::ERfsStarted)
+	        {
+	        PROFILE_DEBUG1("RFS Started, de-registering the profiles")
+	        for (TInt i = 0; i < iProfileCache.Count(); i++)
+	            {
+	            iProfileCache[i]->RfsInprogress(ETrue);
+	            }
+	        }
+	    else if(aValue == CSipSystemStateMonitor::ERfsFailed)
+	        {
+	        PROFILE_DEBUG1("RFS Failed, re-registering the profiles")
+	        for (TInt i = 0; i < iProfileCache.Count(); i++)
+	            {
+	            iProfileCache[i]->RfsInprogress(EFalse);
+	            if (iProfileCache[i]->IsReferred())
+	                {
+	                TRAPD(err, iProfileCache[i]->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+	                if (err != KErrNone)
+	                    {
+	                    HandleAsyncError(*iProfileCache[i],
+	                            CSIPConcreteProfile::ERegistrationInProgress,
+	                            err);	                            
+	                    }
+	                }
+	            }
+	        }
+	    else if(aValue == CSipSystemStateMonitor::ERfsCompleted)
+	        {
+	        PROFILE_DEBUG1("RFS Completed")
+	        for (TInt i = 0; i < iProfileCache.Count(); i++)
+	            {
+	            iProfileCache[i]->RfsInprogress(EFalse);
+	            }
+	        }
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SessionRegisterL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SessionRegisterL(
+	const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    iObservers.AppendL(&aObserver);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SessionCleanup
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SessionCleanup(	
+	const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    TRAP_IGNORE(SessionCleanupL(aObserver))
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfilePluginsL
+// -----------------------------------------------------------------------------
+//
+const CSIPProfilePlugins& CSIPProfileServerCore::ProfilePluginsL()
+    {
+    delete iProfilePlugins;
+    iProfilePlugins = NULL;
+    iProfilePlugins = CSIPProfilePlugins::NewL();
+    RArray<TSIPProfileTypeInfo> array;
+    CleanupClosePushL(array);
+
+    RImplInfoPtrArray infoArray;
+    CleanupStack::PushL(TCleanupItem(ResetAndDestroyInfo, &infoArray));
+
+    TRAPD(err, iPluginDirector->ListImplementationsL(infoArray));
+    if (err == KErrNone) 
+        {
+        for (TInt i = 0; i < infoArray.Count(); i ++)
+            {
+            CImplementationInformation* ecomInfo = infoArray[i];
+            TSIPProfileTypeInfo info;
+            ConvertTypeInfoL(*ecomInfo, info);
+            array.AppendL(info);
+            }
+        }
+    CleanupStack::Pop(&infoArray);
+    infoArray.ResetAndDestroy();
+    infoArray.Close();
+
+    iProfilePlugins->SetPluginsL(array);
+    CleanupStack::Pop(&array);
+    array.Close();
+    return *iProfilePlugins;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::AddProfileL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::AddProfileL(CSIPConcreteProfile* aProfile,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    __ASSERT_ALWAYS(iProfileStorage != NULL, User::Leave(KErrLocked));
+
+    CSIPProfileCacheCleanupItem* cleanup =
+    	new (ELeave) CSIPProfileCacheCleanupItem;
+	CleanupStack::PushL(cleanup);
+    CleanupStack::PushL(TCleanupItem(CrashRevert, cleanup));
+
+    CSIPProfileCacheItem* item = CSIPProfileCacheItem::NewL(*this,
+    														iUnregistered);
+    cleanup->iCacheItem = item;
+
+    item->AddObserverL(aObserver);
+    iProfileCache.AppendL(item);
+    cleanup->iCache = &iProfileCache;
+
+	// AddSIPProfileL sets stream id to aProfile's profile id
+    iProfileStorage->AddSIPProfileL(*aProfile);
+
+    CleanupStack::Pop(); // TCleanupItem
+    CleanupStack::PopAndDestroy(cleanup);
+	
+	CSIPConcreteProfile* defaultProfile = FindDefaultProfile();
+
+	if ( !defaultProfile )
+		{
+		aProfile->SetDefault( ETrue );
+		}
+
+	if ( defaultProfile && aProfile->IsDefault() && defaultProfile != aProfile )
+		{
+		defaultProfile->SetDefault( EFalse );
+		}
+
+    item->SetProfile(aProfile);
+
+    SendProfileAddedEvent(*aProfile);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::RemoveProfileL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::RemoveProfileL(TUint32 aProfileId)
+
+    {
+    __ASSERT_ALWAYS(iProfileStorage != NULL, User::Leave(KErrLocked));
+
+    CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
+    __ASSERT_ALWAYS(item->ReferenceCount() == 0, User::Leave(KErrInUse));
+
+    iProfileStorage->DeleteSIPProfileL(item->Profile().StorageId());
+
+	CSIPConcreteProfile* defaultProfile = FindDefaultProfile();
+	
+	if ( defaultProfile && defaultProfile->Id() == aProfileId )
+        {
+        TUint32 storageId = iProfileStorage->DefaultProfile();
+
+        if ( storageId )
+            {
+            CSIPConcreteProfile* newDefault = &( ProfileCacheItemByStorageIdL( storageId ).Profile() );
+            newDefault->SetDefault( ETrue );
+            }
+        }
+
+    SendProfileRemovedEventL(*item);
+
+    item->RemoveL();
+
+    if (item->CanBePermanentlyRemoved())
+        {
+        RemoveProfileItem(aProfileId);
+        delete item;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::UpdateProfileToStoreL
+// aProfile has the correct profile id.
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::UpdateProfileToStoreL(
+    CSIPConcreteProfile *aProfile,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    __ASSERT_ALWAYS(iProfileStorage != NULL, User::Leave(KErrLocked));
+
+    CSIPProfileCacheItem* item = ProfileCacheItemL(aProfile->Id());    
+
+	if (aProfile->ServerParameter(
+			KSIPOutboundProxy, KSIPDigestPassword) == KNullDesC8)
+		{
+		const TDesC8& oldPassword( 
+				item->Profile().ServerParameter(
+						KSIPOutboundProxy, KSIPDigestPassword) );
+
+		aProfile->SetServerParameterL( 
+			KSIPOutboundProxy, KSIPDigestPassword, oldPassword);	
+		}
+
+	if (aProfile->ServerParameter(
+			KSIPRegistrar, KSIPDigestPassword) == KNullDesC8)
+		{
+		const TDesC8& oldPassword( 
+				item->Profile().ServerParameter(
+						KSIPRegistrar, KSIPDigestPassword) );
+
+		aProfile->SetServerParameterL( 
+			KSIPRegistrar, KSIPDigestPassword, oldPassword);	
+		}
+
+	aProfile->SetStorageId(item->Profile().StorageId());
+    iProfileStorage->UpdateSIPProfileL(*aProfile);
+
+	if ( aProfile->IsDefault() )
+        {
+        CSIPConcreteProfile* defaultProfile = FindDefaultProfile();
+        
+        if ( defaultProfile && defaultProfile != aProfile )
+        	{
+        	defaultProfile->SetDefault( EFalse );
+        	}
+        }
+	
+    SendProfileUpdatedEventL(*item, *aProfile);
+    
+    return item->CacheOldProfile(aProfile, aObserver);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::Profile
+// -----------------------------------------------------------------------------
+//
+const CSIPConcreteProfile*
+CSIPProfileServerCore::Profile(TUint32 aProfileId) const
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfileId);
+    if (item)
+        {
+        return &item->Profile();
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileDefaultL
+// -----------------------------------------------------------------------------
+//
+const CSIPConcreteProfile* CSIPProfileServerCore::ProfileDefaultL()
+    {
+    __ASSERT_ALWAYS(iProfileStorage != NULL, User::Leave(KErrLocked));
+
+	CSIPProfileCacheItem* item =
+		ProfileCacheItemByStorageId(iProfileStorage->DefaultProfile());
+	if (item)
+        {
+        return &item->Profile();
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileL
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile& CSIPProfileServerCore::ProfileL(TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver) const
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfileId);
+	__ASSERT_ALWAYS(item != NULL && item->IsActiveState(),
+					User::Leave(KErrNotFound));
+    __ASSERT_ALWAYS(!item->IsObserverOrUser(aObserver), User::Leave(KErrInUse));
+
+    item->AddObserverL(aObserver);
+	return item->LatestProfile();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileRefreshL
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile& CSIPProfileServerCore::ProfileRefreshL(TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver) const
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfileId);
+	__ASSERT_ALWAYS(item != NULL && item->IsActiveState(),
+					User::Leave(KErrNotFound));
+    __ASSERT_ALWAYS(item->IsObserverOrUser(aObserver),
+    				User::Leave(KErrArgument));
+	return item->LatestProfile();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CreateProfileL
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile*
+CSIPProfileServerCore::CreateProfileL(const TSIPProfileTypeInfo& aType)
+    {
+    PROFILE_DEBUG1("CreateProfileL")
+
+    return iPluginDirector->CreateProfileL(aType);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfilesByAORL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ProfilesByAORL(const TDesC8& aAOR,
+	const MSIPExtendedConcreteProfileObserver* aObserver,
+	RPointerArray<CSIPConcreteProfile>& aArray) const
+    {
+    for (TInt i = 0; i < iProfileCache.Count(); i++)
+        {
+        if (iProfileCache[i]->HasAorL(aAOR) &&
+        	iProfileCache[i]->IsActiveState())
+            {
+            HandleMatchingProfileL(aObserver, aArray, *iProfileCache[i]);
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::DeleteProfileL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::DeleteProfileL(
+    TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfileId);
+	if (item)
+		{
+		if (item->IsUser(aObserver))
+            {
+            DisableProfileL(aProfileId, aObserver);
+            }
+        item->RemoveObserver(aObserver);
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CanServerStop
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::CanServerStop() const
+    {
+    if (iBackupInProgress || iObservers.Count() > 0)
+        {
+        return EFalse;
+        }
+
+    for (TInt i = 0; i < iProfileCache.Count(); i++)
+        {
+        const CSIPConcreteProfile& profile = iProfileCache[i]->Profile();
+        if ((profile.IsAutoRegistrationEnabled() &&
+             profile.LastRegistrationError() == KErrNone)
+             ||
+             profile.Status() != CSIPConcreteProfile::EUnregistered)
+            {
+            return EFalse;
+            }
+        }
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::BackupInProgress
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::BackupInProgress() const
+    {
+    return iBackupInProgress;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfilesL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ProfilesL(
+	const MSIPExtendedConcreteProfileObserver* aObserver,
+	RPointerArray<CSIPConcreteProfile>& aArray) const
+    {
+    for (TInt i = 0; i < iProfileCache.Count(); i++)
+        {
+		HandleMatchingProfileL(aObserver, aArray, *iProfileCache[i]);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfilesByTypeL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ProfilesByTypeL(
+	const TSIPProfileTypeInfo& aType,                                   
+	const MSIPExtendedConcreteProfileObserver* aObserver,
+	RPointerArray<CSIPConcreteProfile>& aArray) const
+    {
+    for (TInt i = 0; i < iProfileCache.Count(); i++)
+        {
+		const TSIPProfileTypeInfo& type =
+        	iProfileCache[i]->LatestProfile().ProfileType();
+
+        if (aType.iSIPProfileName.Compare(type.iSIPProfileName) == 0 &&
+            aType.iSIPProfileClass == type.iSIPProfileClass &&
+            iProfileCache[i]->IsActiveState())
+            {
+			HandleMatchingProfileL(aObserver, aArray, *iProfileCache[i]);
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::HandleMatchingProfileL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::HandleMatchingProfileL(
+	const MSIPExtendedConcreteProfileObserver* aObserver,
+	RPointerArray<CSIPConcreteProfile>& aArray,
+	CSIPProfileCacheItem& aItem) const
+	{
+    // Append only if the profile state is Active i.e if it not 
+    // requested for the removal
+    if (aItem.IsActiveState())
+    	{
+    	aArray.AppendL(&(aItem.LatestProfile()));        	
+    	}    
+
+    if (aObserver && !aItem.IsObserverOrUser(*aObserver))
+        {
+        aItem.AddObserverL(*aObserver);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::UpdateRegistrationL
+// Second phase of profile update.
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::UpdateRegistrationL(TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
+    CSIPConcreteProfile::TStatus
+    	status(CSIPConcreteProfile::ERegistrationInProgress);
+    if (item->Profile().Status() == CSIPConcreteProfile::ERegistered)
+        {
+        status = CSIPConcreteProfile::EUnregistrationInProgress;
+        }
+
+    TRAPD(err, item->UpdateRegistrationL(aObserver));
+    if (err != KErrNone)
+        {
+        HandleAsyncError(*item, status, err);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::EnableProfileL
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile::TStatus CSIPProfileServerCore::EnableProfileL(
+    TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+	CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
+    iAlrHandler->EnableProfileL(*item, aObserver);
+    return item->Profile().Status();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::DisableProfileL
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile::TStatus CSIPProfileServerCore::DisableProfileL(
+    TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
+    iAlrHandler->DisableProfileL(*item, aObserver);
+    return item->Profile().Status();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ForceDisableProfileL
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile::TStatus CSIPProfileServerCore::ForceDisableProfileL(
+    TUint32 aProfileId,
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
+    (void)aObserver;
+    //When profile state is not unregistered, 
+    //perform cleanup and send event notification
+    
+    if(CSIPConcreteProfile::EUnregistered != item->UsedProfile().Status())
+    	{
+    	PROFILE_DEBUG3("CSIPProfileServerCore::ForceDisableProfileL, Forcibly disabling profile", aProfileId);
+    	item->SwitchToUnregisteredState();
+    	iPluginDirector->TerminateHandling(item->UsedProfile());
+    	item->ClearMigrationProfiles();
+    	iPluginDirector->StartTimerForCleanup();
+    	item->ClearOldProfile();
+    	SendProfileForciblyDisabledEvent(*item);
+    	}
+    return item->Profile().Status();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileUsageL
+// -----------------------------------------------------------------------------
+//
+TInt CSIPProfileServerCore::ProfileUsageL(TUint32 aProfileId) const
+    {
+    return ProfileCacheItemL(aProfileId)->ReferenceCount();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::RegisterProfiles
+// If always-on profile has SNAP, it must obtain an IAP before it can register.
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::RegisterProfiles()
+    {
+    for (TInt i = 0; i < iProfileCache.Count(); i++)
+        {
+        CSIPProfileCacheItem* item = iProfileCache[i];
+        if (item->Profile().IsAutoRegistrationEnabled())
+            {
+			TRAPD(err, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+            if (err != KErrNone)
+                {
+                HandleAsyncError(*item,
+                    			 CSIPConcreteProfile::ERegistrationInProgress,
+                    			 err);
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::LoadProfilesL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::LoadProfilesL(TBool aNotifyProfileCreation)
+    {
+    // Read profiles from cenrep
+    TRAPD(err, iProfileStorage = CSIPProfileStorage::NewL(iFs));
+    HandleProfileStorageErrorL(err);
+
+    RPointerArray<CSIPConcreteProfile>* profiles(NULL);
+    TRAP(err, profiles = iProfileStorage->SIPProfilesL());
+    HandleProfileStorageErrorL(err);
+    if (err != KErrNone)
+        {
+        profiles = iProfileStorage->SIPProfilesL();
+        }
+
+    CleanupStack::PushL(TCleanupItem(ResetAndDestroy, profiles));
+    AddProfilesInCacheL(*profiles, aNotifyProfileCreation);    
+    
+    CleanupStack::Pop(); // TCleanupItem
+    profiles->ResetAndDestroy();
+    delete profiles;
+    
+    // Read profiles from profiles.dat file
+    TRAP(err, profiles = iProfileStorage->SIPProfilesL(ETrue));
+    HandleProfileStorageErrorL(err, ETrue);
+    
+    if (err != KErrNone)
+        {
+        profiles = iProfileStorage->SIPProfilesL(ETrue);
+        }    
+
+    CleanupStack::PushL(TCleanupItem(ResetAndDestroy, profiles));
+    AddProfilesInCacheL(*profiles, aNotifyProfileCreation);
+    
+    
+    CleanupStack::Pop(); // TCleanupItem
+    profiles->ResetAndDestroy();
+    delete profiles;
+    
+
+    RegisterProfiles();    
+    iProfileStorage->GetProfileStorageIndexObject()->SetProfileServerCoreObject(this);
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::AddProfilesInCacheL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::AddProfilesInCacheL(RPointerArray<CSIPConcreteProfile>& profiles,TBool aNotifyProfileCreation)
+	{
+	TInt count = profiles.Count();
+    for (TInt i = 0; i < count; i++) 
+        {
+        CSIPConcreteProfile* profile =
+        	static_cast<CSIPConcreteProfile*>(profiles[0]);
+        CSIPProfileCacheItem* item =
+        	CSIPProfileCacheItem::NewLC(*this, iUnregistered);
+        profiles.Remove(0);
+        item->SetProfile(profile);
+        iProfileCache.AppendL(item);
+        CleanupStack::Pop(item);
+        if (aNotifyProfileCreation)
+            {
+            SendProfileAddedEvent(*profile);
+            }
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::TerminateProfilesL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::TerminateProfilesL()
+    {
+    TInt count = iProfileCache.Count();
+    for (TInt i = 0; i < count; ++i)
+        {
+        iPluginDirector->TerminateHandling(iProfileCache[i]->UsedProfile());
+        SendProfileRemovedEventL(*iProfileCache[i]);
+        }
+    iProfileCache.ResetAndDestroy();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileCacheItemL
+// -----------------------------------------------------------------------------
+//
+CSIPProfileCacheItem*
+CSIPProfileServerCore::ProfileCacheItemL(TUint32 aProfileId) const
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfileId);
+    __ASSERT_ALWAYS(item != NULL, User::Leave(KErrNotFound));
+    return item;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileCacheItem
+// -----------------------------------------------------------------------------
+//
+CSIPProfileCacheItem*
+CSIPProfileServerCore::ProfileCacheItem(TUint32 aProfileId) const
+    {
+    return FindProfileCacheItem(ProfileCached(aProfileId));
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileCached
+// -----------------------------------------------------------------------------
+//
+TInt CSIPProfileServerCore::ProfileCached(TUint32 aProfileId) const
+    {
+    TIdentityRelation<CSIPProfileCacheItem>
+    	compareId(CSIPProfileCacheItem::Compare);
+    iFindEntry->SetProfileId(aProfileId);
+    return iProfileCache.Find(iFindEntry, compareId);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::FindProfileCacheItem
+// -----------------------------------------------------------------------------
+//
+CSIPProfileCacheItem*
+CSIPProfileServerCore::FindProfileCacheItem(TInt aIndex) const
+    {
+    if (aIndex != KErrNotFound)
+        {
+        return static_cast<CSIPProfileCacheItem*>(iProfileCache[aIndex]);
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileCacheItemByStorageIdL
+// -----------------------------------------------------------------------------
+//
+CSIPProfileCacheItem&
+CSIPProfileServerCore::ProfileCacheItemByStorageIdL(TUint32 aStorageId) const
+    {
+    CSIPProfileCacheItem* item = ProfileCacheItemByStorageId(aStorageId);
+    __ASSERT_ALWAYS(item != NULL, User::Leave(KErrNotFound));    
+    return *item;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ProfileCacheItemByStorageId
+// -----------------------------------------------------------------------------
+//
+CSIPProfileCacheItem*
+CSIPProfileServerCore::ProfileCacheItemByStorageId(TUint32 aStorageId) const
+    {
+    for (TInt i = 0; i < iProfileCache.Count(); ++i)
+        {
+        if (iProfileCache[i]->Profile().StorageId() == aStorageId)
+        	{
+        	return iProfileCache[i];
+        	}
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendRegistrationStatusEventL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SendRegistrationStatusEventL(
+    CSIPProfileCacheItem& aItem) const
+    {        
+    SendStatusEventL(aItem, aItem.Profile().Status());
+    iPluginDirector->StartTimerForCleanup();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendUnregisteredStatusEventL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SendUnregisteredStatusEventL(
+    CSIPProfileCacheItem& aItem) const
+    {
+    SendStatusEventL(aItem, CSIPConcreteProfile::EUnregistered);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendStatusEventL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SendStatusEventL(CSIPProfileCacheItem& aItem, 
+	CSIPConcreteProfile::TStatus aStatus) const
+    {
+    CSIPConcreteProfile &profile = aItem.Profile();
+    const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	aItem.Observers();
+
+    for (TInt i = 0; i < obs.Count(); i++)
+        {
+		if(aStatus == CSIPConcreteProfile::EUnregistered)	
+	        obs[i]->RegistrationStatusChangedL(aItem.ProfileId(),
+        								   aStatus,
+                                     	   0);
+		else
+			obs[i]->RegistrationStatusChangedL(aItem.ProfileId(),
+        									   aStatus,
+                	                    	   profile.ContextId());
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendErrorEvent
+// -----------------------------------------------------------------------------
+//
+TInt CSIPProfileServerCore::SendErrorEvent(CSIPProfileCacheItem& item,
+                                           CSIPConcreteProfile::TStatus aStatus,
+                                           TInt aError) const
+    {
+    TInt err(KErrNone);
+    
+    const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	item.Observers();
+
+    for (TInt i = 0; i < obs.Count() && !err; i++)
+        {
+        TRAP(err, obs[i]->ErrorOccurredL(item.ProfileId(), aStatus, aError));
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendProfileAddedEvent
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SendProfileAddedEvent(
+    const CSIPConcreteProfile& aProfile) const
+    {
+    for (TInt i = 0; i < iObservers.Count(); i++)
+        {
+        TRAP_IGNORE(iObservers[i]->AddedL(aProfile.Id()))
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendProfileUpdatedEventL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SendProfileUpdatedEventL(
+    const CSIPProfileCacheItem& aItem,
+    const CSIPConcreteProfile& aProfile) const
+    {
+    const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	aItem.Observers();
+
+    for (TInt i = 0; i < obs.Count(); i++)
+        {
+		obs[i]->UpdatedL(aItem.ProfileId(), aProfile.ExternalizedSizeL());
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SendProfileRemovedEventL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SendProfileRemovedEventL(
+    CSIPProfileCacheItem& aItem) const
+    {
+    const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	aItem.Observers();
+
+    for (TInt i = 0; i < obs.Count(); i++)
+        {
+        obs[i]->RemovedL(aItem.ProfileId());
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SessionCleanupL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SessionCleanupL(
+    const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    TInt index = iObservers.Find(&aObserver);
+    if (index != KErrNotFound)
+        {
+        iObservers.Remove(index);
+        }
+
+    for (TInt i = 0; i < iProfileCache.Count(); i ++)
+        {
+        CSIPProfileCacheItem* item = iProfileCache[i];
+        if (item->IsUser(aObserver))
+            {
+            DisableProfileL(item->ProfileId(), aObserver);
+            }        
+        item->RemoveObserver(aObserver);
+        }
+    iPluginDirector->Cleanup();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ConvertTypeInfoL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ConvertTypeInfoL(
+    const CImplementationInformation& aEcomInfo,
+    TSIPProfileTypeInfo& aInfo) const
+    {
+    TLex8 lex(aEcomInfo.DataType());
+    if (!lex.Peek().IsDigit())
+        {
+        User::Leave(KErrArgument);
+        }
+    TInt id(0);
+    User::LeaveIfError(lex.Val(id));
+    lex.Inc();
+    aInfo.iSIPProfileName = lex.Remainder();
+    aInfo.iSIPProfileClass = (enum TSIPProfileTypeInfo::TSIPProfileClass) id;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CheckServerStatus
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::CheckServerStatus() const
+    {
+    if (CanServerStop())
+        {
+        iServer->ServerCanStop();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::HandleProfileStorageErrorL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::HandleProfileStorageErrorL(TInt aErr, TBool fileStore)
+    {
+    switch (aErr)
+    	{
+    	case KErrNone:
+    		break;
+
+    	case KErrNoMemory:
+    	case KErrInUse: 
+    		User::Leave(aErr);
+    		break;
+
+    	default: 	        	        
+	        if (!fileStore)
+	        	{
+	        	delete iProfileStorage;
+	        	iProfileStorage = NULL;
+	        	CSIPProfileStorage::DeleteAllProfilesL();
+	        	iProfileStorage = CSIPProfileStorage::NewL(iFs);
+	        	}
+	        	else
+	        	{
+	        	// Corrupted sipprofiles.dat file
+	        	iProfileStorage->DeleteAllStreamProfilesL();	        		
+	        	}	        
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ValidateErrorStatus
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile::TStatus
+CSIPProfileServerCore::ValidateErrorStatus(CSIPProfileCacheItem& aItem) const
+    {
+    CSIPConcreteProfile::TStatus status = aItem.Profile().Status();
+    if (status == CSIPConcreteProfile::EUnregistrationInProgress)
+        {
+        return status;
+        }
+    return CSIPConcreteProfile::ERegistrationInProgress;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::HandleAsyncError
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::HandleAsyncError(CSIPProfileCacheItem& aItem, 
+	CSIPConcreteProfile::TStatus aStatus,
+    TInt aError)
+    {
+    TInt err(aError);
+    if (aStatus == CSIPConcreteProfile::EUnregistrationInProgress)
+        {
+        err = KErrNone;
+        }
+
+    if (HandleProfileError(aItem, err))
+    	{
+	    if (err == KErrTotalLossOfPrecision)
+	        {
+	        TRAP_IGNORE(SendUnregisteredStatusEventL(aItem))
+	        }
+	    else
+	        {
+	        SendErrorEvent(aItem, aStatus, aError);
+	        }
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ReleaseStorage
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ReleaseStorage(TBool aRestoreOngoing)
+    {
+    PROFILE_DEBUG1("ProfileServerCore::ReleaseStorage")
+
+    iBackupInProgress = ETrue;
+    TRAPD(err, ReleaseStorageL(aRestoreOngoing));
+
+    if (err != KErrNone)
+        {
+        PROFILE_DEBUG1("ProfileServerCore::ReleaseStorage => failed")
+#ifndef CPPUNIT_TEST
+        User::Panic(KSipProfileCSServerPanic, ERestoreFailure);
+#endif
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ReleaseStorageL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ReleaseStorageL(TBool aRestoreOngoing)
+    {
+    __ASSERT_ALWAYS(iProfileStorage != NULL,
+    				User::Leave(KErrTotalLossOfPrecision));
+
+	if (aRestoreOngoing)
+		{
+		TerminateProfilesL();	
+		}
+
+    delete iProfileStorage;
+    iProfileStorage = NULL;
+    PROFILE_DEBUG1("ProfileServerCore::ReleaseStorageL, storage released")
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ReserveStorage
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ReserveStorage(TBool aRestoreOngoing)
+    {
+    PROFILE_DEBUG1("ProfileServerCore::ReserveStorage")
+
+    iBackupInProgress = EFalse;
+    TRAPD(err, ReserveStorageL(aRestoreOngoing));
+
+    if (err != KErrNone)
+        {
+        PROFILE_DEBUG1("ProfileServerCore::ReserveStorage => failed")
+#ifndef CPPUNIT_TEST
+        User::Panic(KSipProfileCSServerPanic, ERestoreFailure);
+#endif
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ReserveStorageL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ReserveStorageL(TBool aRestoreOngoing)
+    {
+	if (!iProfileStorage)
+		{
+		if (aRestoreOngoing)
+			{
+			LoadProfilesL(ETrue);
+    		CheckServerStatus();
+			}
+		else
+			{
+			// Backup ends. Do not read profiles, as they are already in cache.
+			iProfileStorage = CSIPProfileStorage::NewL(iFs);
+			}
+		PROFILE_DEBUG1("ProfileServerCore::ReserveStorageL, storage reserved")
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ResetAndDestroy
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ResetAndDestroy(TAny* aArray)
+    {
+    RPointerArray<CSIPConcreteProfile>* array =
+    	static_cast<RPointerArray<CSIPConcreteProfile>*> (aArray);
+    array->ResetAndDestroy();
+    delete array;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ResetAndDestroyInfo
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ResetAndDestroyInfo(TAny* aArray)
+    {
+    RPointerArray<CImplementationInformation>* array =
+    	static_cast<RPointerArray<CImplementationInformation>*> (aArray);
+    array->ResetAndDestroy();
+    array->Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CrashRevert
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::CrashRevert(TAny* aItem)
+    {
+    CSIPProfileCacheCleanupItem* item =
+    	static_cast<CSIPProfileCacheCleanupItem*> (aItem);
+    item->CrashRevert();
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::AllowMigrationL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::AllowMigrationL(TUint32 aProfileId,
+	TUint32 aIapId,
+	const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    iAlrHandler->AllowMigrationL(*ProfileCacheItemL(aProfileId),
+    							 aIapId,
+    							 aObserver);
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::DisallowMigrationL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::DisallowMigrationL(TUint32 aProfileId,
+	TUint32 aIapId,
+	const MSIPExtendedConcreteProfileObserver& aObserver)
+    {
+    iAlrHandler->DisallowMigrationL(*ProfileCacheItemL(aProfileId),
+    								aIapId,
+    								aObserver);
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::RefreshIapAvailabilityL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::RefreshIapAvailabilityL(TUint32 aProfileId)
+    {
+    iAlrHandler->RefreshIapAvailabilityL(*ProfileCacheItemL(aProfileId));
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::MigrationStartedL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::MigrationStartedL(const CSIPProfileCacheItem& aItem,
+											  TUint32 aSnapId,
+											  TUint32 aIapId) const
+	{
+	const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	aItem.Observers();
+    for (TInt i = 0; i < obs.Count(); ++i)
+        {
+        obs[i]->MigrationStartedL(aItem.ProfileId(), aSnapId, aIapId);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::MigrationCompletedL
+// -----------------------------------------------------------------------------
+//
+void
+CSIPProfileServerCore::MigrationCompletedL(const CSIPProfileCacheItem& aItem,
+										   TUint32 aSnapId,
+										   TUint32 aIapId) const
+	{
+	const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	aItem.Observers();
+    for (TInt i = 0; i < obs.Count(); ++i)
+        {
+        obs[i]->MigrationCompletedL(aItem.ProfileId(), aSnapId, aIapId);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::PassAlrErrorToClientL
+// -----------------------------------------------------------------------------
+//
+TInt
+CSIPProfileServerCore::PassAlrErrorToClient(const CSIPProfileCacheItem& aItem,
+											TInt aError,
+											TUint32 aSnapId,
+											TUint32 aIapId) const
+	{
+	TInt err(KErrNone);
+	const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+    	aItem.Observers();
+    for (TInt i = 0; i < obs.Count() && !err; ++i)
+        {
+        err = obs[i]->AlrError(aError, aItem.ProfileId(), aSnapId, aIapId);
+        }
+    return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::MigrationControllerL
+// -----------------------------------------------------------------------------
+//
+CSipAlrMigrationController&
+CSIPProfileServerCore::MigrationControllerL(TUint32 aSnapId)
+	{
+	RemoveUnusedMigrationControllers(aSnapId);
+
+	for (TInt i = 0; i < iMigrationControllers.Count(); ++i)
+		{
+		if (iMigrationControllers[i]->SnapId() == aSnapId)
+			{
+			return *iMigrationControllers[i];
+			}
+		}
+
+	CSipAlrMigrationController* ctrl =
+		CSipAlrMigrationController::NewLC(iAlrHandler->AlrMonitorL(), aSnapId);
+	iMigrationControllers.AppendL(ctrl);
+	CleanupStack::Pop(ctrl);
+	return *ctrl;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::UnregisteredState
+// -----------------------------------------------------------------------------
+//
+CSIPProfileState& CSIPProfileServerCore::UnregisteredState()
+	{
+	return *iUnregistered;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::RemoveProfileItem
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::RemoveProfileItem(TUint32 aProfileId)
+	{
+    TInt index = ProfileCached(aProfileId);
+    if (index >= 0)
+    	{
+    	iProfileCache.Remove(index);
+    	}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::RemoveUnusedMigrationControllers
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::RemoveUnusedMigrationControllers(TUint32 aSnapId)
+	{	
+	for (TInt i = iMigrationControllers.Count() - 1; i >= 0; --i)
+		{
+		if (!iMigrationControllers[i]->IsUsed() &&
+			iMigrationControllers[i]->SnapId() != aSnapId)
+			{
+			CSipAlrMigrationController* unused = iMigrationControllers[i];
+			iMigrationControllers.Remove(i);
+			delete unused;
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::GenerateProfileIdL
+// Generate a random profile id (don't use value 0) and check it is not in use.
+// -----------------------------------------------------------------------------
+//
+TUint32 CSIPProfileServerCore::GenerateProfileIdL()
+	{
+	const TInt KProfileIdLength = sizeof(TUint32);
+	HBufC8* buf = HBufC8::NewLC(KProfileIdLength);
+    TPtr8 dataPtr(buf->Des());
+    dataPtr.FillZ(dataPtr.MaxLength());
+	CSystemRandom* random = CSystemRandom::NewLC();
+
+	const TUint32 KEmptyProfileId = 0;
+	TUint32 id(KEmptyProfileId);
+	TBool alreadyUsed(EFalse);
+	do
+		{
+		random->GenerateBytesL(dataPtr);
+
+		const TInt KHighestBytePos 		 = 24;
+		const TInt KSecondHighestBytePos = 16;
+		const TInt KLowestBytePos 		 = 8;
+		id = dataPtr[0] << KHighestBytePos |
+			 dataPtr[1] << KSecondHighestBytePos |
+			 dataPtr[2] << KLowestBytePos |
+			 dataPtr[3];
+		alreadyUsed = EFalse;
+
+		for (TInt i = 0; i < iProfileCache.Count() && !alreadyUsed; ++i)
+	        {
+	        alreadyUsed = (iProfileCache[i]->Profile().Id() == id);
+	        }
+		} while (alreadyUsed || id == KEmptyProfileId);
+
+	CleanupStack::PopAndDestroy(random);
+	CleanupStack::PopAndDestroy(buf);
+	return id;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::LoadSystemStateMonitorL
+// Load first matching plugin. There should be just one.
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::LoadSystemStateMonitorL()
+	{
+	__ASSERT_ALWAYS(!iSystemStateMonitor, User::Leave(KErrAlreadyExists));
+
+	RImplInfoPtrArray infoArray;
+	CleanupStack::PushL(TCleanupItem(ResetAndDestroyInfo, &infoArray));
+	REComSession::ListImplementationsL(KSipSystemStateMonitorIfUid, infoArray);    
+
+	if (infoArray.Count() > 0 && infoArray[0])
+	    {
+		// Create a specific plugin with its UID
+		iSystemStateMonitor = reinterpret_cast<CSipSystemStateMonitor*>(
+			REComSession::CreateImplementationL(
+				infoArray[0]->ImplementationUid(),
+				_FOFF(CSipSystemStateMonitor, iInstanceKey)));
+        PROFILE_DEBUG1("System state monitor loaded")
+  		iSystemStateMonitor->StartMonitoringL(
+  		    CSipSystemStateMonitor::ESystemState, 0, *this);
+		iSystemStateMonitor->StartMonitoringL(
+			CSipSystemStateMonitor::ERfsState, 0, *this);
+	    }
+	CleanupStack::Pop(); // TCleanupItem
+	infoArray.ResetAndDestroy();
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::FindDefaultProfile
+// -----------------------------------------------------------------------------
+//
+CSIPConcreteProfile* CSIPProfileServerCore::FindDefaultProfile() const
+	{
+	const TInt count = iProfileCache.Count();
+	
+	for ( TInt i=0 ; i<count ; ++i )
+		{
+		if ( iProfileCache[i]->ProfileId() && iProfileCache[i]->IsActiveState() )
+			{
+			CSIPConcreteProfile* ptr = &( iProfileCache[i]->LatestProfile() );
+			
+			if ( ptr && ptr->IsDefault() )
+				{
+				return ptr;
+				}
+			}
+		}
+	return NULL;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ShouldChangeIap
+// -----------------------------------------------------------------------------
+// 
+TBool CSIPProfileServerCore::ShouldChangeIap(CSIPConcreteProfile& aProfile, TInt aError) const
+	{
+	PROFILE_DEBUG3("CSIPProfileServerCore::ShouldChangeIap, error", aError)
+	TUint32 dummySnapId(0);	
+	if ( aProfile.ExtensionParameter(KSIPSnapId, dummySnapId) == KErrNone &&
+	     !AnyRegisteredProfileUsesIap(aProfile.IapId()) )
+	    {
+		PROFILE_DEBUG1("CSIPProfileServerCore::ShouldChangeIap, snap is in use")
+
+	    // This profile uses a SNAP.
+	    // There are no registered profiles using the same IAP as this profile.
+	    
+        if ( aError == KErrTimedOut ||
+	         aError == KErrSIPResolvingFailure )
+	        {
+			PROFILE_DEBUG1("CSIPProfileServerCore::ShouldChangeIap returns True")
+	        return ETrue;
+	        }
+	    }
+	PROFILE_DEBUG1("CSIPProfileServerCore::ShouldChangeIap returns false")
+    return EFalse;
+	}
+ 
+TBool CSIPProfileServerCore::AnyRegisteredProfileUsesIap(TUint aIap) const
+    {
+    
+    for ( TInt i = 0; i < iProfileCache.Count(); i++ )
+        {
+        PROFILE_DEBUG3("CSIPProfileServerCore::AnyRegisteredProfileUsesIap, i", i)
+        // Iterate all CSIPProfileCacheItems.
+        if ( iProfileCache[i]->IsActiveState() )
+            {
+            // Cache item is valid.
+            CSIPConcreteProfile& profile = iProfileCache[i]->Profile();
+			PROFILE_DEBUG3("CSIPProfileServerCore::AnyRegisteredProfileUsesIap, profile status", profile.Status())
+			PROFILE_DEBUG4("CSIPProfileServerCore::AnyRegisteredProfileUsesIap, aIap, profile.IapId", aIap, profile.IapId())
+
+            if ( profile.Status() == CSIPConcreteProfile::ERegistered && 
+                 profile.IapId() == aIap )
+                {
+                    // Profile is registered and is using the specified IAP.
+					PROFILE_DEBUG1("CSIPProfileServerCore::AnyRegisteredProfileUsesIap returns True")
+
+                    return ETrue;
+                }
+            }
+        }
+
+	PROFILE_DEBUG1("CSIPProfileServerCore::AnyRegisteredProfileUsesIap returns false")
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// Function is used to send ForciblyDisabled event on the profile to the
+// Profile Agent Client.
+// ----------------------------------------------------------------------------
+void CSIPProfileServerCore::SendProfileForciblyDisabledEvent(
+	const CSIPProfileCacheItem& aItem) const
+    {
+    	//Get the list of observers for a given Profile Item
+    	const RPointerArray<MSIPExtendedConcreteProfileObserver>& obs =
+        	aItem.Observers();
+
+    	//Iterate through the list of observers for that profile item
+    	//and send event to each of them.
+        for (TInt i = 0; i < obs.Count(); i++)
+        	{
+			TRAP_IGNORE(obs[i]->RegistrationStatusChangedL(aItem.ProfileId(),
+						aItem.Profile().Status(), ESipProfileItcOpProfileForciblyDisabled));
+            }
+    }