sipproviderplugins/sipprovider/sipstatemachine/src/transitionengine.cpp
changeset 0 307788aac0a8
child 1 dd3853b8dc3f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sipproviderplugins/sipprovider/sipstatemachine/src/transitionengine.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1092 @@
+// Copyright (c) 2005-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:
+// CSIPTransitionEngine implementation file.
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+ 
+
+#include "transitionengine.h"
+#include "SipStateMachine.h"
+#include <siphlerr.h>
+
+
+CSIPTransitionEngine* CSIPTransitionEngine::NewL(CSIP& aSip, TInt aIapId)
+/**
+Transition Engine Instantiation Function
+*/
+	{	
+	CSIPTransitionEngine * self = new (ELeave) CSIPTransitionEngine(aSip, aIapId);
+	CleanupStack::PushL (self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;	
+	}
+ 
+
+void CSIPTransitionEngine::ConstructL()
+/**
+2nd Phase construction
+*/
+	{
+	__FLOG_1(_L("CSIPTransitionEngine %08x:\tConstructL(), expect 'ConstructL successful', otherwise the method left"), this);
+	ASSERT(iConnection == NULL);
+	
+	// Startup Nokia Stack Related Objects
+	iConnState = CSIPConnection::EInactive;
+
+	__FLOG_1(_L("CSIPTransitionEngine %08x:\tInstantiating CSIPProfileRegistry - may leave"), this);
+	iProfileRegistry = CSIPProfileRegistry::NewL(iSIP, *this);
+	CleanupStack::PushL(iProfileRegistry);
+	__FLOG_1(_L("CSIPTransitionEngine %08x:\tInstantiating CSIPHttpDigest - may leave"), this);
+	iDigest = CSIPHttpDigest::NewL(iSIP, *this );
+	CleanupStack::PushL(iDigest);
+	__FLOG_1(_L("CSIPTransitionEngine %08x:\tInstantiating CSIPConnection - may leave"), this);
+    iConnection = CSIPConnection::NewL(iSIP, iIapId, *this );
+
+	// Wait for the connectio to become Active 
+	if( iConnection->State() == CSIPConnection::EInit )
+		{
+		iActiveWait.Start();
+		}
+		
+	__FLOG_1(_L("CSIPTransitionEngine %08x:\tConstructL successful"), this);		
+    CleanupStack::Pop(2);
+	}
+	
+CSIPTransitionEngine::CSIPTransitionEngine(CSIP& aSip, TInt aIapId)
+:iIapId(aIapId),
+ iSIP(aSip)
+/**
+constructor
+*/
+	{
+	// Open Logs
+	__FLOG_OPEN(_L8("SipStateMachine"), _L8("TransitionEngine"));
+	__FLOG_1(_L("[TransitionEngine]:[%x]::CSIPTransitionEngine() "), this);	
+	}
+	
+	
+CSIPTransitionEngine::~CSIPTransitionEngine()
+/**
+Destructor , cleanup wil be done here
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine [%x]::~CSIPTransitionEngine"), this);
+	// Delete all the State Machines that are there registered
+	// with the TE
+	CHLStateMachine *hlSm = NULL;
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		hlSm = (CHLStateMachine*)iSMArray[count];
+		hlSm->iDialog = NULL;
+		hlSm->iTransaction = NULL;
+		delete hlSm;
+		}
+	iSMArray.Close();
+	
+	// Clean Profiles
+	numElements = iProfileArray.Count();
+	for (TInt count = 0; count<numElements; count++)
+		{
+		CSIPProfile* profile = iProfileArray[count];
+		delete profile;
+		}
+	iProfileArray.Close();
+	
+	//Close RegClientArray
+	//TransitionEngine will be deleted only when no SIPConnProviders are using this
+	iRegClientArray.Close();
+	
+	delete iProfileRegistry;
+	delete iConnection;
+    __FLOG_1(_L("<<completed...>> CSIPTransitionEngine [%x]::~CSIPTransitionEngine"), this);
+	__FLOG_CLOSE;	
+	}
+
+void CSIPTransitionEngine::ConnectionStateChanged( CSIPConnection::TState aState )
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine [%x]::ConnectionStateChanged()"), this);
+	// No Matter what the connection state is become we have to stop the wait
+	if (iActiveWait.IsStarted())
+		{
+			iActiveWait.AsyncStop();
+		}
+	
+	if (iConnState == CSIPConnection::EActive && aState != CSIPConnection::EActive)
+		{
+		//CSIP Connection Lost
+		//Notify all Registration Clients
+		for ( TInt count = 0; count<iRegClientArray.Count(); count++)
+			{
+			iRegClientArray[count]->ErrorOccurred(KErrSIPTransportFailure);
+			}
+			
+		}
+	}
+
+
+void CSIPTransitionEngine::IncomingRequest( CSIPServerTransaction* aTransaction )
+/**
+Incoming request recieved outside a dialog
+*/	
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Recieved Outside of a Dialog>>"),this);
+	CleanupStack::PushL(aTransaction); //we're take over the ownership.
+	
+	RStringF method = aTransaction->RequestElements()->Method();
+	if(method == SIPStrings::StringF(SipStrConsts::EInvite))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Received Request Invite>>"),this);
+		TSipMsgBundle	msgBundle;
+		// Create a dialog Association and set server transaction
+		CSIPInviteDialogAssoc*	dialogassoc = CSIPInviteDialogAssoc::NewL(*aTransaction);
+		CleanupStack::PushL(dialogassoc);
+		msgBundle.iRequest = TSipHLConsts::ERequestInvite;
+		msgBundle.iDialog = dialogassoc;
+		msgBundle.iServTransaction = aTransaction;
+		// Look For the state machine which is responsible for handling 
+	 	// this particular request
+	 	CSipStateMachine*	smPtr = FindSMForIncomingCall();
+	 	if(smPtr)
+	 		{
+	 		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Found State Machine to Handle the Request>>"),this);
+	 		smPtr->IncomingRequestOutsideDialog(msgBundle);	
+	 		CleanupStack::Pop(dialogassoc);
+	 		CleanupStack::Pop(aTransaction);
+	 		}
+	 	else
+	 		{// return NotFound
+	 		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<No State Machine found to Handle the Request>>"),this);
+	 		__FLOG_0(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<sending 404>>"));
+	 		CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+							404, SIPStrings::StringF(SipStrConsts::EPhraseNotFound));
+			aTransaction->SendResponseL(ResElem);
+			CleanupStack::Pop(ResElem);		
+			CleanupStack::PopAndDestroy(aTransaction);
+			CleanupStack::PopAndDestroy(dialogassoc);
+	 		}
+		}
+	 else
+	 	{ // bad request , not supported here
+	 	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Received Request other than Invite>>"),this);
+	 	__FLOG_0(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<sending 404>>"));
+	 	CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+							400, SIPStrings::StringF(SipStrConsts::EPhraseBadRequest));
+		aTransaction->SendResponseL(ResElem);
+		CleanupStack::Pop(ResElem);		
+		CleanupStack::PopAndDestroy(aTransaction);
+	 	}		
+	}
+	
+void CSIPTransitionEngine::IncomingRequest( CSIPServerTransaction* aTransaction, CSIPDialog& aDialog )
+/**
+Incoming request recieved on an established dialog
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Recieved on Established Dialog>>"),this);
+	//find state machine from associated DialogAssoc
+	CSipStateMachine* smPtr = FindStateMachine(aDialog);
+	//Extract Method
+	RStringF method = aTransaction->RequestElements()->Method();
+	TSipMsgBundle msgBundle;
+	
+	if (method == SIPStrings::StringF(SipStrConsts::EInvite))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<INVITE>>"),this);
+		msgBundle.iRequest = TSipHLConsts::ERequestInvite;		
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::EAck))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<ACK>>"),this);
+		msgBundle.iRequest = TSipHLConsts::ERequestAck;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::EBye))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<BYE>>"),this);
+		msgBundle.iRequest = TSipHLConsts::ERequestBye;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::ECancel))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<CANCEL>>"),this);
+		msgBundle.iRequest = TSipHLConsts::ERequestCancel;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::ENotify))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<NOTIFY>>"),this);
+		msgBundle.iRequest = TSipHLConsts::ERequestNotify;
+		}
+	
+	msgBundle.iServTransaction = aTransaction;
+	// Match the state machine which is associated with this message
+	if(smPtr)
+		{
+		__FLOG_0(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Found state machine for handling this request>>"));
+		smPtr->IncomingRequestInsideDialog(msgBundle);	
+		}
+	}
+
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& /*aTransaction*/ )
+	{
+	// We will Not handle this case
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Not HANDLED CASE CALLED < ITS AN ERROR>>"),this);
+	}
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+							   CSIPDialogAssocBase& aDialogAssoc )
+/**
+Incoming Response inside an established dialog is received
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Recieved on Established Dialog>>"),this);
+	CSIPCSeqHeader* CseqHdr = (CSIPCSeqHeader*)aTransaction.ResponseElements()->CSeqHeader();
+	RStringF method = CseqHdr->Method();
+	TSipMsgBundle msgBundle;
+	msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+	msgBundle.iClientTransaction = &aTransaction;
+	
+	if (method == SIPStrings::StringF(SipStrConsts::EInvite))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<INVITE>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseInvite;		
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::EAck))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<ACK>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseAck;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::EBye))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<BYE>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseBye;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::ECancel))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<CANCEL>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseCancel;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::ESubscribe))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<SUBSCRIBE>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseSubscribe;
+		}
+
+	//Find the StateMachine associated with this Dialog
+	CSipStateMachine* smPtr = FindStateMachine(aDialogAssoc);
+	if (smPtr)
+	{
+	//Set the error code in case the status code is 3XX 6XX errors.
+		if(msgBundle.iStatusCode >299)
+		{
+		msgBundle.iErrCode= KErrSIPErrorResponse;
+		smPtr->ErrorOccured(msgBundle);
+		}
+		else
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Found state machine for handling this response>>"),this);
+		smPtr->IncomingResponse(msgBundle);
+		}
+	}	
+}	
+	
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+							   CSIPInviteDialogAssoc* aDialogAssoc )
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Recieved on InviteDialog Assoc>>"),this);
+	CSIPCSeqHeader * CseqHdr = (CSIPCSeqHeader*)aTransaction.ResponseElements()->CSeqHeader();
+	RStringF method = CseqHdr->Method();
+	TSipMsgBundle msgBundle;
+	msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+	
+	if (method == SIPStrings::StringF(SipStrConsts::EInvite))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<INVITE>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseInvite;		
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::EAck))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<ACK>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseAck;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::EBye))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<BYE>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseBye;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::ECancel))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<CANCEL>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseCancel;
+		}
+	else if (method == SIPStrings::StringF(SipStrConsts::ESubscribe))
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<SUBSCRIBE>>"),this);
+		msgBundle.iResponse = TSipHLConsts::EResponseSubscribe;
+		}
+		
+	//Find the StateMachine associated with this Dialog
+	CSipStateMachine* smPtr = FindStateMachine(reinterpret_cast<CSIPDialogAssocBase*>(aDialogAssoc));
+	if (smPtr)
+		{
+		__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Found state machine for handling this response>>"),this);
+		smPtr->IncomingResponse(msgBundle);
+		}
+	}
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+							   CSIPRegistrationBinding& aRegistration )
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Recieved on Registration Assoc>>"),this);
+
+	CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+	if (smPtr)
+		{
+		TSipMsgBundle	msgBundle;
+		if (aRegistration.IsContextActive()) // Registeration Response
+			{
+			__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<REGISTER>>"),this);
+			msgBundle.iResponse = TSipHLConsts::EResponseRegister;
+			msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+			smPtr->IncomingResponse(msgBundle);
+			}
+		else // Unregistration Response
+			{
+			__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<UNREGISTER>>"),this);
+			msgBundle.iResponse = TSipHLConsts::EResponseUnRegister;
+			msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+			smPtr->IncomingResponse(msgBundle);
+			}
+		}
+	}
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+						   CSIPTransactionBase& aTransaction )
+/**
+This function will ask the particular state machine to handle the 
+error
+*/						   
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPTransactionBase& aTransaction)"),this);
+	CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+	if(smPtr)
+		{
+		TSipMsgBundle 	errBundle;
+		errBundle.iErrCode = aError;
+		smPtr->ErrorOccured(errBundle);
+		}
+	}
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+						   CSIPClientTransaction& aTransaction,
+						   CSIPRegistrationBinding& /*aRegistration*/ )
+/**
+Handle errors related to Failed Registration. The registration binding is destroyed by
+the state machine, so need not to be destroyed here
+*/						   
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPTransactionBase& aTransaction, CSIPRegistrationBinding & aRegistration)"),this);
+	CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+	if(smPtr)
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+		TSipMsgBundle msgBundle;
+		msgBundle.iErrCode = aError;
+		msgBundle.iResponse = TSipHLConsts::EResponseRegister;
+		const CSIPResponseElements * resElems = aTransaction.ResponseElements();
+		if(resElems)
+			{
+			msgBundle.iStatusCode = resElems->StatusCode();		
+			}
+		else
+			{
+			msgBundle.iStatusCode = -1;			
+			}
+		msgBundle.iClientTransaction = &aTransaction;
+		smPtr->ErrorOccured(msgBundle);
+		}
+	else
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));	
+		}
+	}
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+						   CSIPTransactionBase& /*aTransaction*/,
+						   CSIPDialogAssocBase& aDialogAssoc)
+/**
+Handles the errors related to failed transaction. No need delete the transaction
+or the dialogassoc , as state machine will delete those upon termination
+*/						   
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPTransactionBase& aTransaction, CSIPDialogAssocBase & aDialogAssoc)"),this);
+	CSipStateMachine* smPtr = FindStateMachine(aDialogAssoc);
+	if(smPtr)
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+		TSipMsgBundle	errBundle;
+		errBundle.iErrCode = aError;
+		// we cant get status code from response
+		errBundle.iStatusCode = -1;	
+		smPtr->ErrorOccured(errBundle);
+		}
+	else
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+		// No State Machine, Nothing to do , SM might have been terminated by some 
+		// other request
+		return;	
+		}
+	}
+
+void CSIPTransitionEngine::ErrorOccured(TInt aError, CSIPRefresh & aSIPRefresh)
+/**
+Handles Errors related to refresh 
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPRefresh & aSIPRefresh)"),this);
+	TSipMsgBundle	errBundle;
+	// Get The state machine associated with this particular Refresh request 
+	const CSIPClientTransaction * clientTnx = aSIPRefresh.SIPTransaction();
+	if(clientTnx)
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+		CSipStateMachine* smPtr = FindStateMachine(clientTnx);
+		if(smPtr)
+			{
+			errBundle.iErrCode = aError;
+			const CSIPResponseElements * resElems = clientTnx->ResponseElements();
+			if(resElems)
+				{
+				errBundle.iStatusCode = resElems->StatusCode();
+				}
+			else
+				{
+				errBundle.iStatusCode = -1;	
+				}
+			smPtr->ErrorOccured(errBundle);
+			}
+		else
+			{
+			// NO SM , nothing to do	
+			}
+		}
+	else
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+		// No Client Transaction , Noting can be done	
+		}
+	}
+	
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+						   CSIPRegistrationBinding& aRegistration)
+/**
+Handles the error occurred with the periodic refreshing of an registration
+binding
+*/						   
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPRegistrationBinding& aRegistration)"),this);
+	TSipMsgBundle	errBundle;
+	// Get The state machine to Handle this condition 
+	CSIPRefresh * refresh = aRegistration.SIPRefresh();
+	if(refresh)
+		{
+		const CSIPClientTransaction *clientTxn = refresh->SIPTransaction();
+		if(clientTxn)
+			{
+			CSipStateMachine* smPtr = FindStateMachine(clientTxn);
+			if(smPtr)
+				{
+				errBundle.iErrCode = aError;
+				const CSIPResponseElements * resElems = clientTxn->ResponseElements();
+				if(resElems)
+					{
+					errBundle.iStatusCode = resElems->StatusCode();
+					}
+				else
+					{
+					errBundle.iStatusCode = -1;	
+					}
+				smPtr->ErrorOccured(errBundle);
+				}
+			else
+				{
+				// NO SM , nothing to do	
+				}
+			}
+		else
+			{
+			// No client Txn , Nothing can be done	
+			}
+		}
+	else
+		{
+		// No Refesh inside nothing can be done	
+		}
+	}
+	
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+						CSIPDialogAssocBase& aDialogAssoc)
+/**
+Handles SIP errors based That happens on a Existing Dialog association
+*/						   
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPDialogAssocBase& aDialogAssoc)"),this);
+	TSipMsgBundle errBundle;
+	// Find the state machine to Handle this error condition
+	CSipStateMachine* smPtr = FindStateMachine(aDialogAssoc);
+	if(smPtr)
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+		errBundle.iErrCode = aError;
+		// we dont have handle to SIP message elements from here
+		errBundle.iStatusCode = -1;	
+		smPtr->ErrorOccured(errBundle);
+		}
+	else
+		{
+		__FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+		// NO SM , nothing to do	
+		}
+	}
+
+void CSIPTransitionEngine::InviteCompleted( CSIPClientTransaction& aTransaction )
+/**
+Handles the case related to the Completion of Invite Request
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::InviteCompleted()"),this);
+	CSipStateMachine*	smPtr = FindStateMachine(aTransaction);
+	smPtr->InviteCompleted(aTransaction);
+	}
+
+
+void CSIPTransitionEngine::InviteCanceled( CSIPServerTransaction& aTransaction )
+/**
+This callback will be called when a incoming Invite is cancelled by the remote machine
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::InviteCanceled()"),this);
+	CSipStateMachine*	smPtr = FindStateMachine(aTransaction);
+	TSipMsgBundle	msgBundle;
+	msgBundle.iServTransaction = &aTransaction;
+	msgBundle.iRequest = TSipHLConsts::ERequestCancel;
+	smPtr->IncomingRequest(msgBundle);
+	}
+
+//From MSIPProfileRegistryObserver
+void CSIPTransitionEngine::ProfileRegistryErrorOccurred(TUint32 aProfileId, TInt aError)
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryErrorOccurred()"),this);
+	//if(iActiveWait.IsStarted())
+    //	iActiveWait.AsyncStop();
+	CSIPProfile* profile = NULL;
+	TUint32 profileId;
+	MSIPRegistrationClient* regClient = FindRegistrationClient(aProfileId);
+	
+	TInt size = iProfileArray.Count();
+	for (TInt count = 0; count<size; count++)
+		{
+		profile = iProfileArray[count];
+		profile->GetParameter(KSIPProfileId, profileId);
+		if (profileId == aProfileId)
+			{
+			iProfileRegistry->Disable(*profile);
+			iProfileArray.Remove(count);
+			delete profile;
+			break;	
+			}
+		}
+
+	//MSIPRegistrationClient* regClient = FindRegistrationClient(aProfileId);
+	if(regClient)
+		{
+		regClient->ErrorOccurred(aError);
+		}
+	}
+	
+void CSIPTransitionEngine::ProfileRegistryEventOccurred(TUint32 aProfileId, TEvent aEvent)
+/**
+Handle the registry event for Registration and Deregistration
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred()"),this);
+	//if(iActiveWait.IsStarted())
+    //	iActiveWait.AsyncStop();
+	
+	TUint32 		profileId;
+	CSIPProfile*	profile = NULL;
+	MSIPRegistrationClient* regClient = FindRegistrationClient(aProfileId);
+	if(regClient == NULL)
+		{
+		_LIT(KSipConnProvPanic, "SIPCPR");
+		User::Panic(KSipConnProvPanic, KSIPProfileNotFound);
+		}
+	switch(aEvent)
+		{
+		case EProfileRegistered: 
+			{
+			__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred()  <<EProfileRegistered>>"),this);
+			regClient->RegistrationComplete(KErrNone);	
+			}
+			break;		
+			
+		case EProfileDeregistered:
+			{
+			__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred()  <<EProfileDeRegistered>>"),this);
+			TInt size = iProfileArray.Count();
+			for (TInt count = 0; count<size; count++)
+				{
+				profile = iProfileArray[count];
+				profile->GetParameter(KSIPProfileId, profileId);
+				if (profileId == aProfileId)
+					{
+					iProfileArray.Remove(count);
+					delete profile;
+					break;	
+					}
+				}
+			regClient->DeRegistrationComplete(KErrNone);	
+			break;
+			}
+		default:
+			{
+			__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred()  <<ERROR..>>"),this);
+			regClient->ErrorOccurred(KErrUnknown);	
+			}
+		}
+				
+	}
+
+CSipStateMachine*	CSIPTransitionEngine::FindStateMachine(CSIPTransactionBase& aTransaction)
+/**
+Finds the associated state machine with the SIP transaction
+*/
+	{
+	for(TInt count = 0;count<iSMArray.Count();count++)
+		{
+		if(*(iSMArray[count]->iTransaction) == aTransaction)
+			{
+			return iSMArray[count]->iStateMachine;
+			}
+		}
+	return NULL;
+	};
+
+CSipStateMachine*	CSIPTransitionEngine::FindStateMachine(const CSIPTransactionBase* aTransaction)
+/**
+Finds the associated state machine with the SIP transaction
+*/
+	{
+	for(TInt count = 0;count<iSMArray.Count();count++)
+		{
+		if(iSMArray[count]->iTransaction == aTransaction)
+			{
+			return iSMArray[count]->iStateMachine;
+			}
+		}
+	return NULL;
+	};
+
+CSipStateMachine*	CSIPTransitionEngine::FindStateMachine(CSIPDialogAssocBase* aDialogAssoc)
+/**
+Finds the associated state machine with the SIP Dialog
+*/
+	{
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		if (iSMArray[count]->iDialog == aDialogAssoc)
+			{
+			return iSMArray[count]->iStateMachine;
+			}
+		}
+	return NULL;
+	
+	};
+
+
+CSipStateMachine*	CSIPTransitionEngine::FindStateMachine(CSIPDialog& aDialog)
+/**
+Finds the associated state machine with the SIP Dialog
+*/
+	{
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		if(aDialog.IsAssociated(*(iSMArray[count]->iDialog)))
+			{
+			return iSMArray[count]->iStateMachine;
+			}
+		}
+	return NULL;	
+	};
+
+	
+CSipStateMachine*	CSIPTransitionEngine::FindStateMachine(CSIPDialogAssocBase& aDialogAssoc)
+/**
+Finds the associated state machine with the SIP Dialog Assocition
+*/
+	{
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		if (iSMArray[count]->iDialog == &aDialogAssoc)
+			{
+			return iSMArray[count]->iStateMachine;
+			}
+		}
+	return NULL;
+	};
+
+EXPORT_C void CSIPTransitionEngine::AddStateMachineL(CSipStateMachine* aStateMachine)
+/**
+Using this call The client will register the state machine with the Transition 
+Engine
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::AddStateMachineL()"),this);
+	CHLStateMachine *hlSm = new(ELeave) CHLStateMachine;
+	hlSm->iStateMachine = aStateMachine;
+	hlSm->iDialog		= NULL;
+	hlSm->iTransaction  = NULL;
+	iSMArray.AppendL(hlSm);
+	}
+
+void CSIPTransitionEngine::Cleanup(CSipStateMachine * aStateMachine)
+/**
+Handles the cleanup related to the transition Engine
+*/
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::Cleanup()"),this);
+	CHLStateMachine *hlSm = NULL;
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		if (iSMArray[count]->iStateMachine == aStateMachine)
+			{
+			hlSm = (CHLStateMachine*)iSMArray[count];
+			hlSm->iDialog = NULL;
+			hlSm->iTransaction = NULL;
+			delete hlSm;
+			}
+		}
+	}
+	
+	
+void	CSIPTransitionEngine::SetTransaction(CSipStateMachine* aStateMachine, CSIPTransactionBase* aTransaction)
+/**
+Sets The transaction for a particular state machine
+*/
+	{
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		if (iSMArray[count]->iStateMachine == aStateMachine)
+			{
+			iSMArray[count]->iTransaction = aTransaction;
+			}
+		}
+	}
+
+void	CSIPTransitionEngine::SetDialogAssoc(CSipStateMachine* aStateMachine, CSIPDialogAssocBase* aDialoAssoc)
+/**
+Sets the dialog association for a particular state machine
+*/
+	{
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count++)
+		{
+		if (iSMArray[count]->iStateMachine == aStateMachine)
+			{
+			iSMArray[count]->iDialog = aDialoAssoc;
+			}
+		}
+	}
+
+CSipStateMachine *  CSIPTransitionEngine::FindSMForIncomingCall()
+/**
+Find the empty state machine for handling the incoming calls
+*/
+	{
+	TInt numElements = iSMArray.Count();
+	for(TInt count=0; count<numElements; count ++)
+		{
+		if(iSMArray[count]->iTransaction == NULL && iSMArray[count]->iDialog == NULL)
+			{
+			// Check if this empty state machine is for incoming
+			if(iSMArray[count]->iStateMachine->GetIncomingStatus())
+				{
+				return iSMArray[count]->iStateMachine;
+				}
+			}
+		}
+	return NULL;
+	}
+	
+
+EXPORT_C void  CSIPTransitionEngine::RegisterL(MSIPRegistrationClient* aRegistrationClient)
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::RegisterL()"),this);	
+	TUint32 profileId = aRegistrationClient->GetProfileId();
+	CSIPProfile* profile = NULL;
+	iRegClientArray.AppendL(aRegistrationClient);
+	
+	TInt err = KErrNone;
+	if(profileId == KSIPDefaultProfileId)
+		{
+		TRAP(err,profile = iProfileRegistry->DefaultProfileL());
+		}
+	else
+		{
+		TRAP(err, profile = iProfileRegistry->ProfileL(profileId));	
+		}
+	if(err != KErrNone)
+		{
+    	__FLOG_2(_L("CSIPTransitionEngine %08x:The profile [%d] hasn't been found, aborting..."), this, profileId);
+		User::Leave(KSIPProfileNotFound);
+		}
+	if (!iProfileRegistry->IsEnabled(*profile))
+		{
+    	__FLOG_2(_L("CSIPTransitionEngine %08x:The profile [%d] found, enabling..."), this, profileId);
+		TRAP(err,iProfileRegistry->EnableL( *profile, *this ));
+		if(err != KErrNone)
+			{
+			User::Leave(KSIPProfileNotFound);
+			}
+		iProfileArray.AppendL(profile);
+		}
+	}
+	
+
+EXPORT_C void  CSIPTransitionEngine::Deregister(MSIPRegistrationClient* aRegistrationClient)
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::Deregister()"),this);	
+	TUint32 regProfId = aRegistrationClient->GetProfileId();
+	TUint32 profileId;
+	CSIPProfile* profile;
+	TInt size = iProfileArray.Count();
+	
+	for (TInt count = 0; count<size; count++)
+		{
+		profile = iProfileArray[count];
+		profile->GetParameter(KSIPProfileId, profileId);
+		if (profileId == regProfId)
+			{
+			iProfileRegistry->Disable(*profile);
+			break;		
+			}
+		}
+	}
+	
+	
+EXPORT_C TUint32  CSIPTransitionEngine::FindDuplicateProfile(TUint32 aProfileId)
+	{
+	__FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::FindDuplicateProfile()"),this);	
+	// IAP,Registrar,User AOR,Contacts, Proxy, Digest User Name, Digest Realm, SecMechanism
+	if (aProfileId == KSIPInvalidProfileId)
+		{
+		return KSIPInvalidProfileId;
+		}
+	
+	CSIPProfile* profile = NULL;
+	TRAPD(err,	profile = iProfileRegistry->ProfileL(aProfileId));
+	
+	if (err != KErrNone)
+		{
+		return KErrNone;
+		}
+	
+	TUint32	thisIapId;
+	TUint32 thisProfileId;
+	const TDesC8*	thisAor = NULL;
+	const TDesC8*	thisRegistrar = NULL;
+	const TDesC8*	thisProxy = NULL;
+	const TDesC8*	thisRegRealm = NULL;
+	const TDesC8*	thisProxyRealm = NULL;
+	const TDesC8*	thisRegUser = NULL;
+	const TDesC8*	thisProxyUser = NULL;
+	
+	profile->GetParameter(KSIPProfileId, thisProfileId);
+	profile->GetParameter(KSIPAccessPointId, thisIapId);
+	profile->GetParameter(KSIPUserAor, thisAor);
+	profile->GetParameter(KSIPRegistrar,KSIPServerAddress, thisRegistrar);
+	profile->GetParameter(KSIPOutboundProxy,KSIPServerAddress, thisProxy);
+	profile->GetParameter(KSIPRegistrar,KSIPDigestRealm, thisRegRealm);
+	profile->GetParameter(KSIPRegistrar,KSIPDigestUserName, thisRegUser);
+	profile->GetParameter(KSIPOutboundProxy,KSIPDigestRealm, thisProxyRealm);
+	profile->GetParameter(KSIPOutboundProxy,KSIPDigestUserName, thisProxyUser);
+	
+					 	
+	TInt size = iProfileArray.Count();
+		
+	TUint32	iapId;
+	TUint32 profileId;
+	const TDesC8*	aor = NULL;
+	const TDesC8*	registrar = NULL;
+	const TDesC8*	proxy = NULL;
+	const TDesC8*	regRealm = NULL;
+	const TDesC8*	proxyRealm = NULL;
+	const TDesC8*	regUser = NULL;
+	const TDesC8*	proxyUser = NULL;
+	
+	//Iterate through profiles in iProfileArray
+	//and match
+	
+	for (TInt count=0; count<size; count++)
+		{
+		iProfileArray[count]->GetParameter(KSIPProfileId, profileId);
+		if (profileId == thisProfileId)
+			{
+			//profile Id for an existing profile was passed
+			return profileId;
+			}
+		iProfileArray[count]->GetParameter(KSIPAccessPointId, iapId);
+		if (iapId != thisIapId)
+			{
+		    continue;
+			}
+		iProfileArray[count]->GetParameter(KSIPUserAor, aor);
+		if (aor != thisAor)
+			{
+		    continue;
+			}
+		
+		iProfileArray[count]->GetParameter(KSIPRegistrar,KSIPServerAddress, registrar);
+		if (registrar != thisRegistrar)
+			{
+			continue;
+			}
+			
+		iProfileArray[count]->GetParameter(KSIPOutboundProxy,KSIPServerAddress, proxy);
+		if (proxy != thisProxy)
+			{
+			continue;
+			}
+		
+		iProfileArray[count]->GetParameter(KSIPRegistrar,KSIPDigestRealm, regRealm);
+		if(regRealm != thisRegRealm)
+			{
+			continue;
+			}
+		iProfileArray[count]->GetParameter(KSIPOutboundProxy,KSIPDigestRealm, proxyRealm);
+		if (proxyRealm != thisProxyRealm)
+			{
+			continue;
+			}
+		iProfileArray[count]->GetParameter(KSIPRegistrar,KSIPDigestUserName, regUser);
+		if (regUser != thisRegUser)
+			{
+			continue;
+			}
+		
+		iProfileArray[count]->GetParameter(KSIPOutboundProxy,KSIPDigestUserName, proxyUser);
+		if (proxyUser != thisProxyUser)
+			{
+			continue;
+			}
+		//Duplicate profile found
+		return profileId;
+		}
+		
+	return KSIPInvalidProfileId;
+	}
+	
+	
+
+EXPORT_C void CSIPTransitionEngine::AddCredentialsL(TSIPCredentials aCredential)
+	{
+	iCredentialsArray.AppendL(aCredential);
+	}
+	
+EXPORT_C const TDesC8* CSIPTransitionEngine::GetFromField(TUint32 aProfileId) const
+    {
+	TInt size = iProfileArray.Count();
+	CSIPProfile* profile = NULL;
+    const TDesC8* userName = NULL;
+    TUint32 profileId = KSIPInvalidProfileId;
+	
+	for (TInt count = 0; count<size; count++)
+		{
+		profile = iProfileArray[count];
+		profile->GetParameter(KSIPProfileId, profileId);
+		if (profileId == aProfileId)
+			{
+			profile->GetParameter(KSIPUserAor, userName);
+			}
+		}
+	return userName;
+    }	
+	
+	
+MSIPRegistrationClient*	CSIPTransitionEngine::FindRegistrationClient(TUint32 aProfileId)
+	{
+	TInt size = iRegClientArray.Count();
+	for (TInt count = 0; count<size; count++)
+		{
+		if(aProfileId == iRegClientArray[count]->GetProfileId())
+			{
+			return iRegClientArray[count];
+			}
+		}
+		return NULL;
+	}
+
+//From MSIPHttpDigestChallengeObserver
+void CSIPTransitionEngine::ChallengeReceived(const TDesC8& aRealm)
+	{
+	//Walkthrough the list of Realms to find credentials
+	if (!FindAndSetCredentials(aRealm))
+		{
+		TInt size = iSMArray.Count();
+		//Walk through State Machines and find the current outgoing active state machine
+		for (TInt count=0; count<size; count++)
+			{
+			CSipStateMachine* smPtr= iSMArray[count]->iStateMachine;
+			if(!smPtr->GetIncomingStatus() && smPtr->GetOutgoingStatus())
+				{
+				iDigest->IgnoreChallenge(aRealm);
+				smPtr->ChallengeIgnored(aRealm);
+				}
+			}
+		}
+	
+	}
+	
+	
+TBool CSIPTransitionEngine::FindAndSetCredentials(const TDesC8& aRealm)
+	{
+	TInt size = iCredentialsArray.Count();
+	
+	for (TInt count=0; count<size; count++)
+		{
+		if (aRealm == iCredentialsArray[count].iRealm)
+			{
+			TRAPD(err, iDigest->SetCredentialsL(iCredentialsArray[count].iRealm,
+												iCredentialsArray[count].iUserName,
+												iCredentialsArray[count].iPasswd));
+			if(err != KErrNone)
+				{
+				return ETrue;
+				}
+			}
+		}
+	return EFalse;
+	}