realtimenetprots/sipfw/SIP/TransactionUser/src/TransactionStore.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Name          : TransactionStore.cpp
       
    15 // Part of       : TransactionUser
       
    16 // Version       : SIP/6.0
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include <centralrepository.h>
       
    22 #include "sipprivatecrkeys.h"
       
    23 #include "SipAssert.h"
       
    24 #include "sipfromheader.h"
       
    25 #include "sipviaheader.h"
       
    26 #include "sipcseqheader.h"
       
    27 #include "siphostport.h"
       
    28 #include "siprequest.h"
       
    29 #include "sipresponse.h"
       
    30 #include "sipstrings.h"
       
    31 #include "sipstrconsts.h"
       
    32 
       
    33 #include "CTransactionStore.h"
       
    34 #include "InviteUAS.h"
       
    35 #include "SIPMessageUtility.h"
       
    36 
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CTransactionStore::NewL
       
    40 // -----------------------------------------------------------------------------
       
    41 //
       
    42 CTransactionStore* CTransactionStore::NewL()
       
    43 	{	
       
    44 	CTransactionStore* self = new (ELeave) CTransactionStore();
       
    45     CleanupStack::PushL(self);
       
    46     self->ConstructL();
       
    47     CleanupStack::Pop(self);
       
    48     return self;
       
    49 	}
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // CTransactionStore::CTransactionStore
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 CTransactionStore::CTransactionStore() :
       
    56 	iList(_FOFF(CTransactionInfo, iLink)),
       
    57 	iTransactionIdCounter(KMaxTransactionId),
       
    58 	iMaxServerTransactions(KMaxTInt)
       
    59 	{
       
    60 	}
       
    61 // -----------------------------------------------------------------------------
       
    62 // CTransactionStore::ConstructL
       
    63 // Read upper limit of simultaneous server transactions from central repository
       
    64 // -----------------------------------------------------------------------------
       
    65 //
       
    66 void CTransactionStore::ConstructL()
       
    67 	{
       
    68 	TInt maxServerTransactions(0);
       
    69 	CRepository* repository = CRepository::NewL(KCRUidSIP);
       
    70 	if ((repository->Get(KSIPMaxPendingServerTransactions,
       
    71 						 maxServerTransactions) == KErrNone) &&
       
    72 		maxServerTransactions >= 0)
       
    73 		{
       
    74 		iMaxServerTransactions = maxServerTransactions;
       
    75 		}
       
    76 	delete repository;
       
    77 	}
       
    78 
       
    79 // -----------------------------------------------------------------------------
       
    80 // CTransactionStore::~CTransactionStore
       
    81 // -----------------------------------------------------------------------------
       
    82 //
       
    83 CTransactionStore::~CTransactionStore()
       
    84 	{
       
    85 	CTransactionInfo* taInfo = iList.First();
       
    86 	while (iList.IsFirst(taInfo) && !iList.IsEmpty())
       
    87 		{
       
    88 		DeleteItem(taInfo);		
       
    89 		taInfo = iList.First();
       
    90 		}
       
    91 	}
       
    92 
       
    93 // -----------------------------------------------------------------------------
       
    94 // CTransactionStore::DeleteItem
       
    95 // -----------------------------------------------------------------------------
       
    96 //
       
    97 void CTransactionStore::DeleteItem(CTransactionInfo* aItem)
       
    98 	{
       
    99 	__TEST_INVARIANT;
       
   100 	__SIP_ASSERT_RETURN(aItem, KErrArgument);
       
   101 	
       
   102 	RemoveListItem(*aItem);
       
   103 	aItem->FreeContents();
       
   104 	delete aItem;
       
   105 	
       
   106 	__TEST_INVARIANT;
       
   107 	}
       
   108 
       
   109 // -----------------------------------------------------------------------------
       
   110 // CTransactionStore::NewTransactionId
       
   111 // -----------------------------------------------------------------------------
       
   112 //
       
   113 TTransactionId CTransactionStore::NewTransactionId()
       
   114 	{
       
   115 	__TEST_INVARIANT;
       
   116 
       
   117 	if (iTransactionIdCounter < KMaxTransactionId)
       
   118 		{
       
   119 		++iTransactionIdCounter;
       
   120 		}
       
   121 	else
       
   122 		{
       
   123 		iTransactionIdCounter = KMinTransactionId;
       
   124 		}
       
   125 
       
   126 	__TEST_INVARIANT;
       
   127 	return iTransactionIdCounter;
       
   128 	}
       
   129 
       
   130 // -----------------------------------------------------------------------------
       
   131 // CTransactionStore::AddL
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 void CTransactionStore::AddL(TTransactionId aTransactionId,
       
   135 							 CUserAgent* aUserAgent,
       
   136 							 CTransactionBase* aTransaction,
       
   137 							 CSIPMessage* aMsg,
       
   138 							 CTransactionBase::TTransactionType aType)
       
   139 	{
       
   140 	__TEST_INVARIANT;
       
   141 	__SIP_ASSERT_LEAVE(aTransactionId != KEmptyTransactionId, KErrArgument);
       
   142 	__SIP_ASSERT_LEAVE(aUserAgent, KErrArgument);
       
   143 
       
   144     CTransactionInfo* newItem =
       
   145     	CTransactionInfo::NewL(aType, aUserAgent->TransportParams().IapId());
       
   146     CleanupStack::PushL(newItem);
       
   147 	newItem->UpdateMessageHeadersL(aMsg);
       
   148     CleanupStack::Pop(newItem);
       
   149 	if (aUserAgent->IsUAS())
       
   150 		{
       
   151 		++iServerTransactionCount;
       
   152 		}
       
   153 
       
   154     iList.AddLast(*newItem);
       
   155 
       
   156 	// Attach UA when can't leave
       
   157 	newItem->SetUserAgent(aUserAgent);
       
   158 	newItem->SetTransaction(aTransaction);
       
   159 	newItem->SetTransactionId(aTransactionId);
       
   160 
       
   161 	__TEST_INVARIANT;
       
   162 	}
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CTransactionStore::StoreRecordRouteHeadersL
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 void CTransactionStore::StoreRecordRouteHeadersL(TTransactionId aTransactionId,
       
   169 												 CSIPRequest& aReq)
       
   170 	{
       
   171 	__TEST_INVARIANT;
       
   172 
       
   173 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   174     __SIP_ASSERT_LEAVE(taInfo, KErrNotFound);
       
   175 	taInfo->StoreRecordRouteHeadersL(aReq);
       
   176 
       
   177 	__TEST_INVARIANT;
       
   178 	}
       
   179 
       
   180 // -----------------------------------------------------------------------------
       
   181 // CTransactionStore::FreeRecordRouteHeaders
       
   182 // -----------------------------------------------------------------------------
       
   183 //
       
   184 void CTransactionStore::FreeRecordRouteHeaders(TTransactionId aTransactionId)
       
   185 	{
       
   186 	__TEST_INVARIANT;
       
   187 
       
   188 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   189 	__SIP_ASSERT_RETURN(taInfo, KErrNotFound);
       
   190 	taInfo->FreeRecordRouteHeaders();
       
   191 
       
   192 	__TEST_INVARIANT;
       
   193 	}
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // CTransactionStore::StoreContactHeadersL
       
   197 // -----------------------------------------------------------------------------
       
   198 //
       
   199 void CTransactionStore::StoreContactHeadersL(TTransactionId aTransactionId,
       
   200 											 CSIPRequest& aReq)
       
   201 	{
       
   202 	__TEST_INVARIANT;
       
   203 
       
   204 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   205 	__SIP_ASSERT_LEAVE(taInfo, KErrNotFound);
       
   206 	taInfo->StoreContactHeadersL(aReq);
       
   207 
       
   208 	__TEST_INVARIANT;
       
   209 	}
       
   210 
       
   211 // -----------------------------------------------------------------------------
       
   212 // CTransactionStore::FreeContactHeaders
       
   213 // -----------------------------------------------------------------------------
       
   214 //
       
   215 void CTransactionStore::FreeContactHeaders(TTransactionId aTransactionId)
       
   216 	{
       
   217 	__TEST_INVARIANT;
       
   218 
       
   219 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   220 	__SIP_ASSERT_RETURN(taInfo, KErrNotFound);
       
   221 	taInfo->FreeContactHeaders();
       
   222 
       
   223 	__TEST_INVARIANT;
       
   224 	}
       
   225 
       
   226 // -----------------------------------------------------------------------------
       
   227 // CTransactionStore::Search
       
   228 // UAC sets the magic cookie, so a response without it is broken and dropped.
       
   229 // Incoming request without branch or ACK to a 2xx: search using headers.
       
   230 // -----------------------------------------------------------------------------
       
   231 //
       
   232 MReceiverObserver* CTransactionStore::Search(CSIPMessage& aMsg)
       
   233 	{
       
   234 	__TEST_INVARIANT;
       
   235 
       
   236 	CTransactionBase::TTransactionType taType =
       
   237         CSIPMessageUtility::TransactionType(aMsg, ETrue);
       
   238 
       
   239     if (CSIPMessageUtility::HasViaMagicCookie(aMsg))
       
   240         {
       
   241         MReceiverObserver* receiver = SearchByBranch(aMsg, taType, NULL);
       
   242         if (receiver || !CSIPMessageUtility::IsAck(aMsg))
       
   243             {
       
   244             __TEST_INVARIANT;
       
   245 			return receiver;
       
   246             }
       
   247         }
       
   248 
       
   249 	if (aMsg.IsRequest())
       
   250 		{
       
   251 		return SearchServerByHeaders(
       
   252             static_cast<CSIPRequest&>(aMsg), taType, NULL);
       
   253 		}
       
   254 
       
   255     __TEST_INVARIANT;
       
   256 	return NULL;
       
   257 	}
       
   258 
       
   259 // -----------------------------------------------------------------------------
       
   260 // CTransactionStore::SearchUasToCancel
       
   261 // -----------------------------------------------------------------------------
       
   262 //
       
   263 CUserAgentServer*
       
   264 CTransactionStore::SearchUasToCancel(CSIPRequest& aCancel,
       
   265 									 const CUserAgent& aCancelUAS)
       
   266 	{
       
   267 	__TEST_INVARIANT;
       
   268 
       
   269 	CTransactionBase::TTransactionType taType =
       
   270         CSIPMessageUtility::TransactionType(aCancel, ETrue);
       
   271 	MReceiverObserver* receiver(NULL);
       
   272 
       
   273 	if (CSIPMessageUtility::HasViaMagicCookie(aCancel))
       
   274 		{
       
   275 		receiver = SearchByBranch(aCancel, taType, &aCancelUAS);
       
   276 		}
       
   277 	else
       
   278 		{
       
   279 		receiver = SearchServerByHeaders(aCancel, taType, &aCancelUAS);
       
   280 		}
       
   281 
       
   282 	CUserAgentServer* uas = static_cast<CUserAgentServer*>(receiver);
       
   283 
       
   284 	// Must not return the same UAS that initiated the search
       
   285 	__ASSERT_DEBUG(uas != &aCancelUAS,
       
   286 				   User::Panic(_L("TaStore:SearchUasToCancel"), KErrGeneral));
       
   287 	__TEST_INVARIANT;
       
   288 	return uas;
       
   289 	}
       
   290 
       
   291 // -----------------------------------------------------------------------------
       
   292 // CTransactionStore::SearchServerByHeaders
       
   293 // Use CompareTransactionTypes before CompareHeaders, so CompareHeaders is not
       
   294 // used on UAC's taInfo as it has no sent-by part in Via. UAC uses magic cookie.
       
   295 // -----------------------------------------------------------------------------
       
   296 //
       
   297 MReceiverObserver*
       
   298 CTransactionStore::SearchServerByHeaders(CSIPRequest& aReq,
       
   299 									 CTransactionBase::TTransactionType aType,
       
   300 									 const CUserAgent* aUserAgent)
       
   301 	{
       
   302 	__TEST_INVARIANT;
       
   303 
       
   304 	MReceiverObserver* res(NULL);
       
   305 	if (RequiredHeadersPresent(aReq))
       
   306 		{
       
   307 	    TBool searchCanceledUas = (aUserAgent != NULL);
       
   308 	    TSglQueIter<CTransactionInfo> iter(iList);
       
   309 
       
   310 	    for (CTransactionInfo* taInfo = iter++; !res && taInfo; taInfo = iter++)
       
   311 		    {
       
   312 		    if (taInfo->RequiredHeadersPresent() &&
       
   313 			    CompareTransactionTypes(*taInfo, aType, searchCanceledUas) &&
       
   314 				taInfo->CompareHeaders(aReq) &&
       
   315 				taInfo->CompareRequestLine(*(aReq.RequestURI()),
       
   316 										   aReq.Method(),
       
   317 										   searchCanceledUas))
       
   318 				{
       
   319 				res = CheckResult(*taInfo, aUserAgent);
       
   320 				}
       
   321 		    }
       
   322         }
       
   323 
       
   324 	__TEST_INVARIANT;
       
   325 	return res;
       
   326 	}
       
   327 
       
   328 // -----------------------------------------------------------------------------
       
   329 // CTransactionStore::RequiredHeadersPresent
       
   330 // -----------------------------------------------------------------------------
       
   331 //
       
   332 TBool CTransactionStore::RequiredHeadersPresent(CSIPMessage& aMsg) const
       
   333 	{
       
   334 	__TEST_INVARIANT;
       
   335 	return aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::EViaHeader))  &&
       
   336 		   aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::EFromHeader)) &&
       
   337 		   aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::EToHeader))   &&
       
   338 		   aMsg.HasHeader(SIPStrings::StringF(SipStrConsts::ECSeqHeader)) &&
       
   339 		   (!aMsg.IsRequest() || static_cast<CSIPRequest&>(aMsg).RequestURI());
       
   340 	}
       
   341 
       
   342 // -----------------------------------------------------------------------------
       
   343 // CTransactionStore::SearchByBranch
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 MReceiverObserver*
       
   347 CTransactionStore::SearchByBranch(CSIPMessage& aMsg,
       
   348 								  CTransactionBase::TTransactionType aType,
       
   349 								  const CUserAgent* aUserAgent)
       
   350 	{
       
   351 	__TEST_INVARIANT;
       
   352 
       
   353     CSIPViaHeader* topVia = CSIPMessageUtility::TopVia(aMsg);
       
   354     __ASSERT_DEBUG(topVia != NULL,
       
   355         		   User::Panic(_L("TaStore:SearchByBranch"), KErrArgument));
       
   356 
       
   357     TBool searchCanceledUas = (aUserAgent != NULL);
       
   358 	RStringF method = CSIPMessageUtility::MessageMethod(aMsg);
       
   359 	RStringF branch = SIPStrings::StringF(SipStrConsts::EBranch);		
       
   360 
       
   361 	MReceiverObserver* result(NULL);
       
   362 	TSglQueIter<CTransactionInfo> iter(iList);
       
   363 	for (CTransactionInfo* taInfo = iter++; taInfo && !result; taInfo = iter++)
       
   364 		{
       
   365 		// Skip transactions not associated with a SIP request.
       
   366         // Type must match, e.g. a client transaction receives only responses.
       
   367 		if (taInfo->RequiredHeadersPresent() &&
       
   368 			CompareTransactionTypes(*taInfo, aType, searchCanceledUas))
       
   369 			{
       
   370 			CSIPViaHeader& storedVia = taInfo->TopVia();
       
   371 			if (storedVia.HasParam(branch) &&
       
   372 				(storedVia.ParamValue(branch) == topVia->ParamValue(branch)) &&
       
   373 				(searchCanceledUas || taInfo->CompareMethod(method)) &&
       
   374 				(aType == CTransactionBase::KClientTransaction ||
       
   375 				 aType == CTransactionBase::KClientInviteTransaction ||
       
   376                  // Server transaction: sent-by of top via must match.
       
   377                  // Client transaction: sent-by can be missing from storedVia.
       
   378 				 (storedVia.SentByHostPort() == topVia->SentByHostPort())))
       
   379 				{
       
   380 				result = IgnoreAckTo2xx(aMsg, *taInfo,	aUserAgent);
       
   381 				}
       
   382 			}
       
   383 		}
       
   384 
       
   385 	__TEST_INVARIANT;
       
   386 	return result;
       
   387 	}
       
   388 
       
   389 // -----------------------------------------------------------------------------
       
   390 // CTransactionStore::CompareTransactionTypes
       
   391 // If searching UAS to cancel, accept only server transactions.
       
   392 // -----------------------------------------------------------------------------
       
   393 //
       
   394 TBool CTransactionStore::CompareTransactionTypes(const CTransactionInfo& aInfo,
       
   395 								   CTransactionBase::TTransactionType aType,
       
   396 								   TBool aSearchCanceledUas) const
       
   397 	{
       
   398     __TEST_INVARIANT;
       
   399 
       
   400 	if (aSearchCanceledUas)
       
   401 		{
       
   402 		__ASSERT_DEBUG(aType == CTransactionBase::KServerTransaction,
       
   403 					   User::Panic(_L("TaStore:CompTaTypes"), KErrArgument));		
       
   404 		return aInfo.CompareType(CTransactionBase::KServerTransaction) ||
       
   405                aInfo.CompareType(CTransactionBase::KServerInviteTransaction);
       
   406 		}
       
   407 
       
   408 	return aInfo.CompareType(aType);
       
   409 	}
       
   410 
       
   411 // -----------------------------------------------------------------------------
       
   412 // CTransactionStore::IgnoreAckTo2xx
       
   413 // Ignore Via branch of ACK to a 2xx. INVITE may've forked, one UAS sent 2xx,
       
   414 // other 4xx. Even if UAC sends ACK to both with a same branch as in INVITE, UAS
       
   415 // must ignore the ACK targeted to the other UAS. To-tag is the difference.
       
   416 // -----------------------------------------------------------------------------
       
   417 //
       
   418 MReceiverObserver*
       
   419 CTransactionStore::IgnoreAckTo2xx(const CSIPMessage& aMsg,
       
   420                                   CTransactionInfo& aInfo,
       
   421 								  const CUserAgent* aUserAgent) const
       
   422     {
       
   423     __TEST_INVARIANT;
       
   424 
       
   425 	if (CSIPMessageUtility::IsAck(aMsg) && !aUserAgent && aInfo.UserAgent())
       
   426         {
       
   427         // aMsg is ACK so UA must be InviteUAS
       
   428         __ASSERT_DEBUG(aInfo.UserAgent()->IsUAS() &&
       
   429             aInfo.CompareType(CTransactionBase::KServerInviteTransaction),
       
   430             User::Panic(_L("TaStore:IgnoreAckTo2xx"), KErrGeneral));
       
   431 
       
   432         if (CInviteUAS::Ptr(*(aInfo.UserAgent())).IsSending2xx())
       
   433             {
       
   434             return NULL;
       
   435             }
       
   436         }
       
   437 
       
   438     return CheckResult(aInfo, aUserAgent);
       
   439     }
       
   440 
       
   441 // -----------------------------------------------------------------------------
       
   442 // CTransactionStore::CheckResult
       
   443 // -----------------------------------------------------------------------------
       
   444 //
       
   445 MReceiverObserver*
       
   446 CTransactionStore::CheckResult(CTransactionInfo& aInfo,
       
   447 							   const CUserAgent* aUserAgent) const
       
   448 	{
       
   449     __TEST_INVARIANT;
       
   450 
       
   451 	if (!aUserAgent)
       
   452 		{
       
   453 		__ASSERT_DEBUG(aInfo.Receiver(),
       
   454 					   User::Panic(_L("TaStore:ChkResult"), KErrNotFound));
       
   455 		return aInfo.Receiver();
       
   456 		}
       
   457 
       
   458 	// Ignore result if it is the same UA that makes the search
       
   459     if (aInfo.UserAgent() == aUserAgent)
       
   460         {
       
   461         return NULL;
       
   462         }
       
   463 	return aInfo.UserAgent();
       
   464 	}
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CTransactionStore::SearchById
       
   468 // -----------------------------------------------------------------------------
       
   469 //
       
   470 CUserAgent* CTransactionStore::SearchById(TTransactionId aTransactionId)
       
   471 	{
       
   472 	__TEST_INVARIANT;
       
   473 
       
   474 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   475 	if (taInfo)
       
   476 		{
       
   477 		__ASSERT_DEBUG(taInfo->UserAgent(),
       
   478 					   User::Panic(_L("TaStore:SearchById"), KErrNotFound));
       
   479 		return taInfo->UserAgent();
       
   480 		}
       
   481 
       
   482 	return NULL;
       
   483 	}
       
   484 
       
   485 // -----------------------------------------------------------------------------
       
   486 // CTransactionStore::FindTransactionInfo
       
   487 // -----------------------------------------------------------------------------
       
   488 //
       
   489 CTransactionInfo*
       
   490 CTransactionStore::FindTransactionInfo(TTransactionId aTransactionId)
       
   491 	{
       
   492 	__TEST_INVARIANT;
       
   493     __ASSERT_DEBUG(aTransactionId != KEmptyTransactionId,
       
   494         		   User::Panic(_L("TaStore:FindTaInfo"), KErrArgument));
       
   495 
       
   496     TSglQueIter<CTransactionInfo> iter(iList);
       
   497     for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++)
       
   498     	{
       
   499     	if (taInfo->TransactionId() == aTransactionId)
       
   500 			{
       
   501 			__TEST_INVARIANT;
       
   502 			return taInfo;
       
   503 			}
       
   504     	if (taInfo->TransactionId() == KEmptyTransactionId)
       
   505 			{
       
   506             // TransactionInfo marked for deletion. Delete it.
       
   507 			DeleteItem(taInfo);			
       
   508 			}
       
   509     	}
       
   510 
       
   511 	__TEST_INVARIANT;
       
   512 	return NULL;
       
   513 	}
       
   514 
       
   515 // -----------------------------------------------------------------------------
       
   516 // CTransactionStore::IcmpErrorL
       
   517 // -----------------------------------------------------------------------------
       
   518 //
       
   519 void CTransactionStore::IcmpErrorL(const TInetAddr& aAddress,
       
   520 								   CSipConnectionMgr::TICMPError aError)
       
   521 	{
       
   522 	__TEST_INVARIANT;
       
   523 
       
   524 	TSglQueIter<CTransactionInfo> iter(iList);
       
   525 	for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++)
       
   526 		{
       
   527 		if (taInfo->Receiver())
       
   528 			{
       
   529 			taInfo->Receiver()->IcmpErrorL(aAddress, aError);
       
   530 			}
       
   531 		}
       
   532 
       
   533 	__TEST_INVARIANT;
       
   534 	}
       
   535 
       
   536 // -----------------------------------------------------------------------------
       
   537 // CTransactionStore::ClearUserAgent
       
   538 // -----------------------------------------------------------------------------
       
   539 //
       
   540 void CTransactionStore::ClearUserAgent(TTransactionId aTransactionId)
       
   541 	{
       
   542 	__TEST_INVARIANT;
       
   543 
       
   544 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   545 	if (taInfo)
       
   546 		{
       
   547 		taInfo->SetUserAgent(NULL);
       
   548 		}
       
   549 
       
   550 	__TEST_INVARIANT;
       
   551 	}
       
   552 
       
   553 // -----------------------------------------------------------------------------
       
   554 // CTransactionStore::ClearTransaction
       
   555 // -----------------------------------------------------------------------------
       
   556 //
       
   557 void CTransactionStore::ClearTransaction(TTransactionId aTransactionId)
       
   558 	{
       
   559 	__TEST_INVARIANT;
       
   560 
       
   561 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   562 	if (taInfo)
       
   563 		{
       
   564 		taInfo->SetTransaction(NULL);
       
   565 		}
       
   566 
       
   567 	__TEST_INVARIANT;
       
   568 	}
       
   569 
       
   570 // -----------------------------------------------------------------------------
       
   571 // CTransactionStore::UpdateTransactionId
       
   572 // -----------------------------------------------------------------------------
       
   573 //
       
   574 TInt CTransactionStore::UpdateTransactionId(TTransactionId aOldTransactionId,
       
   575 										    TTransactionId aNewTransactionId)
       
   576 	{
       
   577 	__TEST_INVARIANT;
       
   578     __SIP_ASSERT_RETURN_VALUE(!(aOldTransactionId == aNewTransactionId),
       
   579         					  KErrArgument);
       
   580     TInt status(KErrNotFound);
       
   581 	CTransactionInfo* taInfo = FindTransactionInfo(aOldTransactionId);
       
   582 	if (taInfo)
       
   583 		{
       
   584 		taInfo->SetTransactionId(aNewTransactionId);
       
   585 		status = KErrNone;
       
   586 		}
       
   587 
       
   588     __TEST_INVARIANT;
       
   589 	return status;
       
   590 	}
       
   591 
       
   592 // -----------------------------------------------------------------------------
       
   593 // CTransactionStore::UpdateL
       
   594 // -----------------------------------------------------------------------------
       
   595 //
       
   596 void CTransactionStore::UpdateL(TTransactionId aTransactionId,
       
   597 								CTransactionBase* aTransaction,
       
   598 								CSIPMessage* aMsg)
       
   599 	{
       
   600 	__TEST_INVARIANT;
       
   601 
       
   602 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   603 	__ASSERT_ALWAYS(taInfo, User::Leave(KErrNotFound));
       
   604 	taInfo->SetTransaction(aTransaction);
       
   605 	taInfo->UpdateMessageHeadersL(aMsg);
       
   606 
       
   607 	__TEST_INVARIANT;
       
   608 	}
       
   609 
       
   610 // -----------------------------------------------------------------------------
       
   611 // CTransactionStore::UpdateToTagL
       
   612 // -----------------------------------------------------------------------------
       
   613 //
       
   614 void
       
   615 CTransactionStore::UpdateToTagL(TTransactionId aTransactionId, RStringF aTag)
       
   616 	{
       
   617 	__TEST_INVARIANT;
       
   618 
       
   619 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   620 	__ASSERT_ALWAYS(taInfo, User::Leave(KErrNotFound));
       
   621 	taInfo->UpdateToTagL(aTag);
       
   622 
       
   623 	__TEST_INVARIANT;
       
   624 	}
       
   625 
       
   626 // -----------------------------------------------------------------------------
       
   627 // CTransactionStore::Remove
       
   628 // -----------------------------------------------------------------------------
       
   629 //
       
   630 void CTransactionStore::Remove(TTransactionId aTransactionId)
       
   631 	{
       
   632 	__TEST_INVARIANT;
       
   633 
       
   634 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   635 	if (taInfo)
       
   636 		{
       
   637 		RemoveListItem(*taInfo);
       
   638 		delete taInfo;
       
   639 		}
       
   640 
       
   641 	__TEST_INVARIANT;
       
   642 	}
       
   643 
       
   644 // -----------------------------------------------------------------------------
       
   645 // CTransactionStore::ClearTransactionOwner
       
   646 // -----------------------------------------------------------------------------
       
   647 //
       
   648 TInt
       
   649 CTransactionStore::ClearTransactionOwner(const MTransactionOwner* aObserver)
       
   650 	{
       
   651 	__TEST_INVARIANT;
       
   652     __SIP_ASSERT_RETURN_VALUE(aObserver != NULL, KErrArgument);
       
   653 
       
   654 	TInt status(KErrNotFound);
       
   655 	TSglQueIter<CTransactionInfo> iter(iList);
       
   656     CUserAgent* ua(NULL);
       
   657 
       
   658 	for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++)
       
   659 		{
       
   660 		ua = taInfo->UserAgent();
       
   661 		if (ua && ua->TransactionOwner() == aObserver)
       
   662 			{
       
   663 			ua->ClearTransactionOwner();
       
   664 			status = KErrNone;
       
   665 			// Continue the loop as many transactions may use the same aObserver
       
   666 			}
       
   667 		}
       
   668 
       
   669 	__TEST_INVARIANT;
       
   670 	return status;
       
   671 	}
       
   672 
       
   673 // -----------------------------------------------------------------------------
       
   674 // CTransactionStore::EndResolvingTransactions
       
   675 // Detached transactions (ua == NULL), are never resolving.
       
   676 // -----------------------------------------------------------------------------
       
   677 //
       
   678 void CTransactionStore::EndResolvingTransactions(TUint32 aIapId, TInt aReason)
       
   679 	{
       
   680 	__TEST_INVARIANT;
       
   681 
       
   682 	TSglQueIter<CTransactionInfo> iter(iList);
       
   683 	for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++)
       
   684 		{
       
   685         CUserAgent* ua = taInfo->UserAgent();
       
   686         if (ua && !ua->IsUAS())
       
   687             {
       
   688 			if ((ua->TransportParams().IapId() == aIapId) && ua->IsResolving())
       
   689 				{
       
   690 				ua->Stop(aReason);
       
   691 				}
       
   692             }
       
   693 		}
       
   694 
       
   695 	__TEST_INVARIANT;
       
   696 	}
       
   697 
       
   698 // -----------------------------------------------------------------------------
       
   699 // CTransactionStore::IsMergedRequest
       
   700 // -----------------------------------------------------------------------------
       
   701 //
       
   702 TBool CTransactionStore::IsMergedRequest(const CUserAgent& aUserAgent,
       
   703 										 CSIPRequest& aReq)
       
   704 	{
       
   705 	__TEST_INVARIANT;
       
   706 
       
   707 	CSIPFromHeader* from = aReq.From();
       
   708 	__ASSERT_DEBUG(from, User::Panic(_L("TaStore:IsMerg !from"), KErrArgument));
       
   709 
       
   710 	if (!aReq.HasHeader(SIPStrings::StringF(SipStrConsts::EFromHeader)) ||
       
   711 		!aReq.HasHeader(SIPStrings::StringF(SipStrConsts::ECallIDHeader)) ||
       
   712 		!aReq.HasHeader(SIPStrings::StringF(SipStrConsts::ECSeqHeader)) ||
       
   713 		!from->HasParam(SIPStrings::StringF(SipStrConsts::ETag)))
       
   714 		{
       
   715 		return EFalse;
       
   716 		}
       
   717 
       
   718     CSIPCSeqHeader* cseq = aReq.CSeq();
       
   719     __ASSERT_DEBUG(cseq, User::Panic(_L("TaStore:IsMerg !cseq"), KErrArgument));
       
   720 
       
   721 	TBool merged(EFalse);
       
   722 	TSglQueIter<CTransactionInfo> iter(iList);
       
   723 	for (CTransactionInfo* taInfo = iter++; taInfo && !merged; taInfo = iter++)
       
   724 		{
       
   725 		merged = taInfo->IsMergedRequest(aUserAgent,
       
   726 										 *from,
       
   727 										 *aReq.CallID(),
       
   728 										 cseq->Seq(),
       
   729 										 cseq->Method());
       
   730 		}
       
   731 
       
   732 	__TEST_INVARIANT;
       
   733 	return merged;
       
   734 	}
       
   735 
       
   736 // -----------------------------------------------------------------------------
       
   737 // CTransactionStore::CopyHeadersToResponseL
       
   738 // -----------------------------------------------------------------------------
       
   739 //
       
   740 void CTransactionStore::CopyHeadersToResponseL(TTransactionId aTransactionId,
       
   741 											   CSIPResponse& aResp)
       
   742 	{
       
   743 	__TEST_INVARIANT;
       
   744 	__SIP_ASSERT_RETURN(aTransactionId != KEmptyTransactionId, KErrArgument);
       
   745 	__SIP_ASSERT_RETURN(
       
   746 		!aResp.HasHeader(SIPStrings::StringF(SipStrConsts::EViaHeader)),
       
   747 		KErrArgument);
       
   748 
       
   749 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   750 	if (taInfo)
       
   751 		{
       
   752 		taInfo->CopyToFromCallIDCSeqToMsgL(aResp);
       
   753 		taInfo->CopyViaHeadersToMsgL(aResp);
       
   754 		}
       
   755 
       
   756 	__TEST_INVARIANT;
       
   757 	}
       
   758 
       
   759 // -----------------------------------------------------------------------------
       
   760 // CTransactionStore::CopyHeadersToRequestL
       
   761 // -----------------------------------------------------------------------------
       
   762 //
       
   763 void CTransactionStore::CopyHeadersToRequestL(TTransactionId aTransactionId,
       
   764 										      CSIPRequest& aReq,
       
   765 											  TBool aCopyRequestURI,
       
   766 										      TBool aCopyViaHeaders)
       
   767 	{
       
   768 	__TEST_INVARIANT;
       
   769 	__SIP_ASSERT_LEAVE(aTransactionId != KEmptyTransactionId, KErrArgument);
       
   770 
       
   771 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   772 	if (taInfo)
       
   773 		{
       
   774 		taInfo->CopyToFromCallIDCSeqToMsgL(aReq);
       
   775 
       
   776 		if (aCopyRequestURI)
       
   777 			{
       
   778 			taInfo->CopyRequestUriToRequestL(aReq);
       
   779 			}
       
   780 
       
   781 		if (aCopyViaHeaders)
       
   782 			{
       
   783 			taInfo->CopyViaHeadersToMsgL(aReq);
       
   784 			}
       
   785 		}
       
   786 
       
   787 	__TEST_INVARIANT;
       
   788 	}
       
   789 
       
   790 // -----------------------------------------------------------------------------
       
   791 // CTransactionStore::TransactionHeadersL
       
   792 // -----------------------------------------------------------------------------
       
   793 //
       
   794 MTransactionHeaders*
       
   795 CTransactionStore::TransactionHeadersL(TTransactionId aTransactionId)
       
   796 	{
       
   797 	__TEST_INVARIANT;
       
   798 
       
   799 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   800 	if (taInfo)
       
   801 		{
       
   802 		return taInfo->TransactionHeadersL();
       
   803 		}
       
   804 	return NULL;
       
   805 	}
       
   806 
       
   807 // -----------------------------------------------------------------------------
       
   808 // CTransactionStore::RandomTaInfoL
       
   809 // -----------------------------------------------------------------------------
       
   810 //
       
   811 void CTransactionStore::RandomTaInfoL(TTransactionId& aTaId,
       
   812 								      CUserAgent** aUserAgent,
       
   813 								      CSIPMessage** aMsg)
       
   814 	{
       
   815 	__TEST_INVARIANT;
       
   816 	__SIP_ASSERT_LEAVE(aUserAgent && aMsg, KErrArgument);
       
   817 
       
   818 	TSglQueIter<CTransactionInfo> iter(iList);
       
   819 	for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++)
       
   820 		{
       
   821 		if (aTaId == KEmptyTransactionId)
       
   822 			{
       
   823 			aTaId = taInfo->TransactionId();
       
   824 			}
       
   825 
       
   826 		if (taInfo->UserAgent())
       
   827 			{
       
   828 			*aUserAgent = taInfo->UserAgent();
       
   829 			*aMsg = taInfo->BuildRequestFromStoredInfoL();
       
   830 
       
   831             __TEST_INVARIANT;
       
   832 			return;
       
   833 			}
       
   834 		}
       
   835 
       
   836     __TEST_INVARIANT;
       
   837 	}
       
   838 
       
   839 // -----------------------------------------------------------------------------
       
   840 // CTransactionStore::RequestMethod
       
   841 // -----------------------------------------------------------------------------
       
   842 //
       
   843 RStringF CTransactionStore::RequestMethod(TTransactionId aTransactionId)
       
   844 	{
       
   845     __TEST_INVARIANT;
       
   846 
       
   847 	CTransactionInfo* taInfo = FindTransactionInfo(aTransactionId);
       
   848 	__ASSERT_DEBUG(taInfo, User::Panic(_L("TaStore:ReqMethod"), KErrNotFound));
       
   849 	return taInfo->RequestMethod();
       
   850 	}
       
   851 
       
   852 // -----------------------------------------------------------------------------
       
   853 // CTransactionStore::RemoveItemsByIapId
       
   854 // -----------------------------------------------------------------------------
       
   855 //
       
   856 void CTransactionStore::RemoveItemsByIapId(TUint32 aIapId)
       
   857     {
       
   858     __TEST_INVARIANT;
       
   859 
       
   860 	TSglQueIter<CTransactionInfo> iter(iList);
       
   861     for (CTransactionInfo* taInfo = iter++; taInfo; taInfo = iter++)
       
   862         {
       
   863         if (taInfo->IapId() == aIapId)
       
   864             {
       
   865             DeleteItem(taInfo);
       
   866             }
       
   867         }
       
   868 
       
   869     __TEST_INVARIANT;
       
   870     }
       
   871 
       
   872 // -----------------------------------------------------------------------------
       
   873 // CTransactionStore::AllowMoreServerTransactions
       
   874 // -----------------------------------------------------------------------------
       
   875 //
       
   876 TBool CTransactionStore::AllowMoreServerTransactions() const
       
   877 	{
       
   878 	__TEST_INVARIANT;
       
   879 	return iServerTransactionCount < iMaxServerTransactions;
       
   880 	}
       
   881 
       
   882 // -----------------------------------------------------------------------------
       
   883 // CTransactionStore::RemoveListItem
       
   884 // -----------------------------------------------------------------------------
       
   885 //
       
   886 void CTransactionStore::RemoveListItem(CTransactionInfo& aItem)
       
   887 	{
       
   888 	__TEST_INVARIANT;
       
   889 	if (aItem.CompareType(CTransactionBase::KServerTransaction) ||
       
   890         aItem.CompareType(CTransactionBase::KServerInviteTransaction))
       
   891 		{
       
   892 		--iServerTransactionCount;
       
   893 		}
       
   894 	iList.Remove(aItem);
       
   895 	__TEST_INVARIANT;
       
   896 	}
       
   897 // CTransactionStore::__DbgTestInvariant
       
   898 // -----------------------------------------------------------------------------
       
   899 //
       
   900 
       
   901 void CTransactionStore::__DbgTestInvariant() const
       
   902 	{
       
   903 	if (iTransactionIdCounter < KMinTransactionId)
       
   904 		{
       
   905 		User::Invariant();
       
   906 		}
       
   907 	}
       
   908