--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sipproviderplugins/sipprovider/sipstatemachine/src/transitionengine.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,1092 @@
+// 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:
+// CSIPTransitionEngine implementation file.
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+
+#include "transitionengine.h"
+#include "SipStateMachine.h"
+#include <siphlerr.h>
+
+
+CSIPTransitionEngine* CSIPTransitionEngine::NewL(CSIP& aSip, TInt aIapId)
+/**
+Transition Engine Instantiation Function
+*/
+ {
+ CSIPTransitionEngine * self = new (ELeave) CSIPTransitionEngine(aSip, aIapId);
+ CleanupStack::PushL (self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+void CSIPTransitionEngine::ConstructL()
+/**
+2nd Phase construction
+*/
+ {
+ __FLOG_1(_L("CSIPTransitionEngine %08x:\tConstructL(), expect 'ConstructL successful', otherwise the method left"), this);
+ ASSERT(iConnection == NULL);
+
+ // Startup Nokia Stack Related Objects
+ iConnState = CSIPConnection::EInactive;
+
+ __FLOG_1(_L("CSIPTransitionEngine %08x:\tInstantiating CSIPProfileRegistry - may leave"), this);
+ iProfileRegistry = CSIPProfileRegistry::NewL(iSIP, *this);
+ CleanupStack::PushL(iProfileRegistry);
+ __FLOG_1(_L("CSIPTransitionEngine %08x:\tInstantiating CSIPHttpDigest - may leave"), this);
+ iDigest = CSIPHttpDigest::NewL(iSIP, *this );
+ CleanupStack::PushL(iDigest);
+ __FLOG_1(_L("CSIPTransitionEngine %08x:\tInstantiating CSIPConnection - may leave"), this);
+ iConnection = CSIPConnection::NewL(iSIP, iIapId, *this );
+
+ // Wait for the connectio to become Active
+ if( iConnection->State() == CSIPConnection::EInit )
+ {
+ iActiveWait.Start();
+ }
+
+ __FLOG_1(_L("CSIPTransitionEngine %08x:\tConstructL successful"), this);
+ CleanupStack::Pop(2);
+ }
+
+CSIPTransitionEngine::CSIPTransitionEngine(CSIP& aSip, TInt aIapId)
+:iIapId(aIapId),
+ iSIP(aSip)
+/**
+constructor
+*/
+ {
+ // Open Logs
+ __FLOG_OPEN(_L8("SipStateMachine"), _L8("TransitionEngine"));
+ __FLOG_1(_L("[TransitionEngine]:[%x]::CSIPTransitionEngine() "), this);
+ }
+
+
+CSIPTransitionEngine::~CSIPTransitionEngine()
+/**
+Destructor , cleanup wil be done here
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine [%x]::~CSIPTransitionEngine"), this);
+ // Delete all the State Machines that are there registered
+ // with the TE
+ CHLStateMachine *hlSm = NULL;
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ hlSm = (CHLStateMachine*)iSMArray[count];
+ hlSm->iDialog = NULL;
+ hlSm->iTransaction = NULL;
+ delete hlSm;
+ }
+ iSMArray.Close();
+
+ // Clean Profiles
+ numElements = iProfileArray.Count();
+ for (TInt count = 0; count<numElements; count++)
+ {
+ CSIPProfile* profile = iProfileArray[count];
+ delete profile;
+ }
+ iProfileArray.Close();
+
+ //Close RegClientArray
+ //TransitionEngine will be deleted only when no SIPConnProviders are using this
+ iRegClientArray.Close();
+
+ delete iProfileRegistry;
+ delete iConnection;
+ __FLOG_1(_L("<<completed...>> CSIPTransitionEngine [%x]::~CSIPTransitionEngine"), this);
+ __FLOG_CLOSE;
+ }
+
+void CSIPTransitionEngine::ConnectionStateChanged( CSIPConnection::TState aState )
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine [%x]::ConnectionStateChanged()"), this);
+ // No Matter what the connection state is become we have to stop the wait
+ if (iActiveWait.IsStarted())
+ {
+ iActiveWait.AsyncStop();
+ }
+
+ if (iConnState == CSIPConnection::EActive && aState != CSIPConnection::EActive)
+ {
+ //CSIP Connection Lost
+ //Notify all Registration Clients
+ for ( TInt count = 0; count<iRegClientArray.Count(); count++)
+ {
+ iRegClientArray[count]->ErrorOccurred(KErrSIPTransportFailure);
+ }
+
+ }
+ }
+
+
+void CSIPTransitionEngine::IncomingRequest( CSIPServerTransaction* aTransaction )
+/**
+Incoming request recieved outside a dialog
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Recieved Outside of a Dialog>>"),this);
+ CleanupStack::PushL(aTransaction); //we're take over the ownership.
+
+ RStringF method = aTransaction->RequestElements()->Method();
+ if(method == SIPStrings::StringF(SipStrConsts::EInvite))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Received Request Invite>>"),this);
+ TSipMsgBundle msgBundle;
+ // Create a dialog Association and set server transaction
+ CSIPInviteDialogAssoc* dialogassoc = CSIPInviteDialogAssoc::NewL(*aTransaction);
+ CleanupStack::PushL(dialogassoc);
+ msgBundle.iRequest = TSipHLConsts::ERequestInvite;
+ msgBundle.iDialog = dialogassoc;
+ msgBundle.iServTransaction = aTransaction;
+ // Look For the state machine which is responsible for handling
+ // this particular request
+ CSipStateMachine* smPtr = FindSMForIncomingCall();
+ if(smPtr)
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Found State Machine to Handle the Request>>"),this);
+ smPtr->IncomingRequestOutsideDialog(msgBundle);
+ CleanupStack::Pop(dialogassoc);
+ CleanupStack::Pop(aTransaction);
+ }
+ else
+ {// return NotFound
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<No State Machine found to Handle the Request>>"),this);
+ __FLOG_0(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<sending 404>>"));
+ CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+ 404, SIPStrings::StringF(SipStrConsts::EPhraseNotFound));
+ aTransaction->SendResponseL(ResElem);
+ CleanupStack::Pop(ResElem);
+ CleanupStack::PopAndDestroy(aTransaction);
+ CleanupStack::PopAndDestroy(dialogassoc);
+ }
+ }
+ else
+ { // bad request , not supported here
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Received Request other than Invite>>"),this);
+ __FLOG_0(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<sending 404>>"));
+ CSIPResponseElements *ResElem = CSIPResponseElements::NewLC(
+ 400, SIPStrings::StringF(SipStrConsts::EPhraseBadRequest));
+ aTransaction->SendResponseL(ResElem);
+ CleanupStack::Pop(ResElem);
+ CleanupStack::PopAndDestroy(aTransaction);
+ }
+ }
+
+void CSIPTransitionEngine::IncomingRequest( CSIPServerTransaction* aTransaction, CSIPDialog& aDialog )
+/**
+Incoming request recieved on an established dialog
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Recieved on Established Dialog>>"),this);
+ //find state machine from associated DialogAssoc
+ CSipStateMachine* smPtr = FindStateMachine(aDialog);
+ //Extract Method
+ RStringF method = aTransaction->RequestElements()->Method();
+ TSipMsgBundle msgBundle;
+
+ if (method == SIPStrings::StringF(SipStrConsts::EInvite))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<INVITE>>"),this);
+ msgBundle.iRequest = TSipHLConsts::ERequestInvite;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::EAck))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<ACK>>"),this);
+ msgBundle.iRequest = TSipHLConsts::ERequestAck;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::EBye))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<BYE>>"),this);
+ msgBundle.iRequest = TSipHLConsts::ERequestBye;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::ECancel))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<CANCEL>>"),this);
+ msgBundle.iRequest = TSipHLConsts::ERequestCancel;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::ENotify))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<NOTIFY>>"),this);
+ msgBundle.iRequest = TSipHLConsts::ERequestNotify;
+ }
+
+ msgBundle.iServTransaction = aTransaction;
+ // Match the state machine which is associated with this message
+ if(smPtr)
+ {
+ __FLOG_0(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingRequest() <<Found state machine for handling this request>>"));
+ smPtr->IncomingRequestInsideDialog(msgBundle);
+ }
+ }
+
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& /*aTransaction*/ )
+ {
+ // We will Not handle this case
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Not HANDLED CASE CALLED < ITS AN ERROR>>"),this);
+ }
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+ CSIPDialogAssocBase& aDialogAssoc )
+/**
+Incoming Response inside an established dialog is received
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Recieved on Established Dialog>>"),this);
+ CSIPCSeqHeader* CseqHdr = (CSIPCSeqHeader*)aTransaction.ResponseElements()->CSeqHeader();
+ RStringF method = CseqHdr->Method();
+ TSipMsgBundle msgBundle;
+ msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+ msgBundle.iClientTransaction = &aTransaction;
+
+ if (method == SIPStrings::StringF(SipStrConsts::EInvite))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<INVITE>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseInvite;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::EAck))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<ACK>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseAck;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::EBye))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<BYE>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseBye;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::ECancel))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<CANCEL>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseCancel;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::ESubscribe))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<SUBSCRIBE>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseSubscribe;
+ }
+
+ //Find the StateMachine associated with this Dialog
+ CSipStateMachine* smPtr = FindStateMachine(aDialogAssoc);
+ if (smPtr)
+ {
+ //Set the error code in case the status code is 3XX 6XX errors.
+ if(msgBundle.iStatusCode >299)
+ {
+ msgBundle.iErrCode= KErrSIPErrorResponse;
+ smPtr->ErrorOccured(msgBundle);
+ }
+ else
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Found state machine for handling this response>>"),this);
+ smPtr->IncomingResponse(msgBundle);
+ }
+ }
+}
+
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+ CSIPInviteDialogAssoc* aDialogAssoc )
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Recieved on InviteDialog Assoc>>"),this);
+ CSIPCSeqHeader * CseqHdr = (CSIPCSeqHeader*)aTransaction.ResponseElements()->CSeqHeader();
+ RStringF method = CseqHdr->Method();
+ TSipMsgBundle msgBundle;
+ msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+
+ if (method == SIPStrings::StringF(SipStrConsts::EInvite))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<INVITE>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseInvite;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::EAck))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<ACK>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseAck;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::EBye))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<BYE>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseBye;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::ECancel))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<CANCEL>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseCancel;
+ }
+ else if (method == SIPStrings::StringF(SipStrConsts::ESubscribe))
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<SUBSCRIBE>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseSubscribe;
+ }
+
+ //Find the StateMachine associated with this Dialog
+ CSipStateMachine* smPtr = FindStateMachine(reinterpret_cast<CSIPDialogAssocBase*>(aDialogAssoc));
+ if (smPtr)
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Found state machine for handling this response>>"),this);
+ smPtr->IncomingResponse(msgBundle);
+ }
+ }
+
+void CSIPTransitionEngine::IncomingResponse( CSIPClientTransaction& aTransaction,
+ CSIPRegistrationBinding& aRegistration )
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<Recieved on Registration Assoc>>"),this);
+
+ CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+ if (smPtr)
+ {
+ TSipMsgBundle msgBundle;
+ if (aRegistration.IsContextActive()) // Registeration Response
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<REGISTER>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseRegister;
+ msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+ smPtr->IncomingResponse(msgBundle);
+ }
+ else // Unregistration Response
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::IncomingResponse() <<UNREGISTER>>"),this);
+ msgBundle.iResponse = TSipHLConsts::EResponseUnRegister;
+ msgBundle.iStatusCode = aTransaction.ResponseElements()->StatusCode();
+ smPtr->IncomingResponse(msgBundle);
+ }
+ }
+ }
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+ CSIPTransactionBase& aTransaction )
+/**
+This function will ask the particular state machine to handle the
+error
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPTransactionBase& aTransaction)"),this);
+ CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+ if(smPtr)
+ {
+ TSipMsgBundle errBundle;
+ errBundle.iErrCode = aError;
+ smPtr->ErrorOccured(errBundle);
+ }
+ }
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+ CSIPClientTransaction& aTransaction,
+ CSIPRegistrationBinding& /*aRegistration*/ )
+/**
+Handle errors related to Failed Registration. The registration binding is destroyed by
+the state machine, so need not to be destroyed here
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPTransactionBase& aTransaction, CSIPRegistrationBinding & aRegistration)"),this);
+ CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+ if(smPtr)
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+ TSipMsgBundle msgBundle;
+ msgBundle.iErrCode = aError;
+ msgBundle.iResponse = TSipHLConsts::EResponseRegister;
+ const CSIPResponseElements * resElems = aTransaction.ResponseElements();
+ if(resElems)
+ {
+ msgBundle.iStatusCode = resElems->StatusCode();
+ }
+ else
+ {
+ msgBundle.iStatusCode = -1;
+ }
+ msgBundle.iClientTransaction = &aTransaction;
+ smPtr->ErrorOccured(msgBundle);
+ }
+ else
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+ }
+ }
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+ CSIPTransactionBase& /*aTransaction*/,
+ CSIPDialogAssocBase& aDialogAssoc)
+/**
+Handles the errors related to failed transaction. No need delete the transaction
+or the dialogassoc , as state machine will delete those upon termination
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPTransactionBase& aTransaction, CSIPDialogAssocBase & aDialogAssoc)"),this);
+ CSipStateMachine* smPtr = FindStateMachine(aDialogAssoc);
+ if(smPtr)
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+ TSipMsgBundle errBundle;
+ errBundle.iErrCode = aError;
+ // we cant get status code from response
+ errBundle.iStatusCode = -1;
+ smPtr->ErrorOccured(errBundle);
+ }
+ else
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+ // No State Machine, Nothing to do , SM might have been terminated by some
+ // other request
+ return;
+ }
+ }
+
+void CSIPTransitionEngine::ErrorOccured(TInt aError, CSIPRefresh & aSIPRefresh)
+/**
+Handles Errors related to refresh
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPRefresh & aSIPRefresh)"),this);
+ TSipMsgBundle errBundle;
+ // Get The state machine associated with this particular Refresh request
+ const CSIPClientTransaction * clientTnx = aSIPRefresh.SIPTransaction();
+ if(clientTnx)
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+ CSipStateMachine* smPtr = FindStateMachine(clientTnx);
+ if(smPtr)
+ {
+ errBundle.iErrCode = aError;
+ const CSIPResponseElements * resElems = clientTnx->ResponseElements();
+ if(resElems)
+ {
+ errBundle.iStatusCode = resElems->StatusCode();
+ }
+ else
+ {
+ errBundle.iStatusCode = -1;
+ }
+ smPtr->ErrorOccured(errBundle);
+ }
+ else
+ {
+ // NO SM , nothing to do
+ }
+ }
+ else
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+ // No Client Transaction , Noting can be done
+ }
+ }
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+ CSIPRegistrationBinding& aRegistration)
+/**
+Handles the error occurred with the periodic refreshing of an registration
+binding
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPRegistrationBinding& aRegistration)"),this);
+ TSipMsgBundle errBundle;
+ // Get The state machine to Handle this condition
+ CSIPRefresh * refresh = aRegistration.SIPRefresh();
+ if(refresh)
+ {
+ const CSIPClientTransaction *clientTxn = refresh->SIPTransaction();
+ if(clientTxn)
+ {
+ CSipStateMachine* smPtr = FindStateMachine(clientTxn);
+ if(smPtr)
+ {
+ errBundle.iErrCode = aError;
+ const CSIPResponseElements * resElems = clientTxn->ResponseElements();
+ if(resElems)
+ {
+ errBundle.iStatusCode = resElems->StatusCode();
+ }
+ else
+ {
+ errBundle.iStatusCode = -1;
+ }
+ smPtr->ErrorOccured(errBundle);
+ }
+ else
+ {
+ // NO SM , nothing to do
+ }
+ }
+ else
+ {
+ // No client Txn , Nothing can be done
+ }
+ }
+ else
+ {
+ // No Refesh inside nothing can be done
+ }
+ }
+
+void CSIPTransitionEngine::ErrorOccured( TInt aError,
+ CSIPDialogAssocBase& aDialogAssoc)
+/**
+Handles SIP errors based That happens on a Existing Dialog association
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ErrorOccurred(TInt aError,CSIPDialogAssocBase& aDialogAssoc)"),this);
+ TSipMsgBundle errBundle;
+ // Find the state machine to Handle this error condition
+ CSipStateMachine* smPtr = FindStateMachine(aDialogAssoc);
+ if(smPtr)
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Found State Machine to Handle the Error>>"));
+ errBundle.iErrCode = aError;
+ // we dont have handle to SIP message elements from here
+ errBundle.iStatusCode = -1;
+ smPtr->ErrorOccured(errBundle);
+ }
+ else
+ {
+ __FLOG_0(_L("[TransitionEngine]: <<Not Found State Machine to Handle the Error>>"));
+ // NO SM , nothing to do
+ }
+ }
+
+void CSIPTransitionEngine::InviteCompleted( CSIPClientTransaction& aTransaction )
+/**
+Handles the case related to the Completion of Invite Request
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::InviteCompleted()"),this);
+ CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+ smPtr->InviteCompleted(aTransaction);
+ }
+
+
+void CSIPTransitionEngine::InviteCanceled( CSIPServerTransaction& aTransaction )
+/**
+This callback will be called when a incoming Invite is cancelled by the remote machine
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::InviteCanceled()"),this);
+ CSipStateMachine* smPtr = FindStateMachine(aTransaction);
+ TSipMsgBundle msgBundle;
+ msgBundle.iServTransaction = &aTransaction;
+ msgBundle.iRequest = TSipHLConsts::ERequestCancel;
+ smPtr->IncomingRequest(msgBundle);
+ }
+
+//From MSIPProfileRegistryObserver
+void CSIPTransitionEngine::ProfileRegistryErrorOccurred(TUint32 aProfileId, TInt aError)
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryErrorOccurred()"),this);
+ //if(iActiveWait.IsStarted())
+ // iActiveWait.AsyncStop();
+ CSIPProfile* profile = NULL;
+ TUint32 profileId;
+ MSIPRegistrationClient* regClient = FindRegistrationClient(aProfileId);
+
+ TInt size = iProfileArray.Count();
+ for (TInt count = 0; count<size; count++)
+ {
+ profile = iProfileArray[count];
+ profile->GetParameter(KSIPProfileId, profileId);
+ if (profileId == aProfileId)
+ {
+ iProfileRegistry->Disable(*profile);
+ iProfileArray.Remove(count);
+ delete profile;
+ break;
+ }
+ }
+
+ //MSIPRegistrationClient* regClient = FindRegistrationClient(aProfileId);
+ if(regClient)
+ {
+ regClient->ErrorOccurred(aError);
+ }
+ }
+
+void CSIPTransitionEngine::ProfileRegistryEventOccurred(TUint32 aProfileId, TEvent aEvent)
+/**
+Handle the registry event for Registration and Deregistration
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred()"),this);
+ //if(iActiveWait.IsStarted())
+ // iActiveWait.AsyncStop();
+
+ TUint32 profileId;
+ CSIPProfile* profile = NULL;
+ MSIPRegistrationClient* regClient = FindRegistrationClient(aProfileId);
+ if(regClient == NULL)
+ {
+ _LIT(KSipConnProvPanic, "SIPCPR");
+ User::Panic(KSipConnProvPanic, KSIPProfileNotFound);
+ }
+ switch(aEvent)
+ {
+ case EProfileRegistered:
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred() <<EProfileRegistered>>"),this);
+ regClient->RegistrationComplete(KErrNone);
+ }
+ break;
+
+ case EProfileDeregistered:
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred() <<EProfileDeRegistered>>"),this);
+ TInt size = iProfileArray.Count();
+ for (TInt count = 0; count<size; count++)
+ {
+ profile = iProfileArray[count];
+ profile->GetParameter(KSIPProfileId, profileId);
+ if (profileId == aProfileId)
+ {
+ iProfileArray.Remove(count);
+ delete profile;
+ break;
+ }
+ }
+ regClient->DeRegistrationComplete(KErrNone);
+ break;
+ }
+ default:
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::ProfileRegistryEventOccurred() <<ERROR..>>"),this);
+ regClient->ErrorOccurred(KErrUnknown);
+ }
+ }
+
+ }
+
+CSipStateMachine* CSIPTransitionEngine::FindStateMachine(CSIPTransactionBase& aTransaction)
+/**
+Finds the associated state machine with the SIP transaction
+*/
+ {
+ for(TInt count = 0;count<iSMArray.Count();count++)
+ {
+ if(*(iSMArray[count]->iTransaction) == aTransaction)
+ {
+ return iSMArray[count]->iStateMachine;
+ }
+ }
+ return NULL;
+ };
+
+CSipStateMachine* CSIPTransitionEngine::FindStateMachine(const CSIPTransactionBase* aTransaction)
+/**
+Finds the associated state machine with the SIP transaction
+*/
+ {
+ for(TInt count = 0;count<iSMArray.Count();count++)
+ {
+ if(iSMArray[count]->iTransaction == aTransaction)
+ {
+ return iSMArray[count]->iStateMachine;
+ }
+ }
+ return NULL;
+ };
+
+CSipStateMachine* CSIPTransitionEngine::FindStateMachine(CSIPDialogAssocBase* aDialogAssoc)
+/**
+Finds the associated state machine with the SIP Dialog
+*/
+ {
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ if (iSMArray[count]->iDialog == aDialogAssoc)
+ {
+ return iSMArray[count]->iStateMachine;
+ }
+ }
+ return NULL;
+
+ };
+
+
+CSipStateMachine* CSIPTransitionEngine::FindStateMachine(CSIPDialog& aDialog)
+/**
+Finds the associated state machine with the SIP Dialog
+*/
+ {
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ if(aDialog.IsAssociated(*(iSMArray[count]->iDialog)))
+ {
+ return iSMArray[count]->iStateMachine;
+ }
+ }
+ return NULL;
+ };
+
+
+CSipStateMachine* CSIPTransitionEngine::FindStateMachine(CSIPDialogAssocBase& aDialogAssoc)
+/**
+Finds the associated state machine with the SIP Dialog Assocition
+*/
+ {
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ if (iSMArray[count]->iDialog == &aDialogAssoc)
+ {
+ return iSMArray[count]->iStateMachine;
+ }
+ }
+ return NULL;
+ };
+
+EXPORT_C void CSIPTransitionEngine::AddStateMachineL(CSipStateMachine* aStateMachine)
+/**
+Using this call The client will register the state machine with the Transition
+Engine
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::AddStateMachineL()"),this);
+ CHLStateMachine *hlSm = new(ELeave) CHLStateMachine;
+ hlSm->iStateMachine = aStateMachine;
+ hlSm->iDialog = NULL;
+ hlSm->iTransaction = NULL;
+ iSMArray.AppendL(hlSm);
+ }
+
+void CSIPTransitionEngine::Cleanup(CSipStateMachine * aStateMachine)
+/**
+Handles the cleanup related to the transition Engine
+*/
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::Cleanup()"),this);
+ CHLStateMachine *hlSm = NULL;
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ if (iSMArray[count]->iStateMachine == aStateMachine)
+ {
+ hlSm = (CHLStateMachine*)iSMArray[count];
+ hlSm->iDialog = NULL;
+ hlSm->iTransaction = NULL;
+ delete hlSm;
+ }
+ }
+ }
+
+
+void CSIPTransitionEngine::SetTransaction(CSipStateMachine* aStateMachine, CSIPTransactionBase* aTransaction)
+/**
+Sets The transaction for a particular state machine
+*/
+ {
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ if (iSMArray[count]->iStateMachine == aStateMachine)
+ {
+ iSMArray[count]->iTransaction = aTransaction;
+ }
+ }
+ }
+
+void CSIPTransitionEngine::SetDialogAssoc(CSipStateMachine* aStateMachine, CSIPDialogAssocBase* aDialoAssoc)
+/**
+Sets the dialog association for a particular state machine
+*/
+ {
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count++)
+ {
+ if (iSMArray[count]->iStateMachine == aStateMachine)
+ {
+ iSMArray[count]->iDialog = aDialoAssoc;
+ }
+ }
+ }
+
+CSipStateMachine * CSIPTransitionEngine::FindSMForIncomingCall()
+/**
+Find the empty state machine for handling the incoming calls
+*/
+ {
+ TInt numElements = iSMArray.Count();
+ for(TInt count=0; count<numElements; count ++)
+ {
+ if(iSMArray[count]->iTransaction == NULL && iSMArray[count]->iDialog == NULL)
+ {
+ // Check if this empty state machine is for incoming
+ if(iSMArray[count]->iStateMachine->GetIncomingStatus())
+ {
+ return iSMArray[count]->iStateMachine;
+ }
+ }
+ }
+ return NULL;
+ }
+
+
+EXPORT_C void CSIPTransitionEngine::RegisterL(MSIPRegistrationClient* aRegistrationClient)
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::RegisterL()"),this);
+ TUint32 profileId = aRegistrationClient->GetProfileId();
+ CSIPProfile* profile = NULL;
+ iRegClientArray.AppendL(aRegistrationClient);
+
+ TInt err = KErrNone;
+ if(profileId == KSIPDefaultProfileId)
+ {
+ TRAP(err,profile = iProfileRegistry->DefaultProfileL());
+ }
+ else
+ {
+ TRAP(err, profile = iProfileRegistry->ProfileL(profileId));
+ }
+ if(err != KErrNone)
+ {
+ __FLOG_2(_L("CSIPTransitionEngine %08x:The profile [%d] hasn't been found, aborting..."), this, profileId);
+ User::Leave(KSIPProfileNotFound);
+ }
+ if (!iProfileRegistry->IsEnabled(*profile))
+ {
+ __FLOG_2(_L("CSIPTransitionEngine %08x:The profile [%d] found, enabling..."), this, profileId);
+ TRAP(err,iProfileRegistry->EnableL( *profile, *this ));
+ if(err != KErrNone)
+ {
+ User::Leave(KSIPProfileNotFound);
+ }
+ iProfileArray.AppendL(profile);
+ }
+ }
+
+
+EXPORT_C void CSIPTransitionEngine::Deregister(MSIPRegistrationClient* aRegistrationClient)
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::Deregister()"),this);
+ TUint32 regProfId = aRegistrationClient->GetProfileId();
+ TUint32 profileId;
+ CSIPProfile* profile;
+ TInt size = iProfileArray.Count();
+
+ for (TInt count = 0; count<size; count++)
+ {
+ profile = iProfileArray[count];
+ profile->GetParameter(KSIPProfileId, profileId);
+ if (profileId == regProfId)
+ {
+ iProfileRegistry->Disable(*profile);
+ break;
+ }
+ }
+ }
+
+
+EXPORT_C TUint32 CSIPTransitionEngine::FindDuplicateProfile(TUint32 aProfileId)
+ {
+ __FLOG_1(_L("[TransitionEngine]: CSIPTransitionEngine[%x]::FindDuplicateProfile()"),this);
+ // IAP,Registrar,User AOR,Contacts, Proxy, Digest User Name, Digest Realm, SecMechanism
+ if (aProfileId == KSIPInvalidProfileId)
+ {
+ return KSIPInvalidProfileId;
+ }
+
+ CSIPProfile* profile = NULL;
+ TRAPD(err, profile = iProfileRegistry->ProfileL(aProfileId));
+
+ if (err != KErrNone)
+ {
+ return KErrNone;
+ }
+
+ TUint32 thisIapId;
+ TUint32 thisProfileId;
+ const TDesC8* thisAor = NULL;
+ const TDesC8* thisRegistrar = NULL;
+ const TDesC8* thisProxy = NULL;
+ const TDesC8* thisRegRealm = NULL;
+ const TDesC8* thisProxyRealm = NULL;
+ const TDesC8* thisRegUser = NULL;
+ const TDesC8* thisProxyUser = NULL;
+
+ profile->GetParameter(KSIPProfileId, thisProfileId);
+ profile->GetParameter(KSIPAccessPointId, thisIapId);
+ profile->GetParameter(KSIPUserAor, thisAor);
+ profile->GetParameter(KSIPRegistrar,KSIPServerAddress, thisRegistrar);
+ profile->GetParameter(KSIPOutboundProxy,KSIPServerAddress, thisProxy);
+ profile->GetParameter(KSIPRegistrar,KSIPDigestRealm, thisRegRealm);
+ profile->GetParameter(KSIPRegistrar,KSIPDigestUserName, thisRegUser);
+ profile->GetParameter(KSIPOutboundProxy,KSIPDigestRealm, thisProxyRealm);
+ profile->GetParameter(KSIPOutboundProxy,KSIPDigestUserName, thisProxyUser);
+
+
+ TInt size = iProfileArray.Count();
+
+ TUint32 iapId;
+ TUint32 profileId;
+ const TDesC8* aor = NULL;
+ const TDesC8* registrar = NULL;
+ const TDesC8* proxy = NULL;
+ const TDesC8* regRealm = NULL;
+ const TDesC8* proxyRealm = NULL;
+ const TDesC8* regUser = NULL;
+ const TDesC8* proxyUser = NULL;
+
+ //Iterate through profiles in iProfileArray
+ //and match
+
+ for (TInt count=0; count<size; count++)
+ {
+ iProfileArray[count]->GetParameter(KSIPProfileId, profileId);
+ if (profileId == thisProfileId)
+ {
+ //profile Id for an existing profile was passed
+ return profileId;
+ }
+ iProfileArray[count]->GetParameter(KSIPAccessPointId, iapId);
+ if (iapId != thisIapId)
+ {
+ continue;
+ }
+ iProfileArray[count]->GetParameter(KSIPUserAor, aor);
+ if (aor != thisAor)
+ {
+ continue;
+ }
+
+ iProfileArray[count]->GetParameter(KSIPRegistrar,KSIPServerAddress, registrar);
+ if (registrar != thisRegistrar)
+ {
+ continue;
+ }
+
+ iProfileArray[count]->GetParameter(KSIPOutboundProxy,KSIPServerAddress, proxy);
+ if (proxy != thisProxy)
+ {
+ continue;
+ }
+
+ iProfileArray[count]->GetParameter(KSIPRegistrar,KSIPDigestRealm, regRealm);
+ if(regRealm != thisRegRealm)
+ {
+ continue;
+ }
+ iProfileArray[count]->GetParameter(KSIPOutboundProxy,KSIPDigestRealm, proxyRealm);
+ if (proxyRealm != thisProxyRealm)
+ {
+ continue;
+ }
+ iProfileArray[count]->GetParameter(KSIPRegistrar,KSIPDigestUserName, regUser);
+ if (regUser != thisRegUser)
+ {
+ continue;
+ }
+
+ iProfileArray[count]->GetParameter(KSIPOutboundProxy,KSIPDigestUserName, proxyUser);
+ if (proxyUser != thisProxyUser)
+ {
+ continue;
+ }
+ //Duplicate profile found
+ return profileId;
+ }
+
+ return KSIPInvalidProfileId;
+ }
+
+
+
+EXPORT_C void CSIPTransitionEngine::AddCredentialsL(TSIPCredentials aCredential)
+ {
+ iCredentialsArray.AppendL(aCredential);
+ }
+
+EXPORT_C const TDesC8* CSIPTransitionEngine::GetFromField(TUint32 aProfileId) const
+ {
+ TInt size = iProfileArray.Count();
+ CSIPProfile* profile = NULL;
+ const TDesC8* userName = NULL;
+ TUint32 profileId = KSIPInvalidProfileId;
+
+ for (TInt count = 0; count<size; count++)
+ {
+ profile = iProfileArray[count];
+ profile->GetParameter(KSIPProfileId, profileId);
+ if (profileId == aProfileId)
+ {
+ profile->GetParameter(KSIPUserAor, userName);
+ }
+ }
+ return userName;
+ }
+
+
+MSIPRegistrationClient* CSIPTransitionEngine::FindRegistrationClient(TUint32 aProfileId)
+ {
+ TInt size = iRegClientArray.Count();
+ for (TInt count = 0; count<size; count++)
+ {
+ if(aProfileId == iRegClientArray[count]->GetProfileId())
+ {
+ return iRegClientArray[count];
+ }
+ }
+ return NULL;
+ }
+
+//From MSIPHttpDigestChallengeObserver
+void CSIPTransitionEngine::ChallengeReceived(const TDesC8& aRealm)
+ {
+ //Walkthrough the list of Realms to find credentials
+ if (!FindAndSetCredentials(aRealm))
+ {
+ TInt size = iSMArray.Count();
+ //Walk through State Machines and find the current outgoing active state machine
+ for (TInt count=0; count<size; count++)
+ {
+ CSipStateMachine* smPtr= iSMArray[count]->iStateMachine;
+ if(!smPtr->GetIncomingStatus() && smPtr->GetOutgoingStatus())
+ {
+ iDigest->IgnoreChallenge(aRealm);
+ smPtr->ChallengeIgnored(aRealm);
+ }
+ }
+ }
+
+ }
+
+
+TBool CSIPTransitionEngine::FindAndSetCredentials(const TDesC8& aRealm)
+ {
+ TInt size = iCredentialsArray.Count();
+
+ for (TInt count=0; count<size; count++)
+ {
+ if (aRealm == iCredentialsArray[count].iRealm)
+ {
+ TRAPD(err, iDigest->SetCredentialsL(iCredentialsArray[count].iRealm,
+ iCredentialsArray[count].iUserName,
+ iCredentialsArray[count].iPasswd));
+ if(err != KErrNone)
+ {
+ return ETrue;
+ }
+ }
+ }
+ return EFalse;
+ }