--- /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));
+ }
+ }