--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sipproviderplugins/sipprovider/sipconnectionplugins/src/sipscpr.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,452 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Sip SubConnection Provider implementation
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+
+#include "sipscpr.h"
+#include "sipscprstates.h"
+
+using namespace ESock;
+using namespace NetStateMachine;
+using namespace Messages;
+using namespace MeshMachine;
+_LIT(KPanicSIPSCPRText,"SCPR doesn't appear to expect an incoming connection");
+
+//-=========================================================
+//
+// Activities
+//
+//-=========================================================
+
+
+namespace SipSCprProvisionActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityStoreProvision, SipSCprProvision, TCFDataClient::TProvisionConfig)
+ NODEACTIVITY_ENTRY(KNoTag, SipSCprStates::TStoreProvision, CoreNetStates::TAwaitingProvision, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace SipSCprNoBearerActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityNoBearer, SipSCprNoBearer, TCFControlProvider::TNoBearer)
+ NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TRaiseError<KErrNotSupported>, CoreNetStates::TAwaitingNoBearer, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace SipSCprStartConnectionActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, SipSCprStartConnection, TCFServiceProvider::TStart,PRActivities::CStartActivity::NewL)
+ FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, SipSCprStates::TNoTagOrAlreadyStarted)
+ NODEACTIVITY_ENTRY(KNoTag, SipSCprStates::TStartSession, SipSCprStates::TAwaitingSessionEstablished, MeshMachine::TNoTagOrErrorTag)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted)
+ LAST_NODEACTIVITY_ENTRY(CoreNetStates::KAlreadyStarted, CoreNetStates::TSendStarted)
+ LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseActivityError)
+NODEACTIVITY_END()
+}
+
+
+namespace SipSCprStopActivity
+{
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityStop, SipSCprStop, TCFServiceProvider::TStop)
+ FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStop, SipSCprStates::TNoTagOrAlreadyStopped)
+ //If SCPR is active, stop it, else jumpt to EAlreadyStopped
+ NODEACTIVITY_ENTRY(KNoTag, SipSCprStates::TStopSession, SipSCprStates::TAwaitingSessionTerminated, MeshMachine::TNoTagOrErrorTag)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, /*PRStates::TSendStopped*/PRStates::TSendStoppedAndGoneDown)
+ LAST_NODEACTIVITY_ENTRY(CoreNetStates::KAlreadyStopped, /*PRStates::TSendStopped*/PRStates::TSendStoppedAndGoneDown)
+ LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError)
+NODEACTIVITY_END()
+}
+
+
+namespace SipSCprParamsRequestActivity
+{
+#ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityParamRequest, SipSCprSetParams, TCFScpr::TSetParamsRequest)
+ FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, MeshMachine::TNoTag)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, SipSCprStates::TStoreAndSetParams)
+NODEACTIVITY_END()
+#else
+DECLARE_DEFINE_NODEACTIVITY(ECFActivityParamRequest, SipSCprSetParams, TCFScpr::TParamsRequest)
+ FIRST_NODEACTIVITY_ENTRY(SCprStates::TAwaitingParamRequest, MeshMachine::TNoTag)
+ LAST_NODEACTIVITY_ENTRY(KNoTag, SipSCprStates::TStoreAndSetParams)
+NODEACTIVITY_END()
+#endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
+}
+
+namespace SipSCprBinderRequestActivity
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBinderRequest, SipSCprBinderRequest, TCFServiceProvider::TCommsBinderRequest, MeshMachine::CNodeParallelActivityBase::NewL)
+ NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TRaiseError<KErrNotSupported>, CoreNetStates::TAwaitingBinderRequest, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace SipSCprRejoinDataClient
+{
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityRejoin, SipSCprRejoin, TCFRejoiningProvider::TRejoinDataClientRequest, PRActivities::CRejoinDataClientActivity::NewL)
+ NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TRaiseError<KErrNotSupported>, CoreNetStates::TAwaitingDataClientRejoin, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace SipSCprActivities
+{
+DECLARE_DEFINE_ACTIVITY_MAP(activityMap)
+ ACTIVITY_MAP_ENTRY(SipSCprProvisionActivity, SipSCprProvision)
+ ACTIVITY_MAP_ENTRY(SipSCprNoBearerActivity, SipSCprNoBearer)
+ ACTIVITY_MAP_ENTRY(SipSCprStartConnectionActivity, SipSCprStartConnection)
+ ACTIVITY_MAP_ENTRY(SipSCprStopActivity, SipSCprStop)
+ ACTIVITY_MAP_ENTRY(SipSCprParamsRequestActivity, SipSCprSetParams)
+ ACTIVITY_MAP_ENTRY(SipSCprBinderRequestActivity, SipSCprBinderRequest)
+ ACTIVITY_MAP_ENTRY(SipSCprRejoinDataClient, SipSCprRejoin)
+ ACTIVITY_MAP_ENTRY(SipSCprRejoinDataClient, SipSCprRejoin)
+ACTIVITY_MAP_END_BASE(SCprActivities, coreSCprActivities)
+}
+
+//-=========================================================
+//
+// CSipSubConnectionProvider methods
+//
+//-=========================================================
+CSipSubConnectionProvider::~CSipSubConnectionProvider()
+ {
+ LOG_NODE_DESTROY(KSipSCprTag, CSipSubConnectionProvider);
+ iSipSm->DeleteWhenReady();
+ }
+
+CSipSubConnectionProvider::CSipSubConnectionProvider(ESock::CSubConnectionProviderFactoryBase& aFactory)
+ : CCoreSubConnectionProvider(aFactory, SipSCprActivities::activityMap::Self())
+ {
+ LOG_NODE_CREATE(KSipSCprTag, CSipSubConnectionProvider);
+
+ }
+
+CSipSubConnectionProvider*
+CSipSubConnectionProvider::NewL(CSubConnectionProviderFactoryBase& aFactory, TSubConnOpen::TSubConnType aSubConnType)
+ {
+ CSipSubConnectionProvider* provider = new(ELeave)CSipSubConnectionProvider(aFactory);
+ CleanupStack::PushL(provider);
+ provider->ConstructL(aSubConnType);
+ CleanupStack::Pop();
+ return provider;
+ }
+
+
+void CSipSubConnectionProvider::ConstructL(TSubConnOpen::TSubConnType aSubConnType)
+ {
+ CCoreSubConnectionProvider::ConstructL();
+ iStage = SipSCpr::EFresh;
+ subconType = aSubConnType;
+ // Set the flag if the sub con type is WaitForIncoming
+ if (aSubConnType == RSubConnection::EWaitIncoming)
+ {
+ iAwaitingSubConnection = ETrue;
+ }
+ else
+ {
+ iAwaitingSubConnection = EFalse;
+ }
+ iSipSm = NULL;
+ }
+
+
+void CSipSubConnectionProvider::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+ {
+ TNodeContext<CSipSubConnectionProvider> ctx(*this, aMessage, aSender, aRecipient);
+ CCoreSubConnectionProvider::Received(ctx);
+ User::LeaveIfError(ctx.iReturn);
+ }
+
+void CSipSubConnectionProvider::DoParametersAboutToBeSetL(RCFParameterFamilyBundle_const& aParameterBundle)
+ {
+
+ if (iStage != SipSCpr::EFresh)
+ {
+ //Can't change parameters after starting.
+ User::Leave(KErrNotSupported);
+ }
+
+ RParameterFamily calldescrFamily = aParameterBundle.FindFamily(KSubConnCallDescrParamsFamily);
+ RParameterFamily authFamily = aParameterBundle.FindFamily(KSubConAuthorisationFamily);
+ if(!calldescrFamily.IsNull())
+ {
+ TSipParams& sipParams = iSipSm->GetSipParams();
+ STypeId idInv = STypeId::CreateSTypeId(KSubConSIPParametersUid,KSubConSIPInviteParamsType);
+ STypeId idSbs = STypeId::CreateSTypeId(KSubConSIPParametersUid,KSubConSIPSubscribeParamsType);
+ CSubConSIPInviteParamSet* sipInvitationParams = (CSubConSIPInviteParamSet*)calldescrFamily.FindParameterSet(
+ idInv, RParameterFamily::ERequested);
+ CSubConSIPSubscribeParamSet* sipSubscribeParams = (CSubConSIPSubscribeParamSet*)calldescrFamily.FindParameterSet(
+ idSbs, RParameterFamily::ERequested);
+
+ if (sipInvitationParams)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- CSubConSIPInviteParamSet found "), this));
+
+ sipParams.iRequest = TSipHLConsts::ERequestInvite;
+ sipParams.iInvParams.iReqUri.Set(sipInvitationParams->GetRequestUri());
+ sipParams.iInvParams.iTo.Set(sipInvitationParams->GetTo());
+ if (sipInvitationParams->GetFrom().Length() == 0)
+ {
+ //The application may fail to supply 'from' in which case we
+ //should reuse the 'from' field stored by the profile.
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- From field not found"), this));
+ sipInvitationParams->SetFromL(*iFromField);
+ }
+ sipParams.iInvParams.iFrom.Set(sipInvitationParams->GetFrom());
+ sipParams.iInvParams.iContact.Set(sipInvitationParams->GetContact());
+ sipParams.iInvParams.iContentType.Set(sipInvitationParams->GetContentType());
+ sipParams.iInvParams.iContentSubType.Set(sipInvitationParams->GetContentSubType());
+ sipParams.iInvParams.iContent.Set(sipInvitationParams->GetContent());
+ }
+ else if (sipSubscribeParams)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- CSubConSIPSubscribeParamSet found"), this));
+
+ sipParams.iRequest = TSipHLConsts::ERequestSubscribe;
+ sipParams.iSubsParams.iReqUri.Set(sipSubscribeParams->GetRequestUri());
+ sipParams.iSubsParams.iTo.Set(sipSubscribeParams->GetTo());
+ if (sipSubscribeParams->GetFrom().Length() == 0)
+ {
+ //The application may fail to supply 'from' in which case we
+ //should reuse the 'from' field stored by the profile.
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- From field not found"), this));
+ sipSubscribeParams->SetFromL(*iFromField);
+ }
+ sipParams.iSubsParams.iFrom.Set(sipSubscribeParams->GetFrom());
+ sipParams.iSubsParams.iContact.Set(sipSubscribeParams->GetContact());
+ sipParams.iSubsParams.iEventType.Set(sipSubscribeParams->GetEventType());
+ sipParams.iSubsParams.iAcceptType.Set(sipSubscribeParams->GetAcceptType());
+ sipParams.iSubsParams.iAcceptSubType.Set(sipSubscribeParams->GetAcceptSubType());
+ sipParams.iSubsParams.iExpires = sipSubscribeParams->GetExpires();
+ sipParams.iSubsParams.iAutoRefresh = sipSubscribeParams->GetAutoRefresh();
+ }
+ else
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- UnSupported Call Description Params"), this));
+ //Send error message to mesh. Error activity will handle it and pass it originator
+ User::Leave(KErrNotSupported);
+ }
+ }
+ if (!authFamily.IsNull())
+ {
+ STypeId idAuth = STypeId::CreateSTypeId(KSubConSIPParametersUid,KSubConSIPAuthenticateParamsType);
+ CSubConSIPAuthenticateParamSet* sipAuthenticateParams = (CSubConSIPAuthenticateParamSet*)authFamily.FindParameterSet(
+ idAuth, RParameterFamily::ERequested);
+
+ if (sipAuthenticateParams)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- CSubConSIPAuthenticateParamSet found"), this));
+
+ TSIPCredentials credentials;
+ credentials.iUserName.Set(sipAuthenticateParams->GetUserName());
+ credentials.iPasswd.Set(sipAuthenticateParams->GetPassword());
+ credentials.iRealm.Set(sipAuthenticateParams->GetRealm());
+ iTransitionEngine->AddCredentialsL(credentials);
+ }
+ else
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t -- UnSupported Authentication Params"), this));
+ //Send error message to mesh. Error activity will handle it and pass it originator
+ User::Leave(KErrNotSupported);
+ }
+ }
+ if(authFamily.IsNull() && calldescrFamily.IsNull())
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::DoParametersAboutToBeSet() [this=%08x]\t --Auth and Call Description Family NULL"), this));
+ //Send error message to mesh. Error activity will handle it and pass it originator
+ User::Leave(KErrNotFound);
+ }
+ }
+
+ void CSipSubConnectionProvider::InitialiseParametersL(TIncomingCallParameters& aCallParams)
+ {
+ RCFParameterFamilyBundle newBundle;
+ iParameterBundle.CreateL();
+ newBundle.CreateL();
+ newBundle.Open(iParameterBundle);
+ RParameterFamily sipCallDescrFamily = newBundle.CreateFamilyL(KSubConnCallDescrParamsFamily);
+ CSubConSIPInviteParamSet* subConSipRequestedParSet =
+ CSubConSIPInviteParamSet::NewL(sipCallDescrFamily, RParameterFamily::ERequested);
+
+ subConSipRequestedParSet->SetRequestUriL(aCallParams.iReqUri);
+ subConSipRequestedParSet->SetFromL(aCallParams.iFrom);
+ subConSipRequestedParSet->SetToL(aCallParams.iTo);
+ subConSipRequestedParSet->SetContentL(aCallParams.iContent);
+ }
+//-=========================================================
+//
+// MSIPStateMachineClient methods
+//
+//-=========================================================
+
+void CSipSubConnectionProvider::CallEstablished()
+ {
+
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::Call Established")));
+
+ //We dont need this error here, neither do we need to pass erro in SessionEstablished message
+ TInt error = KErrNone;
+ ASSERT(iStage == SipSCpr::EStarting);
+ RClientInterface::OpenPostMessageClose(Id(),TNodeCtxId(iActivityAwaitingResponse, Id()),TSipSCprMessages::TSipSessionEstablished(error).CRef());
+ iActivityAwaitingResponse = MeshMachine::KActivityNull;
+ }
+
+
+void CSipSubConnectionProvider::CallTerminated(TInt aError, TInt aSipCode)
+ {
+
+ //The CallTerminated callback method can be triggered in three cases
+ //1. As a result of RsubConnection::Stop(). The UE wants to send a BYE
+ //2. As a result of the remote UE sending a BYE
+ //3. SCPR start fails (in the cases where sip HL API's doesn't support the given SIP method)
+
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::Call Terminated")));
+
+ iStage = SipSCpr::EStopped;
+
+ if(iActivityAwaitingResponse == ECFActivityStart)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::Call Terminated : Activity Start")));
+ RClientInterface::OpenPostMessageClose(Id(),TNodeCtxId(iActivityAwaitingResponse, Id()),TSipSCprMessages::TSipSessionEstablished(aError).CRef());
+ iActivityAwaitingResponse = MeshMachine::KActivityNull;
+ }
+ else if (iActivityAwaitingResponse == ECFActivityStop)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::Call Terminated : Activity Stop")));
+ RClientInterface::OpenPostMessageClose(Id(),TNodeCtxId(iActivityAwaitingResponse, Id()),TSipSCprMessages::TSipSessionTerminated(aError).CRef());
+ iActivityAwaitingResponse = MeshMachine::KActivityNull;
+ }
+ else
+ {
+ // it if for incoming connection
+ //if (iAwaitingSubConnection)
+ // {
+ // When the remote party sends BYE send a notification for which the
+ // app is subscribed to.
+ //Notify the upper layeer about the extended SIP reason for termination
+ CSubConSIPResponseEvent* sipevent = NULL;
+ TRAPD(error, sipevent = CSubConSIPResponseEvent::NewL());
+ if (error != KErrNone)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSubConSIPResponseEvent::NewL() left with the error: [%d]"), error));
+ return;
+ }
+ sipevent->SetResponse(aSipCode);
+ NotifyClientsL(*sipevent);
+ }
+ }
+
+/**
+This is a call-back function of SIP stata machine.
+It will be called when an incoming connection(incoming INVITE) is received with the
+incoming connection parameters
+*/
+void CSipSubConnectionProvider::IncomingCall(TIncomingCallParameters& aCallParams)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::IncomingCall")));
+
+ ASSERT(iStage == SipSCpr::EFresh);
+ TInt error = KErrNone;
+
+ if ((!iAwaitingSubConnection) || !iParameterBundle.IsNull())
+ {
+ //The logic behind this panic is that IncomingCall() should not
+ //arrive, if it doesn't represent an incoming subconnection
+ //that is:
+ // iAwaitingSubConnection has have to be true
+ User::Panic(KPanicSIPSCPRText, KErrBadHandle);
+ }
+
+ TRAP(error, InitialiseParametersL(aCallParams));
+ if (error != KErrNone)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::InitialiseParametersL() left with error [%d]"), error));
+ }
+ //at this point the incoming subconnection has been deemed fit
+ //scpr should now send a TIncomingConnection message to its CPR so that RConn::WaitForIncoming can return
+
+ // post this message to its control provider SIP CPR to send binder response
+ // so that the subcon.open will be returned
+ RNodeInterface* cp = ControlProvider();
+ cp->PostMessage(Id(),SipCpr::TSipCprMessages::TIncomingConnection(0).CRef());
+
+ }
+
+/**
+This is a call-back function of the SIP state machine.
+It will be called when the high-level API ignores the received challenge
+(Response code 401).
+*/
+void CSipSubConnectionProvider::CredentialsRequired(const TDesC8 &/* aRealm*/)
+ {
+
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::CredentialsRequired")));
+
+ ASSERT(iStage == SipSCpr::EStarting);
+ TInt error = KErrNone;
+
+ CSubConSIPAuthenticationRequiredEvent* event = NULL;
+ TRAP(error, event = CSubConSIPAuthenticationRequiredEvent::NewL());
+ if (error != KErrNone)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8(" CSubConSIPAuthenticationRequiredEvent::NewL()left with error [%d]"), error));
+ return;
+ }
+ delete event; // remove this if the following code is uncommented
+ // uncomment the following code if app is subscribed for the event
+ #if 0
+ TRAP(error, event->SetRealmL(aRealm));
+ if (error != KErrNone)
+ {
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSubConSIPAuthenticationRequiredEvent::SetRealmL() left with error [%d]"), error));
+ return;
+ }
+ NotifyClientsL(*event);
+ #endif
+ }
+
+/**
+This is callback function. This will be called when the SIP high-level
+API receives notification for the Subscribe request
+*/
+void CSipSubConnectionProvider::ReceiveNotification(TDesC8 & aNotification)
+ {
+
+ __CFLOG_VAR((KSipSCprTag, KSipSCprSubTag, _L8("CSipSubConnectionProvider::ReceiveNotification")));
+ CSubConSIPNotificationEvent* event = CSubConSIPNotificationEvent::NewL();
+ event->SetNotificationL(aNotification);
+
+ TInt32 gId = event->GroupId();
+
+ NotifyClientsL(*event);
+ }
+
+/**
+Creates SIP high-level state machine
+*/
+void CSipSubConnectionProvider::CreateStateMachineL()
+ {
+ iSipSm = CSipStateMachine::NewL(iTransitionEngine,NodeAddr(), iAwaitingSubConnection);
+ }
+
+// this pointer is used in the creation of the SIP statemachine
+MSIPStateMachineClient* CSipSubConnectionProvider::NodeAddr()
+{
+ return this;
+}