diff -r 000000000000 -r 307788aac0a8 sipproviderplugins/sipprovider/sipstatemachine/src/SipStateMachine.cpp --- /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 +#include + +#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() <>"),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() <>"),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() <>"),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() <>"),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 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); + } +