sipproviderplugins/sipprovider/sipstatemachine/src/SipStateMachine.cpp
changeset 0 307788aac0a8
child 4 dd3853b8dc3f
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // CSipStateMachine implementation file.
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22  
       
    23 #include <e32cons.h>
       
    24 #include <e32base.h>
       
    25 
       
    26 #include "SipStateMachine.h"
       
    27 #include "StateIdle.h"
       
    28 #include "StateSessionInitiation.h"
       
    29 #include "StateSessionEstablished.h"
       
    30 #include "StateSessionTerminate.h"
       
    31 
       
    32 EXPORT_C CSipStateMachine * CSipStateMachine::NewL(CSIPTransitionEngine * aTe, MSIPStateMachineClient* aClient, TBool aSMDirection)
       
    33 /**
       
    34  SIP State Machine Instantiation function
       
    35 */
       
    36 	{
       
    37 	CSipStateMachine * SipSm = new(ELeave) CSipStateMachine(aTe, aClient, aSMDirection);
       
    38 	CleanupStack::PushL (SipSm);
       
    39 	SipSm->ConstructL();
       
    40 	CleanupStack::Pop (SipSm);
       
    41 	return SipSm;
       
    42 	}
       
    43 
       
    44 void CSipStateMachine::ConstructL()
       
    45 /**
       
    46  This Function will startup the state machine with a default
       
    47  state
       
    48 */
       
    49 	{
       
    50 	// Tell the TE there's another StateMachine wishing to speak to it.
       
    51 	// Remek: Where do you remove it??? Cos i couldn't find !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    52 	iTe->AddStateMachineL(this);
       
    53 	
       
    54 	// Initialize booleans
       
    55 	iClientStimulus = EFalse;
       
    56 	iServerStimulus = EFalse;
       
    57 	iServerErrorStimulus = EFalse;
       
    58 	iCallTerminateCallback = ETrue;
       
    59 	iDeleteMeNow = EFalse;
       
    60 	isInviteSM = EFalse;
       
    61 	isSubscribeSM = EFalse;
       
    62 	
       
    63 	iCallTerminateCode.iErrorCode = KErrNone;
       
    64 	iCallTerminateCode.iSipCode = KErrNone;
       
    65 	
       
    66 	// Construct States
       
    67 	iStateIdle = CStateIdle::NewL(this);
       
    68 	CleanupStack::PushL (iStateIdle);
       
    69 	
       
    70 	iCommandCntx.iCommandState 		= iStateIdle;
       
    71 	iCommandCntx.iClientTx	 		= NULL;
       
    72 	iCommandCntx.iCancelClientTx	= NULL;
       
    73 	iCommandCntx.iServerTx			= NULL;
       
    74 	iCommandCntx.iRegBinding	 	= NULL;
       
    75 	iCommandCntx.iDialogAssoc	 	= NULL;
       
    76 
       
    77 	
       
    78 	iStateSessionInit = CStateSessionInitiation::NewL(this);
       
    79 	CleanupStack::PushL(iStateSessionInit);
       
    80 	iStateSessionEstablished = CStateSessionEstablished::NewL(this);
       
    81 	CleanupStack::PushL(iStateSessionEstablished);
       
    82 	iStateSessionTerminate = CStateSessionTerminate::NewL(this);
       
    83 	CleanupStack::PushL(iStateSessionTerminate);
       
    84 	
       
    85 	iActiveState = iStateIdle;
       
    86 	
       
    87 	this->Start(&iStatus, NULL) ;
       
    88 	// Maithra's fix : For stray signal
       
    89  	MakeActive();
       
    90 	// Pop From Cleanup Stack
       
    91 	CleanupStack::Pop(4, iStateIdle);
       
    92 	}
       
    93 	
       
    94 CSipStateMachine::CSipStateMachine(CSIPTransitionEngine * aTe, MSIPStateMachineClient* aClient,TBool aSMDirection) 
       
    95 :CActive(EPriorityStandard), 
       
    96  iTe(aTe),
       
    97  iClient(aClient),
       
    98  iIncomingStateMachine (aSMDirection)
       
    99 /**
       
   100  constructor
       
   101 */
       
   102 	{
       
   103 	// Open Logs
       
   104 	__FLOG_OPEN(_L8("SipStateMachine"), _L8("StateMachine"));
       
   105 	__FLOG_1(_L("[SipStateMachine]:[%x]::CSipStateMachine() "), this);
       
   106 
       
   107 	if(this->IsAdded() == EFalse)
       
   108 		{
       
   109 		CActiveScheduler::Add(this);
       
   110 		}		
       
   111 	}
       
   112 	
       
   113 
       
   114 CSipStateMachine::~CSipStateMachine()
       
   115 /**
       
   116  destructor
       
   117 */
       
   118 	{
       
   119 	//Clean-up the iCommand Context
       
   120 	Cleanup();
       
   121 	iSipMsgBundle.Close();
       
   122 	// delete States
       
   123 	delete iStateIdle;
       
   124 	delete iStateSessionInit;
       
   125 	delete iStateSessionEstablished;	
       
   126 	delete iStateSessionTerminate;
       
   127 	// Close Logging
       
   128 	__FLOG_0(_L("[SipStateMachine]: CSipStateMachine::~CSipStateMachine()"));
       
   129 	__FLOG_CLOSE;
       
   130 	}
       
   131 	
       
   132 EXPORT_C void CSipStateMachine::DeleteWhenReady()
       
   133 /**
       
   134 This function will mark the state machine that the CallTerminated callback
       
   135 should not be called, and state machine should delete itself gracefully when
       
   136 completed the operation
       
   137 */
       
   138 	{
       
   139 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::DeleteWhenReady()"),this);
       
   140 	iClient = NULL;
       
   141 	iCallTerminateCallback = EFalse;
       
   142 	iDeleteMeNow = ETrue;
       
   143 	// send the signal to state machine 
       
   144 	if(iActiveState == NULL)
       
   145 		{
       
   146 		MakeActive();
       
   147 		MarkRequestComplete(KErrNone);
       
   148 		}
       
   149 	}
       
   150 	
       
   151 EXPORT_C TSipParams & CSipStateMachine::GetSipParams()
       
   152 /**
       
   153 Returns the SIP parameters
       
   154 */
       
   155  	{
       
   156  	return iSipParams;	
       
   157  	}
       
   158 
       
   159 EXPORT_C TInt CSipStateMachine::AcceptCall()
       
   160 /**
       
   161 Accepts and incoming call
       
   162 */
       
   163 	{
       
   164 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::AcceptCall()"),this);
       
   165 	// This will always be invite as of now. The implementation of the function needs
       
   166 	// changes when more functionality would be added onto this SM machine to handle more
       
   167 	// SIp works
       
   168 	isInviteSM = ETrue;
       
   169 	return SendSIPResponse(TSipHLConsts::EResponseInvite);
       
   170 	}
       
   171 
       
   172 EXPORT_C TInt CSipStateMachine::StartCall()
       
   173 /**
       
   174 Start an outgoing call
       
   175 */
       
   176 	{
       
   177 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::StartCall()"),this);
       
   178 	if(iSipParams.iRequest == TSipHLConsts::ERequestInvite)
       
   179 		{
       
   180 		isInviteSM = ETrue;
       
   181 		return SendSIPRequest(TSipHLConsts::ERequestInvite);			
       
   182 		}
       
   183 	else if(iSipParams.iRequest == TSipHLConsts::ERequestSubscribe)
       
   184 		{
       
   185 		isSubscribeSM = ETrue;
       
   186 		return SendSIPRequest(TSipHLConsts::ERequestSubscribe);			
       
   187 		}
       
   188 	else
       
   189 		{
       
   190 		iActiveState = NULL;
       
   191 		return KErrNotSupported;			
       
   192 		}
       
   193 	}
       
   194 
       
   195 EXPORT_C TInt CSipStateMachine::StopCall()
       
   196 /**
       
   197 Terminate an established connection
       
   198 */
       
   199 	{
       
   200 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::StopCall()"),this);
       
   201 	if(isSubscribeSM)
       
   202 		{
       
   203 		return SendSIPRequest(TSipHLConsts::ERequestUnSubscribe);
       
   204 		}
       
   205 	else if(isInviteSM)
       
   206 		{
       
   207 		return SendSIPRequest(TSipHLConsts::ERequestBye);	
       
   208 		}
       
   209 	else
       
   210 		{
       
   211 		return KErrNotSupported;	
       
   212 		}
       
   213 	}
       
   214 
       
   215 EXPORT_C TInt CSipStateMachine::RejectCall()
       
   216 /**
       
   217 Rejects an incoming call
       
   218 */
       
   219 	{
       
   220 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::RejectCall()"),this);
       
   221 	return SendSIPResponse(TSipHLConsts::EResponseInviteReject);	
       
   222 	}
       
   223 		
       
   224 TInt CSipStateMachine::SendSIPRequest(TSipHLConsts::SIP_REQUESTS aRequest)
       
   225 /**
       
   226 Sends a SIP request of a particular type 
       
   227 */
       
   228 	{
       
   229 	if(iActiveState == NULL)
       
   230 		return KErrNotReady;
       
   231 	iActiveState->ResetRequestResponse();
       
   232 	iActiveState->SetClientRequest(aRequest);
       
   233 	iClientStimulus = ETrue;
       
   234 	if (iSuspendRequest)
       
   235     	{
       
   236     	SetSuspendRequest(EFalse);   
       
   237     	}
       
   238 		
       
   239 	MakeActive();
       
   240 	MarkRequestComplete(KErrNone);
       
   241 	return KErrNone;
       
   242 	}
       
   243 
       
   244 TInt CSipStateMachine::SendSIPResponse(TSipHLConsts::SIP_RESPONSES aResponse)
       
   245 /**
       
   246 Sends a SIP response of a particular type
       
   247 */
       
   248 	{
       
   249 	if(iActiveState == NULL)
       
   250     	{
       
   251     	return KErrNotReady;    
       
   252     	}
       
   253 		
       
   254 	iActiveState->ResetRequestResponse();
       
   255 	iActiveState->SetClientResponse(aResponse);
       
   256 	iClientStimulus = ETrue;
       
   257 	if (iSuspendRequest)
       
   258     	{
       
   259     	SetSuspendRequest(EFalse);  
       
   260     	}
       
   261 		
       
   262 	MakeActive();
       
   263 	MarkRequestComplete(KErrNone);
       
   264 	return KErrNone;
       
   265 	}
       
   266 
       
   267 	
       
   268 void CSipStateMachine::Start( TRequestStatus* aClientStatus, CSipStateBase* aErrorState )
       
   269 /** 
       
   270 Starts the state machine
       
   271 */
       
   272 	{
       
   273 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::Start()"),this);
       
   274 	iClientStatus 	= 	aClientStatus;
       
   275 	iErrorState 	= 	aErrorState;
       
   276 	iSuspendRequest = 	EFalse;
       
   277 
       
   278 	if (iClientStatus != NULL)
       
   279     	{
       
   280     	*iClientStatus = KRequestPending;    
       
   281     	}
       
   282 	  
       
   283 	// we will not call RunL explicitly over here, That means the SM will be 
       
   284 	// created in suspended mode.	  
       
   285 	}
       
   286 	
       
   287 void CSipStateMachine::IncomingResponse(TSipMsgBundle aMsgBundle)
       
   288 /**
       
   289 Handles the incoming response inside a dialog
       
   290 */
       
   291 	{
       
   292 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingResponse()"),this);
       
   293 	iActiveState->ResetRequestResponse();
       
   294 	iActiveState->SetServerResponse(aMsgBundle.iResponse);
       
   295 	// wake up the State Machine if suspended and pass the response back to the state
       
   296 	if (iSuspendRequest)
       
   297     	{
       
   298     	SetSuspendRequest(EFalse);   
       
   299     	}
       
   300 		
       
   301 	iServerStimulus = ETrue;
       
   302 	iSipMsgBundle.Append(aMsgBundle);
       
   303 	MakeActive();
       
   304 	MarkRequestComplete(KErrNone);	
       
   305 	}
       
   306 void CSipStateMachine::IncomingRequestInsideDialog(TSipMsgBundle aMsgBundle)
       
   307 /**
       
   308 Incoming Request inside established dialog
       
   309 */
       
   310 	{
       
   311 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingResponseInsideDialog()"),this);
       
   312 	iActiveState->ResetRequestResponse();
       
   313 	iActiveState->SetServerRequest(aMsgBundle.iRequest);
       
   314 	// Delete the earlier server transaction if any as earlier transaction comes on outside a
       
   315 	// dialog and not needed as new server transaction that comes with ACK / or inside dialoog
       
   316 	// will be used
       
   317 	if(iCommandCntx.iServerTx != NULL)
       
   318 		{
       
   319 		delete iCommandCntx.iServerTx;
       
   320 		iCommandCntx.iServerTx = NULL;
       
   321 		}
       
   322 	// Set the server Transaction
       
   323 	iCommandCntx.iServerTx = aMsgBundle.iServTransaction;
       
   324 	if (iSuspendRequest)
       
   325     	{
       
   326     	SetSuspendRequest(EFalse);   
       
   327     	}
       
   328 		
       
   329 	iServerStimulus = ETrue;
       
   330 	iSipMsgBundle.Append(aMsgBundle);
       
   331 	MakeActive();
       
   332 	MarkRequestComplete(KErrNone);
       
   333 	}
       
   334 	
       
   335 void CSipStateMachine::ErrorOccured(TSipMsgBundle aErrBundle)	
       
   336 /**
       
   337 Handle the error from TE
       
   338 */
       
   339 	{
       
   340 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::ErrorOccurred()"),this);
       
   341 	iActiveState->ResetRequestResponse();
       
   342 	if (iSuspendRequest)
       
   343     	{
       
   344     	SetSuspendRequest(EFalse);   
       
   345     	}
       
   346 		
       
   347 	iServerErrorStimulus = ETrue;
       
   348 	iSipMsgBundle.Append(aErrBundle);
       
   349 	MakeActive();
       
   350 	MarkRequestComplete(KErrNone);
       
   351 	}
       
   352 	
       
   353 void CSipStateMachine::InviteCompleted(CSIPClientTransaction& /*aTransaction*/)
       
   354 /**
       
   355 This callback is called to maek the completion of invite 
       
   356 */
       
   357 	{
       
   358 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::InviteCompleted()"),this);
       
   359 	// we will not match and delete the client transaction as it will be anyway
       
   360 	// deleted when a BYE is being sent or received.
       
   361 	}
       
   362 	
       
   363 void CSipStateMachine::IncomingRequest(TSipMsgBundle aMsgBundle)
       
   364 /**
       
   365 New Incoming request Inside established dialog
       
   366 */
       
   367 	{
       
   368 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingRequest()"),this);
       
   369 	iActiveState->ResetRequestResponse();
       
   370 	iActiveState->SetServerRequest(aMsgBundle.iRequest);
       
   371 	iSipMsgBundle.Append(aMsgBundle);
       
   372 	iServerStimulus = ETrue;
       
   373 	if (iSuspendRequest)
       
   374     	{
       
   375     	SetSuspendRequest(EFalse);    
       
   376     	}
       
   377 		
       
   378 	MakeActive();
       
   379 	MarkRequestComplete(KErrNone);
       
   380 	}
       
   381 
       
   382 void CSipStateMachine::IncomingRequestOutsideDialog(TSipMsgBundle & aMsgBundle)
       
   383 /**
       
   384 New Incoming request outside any established dialog
       
   385 */
       
   386 	{
       
   387 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::IncomingRequestOutsideDialog()"),this);
       
   388 	// set the command context
       
   389 	iCommandCntx.iDialogAssoc	= (CSIPInviteDialogAssoc*)aMsgBundle.iDialog;
       
   390 	iCommandCntx.iServerTx  	= aMsgBundle.iServTransaction;
       
   391 	iActiveState->ResetRequestResponse();
       
   392 	iActiveState->SetServerRequest(aMsgBundle.iRequest);
       
   393 	iSipMsgBundle.Append(aMsgBundle);
       
   394 	iServerStimulus = ETrue;
       
   395 	if (iSuspendRequest)
       
   396     	{
       
   397     	SetSuspendRequest(EFalse);    
       
   398     	}
       
   399 		
       
   400 	MakeActive();
       
   401 	MarkRequestComplete(KErrNone);
       
   402 	}
       
   403 	
       
   404 void CSipStateMachine::GenerateInviteResponseL(
       
   405 						CSIPServerTransaction *& aTransaction,
       
   406 						TSipHLConsts::SIP_RESPONSE_TYPE aType)
       
   407 /**
       
   408  */
       
   409 	{
       
   410 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL()"),this);
       
   411 	switch(aType)
       
   412 		{
       
   413 		case TSipHLConsts::EResponseRinging:
       
   414 			{
       
   415 			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<180 Ringing>>"),this);
       
   416 			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
       
   417 							180, SIPStrings::StringF(SipStrConsts::EPhraseRinging));
       
   418 			aTransaction->SendResponseL(ResElem);
       
   419 			CleanupStack::Pop(ResElem);	
       
   420 			}
       
   421 			break;
       
   422 		case TSipHLConsts::EResponse200OK:
       
   423 			{
       
   424 			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<200 OK>>"),this);
       
   425 			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
       
   426 							200, SIPStrings::StringF(SipStrConsts::EPhraseOk));
       
   427 			aTransaction->SendResponseL(ResElem);
       
   428 			CleanupStack::Pop(ResElem);		
       
   429 			}
       
   430 			break;
       
   431 		case TSipHLConsts::EResponseReject:
       
   432 			{
       
   433 			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<488 Reject>>"),this);
       
   434 			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
       
   435 							488, SIPStrings::StringF(SipStrConsts::EPhraseNotAcceptableHere));
       
   436 			aTransaction->SendResponseL(ResElem);
       
   437 			CleanupStack::Pop(ResElem);			
       
   438 			}
       
   439 			break;
       
   440 		default:
       
   441 			{
       
   442 			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateInviteResponseL() <<No Response Generated>>"),this);
       
   443 			}
       
   444 		}
       
   445 	
       
   446 	}
       
   447 	
       
   448 void CSipStateMachine::GenerateSubscribeResponseL
       
   449 						(CSIPServerTransaction *& aTransaction,
       
   450 						TSipHLConsts::SIP_RESPONSE_TYPE aType)
       
   451 /**
       
   452  */
       
   453 	{
       
   454 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL()"),this);
       
   455 	switch(aType)
       
   456 		{
       
   457 		case TSipHLConsts::EResponse200OK:
       
   458 			{
       
   459 			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL() <<200 OK>>"),this);
       
   460 			CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
       
   461 						200, SIPStrings::StringF(SipStrConsts::EPhraseOk));
       
   462 			aTransaction->SendResponseL(ResElem);
       
   463 			CleanupStack::Pop(ResElem);		
       
   464 			// We will not delete this here , this will be deleted after giving notification
       
   465 			// to the client
       
   466 			/*
       
   467 			delete aTransaction;
       
   468 			aTransaction = NULL;
       
   469 			*/
       
   470 			}
       
   471 			break;
       
   472 		default:
       
   473 			{
       
   474 			__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateSubscribeResponseL() <<No Response Generated>>"),this);
       
   475 			}
       
   476 		}
       
   477 	}
       
   478 	
       
   479 HBufC8 * CSipStateMachine::GenerateNotificationData()
       
   480 /**
       
   481 */
       
   482 	{
       
   483 	// Generate the notification parameter from the incoming server Transaction	
       
   484 	CSIPServerTransaction *sTran = iCommandCntx.iServerTx;
       
   485 	// get the request elements
       
   486 	const CSIPRequestElements *reqElems = sTran->RequestElements();
       
   487 	// Get the contents of the request elements
       
   488 	// Get the Message Elements
       
   489 	const CSIPMessageElements & msgElems = reqElems->MessageElements();
       
   490 	// Get the content
       
   491 	TPtrC8 content = msgElems.Content();
       
   492 	HBufC8 * notificationData = NULL;
       
   493 	TRAPD(err,notificationData = content.AllocL());
       
   494 	if(err != KErrNone)
       
   495 		{
       
   496 		return NULL;
       
   497 		}
       
   498 	return notificationData;
       
   499 	}
       
   500 	
       
   501 void CSipStateMachine::RunL()
       
   502 /** 
       
   503  * Called on completion of one active event
       
   504  */
       
   505 	{
       
   506 	if (iStatus.Int() != KErrNone)
       
   507 		{
       
   508 		OnError();
       
   509 		}
       
   510 	
       
   511 	if (iActiveState)
       
   512 		{
       
   513 		if (iSuspendRequest)
       
   514 			{
       
   515 			// do nothing wait for somebody to enable the state machine
       
   516 			return;	
       
   517 			}
       
   518 		else if (iClientStimulus)
       
   519 			{
       
   520 			iClientStimulus = EFalse;
       
   521 			MakeActive();
       
   522 			iActiveState = iActiveState->ProcessClientL(iStatus);
       
   523 			}
       
   524 		else if (iServerStimulus)
       
   525 			{
       
   526 			iServerStimulus = EFalse;
       
   527 			MakeActive();
       
   528 			iActiveState = iActiveState->ProcessServerL(iStatus);
       
   529 			}
       
   530 		else if(iServerErrorStimulus)
       
   531 			{
       
   532 			iServerErrorStimulus = EFalse;
       
   533 			MakeActive();
       
   534 			iActiveState = iActiveState->ProcessServerErrorL(iStatus);
       
   535 			}
       
   536 		else
       
   537 			{
       
   538 			iSuspendRequest = ETrue;	
       
   539 			MakeActive();
       
   540 			TRequestStatus *stat = &iStatus;
       
   541 			User::RequestComplete(stat,KErrNone);
       
   542 			}
       
   543 		}
       
   544 	else if (iActiveState == NULL && iDeleteMeNow )
       
   545 		{
       
   546 		// Ask the state machine to delete itself
       
   547 		OnCompletion();
       
   548 		}
       
   549 	else
       
   550 		{
       
   551 		//do nothing	
       
   552 		}
       
   553 	}
       
   554 
       
   555 void CSipStateMachine::OnError()
       
   556 /** 
       
   557  * Called from ::RunL when an error occures
       
   558  */
       
   559 	{
       
   560 	// Put the state machine in suspended mode , and return. 
       
   561 	SetSuspendRequest(ETrue);
       
   562 	TRequestStatus *stat = &iStatus;
       
   563 	User::RequestComplete(stat,KErrNone);
       
   564 	}
       
   565 
       
   566 void CSipStateMachine::OnCompletion()
       
   567 /** 
       
   568  * Called by RunL when it is needed to delete the state machine
       
   569  */
       
   570 	{
       
   571 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::OnCompletion() <<delete this>>"),this);
       
   572 	delete this;
       
   573 	}
       
   574 
       
   575 TInt CSipStateMachine::RunError(TInt aError)
       
   576 /** 
       
   577  */
       
   578 	{
       
   579 	TRequestStatus * Stat = &iStatus;
       
   580 	User::RequestComplete( Stat , aError );
       
   581 	return KErrNone; 
       
   582 	}
       
   583 
       
   584 void CSipStateMachine::DoCancel()
       
   585 /** 
       
   586  */
       
   587 	{
       
   588 	OnCompletion();
       
   589 	}
       
   590 
       
   591 void CSipStateMachine::MakeActive()
       
   592 /**
       
   593  Function call to wake State Machine from Suspended
       
   594  state
       
   595 */	{
       
   596 	if(!IsActive())
       
   597     	{
       
   598     	SetActive();   
       
   599     	}
       
   600 	}
       
   601 	
       
   602 void CSipStateMachine::MarkRequestComplete(TInt aErrCode)
       
   603 /**
       
   604 This function will mimic implicitly calling of the 
       
   605 Runl function of the State Machine base
       
   606 */	
       
   607 	{
       
   608 	TRequestStatus * ThisStat = &iStatus;
       
   609 	User::RequestComplete ( ThisStat, aErrCode);
       
   610 	}
       
   611 	
       
   612 CSIPTransitionEngine * CSipStateMachine::GetTe()
       
   613 /**
       
   614 returns the current instance of TE
       
   615 */
       
   616 	{	
       
   617 	return iTe;
       
   618 	}
       
   619 	
       
   620 CSipStateBase * CSipStateMachine::GetActiveState()	
       
   621 /**
       
   622 Return the Currently active state
       
   623 */
       
   624 	{
       
   625 	return iActiveState;
       
   626 	}
       
   627 	
       
   628 void  CSipStateMachine::CallTerminateCallback()
       
   629 /**
       
   630 Varifies and call the terminate call back with appropriate values
       
   631 */
       
   632 	{
       
   633 	__FLOG_2(_L("[SipStateMachine]: CSipStateMachine[%x]::CallTerminateCallback() <<Callback Flag = %d>>"),this,iCallTerminateCallback);
       
   634 	if(iCallTerminateCallback)
       
   635 		{
       
   636 		iClient->CallTerminated(iCallTerminateCode.iErrorCode, iCallTerminateCode.iSipCode);
       
   637 		}
       
   638 	}
       
   639 	
       
   640 void CSipStateMachine::CallIncomingCallback()
       
   641 /**
       
   642 Calls the client with incoming call parameters
       
   643 */
       
   644 	{
       
   645 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallIncomingCallback()"),this);
       
   646 	TIncomingCallParameters inParam;
       
   647 	GenerateIncomingCallParameters(inParam);	
       
   648 	iClient->IncomingCall(inParam);
       
   649 	}
       
   650 	
       
   651 void CSipStateMachine::CallEstablishedCallback()
       
   652 /**
       
   653 Notifies the client about the established call
       
   654 */
       
   655 	{
       
   656 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallEstablishedCallback()"),this);
       
   657 	iClient->CallEstablished();
       
   658 	}
       
   659 	
       
   660 void CSipStateMachine::CallNotificationCallback(TPtrC8 aNotifyData)
       
   661 /**
       
   662 Notifies the client about the incoming notification
       
   663 */
       
   664 	{
       
   665 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::CallNotificationCallback()"),this);
       
   666 	iClient->ReceiveNotification(aNotifyData);
       
   667 	}
       
   668 	
       
   669 void CSipStateMachine::GenerateIncomingCallParameters(TIncomingCallParameters & aParam)
       
   670 /**
       
   671 Store the incoming call parameters
       
   672 */
       
   673 	{
       
   674 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::GenerateIncomingCallParameters()"),this);
       
   675 	_LIT8(KAtTheRate,"@");
       
   676 	
       
   677 	CSIPServerTransaction *sTran = iCommandCntx.iServerTx;
       
   678 	const CSIPRequestElements *reqElems = sTran->RequestElements();
       
   679 	// Get Request Uri
       
   680 	const CUri8 & uri = reqElems->RemoteUri();
       
   681 	TPtr8 ptrUri = iUriValues.iReqUri.Des();
       
   682 		
       
   683 	ptrUri.Append(uri.Uri().Extract(EUriUserinfo));
       
   684 	ptrUri.Append(KAtTheRate);
       
   685 	ptrUri.Append(uri.Uri().Extract(EUriHost));
       
   686 	// Set Request Uri
       
   687 	aParam.iReqUri.Set(iUriValues.iReqUri);
       
   688 	
       
   689 	
       
   690 	// Get from 
       
   691 	const CSIPFromHeader *fromHdr = reqElems->FromHeader();
       
   692 	const CUri8 & uriFrom = fromHdr->SIPAddress().Uri8();
       
   693 	
       
   694 	TPtr8 ptrFrom = iUriValues.iFrom.Des();
       
   695 	ptrFrom.Append(uriFrom.Uri().Extract(EUriUserinfo));
       
   696 	ptrFrom.Append(KAtTheRate);
       
   697 	ptrFrom.Append(uriFrom.Uri().Extract(EUriHost));
       
   698 	// Set from
       
   699 	aParam.iFrom.Set(iUriValues.iFrom);
       
   700 	
       
   701 	// Get To
       
   702 	const CSIPToHeader *toHdr = reqElems->ToHeader();
       
   703 	const CUri8 & uriTo = toHdr->SIPAddress().Uri8();
       
   704 	
       
   705 	TPtr8 ptrTo = iUriValues.iTo.Des();
       
   706 	ptrTo.Append(uriTo.Uri().Extract(EUriUserinfo));
       
   707 	ptrTo.Append(KAtTheRate);
       
   708 	ptrTo.Append(uriTo.Uri().Extract(EUriHost));
       
   709 	// Set To
       
   710 	aParam.iTo.Set(iUriValues.iTo);
       
   711 	
       
   712 	// Get the Message Elements
       
   713 	const CSIPMessageElements & msgElems = reqElems->MessageElements();
       
   714 	aParam.iContent.Set(msgElems.Content());
       
   715 	}
       
   716 	
       
   717 TBool CSipStateMachine::GetIncomingStatus()
       
   718 /**
       
   719 Sets whether the state machine is for incoming call
       
   720 */
       
   721 	{
       
   722 	return iIncomingStateMachine;
       
   723 	}
       
   724 
       
   725 TBool CSipStateMachine::GetOutgoingStatus()
       
   726 /**
       
   727 sets whether an active outgoing is pending or not
       
   728 */
       
   729 	{
       
   730 	return isActiveOutgoingSession;
       
   731 	}
       
   732 	
       
   733 void CSipStateMachine::SetOutgoingStatus(TBool aStatus)	
       
   734 /**
       
   735 Resets the status of active outgoing pending
       
   736 */
       
   737 	{
       
   738 	isActiveOutgoingSession = aStatus;
       
   739 	}
       
   740 	
       
   741 CSipStateBase * CSipStateMachine::GetNextState (TSipHLConsts::SIP_STATES aNextState)
       
   742 	{
       
   743 	switch (aNextState)
       
   744 		{
       
   745 		case TSipHLConsts::EStateSessionIdle:
       
   746 			return iStateIdle;
       
   747 		case TSipHLConsts::EStateSessionInitiation:
       
   748 			return iStateSessionInit;
       
   749 		case TSipHLConsts::EStateSessionEstablished:
       
   750 			return iStateSessionEstablished;
       
   751 		case TSipHLConsts::EStateSessionTerminated:
       
   752 			return iStateSessionTerminate;
       
   753 		case TSipHLConsts::EStateNone:
       
   754 		default:
       
   755 			return NULL;
       
   756 		}	
       
   757 	
       
   758 	}
       
   759 void CSipStateMachine::Cleanup()
       
   760 	{
       
   761 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::Cleanup()"),this);
       
   762 	// Cleanup everything in Command Context
       
   763 	delete iCommandCntx.iClientTx;
       
   764 	iCommandCntx.iClientTx = NULL;
       
   765 	
       
   766 	delete iCommandCntx.iCancelClientTx;
       
   767 	iCommandCntx.iCancelClientTx = NULL;
       
   768 	
       
   769 	delete iCommandCntx.iRegBinding;
       
   770 	iCommandCntx.iRegBinding = NULL;
       
   771 	
       
   772 	delete iCommandCntx.iClientTx;
       
   773 	iCommandCntx.iClientTx = NULL;
       
   774 	
       
   775 	delete iCommandCntx.iServerTx;
       
   776 	iCommandCntx.iServerTx = NULL;
       
   777 	
       
   778 	delete iCommandCntx.iDialogAssoc;
       
   779 	iCommandCntx.iDialogAssoc = NULL;
       
   780 	
       
   781 	delete iCommandCntx.iSubsDialogAssoc;
       
   782 	iCommandCntx.iSubsDialogAssoc = NULL;
       
   783 	}
       
   784 	
       
   785 	
       
   786 void CSipStateMachine::SendRegisterMessageL()
       
   787 	{
       
   788 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendRegisterMessageL()"),this);
       
   789 	// create all the necessary ingredients to send Register Message
       
   790 	CSIPRefresh * refresh = CSIPRefresh::NewLC();
       
   791 	CSIPToHeader * to 	  = CreateToHeaderLC(iSipParams.iRegParams.iTo);
       
   792 	CSIPFromHeader *from  = CreateFromHeaderLC (iSipParams.iRegParams.iFrom);
       
   793 	CSIPAddress * addr 	  = CSIPAddress::DecodeL(iSipParams.iRegParams.iContact);
       
   794 	CSIPContactHeader * contact = CSIPContactHeader::NewL(addr);
       
   795 	CleanupStack::PushL(contact);
       
   796 	TUriParser8 parser;
       
   797 	User::LeaveIfError(parser.Parse(iSipParams.iRegParams.iRegistrar));
       
   798     CUri8* remoteUri 	  = CUri8::NewLC(parser);   	
       
   799     // Send Registration
       
   800     CSIPConnection * sipConn = GetTe()->GetSipConnection();
       
   801     iCommandCntx.iRegBinding 	= CSIPRegistrationBinding::NewL(
       
   802     							  *sipConn, to, contact,
       
   803     							  refresh,0, remoteUri, from);
       
   804     CleanupStack::PushL(iCommandCntx.iRegBinding);
       
   805 	iCommandCntx.iClientTx		= iCommandCntx.iRegBinding->RegisterL();
       
   806 	CleanupStack::Pop(6, refresh);
       
   807 	}
       
   808 	
       
   809 void CSipStateMachine::SendUnRegisterMessageL()	
       
   810 	{
       
   811 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendUnRegisterMessageL()"),this);
       
   812 	if (iCommandCntx.iClientTx != NULL)
       
   813 		{
       
   814 		delete iCommandCntx.iClientTx;
       
   815 		iCommandCntx.iClientTx = NULL;
       
   816 		}
       
   817 	iCommandCntx.iClientTx = iCommandCntx.iRegBinding->DeregisterL();
       
   818 	}
       
   819 
       
   820 void CSipStateMachine::SendInviteMessageL()
       
   821 /**
       
   822 Send an invitation to remote phone
       
   823 */
       
   824 	{
       
   825 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendInviteMessageL()"),this);
       
   826 	// set the active outgoing session
       
   827 	isActiveOutgoingSession = ETrue;
       
   828 	// Get Invite Parameters
       
   829 	CSIPToHeader 	* to 	= CreateToHeaderLC(iSipParams.iInvParams.iTo);
       
   830 	CSIPFromHeader	* from 	= CreateFromHeaderLC(iSipParams.iInvParams.iFrom);
       
   831 	CSIPAddress		* addr 	= CSIPAddress::DecodeL(iSipParams.iInvParams.iContact);
       
   832 	CSIPContactHeader * contact = CSIPContactHeader::NewLC(addr);
       
   833 	TUriParser8		parser;
       
   834 	User::LeaveIfError(parser.Parse(iSipParams.iInvParams.iReqUri));
       
   835 	CUri8 *	remoteUri	=	CUri8::NewLC(parser);	
       
   836 	CSIPMessageElements* msgElements = NULL;
       
   837 
       
   838 	// Check whether the content is provided or not, if not no SDP will be genrated	
       
   839 	if((iSipParams.iInvParams.iContentType.Length() != 0) &&
       
   840 		(iSipParams.iInvParams.iContentSubType.Length() != 0) &&
       
   841 		(iSipParams.iInvParams.iContent.Length() != 0))
       
   842 		{
       
   843 	   // Generate the SDP 
       
   844 		SdpCodecStringPool::OpenL();
       
   845 		
       
   846 		 msgElements = CSIPMessageElements::NewLC();
       
   847 		CSIPContentTypeHeader* ct = CSIPContentTypeHeader::NewLC( 
       
   848 				iSipParams.iInvParams.iContentType, iSipParams.iInvParams.iContentSubType );
       
   849 		CSdpDocument * sdp = CSdpDocument::DecodeLC(iSipParams.iInvParams.iContent);
       
   850 		HBufC8* content = GetContentBodyL( sdp );
       
   851 		CleanupStack::PushL( content );
       
   852 		msgElements->SetContentL( content, ct );
       
   853 		CleanupStack::Pop();
       
   854 		CleanupStack::Check(sdp);
       
   855 		CleanupStack::PopAndDestroy();// for the sdp document.
       
   856 		SdpCodecStringPool::Close();
       
   857 		}
       
   858 	// Create Invite Dialog Association
       
   859 	CSIPConnection * sipConn = GetTe()->GetSipConnection();
       
   860 	iCommandCntx.iDialogAssoc = CSIPInviteDialogAssoc::NewLC(
       
   861 					*sipConn, from, remoteUri, to, contact );
       
   862 	iCommandCntx.iClientTx	= iCommandCntx.iDialogAssoc->SendInviteL(msgElements);
       
   863 
       
   864 	if(msgElements)
       
   865 		{
       
   866 		CleanupStack::Pop(7, to);
       
   867 		}
       
   868 	else
       
   869 		{
       
   870 		CleanupStack::Pop(5, to);
       
   871 		}
       
   872 	}
       
   873 
       
   874 void CSipStateMachine::SendAckForInviteL()
       
   875 /**
       
   876 Send in response to the response of Initial invite request
       
   877 */
       
   878 	{
       
   879 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendAckForInvite()"),this);
       
   880 	iCommandCntx.iDialogAssoc->SendAckL(*(iCommandCntx.iClientTx),NULL);
       
   881 	}
       
   882 	
       
   883 void CSipStateMachine::SendCancelL()
       
   884 /**
       
   885 Cancels the ongoing session
       
   886 */
       
   887 	{
       
   888 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendCancelL()"),this);
       
   889 	iCommandCntx.iCancelClientTx = iCommandCntx.iClientTx->CancelL();	
       
   890 	}
       
   891 
       
   892 void CSipStateMachine::SendByeL()
       
   893 /** 
       
   894 Terminates the ongoing session associated with a dialog
       
   895 */
       
   896 	{
       
   897 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendByeL()"),this);
       
   898 	if (iCommandCntx.iClientTx != NULL)
       
   899 		{
       
   900 		delete iCommandCntx.iClientTx;
       
   901 		iCommandCntx.iClientTx = NULL;	
       
   902 		}
       
   903 	iCommandCntx.iClientTx = iCommandCntx.iDialogAssoc->SendByeL(NULL);
       
   904 	}
       
   905 
       
   906 void CSipStateMachine::SendByeResponseL()
       
   907 /**
       
   908 Acknoweldge the bye
       
   909 */
       
   910 	{
       
   911 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendByeResponseL() <<200 OK>>"),this);
       
   912 	CSIPResponseElements* RespElem =  CSIPResponseElements::NewLC( 
       
   913             200, SIPStrings::StringF( SipStrConsts::EPhraseOk ) );
       
   914 	iCommandCntx.iServerTx->SendResponseL(RespElem);
       
   915 	CleanupStack::Pop(RespElem);	
       
   916 	}
       
   917 
       
   918 HBufC8* CSipStateMachine::GetContentBodyL( CSdpDocument* aContent )
       
   919 	{
       
   920 	HBufC8* contentBuf = NULL;
       
   921 	if ( aContent->IsValid() )
       
   922 		{
       
   923 		CBufFlat* enBuf = CBufFlat::NewL( 1000 );
       
   924 		CleanupStack::PushL( enBuf );
       
   925 		RBufWriteStream writeStream;
       
   926 		writeStream.Open( *enBuf, 0 );
       
   927 		aContent->EncodeL( writeStream );
       
   928 		writeStream.Close();
       
   929 		TPtr8 ptr = enBuf->Ptr( 0 );
       
   930 		contentBuf = ptr.AllocL();
       
   931 		CleanupStack::PopAndDestroy( enBuf );
       
   932 		writeStream.Close();
       
   933 		}
       
   934 	return contentBuf;
       
   935 	}	
       
   936 	
       
   937 void CSipStateMachine::SendSubscribeMessageL()
       
   938 	{
       
   939 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendSubscribeMessageL()"),this);
       
   940 	// set the active outgoing session
       
   941 	isActiveOutgoingSession = ETrue;
       
   942 	// get Refresh
       
   943 	CSIPRefresh* refresh = NULL;
       
   944 	if (iSipParams.iSubsParams.iAutoRefresh)
       
   945     	{
       
   946     	refresh = CSIPRefresh::NewLC();
       
   947     	}
       
   948 	
       
   949 	// SIP Message Elements required for Subscribe
       
   950 	CSIPMessageElements* message = CSIPMessageElements::NewLC();
       
   951     RPointerArray<CSIPHeaderBase> headers;
       
   952     CSIPHeaderBase::PushLC(&headers);
       
   953     // Add Expires
       
   954     CSIPExpiresHeader* expires = new(ELeave)CSIPExpiresHeader(iSipParams.iSubsParams.iExpires);
       
   955     CleanupStack::PushL(expires);
       
   956     headers.AppendL(expires);
       
   957     CleanupStack::Pop(expires);
       
   958     // Add Accept 
       
   959     CSIPAcceptHeader* accept = CSIPAcceptHeader::NewLC(
       
   960     				iSipParams.iSubsParams.iAcceptType,iSipParams.iSubsParams.iAcceptSubType);
       
   961     headers.AppendL(accept);
       
   962     CleanupStack::Pop(accept); 
       
   963     // add user headers
       
   964     message->SetUserHeadersL(headers);
       
   965     CleanupStack::Pop(1); // headers
       
   966     headers.Close();
       
   967         
       
   968 	
       
   969 	CSIPToHeader 	* to 	= CreateToHeaderLC(iSipParams.iSubsParams.iTo);
       
   970 	CSIPFromHeader	* from 	= CreateFromHeaderLC(iSipParams.iSubsParams.iFrom);
       
   971 	CSIPAddress		* addr 	= CSIPAddress::DecodeL(iSipParams.iSubsParams.iContact);
       
   972 	CSIPContactHeader * contact = CSIPContactHeader::NewLC(addr);
       
   973 	TUriParser8		parser;
       
   974 	User::LeaveIfError(parser.Parse(iSipParams.iSubsParams.iReqUri));
       
   975 	CUri8 *	remoteUri	=	CUri8::NewLC(parser);
       
   976 	CSIPEventHeader	*evtHdr	= 	CSIPEventHeader::DecodeL(iSipParams.iSubsParams.iEventType);
       
   977 	CleanupStack::PushL(evtHdr);
       
   978 	CSIPConnection * sipConn = GetTe()->GetSipConnection();
       
   979 	// Create subscription to send
       
   980 	iCommandCntx.iSubsDialogAssoc = CSIPSubscribeDialogAssoc::NewLC(
       
   981 									*sipConn,from,remoteUri,evtHdr,to,contact);
       
   982 	iCommandCntx.iClientTx = iCommandCntx.iSubsDialogAssoc->SendSubscribeL(message,refresh);
       
   983 	if (refresh)
       
   984     	{
       
   985     	CleanupStack::Pop(8, refresh);   
       
   986     	}
       
   987     else
       
   988         {
       
   989         CleanupStack::Pop(7, message); 
       
   990         }			
       
   991 
       
   992 	}
       
   993 
       
   994 void CSipStateMachine::SendUnSubscribeMessageL()
       
   995 	{
       
   996 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::SendUnSubscribeMessageL()"),this);
       
   997 	if (iCommandCntx.iClientTx != NULL)
       
   998 		{
       
   999 		delete iCommandCntx.iClientTx;
       
  1000 		iCommandCntx.iClientTx = NULL;
       
  1001 		}
       
  1002 	iCommandCntx.iClientTx = iCommandCntx.iSubsDialogAssoc->SendUnsubscribeL(NULL);
       
  1003 	}
       
  1004 	
       
  1005 CSIPToHeader* CSipStateMachine::CreateToHeaderLC( const TDesC8& aSipUri )
       
  1006 	{
       
  1007 		CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri );
       
  1008 		CleanupStack::PushL( addr );
       
  1009 	
       
  1010 		CSIPToHeader* to = CSIPToHeader::NewL( addr );
       
  1011 		CleanupStack::Pop( addr );
       
  1012 		CleanupStack::PushL( to );
       
  1013 		return to;
       
  1014 	}
       
  1015 
       
  1016 CSIPFromHeader* CSipStateMachine::CreateFromHeaderLC( const TDesC8& aSipUri )
       
  1017 	{
       
  1018 		CSIPAddress* addr = CSIPAddress::DecodeL( aSipUri );
       
  1019 		CleanupStack::PushL( addr );
       
  1020 	
       
  1021 		CSIPFromHeader* from = CSIPFromHeader::NewL( addr );
       
  1022 		CleanupStack::Pop( addr );
       
  1023 		CleanupStack::PushL( from );
       
  1024 		return from;
       
  1025 	}
       
  1026 	
       
  1027 	
       
  1028 void	CSipStateMachine::ChallengeIgnored(const TDesC8& aRealm)
       
  1029 	{
       
  1030 	__FLOG_1(_L("[SipStateMachine]: CSipStateMachine[%x]::ChallengeIgnored()"),this);
       
  1031 	//Notify SIPSCPR that challenge has been ignored
       
  1032 	//and credentials need to be set
       
  1033 	iClient->CredentialsRequired(aRealm);
       
  1034 	}
       
  1035