sipproviderplugins/sipprovider/sipstatemachine/src/StateIdle.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:27:36 +0100
branchRCL_3
changeset 20 0dcb073356a5
parent 0 307788aac0a8
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

// 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:
// CStateIdle implementation file.
// 
//

/**
 @file
 @internalComponent
*/
 
#include <e32std.h>
#include <e32base.h>

#include "StateIdle.h"

CStateIdle * CStateIdle::NewL( CSipStateMachine * aStateMachine )
/**
Instantiaion static function
*/
	{
	return new(ELeave) CStateIdle (aStateMachine);
	}

CStateIdle::CStateIdle ( CSipStateMachine * aStateMachine ) :
CSipStateBase ( aStateMachine, TSipHLConsts::EStateSessionIdle )
/**
Constuctor
*/
	{
	// Open Logs
	__FLOG_OPEN(_L8("SipStateMachine"), _L8("StateIdle"));
	__FLOG_1(_L("[StateIdle]:[%x]::CStateIdle() "), this);
	}
CStateIdle::~CStateIdle ()
/**
Destructor
*/	
	{
	// Close Logging
	__FLOG_0(_L("[StateIdle]: CStateIdle::~CStateIdle()"));
	__FLOG_CLOSE;
	}

CSipStateBase * CStateIdle::ProcessClientL( TRequestStatus & aStatus )
/**
Function which process the request and responses from the client
*/
	{
	__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()"), this);
	// Handle Requests from Client
	switch (iClientRequest)
		{
		case TSipHLConsts::ERequestNone:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()   <<REQUEST NONE>> "), this);
			iSipSM->SetSuspendRequest(ETrue);
			iNext = this;		
			break;
			}
		case TSipHLConsts::ERequestRegister:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()   <<REQUEST REGISTER>> "), this);
			TRAPD(err,iSipSM->SendRegisterMessageL());
			if(err != KErrNone)
				{
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iSipSM->SetGeneralError(err);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				}
			else
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;	
				}
			// Store this because this is required also in the case of failure
			iSipSM->GetTe()->SetTransaction(iSipSM,iSipSM->GetCommandContext().iClientTx);
			break;
			}
		case TSipHLConsts::ERequestInvite:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()   <<REQUEST INVITE>> "), this);
			TRAPD(err,iSipSM->SendInviteMessageL());
			if(err != KErrNone)
				{
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iSipSM->SetGeneralError(err);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				}
			else
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;	
				}
			iSipSM->GetTe()->SetTransaction(iSipSM,iSipSM->GetCommandContext().iClientTx);
			iSipSM->GetTe()->SetDialogAssoc(iSipSM,iSipSM->GetCommandContext().iDialogAssoc);
			break;				
			}
		case TSipHLConsts::ERequestBye:
		case TSipHLConsts::ERequestCancel:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()   <<REQUEST BYE / REQUEST CANCEL>> "), this);
			TRAPD(err,iSipSM->SendCancelL());
			if(err != KErrNone)
				{
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				// Just set the error , as transition to terminated state is automatically happening
				iSipSM->SetGeneralError(err);
				}
			else
				{
				iSipSM->SetSuspendRequest(ETrue);	
				}
			// Change to session terminated as its not sure that we will get 
			// and Response to the cancel while in trying state
			iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
			iNext->ResetRequestResponse();
			}
			break;
		case TSipHLConsts::ERequestSubscribe:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()   <<REQUEST SUBSCRIBE>> "), this);
			TRAPD(err,iSipSM->SendSubscribeMessageL());
			if(err != KErrNone)
				{
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iSipSM->SetGeneralError(err);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				}
			else
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;	
				}
			iSipSM->GetTe()->SetTransaction(iSipSM,iSipSM->GetCommandContext().iClientTx);
			iSipSM->GetTe()->SetDialogAssoc(iSipSM,iSipSM->GetCommandContext().iSubsDialogAssoc);
			}
			break;
		default:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL()   <<REQUEST DEFAULT>> "), this);
			if(iReqIdentifier == 1)
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;
				}
			}
		}
	TRequestStatus * stat = &aStatus;		
	User::RequestComplete(stat,KErrNone);
#ifdef __FLOG_ACTIVE	
	// This indormation is required only when logging is enabled
	TSipHLConsts::SIP_STATES	iD = (iNext != NULL)?iNext->GetStateId() : TSipHLConsts::EStateNone;
	if(iD == KErrNotFound)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL() <<Next State --> NULL>> "), this);
		}
	if(iD == TSipHLConsts::EStateSessionIdle)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL() <<Next State --> StateIdle>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionInitiation)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL() <<Next State --> StateSessionInitiation>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionEstablished)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL() <<Next State --> StateSessionEstablished>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionTerminated)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL() <<Next State --> StateSessionTerminated>> "), this);	
		}
	else
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessClientL() <<Next State --> Unknown, its a serious error>> "), this);		
		}
#endif	
	return iNext;	
	}

CSipStateBase * CStateIdle::ProcessServerL( TRequestStatus & aStatus )
/**
Function which process the request and responses from the Server
*/
	{
	__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()"), this);
	TSipMsgBundle SipMsgBundle = iSipSM->GetSipMessageBundle();
	// Handle response from server
	switch (iServerResponse)
		{
		case TSipHLConsts::EResponseNone:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<RESPONSE NONE>>"), this);
			iSipSM->SetSuspendRequest(ETrue);
			iNext = this;		
			break;	
			}
		case TSipHLConsts::EResponseRegister:
		case TSipHLConsts::EResponseUnRegister:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<RESPONSE REGISTER/ RESPONSE UNREGISTER>>"), this);
			if(SipMsgBundle.iStatusCode == 200)
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionEstablished);
				iNext->ResetRequestResponse();
				}
			else
				{
				iSipSM->SetSIPError(SipMsgBundle.iStatusCode);
				this->SetClientRequest(TSipHLConsts::ERequestNone);
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				iNext->ResetRequestResponse();
				}
			}
			break;
		case TSipHLConsts::EResponseInvite:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<RESPONSE INVITE>>"), this);
			if(SipMsgBundle.iStatusCode == 100)
				{
				__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<100 Trying>>"), this);
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;
				iNext->ResetRequestResponse();
				}
			else if(SipMsgBundle.iStatusCode == 180)	
				{
				__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<180 Trying>>"), this);
				iSipSM->SetSuspendRequest(ETrue);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionInitiation);
				iNext->ResetRequestResponse();
				}
			else // error condition
				{
				__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<Error Condition neither 100 nor 180>>"), this);
				iSipSM->SetSIPError(SipMsgBundle.iStatusCode);
				iSipSM->SetOutgoingStatus(EFalse);
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				iNext->ResetRequestResponse();		
				}
			}
			break;
		case TSipHLConsts::EResponseSubscribe:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<RESPONSE SUBSCRIBE>>"), this);
			if(SipMsgBundle.iStatusCode == 100)
				{
				__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<100 Trying>>"), this);
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;
				iNext->ResetRequestResponse();
				}
			else if(SipMsgBundle.iStatusCode == 200 || SipMsgBundle.iStatusCode == 202)
				{
				__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<200 or 202>>"), this);
				iSipSM->SetOutgoingStatus(EFalse);
				iSipSM->SetSuspendRequest(ETrue);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionEstablished);
				iNext->ResetRequestResponse();
				iSipSM->CallEstablishedCallback();	
				}
			else
				{
				__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<Error neither 100. nore 200 0r 202>>"), this);
				iSipSM->SetSIPError(SipMsgBundle.iStatusCode);
				iSipSM->SetOutgoingStatus(EFalse);
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				iNext->ResetRequestResponse();	
				}
			}
			break;
		default:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<RESPONSE DEFAULT>>"), this);
			if(iReqIdentifier == 4)
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;
				}
			}
		}
	// Handle Request from server
	switch(iServerRequest)
		{
		case TSipHLConsts::ERequestInvite:
			{
			__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<REQUEST INVITE>>"), this);
			iSipSM->GetTe()->SetDialogAssoc(iSipSM,SipMsgBundle.iDialog);
			iSipSM->GetTe()->SetTransaction(iSipSM,SipMsgBundle.iServTransaction);
			iSipSM->GetCommandContext().iDialogAssoc = (CSIPInviteDialogAssoc*)SipMsgBundle.iDialog;
			iSipSM->GetCommandContext().iServerTx = SipMsgBundle.iServTransaction;
			TRAPD(err,iSipSM->GenerateInviteResponseL(iSipSM->GetCommandContext().iServerTx, TSipHLConsts::EResponseRinging));
			if(err != KErrNone)
				{
				iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
				iSipSM->SetGeneralError(err);
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
				}
			else
				{
				// Go to Next State as Session is Intiated
				iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionInitiation);
				iNext->ResetRequestResponse();
				// since user input is required , SM will go to suspended state
				iSipSM->SetSuspendRequest(ETrue);
				// Send Incomin call Notification to User
				iSipSM->CallIncomingCallback();	
				}
			}
			break;
		default:
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL()  <<REQUEST DEFAULT>>"), this);
			if(iReqIdentifier == 2)
				{
				iSipSM->SetSuspendRequest(ETrue);
				iNext = this;
				}
		}
	TRequestStatus * stat = &aStatus;		
	User::RequestComplete (stat , KErrNone);
#ifdef __FLOG_ACTIVE	
	// This indormation is required only when logging is enabled
	TSipHLConsts::SIP_STATES	iD = (iNext != NULL)?iNext->GetStateId() : TSipHLConsts::EStateNone;
	if(iD == TSipHLConsts::EStateNone)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL() <<Next State --> NULL>> "), this);
		}
	if(iD == TSipHLConsts::EStateSessionIdle)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL() <<Next State --> StateIdle>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionInitiation)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL() <<Next State --> StateSessionInitiation>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionEstablished)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL() <<Next State --> StateSessionEstablished>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionTerminated)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL() <<Next State --> StateSessionTerminated>> "), this);	
		}
	else
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerL() <<Next State --> Unknown, its a serious error>> "), this);		
		}
#endif	
	return iNext;
	}
	
CSipStateBase * CStateIdle::ProcessServerErrorL(TRequestStatus & aStatus)
/**
Handles the Error condition for this state from the server
*/
	{
	__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL()"), this);
	TSipMsgBundle SipMsgBundle = iSipSM->GetSipMessageBundle();
	// Call the call back to Notify the client
	iSipSM->SetGeneralError(SipMsgBundle.iErrCode);
	iSipSM->SetSIPError(SipMsgBundle.iStatusCode);
	iSipSM->CallTerminateCallback();
	iSipSM->SetCallTerminateCallBack(EFalse);
	// Get to The terminated state
	iNext = iSipSM->GetNextState(TSipHLConsts::EStateSessionTerminated);
	iSipSM->SetSIPStimulus(TSipHLConsts::EClientStimulus);
	TRequestStatus * stat = &aStatus;		
	User::RequestComplete(stat, KErrNone);
	if(iNext)
	{
	    iNext->ResetRequestResponse();
	}
#ifdef __FLOG_ACTIVE	
	// This indormation is required only when logging is enabled
	TSipHLConsts::SIP_STATES	iD = (iNext != NULL)?iNext->GetStateId() : TSipHLConsts::EStateNone;
	if(iD == KErrNotFound)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL() <<Next State --> NULL>> "), this);
		}
	if(iD == TSipHLConsts::EStateSessionIdle)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL() <<Next State --> StateIdle>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionInitiation)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL() <<Next State --> StateSessionInitiation>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionEstablished)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL() <<Next State --> StateSessionEstablished>> "), this);
		}
	else if(iD == TSipHLConsts::EStateSessionTerminated)
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL() <<Next State --> StateSessionTerminated>> "), this);	
		}
	else
		{
		__FLOG_1(_L("[StateIdle]:CStateIdle[%x]::ProcessServerErrorL() <<Next State --> Unknown, its a serious error>> "), this);		
		}
#endif	
	return iNext;
	}