sipproviderplugins/sipprovider/sipstatemachine/src/SipStateMachine.cpp
changeset 0 307788aac0a8
child 4 dd3853b8dc3f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sipproviderplugins/sipprovider/sipstatemachine/src/SipStateMachine.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1035 @@
+// 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:
+// CSipStateMachine implementation file.
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+ 
+#include <e32cons.h>
+#include <e32base.h>
+
+#include "SipStateMachine.h"
+#include "StateIdle.h"
+#include "StateSessionInitiation.h"
+#include "StateSessionEstablished.h"
+#include "StateSessionTerminate.h"
+
+EXPORT_C CSipStateMachine * CSipStateMachine::NewL(CSIPTransitionEngine * aTe, MSIPStateMachineClient* aClient, TBool aSMDirection)
+/**
+ SIP State Machine Instantiation function
+*/
+	{
+	CSipStateMachine * SipSm = new(ELeave) CSipStateMachine(aTe, aClient, aSMDirection);
+	CleanupStack::PushL (SipSm);
+	SipSm->ConstructL();
+	CleanupStack::Pop (SipSm);
+	return SipSm;
+	}
+
+void CSipStateMachine::ConstructL()
+/**
+ This Function will startup the state machine with a default
+ state
+*/
+	{
+	// Tell the TE there's another StateMachine wishing to speak to it.
+	// Remek: Where do you remove it??? Cos i couldn't find !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	iTe->AddStateMachineL(this);
+	
+	// Initialize booleans
+	iClientStimulus = EFalse;
+	iServerStimulus = EFalse;
+	iServerErrorStimulus = EFalse;
+	iCallTerminateCallback = ETrue;
+	iDeleteMeNow = EFalse;
+	isInviteSM = EFalse;
+	isSubscribeSM = EFalse;
+	
+	iCallTerminateCode.iErrorCode = KErrNone;
+	iCallTerminateCode.iSipCode = KErrNone;
+	
+	// Construct States
+	iStateIdle = CStateIdle::NewL(this);
+	CleanupStack::PushL (iStateIdle);
+	
+	iCommandCntx.iCommandState 		= iStateIdle;
+	iCommandCntx.iClientTx	 		= NULL;
+	iCommandCntx.iCancelClientTx	= NULL;
+	iCommandCntx.iServerTx			= NULL;
+	iCommandCntx.iRegBinding	 	= NULL;
+	iCommandCntx.iDialogAssoc	 	= NULL;
+
+	
+	iStateSessionInit = CStateSessionInitiation::NewL(this);
+	CleanupStack::PushL(iStateSessionInit);
+	iStateSessionEstablished = CStateSessionEstablished::NewL(this);
+	CleanupStack::PushL(iStateSessionEstablished);
+	iStateSessionTerminate = CStateSessionTerminate::NewL(this);
+	CleanupStack::PushL(iStateSessionTerminate);
+	
+	iActiveState = iStateIdle;
+	
+	this->Start(&iStatus, NULL) ;
+	// Maithra's fix : For stray signal
+ 	MakeActive();
+	// Pop From Cleanup Stack
+	CleanupStack::Pop(4, iStateIdle);
+	}
+	
+CSipStateMachine::CSipStateMachine(CSIPTransitionEngine * aTe, MSIPStateMachineClient* aClient,TBool aSMDirection) 
+:CActive(EPriorityStandard), 
+ iTe(aTe),
+ iClient(aClient),
+ iIncomingStateMachine (aSMDirection)
+/**
+ constructor
+*/
+	{
+	// Open Logs
+	__FLOG_OPEN(_L8("SipStateMachine"), _L8("StateMachine"));
+	__FLOG_1(_L("[SipStateMachine]:[%x]::CSipStateMachine() "), this);
+
+	if(this->IsAdded() == EFalse)
+		{
+		CActiveScheduler::Add(this);
+		}		
+	}
+	
+
+CSipStateMachine::~CSipStateMachine()
+/**
+ destructor
+*/
+	{
+	//Clean-up the iCommand Context
+	Cleanup();
+	iSipMsgBundle.Close();
+	// delete States
+	delete iStateIdle;
+	delete iStateSessionInit;
+	delete iStateSessionEstablished;	
+	delete iStateSessionTerminate;
+	// Close Logging
+	__FLOG_0(_L("[SipStateMachine]: CSipStateMachine::~CSipStateMachine()"));
+	__FLOG_CLOSE;
+	}
+	
+EXPORT_C void CSipStateMachine::DeleteWhenReady()
+/**
+This function will mark the state machine that the CallTerminated callback
+should not be called, and state machine should delete itself gracefully when
+completed the operation
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::DeleteWhenReady()"),this);
+	iClient = NULL;
+	iCallTerminateCallback = EFalse;
+	iDeleteMeNow = ETrue;
+	// send the signal to state machine 
+	if(iActiveState == NULL)
+		{
+		MakeActive();
+		MarkRequestComplete(KErrNone);
+		}
+	}
+	
+EXPORT_C TSipParams & CSipStateMachine::GetSipParams()
+/**
+Returns the SIP parameters
+*/
+ 	{
+ 	return iSipParams;	
+ 	}
+
+EXPORT_C TInt CSipStateMachine::AcceptCall()
+/**
+Accepts and incoming call
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::AcceptCall()"),this);
+	// This will always be invite as of now. The implementation of the function needs
+	// changes when more functionality would be added onto this SM machine to handle more
+	// SIp works
+	isInviteSM = ETrue;
+	return SendSIPResponse(TSipHLConsts::EResponseInvite);
+	}
+
+EXPORT_C TInt CSipStateMachine::StartCall()
+/**
+Start an outgoing call
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::StartCall()"),this);
+	if(iSipParams.iRequest == TSipHLConsts::ERequestInvite)
+		{
+		isInviteSM = ETrue;
+		return SendSIPRequest(TSipHLConsts::ERequestInvite);			
+		}
+	else if(iSipParams.iRequest == TSipHLConsts::ERequestSubscribe)
+		{
+		isSubscribeSM = ETrue;
+		return SendSIPRequest(TSipHLConsts::ERequestSubscribe);			
+		}
+	else
+		{
+		iActiveState = NULL;
+		return KErrNotSupported;			
+		}
+	}
+
+EXPORT_C TInt CSipStateMachine::StopCall()
+/**
+Terminate an established connection
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::StopCall()"),this);
+	if(isSubscribeSM)
+		{
+		return SendSIPRequest(TSipHLConsts::ERequestUnSubscribe);
+		}
+	else if(isInviteSM)
+		{
+		return SendSIPRequest(TSipHLConsts::ERequestBye);	
+		}
+	else
+		{
+		return KErrNotSupported;	
+		}
+	}
+
+EXPORT_C TInt CSipStateMachine::RejectCall()
+/**
+Rejects an incoming call
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::RejectCall()"),this);
+	return SendSIPResponse(TSipHLConsts::EResponseInviteReject);	
+	}
+		
+TInt CSipStateMachine::SendSIPRequest(TSipHLConsts::SIP_REQUESTS aRequest)
+/**
+Sends a SIP request of a particular type 
+*/
+	{
+	if(iActiveState == NULL)
+		return KErrNotReady;
+	iActiveState->ResetRequestResponse();
+	iActiveState->SetClientRequest(aRequest);
+	iClientStimulus = ETrue;
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);   
+    	}
+		
+	MakeActive();
+	MarkRequestComplete(KErrNone);
+	return KErrNone;
+	}
+
+TInt CSipStateMachine::SendSIPResponse(TSipHLConsts::SIP_RESPONSES aResponse)
+/**
+Sends a SIP response of a particular type
+*/
+	{
+	if(iActiveState == NULL)
+    	{
+    	return KErrNotReady;    
+    	}
+		
+	iActiveState->ResetRequestResponse();
+	iActiveState->SetClientResponse(aResponse);
+	iClientStimulus = ETrue;
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);  
+    	}
+		
+	MakeActive();
+	MarkRequestComplete(KErrNone);
+	return KErrNone;
+	}
+
+	
+void CSipStateMachine::Start( TRequestStatus* aClientStatus, CSipStateBase* aErrorState )
+/** 
+Starts the state machine
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::Start()"),this);
+	iClientStatus 	= 	aClientStatus;
+	iErrorState 	= 	aErrorState;
+	iSuspendRequest = 	EFalse;
+
+	if (iClientStatus != NULL)
+    	{
+    	*iClientStatus = KRequestPending;    
+    	}
+	  
+	// we will not call RunL explicitly over here, That means the SM will be 
+	// created in suspended mode.	  
+	}
+	
+void CSipStateMachine::IncomingResponse(TSipMsgBundle aMsgBundle)
+/**
+Handles the incoming response inside a dialog
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingResponse()"),this);
+	iActiveState->ResetRequestResponse();
+	iActiveState->SetServerResponse(aMsgBundle.iResponse);
+	// wake up the State Machine if suspended and pass the response back to the state
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);   
+    	}
+		
+	iServerStimulus = ETrue;
+	iSipMsgBundle.Append(aMsgBundle);
+	MakeActive();
+	MarkRequestComplete(KErrNone);	
+	}
+void CSipStateMachine::IncomingRequestInsideDialog(TSipMsgBundle aMsgBundle)
+/**
+Incoming Request inside established dialog
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingResponseInsideDialog()"),this);
+	iActiveState->ResetRequestResponse();
+	iActiveState->SetServerRequest(aMsgBundle.iRequest);
+	// Delete the earlier server transaction if any as earlier transaction comes on outside a
+	// dialog and not needed as new server transaction that comes with ACK / or inside dialoog
+	// will be used
+	if(iCommandCntx.iServerTx != NULL)
+		{
+		delete iCommandCntx.iServerTx;
+		iCommandCntx.iServerTx = NULL;
+		}
+	// Set the server Transaction
+	iCommandCntx.iServerTx = aMsgBundle.iServTransaction;
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);   
+    	}
+		
+	iServerStimulus = ETrue;
+	iSipMsgBundle.Append(aMsgBundle);
+	MakeActive();
+	MarkRequestComplete(KErrNone);
+	}
+	
+void CSipStateMachine::ErrorOccured(TSipMsgBundle aErrBundle)	
+/**
+Handle the error from TE
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::ErrorOccurred()"),this);
+	iActiveState->ResetRequestResponse();
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);   
+    	}
+		
+	iServerErrorStimulus = ETrue;
+	iSipMsgBundle.Append(aErrBundle);
+	MakeActive();
+	MarkRequestComplete(KErrNone);
+	}
+	
+void CSipStateMachine::InviteCompleted(CSIPClientTransaction& /*aTransaction*/)
+/**
+This callback is called to maek the completion of invite 
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::InviteCompleted()"),this);
+	// we will not match and delete the client transaction as it will be anyway
+	// deleted when a BYE is being sent or received.
+	}
+	
+void CSipStateMachine::IncomingRequest(TSipMsgBundle aMsgBundle)
+/**
+New Incoming request Inside established dialog
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingRequest()"),this);
+	iActiveState->ResetRequestResponse();
+	iActiveState->SetServerRequest(aMsgBundle.iRequest);
+	iSipMsgBundle.Append(aMsgBundle);
+	iServerStimulus = ETrue;
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);    
+    	}
+		
+	MakeActive();
+	MarkRequestComplete(KErrNone);
+	}
+
+void CSipStateMachine::IncomingRequestOutsideDialog(TSipMsgBundle & aMsgBundle)
+/**
+New Incoming request outside any established dialog
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingRequestOutsideDialog()"),this);
+	// set the command context
+	iCommandCntx.iDialogAssoc	= (CSIPInviteDialogAssoc*)aMsgBundle.iDialog;
+	iCommandCntx.iServerTx  	= aMsgBundle.iServTransaction;
+	iActiveState->ResetRequestResponse();
+	iActiveState->SetServerRequest(aMsgBundle.iRequest);
+	iSipMsgBundle.Append(aMsgBundle);
+	iServerStimulus = ETrue;
+	if (iSuspendRequest)
+    	{
+    	SetSuspendRequest(EFalse);    
+    	}
+		
+	MakeActive();
+	MarkRequestComplete(KErrNone);
+	}
+	
+void CSipStateMachine::GenerateInviteResponseL(
+						CSIPServerTransaction *& aTransaction,
+						TSipHLConsts::SIP_RESPONSE_TYPE aType)
+/**
+ */
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL()"),this);
+	switch(aType)
+		{
+		case TSipHLConsts::EResponseRinging:
+			{
+			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<180 Ringing>>"),this);
+			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+							180, SIPStrings::StringF(SipStrConsts::EPhraseRinging));
+			aTransaction->SendResponseL(ResElem);
+			CleanupStack::Pop(ResElem);	
+			}
+			break;
+		case TSipHLConsts::EResponse200OK:
+			{
+			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<200 OK>>"),this);
+			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+							200, SIPStrings::StringF(SipStrConsts::EPhraseOk));
+			aTransaction->SendResponseL(ResElem);
+			CleanupStack::Pop(ResElem);		
+			}
+			break;
+		case TSipHLConsts::EResponseReject:
+			{
+			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<488 Reject>>"),this);
+			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+							488, SIPStrings::StringF(SipStrConsts::EPhraseNotAcceptableHere));
+			aTransaction->SendResponseL(ResElem);
+			CleanupStack::Pop(ResElem);			
+			}
+			break;
+		default:
+			{
+			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<No Response Generated>>"),this);
+			}
+		}
+	
+	}
+	
+void CSipStateMachine::GenerateSubscribeResponseL
+						(CSIPServerTransaction *& aTransaction,
+						TSipHLConsts::SIP_RESPONSE_TYPE aType)
+/**
+ */
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL()"),this);
+	switch(aType)
+		{
+		case TSipHLConsts::EResponse200OK:
+			{
+			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL() <<200 OK>>"),this);
+			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+						200, SIPStrings::StringF(SipStrConsts::EPhraseOk));
+			aTransaction->SendResponseL(ResElem);
+			CleanupStack::Pop(ResElem);		
+			// We will not delete this here , this will be deleted after giving notification
+			// to the client
+			/*
+			delete aTransaction;
+			aTransaction = NULL;
+			*/
+			}
+			break;
+		default:
+			{
+			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL() <<No Response Generated>>"),this);
+			}
+		}
+	}
+	
+HBufC8 * CSipStateMachine::GenerateNotificationData()
+/**
+*/
+	{
+	// Generate the notification parameter from the incoming server Transaction	
+	CSIPServerTransaction *sTran = iCommandCntx.iServerTx;
+	// get the request elements
+	const CSIPRequestElements *reqElems = sTran->RequestElements();
+	// Get the contents of the request elements
+	// Get the Message Elements
+	const CSIPMessageElements & msgElems = reqElems->MessageElements();
+	// Get the content
+	TPtrC8 content = msgElems.Content();
+	HBufC8 * notificationData = NULL;
+	TRAPD(err,notificationData = content.AllocL());
+	if(err != KErrNone)
+		{
+		return NULL;
+		}
+	return notificationData;
+	}
+	
+void CSipStateMachine::RunL()
+/** 
+ * Called on completion of one active event
+ */
+	{
+	if (iStatus.Int() != KErrNone)
+		{
+		OnError();
+		}
+	
+	if (iActiveState)
+		{
+		if (iSuspendRequest)
+			{
+			// do nothing wait for somebody to enable the state machine
+			return;	
+			}
+		else if (iClientStimulus)
+			{
+			iClientStimulus = EFalse;
+			MakeActive();
+			iActiveState = iActiveState->ProcessClientL(iStatus);
+			}
+		else if (iServerStimulus)
+			{
+			iServerStimulus = EFalse;
+			MakeActive();
+			iActiveState = iActiveState->ProcessServerL(iStatus);
+			}
+		else if(iServerErrorStimulus)
+			{
+			iServerErrorStimulus = EFalse;
+			MakeActive();
+			iActiveState = iActiveState->ProcessServerErrorL(iStatus);
+			}
+		else
+			{
+			iSuspendRequest = ETrue;	
+			MakeActive();
+			TRequestStatus *stat = &iStatus;
+			User::RequestComplete(stat,KErrNone);
+			}
+		}
+	else if (iActiveState == NULL && iDeleteMeNow )
+		{
+		// Ask the state machine to delete itself
+		OnCompletion();
+		}
+	else
+		{
+		//do nothing	
+		}
+	}
+
+void CSipStateMachine::OnError()
+/** 
+ * Called from ::RunL when an error occures
+ */
+	{
+	// Put the state machine in suspended mode , and return. 
+	SetSuspendRequest(ETrue);
+	TRequestStatus *stat = &iStatus;
+	User::RequestComplete(stat,KErrNone);
+	}
+
+void CSipStateMachine::OnCompletion()
+/** 
+ * Called by RunL when it is needed to delete the state machine
+ */
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::OnCompletion() <<delete this>>"),this);
+	delete this;
+	}
+
+TInt CSipStateMachine::RunError(TInt aError)
+/** 
+ */
+	{
+	TRequestStatus * Stat = &iStatus;
+	User::RequestComplete( Stat , aError );
+	return KErrNone; 
+	}
+
+void CSipStateMachine::DoCancel()
+/** 
+ */
+	{
+	OnCompletion();
+	}
+
+void CSipStateMachine::MakeActive()
+/**
+ Function call to wake State Machine from Suspended
+ state
+*/	{
+	if(!IsActive())
+    	{
+    	SetActive();   
+    	}
+	}
+	
+void CSipStateMachine::MarkRequestComplete(TInt aErrCode)
+/**
+This function will mimic implicitly calling of the 
+Runl function of the State Machine base
+*/	
+	{
+	TRequestStatus * ThisStat = &iStatus;
+	User::RequestComplete ( ThisStat, aErrCode);
+	}
+	
+CSIPTransitionEngine * CSipStateMachine::GetTe()
+/**
+returns the current instance of TE
+*/
+	{	
+	return iTe;
+	}
+	
+CSipStateBase * CSipStateMachine::GetActiveState()	
+/**
+Return the Currently active state
+*/
+	{
+	return iActiveState;
+	}
+	
+void  CSipStateMachine::CallTerminateCallback()
+/**
+Varifies and call the terminate call back with appropriate values
+*/
+	{
+	__FLOG_2(_L("[SipStateMachine]: CSipStateMachine[%x]::CallTerminateCallback() <<Callback Flag = %d>>"),this,iCallTerminateCallback);
+	if(iCallTerminateCallback)
+		{
+		iClient->CallTerminated(iCallTerminateCode.iErrorCode, iCallTerminateCode.iSipCode);
+		}
+	}
+	
+void CSipStateMachine::CallIncomingCallback()
+/**
+Calls the client with incoming call parameters
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallIncomingCallback()"),this);
+	TIncomingCallParameters inParam;
+	GenerateIncomingCallParameters(inParam);	
+	iClient->IncomingCall(inParam);
+	}
+	
+void CSipStateMachine::CallEstablishedCallback()
+/**
+Notifies the client about the established call
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallEstablishedCallback()"),this);
+	iClient->CallEstablished();
+	}
+	
+void CSipStateMachine::CallNotificationCallback(TPtrC8 aNotifyData)
+/**
+Notifies the client about the incoming notification
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallNotificationCallback()"),this);
+	iClient->ReceiveNotification(aNotifyData);
+	}
+	
+void CSipStateMachine::GenerateIncomingCallParameters(TIncomingCallParameters & aParam)
+/**
+Store the incoming call parameters
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateIncomingCallParameters()"),this);
+	_LIT8(KAtTheRate,"@");
+	
+	CSIPServerTransaction *sTran = iCommandCntx.iServerTx;
+	const CSIPRequestElements *reqElems = sTran->RequestElements();
+	// Get Request Uri
+	const CUri8 & uri = reqElems->RemoteUri();
+	TPtr8 ptrUri = iUriValues.iReqUri.Des();
+		
+	ptrUri.Append(uri.Uri().Extract(EUriUserinfo));
+	ptrUri.Append(KAtTheRate);
+	ptrUri.Append(uri.Uri().Extract(EUriHost));
+	// Set Request Uri
+	aParam.iReqUri.Set(iUriValues.iReqUri);
+	
+	
+	// Get from 
+	const CSIPFromHeader *fromHdr = reqElems->FromHeader();
+	const CUri8 & uriFrom = fromHdr->SIPAddress().Uri8();
+	
+	TPtr8 ptrFrom = iUriValues.iFrom.Des();
+	ptrFrom.Append(uriFrom.Uri().Extract(EUriUserinfo));
+	ptrFrom.Append(KAtTheRate);
+	ptrFrom.Append(uriFrom.Uri().Extract(EUriHost));
+	// Set from
+	aParam.iFrom.Set(iUriValues.iFrom);
+	
+	// Get To
+	const CSIPToHeader *toHdr = reqElems->ToHeader();
+	const CUri8 & uriTo = toHdr->SIPAddress().Uri8();
+	
+	TPtr8 ptrTo = iUriValues.iTo.Des();
+	ptrTo.Append(uriTo.Uri().Extract(EUriUserinfo));
+	ptrTo.Append(KAtTheRate);
+	ptrTo.Append(uriTo.Uri().Extract(EUriHost));
+	// Set To
+	aParam.iTo.Set(iUriValues.iTo);
+	
+	// Get the Message Elements
+	const CSIPMessageElements & msgElems = reqElems->MessageElements();
+	aParam.iContent.Set(msgElems.Content());
+	}
+	
+TBool CSipStateMachine::GetIncomingStatus()
+/**
+Sets whether the state machine is for incoming call
+*/
+	{
+	return iIncomingStateMachine;
+	}
+
+TBool CSipStateMachine::GetOutgoingStatus()
+/**
+sets whether an active outgoing is pending or not
+*/
+	{
+	return isActiveOutgoingSession;
+	}
+	
+void CSipStateMachine::SetOutgoingStatus(TBool aStatus)	
+/**
+Resets the status of active outgoing pending
+*/
+	{
+	isActiveOutgoingSession = aStatus;
+	}
+	
+CSipStateBase * CSipStateMachine::GetNextState (TSipHLConsts::SIP_STATES aNextState)
+	{
+	switch (aNextState)
+		{
+		case TSipHLConsts::EStateSessionIdle:
+			return iStateIdle;
+		case TSipHLConsts::EStateSessionInitiation:
+			return iStateSessionInit;
+		case TSipHLConsts::EStateSessionEstablished:
+			return iStateSessionEstablished;
+		case TSipHLConsts::EStateSessionTerminated:
+			return iStateSessionTerminate;
+		case TSipHLConsts::EStateNone:
+		default:
+			return NULL;
+		}	
+	
+	}
+void CSipStateMachine::Cleanup()
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::Cleanup()"),this);
+	// Cleanup everything in Command Context
+	delete iCommandCntx.iClientTx;
+	iCommandCntx.iClientTx = NULL;
+	
+	delete iCommandCntx.iCancelClientTx;
+	iCommandCntx.iCancelClientTx = NULL;
+	
+	delete iCommandCntx.iRegBinding;
+	iCommandCntx.iRegBinding = NULL;
+	
+	delete iCommandCntx.iClientTx;
+	iCommandCntx.iClientTx = NULL;
+	
+	delete iCommandCntx.iServerTx;
+	iCommandCntx.iServerTx = NULL;
+	
+	delete iCommandCntx.iDialogAssoc;
+	iCommandCntx.iDialogAssoc = NULL;
+	
+	delete iCommandCntx.iSubsDialogAssoc;
+	iCommandCntx.iSubsDialogAssoc = NULL;
+	}
+	
+	
+void CSipStateMachine::SendRegisterMessageL()
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendRegisterMessageL()"),this);
+	// create all the necessary ingredients to send Register Message
+	CSIPRefresh * refresh = CSIPRefresh::NewLC();
+	CSIPToHeader * to 	  = CreateToHeaderLC(iSipParams.iRegParams.iTo);
+	CSIPFromHeader *from  = CreateFromHeaderLC (iSipParams.iRegParams.iFrom);
+	CSIPAddress * addr 	  = CSIPAddress::DecodeL(iSipParams.iRegParams.iContact);
+	CSIPContactHeader * contact = CSIPContactHeader::NewL(addr);
+	CleanupStack::PushL(contact);
+	TUriParser8 parser;
+	User::LeaveIfError(parser.Parse(iSipParams.iRegParams.iRegistrar));
+    CUri8* remoteUri 	  = CUri8::NewLC(parser);   	
+    // Send Registration
+    CSIPConnection * sipConn = GetTe()->GetSipConnection();
+    iCommandCntx.iRegBinding 	= CSIPRegistrationBinding::NewL(
+    							  *sipConn, to, contact,
+    							  refresh,0, remoteUri, from);
+    CleanupStack::PushL(iCommandCntx.iRegBinding);
+	iCommandCntx.iClientTx		= iCommandCntx.iRegBinding->RegisterL();
+	CleanupStack::Pop(6, refresh);
+	}
+	
+void CSipStateMachine::SendUnRegisterMessageL()	
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendUnRegisterMessageL()"),this);
+	if (iCommandCntx.iClientTx != NULL)
+		{
+		delete iCommandCntx.iClientTx;
+		iCommandCntx.iClientTx = NULL;
+		}
+	iCommandCntx.iClientTx = iCommandCntx.iRegBinding->DeregisterL();
+	}
+
+void CSipStateMachine::SendInviteMessageL()
+/**
+Send an invitation to remote phone
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendInviteMessageL()"),this);
+	// set the active outgoing session
+	isActiveOutgoingSession = ETrue;
+	// Get Invite Parameters
+	CSIPToHeader 	* to 	= CreateToHeaderLC(iSipParams.iInvParams.iTo);
+	CSIPFromHeader	* from 	= CreateFromHeaderLC(iSipParams.iInvParams.iFrom);
+	CSIPAddress		* addr 	= CSIPAddress::DecodeL(iSipParams.iInvParams.iContact);
+	CSIPContactHeader * contact = CSIPContactHeader::NewLC(addr);
+	TUriParser8		parser;
+	User::LeaveIfError(parser.Parse(iSipParams.iInvParams.iReqUri));
+	CUri8 *	remoteUri	=	CUri8::NewLC(parser);	
+	CSIPMessageElements* msgElements = NULL;
+
+	// Check whether the content is provided or not, if not no SDP will be genrated	
+	if((iSipParams.iInvParams.iContentType.Length() != 0) &&
+		(iSipParams.iInvParams.iContentSubType.Length() != 0) &&
+		(iSipParams.iInvParams.iContent.Length() != 0))
+		{
+	   // Generate the SDP 
+		SdpCodecStringPool::OpenL();
+		
+		 msgElements = CSIPMessageElements::NewLC();
+		CSIPContentTypeHeader* ct = CSIPContentTypeHeader::NewLC( 
+				iSipParams.iInvParams.iContentType, iSipParams.iInvParams.iContentSubType );
+		CSdpDocument * sdp = CSdpDocument::DecodeLC(iSipParams.iInvParams.iContent);
+		HBufC8* content = GetContentBodyL( sdp );
+		CleanupStack::PushL( content );
+		msgElements->SetContentL( content, ct );
+		CleanupStack::Pop();
+		CleanupStack::Check(sdp);
+		CleanupStack::PopAndDestroy();// for the sdp document.
+		SdpCodecStringPool::Close();
+		}
+	// Create Invite Dialog Association
+	CSIPConnection * sipConn = GetTe()->GetSipConnection();
+	iCommandCntx.iDialogAssoc = CSIPInviteDialogAssoc::NewLC(
+					*sipConn, from, remoteUri, to, contact );
+	iCommandCntx.iClientTx	= iCommandCntx.iDialogAssoc->SendInviteL(msgElements);
+
+	if(msgElements)
+		{
+		CleanupStack::Pop(7, to);
+		}
+	else
+		{
+		CleanupStack::Pop(5, to);
+		}
+	}
+
+void CSipStateMachine::SendAckForInviteL()
+/**
+Send in response to the response of Initial invite request
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendAckForInvite()"),this);
+	iCommandCntx.iDialogAssoc->SendAckL(*(iCommandCntx.iClientTx),NULL);
+	}
+	
+void CSipStateMachine::SendCancelL()
+/**
+Cancels the ongoing session
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendCancelL()"),this);
+	iCommandCntx.iCancelClientTx = iCommandCntx.iClientTx->CancelL();	
+	}
+
+void CSipStateMachine::SendByeL()
+/** 
+Terminates the ongoing session associated with a dialog
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendByeL()"),this);
+	if (iCommandCntx.iClientTx != NULL)
+		{
+		delete iCommandCntx.iClientTx;
+		iCommandCntx.iClientTx = NULL;	
+		}
+	iCommandCntx.iClientTx = iCommandCntx.iDialogAssoc->SendByeL(NULL);
+	}
+
+void CSipStateMachine::SendByeResponseL()
+/**
+Acknoweldge the bye
+*/
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendByeResponseL() <<200 OK>>"),this);
+	CSIPResponseElements* RespElem =  CSIPResponseElements::NewLC( 
+            200, SIPStrings::StringF( SipStrConsts::EPhraseOk ) );
+	iCommandCntx.iServerTx->SendResponseL(RespElem);
+	CleanupStack::Pop(RespElem);	
+	}
+
+HBufC8* CSipStateMachine::GetContentBodyL( CSdpDocument* aContent )
+	{
+	HBufC8* contentBuf = NULL;
+	if ( aContent->IsValid() )
+		{
+		CBufFlat* enBuf = CBufFlat::NewL( 1000 );
+		CleanupStack::PushL( enBuf );
+		RBufWriteStream writeStream;
+		writeStream.Open( *enBuf, 0 );
+		aContent->EncodeL( writeStream );
+		writeStream.Close();
+		TPtr8 ptr = enBuf->Ptr( 0 );
+		contentBuf = ptr.AllocL();
+		CleanupStack::PopAndDestroy( enBuf );
+		writeStream.Close();
+		}
+	return contentBuf;
+	}	
+	
+void CSipStateMachine::SendSubscribeMessageL()
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendSubscribeMessageL()"),this);
+	// set the active outgoing session
+	isActiveOutgoingSession = ETrue;
+	// get Refresh
+	CSIPRefresh* refresh = NULL;
+	if (iSipParams.iSubsParams.iAutoRefresh)
+    	{
+    	refresh = CSIPRefresh::NewLC();
+    	}
+	
+	// SIP Message Elements required for Subscribe
+	CSIPMessageElements* message = CSIPMessageElements::NewLC();
+    RPointerArray<CSIPHeaderBase> headers;
+    CSIPHeaderBase::PushLC(&headers);
+    // Add Expires
+    CSIPExpiresHeader* expires = new(ELeave)CSIPExpiresHeader(iSipParams.iSubsParams.iExpires);
+    CleanupStack::PushL(expires);
+    headers.AppendL(expires);
+    CleanupStack::Pop(expires);
+    // Add Accept 
+    CSIPAcceptHeader* accept = CSIPAcceptHeader::NewLC(
+    				iSipParams.iSubsParams.iAcceptType,iSipParams.iSubsParams.iAcceptSubType);
+    headers.AppendL(accept);
+    CleanupStack::Pop(accept); 
+    // add user headers
+    message->SetUserHeadersL(headers);
+    CleanupStack::Pop(1); // headers
+    headers.Close();
+        
+	
+	CSIPToHeader 	* to 	= CreateToHeaderLC(iSipParams.iSubsParams.iTo);
+	CSIPFromHeader	* from 	= CreateFromHeaderLC(iSipParams.iSubsParams.iFrom);
+	CSIPAddress		* addr 	= CSIPAddress::DecodeL(iSipParams.iSubsParams.iContact);
+	CSIPContactHeader * contact = CSIPContactHeader::NewLC(addr);
+	TUriParser8		parser;
+	User::LeaveIfError(parser.Parse(iSipParams.iSubsParams.iReqUri));
+	CUri8 *	remoteUri	=	CUri8::NewLC(parser);
+	CSIPEventHeader	*evtHdr	= 	CSIPEventHeader::DecodeL(iSipParams.iSubsParams.iEventType);
+	CleanupStack::PushL(evtHdr);
+	CSIPConnection * sipConn = GetTe()->GetSipConnection();
+	// Create subscription to send
+	iCommandCntx.iSubsDialogAssoc = CSIPSubscribeDialogAssoc::NewLC(
+									*sipConn,from,remoteUri,evtHdr,to,contact);
+	iCommandCntx.iClientTx = iCommandCntx.iSubsDialogAssoc->SendSubscribeL(message,refresh);
+	if (refresh)
+    	{
+    	CleanupStack::Pop(8, refresh);   
+    	}
+    else
+        {
+        CleanupStack::Pop(7, message); 
+        }			
+
+	}
+
+void CSipStateMachine::SendUnSubscribeMessageL()
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendUnSubscribeMessageL()"),this);
+	if (iCommandCntx.iClientTx != NULL)
+		{
+		delete iCommandCntx.iClientTx;
+		iCommandCntx.iClientTx = NULL;
+		}
+	iCommandCntx.iClientTx = iCommandCntx.iSubsDialogAssoc->SendUnsubscribeL(NULL);
+	}
+	
+CSIPToHeader* CSipStateMachine::CreateToHeaderLC( const TDesC8& aSipUri )
+	{
+		CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri );
+		CleanupStack::PushL( addr );
+	
+		CSIPToHeader* to = CSIPToHeader::NewL( addr );
+		CleanupStack::Pop( addr );
+		CleanupStack::PushL( to );
+		return to;
+	}
+
+CSIPFromHeader* CSipStateMachine::CreateFromHeaderLC( const TDesC8& aSipUri )
+	{
+		CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri );
+		CleanupStack::PushL( addr );
+	
+		CSIPFromHeader* from = CSIPFromHeader::NewL( addr );
+		CleanupStack::Pop( addr );
+		CleanupStack::PushL( from );
+		return from;
+	}
+	
+	
+void	CSipStateMachine::ChallengeIgnored(const TDesC8& aRealm)
+	{
+	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::ChallengeIgnored()"),this);
+	//Notify SIPSCPR that challenge has been ignored
+	//and credentials need to be set
+	iClient->CredentialsRequired(aRealm);
+	}
+