realtimenetprots/sipfw/SIP/sipapi/src/sipdialogstate.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2005-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          : sipdialogstate.cpp
       
    15 // Part of       : SIPAPI
       
    16 // Version       : SIP/4.0 
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include <uri8.h>
       
    22 #include "siperr.h"
       
    23 #include "sipinternalerr.h"
       
    24 #include "SipAssert.h"
       
    25 #include "sipfromheader.h"
       
    26 #include "siptoheader.h"
       
    27 #include "sipdialogstate.h"
       
    28 #include "SipConnectionImplementation.h"
       
    29 #include "sipclientconnection.h"
       
    30 #include "SipDialogImplementation.h"
       
    31 #include "SipDialogAssocImplementation.h"
       
    32 #include "siprefresh.h"
       
    33 #include "sipservertransaction.h"
       
    34 #include "sipinviteclienttransaction.h"
       
    35 #include "siprequestelements.h"
       
    36 #include "sipresponseelements.h"
       
    37 #include "sipcseqheader.h"
       
    38 #include "csipdialogresponsesender.h"
       
    39 #include "sipconnectioncallback.h"
       
    40 #include "sipinvitedialogassoc.h"
       
    41 #include "sipstrings.h"
       
    42 #include "sipstrconsts.h"
       
    43 
       
    44 #ifdef CPPUNIT_TEST
       
    45 #include "TestCleanupStack.h"
       
    46 #endif
       
    47 
       
    48 // -----------------------------------------------------------------------------
       
    49 // CDialogState::~CDialogState
       
    50 // -----------------------------------------------------------------------------
       
    51 //
       
    52 CDialogState::~CDialogState()
       
    53 	{
       
    54 	}
       
    55 
       
    56 // -----------------------------------------------------------------------------
       
    57 // CDialogState::SendNonTargetRefreshRequestL
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 CSIPClientTransaction* CDialogState::SendNonTargetRefreshRequestL(
       
    61 								const CSIPDialogImplementation& /*aDialog*/,
       
    62                                 CSIPDialogAssocImplementation& /*aAssoc*/,
       
    63                                 RStringF /*aMethod*/,
       
    64                                 CSIPMessageElements* /*aElements*/) const
       
    65     {
       
    66   	return InvalidStateL();
       
    67     }
       
    68 
       
    69 // -----------------------------------------------------------------------------
       
    70 // CDialogState::SendInviteL
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 CSIPClientTransaction*
       
    74 CDialogState::SendInviteL(const CSIPDialogImplementation& /*aDialog*/,
       
    75                           CSIPInviteDialogAssoc& /*aAssoc*/,
       
    76                           CSIPMessageElements* /*aElements*/) const
       
    77 	{
       
    78 	return InvalidStateL();
       
    79 	}
       
    80 
       
    81 // -----------------------------------------------------------------------------
       
    82 // CDialogState::SendPrackL
       
    83 // Application might try to send PRACK at any time
       
    84 // -----------------------------------------------------------------------------
       
    85 //
       
    86 CSIPClientTransaction*
       
    87 CDialogState::SendPrackL(CSIPInviteDialogAssoc& /*aAssoc*/,
       
    88                          CSIPMessageElements* /*aElements*/) const
       
    89     {    
       
    90     return InvalidStateL();
       
    91 	}
       
    92 
       
    93 // -----------------------------------------------------------------------------
       
    94 // CDialogState::SendUpdateL
       
    95 // Application might try to send UPDATE at any time
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 CSIPClientTransaction*
       
    99 CDialogState::SendUpdateL(CSIPInviteDialogAssoc& /*aAssoc*/,
       
   100                           CSIPMessageElements* /*aElements*/) const
       
   101     {
       
   102     return InvalidStateL();
       
   103 	}
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CDialogState::SendAckL
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 void CDialogState::SendAckL(CSIPInviteDialogAssoc& /*aAssoc*/,
       
   110                             const CSIPClientTransaction& /*aTransaction*/,
       
   111 	                        CSIPMessageElements* /*aElements*/) const
       
   112     {
       
   113     InvalidStateL();
       
   114 	}
       
   115 
       
   116 // -----------------------------------------------------------------------------
       
   117 // CDialogState::SendByeL
       
   118 // Application might try to send BYE at any time
       
   119 // -----------------------------------------------------------------------------
       
   120 //
       
   121 CSIPClientTransaction*
       
   122 CDialogState::SendByeL(CSIPInviteDialogAssoc& /*aAssoc*/,
       
   123                        CSIPMessageElements* /*aElements*/) const
       
   124     {
       
   125 	return InvalidStateL();
       
   126 	}
       
   127 
       
   128 // -----------------------------------------------------------------------------
       
   129 // CDialogState::SendNotifyL
       
   130 // Application might try to send NOTIFY at any time
       
   131 // -----------------------------------------------------------------------------
       
   132 //
       
   133 CSIPClientTransaction*
       
   134 CDialogState::SendNotifyL(CSIPNotifyDialogAssoc& /*aAssoc*/,
       
   135                     	  CSIPMessageElements* /*aElements*/) const
       
   136 	{
       
   137 	return InvalidStateL();
       
   138 	}
       
   139 
       
   140 // -----------------------------------------------------------------------------
       
   141 // CDialogState::SendReferL
       
   142 // Application might try to send REFER at any time
       
   143 // -----------------------------------------------------------------------------
       
   144 //
       
   145 CSIPClientTransaction*
       
   146 CDialogState::SendReferL(const CSIPDialogImplementation& /*aDialog*/,
       
   147 						 CSIPReferDialogAssoc& /*aAssoc*/,
       
   148                     	 CSIPMessageElements* /*aElements*/) const
       
   149 	{
       
   150 	return InvalidStateL();
       
   151 	}
       
   152 
       
   153 // -----------------------------------------------------------------------------
       
   154 // CDialogState::SendResponseL
       
   155 // Application might try to send response at any time
       
   156 // -----------------------------------------------------------------------------
       
   157 //
       
   158 void CDialogState::SendResponseL(CSIPDialogImplementation& /*aDialog*/,
       
   159                                  const CSIPResponseElements& /*aElements*/,
       
   160 						         TUint32 /*aRequestId*/,
       
   161                                  TBool /*aAffectsDialogState*/,
       
   162                                  TBool /*aTargetRefresh*/) const
       
   163     {    
       
   164     InvalidStateL();
       
   165     }
       
   166 
       
   167 // -----------------------------------------------------------------------------
       
   168 // CDialogState::SendSubscribeL
       
   169 // Application might try to send SUBSCRIBE at any time
       
   170 // -----------------------------------------------------------------------------
       
   171 //
       
   172 CSIPClientTransaction*
       
   173 CDialogState::SendSubscribeL(const CSIPDialogImplementation& /*aDialog*/,
       
   174                              CSIPSubscribeDialogAssoc& /*aAssoc*/,
       
   175                              CSIPMessageElements* /*aElements*/,
       
   176                              CSIPRefresh* /*aRefresh*/) const
       
   177     {
       
   178 	return InvalidStateL();
       
   179     }
       
   180 
       
   181 // -----------------------------------------------------------------------------
       
   182 // CDialogState::UpdateL
       
   183 // Application might try to update SUBSCRIBE at any time
       
   184 // -----------------------------------------------------------------------------
       
   185 //
       
   186 CSIPClientTransaction*
       
   187 CDialogState::UpdateL(const CSIPDialogImplementation& /*aDialog*/,
       
   188                 	  CSIPSubscribeDialogAssoc& /*aAssoc*/,
       
   189                 	  CSIPMessageElements* /*aElements*/) const
       
   190 	{
       
   191     return InvalidStateL();
       
   192 	}
       
   193 
       
   194 // -----------------------------------------------------------------------------
       
   195 // CDialogState::SendUnsubscribeL
       
   196 // Application might try to send (un)SUBSCRIBE at any time
       
   197 // -----------------------------------------------------------------------------
       
   198 //
       
   199 CSIPClientTransaction*
       
   200 CDialogState::SendUnsubscribeL(CSIPSubscribeDialogAssoc& /*aAssoc*/,
       
   201                                CSIPMessageElements* /*aElements*/) const
       
   202     {    
       
   203     return InvalidStateL();
       
   204     }
       
   205 
       
   206 // -----------------------------------------------------------------------------
       
   207 // CDialogState::IncomingResponseL
       
   208 // -----------------------------------------------------------------------------
       
   209 //
       
   210 TBool CDialogState::IncomingResponseL(CSIPDialogImplementation& /*aDialog*/,
       
   211                                       CSIPResponseElements* /*aElements*/,
       
   212 		                              TUint32 /*aRequestId*/,
       
   213                                       TUint32 /*aDialogId*/,
       
   214                                       CConnectionCallback& /*aCallback*/) const
       
   215     {
       
   216 	__SIP_ASSERT_LEAVE(EFalse, KErrSIPInvalidDialogState);
       
   217     return EFalse;
       
   218 	}
       
   219 
       
   220 // -----------------------------------------------------------------------------
       
   221 // CDialogState::IncomingResponseL
       
   222 // -----------------------------------------------------------------------------
       
   223 //
       
   224 TBool CDialogState::IncomingResponseL(CSIPDialogImplementation& /*aDialog*/,
       
   225                                       CSIPResponseElements* /*aElements*/,
       
   226 		                              TUint32 /*aRequestId*/,
       
   227                                       TUint32 /*aRefreshId*/,
       
   228                                       TUint32 /*aDialogId*/,
       
   229                                       CConnectionCallback& /*aCallback*/) const
       
   230     {
       
   231     __SIP_ASSERT_LEAVE(EFalse, KErrSIPInvalidDialogState);
       
   232     return EFalse;
       
   233 	}
       
   234 
       
   235 // -----------------------------------------------------------------------------
       
   236 // CDialogState::IncomingRequestL
       
   237 // If the received request is not handled by current state, ignore it.
       
   238 // -----------------------------------------------------------------------------
       
   239 //
       
   240 TBool
       
   241 CDialogState::IncomingRequestL(CSIPDialogImplementation& /*aDialog*/,
       
   242                                CSIPServerTransaction* aTransaction,
       
   243                                CConnectionCallback& /*aCallback*/) const                               
       
   244     {
       
   245     delete aTransaction;
       
   246     return EFalse;
       
   247     }
       
   248 
       
   249 // -----------------------------------------------------------------------------
       
   250 // CDialogState::ErrorOccured
       
   251 // -----------------------------------------------------------------------------
       
   252 //
       
   253 TBool CDialogState::ErrorOccured(CSIPDialogImplementation& /*aDialog*/,
       
   254                                  TInt /*aError*/,
       
   255                                  TUint32 /*aRequestId*/,
       
   256                                  CConnectionCallback& /*aCallback*/) const
       
   257     {
       
   258 	__ASSERT_DEBUG(EFalse,
       
   259 		User::Panic(_L("CDialogState::ErrorOccured() no event handler"),
       
   260 					KErrSIPInvalidDialogState));
       
   261 
       
   262     return EFalse;
       
   263 	}
       
   264 
       
   265 // -----------------------------------------------------------------------------
       
   266 // CDialogState::ErrorOccured
       
   267 // -----------------------------------------------------------------------------
       
   268 //
       
   269 TBool CDialogState::ErrorOccured(CSIPDialogImplementation& /*aDialog*/,
       
   270                                  TInt /*aError*/,
       
   271                                  TUint32 /*aRefreshId*/,
       
   272                                  TUint32 /*aRequestId*/,
       
   273                                  CConnectionCallback& /*aCallback*/) const
       
   274     {
       
   275     __ASSERT_DEBUG(EFalse,
       
   276 		User::Panic(_L("CDialogState::ErrorOccured(refresh) no event handler"),
       
   277 					KErrSIPInvalidDialogState));
       
   278     return EFalse;
       
   279     }
       
   280 
       
   281 // -----------------------------------------------------------------------------
       
   282 // CDialogState::HandleErrorOccurred
       
   283 // If the transaction and association are not found, error is ignored.
       
   284 // If ACK wasn't received, the application must still be able to send a BYE to
       
   285 // terminate the session, so the dialog must not be terminated.
       
   286 // If dialog is confirmed, error won't cause it go into terminated state.
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 TBool CDialogState::HandleErrorOccurred(CSIPDialogImplementation& aDialog,
       
   290                                         TInt aError,
       
   291                                         TUint32 aRequestId,
       
   292                                         CConnectionCallback& aCallback,
       
   293                                         CDialogState& aTerminated) const
       
   294     {
       
   295     __SIP_ASSERT_RETURN_VALUE(aError != KErrNone, EFalse);
       
   296 
       
   297     CSIPTransactionBase* ta = NULL;
       
   298     CSIPDialogAssocBase* assoc = NULL;
       
   299 
       
   300 	CConnectionCallback::TCallbackMethod callback =
       
   301 		CConnectionCallback::EErrorOccuredDialogTransaction;
       
   302 	if (!aDialog.FindTransactionAndAssoc(aRequestId, &ta, &assoc))	
       
   303 		{
       
   304 		CSIPConnection* conn = aDialog.Connection();
       
   305 		if (conn)
       
   306 			{
       
   307 			ta = conn->Implementation().FindTransaction(aRequestId);
       
   308 			if (ta)			
       
   309 				{		
       
   310 				callback = CConnectionCallback::EErrorOccuredTransaction;
       
   311 				}
       
   312 			}
       
   313 		}
       
   314 
       
   315 	if (ta)
       
   316 		{
       
   317         if (ta->AffectsDialogState() && aError != KErrSIPNoAckReceived)
       
   318             {
       
   319 			aDialog.ChangeState(&aTerminated);
       
   320             }
       
   321         ta->ChangeState(CSIPTransactionBase::ETerminated);
       
   322 
       
   323     	if (aError == KInviteTransactionCancelled)
       
   324         	{
       
   325         	__SIP_ASSERT_RETURN_VALUE(!ta->IsSIPClientTransaction(), EFalse);
       
   326         	callback = CConnectionCallback::EInviteCanceled;
       
   327         	assoc = NULL;        	
       
   328         	}
       
   329 
       
   330         aCallback.Set(callback, ta, NULL, NULL, assoc, aError);
       
   331         return ETrue;
       
   332         }
       
   333 	return EFalse;
       
   334     }
       
   335 
       
   336 // -----------------------------------------------------------------------------
       
   337 // CDialogState::HandleRefreshErrorOccurred
       
   338 // INVITE can't be refreshed, so KInviteTransactionCancelled and
       
   339 // KErrSIPNoAckReceived don't need to be handled.
       
   340 // -----------------------------------------------------------------------------
       
   341 //
       
   342 TBool
       
   343 CDialogState::HandleRefreshErrorOccurred(CSIPDialogImplementation& aDialog,
       
   344 		                                 TInt aError,
       
   345 		                                 TUint32 aRefreshId,
       
   346 		                                 CConnectionCallback& aCallback,
       
   347 		                                 CDialogState& aTerminated) const
       
   348     {
       
   349  	__SIP_ASSERT_RETURN_VALUE(aError != KErrNone, EFalse);
       
   350 
       
   351     CSIPDialogAssocBase* assoc = NULL;
       
   352     CSIPRefresh* refresh = NULL;
       
   353     if (aDialog.FindAssocAndRefresh(aRefreshId, &assoc, &refresh))
       
   354         {
       
   355         CSIPClientTransaction* ta = refresh->Transaction();
       
   356         if (ta)
       
   357             {
       
   358             if (ta->AffectsDialogState() &&
       
   359             	aDialog.State() != CSIPDialog::EConfirmed)
       
   360                 {
       
   361                 aDialog.ChangeState(&aTerminated);
       
   362                 }
       
   363             ta->ChangeState(CSIPTransactionBase::ETerminated);
       
   364             }
       
   365         refresh->ChangeState(CSIPRefresh::ETerminated);		
       
   366         aCallback.Set(CConnectionCallback::EErrorOccuredDialog,
       
   367                       NULL,
       
   368                       NULL,
       
   369                       NULL,
       
   370                       assoc,
       
   371                       aError);
       
   372         return ETrue;
       
   373         }
       
   374 
       
   375     return EFalse;
       
   376     }
       
   377 
       
   378 // -----------------------------------------------------------------------------
       
   379 // CDialogState::RequestReceivedL
       
   380 // Application must resolve the actual dialog association to which this request
       
   381 // belongs. No dialog association is created by SIP API, it is application's
       
   382 // responsibility to create the association.
       
   383 // Dialog-related sender is set, so that the response goes through the dialog.
       
   384 // -----------------------------------------------------------------------------
       
   385 //
       
   386 TBool CDialogState::RequestReceivedL(CSIPDialogImplementation& aDialog,
       
   387                                      CSIPServerTransaction* aTransaction,                             
       
   388                                      CConnectionCallback& aCallback) const
       
   389     {
       
   390     __SIP_ASSERT_LEAVE(aTransaction, KErrArgument);
       
   391 
       
   392     aDialog.UpdateRemoteTargetL(aTransaction->Type(),
       
   393 						aTransaction->RequestElements()->MessageElements());
       
   394 
       
   395     aTransaction->SetResponseSender(CSIPDialogResponseSender::NewL(aDialog));
       
   396     aCallback.Set(CConnectionCallback::EIncomingRequest,
       
   397                   aTransaction,
       
   398                   NULL,
       
   399                   &aDialog.Dialog());
       
   400     return ETrue;
       
   401     }
       
   402 
       
   403 // -----------------------------------------------------------------------------
       
   404 // CDialogState::SendResponseWithinDialogL
       
   405 // -----------------------------------------------------------------------------
       
   406 //
       
   407 void
       
   408 CDialogState::SendResponseWithinDialogL(CSIPDialogImplementation& aDialog,
       
   409                                         const CSIPResponseElements& aElements,
       
   410 				    		            TUint32 aRequestId,
       
   411                                         TBool aTargetRefresh) const
       
   412     {
       
   413     CSIPConnection* connection = aDialog.Connection();
       
   414     __ASSERT_ALWAYS(connection, User::Leave(KErrSIPResourceNotAvailable));    
       
   415     
       
   416     connection->Implementation().ClientConnectionL().SendResponseWithinDialogL(
       
   417     													aElements,
       
   418                                                         aRequestId,
       
   419                                                         aDialog.DialogId(),
       
   420                                                         aTargetRefresh);    
       
   421     }
       
   422 
       
   423 // -----------------------------------------------------------------------------
       
   424 // CDialogState::IncomingResponseWithinDialogL
       
   425 // As response isn't refresh related, drop it if no matching transaction exists.
       
   426 // -----------------------------------------------------------------------------
       
   427 //
       
   428 TBool CDialogState::IncomingResponseWithinDialogL(
       
   429 									CSIPDialogImplementation& aDialog,
       
   430                                     CSIPResponseElements* aElements,
       
   431 		                            TUint32 aRequestId,
       
   432                                     TUint32 aDialogId,
       
   433                                     CConnectionCallback& aCallback,
       
   434                                     const CDialogState& aEarly,
       
   435                                     const CDialogState& aConfirmed,
       
   436                                     const CDialogState& aTerminated) const
       
   437     {
       
   438     __SIP_ASSERT_LEAVE(aElements, KErrArgument);
       
   439 
       
   440     CSIPTransactionBase* ta = NULL;
       
   441     CSIPDialogAssocBase* assoc = NULL;
       
   442     if (!aDialog.FindTransactionAndAssoc(aRequestId, &ta, &assoc))
       
   443         {
       
   444         delete aElements;
       
   445         return EFalse;
       
   446         }
       
   447 
       
   448     __SIP_ASSERT_LEAVE(ta->IsSIPClientTransaction(), KErrGeneral);
       
   449     CSIPClientTransaction* clientTa = static_cast<CSIPClientTransaction*>(ta);
       
   450     CSIPInviteDialogAssoc* newAssoc = CheckIfForkingL(aDialog,
       
   451                                                       aDialogId,
       
   452                                                       aElements,
       
   453                                                       *clientTa);
       
   454 	CSIPDialogImplementation* dialog = &aDialog;
       
   455     CConnectionCallback::TCallbackMethod callback =
       
   456     	CConnectionCallback::EIncomingResponse;
       
   457 	if (newAssoc)
       
   458 		{
       
   459 		assoc = newAssoc;
       
   460         dialog = &newAssoc->Dialog().Implementation();
       
   461         callback = CConnectionCallback::EIncomingResponseNewAssoc;
       
   462 		}
       
   463 	else
       
   464 		{
       
   465 		aDialog.UpdateRemoteTargetL(ta->Type(), aElements->MessageElements());
       
   466 		}
       
   467 
       
   468     //Ownership of aElements is taken when leave cannot occur
       
   469     clientTa->SetResponseElements(aElements);
       
   470 
       
   471     dialog->UpdateState(*clientTa, aEarly, aConfirmed, aTerminated);
       
   472     aCallback.Set(callback, clientTa, NULL, NULL, assoc);
       
   473 
       
   474     return ETrue;
       
   475     }
       
   476 
       
   477 // -----------------------------------------------------------------------------
       
   478 // CDialogState::CheckIfForkingL
       
   479 // A forked 1xx or 2xx creates a new dialog and INVITE dialog association. No
       
   480 // need to give contact to the new CSIPInviteDialogAssoc. Even the original
       
   481 // dialog does not have iContact anymore.
       
   482 // -----------------------------------------------------------------------------
       
   483 //
       
   484 CSIPInviteDialogAssoc*
       
   485 CDialogState::CheckIfForkingL(CSIPDialogImplementation& aDialog,
       
   486                               TUint32 aDialogId,
       
   487                               CSIPResponseElements* aElements,
       
   488                               CSIPClientTransaction& aTransaction) const
       
   489     {
       
   490     __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument);
       
   491 
       
   492     CSIPInviteDialogAssoc* assoc = NULL;
       
   493 
       
   494     if (aElements->StatusCode() < 300 &&
       
   495         aTransaction.Type() == SIPStrings::StringF(SipStrConsts::EInvite) &&
       
   496         aDialogId != 0 &&
       
   497         aDialogId != aDialog.DialogId())
       
   498         {
       
   499         assoc = CreateForkedInviteAssocLC(aDialog, *aElements);
       
   500 
       
   501         //Link transaction with the new assoc
       
   502         static_cast<CSIPInviteClientTransaction&>(aTransaction).
       
   503             AddAssociationL(assoc->Implementation());
       
   504 
       
   505         assoc->Dialog().Implementation().SetDialogId(aDialogId);
       
   506         CleanupStack::Pop(assoc);
       
   507 
       
   508         assoc->Dialog().Implementation().InitialTransactionStarted(
       
   509         	aTransaction.RequestId());
       
   510         }
       
   511     return assoc;
       
   512     }
       
   513 
       
   514 // -----------------------------------------------------------------------------
       
   515 // CDialogState::CreateForkedInviteAssocLC
       
   516 // -----------------------------------------------------------------------------
       
   517 //
       
   518 CSIPInviteDialogAssoc*
       
   519 CDialogState::CreateForkedInviteAssocLC(CSIPDialogImplementation& aDialog,
       
   520                                         CSIPResponseElements& aElements) const
       
   521     {
       
   522     __SIP_ASSERT_LEAVE(aElements.FromHeader() != NULL, KErrArgument);
       
   523     __SIP_ASSERT_LEAVE(aElements.ToHeader() != NULL, KErrArgument);
       
   524     __ASSERT_ALWAYS(aDialog.Connection(),
       
   525         			User::Leave(KErrSIPResourceNotAvailable));
       
   526 
       
   527     CSIPFromHeader* from = CSIPFromHeader::NewLC(*aElements.FromHeader());
       
   528     CSIPToHeader* to = CSIPToHeader::NewLC(*aElements.ToHeader());
       
   529 
       
   530 	CUri8* remoteUri = aDialog.GetUriFromContactL(aElements.MessageElements());
       
   531     if (remoteUri)
       
   532     	{
       
   533     	CleanupStack::PushL(remoteUri);
       
   534     	}
       
   535     else
       
   536     	{
       
   537     	remoteUri = CUri8::NewLC(aDialog.RemoteURI().Uri());
       
   538     	}
       
   539 
       
   540     CSIPInviteDialogAssoc* assoc = NULL;
       
   541     if (aDialog.RegistrationContext())
       
   542         {
       
   543         assoc = CSIPInviteDialogAssoc::NewL(*aDialog.Connection(),
       
   544         									remoteUri,
       
   545                                             *aDialog.RegistrationContext(),
       
   546                                             from,
       
   547                                             to);
       
   548         }
       
   549     else
       
   550         {
       
   551         assoc = CSIPInviteDialogAssoc::NewL(*aDialog.Connection(),
       
   552                                             from,
       
   553                                             remoteUri,
       
   554                                             to);
       
   555         }
       
   556     CleanupStack::Pop(3); //remoteUri, to, from
       
   557     CleanupStack::PushL(assoc);        
       
   558     assoc->Dialog().Implementation().CopyCallIdL(aDialog);
       
   559 
       
   560     return assoc;
       
   561     }
       
   562 
       
   563 // -----------------------------------------------------------------------------
       
   564 // CDialogState::ResponseToRefreshL
       
   565 // For 3xx-6xx to an existing refresh, the aRequestId is not recognized.
       
   566 // If ErrorOccured is sent to application, it can get the CSIPRefresh and from
       
   567 // it the client transaction and SIP response.
       
   568 // -----------------------------------------------------------------------------
       
   569 //
       
   570 TBool CDialogState::ResponseToRefreshL(CSIPDialogImplementation& aDialog,
       
   571                                        CSIPResponseElements* aElements,
       
   572                                        TUint32 aRequestId,
       
   573                                        TUint32 aRefreshId,
       
   574                                        CConnectionCallback& aCallback,
       
   575                                        const CDialogState& aEarly,
       
   576                                        const CDialogState& aConfirmed,
       
   577                                        const CDialogState& aTerminated) const
       
   578     {
       
   579     __SIP_ASSERT_LEAVE(aElements != NULL, KErrArgument);
       
   580 
       
   581     CSIPDialogAssocBase* assoc = NULL;
       
   582     CSIPRefresh* refresh = NULL;
       
   583     CSIPTransactionBase* ta = NULL;
       
   584     if (aDialog.FindAssocAndRefreshL(aRequestId,
       
   585                                      aRefreshId,
       
   586                                      &assoc,
       
   587                                      &refresh,
       
   588                                      &ta))
       
   589         {
       
   590         aDialog.UpdateRemoteTargetL(aElements->CSeqHeader()->Method(),
       
   591         							aElements->MessageElements());
       
   592 
       
   593         CSIPClientTransaction* clientTa =
       
   594             static_cast<CSIPClientTransaction*>(ta);
       
   595         CBase* objToDelete = NULL;
       
   596         if (ta)
       
   597             {
       
   598             __SIP_ASSERT_LEAVE(ta->IsSIPClientTransaction(), KErrGeneral);
       
   599             }
       
   600         else
       
   601             {
       
   602         	__SIP_ASSERT_LEAVE(aElements->CSeqHeader() != NULL, KErrArgument);
       
   603             clientTa = aDialog.CreateClientTransactionL(
       
   604 					                aElements->CSeqHeader()->Method(),				             
       
   605 					                assoc->Implementation(),
       
   606 					                refresh);
       
   607 			clientTa->SetRequestId(aRequestId);
       
   608 			objToDelete = clientTa;
       
   609             }
       
   610 
       
   611         clientTa->SetResponseElements(aElements);
       
   612         refresh->SetRefreshIdIfEmpty(aRefreshId);
       
   613         refresh->UpdateRefreshState(aElements->StatusCode());
       
   614         aDialog.UpdateState(*clientTa, aEarly, aConfirmed, aTerminated);
       
   615 
       
   616         if (!ta && aElements->StatusCode() >= 300)
       
   617             {
       
   618             aCallback.Set(CConnectionCallback::EErrorOccuredDialog,
       
   619                           NULL,
       
   620                           NULL,
       
   621                           NULL,
       
   622                           assoc,
       
   623                           KErrSIPTerminatedWithResponse,
       
   624                           objToDelete);
       
   625             }
       
   626         else
       
   627             {
       
   628             aCallback.Set(CConnectionCallback::EIncomingResponse,
       
   629                           clientTa,
       
   630                           NULL,
       
   631                           NULL,
       
   632                           assoc,
       
   633                           KErrNone,
       
   634                           objToDelete);
       
   635             }
       
   636         return ETrue;
       
   637         }
       
   638 
       
   639     delete aElements;
       
   640     return EFalse;
       
   641     }
       
   642 
       
   643 // -----------------------------------------------------------------------------
       
   644 // CDialogState::InvalidStateL
       
   645 // -----------------------------------------------------------------------------
       
   646 //
       
   647 CSIPClientTransaction* CDialogState::InvalidStateL() const
       
   648 	{
       
   649 	User::Leave(KErrSIPInvalidDialogState);
       
   650     return NULL;
       
   651 	}