realtimenetprots/sipfw/ProfileAgent/Server/Src/sipalrmigrationcontroller.cpp
changeset 0 307788aac0a8
child 1 dd3853b8dc3f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/sipalrmigrationcontroller.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,437 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name          : sipalrmigrationcontroller.cpp
+// Part of       : SIP / SIP Profile Server
+// Version       : SIP/6.0 
+//
+
+
+
+#include "sipalrmigrationcontroller.h"
+#include "sipalrmonitor.h"
+#include "sipalrmigrationobserver.h"
+#include "sipalrmigrationobserverinfo.h"
+#include "SipProfileLog.h"
+
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::NewLC
+// -----------------------------------------------------------------------------
+//
+CSipAlrMigrationController*
+CSipAlrMigrationController::NewLC(CSipAlrMonitor& aAlrMonitor, TUint32 aSnapId)
+	{
+	CSipAlrMigrationController* self =
+		new (ELeave) CSipAlrMigrationController(aAlrMonitor, aSnapId);
+    CleanupStack::PushL(self);
+    return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::CSipAlrMigrationController
+// -----------------------------------------------------------------------------
+//
+CSipAlrMigrationController::CSipAlrMigrationController(
+	CSipAlrMonitor& aAlrMonitor,
+	TUint32 aSnapId) :
+	iAlrMonitor(aAlrMonitor),
+    iSnapId(aSnapId)
+#ifdef CPPUNIT_TEST
+    // Set the array granularity to 1, so it allocates memory in each append
+    , iObservers(1)
+#endif
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::~CSipAlrMigrationController
+// -----------------------------------------------------------------------------
+//
+CSipAlrMigrationController::~CSipAlrMigrationController()
+	{
+	PROFILE_DEBUG1("~CSipAlrMigrCtrl")
+
+	iAlrMonitor.FreeResources(*this);
+	iObservers.Close();
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::AlrEvent
+// If migration is disallowed, the original IAP id is offered again.
+// -----------------------------------------------------------------------------
+//
+void CSipAlrMigrationController::AlrEvent(MSipAlrObserver::TEvent aEvent,
+										  TUint32 aSnapId,
+										  TUint32 aIapId)
+	{
+	PROFILE_DEBUG3("CSipAlrMigrationController::AlrEvent", (TInt)(aEvent))
+
+	switch (aEvent)
+		{
+		case MSipAlrObserver::EIapAvailable:
+			if (aIapId == iAllowedIapId)
+				{
+				// Pass the failed IAP to observer, not the original IAP.
+				SendMigrationResult(iOfferedIapId, EFalse);
+				}
+			else
+				{
+				IapAvailable(aSnapId, aIapId);
+				}
+			break;
+
+		case MSipAlrObserver::EIapActive:
+			iAllowedIapId = aIapId;
+			SendMigrationResult(aIapId, ETrue);
+		    break;
+
+		case MSipAlrObserver::ENoNewIapAvailable:
+			NoNewIapAvailable();
+		    break;
+
+		case MSipAlrObserver::ERefreshError:
+			// Start from the end, as RefreshIAPsFailed() causes entries to
+			// remove themselves from the array.
+			for (TInt i = iObservers.Count() - 1; i >= 0; --i)
+				{
+				iObservers[i].iObserver.RefreshIAPsFailed();
+				}
+			break;
+
+		case MSipAlrObserver::EOfferedIapRejected:
+			OfferedIapRejected();
+		    break;
+
+
+        default:
+        	User::Panic(_L("ALRMigrationCtrl::AlrEvent"), KErrArgument);
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::SnapId
+// -----------------------------------------------------------------------------
+//
+TUint32 CSipAlrMigrationController::SnapId() const
+	{
+	return iSnapId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::IsUsed
+// -----------------------------------------------------------------------------
+//
+TBool CSipAlrMigrationController::IsUsed() const
+	{
+	return iObservers.Count() > 0;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::AttachProfileL
+// Initiate monitoring only after first observer exists. Otherwise IAP
+// available event could not be forwarded to observer.
+// -----------------------------------------------------------------------------
+//
+TUint32
+CSipAlrMigrationController::AttachProfileL(MSipAlrMigrationObserver& aObserver)
+    {
+	TSipAlrMigrationObserverInfo observerInfo(aObserver);
+	iObservers.AppendL(observerInfo);
+
+    const TInt KFirstObserverExists = 1;
+    if (iObservers.Count() == KFirstObserverExists)
+    	{
+    	PROFILE_DEBUG3("CSipAlrMigrCtrl::AttachProfileL snapId", iSnapId)
+    	iAlrMonitor.MonitorSnapL(iSnapId, *this);
+    	return KNoIap;
+    	}
+
+    return iAllowedIapId;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::DetachProfile
+// This is typically called from destructors, so don't leave.
+// -----------------------------------------------------------------------------
+//
+void
+CSipAlrMigrationController::DetachProfile(MSipAlrMigrationObserver& aObserver)
+	{
+	TInt index = FindIndex(aObserver);
+	if (index != KErrNotFound)
+		{
+		iObservers.Remove(index);
+		}
+
+	if (iObservers.Count() == 0)
+		{
+		PROFILE_DEBUG1("CSipAlrMigrCtrl::DetachProfile free resources")
+
+		iAlrMonitor.FreeResources(*this);
+		ResetFlags();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::IapAvailable
+// Set all observers "waiting", before using IapAvailable. Even if the first
+// observer syncronously uses SetMigrationPermission, ObserversWaitingPermission
+// returns correct value.
+// If an IAP comes available before each observer has (dis)allowed a previous
+// IAP, pass the new IAP to observers and forget the older IAP.
+// -----------------------------------------------------------------------------
+//
+void
+CSipAlrMigrationController::IapAvailable(TUint32 aSnapId, TUint32 aIapId)
+	{
+	PROFILE_DEBUG4("CSipAlrMigrCtrl::IapAvailable snap,iap", aSnapId, aIapId)
+
+	iOfferedIapId = aIapId;
+	iMigrationDisallowed = EFalse;
+	iRefreshIssued = EFalse;
+
+	for (TInt i = 0; i < iObservers.Count(); ++i)
+		{
+		iObservers[i].iIsWaitingForPermission = ETrue;
+		iObservers[i].iIsWaitingForAcceptance = ETrue;
+		}
+
+	for (TInt i = 0; i < iObservers.Count(); ++i)
+		{
+		iObservers[i].iObserver.IapAvailable(aSnapId, aIapId);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::SetMigrationPermission
+// Handle only the latest IAP. If IAP==EMostRecentIap don't care if the observer
+// has already used SetMigrationPermission. Otherwise do nothing if observer is
+// not waiting, as it has already automatically called SetMigrationPermission.
+// -----------------------------------------------------------------------------
+//
+void CSipAlrMigrationController::SetMigrationPermission(
+	MSipAlrMigrationObserver& aObserver,
+	TBool aAllow,
+	TUint32 aIapId)
+	{
+	PROFILE_DEBUG5("CSipAlrMigrCtrl::SetMigrPermission iap,allow,offeredIap",
+				   aIapId,
+				   aAllow,
+				   iOfferedIapId)
+
+	TInt index = FindIndex(aObserver);
+	// If no pending observers, result has been forwarded. Don't do it twice.
+	if (ObserversWaitingPermission() &&
+	    index != KErrNotFound &&
+	    ((aIapId == EMostRecentIap) ||
+		 (aIapId == iOfferedIapId &&
+		  iObservers[index].iIsWaitingForPermission)))
+		{
+		iObservers[index].iIsWaitingForPermission = EFalse;
+		if (!aAllow)
+			{
+			iMigrationDisallowed = ETrue;
+			}
+
+		if (!ObserversWaitingPermission())
+			{
+			PROFILE_DEBUG3("CSipAlrMigrCtrl::SetMigrPermission, allow=",
+						   !iMigrationDisallowed)
+			TInt err(KErrNone);
+			if (iMigrationDisallowed)
+				{
+				err = iAlrMonitor.DisallowMigration(iSnapId);
+				}
+			else
+				{
+				err = iAlrMonitor.AllowMigration(iSnapId);
+				}
+			if (err != KErrNone)
+				{
+	        	for (TInt i = 0; i < iObservers.Count(); ++i)
+					{
+					iObservers[i].iObserver.ErrorOccurred(err);
+					}
+				}
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::RefreshIapAvailabilityL
+// -----------------------------------------------------------------------------
+//
+void CSipAlrMigrationController::RefreshIapAvailabilityL(TUint32 aSnapId)
+	{
+	if (!iRefreshIssued && aSnapId == iSnapId)
+		{
+		iAlrMonitor.RefreshIapAvailabilityL(aSnapId);
+		iRefreshIssued = ETrue;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::SetIapAcceptance
+// Pass result to ALR monitor if any profile succeeds with new IAP or all failed
+// -----------------------------------------------------------------------------
+//
+TInt CSipAlrMigrationController::SetIapAcceptance(
+	MSipAlrMigrationObserver& aObserver,
+	TBool aIapWorks)
+	{
+	PROFILE_DEBUG4("CSipAlrMigrCtrl::SetIapAcceptance, iap,works=",
+				   iAllowedIapId,
+				   aIapWorks)
+
+	TInt index = FindIndex(aObserver);
+	if (index != KErrNotFound && iObservers[index].iIsWaitingForAcceptance)
+		{
+		iObservers[index].iIsWaitingForAcceptance = EFalse;
+		if (aIapWorks)
+			{
+			// IAP works, no need to wait other observers
+			for (TInt i = 0; i < iObservers.Count(); ++i)
+				{
+				iObservers[i].iIsWaitingForAcceptance = EFalse;
+				}
+			PROFILE_DEBUG1("CSipAlrMigrCtrl::SetIapAcceptance accepted")
+			return iAlrMonitor.NewIapAccepted(iSnapId);
+			}
+
+		if (!ObserversWaitingAcceptance())
+			{
+			// Nobody got IAP to work
+			PROFILE_DEBUG1("CSipAlrMigrCtrl::SetIapAcceptance rejected")
+			return iAlrMonitor.NewIapRejected(iSnapId);
+			}
+		}
+	return KErrNone;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::SendMigrationResult
+// -----------------------------------------------------------------------------
+//
+void
+CSipAlrMigrationController::SendMigrationResult(TUint32 aIapId, TBool aAllowed)
+	{
+	PROFILE_DEBUG5("CSipAlrMigrCtrl::SendMigrationResult iap,allow,obsCount",
+				   aIapId,
+				   aAllowed,
+				   iObservers.Count())	
+
+	for (TInt i = 0; i < iObservers.Count(); ++i)
+		{
+		MSipAlrMigrationObserver& obs = iObservers[i].iObserver;
+		TRAPD(err, if (aAllowed)
+			{
+			obs.MigrationIsAllowedL(aIapId);
+			}
+		else
+			{
+			obs.MigrationIsDisallowedL(aIapId);
+			});
+
+		if (err != KErrNone)
+			{
+			PROFILE_DEBUG4("MigrationIs(Dis)AllowedL leaves err,index", err, i)
+			obs.ErrorOccurred(err);
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::FindIndex
+// -----------------------------------------------------------------------------
+//
+TInt
+CSipAlrMigrationController::FindIndex(MSipAlrMigrationObserver& aObserver) const
+	{
+	TSipAlrMigrationObserverInfo observerInfo(aObserver);
+	TIdentityRelation<TSipAlrMigrationObserverInfo>
+		compare(TSipAlrMigrationObserverInfo::CompareObservers);
+	return iObservers.Find(observerInfo, compare);
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::ObserversWaitingPermission
+// -----------------------------------------------------------------------------
+//
+TBool CSipAlrMigrationController::ObserversWaitingPermission() const
+	{
+	for (TInt i = 0; i < iObservers.Count(); ++i)
+		{
+		if (iObservers[i].iIsWaitingForPermission)
+			{
+			return ETrue;
+			}
+		}
+
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::ObserversWaitingAcceptance
+// -----------------------------------------------------------------------------
+//
+TBool CSipAlrMigrationController::ObserversWaitingAcceptance() const
+	{
+	for (TInt i = 0; i < iObservers.Count(); ++i)
+		{
+		if (iObservers[i].iIsWaitingForAcceptance)
+			{
+			return ETrue;
+			}
+		}
+
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::NoNewIapAvailable
+// -----------------------------------------------------------------------------
+//
+void CSipAlrMigrationController::NoNewIapAvailable() const
+	{
+	for (TInt i = 0; i < iObservers.Count(); ++i)
+		{
+		iObservers[i].iObserver.NoNewIapAvailable();
+		}		
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::ResetFlags
+// -----------------------------------------------------------------------------
+//
+void CSipAlrMigrationController::ResetFlags()
+	{
+	iRefreshIssued = EFalse;
+    iAllowedIapId = KNoIap;
+    iOfferedIapId = KNoIap;
+    iMigrationDisallowed = EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CSipAlrMigrationController::OfferedIapRejected
+// -----------------------------------------------------------------------------
+//
+void CSipAlrMigrationController::OfferedIapRejected() const
+	{
+	// Start from the end, as RefreshIAPsFailed() causes entries to
+	// remove themselves from the array.
+	for (TInt i = iObservers.Count() - 1; i >= 0; --i)
+		{
+		iObservers[i].iObserver.OfferedIapRejected();
+		}
+	}