--- /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 <centralrepository.h>
+#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<CSIPRequest&>(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<CUserAgentServer*>(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<CTransactionInfo> 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<CSIPRequest&>(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<CTransactionInfo> 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<CTransactionInfo> 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<CTransactionInfo> 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<CTransactionInfo> 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<CTransactionInfo> 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<CTransactionInfo> 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<CTransactionInfo> 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<CTransactionInfo> 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();
+ }
+ }
+