diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/TransactionUser/src/TransactionStore.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/TransactionUser/src/TransactionStore.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,908 @@ +// Copyright (c) 2006-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 : TransactionStore.cpp +// Part of : TransactionUser +// Version : SIP/6.0 +// + + + +#include +#include "sipprivatecrkeys.h" +#include "SipAssert.h" +#include "sipfromheader.h" +#include "sipviaheader.h" +#include "sipcseqheader.h" +#include "siphostport.h" +#include "siprequest.h" +#include "sipresponse.h" +#include "sipstrings.h" +#include "sipstrconsts.h" + +#include "CTransactionStore.h" +#include "InviteUAS.h" +#include "SIPMessageUtility.h" + + +// ----------------------------------------------------------------------------- +// CTransactionStore::NewL +// ----------------------------------------------------------------------------- +// +CTransactionStore* CTransactionStore::NewL() + { + CTransactionStore* self = new (ELeave) CTransactionStore(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::CTransactionStore +// ----------------------------------------------------------------------------- +// +CTransactionStore::CTransactionStore() : + iList(_FOFF(CTransactionInfo, iLink)), + iTransactionIdCounter(KMaxTransactionId), + iMaxServerTransactions(KMaxTInt) + { + } +// ----------------------------------------------------------------------------- +// CTransactionStore::ConstructL +// Read upper limit of simultaneous server transactions from central repository +// ----------------------------------------------------------------------------- +// +void CTransactionStore::ConstructL() + { + TInt maxServerTransactions(0); + CRepository* repository = CRepository::NewL(KCRUidSIP); + if ((repository->Get(KSIPMaxPendingServerTransactions, + maxServerTransactions) == KErrNone) && + maxServerTransactions >= 0) + { + iMaxServerTransactions = maxServerTransactions; + } + delete repository; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::~CTransactionStore +// ----------------------------------------------------------------------------- +// +CTransactionStore::~CTransactionStore() + { + CTransactionInfo* taInfo = iList.First(); + while (iList.IsFirst(taInfo) && !iList.IsEmpty()) + { + DeleteItem(taInfo); + taInfo = iList.First(); + } + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::DeleteItem +// ----------------------------------------------------------------------------- +// +void CTransactionStore::DeleteItem(CTransactionInfo* aItem) + { + __TEST_INVARIANT; + __SIP_ASSERT_RETURN(aItem, KErrArgument); + + RemoveListItem(*aItem); + aItem->FreeContents(); + delete aItem; + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::NewTransactionId +// ----------------------------------------------------------------------------- +// +TTransactionId CTransactionStore::NewTransactionId() + { + __TEST_INVARIANT; + + if (iTransactionIdCounter < KMaxTransactionId) + { + ++iTransactionIdCounter; + } + else + { + iTransactionIdCounter = KMinTransactionId; + } + + __TEST_INVARIANT; + return iTransactionIdCounter; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::AddL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::AddL(TTransactionId aTransactionId, + CUserAgent* aUserAgent, + CTransactionBase* aTransaction, + CSIPMessage* aMsg, + CTransactionBase::TTransactionType aType) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aTransactionId != KEmptyTransactionId, KErrArgument); + __SIP_ASSERT_LEAVE(aUserAgent, KErrArgument); + + CTransactionInfo* newItem = + CTransactionInfo::NewL(aType, aUserAgent->TransportParams().IapId()); + CleanupStack::PushL(newItem); + newItem->UpdateMessageHeadersL(aMsg); + CleanupStack::Pop(newItem); + if (aUserAgent->IsUAS()) + { + ++iServerTransactionCount; + } + + iList.AddLast(*newItem); + + // Attach UA when can't leave + newItem->SetUserAgent(aUserAgent); + newItem->SetTransaction(aTransaction); + newItem->SetTransactionId(aTransactionId); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::StoreRecordRouteHeadersL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::StoreRecordRouteHeadersL(TTransactionId aTransactionId, + CSIPRequest& aReq) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __SIP_ASSERT_LEAVE(taInfo, KErrNotFound); + taInfo->StoreRecordRouteHeadersL(aReq); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::FreeRecordRouteHeaders +// ----------------------------------------------------------------------------- +// +void CTransactionStore::FreeRecordRouteHeaders(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __SIP_ASSERT_RETURN(taInfo, KErrNotFound); + taInfo->FreeRecordRouteHeaders(); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::StoreContactHeadersL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::StoreContactHeadersL(TTransactionId aTransactionId, + CSIPRequest& aReq) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __SIP_ASSERT_LEAVE(taInfo, KErrNotFound); + taInfo->StoreContactHeadersL(aReq); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::FreeContactHeaders +// ----------------------------------------------------------------------------- +// +void CTransactionStore::FreeContactHeaders(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __SIP_ASSERT_RETURN(taInfo, KErrNotFound); + taInfo->FreeContactHeaders(); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::Search +// UAC sets the magic cookie, so a response without it is broken and dropped. +// Incoming request without branch or ACK to a 2xx: search using headers. +// ----------------------------------------------------------------------------- +// +MReceiverObserver* CTransactionStore::Search(CSIPMessage& aMsg) + { + __TEST_INVARIANT; + + CTransactionBase::TTransactionType taType = + CSIPMessageUtility::TransactionType(aMsg, ETrue); + + if (CSIPMessageUtility::HasViaMagicCookie(aMsg)) + { + MReceiverObserver* receiver = SearchByBranch(aMsg, taType, NULL); + if (receiver || !CSIPMessageUtility::IsAck(aMsg)) + { + __TEST_INVARIANT; + return receiver; + } + } + + if (aMsg.IsRequest()) + { + return SearchServerByHeaders( + static_cast(aMsg), taType, NULL); + } + + __TEST_INVARIANT; + return NULL; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::SearchUasToCancel +// ----------------------------------------------------------------------------- +// +CUserAgentServer* +CTransactionStore::SearchUasToCancel(CSIPRequest& aCancel, + const CUserAgent& aCancelUAS) + { + __TEST_INVARIANT; + + CTransactionBase::TTransactionType taType = + CSIPMessageUtility::TransactionType(aCancel, ETrue); + MReceiverObserver* receiver(NULL); + + if (CSIPMessageUtility::HasViaMagicCookie(aCancel)) + { + receiver = SearchByBranch(aCancel, taType, &aCancelUAS); + } + else + { + receiver = SearchServerByHeaders(aCancel, taType, &aCancelUAS); + } + + CUserAgentServer* uas = static_cast(receiver); + + // Must not return the same UAS that initiated the search + __ASSERT_DEBUG(uas != &aCancelUAS, + User::Panic(_L("TaStore:SearchUasToCancel"), KErrGeneral)); + __TEST_INVARIANT; + return uas; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::SearchServerByHeaders +// Use CompareTransactionTypes before CompareHeaders, so CompareHeaders is not +// used on UAC's taInfo as it has no sent-by part in Via. UAC uses magic cookie. +// ----------------------------------------------------------------------------- +// +MReceiverObserver* +CTransactionStore::SearchServerByHeaders(CSIPRequest& aReq, + CTransactionBase::TTransactionType aType, + const CUserAgent* aUserAgent) + { + __TEST_INVARIANT; + + MReceiverObserver* res(NULL); + if (RequiredHeadersPresent(aReq)) + { + TBool searchCanceledUas = (aUserAgent != NULL); + TSglQueIter iter(iList); + + for (CTransactionInfo* taInfo = iter++; !res && taInfo; taInfo = iter++) + { + if (taInfo->RequiredHeadersPresent() && + CompareTransactionTypes(*taInfo, aType, searchCanceledUas) && + taInfo->CompareHeaders(aReq) && + taInfo->CompareRequestLine(*(aReq.RequestURI()), + aReq.Method(), + searchCanceledUas)) + { + res = CheckResult(*taInfo, aUserAgent); + } + } + } + + __TEST_INVARIANT; + return res; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::RequiredHeadersPresent +// ----------------------------------------------------------------------------- +// +TBool CTransactionStore::RequiredHeadersPresent(CSIPMessage& aMsg) const + { + __TEST_INVARIANT; + return aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::EViaHeader)) && + aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::EFromHeader)) && + aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::EToHeader)) && + aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::ECSeqHeader)) && + (!aMsg.IsRequest() || static_cast(aMsg).RequestURI()); + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::SearchByBranch +// ----------------------------------------------------------------------------- +// +MReceiverObserver* +CTransactionStore::SearchByBranch(CSIPMessage& aMsg, + CTransactionBase::TTransactionType aType, + const CUserAgent* aUserAgent) + { + __TEST_INVARIANT; + + CSIPViaHeader* topVia = CSIPMessageUtility::TopVia(aMsg); + __ASSERT_DEBUG(topVia != NULL, + User::Panic(_L("TaStore:SearchByBranch"), KErrArgument)); + + TBool searchCanceledUas = (aUserAgent != NULL); + RStringF method = CSIPMessageUtility::MessageMethod(aMsg); + RStringF branch = SIPStrings::StringF(SipStrConsts::EBranch); + + MReceiverObserver* result(NULL); + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo && !result; taInfo = iter++) + { + // Skip transactions not associated with a SIP request. + // Type must match, e.g. a client transaction receives only responses. + if (taInfo->RequiredHeadersPresent() && + CompareTransactionTypes(*taInfo, aType, searchCanceledUas)) + { + CSIPViaHeader& storedVia = taInfo->TopVia(); + if (storedVia.HasParam(branch) && + (storedVia.ParamValue(branch) == topVia->ParamValue(branch)) && + (searchCanceledUas || taInfo->CompareMethod(method)) && + (aType == CTransactionBase::KClientTransaction || + aType == CTransactionBase::KClientInviteTransaction || + // Server transaction: sent-by of top via must match. + // Client transaction: sent-by can be missing from storedVia. + (storedVia.SentByHostPort() == topVia->SentByHostPort()))) + { + result = IgnoreAckTo2xx(aMsg, *taInfo, aUserAgent); + } + } + } + + __TEST_INVARIANT; + return result; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::CompareTransactionTypes +// If searching UAS to cancel, accept only server transactions. +// ----------------------------------------------------------------------------- +// +TBool CTransactionStore::CompareTransactionTypes(const CTransactionInfo& aInfo, + CTransactionBase::TTransactionType aType, + TBool aSearchCanceledUas) const + { + __TEST_INVARIANT; + + if (aSearchCanceledUas) + { + __ASSERT_DEBUG(aType == CTransactionBase::KServerTransaction, + User::Panic(_L("TaStore:CompTaTypes"), KErrArgument)); + return aInfo.CompareType(CTransactionBase::KServerTransaction) || + aInfo.CompareType(CTransactionBase::KServerInviteTransaction); + } + + return aInfo.CompareType(aType); + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::IgnoreAckTo2xx +// Ignore Via branch of ACK to a 2xx. INVITE may've forked, one UAS sent 2xx, +// other 4xx. Even if UAC sends ACK to both with a same branch as in INVITE, UAS +// must ignore the ACK targeted to the other UAS. To-tag is the difference. +// ----------------------------------------------------------------------------- +// +MReceiverObserver* +CTransactionStore::IgnoreAckTo2xx(const CSIPMessage& aMsg, + CTransactionInfo& aInfo, + const CUserAgent* aUserAgent) const + { + __TEST_INVARIANT; + + if (CSIPMessageUtility::IsAck(aMsg) && !aUserAgent && aInfo.UserAgent()) + { + // aMsg is ACK so UA must be InviteUAS + __ASSERT_DEBUG(aInfo.UserAgent()->IsUAS() && + aInfo.CompareType(CTransactionBase::KServerInviteTransaction), + User::Panic(_L("TaStore:IgnoreAckTo2xx"), KErrGeneral)); + + if (CInviteUAS::Ptr(*(aInfo.UserAgent())).IsSending2xx()) + { + return NULL; + } + } + + return CheckResult(aInfo, aUserAgent); + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::CheckResult +// ----------------------------------------------------------------------------- +// +MReceiverObserver* +CTransactionStore::CheckResult(CTransactionInfo& aInfo, + const CUserAgent* aUserAgent) const + { + __TEST_INVARIANT; + + if (!aUserAgent) + { + __ASSERT_DEBUG(aInfo.Receiver(), + User::Panic(_L("TaStore:ChkResult"), KErrNotFound)); + return aInfo.Receiver(); + } + + // Ignore result if it is the same UA that makes the search + if (aInfo.UserAgent() == aUserAgent) + { + return NULL; + } + return aInfo.UserAgent(); + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::SearchById +// ----------------------------------------------------------------------------- +// +CUserAgent* CTransactionStore::SearchById(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + __ASSERT_DEBUG(taInfo->UserAgent(), + User::Panic(_L("TaStore:SearchById"), KErrNotFound)); + return taInfo->UserAgent(); + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::FindTransactionInfo +// ----------------------------------------------------------------------------- +// +CTransactionInfo* +CTransactionStore::FindTransactionInfo(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + __ASSERT_DEBUG(aTransactionId != KEmptyTransactionId, + User::Panic(_L("TaStore:FindTaInfo"), KErrArgument)); + + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++) + { + if (taInfo->TransactionId() == aTransactionId) + { + __TEST_INVARIANT; + return taInfo; + } + if (taInfo->TransactionId() == KEmptyTransactionId) + { + // TransactionInfo marked for deletion. Delete it. + DeleteItem(taInfo); + } + } + + __TEST_INVARIANT; + return NULL; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::IcmpErrorL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::IcmpErrorL(const TInetAddr& aAddress, + CSipConnectionMgr::TICMPError aError) + { + __TEST_INVARIANT; + + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++) + { + if (taInfo->Receiver()) + { + taInfo->Receiver()->IcmpErrorL(aAddress, aError); + } + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::ClearUserAgent +// ----------------------------------------------------------------------------- +// +void CTransactionStore::ClearUserAgent(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + taInfo->SetUserAgent(NULL); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::ClearTransaction +// ----------------------------------------------------------------------------- +// +void CTransactionStore::ClearTransaction(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + taInfo->SetTransaction(NULL); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::UpdateTransactionId +// ----------------------------------------------------------------------------- +// +TInt CTransactionStore::UpdateTransactionId(TTransactionId aOldTransactionId, + TTransactionId aNewTransactionId) + { + __TEST_INVARIANT; + __SIP_ASSERT_RETURN_VALUE(!(aOldTransactionId == aNewTransactionId), + KErrArgument); + TInt status(KErrNotFound); + CTransactionInfo* taInfo = FindTransactionInfo(aOldTransactionId); + if (taInfo) + { + taInfo->SetTransactionId(aNewTransactionId); + status = KErrNone; + } + + __TEST_INVARIANT; + return status; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::UpdateL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::UpdateL(TTransactionId aTransactionId, + CTransactionBase* aTransaction, + CSIPMessage* aMsg) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __ASSERT_ALWAYS(taInfo, User::Leave(KErrNotFound)); + taInfo->SetTransaction(aTransaction); + taInfo->UpdateMessageHeadersL(aMsg); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::UpdateToTagL +// ----------------------------------------------------------------------------- +// +void +CTransactionStore::UpdateToTagL(TTransactionId aTransactionId, RStringF aTag) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __ASSERT_ALWAYS(taInfo, User::Leave(KErrNotFound)); + taInfo->UpdateToTagL(aTag); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::Remove +// ----------------------------------------------------------------------------- +// +void CTransactionStore::Remove(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + RemoveListItem(*taInfo); + delete taInfo; + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::ClearTransactionOwner +// ----------------------------------------------------------------------------- +// +TInt +CTransactionStore::ClearTransactionOwner(const MTransactionOwner* aObserver) + { + __TEST_INVARIANT; + __SIP_ASSERT_RETURN_VALUE(aObserver != NULL, KErrArgument); + + TInt status(KErrNotFound); + TSglQueIter iter(iList); + CUserAgent* ua(NULL); + + for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++) + { + ua = taInfo->UserAgent(); + if (ua && ua->TransactionOwner() == aObserver) + { + ua->ClearTransactionOwner(); + status = KErrNone; + // Continue the loop as many transactions may use the same aObserver + } + } + + __TEST_INVARIANT; + return status; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::EndResolvingTransactions +// Detached transactions (ua == NULL), are never resolving. +// ----------------------------------------------------------------------------- +// +void CTransactionStore::EndResolvingTransactions(TUint32 aIapId, TInt aReason) + { + __TEST_INVARIANT; + + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++) + { + CUserAgent* ua = taInfo->UserAgent(); + if (ua && !ua->IsUAS()) + { + if ((ua->TransportParams().IapId() == aIapId) && ua->IsResolving()) + { + ua->Stop(aReason); + } + } + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::IsMergedRequest +// ----------------------------------------------------------------------------- +// +TBool CTransactionStore::IsMergedRequest(const CUserAgent& aUserAgent, + CSIPRequest& aReq) + { + __TEST_INVARIANT; + + CSIPFromHeader* from = aReq.From(); + __ASSERT_DEBUG(from, User::Panic(_L("TaStore:IsMerg !from"), KErrArgument)); + + if (!aReq.HasHeader(SIPStrings::StringF(SipStrConsts::EFromHeader)) || + !aReq.HasHeader(SIPStrings::StringF(SipStrConsts::ECallIDHeader)) || + !aReq.HasHeader(SIPStrings::StringF(SipStrConsts::ECSeqHeader)) || + !from->HasParam(SIPStrings::StringF(SipStrConsts::ETag))) + { + return EFalse; + } + + CSIPCSeqHeader* cseq = aReq.CSeq(); + __ASSERT_DEBUG(cseq, User::Panic(_L("TaStore:IsMerg !cseq"), KErrArgument)); + + TBool merged(EFalse); + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo && !merged; taInfo = iter++) + { + merged = taInfo->IsMergedRequest(aUserAgent, + *from, + *aReq.CallID(), + cseq->Seq(), + cseq->Method()); + } + + __TEST_INVARIANT; + return merged; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::CopyHeadersToResponseL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::CopyHeadersToResponseL(TTransactionId aTransactionId, + CSIPResponse& aResp) + { + __TEST_INVARIANT; + __SIP_ASSERT_RETURN(aTransactionId != KEmptyTransactionId, KErrArgument); + __SIP_ASSERT_RETURN( + !aResp.HasHeader(SIPStrings::StringF(SipStrConsts::EViaHeader)), + KErrArgument); + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + taInfo->CopyToFromCallIDCSeqToMsgL(aResp); + taInfo->CopyViaHeadersToMsgL(aResp); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::CopyHeadersToRequestL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::CopyHeadersToRequestL(TTransactionId aTransactionId, + CSIPRequest& aReq, + TBool aCopyRequestURI, + TBool aCopyViaHeaders) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aTransactionId != KEmptyTransactionId, KErrArgument); + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + taInfo->CopyToFromCallIDCSeqToMsgL(aReq); + + if (aCopyRequestURI) + { + taInfo->CopyRequestUriToRequestL(aReq); + } + + if (aCopyViaHeaders) + { + taInfo->CopyViaHeadersToMsgL(aReq); + } + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::TransactionHeadersL +// ----------------------------------------------------------------------------- +// +MTransactionHeaders* +CTransactionStore::TransactionHeadersL(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + if (taInfo) + { + return taInfo->TransactionHeadersL(); + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::RandomTaInfoL +// ----------------------------------------------------------------------------- +// +void CTransactionStore::RandomTaInfoL(TTransactionId& aTaId, + CUserAgent** aUserAgent, + CSIPMessage** aMsg) + { + __TEST_INVARIANT; + __SIP_ASSERT_LEAVE(aUserAgent && aMsg, KErrArgument); + + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++) + { + if (aTaId == KEmptyTransactionId) + { + aTaId = taInfo->TransactionId(); + } + + if (taInfo->UserAgent()) + { + *aUserAgent = taInfo->UserAgent(); + *aMsg = taInfo->BuildRequestFromStoredInfoL(); + + __TEST_INVARIANT; + return; + } + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::RequestMethod +// ----------------------------------------------------------------------------- +// +RStringF CTransactionStore::RequestMethod(TTransactionId aTransactionId) + { + __TEST_INVARIANT; + + CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId); + __ASSERT_DEBUG(taInfo, User::Panic(_L("TaStore:ReqMethod"), KErrNotFound)); + return taInfo->RequestMethod(); + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::RemoveItemsByIapId +// ----------------------------------------------------------------------------- +// +void CTransactionStore::RemoveItemsByIapId(TUint32 aIapId) + { + __TEST_INVARIANT; + + TSglQueIter iter(iList); + for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++) + { + if (taInfo->IapId() == aIapId) + { + DeleteItem(taInfo); + } + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::AllowMoreServerTransactions +// ----------------------------------------------------------------------------- +// +TBool CTransactionStore::AllowMoreServerTransactions() const + { + __TEST_INVARIANT; + return iServerTransactionCount < iMaxServerTransactions; + } + +// ----------------------------------------------------------------------------- +// CTransactionStore::RemoveListItem +// ----------------------------------------------------------------------------- +// +void CTransactionStore::RemoveListItem(CTransactionInfo& aItem) + { + __TEST_INVARIANT; + if (aItem.CompareType(CTransactionBase::KServerTransaction) || + aItem.CompareType(CTransactionBase::KServerInviteTransaction)) + { + --iServerTransactionCount; + } + iList.Remove(aItem); + __TEST_INVARIANT; + } +// CTransactionStore::__DbgTestInvariant +// ----------------------------------------------------------------------------- +// + +void CTransactionStore::__DbgTestInvariant() const + { + if (iTransactionIdCounter < KMinTransactionId) + { + User::Invariant(); + } + } +