sipproviderplugins/sipprovider/sipconnectionplugins/src/sipscprstates.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:03:15 +0200
changeset 0 307788aac0a8
permissions -rw-r--r--
Revision: 201003 Kit: 201005

// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// SIP SubConnection Provider states/transitions
// 
//

/**
 @file
 @internalComponent
*/

#include "sipdeftscpr.h"
#include "sipscpr.h"
#include "sipscprstates.h"



using namespace ESock;
using namespace NetStateMachine;
using namespace SipSCpr;
using namespace SipSCprStates;


//===========================================
//
//	SIP Sub Connection Provider States
//
//===========================================
namespace SipSCprStates
{

//===================================================================================
//
// StartConnection Activity
//
//====================================================================================

DEFINE_SMELEMENT(TNoTagOrAlreadyStarted,NetStateMachine::MStateFork, SipSCprStates::TContext)
DEFINE_SMELEMENT(TStartSession, NetStateMachine::MStateTransition, SipSCprStates::TContext)
DEFINE_SMELEMENT(TAwaitingSessionEstablished,NetStateMachine::MState, SipSCprStates::TContext)

	
TInt TNoTagOrAlreadyStarted::TransitionTag()
	{
	if(iContext.Node().iStage == SipSCpr::EActive)
		{
		return CoreNetStates::KAlreadyStarted;
		}
	return MeshMachine::KNoTag;
	}

void TStartSession::DoL()
	{
	//check error conditions before starting sip session
	TInt stage = iContext.Node().iStage;
	const Messages::TNodeId& self = iContext.Node().NodeId();
	if(stage != SipSCpr::EFresh)
		{
		switch(stage)
			{
			case SipSCpr::EStopped:
				__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start stopped subconnection")));				
				
            	Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStart,self),TSipSCprMessages::TSipSessionEstablished(KErrAbort).CRef());	
				break;
			case SipSCpr::EStopping:
				__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start stopping subconnection")));				
            	Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStart,self),TSipSCprMessages::TSipSessionEstablished(KErrAbort).CRef());	
				break;
			}
		}		
	
	//In the case of SIP SubConnection, the session params should be be set before we start a call.
	TSipParams& sipParams = iContext.Node().iSipSm->GetSipParams();
	// Check should be made only to non-incoming request. For incoming request the 
	// sipParams won't be set in SIP SCPR. The incoming params will be saved in iParameterBundle
	TInt err;		
	if(!(iContext.Node().iAwaitingSubConnection) && sipParams.iRequest == TSipHLConsts::ERequestNone)
		{
		__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start SIP subconnection if Params are notset")));
		err = KErrNotSupported;		
		}
		else
		{				
		if (iContext.Node().subconType == RSubConnection::EWaitIncoming)
        	{    	
    		__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("appears to be an incoming call subconection, accepting")));
        	err = iContext.Node().iSipSm->AcceptCall();        
        	}
        	else
        	{        
        	err = iContext.Node().iSipSm->StartCall();			        	
        	}		
		}
			
	if (KErrNone != err)
     	{
     	__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot start SIP subconnection if Params are notset")));       	
       	Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStart,self),TSipSCprMessages::TSipSessionEstablished(err).CRef());	
		}
	//Expect Response
	iContext.Node().iActivityAwaitingResponse = iContext.iNodeActivity->ActivityId();       
    iContext.iNodeActivity->SetPostedTo(iContext.Node().NodeId());
	iContext.Node().iStage = SipSCpr::EStarting;
	}	

TBool TAwaitingSessionEstablished::Accept()
	{
	if(iContext.iMessage.IsMessage<TSipSCprMessages::TSipSessionEstablished>())	
		{
		TSipSCprMessages::TSipSessionEstablished* msg = Messages::message_cast<TSipSCprMessages::TSipSessionEstablished>(&iContext.iMessage);
		if (msg->iValue == KErrNone)
			{
			// This means we have a successful session
			iContext.Node().iStage = SipSCpr::EActive;
			return ETrue;
			}
			else
			{
			//session start failed
			//Set the error for activity and will be cleared using TClearError
			TInt error = msg->iValue;
			iContext.iNodeActivity->SetError(error);
			return ETrue;							
			}
		}
	
	return EFalse;
	}

//========================================================================================================
//
// Stop Activiity
//
//========================================================================================================

DEFINE_SMELEMENT(TNoTagOrAlreadyStopped, NetStateMachine::MStateFork, SipSCprStates::TContext)
DEFINE_SMELEMENT(TStopSession, NetStateMachine::MStateTransition, SipSCprStates::TContext)
DEFINE_SMELEMENT(TAwaitingSessionTerminated,NetStateMachine::MState, SipSCprStates::TContext)


TInt TNoTagOrAlreadyStopped::TransitionTag()
	{

	//iStage defined only for non-deft SCPR
	TInt stage = iContext.Node().iStage;
	if (iContext.Node().iStage && iContext.Node().iStage >= SipSCpr::EStopping)
		{
		return CoreNetStates::KAlreadyStopped;	
		}
		return MeshMachine::KNoTag;
	}

void TStopSession::DoL()
	{
	__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("AStopSession::DoL")));		

	//there's no need to check message type before casting as it should've been checked
	//by the State::Accept() => cast & assert if not the desired type
	iContext.Node().iStopCode = Messages::message_cast<TCFServiceProvider::TStop>(iContext.iMessage).iValue;
	TInt err;	
	
	if (iContext.Node().iStage == SipSCpr::EFresh)
	{
		err = KErrNotReady;
	}
	//If this is an incoming call that hasn't been accepted yet. We should
	//reject it. Otherwise we should just stop it.
	else if (iContext.Node().iAwaitingSubConnection && iContext.Node().iStage == SipSCpr::EStarting)
        {
    	err = iContext.Node().iSipSm->RejectCall();
        }
    else
        {
    	err = iContext.Node().iSipSm->StopCall();
        }
    
    if (KErrNone != err)
     	{
     	__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("Cannot stop SIP subconnection if Params are notset")));
       	const Messages::TNodeId& self = iContext.Node().NodeId();
       	Messages::RClientInterface::OpenPostMessageClose(self,Messages::TNodeCtxId(ECFActivityStop,self),TSipSCprMessages::TSipSessionTerminated(err).CRef());	
		}
		
    iContext.Node().iActivityAwaitingResponse = iContext.iNodeActivity->ActivityId();    
    iContext.iNodeActivity->SetPostedTo(iContext.Node().NodeId());
    iContext.Node().iStage = SipSCpr::EStopping;
	}
	
TBool TAwaitingSessionTerminated::Accept()
	{		
	if(iContext.iMessage.IsMessage<TSipSCprMessages::TSipSessionTerminated>())	
		{
		TSipSCprMessages::TSipSessionTerminated* msg = Messages::message_cast<TSipSCprMessages::TSipSessionTerminated>(&iContext.iMessage);
		if (msg->iValue == KErrNone)
			{							
			iContext.Node().iStage = SipSCpr::EStopped;
			return ETrue;
			}		
		else
			{
			//Set the error for activity and will be cleared using TClearError
			TInt error = msg->iValue;
			iContext.iNodeActivity->SetError(error);
			return ETrue;			
			}		
	}
	return EFalse;
	}	


//=================================================================================================
//
//Set Params
//
//==================================================================================================

DEFINE_SMELEMENT(TSetParameters,NetStateMachine::MStateTransition, SipSCprStates::TContext)
void TSetParameters::DoL()
    {	
	TRAPD(err, iContext.Node().DoParametersAboutToBeSetL(iContext.Node().iParameterBundle));
	if(KErrNone != err)
		{
		__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("call to DoParemetersAboutToBeSet failed in ASetParameters::DoL() [error=%d]"), err));
		User::Leave(err);
		}
#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
    iContext.PostToSender(TCFScpr::TSetParamsResponse(iContext.Node().iParameterBundle).CRef());
#else
    iContext.PostToSender(TCFScpr::TParamsResponse(iContext.Node().iParameterBundle).CRef());
#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
    }



DEFINE_SMELEMENT(TStoreProvision, NetStateMachine::MStateTransition, SipSCprStates::TContext)
void TStoreProvision::DoL()
	{
	__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("AStoreProvision::DoL()")));
	PRStates::TStoreProvision storeProvision(iContext);
	storeProvision.DoL();	
	  		
	const TSipCprProvisionInfo* ext = static_cast<const TSipCprProvisionInfo*>(iContext.Node().AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TSipCprProvisionInfo::EUid, TSipCprProvisionInfo::ETypeId)));
	if (ext)
    	{
    	iContext.Node().iTransitionEngine = ext->iTransitionEngine;    	
    	iContext.Node().iFromField = ext->iFromField;
    	
    	// Set the falg for WaitForIncoming connection   	
    	if (iContext.Node().iAwaitingSubConnection)
    		{
    		iContext.Node().iActivityAwaitingResponse = iContext.ActivityId();
    		}    	    	
    	// Create the SIP state machine
    	iContext.Node().CreateStateMachineL();
    	__CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::TStoreProvision() [this=%08x]\t -- SIP State Machine created "), this));
    		
        }
	}   
}//namespace SipSCprStates