realtimenetprots/sipfw/SIP/SIPSec/IpSecPlugin/src/CSipSecAgreeContext.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          : CSipSecAgreeContext.cpp
       
    15 // Part of       : SIPSec
       
    16 // Version       : SIP/5.0
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include "sipstrings.h"
       
    22 #include "siprequest.h"
       
    23 #include "sipresponse.h"
       
    24 #include "sipcseqheader.h"
       
    25 #include "MSIPTransportMgr.h"
       
    26 #include "MIpSecMechanismParams.h"
       
    27 #include "MSIPSecSecurityMechanismObserver.h"
       
    28 #include "CSipSecAgreeRecord.h"
       
    29 #include "CSipSecAgreeContext.h"
       
    30 #include "SipSecUtils.h"
       
    31 
       
    32 #ifdef CPPUNIT_TEST
       
    33 #include "CActiveObjController1.h"
       
    34 #endif
       
    35 
       
    36 
       
    37 // ----------------------------------------------------------------------------
       
    38 // CSipSecAgreeContext::NewL
       
    39 // ----------------------------------------------------------------------------
       
    40 //
       
    41 CSipSecAgreeContext* CSipSecAgreeContext::NewL(
       
    42 	MIpSecMechanismParams& aParams,
       
    43 	TSIPTransportParams& aTransportParams,
       
    44 	CSIPResponse& aResponse,
       
    45 	CSIPRequest& aRequest,
       
    46 	TInetAddr& aRemoteAddress,
       
    47 	MSIPSecUser* aUser,
       
    48 	MSIPSecSecurityMechanismObserver& aObserver,
       
    49 	RPointerArray<CState>& aStates )	
       
    50 	{
       
    51 	CSipSecAgreeContext* 
       
    52 		self = CSipSecAgreeContext::NewLC( aParams,
       
    53 		                                   aTransportParams,
       
    54 		                                   aResponse,
       
    55 		                                   aRequest,
       
    56 										   aRemoteAddress,
       
    57 										   aUser,
       
    58 										   aObserver,
       
    59 										   aStates );
       
    60 	CleanupStack::Pop( self );
       
    61 	return self;
       
    62 	}
       
    63 
       
    64 // ----------------------------------------------------------------------------
       
    65 // CSipSecAgreeContext::NewLC
       
    66 // ----------------------------------------------------------------------------
       
    67 //
       
    68 CSipSecAgreeContext* CSipSecAgreeContext::NewLC(
       
    69 	MIpSecMechanismParams& aParams,
       
    70 	TSIPTransportParams& aTransportParams,
       
    71 	CSIPResponse& aResponse,
       
    72 	CSIPRequest& aRequest,
       
    73 	TInetAddr& aRemoteAddress,
       
    74 	MSIPSecUser* aUser,
       
    75 	MSIPSecSecurityMechanismObserver& aObserver,
       
    76 	RPointerArray<CState>& aStates )
       
    77 	{
       
    78 	CSipSecAgreeContext* self = 
       
    79 	    new ( ELeave ) CSipSecAgreeContext( aParams, aObserver, aStates );
       
    80 	CleanupStack::PushL(self);
       
    81 	self->ConstructL( aTransportParams,
       
    82 	                  aResponse,
       
    83 	                  aRequest,
       
    84 					  aRemoteAddress,
       
    85 					  aUser );
       
    86 	return self;
       
    87 	}
       
    88 
       
    89 // ----------------------------------------------------------------------------
       
    90 // CSipSecAgreeContext::CSipSecAgreeContext
       
    91 // ----------------------------------------------------------------------------
       
    92 //
       
    93 CSipSecAgreeContext::CSipSecAgreeContext( 
       
    94 	MIpSecMechanismParams& aParams,
       
    95 	MSIPSecSecurityMechanismObserver& aObserver,
       
    96 	RPointerArray<CState>& aStates ) :
       
    97 	iParams( aParams ),
       
    98 	iObserver( &aObserver ),
       
    99 	iStates( aStates )
       
   100 #ifdef CPPUNIT_TEST
       
   101     , iSecAgreeRecords( 1 )
       
   102 #endif
       
   103 	{
       
   104 	}
       
   105 
       
   106 // ----------------------------------------------------------------------------
       
   107 // CSipSecAgreeContext::ConstructL
       
   108 // ----------------------------------------------------------------------------
       
   109 //
       
   110 void CSipSecAgreeContext::ConstructL( TSIPTransportParams& aTransportParams,
       
   111 								      CSIPResponse& aResponse,
       
   112 								      CSIPRequest& aRequest,
       
   113 									  TInetAddr& aRemoteAddress,
       
   114 									  MSIPSecUser* aUser )
       
   115 	{
       
   116 	User::LeaveIfError( iParams.TransportMan().GetLocalAddress(
       
   117                                                 aTransportParams.IapId(),
       
   118                                                 iLocalAddress ) );
       
   119 	iRemoteAddress = aRemoteAddress;
       
   120 	iSecUser = aUser;
       
   121 
       
   122 	CSipSecAgreeRecord* r =
       
   123 	    CSipSecAgreeRecord::NewLC( iStates, *this, aTransportParams );
       
   124 
       
   125 #ifdef CPPUNIT_TEST
       
   126 	iObjCtr = new ( ELeave ) CActiveObjController1();
       
   127 	iObjCtr->iContext = this;
       
   128 	iObjCtr->iRcrdCtrl1 = r->iObjCtr;
       
   129 	r->iObjCtr->iFeedBack = iObjCtr;
       
   130 #endif
       
   131 
       
   132 	r->Resp4xxL( aResponse, aRequest );
       
   133 	iSecAgreeRecords.AppendL( r );
       
   134 	CleanupStack::Pop( r );
       
   135 	}
       
   136 	
       
   137 // ----------------------------------------------------------------------------
       
   138 // Destructor
       
   139 // ----------------------------------------------------------------------------
       
   140 //
       
   141 CSipSecAgreeContext::~CSipSecAgreeContext()
       
   142 	{
       
   143 	iSecAgreeRecords.ResetAndDestroy();	
       
   144 	}
       
   145 
       
   146 // ----------------------------------------------------------------------------
       
   147 // CSipSecAgreeContext::MechParams
       
   148 // ----------------------------------------------------------------------------
       
   149 //
       
   150 MIpSecMechanismParams& CSipSecAgreeContext::MechParams()
       
   151 	{
       
   152 	return iParams;
       
   153 	}
       
   154 
       
   155 // ----------------------------------------------------------------------------
       
   156 // CSipSecAgreeContext::LocalAddress
       
   157 // ----------------------------------------------------------------------------
       
   158 //
       
   159 TInetAddr CSipSecAgreeContext::LocalAddress()
       
   160 	{
       
   161 	return iLocalAddress;
       
   162 	}
       
   163 
       
   164 // ----------------------------------------------------------------------------
       
   165 // CSipSecAgreeContext::PolicyServer
       
   166 // ----------------------------------------------------------------------------
       
   167 //	
       
   168 RIpsecPolicyServ& CSipSecAgreeContext::PolicyServer()
       
   169     {
       
   170     return iParams.PolicyServer();
       
   171     }
       
   172 
       
   173 // ----------------------------------------------------------------------------
       
   174 // CSipSecAgreeContext::RemoteAddress
       
   175 // ----------------------------------------------------------------------------
       
   176 //  
       
   177 TInetAddr CSipSecAgreeContext::RemoteAddress()
       
   178 	{
       
   179 	return iRemoteAddress;
       
   180 	}
       
   181 
       
   182 // ----------------------------------------------------------------------------
       
   183 // CSipSecAgreeContext::HasOnlyOneRecord
       
   184 // ----------------------------------------------------------------------------
       
   185 //
       
   186 TBool CSipSecAgreeContext::HasOnlyOneRecord() const
       
   187 	{
       
   188 	TInt pos( 0 );
       
   189 	return ( NextRecord( pos ) != NULL && !NextRecord( pos ) );
       
   190 	}
       
   191 
       
   192 // ----------------------------------------------------------------------------
       
   193 // CSipSecAgreeContext::HasRecordInState
       
   194 // ----------------------------------------------------------------------------
       
   195 //
       
   196 TBool
       
   197 CSipSecAgreeContext::HasRecordInState( CState::TSecAgreeRecordState aState )
       
   198 	{	
       
   199 	TInt pos( 0 );
       
   200 	TBool found( EFalse );
       
   201 	CSipSecAgreeRecord* record = NextRecord( pos );
       
   202 	for ( ; !found && record; record = NextRecord( pos ) )
       
   203 		{
       
   204 		found = ( record->State() == aState );
       
   205 		}
       
   206 	return found;
       
   207 	}
       
   208 	
       
   209 // ----------------------------------------------------------------------------
       
   210 // CSipSecAgreeContext::SaDeleted
       
   211 // ----------------------------------------------------------------------------
       
   212 //
       
   213 void CSipSecAgreeContext::SaDeleted( CSipSecAgreeRecord* aRecord )
       
   214 	{
       
   215 	DeleteRecord( aRecord );
       
   216 	}
       
   217 
       
   218 // ----------------------------------------------------------------------------
       
   219 // CSipSecAgreeContext::SaCleared
       
   220 // ----------------------------------------------------------------------------
       
   221 //
       
   222 void CSipSecAgreeContext::SaCleared( CSipSecAgreeRecord* aRecord )
       
   223 	{
       
   224 	DeleteRecord( aRecord );
       
   225 	if ( iSecAgreeRecords.Count() == 0 )
       
   226 		{
       
   227 		iParams.ContextCleared( this );
       
   228 		}
       
   229 	}
       
   230 
       
   231 // ----------------------------------------------------------------------------
       
   232 // CSipSecAgreeContext::SAReady
       
   233 // ----------------------------------------------------------------------------
       
   234 //	
       
   235 void CSipSecAgreeContext::SAReady( TBool aSuccess )
       
   236     {
       
   237     if ( iObserver )
       
   238         {
       
   239         iObserver->SAReady( aSuccess );
       
   240         }
       
   241     }
       
   242 
       
   243 // ----------------------------------------------------------------------------
       
   244 // CSipSecAgreeContext::HasLongerLifetimeSA
       
   245 // ----------------------------------------------------------------------------
       
   246 //
       
   247 TBool
       
   248 CSipSecAgreeContext::HasLongerLifetimeSA( TUint aTimeToCompareInMillisecs,
       
   249 										  TUint& aLongerLifetimeInMillisecs )
       
   250     {
       
   251     // Compare only with "inuse" records
       
   252     TBool found( EFalse );
       
   253     TInt pos( 0 );
       
   254 	for ( CSipSecAgreeRecord* record = NextRecord( pos );
       
   255 		  !found && record;
       
   256 		  record = NextRecord( pos ) )	
       
   257 		{
       
   258 		TUint expiresAfter = record->ExpiresAfter();
       
   259 
       
   260 		if ( record->State() == CState::EInUse &&
       
   261 		     ( expiresAfter > aTimeToCompareInMillisecs ) )
       
   262 			{
       
   263 			aLongerLifetimeInMillisecs = expiresAfter;
       
   264 			found = ETrue;
       
   265 			}		
       
   266 		}
       
   267 	return found;
       
   268     }
       
   269 	
       
   270 // ----------------------------------------------------------------------------
       
   271 // CSipSecAgreeContext::HasSecUser
       
   272 // ----------------------------------------------------------------------------
       
   273 //
       
   274 TBool CSipSecAgreeContext::HasSecUser( const MSIPSecUser* aSecUser ) const
       
   275 	{
       
   276 	return aSecUser == iSecUser;
       
   277 	}
       
   278 
       
   279 // ----------------------------------------------------------------------------
       
   280 // CSipSecAgreeContext::HasNextHop
       
   281 // Ignore context for which clearing has started.
       
   282 // ----------------------------------------------------------------------------
       
   283 //
       
   284 TBool CSipSecAgreeContext::HasNextHop( const TInetAddr& aNextHop ) const
       
   285     {
       
   286     return ( !aNextHop.IsWildAddr() &&
       
   287     		 iRemoteAddress.Match( aNextHop ) &&
       
   288     		 !iClearOrdered );
       
   289     }
       
   290 
       
   291 // ----------------------------------------------------------------------------
       
   292 // CSipSecAgreeContext::ApplyRulesL
       
   293 // ----------------------------------------------------------------------------
       
   294 //
       
   295 void CSipSecAgreeContext::ApplyRulesL( TSIPTransportParams& aTransportParams, 
       
   296 									   CSIPRequest& aRequest,
       
   297 									   const TDesC8& aOutboundProxy,
       
   298 									   MSIPSecUser* aUser )
       
   299 	{
       
   300 	TInt pos( 0 );
       
   301 	CSipSecAgreeRecord* record = NextRecord( pos );
       
   302 
       
   303 	if ( SipSecUtils::Match( SipStrConsts::ERegister, aRequest.Method() ) )
       
   304 		{
       
   305 		// Other MSIPSecUsers cannot use existing context (SA)
       
   306 		// for registration to the same outbound proxy.
       
   307 		__ASSERT_ALWAYS( HasSecUser( aUser ), User::Leave( KErrInUse ) );
       
   308 
       
   309 		for ( ; record; record = NextRecord( pos ) )
       
   310 			{
       
   311 			record->RegisterL( aTransportParams, aRequest, aOutboundProxy );
       
   312 			}
       
   313 		}
       
   314 	else
       
   315 		{
       
   316 		for ( ; record; record = NextRecord( pos ) )
       
   317 			{
       
   318 			record->ReguestL( aTransportParams, aRequest, aOutboundProxy );
       
   319 			}
       
   320 		}
       
   321 	}
       
   322 	
       
   323 // ----------------------------------------------------------------------------
       
   324 // CSipSecAgreeContext::ApplyRulesL
       
   325 // IPSec is only interested on 401 and 200 responses
       
   326 // ----------------------------------------------------------------------------
       
   327 //	
       
   328 void CSipSecAgreeContext::ApplyRulesL( 
       
   329 	CSIPResponse& aResponse,
       
   330 	CSIPRequest& aRequest,
       
   331 	MSIPSecSecurityMechanismObserver& aObserver )
       
   332 	{
       
   333 	if ( aResponse.ResponseCode() == K401Response )
       
   334 		{
       
   335 		// First check if a new record must be created
       
   336 		CreateNewSecAgreeRecordIfNeededL();
       
   337 
       
   338 		TInt pos( 0 );		
       
   339 		for ( CSipSecAgreeRecord* record = NextRecord( pos );
       
   340 			  record;
       
   341 			  record = NextRecord( pos ) )
       
   342 			{
       
   343 			record->Resp4xxL( aResponse, aRequest );
       
   344 			}
       
   345 		iObserver = &aObserver;	
       
   346 		}
       
   347 	if ( aResponse.ResponseCode() == K200Response )
       
   348 		{
       
   349 		CSIPCSeqHeader* h = static_cast<CSIPCSeqHeader*>(
       
   350 			SipSecUtils::SingleHeader( aResponse, SipStrConsts::ECSeqHeader ) );
       
   351 		if ( h && h->Method() == _STRINGF( SipStrConsts::ERegister ) )
       
   352 			{
       
   353 			TInt pos( 0 );
       
   354 			for ( CSipSecAgreeRecord* record = NextRecord( pos );
       
   355 				  record;
       
   356 				  record = NextRecord( pos ) )
       
   357 				{
       
   358 				record->Resp2xxL( aResponse );
       
   359 				}
       
   360 			iObserver = &aObserver;
       
   361 			}
       
   362 		}
       
   363 	}
       
   364 
       
   365 // ----------------------------------------------------------------------------
       
   366 // CSipSecAgreeContext::CreateNewSecAgreeRecordIfNeededL
       
   367 // Create new record if an existing record is in InUse, Deleting or Clearing
       
   368 // state. Deleting and Clearing states are included because in some very rare
       
   369 // scenario 4xx might be received before SA deletion is completed, and such
       
   370 // situation must not cause malfunction.
       
   371 //
       
   372 //
       
   373 // If two records exist already. Drop one of them by setting it obsolete.
       
   374 //
       
   375 // Selecting the record to be obsoleted:
       
   376 //   SA-1's state	  SA-2's state				  drop
       
   377 //   ------------     ------------                ----
       
   378 //   InUse      	  Tentative..PendingPolicy	  SA-2
       
   379 //   Old..Deleting	  InUse						  SA-1
       
   380 //
       
   381 // When 2xx is received, SA-1 enters "Old" and SA-2 enters "InUse",
       
   382 // so two records can't be in "InUse".
       
   383 //
       
   384 //
       
   385 // New record uses initially same transport params, as it must share protected
       
   386 // server port with old record. When new record is reserving transport,
       
   387 // transport params will be updated. New record derives Security-Client and
       
   388 // Security-Verify headers from response and corresponding request.
       
   389 // ----------------------------------------------------------------------------
       
   390 //
       
   391 void CSipSecAgreeContext::CreateNewSecAgreeRecordIfNeededL()
       
   392 	{
       
   393 	if ( HasRecordInState( CState::EInUse ) ||
       
   394 		 HasRecordInState( CState::EDeleting ) ||
       
   395 		 HasRecordInState( CState::EClearing ) )
       
   396 		{
       
   397 		if ( !HasOnlyOneRecord() )	
       
   398 			{			
       
   399 			TInt pos( 0 );
       
   400 			CSipSecAgreeRecord* rec = NextRecord( pos );
       
   401 			if(rec)
       
   402 			{
       
   403 			if ( rec->State() == CState::EInUse )
       
   404 				{
       
   405 				// Record is "in use", drop the other record
       
   406 				rec = NextRecord( pos );
       
   407 				if(rec)
       
   408 				{
       
   409 					__ASSERT_ALWAYS( rec->State() != CState::EInUse,
       
   410 							 	 User::Leave( KErrGeneral ) );
       
   411 				}
       
   412 				}
       
   413 			}
       
   414 			if(rec)
       
   415 			{
       
   416 				rec->SetObsoleteL();
       
   417 			}
       
   418 			}
       
   419 		TInt pos = 0;
       
   420 		CSipSecAgreeRecord* rec = NextRecord( pos );
       
   421 		__ASSERT_ALWAYS( rec, User::Leave( KErrNotFound ) );
       
   422 
       
   423 		CSipSecAgreeRecord*	newRecord =
       
   424 		    CSipSecAgreeRecord::NewLC( iStates, *this, rec->TransportParams() );
       
   425 
       
   426 #ifdef CPPUNIT_TEST
       
   427 	    if ( !rec->iObjCtr->iFeedBack->iRcrdCtrl2 )
       
   428 	    	{
       
   429 	    	rec->iObjCtr->iFeedBack->iRcrdCtrl2 = newRecord->iObjCtr;
       
   430 	    	}
       
   431 	    else if ( !rec->iObjCtr->iFeedBack->iRcrdCtrl3 )
       
   432 	    	{
       
   433 	    	rec->iObjCtr->iFeedBack->iRcrdCtrl3 = newRecord->iObjCtr;
       
   434 	    	}
       
   435 	    else if ( !rec->iObjCtr->iFeedBack->iRcrdCtrl4 )
       
   436 	    	{
       
   437 	    	rec->iObjCtr->iFeedBack->iRcrdCtrl4 = newRecord->iObjCtr;
       
   438 	    	}
       
   439 #endif
       
   440 		iSecAgreeRecords.AppendL( newRecord );
       
   441 		CleanupStack::Pop( newRecord );
       
   442 		}
       
   443 	}
       
   444 
       
   445 // ----------------------------------------------------------------------------
       
   446 // CSipSecAgreeContext::ApplyRulesL
       
   447 // ----------------------------------------------------------------------------
       
   448 //	
       
   449 void CSipSecAgreeContext::ApplyRulesL( 
       
   450 	RPointerArray<CSIPSecurityVerifyHeader>& aSecurityVerify )
       
   451 	{
       
   452 	TInt pos( 0 );
       
   453 	CSipSecAgreeRecord* record( NULL );
       
   454 	while ( ( record = NextRecord( pos ) ) != NULL )
       
   455 		{
       
   456 		record->ProcessSecVerifyL( aSecurityVerify );
       
   457 		}
       
   458 	}
       
   459 	
       
   460 // ----------------------------------------------------------------------------
       
   461 // CSipSecAgreeContext::SetAuthKeyL
       
   462 // ----------------------------------------------------------------------------
       
   463 //
       
   464 TBool CSipSecAgreeContext::SetAuthKeyL( const TDesC8& aAuthKey )
       
   465 	{
       
   466 	TBool ret( EFalse );
       
   467 	TInt pos( 0 );
       
   468 	CSipSecAgreeRecord* record( NULL );
       
   469 	while ( ( record = NextRecord( pos ) ) != NULL )
       
   470 		{
       
   471 		ret |= record->AuthKeyL( aAuthKey );
       
   472 		}
       
   473 	return ret;
       
   474 	}
       
   475 
       
   476 // ----------------------------------------------------------------------------
       
   477 // CSipSecAgreeContext::AuthKeyFailedL
       
   478 // ----------------------------------------------------------------------------
       
   479 //	
       
   480 void CSipSecAgreeContext::AuthKeyFailedL()
       
   481     {
       
   482     // Reverse order since call might lead to deletion of record
       
   483     TInt lastIndex( iSecAgreeRecords.Count() - 1 );
       
   484     for ( TInt i = lastIndex; i >= 0; --i )
       
   485 		{
       
   486 		if ( !iSecAgreeRecords[ i ]->IsObsolete() )
       
   487 			{
       
   488 			iSecAgreeRecords[ i ]->AuthKeyFailedL();
       
   489 			}
       
   490 		}
       
   491     }
       
   492 
       
   493 // ----------------------------------------------------------------------------
       
   494 // CSipSecAgreeContext::ClearL
       
   495 // Affects also obsolete records.
       
   496 // ----------------------------------------------------------------------------
       
   497 //	
       
   498 void CSipSecAgreeContext::ClearL()
       
   499 	{	
       
   500 	iClearOrdered = ETrue;
       
   501 
       
   502 	// Reverse order since call might lead to deletion of record, also whole
       
   503 	// context (this) will be removed if clearing leads to immediate deletion
       
   504 	// of all records.
       
   505     TInt lastIndex( iSecAgreeRecords.Count() - 1 );
       
   506 	for ( TInt i = lastIndex; i >= 0; i--  )
       
   507 		{
       
   508 		iSecAgreeRecords[ i ]->ClearSaL();
       
   509 		}
       
   510 	}
       
   511 
       
   512 // ----------------------------------------------------------------------------
       
   513 // CSipSecAgreeContext::CancelPendingOps
       
   514 // Affects also obsolete records.
       
   515 // ----------------------------------------------------------------------------
       
   516 //   
       
   517 void CSipSecAgreeContext::CancelPendingOps(
       
   518     const MSIPSecSecurityMechanismObserver* aObserver )
       
   519     {
       
   520     if ( iObserver && iObserver == aObserver )
       
   521         {
       
   522         // Observer cannot be used anymore
       
   523         iObserver = NULL;
       
   524         for ( TInt i = 0; i < iSecAgreeRecords.Count(); ++i )
       
   525 		    {
       
   526 		    iSecAgreeRecords[ i ]->CancelPendingOps();
       
   527 		    }
       
   528         }
       
   529     }
       
   530 
       
   531 // ----------------------------------------------------------------------------
       
   532 // CSipSecAgreeContext::SADBAddMsgReceived
       
   533 // ----------------------------------------------------------------------------
       
   534 //
       
   535 void CSipSecAgreeContext::SADBAddMsgReceived( TUint aMsgSeq, TInt aError )
       
   536     {    
       
   537     TInt pos( 0 );
       
   538 	CSipSecAgreeRecord* record( NULL );
       
   539 	while ( ( record = NextRecord( pos ) ) != NULL )	    
       
   540         {
       
   541         record->SADBAddMsgReceived( aMsgSeq, aError );
       
   542         }
       
   543     }
       
   544 
       
   545 // ----------------------------------------------------------------------------
       
   546 // CSipSecAgreeContext::RemovalCompleted
       
   547 // Affects also obsolete records.
       
   548 // ----------------------------------------------------------------------------
       
   549 //
       
   550 void CSipSecAgreeContext::RemovalCompleted( TUint32 aTransportId )
       
   551     {    
       
   552     for ( TInt i = 0; i < iSecAgreeRecords.Count(); ++i  )
       
   553         {
       
   554         iSecAgreeRecords[ i ]->RemovalCompleted( aTransportId );
       
   555         }
       
   556     }
       
   557 
       
   558 // ----------------------------------------------------------------------------
       
   559 // CSipSecAgreeContext::DeleteRecord
       
   560 // Affects also obsolete records.
       
   561 // ----------------------------------------------------------------------------
       
   562 //
       
   563 void CSipSecAgreeContext::DeleteRecord( CSipSecAgreeRecord* aRecord )
       
   564 	{
       
   565 	TInt i = iSecAgreeRecords.Find( aRecord );
       
   566 	iSecAgreeRecords.Remove( i );
       
   567 	iSecAgreeRecords.Compress();
       
   568 	delete aRecord;	
       
   569 	}
       
   570 
       
   571 // ----------------------------------------------------------------------------
       
   572 // CSipSecAgreeContext::NextRecord
       
   573 // ----------------------------------------------------------------------------
       
   574 //
       
   575 CSipSecAgreeRecord* CSipSecAgreeContext::NextRecord( TInt& aPos ) const
       
   576 	{
       
   577 	for ( TInt i = aPos; i < iSecAgreeRecords.Count(); ++i )
       
   578 		{
       
   579 		if ( !iSecAgreeRecords[ i ]->IsObsolete() )
       
   580 			{
       
   581 			// Set aPos point to next record
       
   582 			aPos = i + 1;
       
   583 			return iSecAgreeRecords[ i ];
       
   584 			}
       
   585 		}
       
   586 	return NULL;
       
   587 	}
       
   588 
       
   589 // End of File