diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogMgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/Dialogs/src/SipDialogMgr.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,912 @@ +// 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: +// Name : SipDialogMgr.cpp +// Part of : SIPDialogs +// Version : SIP/4.0 +// + + + + +#include "CSipDialogMgr.h" +#include "sipfromheader.h" +#include "DialogStateBase.h" +#include "MSipRegistrationContact.h" +#include "MTransactionUser.h" +#include "MSipRefreshMgr.h" +#include "MDialogOwner.h" +#include "DeleteMgr.h" +#include "sipcontactheader.h" +#include "siprequest.h" +#include "sipresponse.h" +#include "siptoheader.h" +#include "sipcallidheader.h" +#include "sipcseqheader.h" +#include "SipLogs.h" +#include "sipaddress.h" +#include "siphostport.h" +#include "uricontainer.h" +#include "sipuri.h" +#include "sipcodecutils.h" +#include "sipinternalstates.h" +#include "MTransactionHeaders.h" +#include "siprouteheader.h" +#include "DialogsStore.h" +#include "SipAssert.h" +#include "RefreshItem.h" +#include "TransactionItem.h" +#include "TransactionItemStore.h" +#include "Establishing.h" +#include "Early.h" +#include "Confirmed.h" +#include "Terminated.h" +#include "CSigCompMgr.h" +#include "sipstrings.h" +#include "sipstrconsts.h" +#include "siperr.h" +#include "TSIPTransportParams.h" + +_LIT8(KLocalHostSIPURI, "sip:localhost"); +const TUint K100Response = 100; +const TUint K400Response = 400; +const TUint K481Response = 481; + + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::NewL +// ----------------------------------------------------------------------------- +// +CSipDialogMgr* CSipDialogMgr::NewL( + MTransactionUser& aTU, + MSipRefreshMgr& aRefreshMgr, + MSipRegistrationContact& aRegistrationContact, + CSIPSec& aSIPSec, + MSigComp& aSigComp) + { + CSipDialogMgr* self = new(ELeave)CSipDialogMgr(aTU,aRefreshMgr, + aRegistrationContact, + aSIPSec, aSigComp); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::CSipDialogMgr +// ----------------------------------------------------------------------------- +// +CSipDialogMgr::CSipDialogMgr (MTransactionUser& aTU, + MSipRefreshMgr& aRefreshMgr, + MSipRegistrationContact& aRegistratinonContact, + CSIPSec& aSIPSec, + MSigComp& aSigComp) +: iTU(aTU), + iRefreshMgr(aRefreshMgr), + iRegistrationContact(aRegistratinonContact), + iSIPSec(aSIPSec), + iSigComp(aSigComp) + { + iContactHeaderName = SIPStrings::StringF(SipStrConsts::EContactHeader); + iRouteHeaderName = SIPStrings::StringF(SipStrConsts::ERouteHeader); + iTagParamName = SIPStrings::StringF(SipStrConsts::ETag); + iPhraseCallTransactionDoesNotExist = + SIPStrings::StringF(SipStrConsts::EPhraseCallTransactionDoesNotExist); + iPhraseBadRequest = SIPStrings::StringF(SipStrConsts::EPhraseBadRequest); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::ConstructL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::ConstructL () + { + iDialogsStore = CDialogsStore::NewL(); + iDeleteMgr = CDeleteMgr::NewL(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::~CSipDialogMgr +// ----------------------------------------------------------------------------- +// +CSipDialogMgr::~CSipDialogMgr () + { + delete iDialogsStore; + delete iDeleteMgr; + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SendAndCreateDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::SendAndCreateDialogL (TTransactionId& aTransactionId, + TRefreshId& aRefreshId, + TRegistrationId aRegistrationId, + TDialogId& aDialogId, + CSIPRequest* aRequest, + CURIContainer& aRemoteTarget, + MDialogOwner* aOwner, + MSIPSecUser& aSIPSecUser, + TBool aRefresh) + { + __SIP_ASSERT_LEAVE(aOwner, KErrArgument); + __SIP_ASSERT_LEAVE(aRequest, KErrArgument); + __SIP_ASSERT_LEAVE(aRequest->To(), KErrSIPMalformedMessage); + __SIP_ASSERT_LEAVE(aRequest->From(), KErrSIPMalformedMessage); + __SIP_ASSERT_LEAVE(aRequest->Method().DesC().Length() > 0, + KErrSIPMalformedMessage); + __SIP_ASSERT_LEAVE(aRequest->HeaderCount(iContactHeaderName) <= 1, + KErrSIPMalformedMessage); + __SIP_MESSAGE_LOG("Dialogs", *aRequest) + + TBool newDialogCreated = EFalse; + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + if (!dialog) + { + dialog = CSipDialogItem::NewLC(*iDialogsStore,aOwner,aSIPSecUser,iTU, + iRefreshMgr,iSIPSec,*iDeleteMgr, + iSigComp,aRegistrationId); + newDialogCreated = ETrue; + } + + dialog->SetLocalAddressL(aRequest->From()->SIPAddress()); + dialog->SetRemoteAddressL(aRequest->To()->SIPAddress()); + dialog->SetInitialRemoteTargetL(aRemoteTarget); + dialog->SetRouteSetUsingRouteL(*aRequest); + AddContactHeaderL(dialog->IapId(),aRegistrationId, + *aRequest,aRequest->From()); + dialog->SetLocalTargetWithMsgL(*aRequest,EFalse); + + CTransactionItemBase* transactionItem = 0; + if (aRefresh) + { + transactionItem = CRefreshItem::NewLC(iRefreshMgr,dialog, + *dialog,aRequest->Method()); + } + else + { + transactionItem = CTransactionItem::NewLC(iTU,dialog, + aRequest->Method()); + } + transactionItem->SetTargetRefresh(); + + dialog->CurrentState().SendL(aTransactionId,aRequest,*transactionItem, + *dialog->RemoteTarget()); + + dialog->TransactionItems().AddItem(transactionItem); + CleanupStack::Pop(transactionItem); + dialog->SetFirstTransactionId(aTransactionId); + + if (newDialogCreated) + { + aDialogId = dialog->DialogId(); + iDialogsStore->AddDialogItem(dialog); + CleanupStack::Pop(dialog); + } + + if (aRefresh) + { + aRefreshId = static_cast(transactionItem)->RefreshId(); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SendWithinDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::SendWithinDialogL (TTransactionId& aTransactionId, + TRefreshId& aRefreshId, + const TDialogId& aDialogId, + CSIPRequest* aRequest, + const MDialogOwner* aOwner, + TBool aRefresh, + TBool aAllowOverlap, + TBool aTargetRefresh) + { + __SIP_ASSERT_LEAVE(aDialogId, KErrArgument); + __SIP_ASSERT_LEAVE(aRequest, KErrArgument); + __SIP_ASSERT_LEAVE(aRequest->Method().DesC().Length() != 0, + KErrSIPMalformedMessage); + __SIP_ASSERT_LEAVE(aRequest->HeaderCount(iContactHeaderName) <= 1, + KErrSIPMalformedMessage); + __ASSERT_ALWAYS(!aRequest->HasHeader(iRouteHeaderName), + User::Leave(KErrSIPMalformedMessage)); + + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + __ASSERT_ALWAYS(dialog, User::Leave(KErrSIPInvalidDialogState)); + __ASSERT_ALWAYS(dialog->CurrentState().RequestsWithinDialogAllowed(), + User::Leave(KErrSIPInvalidDialogState)); + + RStringF method = aRequest->Method(); + if (dialog->TransactionItems().OverlappingRestricted(method)) + { + User::Leave(KErrSIPRequestPending); + } + + __SIP_MESSAGE_LOG("Dialogs", *aRequest) + + dialog->AddToHeaderInDialogL(*aRequest); + dialog->AddFromHeaderInDialogL(*aRequest); + dialog->AddCallIdHeaderInDialogL(*aRequest); + dialog->AddRouteToMessageL(*aRequest); + AddContactHeaderL(*dialog,*aRequest,aRequest->From(),aTargetRefresh); + if (aTargetRefresh) + { + dialog->UpdateLocalTargetL(*aRequest); + } + if (method != SIPStrings::StringF(SipStrConsts::EAck)) + { + dialog->AddCSeqHeaderInDialogL(*aRequest); + } + + CTransactionItemBase* transactionItem = 0; + if (aRefresh) + { + transactionItem = + CRefreshItem::NewLC(iRefreshMgr,dialog,*dialog,method); + } + else + { + transactionItem = CTransactionItem::NewLC(iTU,dialog,method); + } + transactionItem->SetOverlappingRestricted(!aAllowOverlap); + transactionItem->SetTargetRefresh(aTargetRefresh); + + dialog->CurrentState().SendL(aTransactionId,aRequest,*transactionItem, + *dialog->RemoteTarget()); + + dialog->TransactionItems().AddItem(transactionItem); + CleanupStack::Pop(transactionItem); + if (aRefresh) + { + aRefreshId = static_cast(transactionItem)->RefreshId(); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SendAndUpdateRefreshL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::SendAndUpdateRefreshL (TTransactionId& aTransactionId, + const TRefreshId& aRefreshId, + const TDialogId& aDialogId, + CSIPRequest* aRequest, + const MDialogOwner* aOwner) + { + __SIP_ASSERT_LEAVE(aRefreshId, KErrArgument); + __SIP_ASSERT_LEAVE(aDialogId, KErrArgument); + __SIP_ASSERT_LEAVE(aRequest, KErrArgument); + __SIP_ASSERT_LEAVE(aRequest->HeaderCount(iContactHeaderName) <= 1, + KErrSIPMalformedMessage); + __ASSERT_ALWAYS (!aRequest->HasHeader(iRouteHeaderName), + User::Leave(KErrSIPMalformedMessage)); + + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + __ASSERT_ALWAYS(dialog, User::Leave(KErrSIPInvalidDialogState)); + __ASSERT_ALWAYS(dialog->CurrentState().RequestsWithinDialogAllowed(), + User::Leave(KErrSIPInvalidDialogState)); + + CTransactionItemBase* refreshItem = + dialog->TransactionItems().FindRefreshItem(aRefreshId); + __ASSERT_ALWAYS(refreshItem,User::Leave(KErrSIPInvalidTransactionState)); + + __SIP_MESSAGE_LOG("Dialogs", *aRequest) + + dialog->AddToHeaderInDialogL(*aRequest); + dialog->AddFromHeaderInDialogL(*aRequest); + dialog->AddCallIdHeaderInDialogL(*aRequest); + if (aRequest->Method().DesC().Length() == 0) + { + aRequest->SetMethodL(refreshItem->Method()); + } + dialog->AddRouteToMessageL(*aRequest); + TBool targetRefresh = refreshItem->TargetRefresh(); + AddContactHeaderL(*dialog,*aRequest,aRequest->From(),targetRefresh); + if (targetRefresh) + { + dialog->UpdateLocalTargetL(*aRequest); + } + dialog->CurrentState().SendL(aTransactionId,aRequest,*refreshItem, + *dialog->RemoteTarget()); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SendAndCreateDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::SendAndCreateDialogL (const TTransactionId& aTransactionId, + TRegistrationId aRegistrationId, + TDialogId& aDialogId, + CSIPResponse* aResponse, + MDialogOwner* aOwner, + MSIPSecUser& aSIPSecUser) + { + __SIP_ASSERT_LEAVE (aTransactionId != 0, KErrArgument); + __SIP_ASSERT_LEAVE (!aDialogId, KErrNotSupported); + __SIP_ASSERT_LEAVE (aResponse, KErrArgument); + __SIP_ASSERT_LEAVE (aOwner, KErrArgument); + __SIP_ASSERT_LEAVE (aResponse->ResponseCode() > K100Response, KErrArgument); + + __SIP_MESSAGE_LOG("Dialogs", *aResponse) + + + CSipDialogItem* dialog = + CSipDialogItem::NewLC(*iDialogsStore,aOwner,aSIPSecUser, + iTU,iRefreshMgr,iSIPSec,*iDeleteMgr,iSigComp, aRegistrationId); + TSIPTransportParams transportParams( + dialog->TransportParams(aRegistrationId)); + + MTransactionHeaders* trHeaders = iTU.TransactionHeadersL(aTransactionId); + __ASSERT_ALWAYS(trHeaders, User::Leave(KErrSIPInvalidTransactionState)); + TCleanupItem cleanupItem(DeleteTransactionHeaders,trHeaders); + CleanupStack::PushL (cleanupItem); + + // Remote target + CSIPContactHeader* remoteContact = + ExtractContactL(aTransactionId,*trHeaders,transportParams,ETrue); + CleanupStack::PushL(remoteContact); + dialog->SetRemoteTargetL(remoteContact->SIPAddress()->URI()); + CleanupStack::PopAndDestroy(remoteContact); + + // Remote CSeq + dialog->SetRemoteSeqNum(trHeaders->CSeqNumber()); + + // Call-ID + CSIPCallIDHeader* callId = trHeaders->CallIDHeader(); + __SIP_ASSERT_LEAVE(callId, KErrSIPInvalidDialogRequest); + dialog->SetCallId(callId); + + // Route-set + RPointerArray* route = trHeaders->RecordRoute(); + if (route) + { + TCleanupItem routeCleanupItem(DeleteRouteSet,route); + CleanupStack::PushL (routeCleanupItem); + CheckRecordRouteL(aTransactionId,*route,transportParams); + dialog->SetRouteSetL(*route); + CleanupStack::PopAndDestroy(1);// routeCleanupItem + } + + // From + CSIPFromHeader* from = trHeaders->FromHeader(); + CleanupStack::PushL(from); + __SIP_ASSERT_LEAVE(from, KErrSIPInvalidDialogRequest); + dialog->SetRemoteAddressL(from->SIPAddress()); + if (from->HasParam(iTagParamName)) + { + dialog->SetRemoteTagL(from); + } + aResponse->AddHeaderL(from); + CleanupStack::Pop(from); + + // To + CSIPToHeader* to = trHeaders->ToHeader(); + CleanupStack::PushL(to); + __SIP_ASSERT_LEAVE(to, KErrSIPInvalidDialogRequest); + dialog->SetLocalAddressL(to->SIPAddress()); + if (!to->HasParam(iTagParamName)) + { + HBufC8* tagBuf = HBufC8::NewLC(MTransactionUser::KTagLength); + TPtr8 tagPtr = tagBuf->Des(); + iTU.MakeTagL(tagPtr); + RStringF tag = SIPStrings::Pool().OpenFStringL(tagPtr); + CleanupClosePushL(tag); + to->SetParamL(iTagParamName,tag); + CleanupStack::PopAndDestroy(); // tag + CleanupStack::PopAndDestroy(tagBuf); + } + dialog->SetLocalTag(to->ParamValue(iTagParamName)); + aResponse->AddHeaderL(to); + CleanupStack::Pop(to); + + // Local target (Contact) + CURIContainer* requestURI = trHeaders->RequestURI(); + __SIP_ASSERT_LEAVE(requestURI, KErrSIPInvalidDialogRequest); + CleanupStack::PushL(requestURI); + if (!aResponse->IsErrorResponse()) + { + AddContactHeaderL(dialog->IapId(),*aResponse,aResponse->To(), + *requestURI); + } + CleanupStack::PopAndDestroy(requestURI); + dialog->SetLocalTargetWithMsgL(*aResponse); + + dialog->AddRecordRouteToMessageL(*aResponse); + dialog->AddCallIdHeaderInDialogL(*aResponse); + dialog->SetFirstTransactionId(aTransactionId); + + CTransactionItem* transactionItem = + CTransactionItem::NewLC(iTU,dialog,aTransactionId); + dialog->CurrentState().SendL(*transactionItem,aResponse); + dialog->TransactionItems().AddItem(transactionItem); + iDialogsStore->AddDialogItem(dialog); + + aDialogId = dialog->DialogId(); + + CleanupStack::Pop(transactionItem); + CleanupStack::PopAndDestroy(); // trHeaders + CleanupStack::Pop(dialog); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SendWithinDialogL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::SendWithinDialogL (const TTransactionId& aTransactionId, + const TDialogId& aDialogId, + CSIPResponse* aResponse, + const MDialogOwner* aOwner, + TBool aTargetRefresh) + { + __SIP_ASSERT_LEAVE (aTransactionId, KErrArgument); + __SIP_ASSERT_LEAVE (aDialogId, KErrSIPInvalidDialogState); + __SIP_ASSERT_LEAVE (aResponse, KErrArgument); + __SIP_ASSERT_LEAVE (aResponse->ResponseCode() > K100Response, KErrArgument); + + __SIP_MESSAGE_LOG("Dialogs", *aResponse) + + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + __ASSERT_ALWAYS(dialog, User::Leave(KErrSIPInvalidDialogState)); + CTransactionItemBase* transactionItem = + dialog->TransactionItems().FindItem(aTransactionId); + __ASSERT_ALWAYS(transactionItem, + User::Leave(KErrSIPInvalidTransactionState)); + + MTransactionHeaders* trHeaders = iTU.TransactionHeadersL(aTransactionId); + __ASSERT_ALWAYS(trHeaders, User::Leave(KErrSIPInvalidTransactionState)); + TCleanupItem cleanupItem(DeleteTransactionHeaders,trHeaders); + CleanupStack::PushL (cleanupItem); + + // To + CSIPToHeader* to = trHeaders->ToHeader(); + CleanupStack::PushL(to); + if (!to->HasParam(iTagParamName)) + { + to->SetParamL(iTagParamName,dialog->LocalTag()); + } + aResponse->AddHeaderL(to); + CleanupStack::Pop(to); + + // Add Record-Route only to the responses to the first transaction + if (aTransactionId == dialog->FirstTransactionId()) + { + dialog->AddRecordRouteToMessageL(*aResponse); + } + + // Remote and local target + if (!aResponse->IsErrorResponse()) + { + AddContactHeaderL(*dialog,*aResponse,aResponse->To(),aTargetRefresh); + } + if (aTargetRefresh && aResponse->Type() == CSIPResponse::E2XX) + { + CSIPContactHeader* remoteContact = + ExtractContactL(aTransactionId,*trHeaders, + dialog->TransportParams(KEmptyRegistrationId), + EFalse); + if (remoteContact) + { + CleanupStack::PushL(remoteContact); + CURIContainer& remoteTarget = remoteContact->SIPAddress()->URI(); + dialog->SetRemoteTargetL(remoteTarget); + CleanupStack::PopAndDestroy(remoteContact); + } + dialog->UpdateLocalTargetL(*aResponse); + } + CleanupStack::PopAndDestroy(); // trHeaders + dialog->CurrentState().SendL(*transactionItem, aResponse); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::TerminateDialog +// ----------------------------------------------------------------------------- +// +TInt CSipDialogMgr::TerminateDialog (const TDialogId& aDialogId, + const MDialogOwner* aOwner) + { + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + if(!dialog) + { + return KErrNotFound; + } + return iDialogsStore->Remove(dialog); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::TerminateDialogsFor +// ----------------------------------------------------------------------------- +// +TInt CSipDialogMgr::TerminateDialogsFor (const MDialogOwner* aOwner) + { + return iDialogsStore->RemoveAllWith(aOwner); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::TerminateDialogRefresh +// ----------------------------------------------------------------------------- +// +TInt CSipDialogMgr::TerminateDialogRefresh (const TDialogId& aDialogId, + const TRefreshId& aRefreshId, + const MDialogOwner* aOwner) + { + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + if (!dialog) + { + return KErrNotFound; + } + CTransactionItemBase* refreshItem = + dialog->TransactionItems().FindRefreshItem(aRefreshId); + if (!refreshItem) + { + return KErrNotFound; + } + return dialog->TransactionItems().RemoveItem(refreshItem->Id()); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::GetStateL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::GetStateL (const TDialogId& aDialogId, + CSIPInternalStates::TState& aState) + { + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId); + if (!dialog) + { + User::Leave(KErrNotFound); + } + dialog->CurrentState().GetState(aState); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::CallIDL +// ----------------------------------------------------------------------------- +// +const CSIPCallIDHeader& CSipDialogMgr::CallIDL (const TDialogId& aDialogId, + const MDialogOwner* aOwner) + { + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + if (!dialog) + { + User::Leave(KErrNotFound); + } + if (!dialog->CallId()) + { + User::Leave(KErrNotFound); + } + return *(dialog->CallId()); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::LocalTagL +// ----------------------------------------------------------------------------- +// +const TDesC8& CSipDialogMgr::LocalTagL(const TDialogId& aDialogId, + const MDialogOwner* aOwner) + { + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + if (!dialog) + { + User::Leave(KErrNotFound); + } + return dialog->LocalTag().DesC(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::ResetStateL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::ResetStateL(const TDialogId& aDialogId, + const MDialogOwner* aOwner) + { + CSipDialogItem* dialog = iDialogsStore->FindDialogItem(aDialogId,aOwner); + if (!dialog) + { + User::Leave(KErrNotFound); + } + dialog->ResetStateL(); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SIPSecUserForTransaction +// ----------------------------------------------------------------------------- +// +const MSIPSecUser* CSipDialogMgr::SIPSecUserForTransaction( + const TTransactionId& aTransactionId) + { + return iDialogsStore->FindDialogItemByTransaction(aTransactionId); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::TransactionOwnerL +// ----------------------------------------------------------------------------- +// +MTransactionOwner* CSipDialogMgr::TransactionOwnerL (CSIPRequest& aRequest, + CSIPResponse** aResponse) + { + if (aRequest.To() && !(aRequest.To()->HasParam(iTagParamName))) + { + return 0; + } + CSipDialogItem* dialog = iDialogsStore->DialogItemForRequest(&aRequest); + if (!dialog) + { + *aResponse = + CSIPResponse::NewL(K481Response,iPhraseCallTransactionDoesNotExist); + } + return dialog; + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::ConnectionStateChangedL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::ConnectionStateChangedL (TUint32 aIapId, + CSIPConnection::TState aState) + { + if (aState == CSIPConnection::EInactive || + aState == CSIPConnection::EUnavailable) + { + iDialogsStore->DeleteItemsWithThisIapId(aIapId); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::ExtractContactL +// ----------------------------------------------------------------------------- +// +CSIPContactHeader* CSipDialogMgr::ExtractContactL ( + TTransactionId aTransactionId, + MTransactionHeaders& aHeaders, + const TSIPTransportParams& aParams, + TBool aContactMandatory) + { + RPointerArray* contacts = aHeaders.Contact(); + TCleanupItem contactsCleanupItem(DeleteContacts,contacts); + CleanupStack::PushL(contactsCleanupItem); + CSIPContactHeader* contact = NULL; + if (contacts && contacts->Count() == 1) + { + contact = (*contacts)[0]; + contacts->Remove(0); + CleanupStack::PushL(contact); + if (!CSipDialogItem::ContactOk(*contact)) + { + SendErrorResponseAndLeaveL(aTransactionId, + KErrSIPInvalidURIType, + aParams); + } + CleanupStack::Pop(contact); + } + if (!contact && aContactMandatory) + { + SendErrorResponseAndLeaveL(aTransactionId, + KErrSIPInvalidDialogRequest, + aParams); + } + CleanupStack::PopAndDestroy(1); // contactsCleanupItem + return contact; + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::CheckRecordRouteL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::CheckRecordRouteL ( + TTransactionId aTransactionId, + RPointerArray& aRecordRoute, + const TSIPTransportParams& aParams) + { + // For an incoming request creating a dialog it must be checked + // that the first Record-Route-header (the next hop) has a SIP-URI. + TInt count = aRecordRoute.Count(); + if (count > 0) + { + CSIPRouteHeaderBase* nextHop = aRecordRoute[0]; + if (!nextHop->SIPAddress().URI().IsSIPURI()) + { + SendErrorResponseAndLeaveL(aTransactionId,KErrSIPInvalidURIType, + aParams); + } + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::AddContactHeaderL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::AddContactHeaderL (TUint32 aIapId, + TRegistrationId aRegistrationId, + CSIPRequest& aRequest, + const CSIPFromHeader* aFrom) + { + if (!aRequest.HasHeader(iContactHeaderName)) + { + CreateAndAddContactL(aIapId,aRegistrationId,aRequest,aFrom); + } + else + { + FillHostInContactL(aIapId,aRegistrationId,aRequest,aFrom); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::AddContactHeaderL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::AddContactHeaderL (TUint32 aIapId, + CSIPResponse& aResponse, + const CSIPToHeader* aTo, + const CURIContainer& aRequestUri) + { + if (!aResponse.HasHeader(iContactHeaderName)) + { + CreateAndAddContactL(aRequestUri,aResponse); + } + else + { + FillHostInContactL(aIapId,KEmptyRegistrationId,aResponse,aTo); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::AddContactHeaderL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::AddContactHeaderL (CSipDialogItem& aDialog, + CSIPMessage& aMessage, + const CSIPFromToHeaderBase* aFromTo, + TBool aTargetRefresh) + { + if (!aMessage.HasHeader(iContactHeaderName)) + { + if (aTargetRefresh) + { + CSIPContactHeader* contact = + static_cast( + aDialog.LocalTarget()->CloneL()); + CleanupStack::PushL(contact); + aMessage.AddHeaderL(contact); + CleanupStack::Pop(contact); + } + } + else + { + FillHostInContactL(aDialog.IapId(),aDialog.RegistrationId(), + aMessage,aFromTo); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::CreateAndAddContactL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::CreateAndAddContactL (TUint32 aIapId, + TRegistrationId aRegistrationId, + CSIPMessage& aMessage, + const CSIPFromToHeaderBase* aFromTo) + { + // Create and and Contact with empty host + CURIContainer* uri = CURIContainer::DecodeL(KLocalHostSIPURI); + CleanupStack::PushL(uri); + CreateAndAddContactL(*uri,aMessage); + CleanupStack::PopAndDestroy(uri); + // Fill host + FillHostInContactL(aIapId,aRegistrationId,aMessage,aFromTo); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::FillHostInContactL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::FillHostInContactL (TUint32 aIapId, + TRegistrationId aRegistrationId, + CSIPMessage& aMessage, + const CSIPFromToHeaderBase* aFromTo) + { + __SIP_ASSERT_LEAVE (aFromTo != 0, KErrArgument); + + CSIPContactHeader* contact = + static_cast( + aMessage.Header(iContactHeaderName,0)); + + __SIP_ASSERT_LEAVE (contact != 0, KErrArgument); + __SIP_ASSERT_LEAVE (contact->SIPAddress() != 0, KErrArgument); + + TPtrC8 localHost(SIPStrings::StringF(SipStrConsts::ELocalHost).DesC()); + + CSIPURI* contactUri = contact->SIPAddress()->URI().SIPURI(); + if (contactUri && contactUri->HostPort().Host().CompareF(localHost) == 0) + { + // if contact header does not have host --> add it + iRegistrationContact.ContactL(aIapId,aRegistrationId,aFromTo,*contact); + } + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::CreateContactL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::CreateAndAddContactL (const CURIContainer& aUri, + CSIPMessage& aMessage) + { + CURIContainer* uri = CURIContainer::NewLC(aUri); + CSIPAddress* sipAddress = SIPCodecUtils::CreateSIPAddressLC(uri); + CleanupStack::Pop(sipAddress); + CleanupStack::Pop(uri); + CleanupStack::PushL(sipAddress); + CSIPContactHeader* contact = CSIPContactHeader::NewL(sipAddress); + CleanupStack::Pop(sipAddress); + CleanupStack::PushL(contact); + aMessage.AddHeaderL(contact); + CleanupStack::Pop(contact); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::SendErrorResponseAndLeaveL +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::SendErrorResponseAndLeaveL ( + TTransactionId aTransactionId, + TInt aLeaveCode, + const TSIPTransportParams& aParams) + { + CSIPResponse* response = + CSIPResponse::NewLC(K400Response,iPhraseBadRequest); + iTU.SendL(aTransactionId, response, aParams); + CleanupStack::Pop(response); // ownership given to TU + iTU.ClearTransactionOwner(aTransactionId); + User::Leave(aLeaveCode); + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::DeleteTransactionHeaders +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::DeleteTransactionHeaders (TAny* aTransactionHeaders) + { + MTransactionHeaders* transactionHeaders = + reinterpret_cast(aTransactionHeaders); + delete transactionHeaders; + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::DeleteRouteSet +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::DeleteRouteSet (TAny* aRouteSet) + { + RPointerArray* routeSet = + reinterpret_cast*>(aRouteSet); + if (routeSet) + { + routeSet->ResetAndDestroy(); + } + delete routeSet; + } + +// ----------------------------------------------------------------------------- +// CSipDialogMgr::DeleteContacts +// ----------------------------------------------------------------------------- +// +void CSipDialogMgr::DeleteContacts (TAny* aContacts) + { + RPointerArray* contacts = + reinterpret_cast*>(aContacts); + if (contacts) + { + contacts->ResetAndDestroy(); + } + delete contacts; + }