diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogItem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogItem.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,1537 @@ +// 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: +// Name : SipDialogItem.cpp +// Part of : SIPDialogs +// Version : SIP/6.0 +// + + + + +#include "CSipDialogItem.h" +#include "MSipRefreshMgr.h" +#include "MTransactionUser.h" +#include "sipsec.h" +#include "DeleteMgr.h" +#include "MDialogOwner.h" +#include "SipLogs.h" +#include "SipAssert.h" +#include "siprequest.h" +#include "sipresponse.h" +#include "sipcontactheader.h" +#include "siptoheader.h" +#include "sipfromheader.h" +#include "sipcseqheader.h" +#include "sipcallidheader.h" +#include "siprecordrouteheader.h" +#include "siprouteheader.h" +#include "sipaddress.h" +#include "uricontainer.h" +#include "sipuri.h" +#include "Establishing.h" +#include "Early.h" +#include "Confirmed.h" +#include "Terminated.h" +#include "DialogsStore.h" +#include "TransactionItemStore.h" +#include "TransactionItemBase.h" +#include "RefreshItem.h" +#include "TransactionItem.h" +#include "CSigCompMgr.h" +#include "MSigComp.h" +#include "sipcodecutils.h" +#include "sipstrings.h" +#include "sipstrconsts.h" +#include "sipcodecerr.h" +#include "siperr.h" +#include "TSIPTransportParams.h" + +const TUint K100Response = 100; +const TUint K400Response = 400; +const TUint K500Response = 500; + + +// ----------------------------------------------------------------------------- +// CSipDialogItem::NewLC +// ----------------------------------------------------------------------------- +// +CSipDialogItem* CSipDialogItem::NewLC(CDialogsStore& aDialogStore, + MDialogOwner* aDialogOwner, + MSIPSecUser& aSIPSecUser, + MTransactionUser& aTransactionUser, + MSipRefreshMgr& aRefreshMgr, + CSIPSec& aSIPSec, + CDeleteMgr& aDeleteMgr, + MSigComp& aSigComp, + TRegistrationId aRegistrationId) + { + CSipDialogItem* self = new(ELeave)CSipDialogItem(aDialogStore, + aSIPSecUser, + aTransactionUser, + aRefreshMgr, + aSIPSec, + aDeleteMgr, + aSigComp, + aRegistrationId); + CleanupStack::PushL(self); + self->ConstructL(aDialogOwner); + return self; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CSipDialogItem +// ----------------------------------------------------------------------------- +// +CSipDialogItem::CSipDialogItem (CDialogsStore& aDialogStore, + MSIPSecUser& aSIPSecUser, + MTransactionUser& aTransactionUser, + MSipRefreshMgr& aRefreshMgr, + CSIPSec& aSIPSec, + CDeleteMgr& aDeleteMgr, + MSigComp& aSigComp, + TRegistrationId aRegistrationId) +: iRegistrationId(aRegistrationId), + iDialogStore(aDialogStore), + iTU(aTransactionUser), + iRefreshMgr(aRefreshMgr), + iSIPSec(aSIPSec), + iDeleteMgr(aDeleteMgr), + iSigComp(aSigComp), + iSIPSecUser(aSIPSecUser), + iTerminated(*this), + iConfirmed(*this,iTerminated), + iEarly(*this,iConfirmed,iTerminated), + iEstablishing(*this,iEarly,iConfirmed,iTerminated), + iRemoteTagSet(EFalse) + { + iTagParamName = SIPStrings::StringF(SipStrConsts::ETag); + iTransportParamName = SIPStrings::StringF(SipStrConsts::ETransport); + iContactHeaderName = SIPStrings::StringF(SipStrConsts::EContactHeader); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ConstructL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::ConstructL (MDialogOwner* aDialogOwner) + { + __SIP_ASSERT_LEAVE(aDialogOwner, KErrArgument); + + iDialogOwner = aDialogOwner; + iTransactionItemStore = CTransactionItemStore::NewL(); + iSigCompMgr = CSigCompMgr::NewL( + aDialogOwner->TransportParams(KEmptyRegistrationId).IapId(),iSigComp); + + iDialogId = iDialogStore.NewDialogId(); + ChangeState(iEstablishing); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::~CSipDialogItem +// ----------------------------------------------------------------------------- +// +CSipDialogItem::~CSipDialogItem() + { + iTU.ClearTransactionOwner(this); + delete iSigCompMgr; + delete iCallId; + iLocalTag.Close(); + iRemoteTag.Close(); + delete iLocalAddress; + delete iRemoteAddress; + delete iLocalTarget; + delete iRemoteTarget; + iRouteSet.ResetAndDestroy(); + delete iTransactionItemStore; + iSIPSec.ClearCache(this); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::IapId +// ----------------------------------------------------------------------------- +// +TUint32 CSipDialogItem::IapId() + { + return TransportParams(KEmptyRegistrationId).IapId(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RegistrationId +// ----------------------------------------------------------------------------- +// +TRegistrationId CSipDialogItem::RegistrationId() const + { + return iRegistrationId; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::Offset +// ----------------------------------------------------------------------------- +// +TInt CSipDialogItem::Offset () + { + return _FOFF(CSipDialogItem,iLink); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ResetStateL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::ResetStateL() + { + CTransactionItemStore* transactionStore = CTransactionItemStore::NewLC(); + CSigCompMgr* sigCompMgr = + CSigCompMgr::NewL( + iDialogOwner->TransportParams(KEmptyRegistrationId).IapId(), + iSigComp); + CleanupStack::Pop(transactionStore); + iTU.ClearTransactionOwner(this); + iSIPSec.ClearCache(this); + delete iTransactionItemStore; + iTransactionItemStore = transactionStore; + delete iSigCompMgr; + iSigCompMgr = sigCompMgr; + iRemoteTag = SIPStrings::StringF(SipStrConsts::EEmpty); + iRemoteTagSet = EFalse; + ChangeState(iEstablishing); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::DialogOwner +// ----------------------------------------------------------------------------- +// +MDialogOwner* CSipDialogItem::DialogOwner() + { + return iDialogOwner; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::DeleteMgr +// ----------------------------------------------------------------------------- +// +CDeleteMgr& CSipDialogItem::DeleteMgr() + { + return iDeleteMgr; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::Match +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::Match(CSIPRequest& aRequest) const + { + CSIPCallIDHeader* callId = aRequest.CallID(); + CSIPToHeader* to = aRequest.To(); + CSIPFromHeader* from = aRequest.From(); + + if ((callId && *callId == *iCallId) && + (to && + to->HasParam(iTagParamName) && + iLocalTag == to->ParamValue(iTagParamName))) + { + if (iRemoteTagSet) + { + if (from && + from->HasParam(iTagParamName) && + iRemoteTag == from->ParamValue(iTagParamName)) + { + return iCurrentState->Accept(aRequest); + } + } + else + { + return iCurrentState->Accept(aRequest); + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ContactOk +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::ContactOk(const CSIPContactHeader& aContact) + { + if (aContact.Star() || !aContact.SIPAddress()) + { + return EFalse; + } + return (aContact.SIPAddress()->URI().IsSIPURI()); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetFirstTransactionIdId +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetFirstTransactionId(const TTransactionId& aTransactionId) + { + iFirstTransactionId = aTransactionId; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::FirstTransactionId +// ----------------------------------------------------------------------------- +// +TTransactionId CSipDialogItem::FirstTransactionId() + { + return iFirstTransactionId; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::DialogId +// ----------------------------------------------------------------------------- +// +TDialogId CSipDialogItem::DialogId() const + { + return iDialogId; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SelfDestruct +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SelfDestruct () + { + iTU.ClearTransactionOwner(this); + ChangeState(iTerminated); + iDialogStore.Remove(this); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::TerminateForkedDialogs +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::TerminateForkedDialogs (TTransactionId aTransactionId) + { + iDialogStore.RemoveAllEarlyDialogsWith(aTransactionId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::IsEarly +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::IsEarly () const + { + return (iCurrentState == &iEarly); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::TransactionItems +// ----------------------------------------------------------------------------- +// +CTransactionItemStore& CSipDialogItem::TransactionItems () + { + return *iTransactionItemStore; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::HasTransactionItem +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::HasTransactionItem (TTransactionId aTransactionId) + { + return iTransactionItemStore->HasItem(aTransactionId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RemoveTransactionItem +// ----------------------------------------------------------------------------- +// +TInt CSipDialogItem::RemoveTransactionItem(TTransactionId& aTransactionId) + { + return iTransactionItemStore->RemoveItem(aTransactionId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ChangeState +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::ChangeState(TDialogStateBase& aState) + { + if (iCurrentState != &aState) + { + iCurrentState = &aState; + __SIP_INT_LOG1( "CSipDialogItem::ChangeState: ID", iDialogId ) + __SIP_DES8_LOG( "CSipDialogItem::ChangeState: state", aState.Name() ) + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CurrentState +// ----------------------------------------------------------------------------- +// +TDialogStateBase& CSipDialogItem::CurrentState() + { + return *iCurrentState; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CallId +// ----------------------------------------------------------------------------- +// +CSIPCallIDHeader* CSipDialogItem::CallId() + { + return iCallId; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetCallId +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetCallId (CSIPCallIDHeader* aCallId) + { + delete iCallId; + iCallId = aCallId; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::LocalTag +// ----------------------------------------------------------------------------- +// +RStringF CSipDialogItem::LocalTag () + { + return iLocalTag; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetLocalTag +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetLocalTag (RStringF aTag) + { + iLocalTag.Close(); + iLocalTag = aTag.Copy(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RemoteTag +// ----------------------------------------------------------------------------- +// +RStringF CSipDialogItem::RemoteTag () + { + return iRemoteTag; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RemoteTag +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::RemoteTagSet () + { + return iRemoteTagSet; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRemoteTagL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRemoteTagL (CSIPFromToHeaderBase* aFromTo) + { + if (aFromTo->HasParam(iTagParamName)) + { + if (iRemoteTagSet) + { + if (iRemoteTag != aFromTo->ParamValue(iTagParamName)) + { + User::Leave (KErrAlreadyExists); + } + } + else + { + RStringF tmp = aFromTo->ParamValue(iTagParamName); + UpdateRemoteTagForRefreshesL(tmp); + iRemoteTag.Close(); + iRemoteTag = tmp.Copy(); + iRemoteTagSet = ETrue; + } + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::LocalSeqNum +// ----------------------------------------------------------------------------- +// +TUint CSipDialogItem::LocalSeqNum() + { + return iLocalSeqNum; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetLocalSeqNum +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetLocalSeqNum(TUint aNum) + { + iLocalSeqNum = aNum; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RemoteSeqNum +// ----------------------------------------------------------------------------- +// +TUint CSipDialogItem::RemoteSeqNum() + { + return iRemoteSeqNum; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRemoteSeqNum +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRemoteSeqNum(TUint aNum) + { + iRemoteSeqNum = aNum; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::LocalAddress +// ----------------------------------------------------------------------------- +// +const CSIPAddress* CSipDialogItem::LocalAddress() + { + return iLocalAddress; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetLocalAddressL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetLocalAddressL (const CSIPAddress& aAddr) + { + CSIPAddress* tmp = CSIPAddress::NewL(aAddr); + delete iLocalAddress; + iLocalAddress = tmp; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RemoteAddress +// ----------------------------------------------------------------------------- +// +const CSIPAddress* CSipDialogItem::RemoteAddress() + { + return iRemoteAddress; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRemoteAddressL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRemoteAddressL (const CSIPAddress& aAddr) + { + CSIPAddress* tmp = CSIPAddress::NewL(aAddr); + delete iRemoteAddress; + iRemoteAddress = tmp; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RemoteTarget +// ----------------------------------------------------------------------------- +// +CURIContainer* CSipDialogItem::RemoteTarget() + { + return iRemoteTarget; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetInitialRemoteTargetL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetInitialRemoteTargetL (CURIContainer& aUri) + { + CURIContainer* tmp = CURIContainer::NewL(aUri); + delete iRemoteTarget; + iRemoteTarget = tmp; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRemoteTargetL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRemoteTargetL (CURIContainer& aUri) + { + __ASSERT_ALWAYS(aUri.IsSIPURI(), User::Leave(KErrSIPInvalidURIType)); + if (iLocalTarget) + { + CSIPURI* localTargetURI = iLocalTarget->SIPAddress()->URI().SIPURI(); + iSigCompMgr->UpdateL(aUri,iRouteSet,*localTargetURI); + } + CURIContainer* tmp = CURIContainer::NewL(aUri); + if (iTransactionItemStore->HasRefreshedItems()) + { + CleanupStack::PushL(tmp); + iRefreshMgr.UpdateRemoteTargetL(this,*tmp); + CleanupStack::Pop(tmp); + } + delete iRemoteTarget; + iRemoteTarget = tmp; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRemoteTargetWithMsgL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRemoteTargetWithMsgL (CSIPMessage& aMsg) + { + CSIPContactHeader* contact = static_cast + (aMsg.Header(iContactHeaderName,0)); + if (contact && contact->SIPAddress()) + { + SetRemoteTargetL(contact->SIPAddress()->URI()); + // Contact is updated only for outgoing requests + UpdateTransportForNextHopAndLocalTargetL(NULL); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::LocalTarget +// ----------------------------------------------------------------------------- +// +CSIPContactHeader* CSipDialogItem::LocalTarget() + { + return iLocalTarget; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetLocalTargetL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetLocalTargetL(CSIPContactHeader& aContact, + TBool aUpdateSigCompParam) + { + __ASSERT_ALWAYS(aContact.SIPAddress(), + User::Leave(KErrSIPInvalidURIType)); + CURIContainer& contactURI = aContact.SIPAddress()->URI(); + __ASSERT_ALWAYS(contactURI.IsSIPURI(), User::Leave(KErrSIPInvalidURIType)); + if (iRouteSet.Count() > 0 && iRouteSet[0] != NULL && + iRouteSet[0]->SIPAddress().URI().IsSIPURI() && + iRouteSet[0]->SIPAddress().URI().SIPURI()->IsSIPSURI()) + { + // Next hop has sips-scheme + aContact.SIPAddress()->URI().SIPURI()->SetSIPS(ETrue); + } + if (iRemoteTarget) + { + iSigCompMgr->UpdateL(*iRemoteTarget, iRouteSet, + *contactURI.SIPURI(), aUpdateSigCompParam); + } + CSIPContactHeader* tmp = static_cast(aContact.CloneL()); + delete iLocalTarget; + iLocalTarget = tmp; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetLocalTargetWithMsgL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetLocalTargetWithMsgL(CSIPMessage& aMsg, + TBool aUpdateSigCompParam) + { + CSIPContactHeader* contact = + static_cast(aMsg.Header(iContactHeaderName,0)); + if (contact) + { + SetLocalTargetL(*contact,aUpdateSigCompParam); + UpdateTransportForNextHopAndLocalTargetL(contact); + if (aMsg.IsRequest()) + { + // UpdateTransportForNextHopAndLocalTargetL + // may have updated the next hop transport + aMsg.DeleteHeaders(SIPStrings::StringF(SipStrConsts::ERouteHeader)); + AddRouteToMessageL(aMsg); + } + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRouteSetL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRouteSetL(RPointerArray& aRoute) + { + RPointerArray* routeSet = + new(ELeave)RPointerArray; + TCleanupItem cleanupItem(CleanupRouteSet,routeSet); + CleanupStack::PushL (cleanupItem); + + for (TInt i=0; i < aRoute.Count(); i++) + { + CSIPRouteHeader* routeHeader = + SIPCodecUtils::CreateRouteHeaderLC(*(aRoute[i])); + User::LeaveIfError(routeSet->Append(routeHeader)); + CleanupStack::Pop(routeHeader); + } + + /* Ownership is transferred for routeset, so popping routset before passing + * to SetRouteSet() + */ + CleanupStack::Pop(1); // cleanupItem + SetRouteSet(routeSet); // ownership transferred + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRouteSetUsingRouteL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRouteSetUsingRouteL (CSIPMessage& aMessage) + { + TSglQueIter iter = + aMessage.Headers(SIPStrings::StringF(SipStrConsts::ERouteHeader)); + + RPointerArray* routeSet = + new(ELeave)RPointerArray; + TCleanupItem cleanupItem(CleanupRouteSet,routeSet); + CleanupStack::PushL (cleanupItem); + + while (iter) + { + CSIPHeaderBase* header = iter++; + CSIPRouteHeader* newRoute = + static_cast(header->CloneL()); + CleanupStack::PushL(newRoute); + User::LeaveIfError(routeSet->Append(newRoute)); + CleanupStack::Pop(newRoute); + } + + /* Ownership is transferred for routeset, so popping routset before passing + * to SetRouteSet() + */ + CleanupStack::Pop(1); // cleanupItem + SetRouteSet(routeSet); // ownership transferred + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRouteSetUsingRecordRouteL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRouteSetUsingRecordRouteL (CSIPMessage& aMessage, + TBool aIsUAC, + TInt aLeaveCode) + { + TSglQueIter iter = + aMessage.Headers(SIPStrings::StringF(SipStrConsts::ERecordRouteHeader)); + + if (iter) + { + RPointerArray* routeSet = + new(ELeave)RPointerArray; + TCleanupItem cleanupItem(CleanupRouteSet,routeSet); + CleanupStack::PushL (cleanupItem); + + while (iter) + { + CSIPHeaderBase* header = iter++; + CSIPRecordRouteHeader* recRoute = + static_cast(header); + CSIPRouteHeader* newRoute = + SIPCodecUtils::CreateRouteHeaderLC(*recRoute); + if (aIsUAC) + { + User::LeaveIfError(routeSet->Insert(newRoute, 0)); + } + else + { + User::LeaveIfError(routeSet->Append(newRoute)); + } + CleanupStack::Pop(newRoute); + } + CSIPRouteHeader* firstRoute = (*routeSet)[0]; + if (!firstRoute->SIPAddress().URI().IsSIPURI()) + { + User::Leave(aLeaveCode); + } + iRefreshMgr.UpdateRouteSetsL(this,*routeSet); + + /* Ownership is transferred for routeset, so popping routset before passing + * to SetRouteSet() + */ + CleanupStack::Pop(1); // cleanupItem + SetRouteSet(routeSet); // ownership transferred + + } + else + { + iRefreshMgr.RemoveRouteSets(this); + iRouteSet.ResetAndDestroy(); + } + // Route updated, tell Refreshes not to include Registration Id + // for the calls to TU anymore. + iRefreshMgr.SetRegistrationIdsEmpty(this); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SetRouteSet +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::SetRouteSet (RPointerArray* aRouteSet) + { + iRouteSet.ResetAndDestroy(); + if (aRouteSet) + { + iRouteSet = *aRouteSet; + + delete aRouteSet; + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::HasRouteSet +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::HasRouteSet() const + { + return (iRouteSet.Count() > 0); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::AddRouteToMessageL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::AddRouteToMessageL(CSIPMessage& aMessage) + { + for (TInt i=0; i < iRouteSet.Count(); i++) + { + CSIPRouteHeader* route = + static_cast(iRouteSet[i]->CloneL()); + CleanupStack::PushL(route); + aMessage.AddHeaderL(route); + CleanupStack::Pop(route); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::AddRecordRouteToMessageL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::AddRecordRouteToMessageL(CSIPMessage& aMessage) + { + for (TInt i=0; i < iRouteSet.Count(); i++) + { + CSIPRecordRouteHeader* route = + SIPCodecUtils::CreateRecordRouteHeaderLC(*(iRouteSet[i])); + aMessage.AddHeaderL(route); + CleanupStack::Pop(route); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::AddToHeaderInDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::AddToHeaderInDialogL(CSIPRequest& aRequest) + { + if (!aRequest.To()) + { + CSIPAddress* address = CSIPAddress::NewLC(*iRemoteAddress); + CSIPToHeader* to = CSIPToHeader::NewL(address); + CleanupStack::Pop(address); + CleanupStack::PushL(to); + if (iRemoteTagSet) + { + to->SetParamL(iTagParamName,iRemoteTag); + } + aRequest.AddHeaderL(to); + CleanupStack::Pop(to); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::AddFromHeaderInDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::AddFromHeaderInDialogL(CSIPRequest& aRequest) + { + if (!aRequest.From()) + { + CSIPAddress* address = CSIPAddress::NewLC(*iLocalAddress); + CSIPFromHeader* from = CSIPFromHeader::NewL(address); + CleanupStack::Pop(address); + CleanupStack::PushL(from); + from->SetParamL(iTagParamName,iLocalTag); + aRequest.AddHeaderL(from); + CleanupStack::Pop(from); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::AddCallIdHeaderInDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::AddCallIdHeaderInDialogL(CSIPMessage& aMessage) + { + if (!aMessage.CallID()) + { + CSIPCallIDHeader* callId = + static_cast(iCallId->CloneL()); + CleanupStack::PushL(callId); + aMessage.AddHeaderL(callId); + CleanupStack::Pop(callId); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::AddCSeqHeaderInDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::AddCSeqHeaderInDialogL(CSIPRequest& aRequest) + { + if (!aRequest.CSeq()) + { + CSIPCSeqHeader* cseq = + CSIPCSeqHeader::NewLC(iLocalSeqNum+1,aRequest.Method()); + aRequest.AddHeaderL(cseq); + CleanupStack::Pop(cseq); + iLocalSeqNum++; + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ReceiveL +// From MTransactionOwner: +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::ReceiveL (TTransactionId aTransactionId, + CSIPResponse* aResponse) + { + __SIP_ASSERT_LEAVE(aTransactionId, KErrSIPInvalidDialogResponse); + __SIP_ASSERT_LEAVE(aResponse, KErrSIPInvalidDialogResponse); + CTransactionItemBase* transactionItem = + iTransactionItemStore->FindItem(aTransactionId); + __SIP_ASSERT_LEAVE (transactionItem, KErrNotFound); + + __SIP_MESSAGE_LOG("Dialogs", *aResponse) + + if (transactionItem->TargetRefresh()) + { + CheckContactsL(aTransactionId,*aResponse); + } + + CSIPToHeader* to = aResponse->To(); + if (!CheckResponse(aResponse) || + (aResponse->ResponseCode() > K100Response && + iRemoteTagSet && iRemoteTag != to->ParamValue(iTagParamName) && + aTransactionId != FirstTransactionId())) + { + iDialogOwner->DialogsError(aTransactionId,KEmptyRefreshId,iDialogId, + KErrSIPInvalidDialogResponse); + delete aResponse; + return; + } + + if (aResponse->ResponseCode() > K100Response && + !aResponse->IsErrorResponse() && + iRemoteTagSet && + iRemoteTag != to->ParamValue(iTagParamName)) + { + if(to->HasParam(iTagParamName)) + { + CSipDialogItem* dialog = + iDialogStore.FindDialogItemForPass(aTransactionId,aResponse); + if(!dialog) + { + dialog = CreateForkingDialogLC(); + dialog->SetRemoteTagL(to); + dialog->ReceiveL(aTransactionId, aResponse); + iDialogStore.AddDialogItem(dialog); + CleanupStack::Pop(dialog); + } + else + { + dialog->ReceiveL(aTransactionId, aResponse); + } + return; + } + } + + iCurrentState->ReceiveL(*transactionItem,aResponse); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ReceiveL +// From MTransactionOwner: +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::ReceiveL (TUint32 aIapId, + TTransactionId aTransactionId, + CSIPRequest* aRequest) + { + __SIP_ASSERT_LEAVE(aTransactionId, KErrSIPInvalidDialogResponse); + __SIP_ASSERT_LEAVE(aRequest, KErrSIPInvalidDialogRequest); + __SIP_ASSERT_LEAVE(CheckRequest(aRequest), KErrSIPMalformedMessage); + __SIP_ASSERT_LEAVE(aIapId == IapId(), KErrArgument); + __SIP_MESSAGE_LOG("Dialogs", *aRequest) + + TSIPTransportParams transportParams(TransportParams(KEmptyRegistrationId)); + if (!CheckContacts(*aRequest)) + { + if (aRequest->Method() == SIPStrings::StringF(SipStrConsts::EAck)) + { + iDialogOwner->DialogsError(aTransactionId, KEmptyRefreshId, + iDialogId, KErrSIPNoAckReceived); + delete aRequest; + return; + } + CSIPResponse* response = + CSIPResponse::NewLC(K400Response, + SIPStrings::StringF(SipStrConsts::EPhraseBadRequest)); + iTU.SendL(aTransactionId, response, this, transportParams); + CleanupStack::Pop(response); + delete aRequest; + return; + } + + // check cseq compared to iRemoteSeqNum + if (aRequest->Method() != SIPStrings::StringF(SipStrConsts::EAck)) + { + if (iRemoteSeqNum > aRequest->CSeq()->Seq()) + { + CSIPResponse* response = + CSIPResponse::NewLC(K500Response, + SIPStrings::StringF( + SipStrConsts::EPhraseServerInternalError)); + iTU.SendL(aTransactionId, response, this, transportParams); + CleanupStack::Pop(response); + delete aRequest; + return; + } + } + + iRemoteSeqNum = aRequest->CSeq()->Seq(); + CTransactionItem* transactionItem = + CTransactionItem::NewLC(iTU,this,aTransactionId,aRequest->Method()); + iCurrentState->ReceiveL(aTransactionId, aRequest); + iTransactionItemStore->AddItem(transactionItem); + CleanupStack::Pop(transactionItem); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::TransactionEnded +// From MTransactionOwner: +// ----------------------------------------------------------------------------- +// +TInt CSipDialogItem::TransactionEnded (TUint32 /*aIapId*/, + TTransactionId aTransactionId, + TInt aReason) + { + TInt err = KErrNone; + + CTransactionItemBase* item = + iTransactionItemStore->FindItem(aTransactionId); + if (item && + aReason == KErrNone && + item->Method() == SIPStrings::StringF(SipStrConsts::EInvite)) + { + err = iDialogOwner->InviteTransactionCompleted(aTransactionId); + } + + iDialogStore.TransactionEnded(aTransactionId,aReason); + + return err; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::NextCSeq +// From MTransactionOwner: +// ----------------------------------------------------------------------------- +// +TInt CSipDialogItem::NextCSeq(TUint& aCSeq) + { + aCSeq = ++iLocalSeqNum; + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SIPSecUser +// From MTransactionOwner: +// ----------------------------------------------------------------------------- +// +const MSIPSecUser* CSipDialogItem::SIPSecUser() const + { + return this; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RefreshReceivedL +// From MRefreshOwner: +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::RefreshReceivedL (TTransactionId aTransactionId, + TRefreshId aRefreshId, + CSIPResponse* aResponse) + { + __SIP_ASSERT_LEAVE(aTransactionId, KErrSIPInvalidDialogResponse); + __SIP_ASSERT_LEAVE(aResponse, KErrSIPInvalidDialogResponse); + __SIP_MESSAGE_LOG("Dialogs", *aResponse) + + // Check Call-ID, CSeq and From-tag + if (!CheckResponse(aResponse)) + { + iDialogOwner->DialogsError(aTransactionId, aRefreshId, iDialogId, + KErrSIPInvalidDialogResponse); + delete aResponse; + return; + } + + CRefreshItem* item = iTransactionItemStore->FindRefreshItem(aRefreshId); + if (!item) + { + iDialogOwner->DialogsError(aTransactionId,aRefreshId,iDialogId, + KErrSIPInvalidTransactionState); + delete aResponse; + return; + } + + if (iRemoteTagSet) + { + if (iRemoteTag != aResponse->To()->ParamValue(iTagParamName)) + { + iDialogOwner->DialogsError(aTransactionId,aRefreshId,iDialogId, + KErrSIPInvalidDialogResponse); + delete aResponse; + return; + } + } + + if (item->TargetRefresh()) + { + CheckContactsL(aTransactionId,*aResponse); + } + + if (aResponse->IsErrorResponse()) + { + item->SetTerminated(); + } + + item->SetTransactionId(aTransactionId); + iCurrentState->ReceiveL(*item, aResponse); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RefreshError +// From MRefreshOwner: +// ----------------------------------------------------------------------------- +// +TInt CSipDialogItem::RefreshError (TRefreshId aRefreshId, + TTransactionId aTransactionId, + TInt aReason) + { + CTransactionItemBase* refreshItem = + iTransactionItemStore->FindItem(aTransactionId); + if (!refreshItem) + { + refreshItem = iTransactionItemStore->FindRefreshItem(aRefreshId); + if (!refreshItem) + { + return KErrArgument; + } + } + refreshItem->SetTransactionId(aTransactionId); + iDialogStore.TransactionEnded(refreshItem->Id(),aReason); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::NextRefreshCSeq +// From MRefreshOwner: +// ----------------------------------------------------------------------------- +// +TInt CSipDialogItem::NextRefreshCSeq(TUint& aCSeq) + { + return NextCSeq(aCSeq); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::TransportParams +// From MRefreshOwner: +// ----------------------------------------------------------------------------- +// +TSIPTransportParams CSipDialogItem::TransportParams( + const TRegistrationId& aRegistrationId) + { + TSIPTransportParams transportParams( + iDialogOwner->TransportParams(aRegistrationId)); + if (aRegistrationId == KEmptyRegistrationId) + { + // Registration id is set empty after receiving the first + // response to the refreshed initial request. + // See function SetRouteSetUsingRecordRouteL. + transportParams.SetCompartmentId(iSigCompMgr->CompartmentId()); + } + return transportParams; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::SIPSecUser +// From MRefreshOwner: +// ----------------------------------------------------------------------------- +// +const MSIPSecUser* CSipDialogItem::SIPSecUser( + const TRegistrationId& aRegistrationId) + { + return iDialogOwner->SIPSecUser(aRegistrationId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RefreshDurationL +// ----------------------------------------------------------------------------- +// +TUint CSipDialogItem::RefreshDurationL() + { + User::Leave(KErrNotFound); + return 0; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::PassOnlyRealmsToUser +// From MSIPSecUser: +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::PassOnlyRealmsToUser() const + { + return iSIPSecUser.PassOnlyRealmsToUser(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RequestCredentialsL +// From MSIPSecUser: +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::RequestCredentialsL(const TDesC8& aRealm) + { + iSIPSecUser.RequestCredentialsL(aRealm); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::RequestCredentialsL +// From MSIPSecUser: +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::RequestCredentialsL(CSIPResponse& aResponse, + TTransactionId aTransactionId, + TRefreshId aRefreshId) + { + iSIPSecUser.RequestCredentialsL(aResponse,aTransactionId,aRefreshId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::TrustedUser +// From MSIPSecUser: +// ----------------------------------------------------------------------------- +// +const MSIPSecUser* CSipDialogItem::TrustedUser( + TRegistrationId /*aRegistrationId*/) + { + return iDialogOwner->SIPSecUser(iRegistrationId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ByPassSIPSec +// From MSIPSecUser: +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::ByPassSIPSec() const + { + const MSIPSecUser* trustedUser = iDialogOwner->SIPSecUser(iRegistrationId); + if (trustedUser) + { + // Use the same value as the related registration, if possible + return trustedUser->ByPassSIPSec(); + } + return iSIPSecUser.ByPassSIPSec(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::EndTransaction +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::EndTransaction (TTransactionId aTransactionId, + TInt aReason) + { + CTransactionItemBase* transactionItem = + iTransactionItemStore->FindItem(aTransactionId); + if (transactionItem) + { + iCurrentState->EndTransaction(*transactionItem, aReason); + iTransactionItemStore->RemoveItem(transactionItem->Id()); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CheckResponse +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::CheckResponse(CSIPResponse* aResponse) + { + CSIPCallIDHeader* callId = aResponse->CallID(); + if (!callId) + { + return EFalse; + } + if (!(*iCallId == *callId)) + { + return EFalse; + } + CSIPFromHeader* from = aResponse->From(); + if (!from) + { + return EFalse; + } + if (iLocalTag != from->ParamValue(iTagParamName)) + { + return EFalse; + } + if (!aResponse->CSeq()) + { + return EFalse; + } + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CheckRequest +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::CheckRequest(CSIPRequest* aRequest) + { + CSIPCallIDHeader* callId = aRequest->CallID(); + if (!callId) + { + return EFalse; + } + if (!(*iCallId == *callId)) + { + return EFalse; + } + CSIPToHeader* to = aRequest->To(); + if (!to) + { + return EFalse; + } + if (iLocalTag != to->ParamValue(iTagParamName)) + { + return EFalse; + } + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::UpdateRemoteTagForRefreshesL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::UpdateRemoteTagForRefreshesL (RStringF aRemoteTag) + { + RArray ids = iTransactionItemStore->RefreshItemIdsL(); + CleanupClosePushL(ids); + for (TInt i=0; iTo(); + if (refreshReqTo && !refreshReqTo->HasParam(iTagParamName)) + { + refreshReqTo->SetParamL(iTagParamName,aRemoteTag); + } + } + } + CleanupStack::PopAndDestroy(1); // ids + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::UpdateLocalTargetL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::UpdateLocalTargetL(CSIPMessage& aMessage) + { + SetLocalTargetWithMsgL(aMessage); + CSIPContactHeader* contact = + static_cast(aMessage.Header(iContactHeaderName,0)); + + RArray ids = iTransactionItemStore->RefreshItemIdsL(); + CleanupClosePushL(ids); + for (TInt i=0; i(contact->CloneL()); + CleanupStack::PushL(newContact); + iRefreshMgr.UpdateHeaderL(ids[i],this,newContact); + CleanupStack::Pop(newContact); + } + CleanupStack::PopAndDestroy(1); // ids + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CheckContacts +// ----------------------------------------------------------------------------- +// +TBool CSipDialogItem::CheckContacts (CSIPMessage& aMessage, + TBool aContactRequired) const + { + TInt contactCount = aMessage.HeaderCount(iContactHeaderName); + if (contactCount == 1) + { + CSIPContactHeader* contact = + static_cast( + aMessage.Header(iContactHeaderName,0)); + if (!ContactOk(*contact)) + { + return EFalse; + } + } + if (aContactRequired) + { + return (contactCount == 1); + } + return (contactCount <= 1); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CheckContactsL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::CheckContactsL (TTransactionId aTransactionId, + CSIPResponse& aResponse) const + { + if (aResponse.ResponseCode() > K100Response && + !aResponse.IsErrorResponse()) + { + TBool contactRequired = + (aResponse.Type() == CSIPResponse::E2XX && + aTransactionId == iFirstTransactionId); + if (!CheckContacts(aResponse,contactRequired)) + { + User::Leave(KErrSIPInvalidDialogResponse); + } + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CreateForkingDialogLC +// ----------------------------------------------------------------------------- +// +CSipDialogItem* CSipDialogItem::CreateForkingDialogLC () + { + CSipDialogItem* dialog = + CSipDialogItem::NewLC(iDialogStore,iDialogOwner,iSIPSecUser,iTU, + iRefreshMgr,iSIPSec,iDeleteMgr,iSigComp); + + //copy the first TransactionItem from parent dialog + TTransactionId firstTransactionId = iFirstTransactionId; + CTransactionItemBase* firstTransactionItem = + iTransactionItemStore->FindItem(firstTransactionId); + __ASSERT_ALWAYS (firstTransactionItem, User::Leave(KErrGeneral)); + + CTransactionItemBase* forkingTransactionItem = + CTransactionItem::NewL(iTU,this,*firstTransactionItem); + + dialog->TransactionItems().AddItem(forkingTransactionItem); + + dialog->SetFirstTransactionId(iFirstTransactionId); + + CSIPCallIDHeader* callIdHeader = + static_cast(iCallId->CloneL()); + dialog->SetCallId(callIdHeader); + dialog->SetLocalTag(iLocalTag); + + __SIP_ASSERT_LEAVE(iLocalAddress, KErrArgument); + dialog->SetLocalAddressL(*iLocalAddress); + + __SIP_ASSERT_LEAVE(iRemoteAddress, KErrArgument); + dialog->SetRemoteAddressL(*iRemoteAddress); + + dialog->SetLocalSeqNum(iLocalSeqNum); + + __SIP_ASSERT_LEAVE(iLocalTarget, KErrArgument); + dialog->SetLocalTargetL(*iLocalTarget); + + return dialog; + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::UpdateTransportForNextHopAndLocalTargetL +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::UpdateTransportForNextHopAndLocalTargetL( + CSIPContactHeader* aContactInOutgoingRequest) + { + CSIPURI& localTarget = ExtractUriL(iLocalTarget); + RStringF localTargetTransport = localTarget.ParamValue(iTransportParamName); + + CSIPURI* nextHop = NULL; + if (iRouteSet.Count() > 0) + { + CURIContainer& uri = iRouteSet[0]->SIPAddress().URI(); + __ASSERT_ALWAYS(uri.IsSIPURI(), User::Leave(KErrSIPInvalidURIType)); + nextHop = uri.SIPURI(); + } + else + { + __ASSERT_ALWAYS(iRemoteTarget, User::Leave(KErrNotFound)); + __ASSERT_ALWAYS(iRemoteTarget->IsSIPURI(), + User::Leave(KErrSIPInvalidURIType)); + nextHop = iRemoteTarget->SIPURI(); + } + RStringF nextHopTransport = nextHop->ParamValue(iTransportParamName); + + if (nextHopTransport.DesC().Length() > 0) + { + if (localTargetTransport.DesC().Length() == 0 && + !localTarget.IsSIPSURI()) + { + localTarget.SetParamL(iTransportParamName,nextHopTransport); + if (aContactInOutgoingRequest) + { + CSIPURI& contactUri = ExtractUriL(aContactInOutgoingRequest); + contactUri.SetParamL(iTransportParamName,nextHopTransport); + } + } + } + else + { + if (localTargetTransport.DesC().Length() > 0 && + !nextHop->IsSIPSURI()) + { + nextHop->SetParamL(iTransportParamName,localTargetTransport); + } + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::ExtractUriL +// ----------------------------------------------------------------------------- +// +CSIPURI& CSipDialogItem::ExtractUriL(CSIPContactHeader* aContact) + { + __ASSERT_ALWAYS(aContact, User::Leave(KErrNotReady)); + __ASSERT_ALWAYS(aContact->SIPAddress(), User::Leave(KErrNotReady)); + __ASSERT_ALWAYS(aContact->SIPAddress()->URI().IsSIPURI(), + User::Leave(KErrSIPInvalidURIType)); + return *(aContact->SIPAddress()->URI().SIPURI()); + } + +// ----------------------------------------------------------------------------- +// CSipDialogItem::CleanupRouteSet +// ----------------------------------------------------------------------------- +// +void CSipDialogItem::CleanupRouteSet (TAny* aRouteSet) + { + RPointerArray* routeSet = + reinterpret_cast*>(aRouteSet); + if (routeSet) + { + routeSet->ResetAndDestroy(); + } + delete routeSet; + }