sipvoipprovider/src/svpcontroller.cpp
changeset 0 a4daefaec16c
child 8 7117cbf1600a
equal deleted inserted replaced
-1:000000000000 0:a4daefaec16c
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Handles all common logic for SVP and handles sessions.        
       
    15 *
       
    16 */
       
    17 
       
    18 #include <mcevideostream.h>
       
    19 #include <mceaudiocodec.h>
       
    20 #include <mcemediasink.h>
       
    21 #include <mcemediasource.h>
       
    22 #include <mceevent.h>
       
    23 #include <mcesession.h>
       
    24 #include <mceinrefer.h>
       
    25 #include <mcesecuresession.h>
       
    26 #include <mcertpsource.h>
       
    27 #include <mccpdtmfobserver.h>
       
    28 #include <sipstrings.h>
       
    29 #include <sipstrconsts.h>
       
    30 
       
    31 #include <crcseprofileentry.h>
       
    32 #include <crcseprofileregistry.h>
       
    33 
       
    34 #include <wlantrafficstreamparameters.h> // CWlanMgmtClient
       
    35 #include <ccpdefs.h>
       
    36 
       
    37 #include "svpcontroller.h"
       
    38 #include "svpmosession.h"
       
    39 #include "svpmtsession.h"
       
    40 #include "svplogger.h"
       
    41 #include "svptimer.h"
       
    42 #include "svputility.h"
       
    43 #include "svpholdcontext.h"
       
    44 #include "svpholdcontroller.h"
       
    45 #include "svpcleanupresetanddestroy.h"
       
    46 #include "svpaudioutility.h"
       
    47 #include "svpsipconsts.h"
       
    48 #include "svpemergencyiapprovider.h"
       
    49 #include "svprtpobserver.h"
       
    50 #include "svpsettings.h"
       
    51 
       
    52 // ---------------------------------------------------------------------------
       
    53 // CSVPController::CSVPController
       
    54 // ---------------------------------------------------------------------------
       
    55 //
       
    56 CSVPController::CSVPController() : iSessionUpdateOngoing( EFalse )
       
    57     {
       
    58     
       
    59     }
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // CSVPController::ConstructL
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 void CSVPController::ConstructL()
       
    66     {
       
    67     SVPDEBUG1( "CSVPController::ConstructL In" )
       
    68     
       
    69     iIncomingReferCallIndex = KErrNotFound;
       
    70     iHoldCallIndex = KErrNotFound;
       
    71     iSuppServices = CSVPSupplementaryServices::NewL();
       
    72     iSVPUtility = CSVPUtility::NewL();
       
    73     iRtpObserver = CSVPRtpObserver::NewL();
       
    74 #ifndef __WINS__
       
    75     iWlanMgmt = CWlanMgmtClient::NewL();
       
    76 #endif // __WINS__
       
    77 
       
    78     SVPDEBUG1( "CSVPController::ConstructL Out" )
       
    79     }
       
    80 
       
    81 // ---------------------------------------------------------------------------
       
    82 // CSVPController::NewL
       
    83 // ---------------------------------------------------------------------------
       
    84 //
       
    85 CSVPController* CSVPController::NewL()
       
    86     {
       
    87     CSVPController* self = new ( ELeave ) CSVPController();
       
    88     CleanupStack::PushL( self );
       
    89     self->ConstructL();
       
    90     CleanupStack::Pop( self );
       
    91     return self;
       
    92     }
       
    93 
       
    94 // ---------------------------------------------------------------------------
       
    95 // CSVPController::~CSVPController
       
    96 // ---------------------------------------------------------------------------
       
    97 //
       
    98 CSVPController::~CSVPController()
       
    99     {
       
   100     SVPDEBUG1( "CSVPController::~CSVPController In" )
       
   101     
       
   102 #ifndef __WINS__
       
   103     delete iWlanMgmt;
       
   104 #endif // __WINS__
       
   105 
       
   106     delete iSVPUtility;
       
   107     
       
   108     // clean array that contains SVP sessions.
       
   109     iSessionArray.ResetAndDestroy();
       
   110     iSessionArray.Close();
       
   111     
       
   112     // SVP emergency session
       
   113     delete iEmergencySession;
       
   114  
       
   115     iEmergencyProfileIds.Close();
       
   116     iEmergencyIapIds.Close();
       
   117     
       
   118     delete iSuppServices;
       
   119     delete iMceManager;
       
   120     delete iRtpObserver;
       
   121     
       
   122     delete iDtmfString;
       
   123     
       
   124     SVPDEBUG1( "CSVPController::~CSVPController Out" )
       
   125     }
       
   126 
       
   127 // ---------------------------------------------------------------------------
       
   128 // CSVPController::InitializeL 
       
   129 // ---------------------------------------------------------------------------
       
   130 //
       
   131 void CSVPController::InitializeL( const TUint32 aServiceId,
       
   132 		  					      const MCCPObserver& aMonitor, 
       
   133 		                          const MCCPSsObserver& aSsObserver )
       
   134     {
       
   135     
       
   136     SVPDEBUG2( "CSVPController::InitializeL serviceId = %d", aServiceId )
       
   137     
       
   138     SVPDEBUG2( "CSVPController::InitializeL iCCPMonitor: 0x%x", iCCPMonitor )
       
   139     
       
   140     //Find callprovider plugin uid that should be used when registering to MCE
       
   141     TInt ccpUid = SvpSettings::IntPropertyL( aServiceId, 
       
   142 										EPropertyCallProviderPluginId );
       
   143     SVPDEBUG2( "CSVPController::InitializeL callproviderpluginuid=%d", ccpUid )
       
   144 
       
   145     // See CConvergedCallProvider API documentation. If already called,
       
   146     // leave with KErrAlreadyExists.
       
   147     __ASSERT_ALWAYS( !iCCPMonitor, User::Leave( KErrAlreadyExists ) );
       
   148     __ASSERT_ALWAYS( !iCCPSsObserver, User::Leave( KErrAlreadyExists ) );
       
   149     __ASSERT_ALWAYS( iSVPUtility, User::Leave( KErrNotReady ) );
       
   150     __ASSERT_ALWAYS( iRtpObserver, User::Leave( KErrNotReady ) );
       
   151     
       
   152     // save CCP monitor 
       
   153     iCCPMonitor = const_cast< MCCPObserver* >( &aMonitor );
       
   154      
       
   155     // save CCP Supplementary Services observer
       
   156     iCCPSsObserver = const_cast< MCCPSsObserver* >( &aSsObserver );
       
   157     
       
   158     // get terminal type and wlan mac address, needed for user agent header
       
   159     iSVPUtility->GetTerminalTypeL( iTerminalType );
       
   160     iSVPUtility->GetWlanMACAddressL( iWlanMacAddress );
       
   161     
       
   162     TUid uid = { ccpUid };
       
   163     // create Mce Manager, establishes connection to Mce server
       
   164     iMceManager = CMceManager::NewL( uid, &iContainer );
       
   165     
       
   166     // set observers for asynchronous events
       
   167     iMceManager->SetSessionObserver( this );
       
   168     iMceManager->SetInSessionObserver( this );
       
   169     iMceManager->SetInReferObserver( this );
       
   170     iMceManager->SetReferObserver( this );
       
   171     iMceManager->SetMediaObserver( this );
       
   172     iMceManager->SetEventObserver( this );
       
   173     iMceManager->SetDtmfObserver( this );
       
   174     iMceManager->SetRtpObserver( iRtpObserver );
       
   175     
       
   176     iTrafficStreamCreated = EFalse;
       
   177     
       
   178     SVPDEBUG1( "CSVPController::InitializeL Out" )
       
   179     } 
       
   180 
       
   181 // ---------------------------------------------------------------------------
       
   182 // CSVPController::InitializeL 
       
   183 // ---------------------------------------------------------------------------
       
   184 //
       
   185 void CSVPController::InitializeL( const MCCPObserver& aMonitor,
       
   186                                   const MCCPSsObserver& aSsObserver )
       
   187     {
       
   188     SVPDEBUG2( "CSVPController::InitializeL iCCPMonitor: 0x%x", iCCPMonitor )
       
   189     SVPDEBUG2( "CSVPController::InitializeL iCCPSsObserver: 0x%x", iCCPSsObserver )
       
   190     
       
   191     // See CConvergedCallProvider API documentation. If already called,
       
   192     // leave with KErrAlreadyExists.
       
   193     __ASSERT_ALWAYS( !iCCPMonitor, User::Leave( KErrAlreadyExists ) );
       
   194     __ASSERT_ALWAYS( !iCCPSsObserver, User::Leave( KErrAlreadyExists ) );
       
   195     __ASSERT_ALWAYS( iSVPUtility, User::Leave( KErrNotReady ) );
       
   196     __ASSERT_ALWAYS( iRtpObserver, User::Leave( KErrNotReady ) );
       
   197     
       
   198     // save CCP monitor 
       
   199     iCCPMonitor = const_cast< MCCPObserver* >( &aMonitor );
       
   200     
       
   201     // save CCP Supplementary Services observer
       
   202     iCCPSsObserver = const_cast< MCCPSsObserver* >( &aSsObserver );
       
   203 
       
   204     // get terminal type and wlan mac address, needed for user agent header
       
   205     iSVPUtility->GetTerminalTypeL( iTerminalType );
       
   206     iSVPUtility->GetWlanMACAddressL( iWlanMacAddress );
       
   207     
       
   208     // create Mce Manager, establishes connection to Mce server
       
   209     iMceManager = CMceManager::NewL( KSVPImplementationUid, &iContainer );
       
   210     
       
   211     // set observers for asynchronous events
       
   212     iMceManager->SetSessionObserver( this );
       
   213     iMceManager->SetInSessionObserver( this );
       
   214     iMceManager->SetInReferObserver( this );
       
   215     iMceManager->SetReferObserver( this );
       
   216     iMceManager->SetMediaObserver( this );
       
   217     iMceManager->SetEventObserver( this );
       
   218     iMceManager->SetDtmfObserver( this );
       
   219     iMceManager->SetRtpObserver( iRtpObserver );
       
   220     
       
   221     iTrafficStreamCreated = EFalse;
       
   222 
       
   223     SVPDEBUG1( "CSVPController::InitializeL Out" )
       
   224     }
       
   225     
       
   226 // ---------------------------------------------------------------------------
       
   227 // CSVPController::NewCallL
       
   228 // ---------------------------------------------------------------------------
       
   229 // 
       
   230 MCCPCall* CSVPController::NewCallL( 
       
   231                             const CCCPCallParameters& aParameters,
       
   232                             const TDesC& aRecipient,
       
   233                             const MCCPCallObserver& aObserver )
       
   234     {
       
   235     SVPDEBUG1( "CSVPController::NewCallL In" )
       
   236    
       
   237     __ASSERT_ALWAYS( &aParameters, User::Leave( KErrArgument ) );
       
   238     __ASSERT_ALWAYS( &aRecipient, User::Leave( KErrArgument ) );
       
   239     __ASSERT_ALWAYS( &aObserver, User::Leave( KErrArgument ) );
       
   240  
       
   241 #ifndef __WINS__
       
   242     // Preliminary Call Admission Control implementation, run only if no stream yet open
       
   243     if ( !iTrafficStreamCreated )
       
   244         {
       
   245         SVPDEBUG1( "CSVPController::NewCallL - Creating WLAN traffic stream.." )
       
   246 
       
   247         TRequestStatus requestStatus;
       
   248         TUint streamId = 0;
       
   249         TWlanTrafficStreamParameters streamParams( KSVPWlanTrafficStreamParamUserPriority );
       
   250         TWlanTrafficStreamStatus streamStatus = EWlanTrafficStreamStatusActive;
       
   251 
       
   252         // Disabling WLAN traffic stream automation and get stream status
       
   253         iWlanMgmt->CreateTrafficStream( requestStatus, streamParams, streamId, streamStatus );
       
   254         User::WaitForRequest( requestStatus );
       
   255         
       
   256         // Save traffic stream ID, needed for stream deletion
       
   257         iTrafficStreamId = streamId;
       
   258 
       
   259         if ( EWlanTrafficStreamStatusInactiveNoBandwidth == streamStatus )
       
   260             {
       
   261             SVPDEBUG1( "CSVPController::NewCallL - No bandwidth in traffic stream, leaving with ECCPErrorNetworkBusy" )        
       
   262 
       
   263             // Enabling WLAN traffic stream automation back by deleting used stream
       
   264             iWlanMgmt->DeleteTrafficStream( requestStatus, iTrafficStreamId );
       
   265             User::WaitForRequest( requestStatus );
       
   266             
       
   267             TCCPError err = ECCPErrorNetworkBusy;
       
   268             User::Leave( err );
       
   269             }
       
   270         SVPDEBUG1( "CSVPController::NewCallL - WLAN traffic stream created, continuing with NewCallL" )
       
   271 
       
   272         iTrafficStreamCreated = ETrue;
       
   273         }
       
   274     else
       
   275         {
       
   276         SVPDEBUG1( "CSVPController::NewCallL - WLAN traffic stream already created, continuing with NewCallL" )
       
   277         ;
       
   278         }
       
   279 #endif // __WINS__
       
   280     
       
   281     SVPDEBUG2( "CSVPController::NewCallL aRecipient length = %d", aRecipient.Length() )
       
   282     SVPDEBUG2( "CSVPController::NewCallL aRecipient = %S", &aRecipient )
       
   283     SVPDEBUG2( "CSVPController::NewCallL Serviceid = %d", aParameters.ServiceId() )
       
   284 
       
   285     // Prepare and remove possible DTMF suffix
       
   286     HBufC* parsedRecipient = NULL;
       
   287     parsedRecipient = ParseRecipientDtmfSuffixL( aRecipient );
       
   288   
       
   289     // "convert" recpient to 8-bit format
       
   290     HBufC8* recipient = HBufC8::NewLC( parsedRecipient->Length() ); // CS:1
       
   291     TPtr8 temp = recipient->Des();
       
   292     temp.Copy( *parsedRecipient );
       
   293 
       
   294     // Pointer to parsedRecipient no longer needed
       
   295     delete parsedRecipient;
       
   296     parsedRecipient = NULL;
       
   297     
       
   298     // fetch SIP profile ID from VoIP profiles
       
   299     RPointerArray< CRCSEProfileEntry > entryArray;
       
   300     CleanupResetAndDestroy<
       
   301         RPointerArray<CRCSEProfileEntry> >::PushL( entryArray ); //CS:2
       
   302     
       
   303     CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC(); // CS:3
       
   304     
       
   305     // take service id to local variable
       
   306     TUint32 serviceId = aParameters.ServiceId();
       
   307     
       
   308     // Get VoIP profile by service id
       
   309     reg->FindByServiceIdL( serviceId, entryArray );
       
   310     __ASSERT_ALWAYS( entryArray.Count(), User::Leave( KErrArgument ) );
       
   311     
       
   312     // Take first entry from array
       
   313     CRCSEProfileEntry* entry = entryArray[0];
       
   314     
       
   315     // create new session
       
   316     MCCPCall* moSessionTemp = CreateNewSessionL( *recipient, 
       
   317                                                  *entry, 
       
   318                                                  aParameters,
       
   319                                                  aObserver );
       
   320     
       
   321     CleanupStack::PopAndDestroy( 2, &entryArray ); // CS:1
       
   322     CleanupStack::PopAndDestroy( recipient ); // CS:0
       
   323     
       
   324     SVPDEBUG1( "CSVPController::NewCallL Out" )
       
   325     return moSessionTemp;
       
   326     }
       
   327 
       
   328 // ---------------------------------------------------------------------------
       
   329 // CSVPController::CreateNewSessionL
       
   330 // ---------------------------------------------------------------------------
       
   331 //
       
   332 MCCPCall* CSVPController::CreateNewSessionL( 
       
   333     TDesC8& aRecipient, 
       
   334     CRCSEProfileEntry& aVoipProfile, 
       
   335     const CCCPCallParameters& aParameters,
       
   336     const MCCPCallObserver& aObserver )
       
   337     {
       
   338     SVPDEBUG1( "CSVPController::CreateNewSessionL In" )
       
   339     
       
   340     // array for provisioned data
       
   341     CDesC8ArrayFlat* userAgentHeaders = new( ELeave ) CDesC8ArrayFlat( 4 );
       
   342     CleanupStack::PushL( userAgentHeaders ); // CS:1
       
   343     
       
   344     // variable for storing security status
       
   345     TUint32 securityStatus( 0 );
       
   346     
       
   347     // set provisioning data
       
   348     SVPDEBUG1( "CSVPController::CreateNewSessionL Set provisioning data..." )
       
   349     iSVPUtility->SetProvisioningDataL( aVoipProfile, 
       
   350                                        *userAgentHeaders,
       
   351                                        securityStatus,
       
   352                                        iTerminalType,
       
   353                                        iWlanMacAddress  );
       
   354     
       
   355     SVPDEBUG2( "CSVPController::CreateNewSessionL Security status: %d", securityStatus )
       
   356     SVPDEBUG2( "CSVPController::CreateNewSessionL UAHeaders count: %d", userAgentHeaders->Count() )
       
   357     
       
   358     // Creates a SVP Mo session 
       
   359     CSVPMoSession* moSessionTemp = CSVPMoSession::NewL( *iMceManager,
       
   360                                                         aRecipient,
       
   361                                                         aVoipProfile, 
       
   362                                                         aParameters,
       
   363                                                         iContainer,
       
   364                                                         *this,
       
   365                                                         *iSVPUtility,
       
   366                                                         *iRtpObserver,
       
   367                                                         securityStatus,
       
   368                                                         userAgentHeaders );
       
   369     CleanupStack::Pop( userAgentHeaders ); // CS:0, to member data
       
   370     CleanupStack::PushL( moSessionTemp ); // CS:1
       
   371     
       
   372     FinalizeSessionCreationL( moSessionTemp );
       
   373     
       
   374     // set CCP session observer to SVP session
       
   375     moSessionTemp->AddObserverL( aObserver );
       
   376     // set CCP supplementary services events observer to SVP session
       
   377     moSessionTemp->SetSsObserver( *iCCPSsObserver );
       
   378     
       
   379     CleanupStack::Pop( moSessionTemp ); // CS:0
       
   380     
       
   381     // session pointer is passed to CCP
       
   382     SVPDEBUG1( "CSVPController::CreateNewSessionL Out" )
       
   383     return moSessionTemp;
       
   384     }
       
   385 
       
   386 // ---------------------------------------------------------------------------
       
   387 // Releases call
       
   388 // ---------------------------------------------------------------------------
       
   389 // 
       
   390 TInt CSVPController::ReleaseCall( MCCPCall& aCall )
       
   391     {
       
   392     SVPDEBUG1( "CSVPController::ReleaseCall In" )
       
   393 
       
   394     TInt response = KErrNotFound;
       
   395 
       
   396     // To ensure correct value
       
   397     iIncomingReferCallIndex = KErrNotFound;
       
   398     iSessionUpdateOngoing = EFalse;
       
   399 
       
   400     for ( TInt i = 0; i < iSessionArray.Count(); i++ )
       
   401         {
       
   402         if ( iSessionArray[i] == &aCall )
       
   403             {
       
   404             if ( iDtmfStringSending )
       
   405                 {
       
   406                 SVPDEBUG1( "CSVPController::ReleaseCall - Abort DTMF Sending" )
       
   407                 
       
   408                 // send abort event
       
   409                 iSessionArray[i]->DtmfObserver().HandleDTMFEvent(
       
   410                        MCCPDTMFObserver::ECCPDtmfSequenceAbort,
       
   411                        KErrNone,
       
   412                        iDtmfStringLex.Peek() );
       
   413                 
       
   414                 SVPDEBUG1( "CSVPController::ReleaseCall - Complete DTMF" )
       
   415                 
       
   416                 // send sequence completed event
       
   417                 iSessionArray[i]->DtmfObserver().HandleDTMFEvent(
       
   418                     MCCPDTMFObserver::ECCPDtmfStringSendingCompleted,
       
   419                     KErrNone,
       
   420                     iDtmfStringLex.Peek() );
       
   421                 
       
   422                 // sequence complete, clear flags
       
   423                 iDtmfStringSending = EFalse;
       
   424                 iFirstDtmfSent = EFalse;
       
   425                 
       
   426                 delete iDtmfString;
       
   427                 iDtmfString = NULL;
       
   428                 }
       
   429             iSessionArray[i]->Release();
       
   430             response = KErrNone;
       
   431             }
       
   432         }
       
   433 
       
   434 #ifndef __WINS__
       
   435     // Preliminary Call Admission Control implementation, delete only if created in NewCallL 
       
   436     if ( iTrafficStreamCreated )
       
   437         {
       
   438         SVPDEBUG1( "CSVPController::ReleaseCall - Deleting WLAN traffic stream" )
       
   439 
       
   440         TRequestStatus requestStatus;
       
   441 
       
   442         // Enabling WLAN traffic stream automation back by deleting used stream
       
   443         iWlanMgmt->DeleteTrafficStream( requestStatus, iTrafficStreamId );
       
   444         User::WaitForRequest( requestStatus );
       
   445         
       
   446         iTrafficStreamCreated = EFalse;
       
   447 
       
   448         SVPDEBUG1( "CSVPController::ReleaseCall - WLAN traffic stream deleted" )
       
   449         }
       
   450     else
       
   451         {
       
   452         SVPDEBUG1( "CSVPController::ReleaseCall - No WLAN traffic stream to delete" )
       
   453         ;
       
   454         }
       
   455 #endif // __WINS__
       
   456 
       
   457     SVPDEBUG1( "CSVPController::ReleaseCall Out" )
       
   458     return response;
       
   459     }
       
   460 
       
   461 // ---------------------------------------------------------------------------
       
   462 // Releases emergency call
       
   463 // ---------------------------------------------------------------------------
       
   464 // 
       
   465 TInt CSVPController::ReleaseEmergencyCall( MCCPEmergencyCall& /*aCall*/ )
       
   466     {
       
   467     SVPDEBUG1( "CSVPController::ReleaseEmergencyCall In" )
       
   468 
       
   469     // To ensure correct value next time
       
   470     iIncomingReferCallIndex = KErrNotFound;
       
   471     iSessionUpdateOngoing = EFalse;
       
   472 
       
   473     delete iEmergencySession;
       
   474     iEmergencySession = NULL;
       
   475     
       
   476     SVPDEBUG1( "CSVPController::ReleaseEmergencyCall Out" )
       
   477     return KErrNone;
       
   478     }
       
   479 
       
   480 // ---------------------------------------------------------------------------
       
   481 // Releases conference call
       
   482 // ---------------------------------------------------------------------------
       
   483 // 
       
   484 TInt CSVPController::ReleaseConferenceCall( MCCPConferenceCall& /*aCall*/ )
       
   485     {
       
   486     SVPDEBUG1( "CSVPController::ReleaseConferenceCall In" )
       
   487     SVPDEBUG1( "CSVPController::ReleaseConferenceCall Out" )
       
   488     return KErrNotSupported;
       
   489     }
       
   490 
       
   491 // ---------------------------------------------------------------------------
       
   492 // CSVPController::RemoveFromArray
       
   493 // ---------------------------------------------------------------------------
       
   494 // 
       
   495 void CSVPController::RemoveFromArray( CSVPSessionBase& aSession )
       
   496     {
       
   497     SVPDEBUG1( "CSVPController::RemoveFromArray In" )
       
   498     
       
   499     // When Sessions destructor is called object be removed from array
       
   500     // manually after when data has been deleted.
       
   501     SVPDEBUG2( "CSVPController::RemoveFromArray aSession: 0x%x", &aSession )
       
   502     
       
   503     TInt index = FindSVPSession( aSession.Session() );  
       
   504     if ( KErrNotFound != index )
       
   505         {
       
   506         SVPDEBUG1( "CSVPController::RemoveFromArray Session found - removing" )
       
   507         iSessionArray.Remove( index );
       
   508         iSessionArray.Compress();
       
   509         }
       
   510     
       
   511     // Try also to remove it from RTCP observer. Ingore the return code, yet
       
   512     // again this is "just in case" thing.
       
   513     iRtpObserver->RemoveSessionFromObserving( &aSession );
       
   514     SVPDEBUG1( "CSVPController::RemoveFromArray Out" )
       
   515     }
       
   516 
       
   517 // ---------------------------------------------------------------------------
       
   518 // CSVPController::FindSVPSession
       
   519 // ---------------------------------------------------------------------------
       
   520 //
       
   521 TInt CSVPController::FindSVPSession( const CMceSession& aSession ) const
       
   522     {
       
   523     SVPDEBUG1( "CSVPController::FindSVPSession In" )
       
   524     
       
   525     TInt count = iSessionArray.Count();
       
   526     SVPDEBUG2( "CSVPController::FindSVPSession count = %d", count )
       
   527     
       
   528     while ( count )
       
   529         {
       
   530         count--;
       
   531         
       
   532         if (  &iSessionArray[count]->Session() == &aSession )
       
   533             {
       
   534             SVPDEBUG2( "CSVPController::FindSVPSession Out return: %d", count )
       
   535             return count;
       
   536             }
       
   537         }
       
   538     
       
   539     SVPDEBUG1( "CSVPController::FindSVPSession Out return: KErrNotFound" )
       
   540     return KErrNotFound;
       
   541     }
       
   542 
       
   543 // ---------------------------------------------------------------------------
       
   544 // CSVPController::Uid
       
   545 // ---------------------------------------------------------------------------
       
   546 //
       
   547 const TUid& CSVPController::Uid() const
       
   548     {
       
   549     SVPDEBUG1( "CSVPController::Uid" )
       
   550     return KSVPImplementationUid; 
       
   551     }
       
   552 
       
   553 // ---------------------------------------------------------------------------
       
   554 // CSVPController::CreateNonSecureSessionL
       
   555 // ---------------------------------------------------------------------------
       
   556 // 
       
   557 void CSVPController::CreateNonSecureSessionL( TInt aSessionIndex )
       
   558     {
       
   559     SVPDEBUG1( "CSVPController::CreateNonSecureSessionL In" )
       
   560     
       
   561     // secure session failed -> create non secure Mo session
       
   562     static_cast< CSVPMoSession* >( iSessionArray[ aSessionIndex ] )->
       
   563             CreateNonSecureSessionL( *iMceManager );
       
   564     
       
   565     SVPDEBUG1( "CSVPController::CreateNonSecureSessionL Out" )
       
   566     }
       
   567 
       
   568 // ---------------------------------------------------------------------------
       
   569 // CSVPController::CheckIfSecureFailed
       
   570 // ---------------------------------------------------------------------------
       
   571 //    
       
   572 TBool CSVPController::CheckIfSecureFailed( TInt aStatusCode ) const
       
   573     {
       
   574     SVPDEBUG2( "CSVPController::CheckIfSecureFailed In, aStatusCode: %d", aStatusCode )
       
   575     
       
   576     // if secure fails with the following response codes
       
   577     // normal session is tried next
       
   578     if ( KSVPNotAcceptableHereVal == aStatusCode ||
       
   579          KSVPNotAcceptableVal == aStatusCode ||
       
   580          KSVPPreconditionFailureVal == aStatusCode ||
       
   581          KSVPMethodNotAllowedVal == aStatusCode )
       
   582         {
       
   583         SVPDEBUG1( "CSVPController::CheckIfSecureFailed Out ETrue" )
       
   584         return ETrue;
       
   585         }
       
   586     else
       
   587         {
       
   588         SVPDEBUG1( "CSVPController::CheckIfSecureFailed Out EFalse" )
       
   589         return EFalse;
       
   590         }
       
   591     }
       
   592 
       
   593 // ---------------------------------------------------------------------------
       
   594 // CSVPController::SessionStateChanged
       
   595 // ---------------------------------------------------------------------------
       
   596 // 
       
   597 void CSVPController::SessionStateChanged( CMceSession& aSession,
       
   598     TMceTransactionDataContainer* aContainer )
       
   599     {
       
   600     SVPDEBUG1( "CSVPController::SessionStateChanged In" )
       
   601     
       
   602     // Note, getting the status code may reset it in the container. So do it
       
   603     // only once and be sure that it stays as it should be.
       
   604     const TInt statusCode = aContainer->GetStatusCode();
       
   605     SVPDEBUG2( "CSVPController::SessionStateChanged statusCode: %d", statusCode )
       
   606     
       
   607     // check if this is emergency session
       
   608     if ( iEmergencySession )
       
   609         {
       
   610         SVPDEBUG1( "CSVPController::SessionStateChanged, emergency session" )
       
   611         
       
   612         if ( CMceSession::EEstablished == aSession.State() )
       
   613             {
       
   614             // Rest of the profiles not needed since session is established
       
   615             iEmergencyProfileIds.Reset();
       
   616             iEmergencyIapIds.Reset();
       
   617             }
       
   618         
       
   619         if ( CMceSession::EEstablished == aSession.State() &&
       
   620              iEmergencySession->HasHoldController() &&
       
   621              ( ( iEmergencySession->HoldController() ).HoldInProgress() ||
       
   622                ( iEmergencySession->HoldController() ).HoldRolledBack() ) )
       
   623             {
       
   624             // Handle hold
       
   625             TRAPD( error, iEmergencySession->HoldSessionStateChangedL( aSession ) )
       
   626             
       
   627             if ( error )
       
   628                 {
       
   629                 SVPDEBUG2( "CSVPController::SessionStateChanged, emergency session error %d", error )
       
   630                 }
       
   631             }
       
   632         else
       
   633             {
       
   634             iEmergencySession->SessionStateChanged( statusCode );
       
   635             }
       
   636         }
       
   637     else if ( iSessionUpdateOngoing )
       
   638         {
       
   639         // Non-hold session update, e.g. codec renegotiation ongoing; no actions
       
   640         // needed until MCE session state is established.
       
   641         SVPDEBUG1( "CSVPController::SessionStateChanged - MT Session Update" )
       
   642         
       
   643         if ( CMceSession::EEstablished == aSession.State() )
       
   644             {
       
   645             // Session update done (Ack received)
       
   646             iSessionUpdateOngoing = EFalse;
       
   647             SVPDEBUG1( "CSVPController::SessionStateChanged - MT Session Updated" )
       
   648             }
       
   649         }
       
   650     else
       
   651         {
       
   652         // fetch correct session
       
   653         const TInt ind = FindSVPSession( aSession );
       
   654         
       
   655         // KErrNone = status, status had to be error code
       
   656         if ( KErrNotFound != ind &&
       
   657              iSessionArray[ ind ]->SecurePreferred() &&
       
   658              CheckIfSecureFailed( statusCode ) ||
       
   659              CMceSession::ECancelling == aSession.State() )
       
   660             {
       
   661             SVPDEBUG1( "CSVPController::SessionStateChanged - Secure failed, trying normal session" )
       
   662             
       
   663             // trying normal session after secure session trial failed
       
   664             TRAPD( err, CreateNonSecureSessionL( ind ) );
       
   665             
       
   666             if ( err )
       
   667                 {
       
   668                 iSessionArray[ ind ]->GetCCPSessionObserver().
       
   669                     ErrorOccurred( ECCPRedirection, iSessionArray[ ind ] );
       
   670                 iSessionArray[ ind ]->GetCCPSessionObserver().
       
   671                     CallStateChanged( MCCPCallObserver::ECCPStateIdle,
       
   672                                       iSessionArray[ ind ]);
       
   673                 }
       
   674             }
       
   675         else if ( KErrNotFound != ind )
       
   676             {
       
   677             SVPDEBUG1( "CSVPController::SessionStateChanged - Session found" )
       
   678             
       
   679             CSVPSessionBase* session = iSessionArray[ ind ];
       
   680             
       
   681             if ( !session->CallId() &&
       
   682                  KSVPMultipleChoicesVal != statusCode &&
       
   683                  KSVPMovedPermanentlyVal != statusCode &&
       
   684                  KSVPMovedTemporarilyVal != statusCode )
       
   685                 {
       
   686                 // CallId not stored yet and not a 3XX case,
       
   687                 // check and store headers data.
       
   688                 CheckHeadersData( session, aContainer );
       
   689                 }
       
   690             
       
   691             if ( !session->SecurePreferred() )
       
   692                 {
       
   693                 session->ReleaseTempSecure();
       
   694                 }
       
   695             
       
   696             // Release attended transfer target session index 
       
   697             // if e.g. early stage session terminate
       
   698             if ( CMceSession::ETerminated == aSession.State() )
       
   699                 {
       
   700                 iHoldCallIndex = KErrNotFound;
       
   701                 }
       
   702             
       
   703             if ( CMceSession::EProceeding == aSession.State() )
       
   704                 {
       
   705                 SVPDEBUG1( "CSVPController::SessionStateChanged EProceeding" )
       
   706                 
       
   707                 if ( KErrNotFound != iHoldCallIndex && iSessionArray.Count() > 1 )
       
   708                     {
       
   709                     SVPDEBUG3( "CSVPController::SessionStateChanged, atte trans target, ind %d, iHCInd %d",
       
   710                                                 ind, iHoldCallIndex )
       
   711                     CheckCallEventToBeSent( session, iSessionArray[iHoldCallIndex] );
       
   712                     ExecCbIncomingCall( session, *iSessionArray[iHoldCallIndex] );
       
   713                     iHoldCallIndex = KErrNotFound;
       
   714                     }
       
   715                 else if ( session->HasHoldController() &&
       
   716                           ( session->HoldController() ).HoldInProgress() )
       
   717                     {
       
   718                     // Do nothing here; this only prevents wrong new call
       
   719                     // callback to CCP.
       
   720                     SVPDEBUG1( "CSVPController::SessionStateChanged - HoldInProgress" )
       
   721                     }
       
   722                 else if ( session->IsEmptyReInvite() )
       
   723                     {
       
   724                     SVPDEBUG1( "CSVPController::SessionStateChanged - Empty re-Invite handling ongoing" )
       
   725                     }
       
   726                 else if ( !session->IsIdle() )
       
   727                     {
       
   728                     SVPDEBUG1( "CSVPController::SessionStateChanged - NOP" )
       
   729                     }
       
   730                 else
       
   731                     {
       
   732                     SVPDEBUG1( "CSVPController::SessionStateChanged Incoming" )
       
   733                     ExecCbIncomingCall( session );
       
   734                     session->SessionStateChanged( statusCode );
       
   735                     }
       
   736                 }
       
   737             else if ( CMceSession::EEstablished == aSession.State() &&
       
   738                       session->HasHoldController() &&
       
   739                     ( ( session->HoldController() ).HoldInProgress() ||
       
   740                       ( session->HoldController() ).HoldRolledBack() ) )
       
   741                 {
       
   742                 SVPDEBUG1( "CSVPController::SessionStateChanged EEstablished & HoldController" )
       
   743                 
       
   744                 session->HandleSessionStateChanged( aSession );
       
   745                 }
       
   746             else if ( ( CMceSession::EEstablished == aSession.State() || 
       
   747                         CMceSession::ETerminated == aSession.State() ) &&
       
   748                         KErrNone != statusCode &&
       
   749                         KErrNotFound != iIncomingReferCallIndex &&
       
   750                         iIncomingReferCallIndex < iSessionArray.Count() &&
       
   751                         iSessionArray[ iIncomingReferCallIndex ]->IsIncomingTransfer() )
       
   752                 {
       
   753                 SVPDEBUG1( "CSVPController::SessionStateChanged transferor" )
       
   754                 
       
   755                 // Transferor sends notify to original when new session connected/failed.
       
   756                 // If secure is mandatory but path unsecure, attended transfer req must be rejected
       
   757                 if ( session->SecureMandatory() &&
       
   758                      CMceSession::EControlPathUnsecure == aSession.ControlPathSecurityLevel() &&
       
   759                      iSessionArray[ iIncomingReferCallIndex ]->IsAttended() )
       
   760                     {
       
   761                     iSessionArray[ iIncomingReferCallIndex ]->SendNotify( KSVPDeclineVal );
       
   762                     }
       
   763                 else
       
   764                     {
       
   765                     iSessionArray[ iIncomingReferCallIndex ]->SendNotify( statusCode );
       
   766                     }
       
   767 
       
   768                 if ( iSessionArray[ iIncomingReferCallIndex ]->IsAttended() )
       
   769                     {
       
   770                     // remotepartyinfo and/or secure status might have been changed,
       
   771                     // proper event will be sent later on.
       
   772                     CheckCallEventToBeSent( session, iSessionArray[iIncomingReferCallIndex] );
       
   773                     }
       
   774                 iIncomingReferCallIndex = KErrNotFound;
       
   775                 session->SessionStateChanged( statusCode );
       
   776                 }
       
   777             // 3xx Call forward handling
       
   778             else if ( KSVPMultipleChoicesVal == statusCode  ||
       
   779                       KSVPMovedPermanentlyVal == statusCode ||
       
   780                       KSVPMovedTemporarilyVal == statusCode )
       
   781                 {
       
   782                 HandleCallForward( statusCode, ind, aContainer );
       
   783                 }
       
   784             else
       
   785                 {
       
   786                 if ( ( aSession.State() == CMceSession::EOffering || 
       
   787                        aSession.State() == CMceSession::ETerminating ||
       
   788                        aSession.State() == CMceSession::ETerminated ) &&
       
   789                        iSessionArray[ ind ]->HasHoldController() &&
       
   790                        ( ( iSessionArray[ ind ]->HoldController() ).HoldInProgress() ||
       
   791                        ( iSessionArray[ ind ]->HoldController() ).HoldRolledBack() ) )
       
   792                     {
       
   793                     // Failed hold e.g. 408 response
       
   794                     SVPDEBUG1("CSVPController::SessionStateChanged()\
       
   795                     State change: Failed && HoldController");            
       
   796                     if ( 491 == statusCode )
       
   797                         {
       
   798                         SVPDEBUG1( 
       
   799                         "CSVPController::SessionStateChanged - UpdateFailed()" )
       
   800                         UpdateFailed( aSession, aContainer );
       
   801                         }
       
   802                     else if ( 100 <= statusCode && 200 > statusCode ) // Provisional response
       
   803                         {
       
   804                         // NOP
       
   805                         SVPDEBUG1( 
       
   806                         "CSVPController::SessionStateChanged - Provisional - NOP" )
       
   807                         }
       
   808                     else
       
   809                         {
       
   810                         iSessionArray[ ind ]->HandleSessionStateChanged( aSession );
       
   811                         session->SessionStateChanged( statusCode );                
       
   812                         }
       
   813                     }                
       
   814                 
       
   815                 else if ( session->HasHoldController() )
       
   816                     {
       
   817                     // MCE Session Refresh; no actions by the SVP
       
   818                     SVPDEBUG1( 
       
   819                     "CSVPController::SessionStateChanged - Session refresh" )
       
   820                     if ( CMceSession::ETerminating == aSession.State() ||
       
   821                          CMceSession::ETerminated == aSession.State() )
       
   822                         {
       
   823                         session->SessionStateChanged( statusCode );
       
   824                         }
       
   825                     }
       
   826                 else if ( !iFailed )
       
   827                     {
       
   828                     SVPDEBUG1( 
       
   829                     "CSVPController::SessionStateChanged - Not handled -> Notify session" )
       
   830                     session->SessionStateChanged( statusCode );
       
   831                     }                
       
   832                 else
       
   833                     {
       
   834                     // Failed() callback occurred before EEstablished state
       
   835                     // -> No action needed, session termination timer is set
       
   836                     }
       
   837                 }
       
   838             }
       
   839         else
       
   840             {
       
   841             SVPDEBUG1( "CSVPController::SessionStateChanged else" )
       
   842             }
       
   843         }
       
   844     
       
   845     SVPDEBUG1( "CSVPController::SessionStateChanged Out" )
       
   846     }
       
   847     
       
   848 // ---------------------------------------------------------------------------
       
   849 // CSVPController::SessionConnectionStateChanged
       
   850 // ---------------------------------------------------------------------------
       
   851 //  
       
   852 void CSVPController::SessionConnectionStateChanged(
       
   853                 CMceSession& aSession,
       
   854                 TBool aActive )
       
   855     {
       
   856     SVPDEBUG2("CSVPController::SessionConnectionStateChanged Active ETrue, Inactive EFalse: %d", aActive )
       
   857     
       
   858     if ( iEmergencySession )
       
   859         {
       
   860         iEmergencySession->SessionConnectionStateChanged( aSession, aActive );
       
   861         }
       
   862     }
       
   863     
       
   864 // ---------------------------------------------------------------------------
       
   865 // CSVPController::Failed
       
   866 // ---------------------------------------------------------------------------
       
   867 //
       
   868 #ifdef _DEBUG
       
   869 void CSVPController::Failed( CMceSession& aSession, TInt aError )
       
   870 #else
       
   871 void CSVPController::Failed( CMceSession& aSession, TInt /*aError*/ )
       
   872 #endif // _DEBUG
       
   873     {
       
   874     SVPDEBUG1("CSVPController::Failed In" )
       
   875     SVPDEBUG2("CSVPController::Failed With error code: %d", aError )
       
   876     
       
   877     TInt ind = FindSVPSession( aSession );
       
   878     
       
   879     if ( KErrNotFound != ind )
       
   880         {
       
   881         SVPDEBUG1("CSVPController::Failed() Session found")
       
   882         
       
   883         if ( &iSessionArray[ ind ]->GetCCPSessionObserver() )
       
   884             {
       
   885         	iSessionArray[ ind ]->GetCCPSessionObserver().
       
   886             	ErrorOccurred( ECCPErrorConnectionError, 
       
   887             	               iSessionArray[ ind ] );
       
   888         
       
   889         	// Actually MCE session state should always 
       
   890         	// be ETerminated when this method is 
       
   891         	// called; but check anyway:        
       
   892         	if ( CMceSession::ETerminated == aSession.State() )
       
   893         	    {
       
   894                 iFailed = ETrue;
       
   895         	    // start termination timer, needed for UI
       
   896         	    // to handle Disconnected-bubble   
       
   897         	    TRAP_IGNORE( iSessionArray[ ind ]->StartTimerL( 
       
   898         	            KSVPTerminatingTime, KSVPTerminationTimerExpired ) );
       
   899             
       
   900         	    iSessionArray[ ind ]->GetCCPSessionObserver().
       
   901         		    CallStateChanged( MCCPCallObserver::ECCPStateDisconnecting, 
       
   902         		                      iSessionArray[ ind ] );
       
   903             
       
   904         	    SVPDEBUG1("CSVPController::Failed() Session terminating");            
       
   905         	    }
       
   906             }
       
   907         else
       
   908             {
       
   909             iCCPMonitor->ErrorOccurred( MCCPObserver::ECCPIncomingCallFailed ); 
       
   910             }
       
   911         }
       
   912     else
       
   913         {
       
   914         SVPDEBUG1("CSVPController::Failed() Session not Found!!");
       
   915         }
       
   916     
       
   917     SVPDEBUG1("CSVPController::Failed Out" )
       
   918     }
       
   919 
       
   920 // ---------------------------------------------------------------------------
       
   921 // CSVPController::UpdateFailed
       
   922 // ---------------------------------------------------------------------------
       
   923 //
       
   924 void CSVPController::UpdateFailed(
       
   925     			CMceSession& aSession,
       
   926     			TMceTransactionDataContainer* aContainer )
       
   927     {
       
   928     SVPDEBUG1( "CSVPController::UpdateFailed In" )
       
   929     
       
   930     TInt ind = FindSVPSession( aSession );
       
   931     TInt statusCode = aContainer->GetStatusCode();
       
   932     
       
   933     SVPDEBUG2( "CSVPController::UpdateFailed statusCode: %d", statusCode )
       
   934     
       
   935     if ( KErrNotFound != ind )
       
   936         {
       
   937         iSessionArray[ ind ]->UpdateFailed( aSession, statusCode );
       
   938         }
       
   939     iSessionUpdateOngoing = EFalse;
       
   940     SVPDEBUG1( "CSVPController::UpdateFailed Out" )
       
   941     }
       
   942     
       
   943 // ---------------------------------------------------------------------------
       
   944 // CSVPController::EventStateChanged
       
   945 // ---------------------------------------------------------------------------
       
   946 //			
       
   947 void CSVPController::EventStateChanged(
       
   948     			CMceEvent& aEvent,
       
   949 				TMceTransactionDataContainer* aContainer )
       
   950     {
       
   951     SVPDEBUG1( "CSVPController:EventStateChanged In" )
       
   952     
       
   953     iContainer = *aContainer;
       
   954     TInt ind = FindSVPSession( *aEvent.AssociatedSession() );
       
   955     TInt statusCode = iContainer.GetStatusCode();
       
   956     
       
   957     SVPDEBUG2( "CSVPController:EventStateChanged statusCode: %d", statusCode )
       
   958 
       
   959     if ( KErrNotFound != ind )
       
   960         {
       
   961         SVPDEBUG2( "CSVPController::EventStateChanged ind = %d", ind )
       
   962         TInt err = iSessionArray[ ind ]->EventStateChanged( aEvent, statusCode );
       
   963         
       
   964         if ( KSVPOKVal == statusCode &&
       
   965              iSessionArray[ ind ]->IsAttended() &&
       
   966              KErrNone == err )
       
   967             {
       
   968             SVPDEBUG1( "CSVPController::EventStateChanged Atte transfer cont." )
       
   969             
       
   970             TRAP( err, CreateNewTransferSessionL( ind, ETrue ) );
       
   971             
       
   972             if ( err )
       
   973                 {
       
   974                 SVPDEBUG2( "CSVPController::EventStateChanged: err: %d", err )
       
   975                 }
       
   976             }
       
   977         }
       
   978     else
       
   979         {
       
   980         SVPDEBUG1( "CSVPController::EventStateChanged Session not Found!!" )
       
   981         }
       
   982 
       
   983     SVPDEBUG1("CSVPController:EventStateChanged OUT");
       
   984     }
       
   985     
       
   986 // ---------------------------------------------------------------------------
       
   987 // CSVPController::NotifyReceived
       
   988 // ---------------------------------------------------------------------------
       
   989 //
       
   990 void CSVPController::NotifyReceived(
       
   991 				CMceEvent& aEvent,
       
   992 				TMceTransactionDataContainer* aContainer )
       
   993     {
       
   994     SVPDEBUG1( "CSVPController::NotifyReceived In" )
       
   995     
       
   996     TInt ind = FindSVPSession( *aEvent.AssociatedSession() );
       
   997     
       
   998     if ( KErrNotFound != ind )
       
   999         {         
       
  1000         iSessionArray[ ind ]->NotifyReceived( aEvent, aContainer );
       
  1001         }
       
  1002     else
       
  1003         {
       
  1004         SVPDEBUG1( "CSVPController::NotifyReceived, session not found !" )
       
  1005         }
       
  1006 
       
  1007     SVPDEBUG1( "CSVPController::NotifyReceived Out" )
       
  1008     }
       
  1009 
       
  1010 // ---------------------------------------------------------------------------
       
  1011 // CSVPController::EventConnectionStateChanged
       
  1012 // ---------------------------------------------------------------------------
       
  1013 //			
       
  1014 void CSVPController:: EventConnectionStateChanged(
       
  1015                 CMceEvent& /*aEvent*/,
       
  1016                 TBool /*aActive*/ )
       
  1017     {
       
  1018     SVPDEBUG1( "CSVPController:: EventConnectionStateChanged In" )
       
  1019     SVPDEBUG1( "CSVPController:: EventConnectionStateChanged Out" )
       
  1020     }
       
  1021 
       
  1022 // ---------------------------------------------------------------------------
       
  1023 // CSVPController::Failed
       
  1024 // ---------------------------------------------------------------------------
       
  1025 //
       
  1026 #ifdef _DEBUG
       
  1027 void CSVPController::Failed( CMceEvent& /*aEvent*/, TInt aError )
       
  1028 #else
       
  1029 void CSVPController::Failed( CMceEvent& /*aEvent*/, TInt /*aError*/ )
       
  1030 #endif // _DEBUG
       
  1031     {
       
  1032     SVPDEBUG2("CSVPController::Failed Event failure, error: %d", aError )
       
  1033     }
       
  1034 
       
  1035 // ---------------------------------------------------------------------------
       
  1036 // CSVPController::IncomingSession
       
  1037 // ---------------------------------------------------------------------------
       
  1038 //
       
  1039 void CSVPController::IncomingSession(
       
  1040                 CMceInSession* aSession,
       
  1041 				TMceTransactionDataContainer* aContainer )
       
  1042     {
       
  1043     SVPDEBUG1( "CSVPController::IncomingSession In" )
       
  1044     SVPDEBUG2( "CSVPController::IncomingSession - status code: %d", aContainer->GetStatusCode() )
       
  1045     
       
  1046     if ( iEmergencySession )
       
  1047         {
       
  1048         SVPDEBUG1( "CSVPController::IncomingSession - ongoing emergency call - reject incoming call" )
       
  1049         TRAP_IGNORE( aSession->RejectL( KSVPBusyHereReason, KSVPBusyHereVal ) )
       
  1050         // Ownership of aSession is changed, delete it
       
  1051         delete aSession;
       
  1052         aSession = NULL;
       
  1053         return;
       
  1054         }
       
  1055     
       
  1056     // IncomingSessionHandlerL is used to handle possible leave 
       
  1057     SVPDEBUG1( "CSVPController::IncomingSession IncomingSessionHandlerL" )
       
  1058     TRAPD( err, IncomingSessionHandlerL( aSession, aContainer ) );
       
  1059     
       
  1060     if ( err )
       
  1061         {
       
  1062         SVPDEBUG2( "CSVPController::IncomingSession: err: %d", err )
       
  1063         
       
  1064         // RejectL must be called in case SVP needs to delete session.
       
  1065         // TRAP is used because of RejectL might contain a leaver.
       
  1066         switch ( err )
       
  1067             {
       
  1068             case KErrNotSupported:
       
  1069                 {
       
  1070                 TRAP( err, aSession->RejectL( KSVPCallTransactDoesNotExistReason,
       
  1071                         KSVPCallDoesNotExistVal ) );
       
  1072                 break;
       
  1073                 }
       
  1074             
       
  1075             case KSVPErrWrongMinSE:
       
  1076                 // NOP. Reject has been done as a result of call to
       
  1077                 // IncomingSessionHandlerL.
       
  1078                 break;
       
  1079             
       
  1080             case KSVPErrDnDRejection:
       
  1081                 {
       
  1082                 // Reject call because of Do not Disturb service active.
       
  1083                 TRAP( err, aSession->RejectL( KSVPBusyHereReason,
       
  1084                         KSVPBusyHereVal ) );
       
  1085                 break;
       
  1086                 }
       
  1087              
       
  1088              case KSVPErrAnonymousCallRejection:
       
  1089                 {
       
  1090                 // Reject call because of Anonymous Barring service active.
       
  1091                 TRAP( err, aSession->RejectL( KSVPNotAcceptableHereReason,
       
  1092                         KSVPNotAcceptableHereVal ) );
       
  1093                 break;
       
  1094                 }
       
  1095              
       
  1096              case KSVPErrCodecMismatch:
       
  1097                 {
       
  1098                 TRAP( err, aSession->RejectL( KSVPIncompatibleMediaFormatReason,
       
  1099                         KSVPNotAcceptableHereVal ) );
       
  1100                 break;
       
  1101                 }
       
  1102              
       
  1103              default:
       
  1104                 {
       
  1105                 // NOP.
       
  1106                 break;
       
  1107                 }
       
  1108             }
       
  1109         
       
  1110         if ( KErrNotFound == FindSVPSession( *aSession ) )
       
  1111             {
       
  1112             // Leave has occured before CSVPMtSession was created.
       
  1113             delete aSession;
       
  1114             }
       
  1115         else
       
  1116             {
       
  1117             SVPDEBUG1( "CSVPController::IncomingSession IncomingSessionHandlerL leave occurred" )
       
  1118             // clean up session 
       
  1119             TerminateSession( *aSession );
       
  1120             }
       
  1121         }
       
  1122     }
       
  1123 
       
  1124 // ---------------------------------------------------------------------------
       
  1125 // CSVPController::TerminateSession
       
  1126 // ---------------------------------------------------------------------------
       
  1127 //
       
  1128 void CSVPController::TerminateSession( CMceInSession& aSession ) 
       
  1129     {
       
  1130     SVPDEBUG1( "CSVPController::TerminateSession In" )
       
  1131     
       
  1132     // find correct session
       
  1133     TInt index =  FindSVPSession( aSession );
       
  1134     
       
  1135     if ( KErrNotFound != index )
       
  1136         {
       
  1137         CSVPSessionBase* tempBase = iSessionArray[ index ];
       
  1138         // remove session pointer from array and compress array
       
  1139         iSessionArray.Remove( index );
       
  1140         iSessionArray.Compress();
       
  1141         
       
  1142         // delete session  
       
  1143         delete tempBase;
       
  1144         tempBase = NULL;            
       
  1145         }
       
  1146             
       
  1147     SVPDEBUG1( "CSVPController::TerminateSession Out" )  
       
  1148     }
       
  1149 
       
  1150 // ---------------------------------------------------------------------------
       
  1151 // CSVPController::CheckMinSessionExpiresL
       
  1152 // ---------------------------------------------------------------------------
       
  1153 //
       
  1154 void CSVPController::CheckMinSessionExpiresL( CMceInSession& aSession,
       
  1155                                               CDesC8Array& aHeaders, 
       
  1156                                               TInt aMinSE  )
       
  1157     {
       
  1158     SVPDEBUG1( "CSVPController::CheckMinSessionExpiresL In" )
       
  1159     
       
  1160     TInt count = aHeaders.MdcaCount();
       
  1161     TUint32 sessionExpires = 0;
       
  1162     TInt error = KErrNone;
       
  1163     while ( count-- )  
       
  1164     	{
       
  1165         TPtrC8 tmpHeader = aHeaders.MdcaPoint( count );
       
  1166         if ( KErrNotFound != tmpHeader.Find( KSVPSessionExpires ) )
       
  1167             {
       
  1168             // "Session-Expires:" found
       
  1169             SVPDEBUG1( "CSVPController::CheckMinSEL: 'Session-Expires:' found" )
       
  1170             
       
  1171             TInt offset = tmpHeader.FindF( KSVPRefresher );
       
  1172             if ( KErrNotFound != offset )
       
  1173                 {
       
  1174                 tmpHeader.Set( tmpHeader.Left( offset ) );
       
  1175                 }
       
  1176             
       
  1177             TPtrC8 header;
       
  1178             header.Set( tmpHeader );
       
  1179             if ( header.FindF( KSVPCln ) )
       
  1180                 {
       
  1181                 // 5 digits should be enought for Min-SE
       
  1182                 // For example: "Min-SE: 1200" 
       
  1183                 TLex8 expires( header.Right( 5 ) ); 
       
  1184                 TInt digits = 0;
       
  1185                 while ( !expires.Eos() )
       
  1186                     {
       
  1187                     if ( expires.Peek().IsDigit() )
       
  1188                         {
       
  1189                         digits++; 
       
  1190                         }
       
  1191                     expires.Inc();
       
  1192                     }  
       
  1193                 TLex8 expiresVal( header.Right( digits ) );
       
  1194                 error = expiresVal.Val( sessionExpires, EDecimal );
       
  1195                 SVPDEBUG2(" CSVPController::CheckMinSEL sesExp: %d", sessionExpires )
       
  1196 
       
  1197                 if ( error || aMinSE > sessionExpires  )  
       
  1198                     {
       
  1199                     SVPDEBUG2(" CSVPController::CheckMinSEL reject, err: %d", error )
       
  1200                     CDesC8ArrayFlat* minSEHeader = 
       
  1201                         new ( ELeave ) CDesC8ArrayFlat( 1 );
       
  1202                     CleanupStack::PushL( minSEHeader ); // CS:0
       
  1203                         
       
  1204                     HBufC8* header = HBufC8::NewL( 
       
  1205                                  KSVPMinExpiresLenght + digits  );
       
  1206                     CleanupStack::PushL( header );  // CS:1
       
  1207                     
       
  1208                     header->Des().Copy( KSVPMinSessionExpires );
       
  1209                     header->Des().AppendNum( aMinSE );
       
  1210                     minSEHeader[ 0 ].AppendL( *header );
       
  1211                     CleanupStack::PopAndDestroy( header ); // CS:1
       
  1212                     
       
  1213                     aSession.RejectL( KSVPIntervalTooSmallReason,
       
  1214               		 			      KSVPSessionIntervalTooSmallVal,
       
  1215                                       minSEHeader );
       
  1216                     
       
  1217                     // ownership to Mce
       
  1218                     CleanupStack::Pop( minSEHeader ); // CS:0
       
  1219                     User::Leave( KSVPErrWrongMinSE );
       
  1220                     }
       
  1221                 }
       
  1222             }
       
  1223         }
       
  1224     
       
  1225     SVPDEBUG1( "CSVPController::CheckMinSessionExpiresL Out" )
       
  1226     }
       
  1227 
       
  1228 // ---------------------------------------------------------------------------
       
  1229 // CSVPController::FetchExpiresTime
       
  1230 // ---------------------------------------------------------------------------
       
  1231 //
       
  1232 void CSVPController::FetchExpiresTime( TUint32& aExpiresTime, 
       
  1233                                        CDesC8Array& aHeaders ) const
       
  1234     {
       
  1235     SVPDEBUG1( "CSVPController::FetchExpiresTime In" )
       
  1236     
       
  1237     TBool expiresTaken = EFalse;
       
  1238     for ( TInt i = 0; i < aHeaders.MdcaCount() && !expiresTaken; i++ )
       
  1239         {
       
  1240         TPtrC8 tmpHeader = aHeaders.MdcaPoint( i );
       
  1241         if ( KErrNotFound != tmpHeader.Find( KSVPExpiresHeader ) &&
       
  1242              KErrNotFound == tmpHeader.Find( KSVPSessionExpires ) )
       
  1243             {
       
  1244             // "Expires:" found
       
  1245             SVPDEBUG1(" CSVPController::FetchExpiresTimer: 'Expires:' found")
       
  1246 
       
  1247             TInt colonMark = tmpHeader.FindF( KSVPCln );
       
  1248            
       
  1249             if ( colonMark )
       
  1250                 {
       
  1251                 
       
  1252                 TLex8 expires( tmpHeader.Right( 5 ) ); // three digits max
       
  1253                 TInt digits = 0;
       
  1254                 while ( !expires.Eos() )
       
  1255                     {
       
  1256                     if ( expires.Peek().IsDigit() )
       
  1257                         {
       
  1258                         digits++; 
       
  1259                         }
       
  1260                     expires.Inc();
       
  1261                     }
       
  1262                 TLex8 expiresVal( tmpHeader.Right( digits ) );
       
  1263                 TInt error = expiresVal.Val( aExpiresTime, EDecimal );
       
  1264 
       
  1265                 if ( error )
       
  1266                     {
       
  1267                     SVPDEBUG2(" CSVPController::FetchExpiresTimer, set default value\
       
  1268                      Val error: %d", error );
       
  1269                     // if error occurred, set default time
       
  1270                     aExpiresTime = KSVPDefaultExpiresTime;
       
  1271                     expiresTaken = ETrue;
       
  1272                     } 
       
  1273                 else if ( KSVPDefaultExpiresTime < aExpiresTime )
       
  1274                     {
       
  1275                     aExpiresTime = KSVPDefaultExpiresTime;
       
  1276                     expiresTaken = ETrue;
       
  1277                     }
       
  1278                 else
       
  1279                     {
       
  1280                     SVPDEBUG2(" CSVPController::FetchExpiresTime: %d", aExpiresTime )
       
  1281                     expiresTaken = ETrue;
       
  1282                     }
       
  1283                 }                 
       
  1284             }
       
  1285         }
       
  1286     
       
  1287     SVPDEBUG1( "CSVPController::FetchExpiresTime Out" )
       
  1288     }
       
  1289 
       
  1290 // ---------------------------------------------------------------------------
       
  1291 // CSVPController::IncomingSessionHandlerL
       
  1292 // ---------------------------------------------------------------------------
       
  1293 //
       
  1294 void CSVPController::IncomingSessionHandlerL( CMceInSession* aSession,
       
  1295 			                    	TMceTransactionDataContainer* aContainer )
       
  1296     {
       
  1297     SVPDEBUG1( "CSVPController::IncomingSessionHandlerL In" )
       
  1298     
       
  1299     __ASSERT_ALWAYS( aSession, User::Leave( KErrArgument ) );
       
  1300     __ASSERT_ALWAYS( aContainer, User::Leave( KErrArgument ) );
       
  1301 
       
  1302     CDesC8Array* headers = aContainer->GetHeaders();
       
  1303     __ASSERT_ALWAYS( headers, User::Leave( KErrArgument ) );
       
  1304     CleanupStack::PushL( headers ); // CS:1
       
  1305 
       
  1306     IsTransferTargetCaseL( headers );
       
  1307     
       
  1308     // check if Require header contains precondition and that Supported header
       
  1309     // includes option tag 100rel, providing support for PRACK's
       
  1310     iPreconditions = IsPreconditionRequired( *headers );
       
  1311 
       
  1312     // Default expiration time (120 s) is set due IOP issue,
       
  1313 	// otherwise incoming call would continue eternity in some cases.
       
  1314     TUint32 expireTime = KSVPDefaultExpiresTime;
       
  1315     // check if expires header is present and update expiration time
       
  1316     FetchExpiresTime( expireTime, *headers );
       
  1317     
       
  1318     // mt session temp
       
  1319     CSVPMtSession* mtSessionTemp = NULL;
       
  1320     
       
  1321     CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC();      // CS:2
       
  1322     
       
  1323     RPointerArray< CRCSEProfileEntry > voipProfiles;
       
  1324     CleanupResetAndDestroy< RPointerArray< CRCSEProfileEntry > >::PushL(
       
  1325         voipProfiles );                                             // CS:3
       
  1326     
       
  1327     reg->FindBySIPProfileIdL( aSession->Profile(), voipProfiles );
       
  1328     
       
  1329     // Take first profile from the array
       
  1330     const TUint32 voipProfileId = voipProfiles[ 0 ]->iId;
       
  1331     const TUint32 minSE = voipProfiles[ 0 ]->iSIPMinSE;
       
  1332     
       
  1333     CheckMinSessionExpiresL( *aSession, *headers, minSE );
       
  1334      
       
  1335     SVPDEBUG2("CSVPController::IncomingSessionHandlerL VoIP profile id: %d",
       
  1336         voipProfileId );
       
  1337              
       
  1338     // Take first profile from the array
       
  1339     const TUint32 serviceId = voipProfiles[ 0 ]->iServiceProviderId;
       
  1340     
       
  1341     SVPDEBUG2("CSVPController::IncomingSessionHandlerL Service id: %d",
       
  1342         serviceId );
       
  1343     
       
  1344     // create SIP and ProfileRegistry for profile handling
       
  1345     CSIP* sip = CSIP::NewLC( KSVPUid, *this );      // CS: 4
       
  1346     SVPDEBUG1( "CSVPController::IncomingSessionHandlerL sip CREATED" );
       
  1347     
       
  1348     CSIPProfileRegistry* sipProfileRegistry = 
       
  1349         CSIPProfileRegistry::NewLC( *sip, *this );  // CS: 5
       
  1350     
       
  1351     SVPDEBUG1( "CSVPController::IncomingSessionHandlerL\
       
  1352     profile registry CREATED" );
       
  1353     
       
  1354     // retrieve SIP profile by using sip profile id, note ownership transfer
       
  1355     CSIPProfile* profile = sipProfileRegistry->ProfileL( aSession->Profile() );
       
  1356     
       
  1357     // Get keep-alive timer value
       
  1358     TUint32 iapId = 0;
       
  1359     TBool found = EFalse;
       
  1360     TInt keepAliveValue;
       
  1361     
       
  1362     profile->GetParameter( KSIPAccessPointId, iapId );
       
  1363 
       
  1364     TRAPD( errKeepAlive, 
       
  1365         found = iSVPUtility->GetKeepAliveByIapIdL( iapId, keepAliveValue ) );
       
  1366     
       
  1367     SVPDEBUG3( "CSVPController::IncomingSessionHandlerL\
       
  1368                 GetKeepAliveByIapIdL: errKeepAlive = %d found = %d",
       
  1369                 errKeepAlive, found );
       
  1370      
       
  1371     if ( !found )
       
  1372         {
       
  1373         const TDesC8* aor;
       
  1374         profile->GetParameter( KSIPUserAor, aor );
       
  1375         TRAP( errKeepAlive, found = 
       
  1376             iSVPUtility->GetKeepAliveByAORL( *aor, keepAliveValue ) );
       
  1377         
       
  1378         SVPDEBUG3( "CSVPController::IncomingSessionHandlerL\
       
  1379                     GetKeepAliveByAORL: errKeepAlive = %d found = %d",
       
  1380                     errKeepAlive, found );
       
  1381         }
       
  1382     
       
  1383     delete profile;
       
  1384     CleanupStack::PopAndDestroy( 2, sip );          // CS:3
       
  1385     
       
  1386     CMceRtpSource* rtpSource = NULL;
       
  1387     
       
  1388     // modify codecs and codec settings if streams found
       
  1389     if ( aSession->Streams().Count() )
       
  1390         {
       
  1391       	const RPointerArray<CMceMediaStream>& streams = aSession->Streams();
       
  1392       	
       
  1393         SVPDEBUG2("CSVPController::IncomingSessionHandlerL Streamcount: %d",
       
  1394             streams.Count() );
       
  1395         
       
  1396         // disable rtp source and speaker sink so that audio is not on
       
  1397         // before session is up signalling-wise
       
  1398         for ( TInt i = 0; i < streams.Count(); i++ )
       
  1399             {
       
  1400             SVPDEBUG1( "CSVPController::IncomingSessionHandlerL disabling" );
       
  1401             
       
  1402             CMceMediaStream* stream1 = streams[i];
       
  1403             
       
  1404             // if stream is not audio stream -> remove 
       
  1405             if ( KMceAudio != stream1->Type() )
       
  1406                 {
       
  1407                 aSession->RemoveStreamL( *streams[ i ] );
       
  1408                 }
       
  1409             else
       
  1410                 {
       
  1411                 // search for RTP source
       
  1412                 if ( stream1->Source() && 
       
  1413                      KMceRTPSource == stream1->Source()->Type() )
       
  1414                     {
       
  1415                     SVPDEBUG1(
       
  1416                         "CSVPController::IncomingSessionHandlerL\
       
  1417                          RTPSource found" );
       
  1418                     
       
  1419                 	rtpSource = static_cast<CMceRtpSource*>(
       
  1420                 	    stream1->Source() );
       
  1421                     }
       
  1422             
       
  1423                 SVPAudioUtility::DisableSpeakerSinkL( stream1->Sinks() );
       
  1424                 SVPAudioUtility::DisableMicSourceL( *stream1 );
       
  1425                 }
       
  1426             }
       
  1427             
       
  1428         // sets MMF priorities and sets codec specific settings
       
  1429         CheckStreamsL( *voipProfiles[ 0 ], *aSession, keepAliveValue );
       
  1430         if ( rtpSource )
       
  1431             {
       
  1432             iSVPUtility->UpdateJitterBufferSizeL( *rtpSource );
       
  1433             }
       
  1434         
       
  1435         // create SVP Mt session    
       
  1436         mtSessionTemp = CSVPMtSession::NewL( aSession,
       
  1437                                              iContainer,
       
  1438                                              serviceId,
       
  1439                                              voipProfileId, 
       
  1440                                              *this, 
       
  1441                                              *iSVPUtility,
       
  1442                                              *iRtpObserver,
       
  1443                                              keepAliveValue,
       
  1444                                              iPreconditions );
       
  1445         
       
  1446         CleanupStack::PushL( mtSessionTemp );
       
  1447         FinalizeSessionCreationL( mtSessionTemp );
       
  1448         CleanupStack::Pop( mtSessionTemp );
       
  1449         }
       
  1450     else
       
  1451         {
       
  1452         SVPDEBUG1( "CSVPController::IncomingSessionHandlerL NO streams!" );
       
  1453         
       
  1454         // no streams found, handle streams like in Mo-case  
       
  1455         mtSessionTemp = CSVPMtSession::NewL( aSession,
       
  1456                                              iContainer,
       
  1457                                              serviceId,
       
  1458                                              voipProfileId, 
       
  1459                                              *this, 
       
  1460                                              *iSVPUtility,
       
  1461                                              *iRtpObserver,
       
  1462                                              keepAliveValue,
       
  1463                                              iPreconditions );
       
  1464         
       
  1465         CleanupStack::PushL( mtSessionTemp );
       
  1466         // construct audio streams 
       
  1467         mtSessionTemp->ConstructAudioStreamsL();
       
  1468         FinalizeSessionCreationL( mtSessionTemp );
       
  1469         CleanupStack::Pop( mtSessionTemp );
       
  1470         }
       
  1471     
       
  1472     CleanupStack::PopAndDestroy( 3, headers );                          // CS:0
       
  1473     
       
  1474     // set expires timer
       
  1475     if ( expireTime )
       
  1476         {
       
  1477         SVPDEBUG2( "CSVPController::IncomingSessionHandlerL expireTime: %i s.", expireTime );
       
  1478         mtSessionTemp->StartTimerL( KSVPMilliSecondCoefficient * expireTime,
       
  1479                                     KSVPExpiresTimeExpired );
       
  1480         }
       
  1481     
       
  1482     SVPDEBUG1( "CSVPController::IncomingSessionHandlerL Updating call" );
       
  1483     
       
  1484     aSession->UpdateL();
       
  1485     
       
  1486     SVPDEBUG2( "CSVPController::IncomingSessionHandlerL, Call state after update: %i",
       
  1487         aSession->State() );
       
  1488     
       
  1489     if ( CMceSession::EProceeding == aSession->State() )
       
  1490         {
       
  1491         const TInt ind = FindSVPSession( *aSession );
       
  1492         iCCPMonitor->IncomingCall( iSessionArray[ ind ] );
       
  1493         
       
  1494         SVPDEBUG1( "CSVPController::IncomingSessionHandlerL - EProceeding" );
       
  1495         
       
  1496         iSessionArray[ ind ]->SessionStateChanged( KErrNone );
       
  1497         }
       
  1498     
       
  1499     // reset flag
       
  1500     iPreconditions = EFalse;
       
  1501     
       
  1502     SVPDEBUG1( "CSVPController::IncomingSessionHandlerL Out" )
       
  1503     }
       
  1504    
       
  1505 // ---------------------------------------------------------------------------
       
  1506 // CSVPController::CheckStreamsL
       
  1507 // ---------------------------------------------------------------------------
       
  1508 //    
       
  1509 void CSVPController::CheckStreamsL( CRCSEProfileEntry& aVoipProfile, 
       
  1510                                     CMceSession& aInSession,
       
  1511                                     TInt aKeepAliveValue,
       
  1512                                     TBool aSessionUpdateOngoing)
       
  1513     {
       
  1514     SVPDEBUG1( "CSVPController::CheckStreamsL In" )
       
  1515     
       
  1516     __ASSERT_ALWAYS( &aInSession, User::Leave( KErrArgument ) );
       
  1517 
       
  1518     const RPointerArray< CMceMediaStream >& streamArray = 
       
  1519         aInSession.Streams();
       
  1520     
       
  1521     const TInt streamCount( streamArray.Count() );
       
  1522     
       
  1523     SVPDEBUG3("CSVPController::CheckStreamsL aVoIPProfileId: %u streamCount: %d ",
       
  1524             aVoipProfile.iId, streamCount );
       
  1525     
       
  1526     // Set codec settings, this also removes unneeded codecs.
       
  1527     for ( TInt i = 0; i < streamCount; i++ )
       
  1528         {
       
  1529         iSVPUtility->SetAudioCodecsMTL( aVoipProfile, 
       
  1530                                         *streamArray[ i ], 
       
  1531                                         aKeepAliveValue,
       
  1532                                         aSessionUpdateOngoing );
       
  1533 
       
  1534         // Set the priorities for the remaining codecs. This will handle also the
       
  1535         // DTMF priorites once correct codecs are set in the streams. Also note
       
  1536         // the downlink/uplink (in/out) discrimination.
       
  1537 
       
  1538         if ( KMceAudio == streamArray[i]->Type() && 
       
  1539             streamArray[i]->BoundStream() )
       
  1540             {
       
  1541             SVPDEBUG2( "CSVPController::CheckStreamsL round: %d start", i )
       
  1542             
       
  1543             CMceAudioStream* stream = static_cast<CMceAudioStream*>( streamArray[i] );
       
  1544             
       
  1545             TBool dtmfMode = EFalse;
       
  1546             if ( SVPAudioUtility::IsDownlinkStream( *stream ) )
       
  1547                 {
       
  1548                 dtmfMode = SVPAudioUtility::SetPriorityCodecValuesL( *stream,
       
  1549                     static_cast<CMceAudioStream&>( stream->BoundStreamL() ) );
       
  1550                 }
       
  1551             else
       
  1552                 {
       
  1553                 dtmfMode = SVPAudioUtility::SetPriorityCodecValuesL(
       
  1554                     static_cast<CMceAudioStream&>( stream->BoundStreamL() ),
       
  1555                         *stream );
       
  1556                 }
       
  1557             
       
  1558             iSVPUtility->SetDtmfMode( dtmfMode );
       
  1559             
       
  1560             SVPDEBUG2( "CSVPController::CheckStreamsL round: %d done", i )
       
  1561             }
       
  1562         }
       
  1563     
       
  1564     SVPDEBUG1( "CSVPController::CheckStreamsL Out" )
       
  1565     }
       
  1566 
       
  1567 // -----------------------------------------------------------------------------
       
  1568 // CSVPController::GetCallIdFromUserHeadersL
       
  1569 // Extract call id from user headers
       
  1570 // -----------------------------------------------------------------------------
       
  1571 //
       
  1572 TBool CSVPController::GetCallIdFromUserHeadersL(
       
  1573     const CDesC8Array& aUserHeaders,
       
  1574     TDes8& aCallId )
       
  1575     {
       
  1576     // All variables is used for parser.
       
  1577     TInt tmpMark1 = 0;
       
  1578     TInt tmpMark2 = 0;
       
  1579     
       
  1580     TBool found = EFalse;
       
  1581 
       
  1582     // Find replaces header descriptor from userheaders array.
       
  1583     for ( TInt m = 0; &aUserHeaders && m < aUserHeaders.Count() && !found; m++ )
       
  1584         {
       
  1585         TPtrC8 tmpHeader = aUserHeaders[m];
       
  1586         if ( KErrNotFound != tmpHeader.FindF( KSVPReplacesColonTxt ) )
       
  1587             {
       
  1588             SVPDEBUG1("  CSVPController::\
       
  1589             GetCallIdFromUserHeadersL: Replaces: found:");
       
  1590 
       
  1591             // variables used for parse tags from replaces header.
       
  1592             tmpMark1 = tmpHeader.Locate( KSVPColonMark );
       
  1593             tmpMark2 = tmpHeader.Locate( KSVPSemiColonMark );
       
  1594             if ( KErrNotFound == tmpMark1 ||
       
  1595                  KErrNotFound == tmpMark2 )
       
  1596                 {
       
  1597                 SVPDEBUG3("CSVPController::GetCallIdFromUserHeadersL leave \
       
  1598                       tmpMark1: %d, tmpMark2: %d", tmpMark1, tmpMark2 )
       
  1599                 User::Leave( KErrArgument );
       
  1600                 }
       
  1601 
       
  1602             // Call id is between tmpMark1 and tmpMark2 and there is a space
       
  1603             // between Replaces: -text and callid
       
  1604             if ( ( tmpHeader.Mid( tmpMark1+2, tmpMark2 - tmpMark1 - 2 ).Length() < KSVPTempStringlength ) )
       
  1605                 {
       
  1606                 aCallId.Copy( 
       
  1607                     tmpHeader.Mid( tmpMark1+2, tmpMark2 - tmpMark1 - 2 ) );
       
  1608 
       
  1609                 found = ETrue;                
       
  1610                 }
       
  1611             else
       
  1612                 {
       
  1613                 SVPDEBUG1("  CSVPController::\
       
  1614                 GetCallIdFromUserHeadersL: Replaces: Too long, Leave");
       
  1615                 User::Leave( KErrArgument );
       
  1616                 }
       
  1617             }
       
  1618         }
       
  1619     
       
  1620     SVPDEBUG2( "CSVPController::GetCallIdFromUserHeadersL return %d", found )
       
  1621     return found;
       
  1622     }
       
  1623 
       
  1624 // -----------------------------------------------------------------------------
       
  1625 // CSVPController::IsTransferTargetCaseL
       
  1626 // -----------------------------------------------------------------------------
       
  1627 //
       
  1628 void CSVPController::IsTransferTargetCaseL( CDesC8Array* aHeaders )
       
  1629     {
       
  1630     SVPDEBUG1( "CSVPController::IsTransferTargetCaseL In" )
       
  1631     
       
  1632     iHoldCallIndex = KErrNotFound;
       
  1633     TBool found = EFalse;
       
  1634     
       
  1635     if ( aHeaders && aHeaders->Count() )
       
  1636         {
       
  1637         // Variable to contain callID from replaces header.
       
  1638         TBuf8< KSVPTempStringlength > repCallId( KNullDesC8 );
       
  1639 
       
  1640         // This is transfer session if Replaces: text is found from userheader
       
  1641         if ( GetCallIdFromUserHeadersL( *aHeaders, repCallId ) )
       
  1642             {
       
  1643             SVPDEBUG1( "  CSVPController::IsTransferTargetCaseL: \
       
  1644                 (attended) Transfer target case" )
       
  1645             
       
  1646             if ( repCallId.Length() != 0 )
       
  1647                 {
       
  1648                 // Find from SVP session array a session including same CallId
       
  1649                 // that parsed from replace header.
       
  1650                 for ( TInt v = 0; v < iSessionArray.Count() && !found; v++ )
       
  1651                     {
       
  1652                     SVPDEBUG2( "  CSVPController::IsTransferTargetCaseL v=%d", v )
       
  1653                     
       
  1654                     TBuf8< KSVPTempStringlength > holdCallId( KNullDesC8 );     
       
  1655                     TDesC8* callid2 = iSessionArray[v]->CallId();
       
  1656                     
       
  1657                     if ( callid2 )
       
  1658                         {
       
  1659                         TInt index = callid2->Find( KSVPCallId_replaces );
       
  1660                         holdCallId.Append( 
       
  1661                         callid2->Mid( index + KSVPCallId_replaces().Length() ) );
       
  1662 
       
  1663                         SVPDEBUG2( "CSVPController::IsTransferTargetCaseL: SesState: %d",
       
  1664                                      iSessionArray[v]->State() )
       
  1665                         
       
  1666                         if ( repCallId == holdCallId && 
       
  1667                              MCCPCallObserver::ECCPStateDisconnecting != 
       
  1668                                 iSessionArray[v]->State() )
       
  1669                             {
       
  1670                             iHoldCallIndex = v;
       
  1671                             }
       
  1672                         }
       
  1673                     }
       
  1674                 
       
  1675                 if ( KErrNotFound == iHoldCallIndex )
       
  1676                     {
       
  1677                     SVPDEBUG1("CSVPController::IsTransferTargetCaseL: \
       
  1678                         sessions or CallIds does not match, leave !!!" ) 
       
  1679                     User::Leave( KErrNotSupported );
       
  1680                     }
       
  1681                 }
       
  1682             else
       
  1683                 {
       
  1684                 SVPDEBUG1("CSVPController::IsTransferTargetCaseL: \
       
  1685                     Transfer session but CallId wasn't found, leave !!!" )
       
  1686                 User::Leave( KErrNotSupported );
       
  1687                 }
       
  1688             }
       
  1689         else
       
  1690             {
       
  1691 		    TSupplementaryServicesEvent restrictEvent = 
       
  1692 		    	iSuppServices->CheckRestrictionsL( *aHeaders );
       
  1693 
       
  1694 			if ( ESVPSSDoNotDisturb == restrictEvent )
       
  1695 				{
       
  1696 				User::Leave( KSVPErrDnDRejection );
       
  1697 				}
       
  1698 			if ( ESVPSSAnonymousBarring == restrictEvent )
       
  1699 				{
       
  1700 				User::Leave( KSVPErrAnonymousCallRejection );
       
  1701 				}
       
  1702             SVPDEBUG1("  CSVPController::IsTransferTargetCaseL: \
       
  1703                 Normal incoming case");
       
  1704             }
       
  1705         }
       
  1706 
       
  1707     SVPDEBUG2( "CSVPController::IsTransferTargetCaseL Out iHoldCallIndex: %d",
       
  1708                 iHoldCallIndex )
       
  1709     }
       
  1710 
       
  1711 // --------------------------------------------------------------------------
       
  1712 // CSVPController::IsPreconditionRequired
       
  1713 // Check if Require header contains precondition and that Supported header
       
  1714 // includes option tag 100rel, providing support for PRACK's
       
  1715 // --------------------------------------------------------------------------
       
  1716 TBool CSVPController::IsPreconditionRequired( CDesC8Array& aHeaders )
       
  1717     {
       
  1718     SVPDEBUG1( "CSVPController::IsPreconditionRequired In" )
       
  1719         
       
  1720     TInt count = aHeaders.MdcaCount();
       
  1721     TBool require = EFalse;
       
  1722     TBool supported = EFalse;
       
  1723     while ( count-- )  
       
  1724         {
       
  1725         TPtrC8 tmpHeader = aHeaders.MdcaPoint( count );
       
  1726         if ( KErrNotFound != tmpHeader.Find( KSVPRequire ) && !require )
       
  1727             {
       
  1728             // "Require:" found
       
  1729             SVPDEBUG1( "CSVPController::IsPreconditionRequired 'Require-header' found" )
       
  1730             
       
  1731             if ( tmpHeader.FindF( KSVPPrecondition ) )
       
  1732                 {
       
  1733                 // "precondition" found in Require header field
       
  1734                 SVPDEBUG1( "CSVPController::IsPreconditionRequired 'precondition' found" )
       
  1735                 require = ETrue;
       
  1736                 }
       
  1737             }
       
  1738         else if ( KErrNotFound != tmpHeader.Find( KSVPSupported ) && !supported )
       
  1739             {
       
  1740             // "Supported:" found
       
  1741             SVPDEBUG1( "CSVPController::IsPreconditionRequired 'Supported-header' found" )
       
  1742             
       
  1743             if ( tmpHeader.FindF( KSVP100rel ) )
       
  1744                 {
       
  1745                 // "100rel" found in Supported header field
       
  1746                 SVPDEBUG1( "CSVPController::IsPreconditionRequired '100rel' found" )
       
  1747                 supported = ETrue;
       
  1748                 }
       
  1749             }
       
  1750         }
       
  1751     if ( require && supported )
       
  1752         {
       
  1753         SVPDEBUG1( "CSVPController::IsPreconditionRequired return ETrue" )
       
  1754         return ETrue;
       
  1755         }        
       
  1756     SVPDEBUG1( "CSVPController::IsPreconditionRequired return EFalse" )
       
  1757     return EFalse;
       
  1758     }
       
  1759 	
       
  1760 // ---------------------------------------------------------------------------
       
  1761 // CSVPController::CheckHeadersData
       
  1762 // Check and store data (FromHeader, ToHeader, CallId) from the headers
       
  1763 // to the SessionBase.
       
  1764 // ---------------------------------------------------------------------------
       
  1765 //    
       
  1766 void CSVPController::CheckHeadersData( CSVPSessionBase* aSVPSession, 
       
  1767                             TMceTransactionDataContainer* aContainer )
       
  1768     {
       
  1769     SVPDEBUG1( "CSVPController::CheckHeadersData In" )
       
  1770     
       
  1771     TRAPD( stringErr, SIPStrings::OpenL() );
       
  1772 
       
  1773     if ( KErrNone == stringErr )
       
  1774         {
       
  1775         // get headers
       
  1776         CDesC8Array* headers = aContainer->GetHeaders();
       
  1777 	    RStringF fromHdr = SIPStrings::StringF(SipStrConsts::EFromHeader);
       
  1778 	    RStringF fromCompHdr = SIPStrings::StringF(SipStrConsts::EFromHeaderCompact);
       
  1779 
       
  1780 	    RStringF toHdr = SIPStrings::StringF(SipStrConsts::EToHeader);
       
  1781 	    RStringF toCompHdr = SIPStrings::StringF(SipStrConsts::EToHeaderCompact);
       
  1782 
       
  1783 	    RStringF callidHdr = SIPStrings::StringF(SipStrConsts::ECallIDHeader);
       
  1784 	    RStringF callidCompHdr = SIPStrings::StringF(SipStrConsts::ECallIDHeaderCompact);
       
  1785 	    
       
  1786 	    RStringF cSeqHdr = SIPStrings::StringF(SipStrConsts::ECSeqHeader);
       
  1787 
       
  1788         if ( headers )
       
  1789             {
       
  1790             TBool fromFound( EFalse );
       
  1791             TBool toFound( EFalse );
       
  1792             TBool callIdFound( EFalse );
       
  1793             TBool cSeqFound( EFalse );
       
  1794 
       
  1795             for( TInt i = 0;i < headers->MdcaCount();i++ )
       
  1796                 {
       
  1797                 TPtrC8 tmpHeader = headers->MdcaPoint( i );
       
  1798                 TInt colonMark = tmpHeader.FindF( KSVPCln );
       
  1799                 
       
  1800                 SVPDEBUG2( "CSVPController::CheckHeadersData colonMark=%d", colonMark )
       
  1801                 
       
  1802                 TInt fromHdrPos = tmpHeader.FindF( fromHdr.DesC() );
       
  1803                 TInt fromCompHdrPos = tmpHeader.FindF( fromCompHdr.DesC() );
       
  1804 
       
  1805                 TInt toHdrPos = tmpHeader.FindF( toHdr.DesC() );
       
  1806                 TInt toCompHdrPos = tmpHeader.FindF( toCompHdr.DesC() );
       
  1807 
       
  1808                 TInt callidHdrPos = tmpHeader.FindF( callidHdr.DesC() );
       
  1809                 TInt callidCompHdrPos = tmpHeader.FindF( callidCompHdr.DesC() );
       
  1810                 
       
  1811                 TInt cSeqHdrPos = tmpHeader.FindF( cSeqHdr.DesC() );
       
  1812 
       
  1813                 // Header name is separeted by colonmark from header body.
       
  1814                 // There might be space between name and colonmark.
       
  1815 
       
  1816                 if ( !fromFound &&
       
  1817                      ( (KErrNotFound < fromHdrPos && fromHdrPos < colonMark) ||
       
  1818                        (KErrNotFound < fromCompHdrPos && fromCompHdrPos < colonMark ) ) )
       
  1819                     {
       
  1820                     fromFound = ETrue;
       
  1821                     aSVPSession->SetFromHeader( headers->MdcaPoint( i ) );
       
  1822                     }
       
  1823                 else if ( !toFound &&
       
  1824                         ( (KErrNotFound < toHdrPos && toHdrPos < colonMark) ||
       
  1825                           (KErrNotFound < toCompHdrPos && toCompHdrPos < colonMark ) ) )
       
  1826                     {
       
  1827                     toFound = ETrue;
       
  1828                     aSVPSession->SetToHeader( headers->MdcaPoint( i ) );
       
  1829                     }
       
  1830                 else if ( !callIdFound &&
       
  1831                         ( (KErrNotFound < callidHdrPos && callidHdrPos < colonMark) ||
       
  1832                           (KErrNotFound < callidCompHdrPos && callidCompHdrPos < colonMark ) ) )
       
  1833                     {
       
  1834                     callIdFound = ETrue;
       
  1835                     aSVPSession->SetCallId( headers->MdcaPoint( i ) );
       
  1836                     }
       
  1837                 else if ( !cSeqFound && 
       
  1838                           KErrNotFound < cSeqHdrPos && cSeqHdrPos < colonMark )
       
  1839                     {
       
  1840                     cSeqFound = ETrue;
       
  1841                     aSVPSession->SetCSeqHeader( headers->MdcaPoint( i ) );
       
  1842                     }
       
  1843                 }
       
  1844             }
       
  1845         
       
  1846         SIPStrings::Close();
       
  1847         delete headers;
       
  1848         headers = NULL;
       
  1849         }
       
  1850     else
       
  1851         {
       
  1852         SVPDEBUG2( "CSVPController::CheckHeadersData stringErr=%d", stringErr )
       
  1853         }
       
  1854     
       
  1855     SVPDEBUG1( "CSVPController::CheckHeadersData Out" )
       
  1856     }
       
  1857 
       
  1858 // ---------------------------------------------------------------------------
       
  1859 // CSVPController::CheckContactData
       
  1860 // Check and store contact data from the headers to the MoSession
       
  1861 // ---------------------------------------------------------------------------
       
  1862 //    
       
  1863 TInt CSVPController::CheckContactData( CSVPSessionBase* aSVPSession, 
       
  1864                             TMceTransactionDataContainer* aContainer )
       
  1865     {
       
  1866     SVPDEBUG1( "CSVPController::CheckContactData In" )
       
  1867     
       
  1868     TInt count( 0 );
       
  1869     TRAPD( stringErr, SIPStrings::OpenL() );
       
  1870 
       
  1871     if ( KErrNone == stringErr && aSVPSession->IsMobileOriginated() )
       
  1872         {
       
  1873         CDesC8Array* headers = aContainer->GetHeaders();
       
  1874 
       
  1875         if ( headers )
       
  1876             {
       
  1877     	    RStringF contactHdr = SIPStrings::StringF(SipStrConsts::EContactHeader);
       
  1878     	    RStringF contactHdrComp = SIPStrings::StringF(SipStrConsts::EContactHeaderCompact);
       
  1879 
       
  1880             CSVPMoSession* moSession = static_cast< CSVPMoSession* >( aSVPSession );
       
  1881             moSession->ResetForwardAddressChoices();
       
  1882 
       
  1883             TInt ret( 0 );
       
  1884             for( TInt i( 0 ); i < headers->MdcaCount(); i++ )
       
  1885                 {
       
  1886                 TPtrC8 tmpHeader = headers->MdcaPoint( i );
       
  1887                 TInt colonMark = tmpHeader.FindF( KSVPCln );
       
  1888                 TPtrC8 left = tmpHeader.Left( colonMark ); // string until to first colon mark
       
  1889 
       
  1890                 if ( left.CompareF( contactHdr.DesC() ) == KErrNone ||
       
  1891                      left.CompareF( contactHdrComp.DesC() ) == KErrNone ) 
       
  1892                     {
       
  1893                     SVPDEBUG1( "CSVPController::CheckContactData - Contact header found" )
       
  1894 
       
  1895                     // Get the remaining part of the contact header string and
       
  1896                     // send it to mo session for parsing 
       
  1897                     TPtrC8 right = tmpHeader.Right( 
       
  1898                         tmpHeader.Length() - left.Length() - 1 );
       
  1899 
       
  1900                     TRAPD( addErr, ret = moSession->AddForwardAddressL( right ) );
       
  1901                     if (KErrNone == addErr)
       
  1902                         {
       
  1903                         count = count + ret;
       
  1904                         }
       
  1905                     else
       
  1906                         {
       
  1907                         SVPDEBUG2( "CSVPController::CheckContactData: addErr = %d", addErr )
       
  1908                         }
       
  1909                     }
       
  1910                 }
       
  1911             }
       
  1912         else
       
  1913             {
       
  1914             SVPDEBUG1( "CSVPController::CheckContactData No headers" )
       
  1915             }
       
  1916 
       
  1917         SIPStrings::Close();
       
  1918         delete headers;
       
  1919         headers = NULL;
       
  1920         }
       
  1921     else
       
  1922         {
       
  1923         SVPDEBUG2( "CSVPController::CheckContactData stringErr=%d", stringErr )
       
  1924         }
       
  1925     
       
  1926     SVPDEBUG2( "CSVPController::CheckContactData Out return=%d", count )
       
  1927     return count;
       
  1928     }
       
  1929 
       
  1930 // ---------------------------------------------------------------------------
       
  1931 // CSVPController::IncomingUpdate
       
  1932 // ---------------------------------------------------------------------------
       
  1933 //			
       
  1934 void CSVPController::IncomingUpdate(
       
  1935 				CMceSession& aOrigSession, 
       
  1936 				CMceInSession* aUpdatedSession,
       
  1937 				TMceTransactionDataContainer* aContainer )
       
  1938     {
       
  1939     SVPDEBUG1( "CSVPController::IncomingUpdate In" )
       
  1940     
       
  1941     iContainer = *aContainer;
       
  1942     const TInt sessionIndex = FindSVPSession( aOrigSession );
       
  1943     
       
  1944     if ( KErrNotFound != sessionIndex )
       
  1945         {
       
  1946         SVPDEBUG1( "CSVPController::IncomingUpdate - Session found" )
       
  1947         
       
  1948         // handle RE-INVITE without SDP
       
  1949         if ( !aUpdatedSession->Streams().Count() )
       
  1950             {
       
  1951             SVPDEBUG1( "CSVPController::IncomingUpdate No streams present" )
       
  1952             
       
  1953             // this call sets iEmptyReInvite flag to ETrue for session, 
       
  1954             // flag prevents "ghots session" to be seen on UI 
       
  1955             // when empty Re-Invite is received
       
  1956             iSessionArray[ sessionIndex ]->SetEmptyReInvite();
       
  1957                                
       
  1958             
       
  1959             #ifdef _DEBUG
       
  1960             
       
  1961             TRAPD( noSdpErr, IncomingUpdateNoSdpHandlerL( sessionIndex,
       
  1962                                                           aUpdatedSession ) );
       
  1963             
       
  1964             SVPDEBUG2( "CSVPController::IncomingUpdate trapped: %d", noSdpErr )
       
  1965             
       
  1966             #else   // _UREL
       
  1967             
       
  1968             TRAP_IGNORE( IncomingUpdateNoSdpHandlerL(
       
  1969                 sessionIndex, aUpdatedSession ) )
       
  1970             
       
  1971             #endif  // _DEBUG
       
  1972             }
       
  1973         
       
  1974         else
       
  1975             {
       
  1976             SVPDEBUG1( "CSVPController::IncomingUpdate - Normal case" )
       
  1977             IncomingNormalUpdate( sessionIndex,
       
  1978                     aOrigSession, aUpdatedSession );
       
  1979             }
       
  1980         
       
  1981         SVPDEBUG1( "CSVPController::IncomingUpdate - Handled" )
       
  1982         }
       
  1983     else if ( iEmergencySession && 
       
  1984               aUpdatedSession && 
       
  1985               aUpdatedSession->Streams().Count() )
       
  1986         {
       
  1987         // Handle emergency hold
       
  1988         TRAPD( error, iEmergencySession->IncomingRequestL(
       
  1989                 aUpdatedSession, iContainer ) );
       
  1990         
       
  1991         if ( error )
       
  1992             {
       
  1993             SVPDEBUG2( "CSVPController::IncomingUpdate, emergency error=%d",
       
  1994                     error )
       
  1995             }
       
  1996         }
       
  1997     
       
  1998     SVPDEBUG1( "CSVPController::IncomingUpdate Out" )
       
  1999     }
       
  2000 
       
  2001 // ---------------------------------------------------------------------------
       
  2002 // CSVPController::IncomingNormalUpdate
       
  2003 // ---------------------------------------------------------------------------
       
  2004 //
       
  2005 void CSVPController::IncomingNormalUpdate( TInt aSessionIndex,
       
  2006                                            CMceSession& aOrigSession,
       
  2007                                            CMceInSession* aUpdatedSession )
       
  2008     {
       
  2009     SVPDEBUG1( "CSVPController::IncomingNormalUpdate In" )
       
  2010     
       
  2011     TInt err = iSessionArray[ aSessionIndex ]->IncomingRequest(
       
  2012         *aUpdatedSession );
       
  2013     
       
  2014     if ( KErrSVPHoldNotHoldRequest == err )
       
  2015         {
       
  2016         SVPDEBUG1( "CSVPController::IncomingNormalUpdate - Not Hold/Resume" )
       
  2017         
       
  2018         if ( iSessionArray[ aSessionIndex ]->HasHoldController() &&
       
  2019              KSVPHoldConnectedStateIndex != iSessionArray[ aSessionIndex ]->
       
  2020                  HoldController().HoldState() )
       
  2021             {
       
  2022             // Hold is active; must update MCE streams state 
       
  2023             // correspondingly
       
  2024             TRAP( err, iSessionArray[ aSessionIndex ]->HoldController().
       
  2025                             RefreshHoldStateL() );
       
  2026             SVPDEBUG2( "CSVPController::IncomingNormalUpdate - Err: %d", err )
       
  2027             }
       
  2028         
       
  2029         TRAP( err, UpdateSessionL( aOrigSession, *aUpdatedSession ) );
       
  2030         
       
  2031         SVPDEBUG2( "CSVPController::IncomingNormalUpdate - Updated err: %d",
       
  2032             err )
       
  2033         }
       
  2034     else if ( iDtmfStringSending )
       
  2035         {
       
  2036         SVPDEBUG1( "CSVPController::IncomingNormalUpdate - Dtmf sending will be stopped" )
       
  2037         // send stop event to the previous character in string 
       
  2038         // Default tone char
       
  2039         TChar dtmfToneChar( '0' );
       
  2040 
       
  2041         iSessionArray[ aSessionIndex ]->DtmfObserver().HandleDTMFEvent( 
       
  2042                 MCCPDTMFObserver::ECCPDtmfSequenceStop, 
       
  2043                 KErrNone, 
       
  2044                 dtmfToneChar );
       
  2045 
       
  2046         // send sequence stop event
       
  2047         iSessionArray[ aSessionIndex ]->DtmfObserver().HandleDTMFEvent( 
       
  2048              MCCPDTMFObserver::ECCPDtmfStringSendingCompleted, 
       
  2049              KErrNone, 
       
  2050              dtmfToneChar );
       
  2051 
       
  2052         // sequence complete, clear flags
       
  2053         iDtmfStringSending = EFalse;
       
  2054         iFirstDtmfSent = EFalse;
       
  2055         
       
  2056         SVPDEBUG1( "CSVPController::IncomingNormalUpdate - Dtmf sending stopped" )
       
  2057         }
       
  2058     else
       
  2059         {
       
  2060         SVPDEBUG2( "CSVPController::IncomingNormalUpdate - IncomingRequest err: %d", err )
       
  2061         }
       
  2062     
       
  2063     iSessionArray[ aSessionIndex ]->SetUpdatedSession( aUpdatedSession );
       
  2064     
       
  2065     SVPDEBUG1( "CSVPController::IncomingNormalUpdate Out" )
       
  2066     }
       
  2067 
       
  2068 // ---------------------------------------------------------------------------
       
  2069 // CSVPController::IncomingUpdateNoSdpHandlerL
       
  2070 // ---------------------------------------------------------------------------
       
  2071 //
       
  2072 void CSVPController::IncomingUpdateNoSdpHandlerL( TInt aSessionIndex,
       
  2073         CMceInSession* aUpdatedSession )
       
  2074     {
       
  2075     SVPDEBUG1( "CSVPController::IncomingUpdateNoSdpHandlerL In" )
       
  2076     if ( iRtpObserver )
       
  2077         {
       
  2078         iRtpObserver->ResetSessionInObserving( iSessionArray[ aSessionIndex ] );
       
  2079 		}
       
  2080     // set updated session to SVP, ownership is transferred
       
  2081     // old session is obsolete
       
  2082     iSessionArray[ aSessionIndex ]->SetUpdatedSession( aUpdatedSession );
       
  2083     
       
  2084     // construct audio streams again, adding all the supported codecs
       
  2085     iSessionArray[ aSessionIndex ]->ConstructAudioStreamsL();
       
  2086     
       
  2087     // finally update the session
       
  2088     aUpdatedSession->UpdateL();
       
  2089     
       
  2090     SVPDEBUG1( "CSVPController::IncomingUpdateNoSdpHandlerL Out" )
       
  2091     }
       
  2092 
       
  2093 // ---------------------------------------------------------------------------
       
  2094 // CSVPController::UpdateSessionL
       
  2095 // ---------------------------------------------------------------------------
       
  2096 //			
       
  2097 void CSVPController::UpdateSessionL( CMceSession& aOrigSession,
       
  2098                                      CMceInSession& aUpdatedSession )
       
  2099     {
       
  2100     SVPDEBUG1( "CSVPController::UpdateSessionL In" )
       
  2101     
       
  2102     __ASSERT_ALWAYS( &aOrigSession, User::Leave( KErrArgument ) );
       
  2103     __ASSERT_ALWAYS( &aUpdatedSession, User::Leave( KErrArgument ) );
       
  2104     
       
  2105     CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC();
       
  2106     RPointerArray< CRCSEProfileEntry > voipProfiles;
       
  2107     CleanupResetAndDestroy< RPointerArray< CRCSEProfileEntry > >::PushL(
       
  2108         voipProfiles );
       
  2109     
       
  2110     reg->FindBySIPProfileIdL( aOrigSession.Profile(), voipProfiles );
       
  2111     
       
  2112     TInt keepAliveTime = 0;
       
  2113     TInt index = FindSVPSession( aOrigSession );
       
  2114     if ( KErrNotFound != index )
       
  2115         {
       
  2116         keepAliveTime = iSessionArray[ index ]->GetKeepAliveTime();
       
  2117         __ASSERT_ALWAYS( iRtpObserver, User::Leave( KErrTotalLossOfPrecision ) );
       
  2118         iRtpObserver->ResetSessionInObserving( iSessionArray[ index ] );
       
  2119         }
       
  2120 
       
  2121     // flag prevents wrong handling after SessionStateChanged -callback
       
  2122     iSessionUpdateOngoing = ETrue;
       
  2123 
       
  2124     // sets MMF priorities and sets codec specific settings
       
  2125     CheckStreamsL( *voipProfiles[ 0 ], aUpdatedSession, keepAliveTime,
       
  2126                    iSessionUpdateOngoing );
       
  2127     CleanupStack::PopAndDestroy( 2, reg );
       
  2128     
       
  2129     SVPDEBUG1( "CSVPController::UpdateSessionL - Checked" )
       
  2130     
       
  2131     aUpdatedSession.UpdateL();
       
  2132     SVPDEBUG1( "CSVPController::UpdateSessionL Out" )
       
  2133     }
       
  2134 
       
  2135 // ---------------------------------------------------------------------------
       
  2136 // CSVPController::IncomingRefer
       
  2137 // ---------------------------------------------------------------------------
       
  2138 //			
       
  2139 void CSVPController::IncomingRefer( CMceInRefer* aRefer,
       
  2140         const TDesC8& aReferTo, TMceTransactionDataContainer* aContainer )
       
  2141     {
       
  2142     SVPDEBUG1( "CSVPController::IncomingRefer In" )
       
  2143     
       
  2144     // IncomingReferHandlerL is used to handle possible leave 
       
  2145     SVPDEBUG1( "CSVPController::IncomingRefer IncomingReferHandlerL" )
       
  2146     TRAPD( err, IncomingReferHandlerL( aRefer, aReferTo, aContainer ) );
       
  2147     
       
  2148     if ( err )
       
  2149         {
       
  2150         SVPDEBUG2("CSVPController::IncomingRefer: err: %d", err )
       
  2151         // TRAP is used because of RejectL might leave.
       
  2152         TRAP( err, aRefer->RejectL() );
       
  2153         
       
  2154         if ( err )
       
  2155             {
       
  2156             SVPDEBUG2("CSspController::IncomingRefer: RejectL err: %d", err )
       
  2157             }
       
  2158         }
       
  2159     
       
  2160     SVPDEBUG1( "CSVPController::IncomingRefer Out" )
       
  2161     }
       
  2162 
       
  2163 // ---------------------------------------------------------------------------
       
  2164 // CSVPController::IncomingReferHandlerL
       
  2165 // ---------------------------------------------------------------------------
       
  2166 //			
       
  2167 void CSVPController::IncomingReferHandlerL( CMceInRefer* aRefer,
       
  2168         const TDesC8& aReferTo, TMceTransactionDataContainer* aContainer )
       
  2169     {
       
  2170     SVPDEBUG1( "CSVPController::IncomingReferHandlerL In" )
       
  2171     
       
  2172     __ASSERT_ALWAYS( aRefer, User::Leave( KErrArgument ) );
       
  2173     
       
  2174     iContainer = *aContainer;
       
  2175     TInt sessionIndex = FindSVPSession( *aRefer->AssociatedSession() );
       
  2176     
       
  2177     if ( KErrNotFound != sessionIndex )    
       
  2178         {
       
  2179         SVPDEBUG2( "CSVPController::InRefHL: AssoSes OK,ind=%d",
       
  2180                 sessionIndex )
       
  2181         
       
  2182         iSessionArray[ sessionIndex ]->IncomingReferL( 
       
  2183                 aRefer, aReferTo, aContainer );
       
  2184         
       
  2185         if ( iSessionArray[ sessionIndex ]->IsAttended() )
       
  2186             {
       
  2187             SVPDEBUG1( "CSVPController::InRefHL: - Attended case" )
       
  2188             }
       
  2189         else
       
  2190             {
       
  2191             SVPDEBUG1( "CSVPController::InRefHL: - Unattended case" )
       
  2192             // Create a new session
       
  2193             CreateNewTransferSessionL( sessionIndex, EFalse );
       
  2194             }
       
  2195         }
       
  2196     else
       
  2197         {
       
  2198         SVPDEBUG1( "CSVPController::InRefHL: Session not Found!!" )
       
  2199         User::Leave( KErrNotFound );
       
  2200         }
       
  2201     
       
  2202     SVPDEBUG1( "CSVPController::IncomingReferHandlerL Out" ) 
       
  2203     }
       
  2204 
       
  2205 // ---------------------------------------------------------------------------
       
  2206 // CSVPController::CreateNewTransferSessionL
       
  2207 // ---------------------------------------------------------------------------
       
  2208 //
       
  2209 void CSVPController::CreateNewTransferSessionL( TInt aSessionIndex,
       
  2210         TBool aAttended )
       
  2211     {
       
  2212     SVPDEBUG1( "CSVPController::CreateNewTransferSessionL In" )
       
  2213 
       
  2214     iIncomingReferCallIndex = aSessionIndex;
       
  2215     // Create a new session
       
  2216     // fetch SIP profile ID from VoIP profiles
       
  2217     RPointerArray< CRCSEProfileEntry > entryArray;
       
  2218     CleanupResetAndDestroy<
       
  2219         RPointerArray<CRCSEProfileEntry> >::PushL( entryArray ); //CS: 1
       
  2220     
       
  2221     CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC(); //CS:2
       
  2222 
       
  2223     const CCCPCallParameters& callParams = iSessionArray[ aSessionIndex ]->Parameters();
       
  2224     SVPDEBUG2(" CSVPController::CNTSL: iServiceId = %d", callParams.ServiceId() )
       
  2225 
       
  2226     // Get VoIP profile by service id
       
  2227     reg->FindByServiceIdL( callParams.ServiceId(), entryArray );
       
  2228     // Take first entry from array
       
  2229     CRCSEProfileEntry* entry = entryArray[0];
       
  2230     
       
  2231     // array for provisioned data
       
  2232     CDesC8ArrayFlat* userAgentHeaders = new( ELeave )CDesC8ArrayFlat( 4 );
       
  2233     CleanupStack::PushL( userAgentHeaders );
       
  2234     
       
  2235     // variable for storing security status
       
  2236     TUint32 securityStatus = 0;
       
  2237     
       
  2238     // set provisioning data
       
  2239     SVPDEBUG1( "CSVPController::CNTSL: Set provisioning data..." )
       
  2240     TRAP_IGNORE( iSVPUtility->SetProvisioningDataL( 
       
  2241                                 *entry, 
       
  2242                                 *userAgentHeaders,
       
  2243                                 securityStatus,
       
  2244                                 iTerminalType,
       
  2245                                 iWlanMacAddress ) );
       
  2246     
       
  2247     // only one sip profile per voip profile
       
  2248     TInt sipProfileId = entry->iIds[ 0 ].iProfileId; 
       
  2249     SVPDEBUG2( "CSVPController::CNTSL: sipProfileId=%d", sipProfileId )
       
  2250     
       
  2251     if ( KSVPStatusNonSecure != securityStatus )
       
  2252         {
       
  2253         // If preferred sec is 1 or 2, we check also secure mechanism of sip profile.
       
  2254         // create SIP and ProfileRegistry for URI handling
       
  2255         CSIP* sip = CSIP::NewL( KSVPUid, *this );
       
  2256         CleanupStack::PushL( sip );
       
  2257         SVPDEBUG1( "CSVPController::CNTSL: sip CREATED" )
       
  2258         
       
  2259         CSIPProfileRegistry* sipProfileRegistry = 
       
  2260             CSIPProfileRegistry::NewL( *sip, *this );
       
  2261         CleanupStack::PushL( sipProfileRegistry );
       
  2262 
       
  2263         SVPDEBUG1( "CSVPController::CNTSL: sipProfileRegistry CREATED" )
       
  2264         
       
  2265         // retrieve SIP profile by using sip profile id
       
  2266         CSIPProfile* profile = sipProfileRegistry->ProfileL( sipProfileId );
       
  2267         CleanupStack::PushL( profile );
       
  2268 
       
  2269         // set secure status to 0 if no security mechanism found from SIP profile
       
  2270         iSVPUtility->ResolveSecurityMechanismL( *profile, securityStatus );
       
  2271 
       
  2272         CleanupStack::PopAndDestroy( 3, sip );  // profile, sipProfileRegistry, sip
       
  2273         }
       
  2274     
       
  2275     // set transfer data
       
  2276     SVPDEBUG1( "CSVPController::CNTSL: Set transfer data..." )
       
  2277     iSessionArray[ aSessionIndex ]->SetTransferDataL(
       
  2278             userAgentHeaders, securityStatus );
       
  2279     
       
  2280     SVPDEBUG3( "CSVPController::CNTSL: Header count:%d, sec status:%d",
       
  2281             userAgentHeaders->Count(), securityStatus )
       
  2282     
       
  2283     CSVPMoSession* moSessionTemp = NULL;
       
  2284     
       
  2285     // In attended and unattended transfer case recipient is solved here
       
  2286     SVPDEBUG1( "CSVPController::CNTSL: (Un)Attended, create new mo session" )
       
  2287     const TDesC& referTo = iSessionArray[ aSessionIndex ]->TransferTarget();
       
  2288     // "convert" recpient to 8-bit format
       
  2289     HBufC8* recipient = HBufC8::NewLC( referTo.Length() );
       
  2290     recipient->Des().Copy( referTo );
       
  2291     
       
  2292     moSessionTemp = CSVPMoSession::NewL( *iMceManager,
       
  2293                                          *recipient,
       
  2294                                          *entry, 
       
  2295                                          callParams,
       
  2296                                          iContainer,
       
  2297                                          *this,
       
  2298                                          *iSVPUtility,
       
  2299                                          *iRtpObserver,
       
  2300                                          securityStatus,
       
  2301                                          userAgentHeaders );
       
  2302     
       
  2303     CleanupStack::PopAndDestroy( recipient );
       
  2304     CleanupStack::PushL( moSessionTemp );
       
  2305     
       
  2306     // dtmf and rtp observervers are set
       
  2307     moSessionTemp->SetDtmfObserver( iSessionArray[ aSessionIndex ]->DtmfObserver() );
       
  2308     iRtpObserver->AddSessionForObservingL( moSessionTemp );
       
  2309     
       
  2310     // created SVP session is appended to session array
       
  2311     iSessionArray.AppendL( moSessionTemp );
       
  2312     CleanupStack::Pop( moSessionTemp );
       
  2313     CleanupStack::Pop( userAgentHeaders );
       
  2314     CleanupStack::PopAndDestroy( 2, &entryArray );
       
  2315     
       
  2316     // set CCP session observer to SVP session
       
  2317     SVPDEBUG1( "CSVPController::CNTSL: AddObserverL" )
       
  2318     moSessionTemp->AddObserverL( iSessionArray[ aSessionIndex ]->GetCCPSessionObserver() );
       
  2319     
       
  2320     //set CCP supplementary services events observer to SVP session
       
  2321     SVPDEBUG1( "CSVPController::CNTSL: AddSsObserverL" )
       
  2322     moSessionTemp->SetSsObserver( iSessionArray[ aSessionIndex ]->GetSsObserver() );
       
  2323         
       
  2324     SVPDEBUG1( "CSVPController::CNTSL: callcreated, send to CCP" )
       
  2325     ExecCbCallCreated( moSessionTemp, iSessionArray[ aSessionIndex ], aAttended );
       
  2326     
       
  2327     SVPDEBUG1( "CSVPController::CreateNewTransferSessionL Out" )
       
  2328     }
       
  2329 
       
  2330 // ---------------------------------------------------------------------------
       
  2331 // CSVPController::HandleForwardEvent
       
  2332 // ---------------------------------------------------------------------------
       
  2333 // 
       
  2334 void CSVPController::HandleCallForward( TInt aStatusCode,
       
  2335         TInt aSessionIndex, TMceTransactionDataContainer* aContainer )
       
  2336     {
       
  2337     SVPDEBUG1( "CSVPController::HandleForwardEvent In" )
       
  2338     SVPDEBUG2( "CSVPController::HandleForwardEvent aStatusCode=%d", aStatusCode )
       
  2339     
       
  2340     if ( !iSessionArray[ aSessionIndex ]->IsMobileOriginated() )
       
  2341         {
       
  2342         iSessionArray[ aSessionIndex ]->
       
  2343             GetCCPSessionObserver().ErrorOccurred( ECCPErrorNotReached, 
       
  2344                                               iSessionArray[ aSessionIndex ] );
       
  2345         }
       
  2346     else
       
  2347         {
       
  2348         CSVPMoSession* session = static_cast< CSVPMoSession* >(
       
  2349                 iSessionArray[ aSessionIndex ] );
       
  2350         
       
  2351         switch ( aStatusCode )
       
  2352             {
       
  2353             case KSVPMultipleChoicesVal:    // 300
       
  2354             case KSVPMovedPermanentlyVal:   // 301
       
  2355                 {
       
  2356                 // Get contact headers and notify
       
  2357                 TInt count = CheckContactData( session, aContainer );
       
  2358 
       
  2359                 if ( 0 < count )
       
  2360                     {
       
  2361                     session->NotifyForwardEvent( aStatusCode );
       
  2362                     }
       
  2363                 else
       
  2364                     {
       
  2365                     session->GetCCPSessionObserver().ErrorOccurred( 
       
  2366                                                         ECCPErrorNotReached,
       
  2367                                                         session );
       
  2368                     }
       
  2369                 break;
       
  2370                 }
       
  2371             case KSVPMovedTemporarilyVal:   // 302
       
  2372                 {
       
  2373                 // Just notify, this call forward is handled automatically by mce
       
  2374                 session->NotifyForwardEvent( aStatusCode );
       
  2375                 session->GetCCPSessionObserver().
       
  2376                     CallStateChanged( MCCPCallObserver::ECCPStateForwarding,
       
  2377                                       session );
       
  2378                 break;
       
  2379                 }
       
  2380             default:
       
  2381                 {
       
  2382                 SVPDEBUG1( "CSVPController::HandleForwardEvent: unknown code" )
       
  2383                 session->GetCCPSessionObserver().ErrorOccurred( 
       
  2384                                                     ECCPErrorNotReached,
       
  2385                                                     session );
       
  2386                 }
       
  2387             }
       
  2388         }
       
  2389     
       
  2390     SVPDEBUG1( "CSVPController::HandleForwardEvent Out" )
       
  2391     }
       
  2392 
       
  2393 // ---------------------------------------------------------------------------
       
  2394 // CSVPController::StreamStateChanged
       
  2395 // ---------------------------------------------------------------------------
       
  2396 //			
       
  2397 void CSVPController::StreamStateChanged( CMceMediaStream& aStream )
       
  2398     {
       
  2399     SVPDEBUG1("CSVPController::StreamStateChanged In" )
       
  2400     
       
  2401     if ( &aStream )
       
  2402         {
       
  2403         if ( !iEmergencySession )
       
  2404             {
       
  2405             const TInt index = FindSVPSession( *aStream.Session() );
       
  2406             if ( KErrNotFound != index )
       
  2407                 {
       
  2408                 iSessionArray[ index ]->HandleStreamStateChange( aStream );
       
  2409                 }
       
  2410                 
       
  2411             SVPDEBUG2( "CSVPController::StreamStateChanged index: %d", index )
       
  2412             }
       
  2413         else // Emergency session
       
  2414             {
       
  2415             iEmergencySession->StreamStateChanged( aStream );
       
  2416             }
       
  2417         }
       
  2418     else
       
  2419         {
       
  2420         SVPDEBUG1( "CSVPController::StreamStateChanged, faulty arguments" )
       
  2421         }
       
  2422     
       
  2423     SVPDEBUG1("CSVPController::StreamStateChanged Out" )
       
  2424     }
       
  2425 
       
  2426 // ---------------------------------------------------------------------------
       
  2427 // CSVPController::StreamStateChanged
       
  2428 // ---------------------------------------------------------------------------
       
  2429 //
       
  2430 void CSVPController::StreamStateChanged( CMceMediaStream& aStream,
       
  2431     CMceMediaSink& aSink )
       
  2432     {
       
  2433     SVPDEBUG1( "CSVPController::StreamStateChanged SINK In" )
       
  2434     
       
  2435     if ( &aStream && &aSink )
       
  2436         {
       
  2437         SVPDEBUG2( "CSVPController::StreamStateChanged SINK Stream State: %d", aStream.State() )
       
  2438         SVPDEBUG2( "CSVPController::StreamStateChanged SINK Sink IsEnabled: %d", aSink.IsEnabled() )
       
  2439         
       
  2440         if ( !iEmergencySession )
       
  2441             {
       
  2442             const TInt index = FindSVPSession( *aStream.Session() );
       
  2443             
       
  2444             if ( KErrNotFound != index )
       
  2445                 {
       
  2446                 iSessionArray[ index ]->HandleStreamStateChange( aStream, aSink );
       
  2447                 }
       
  2448             
       
  2449             SVPDEBUG2( "CSVPController::StreamStateChanged SINK index: %d", index )
       
  2450             }
       
  2451         else // Emergency session
       
  2452             {
       
  2453             iEmergencySession->StreamStateChanged( aStream );
       
  2454             }
       
  2455         }
       
  2456     else
       
  2457         {
       
  2458         SVPDEBUG1( "CSVPController::StreamStateChanged SINK, faulty arguments" )
       
  2459         }
       
  2460     
       
  2461     SVPDEBUG1( "CSVPController::StreamStateChanged SINK Out" )
       
  2462     }
       
  2463 
       
  2464 // ---------------------------------------------------------------------------
       
  2465 // CSVPController::StreamStateChanged
       
  2466 // ---------------------------------------------------------------------------
       
  2467 //
       
  2468 void CSVPController::StreamStateChanged( CMceMediaStream& aStream,
       
  2469     CMceMediaSource& aSource )
       
  2470     {
       
  2471     SVPDEBUG1( "CSVPController::StreamStateChanged SOURCE In" )
       
  2472     
       
  2473     if ( &aStream && &aSource )
       
  2474         {
       
  2475         SVPDEBUG2( "CSVPController::StreamStateChanged SOURCE Stream State: %d", aStream.State() )
       
  2476         SVPDEBUG2( "CSVPController::StreamStateChanged SOURCE Source IsEnabled: %d", aSource.IsEnabled() )
       
  2477 
       
  2478         if ( !iEmergencySession )
       
  2479             {
       
  2480             const TInt index = FindSVPSession( *aStream.Session() );           
       
  2481             if ( KErrNotFound != index )
       
  2482                 {
       
  2483                 iSessionArray[ index ]->HandleStreamStateChange( aStream, aSource );
       
  2484                 }
       
  2485             
       
  2486             SVPDEBUG2( "CSVPController::StreamStateChanged SOURCE index: %d", index )
       
  2487             }
       
  2488         else // Emergency session
       
  2489             {
       
  2490             iEmergencySession->StreamStateChanged( aStream );
       
  2491             }        
       
  2492         
       
  2493         }
       
  2494     
       
  2495     SVPDEBUG1( "CSVPController::StreamStateChanged SOURCE Out" )
       
  2496     }
       
  2497 
       
  2498 
       
  2499 // from ConvergedCallProvider
       
  2500 // ---------------------------------------------------------------------------
       
  2501 // CSVPController::NewEmergencyCallL
       
  2502 // ---------------------------------------------------------------------------
       
  2503 //
       
  2504 MCCPEmergencyCall* CSVPController::NewEmergencyCallL( 
       
  2505     const TUint32 /*aServiceId*/,
       
  2506     const TDesC&  aAddress, 
       
  2507     const MCCPCallObserver& aObserver )                                            
       
  2508     {
       
  2509     SVPDEBUG1( "CSVPController::NewEmergencyCallL In" )
       
  2510     
       
  2511     // Retrieve available VoIP and IAP IDs
       
  2512     if ( 0 == iEmergencyProfileIds.Count() && 0 == iEmergencyIapIds.Count() )
       
  2513         {
       
  2514         CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC(); // CS:1
       
  2515         CSIP* sip = CSIP::NewLC( KSVPUid, *this ); // CS:2
       
  2516         CSIPProfileRegistry* sipProfileRegistry = CSIPProfileRegistry::NewLC( 
       
  2517             *sip, *this ); // CS:3
       
  2518         
       
  2519         // Get all VoIP profile IDs into an array
       
  2520         RArray< TUint32 > voipProfileIds;
       
  2521         CleanupClosePushL( voipProfileIds );    //CS: 4
       
  2522         reg->GetAllIdsL( voipProfileIds );
       
  2523     
       
  2524         // Sort the VoIP profile array so that registered profiles are first
       
  2525         for ( TInt i = 0; i < voipProfileIds.Count(); i++ )
       
  2526             {
       
  2527             TBool registered( EFalse );
       
  2528             CRCSEProfileEntry* entry = CRCSEProfileEntry::NewLC(); // CS:5
       
  2529             reg->FindL( voipProfileIds[i], *entry );
       
  2530             // There is only one (or zero) SIP profile per VoIP profile.
       
  2531             // If profileId is not found,
       
  2532             // CSVPEmergencySession::ConstructL will handle the error
       
  2533             if ( 0 < entry->iIds.Count() )
       
  2534                 {
       
  2535                 SVPDEBUG2( "CSVPController::NewEmergencyCallL, SIP Id count:%d",
       
  2536                         entry->iIds.Count() )
       
  2537                 CSIPProfile* sipProfile = sipProfileRegistry->ProfileL( 
       
  2538                     entry->iIds[0].iProfileId );
       
  2539                 sipProfile->GetParameter( KSIPProfileRegistered, registered );
       
  2540                 delete sipProfile;
       
  2541                 }
       
  2542             CleanupStack::PopAndDestroy( entry ); // CS:4
       
  2543             if ( registered )
       
  2544                 {
       
  2545                 // Move registered VoIP profile IDs to the front
       
  2546                 iEmergencyProfileIds.Insert( voipProfileIds[i], 0 );
       
  2547                 }
       
  2548             else
       
  2549                 {
       
  2550                 iEmergencyProfileIds.Append( voipProfileIds[i] );
       
  2551                 }
       
  2552             }
       
  2553         
       
  2554         CleanupStack::PopAndDestroy( 4, reg ); 
       
  2555         // CS:0 voipProfileIds, sipProfileRegistry, sip, reg
       
  2556         
       
  2557         // Request and wait for IAP IDs
       
  2558         CSVPEmergencyIapProvider* iapProvider = 
       
  2559             CSVPEmergencyIapProvider::NewLC( 
       
  2560             CActive::EPriorityStandard ); // CS:1
       
  2561         iapProvider->RequestIapIds( iEmergencyIapIds );
       
  2562         CleanupStack::PopAndDestroy( iapProvider ); // CS:0
       
  2563         }
       
  2564     
       
  2565     SVPDEBUG2("CSVPController::NewEmergencyCallL, VoIP count:%d", 
       
  2566             iEmergencyProfileIds.Count() )
       
  2567     SVPDEBUG2("CSVPController::NewEmergencyCallL, IAP count:%d", 
       
  2568             iEmergencyIapIds.Count() )
       
  2569     
       
  2570     // Define last try
       
  2571     TBool isLastId( EFalse );
       
  2572     
       
  2573     if ( ( 0 == iEmergencyProfileIds.Count() && 
       
  2574            1 == iEmergencyIapIds.Count() ) ||
       
  2575          ( 1 == iEmergencyProfileIds.Count() && 
       
  2576            0 == iEmergencyIapIds.Count() )
       
  2577        )
       
  2578         {
       
  2579         isLastId = ETrue;
       
  2580         SVPDEBUG1("CSVPController::NewEmergencyCallL, last ID");
       
  2581         }
       
  2582     
       
  2583     // Create session
       
  2584     CSVPEmergencySession* emergencySession = NULL;
       
  2585     
       
  2586     if ( iEmergencyProfileIds.Count() )
       
  2587         {
       
  2588         // Create emergency session with VoIP ID
       
  2589         TRAPD( err, emergencySession = CSVPEmergencySession::NewL( 
       
  2590             *iMceManager,
       
  2591             iEmergencyProfileIds[0], 
       
  2592             aAddress,
       
  2593             aObserver,
       
  2594             *iSVPUtility, 
       
  2595             isLastId ) )
       
  2596     
       
  2597         if ( err )
       
  2598             {
       
  2599             // Create dummy session for session release
       
  2600             emergencySession = CSVPEmergencySession::NewL( 
       
  2601                 *iMceManager,
       
  2602                 iEmergencyProfileIds[0], 
       
  2603                 aAddress,
       
  2604                 aObserver,
       
  2605                 *iSVPUtility, 
       
  2606                 isLastId, 
       
  2607                 ETrue );   
       
  2608             }
       
  2609         
       
  2610         // Update profile array
       
  2611         iEmergencyProfileIds.Remove( 0 );
       
  2612         }
       
  2613     else if ( iEmergencyIapIds.Count() )
       
  2614         {
       
  2615         // Create emergency session with IAP ID
       
  2616         TRAPD( err, emergencySession = CSVPEmergencySession::NewL( 
       
  2617             *iMceManager,
       
  2618             aAddress,
       
  2619             aObserver,
       
  2620             *iSVPUtility,
       
  2621             iEmergencyIapIds[0],  
       
  2622             isLastId ) )
       
  2623     
       
  2624         if ( err )
       
  2625             {
       
  2626             // Create dummy session for session release
       
  2627             emergencySession = CSVPEmergencySession::NewL( 
       
  2628                 *iMceManager,
       
  2629                 aAddress,
       
  2630                 aObserver,
       
  2631                 *iSVPUtility, 
       
  2632                 iEmergencyIapIds[0], 
       
  2633                 isLastId, 
       
  2634                 ETrue );   
       
  2635             }        
       
  2636         
       
  2637         // Update IAP array
       
  2638         iEmergencyIapIds.Remove( 0 );
       
  2639         }
       
  2640     else
       
  2641         {
       
  2642         User::Leave( KErrNotFound );
       
  2643         }
       
  2644     
       
  2645     // save emergency session to controller
       
  2646     iEmergencySession = emergencySession;
       
  2647     
       
  2648     if ( iCCPDtmfObserver )
       
  2649             {
       
  2650             SVPDEBUG1( "CSVPController::NewEmergencyCallL setting DTMFObserver" )
       
  2651             iEmergencySession->SetDtmfObserver( *iCCPDtmfObserver );
       
  2652             }
       
  2653     
       
  2654     SVPDEBUG1( "CSVPController::NewEmergencyCallL Out" )
       
  2655     // return pointer to CCP emergency call object
       
  2656     return emergencySession;
       
  2657     }
       
  2658                         
       
  2659 // ---------------------------------------------------------------------------
       
  2660 // CSVPController::NewConferenceL
       
  2661 // ---------------------------------------------------------------------------
       
  2662 //
       
  2663 MCCPConferenceCall* CSVPController::NewConferenceL( 
       
  2664         const TUint32 /* aServiceId */, 
       
  2665         const MCCPConferenceCallObserver& /*aObserver*/ )
       
  2666     {
       
  2667     return NULL;
       
  2668     }
       
  2669     
       
  2670 // ---------------------------------------------------------------------------
       
  2671 // CSVPController::AcceptTransfer
       
  2672 // ---------------------------------------------------------------------------
       
  2673 //                 
       
  2674 void CSVPController::AcceptTransfer( TBool /*aAccept*/ ) 
       
  2675     {
       
  2676     SVPDEBUG1( "CSVPController::AcceptTransfer In" )
       
  2677     SVPDEBUG1( "CSVPController::AcceptTransfer Out" )
       
  2678     }
       
  2679 
       
  2680 // ---------------------------------------------------------------------------
       
  2681 // CSVPController::ForwardCallToAddressL
       
  2682 // ---------------------------------------------------------------------------
       
  2683 //
       
  2684 TInt CSVPController::ForwardCallToAddressL( const TInt /*aIndex*/ ) 
       
  2685     {
       
  2686     return NULL;
       
  2687     }
       
  2688     
       
  2689 // ---------------------------------------------------------------------------
       
  2690 // CSVPController::Caps
       
  2691 // ---------------------------------------------------------------------------
       
  2692 //
       
  2693 TUint32 CSVPController::Caps() const
       
  2694     {
       
  2695     return 0;
       
  2696     }
       
  2697 
       
  2698 // ---------------------------------------------------------------------------
       
  2699 // CSVPController::DTMFProvider
       
  2700 // ---------------------------------------------------------------------------
       
  2701 //
       
  2702 MCCPDTMFProvider* CSVPController::DTMFProviderL(
       
  2703     const MCCPDTMFObserver& aObserver )
       
  2704     {
       
  2705     SVPDEBUG1( "CSVPController::DTMFProviderL In" )
       
  2706     
       
  2707     iCCPDtmfObserver = &aObserver;
       
  2708     
       
  2709     TInt sessions = iSessionArray.Count();
       
  2710     while ( sessions )
       
  2711         {
       
  2712         sessions--;
       
  2713         iSessionArray[ sessions ]->SetDtmfObserver( aObserver );
       
  2714         
       
  2715         SVPDEBUG2( "CSVPController::DTMFProviderL sessions: %d", sessions )
       
  2716         }
       
  2717     
       
  2718     if ( iEmergencySession )
       
  2719         {
       
  2720         iEmergencySession->SetDtmfObserver( aObserver );
       
  2721         }
       
  2722     
       
  2723     SVPDEBUG1( "CSVPController::DTMFProviderL Out" )
       
  2724     return this;
       
  2725     }
       
  2726 
       
  2727 
       
  2728 // ---------------------------------------------------------------------------
       
  2729 // CSVPController::ExtensionProvider
       
  2730 // ---------------------------------------------------------------------------
       
  2731 //
       
  2732 MCCPExtensionProvider* CSVPController::ExtensionProviderL( 
       
  2733     const MCCPExtensionObserver& /*aObserver*/ )
       
  2734     {
       
  2735     return NULL;
       
  2736     }
       
  2737   
       
  2738 // dtmf provider
       
  2739 
       
  2740 // ---------------------------------------------------------------------------
       
  2741 // CSVPController::CancelDtmfStringSending
       
  2742 // ---------------------------------------------------------------------------
       
  2743 //
       
  2744 TInt CSVPController::CancelDtmfStringSending()
       
  2745     {
       
  2746     SVPDEBUG1( "CSVPController::CancelDtmfStringSending In" )
       
  2747     
       
  2748     TInt err( KErrNotSupported ); 
       
  2749     // find active session
       
  2750     
       
  2751     TInt sesCount = iSessionArray.Count();
       
  2752     CSVPSessionBase* session = NULL;
       
  2753     while ( sesCount )
       
  2754         {
       
  2755         sesCount--;
       
  2756         session = iSessionArray[ sesCount ];
       
  2757         
       
  2758         if ( SVPAudioUtility::DtmfActionCapableSession( *session ) )
       
  2759             {
       
  2760             err = session->CancelDtmfStringSending();
       
  2761             }
       
  2762         SVPDEBUG3( "CSVPController::CancelDtmfStringSending sesCount: %d, err: %d",
       
  2763                      sesCount, err )
       
  2764         session = NULL;
       
  2765         }
       
  2766     
       
  2767     if ( iEmergencySession && 
       
  2768          SVPAudioUtility::DtmfActionCapableSession( *iEmergencySession ) )
       
  2769         {
       
  2770         err = iEmergencySession->CancelDtmfStringSending();
       
  2771         }
       
  2772         
       
  2773     SVPDEBUG2("CSVPController::CancelDtmfStringSending Out return=%d", err )
       
  2774     iDtmfStringSending = EFalse;
       
  2775     iFirstDtmfSent = EFalse;
       
  2776     return err;
       
  2777     }
       
  2778 
       
  2779 // ---------------------------------------------------------------------------
       
  2780 // CSVPController::StartDtmfTone
       
  2781 // ---------------------------------------------------------------------------
       
  2782 //
       
  2783 TInt CSVPController::StartDtmfTone( const TChar aTone )
       
  2784     {
       
  2785     SVPDEBUG1( "CSVPController::StartDtmfTone In" )
       
  2786     
       
  2787     TInt err( KErrNotSupported );
       
  2788     
       
  2789     // Save DTMF tone for later use in outband dtmf start/stop events
       
  2790     iDtmfTone = aTone;
       
  2791     // Send the tone to all sessions, but check mute and hold cases where session must
       
  2792     // be in 'connected' state in order to send DTMF's. Session will then
       
  2793     // discriminate between inband and outband DTMF's.
       
  2794     TInt sesCount = iSessionArray.Count();
       
  2795     CSVPSessionBase* session = NULL;
       
  2796     while ( sesCount )
       
  2797         {
       
  2798         sesCount--;
       
  2799         session = iSessionArray[ sesCount ];
       
  2800         // Checking hold and mute status
       
  2801         if ( SVPAudioUtility::DtmfActionCapableSession( *session ) &&
       
  2802                 !session->IsSessionMuted()  )
       
  2803             {
       
  2804             err = session->StartDtmfTone( aTone );
       
  2805             }
       
  2806         SVPDEBUG3( "CSVPController::StartDtmfTone sesCount: %d, err: %d",
       
  2807                       sesCount, err )
       
  2808         session = NULL;
       
  2809         }
       
  2810     
       
  2811     if ( iEmergencySession && 
       
  2812          SVPAudioUtility::DtmfActionCapableSession( *iEmergencySession ) )
       
  2813         {
       
  2814         err = iEmergencySession->StartDtmfTone( aTone );
       
  2815         }
       
  2816     
       
  2817     SVPDEBUG2("CSVPController::StartDtmfTone Out return=%d", err )
       
  2818     return err;
       
  2819     }
       
  2820 
       
  2821 // ---------------------------------------------------------------------------
       
  2822 // CSVPController::StopDtmfTone
       
  2823 // ---------------------------------------------------------------------------
       
  2824 //
       
  2825 TInt CSVPController::StopDtmfTone()
       
  2826     {
       
  2827     SVPDEBUG1( "CSVPController::StopDtmfTone In" )
       
  2828     
       
  2829     TInt err( KErrNotSupported );
       
  2830     
       
  2831     TInt sesCount = iSessionArray.Count();
       
  2832     CSVPSessionBase* session = NULL;
       
  2833     while ( sesCount )
       
  2834         {
       
  2835         sesCount--;
       
  2836         session = iSessionArray[ sesCount ];
       
  2837         
       
  2838         if ( SVPAudioUtility::DtmfActionCapableSession( *session ) )
       
  2839             {
       
  2840             err = session->StopDtmfTone();
       
  2841             }
       
  2842         SVPDEBUG3( "CSVPController::StopDtmfTone sesCount: %d, err: %d",
       
  2843                      sesCount, err )
       
  2844         session = NULL;
       
  2845         }
       
  2846 
       
  2847     if ( iEmergencySession && 
       
  2848          SVPAudioUtility::DtmfActionCapableSession( *iEmergencySession ) )
       
  2849         {
       
  2850         err = iEmergencySession->StopDtmfTone();
       
  2851         }
       
  2852 
       
  2853     SVPDEBUG2("CSVPController::StopDtmfTone Out return=%d", err )
       
  2854     return err;
       
  2855     }
       
  2856 
       
  2857 // ---------------------------------------------------------------------------
       
  2858 // CSVPController::SendDtmfToneString
       
  2859 // ---------------------------------------------------------------------------
       
  2860 //
       
  2861 TInt CSVPController::SendDtmfToneString( const TDesC& aString )
       
  2862     {
       
  2863     SVPDEBUG1( "CSVPController::SendDtmfToneString In" )
       
  2864     
       
  2865     TInt err( KErrNotSupported );
       
  2866     
       
  2867     delete iDtmfString;
       
  2868     iDtmfString = NULL;
       
  2869     TRAPD( errBuf, iDtmfString = HBufC::NewL( aString.Length() ) );
       
  2870     if ( KErrNone != errBuf )
       
  2871         {
       
  2872         return errBuf;
       
  2873         }
       
  2874     // Take local copy of the dtmf string to be sent
       
  2875     // This is needed for outband dtmf sequence start/stop event
       
  2876     *iDtmfString = aString;
       
  2877     iDtmfStringLex.Assign( *iDtmfString );
       
  2878     
       
  2879     TInt sesCount = iSessionArray.Count();
       
  2880     CSVPSessionBase* session = NULL;
       
  2881 
       
  2882     while ( sesCount )
       
  2883         {
       
  2884         sesCount--;
       
  2885         session = iSessionArray[ sesCount ];
       
  2886         // Checking hold and mute status
       
  2887         if ( SVPAudioUtility::DtmfActionCapableSession( *session ) &&
       
  2888              !session->IsSessionMuted() )
       
  2889             {
       
  2890             err = session->SendDtmfToneString( aString );
       
  2891             if ( KErrNone == err )
       
  2892                 {
       
  2893                 iDtmfStringSending = ETrue;
       
  2894                 iFirstDtmfSent = EFalse;
       
  2895                 }
       
  2896             }
       
  2897         SVPDEBUG3( "CSVPController::SendDtmfToneString sesCount: %d, err: %d",
       
  2898                      sesCount, err )
       
  2899         session = NULL;
       
  2900         }
       
  2901     
       
  2902     if ( iEmergencySession )
       
  2903         {
       
  2904         if ( SVPAudioUtility::DtmfActionCapableSession( *iEmergencySession ) )
       
  2905             {
       
  2906             err = iEmergencySession->SendDtmfToneString( aString );
       
  2907             }
       
  2908         iDtmfStringSending = ETrue;
       
  2909         iFirstDtmfSent = EFalse;        
       
  2910         }
       
  2911 
       
  2912     SVPDEBUG2("CSVPController::SendDtmfToneString Out return=%d", err )
       
  2913     return err;
       
  2914     }
       
  2915 
       
  2916 // ---------------------------------------------------------------------------
       
  2917 // CSVPController::ContinueDtmfStringSending
       
  2918 // ---------------------------------------------------------------------------
       
  2919 //
       
  2920 TInt CSVPController::ContinueDtmfStringSending( const TBool /*aContinue*/ )
       
  2921     {
       
  2922     // SVP sessionbase used to implement this as only returning
       
  2923     // KErrNotSupported, so why not accept the situation here and just
       
  2924     // return KErrNotSupported.
       
  2925     
       
  2926     SVPDEBUG1( "CSVPController::ContinueDtmfStringSending KErrNotSupported" )
       
  2927     return KErrNotSupported;
       
  2928     }
       
  2929 
       
  2930 // ---------------------------------------------------------------------------
       
  2931 // CSVPController::AddObserverL
       
  2932 // ---------------------------------------------------------------------------
       
  2933 //   
       
  2934 void CSVPController::AddObserverL( const MCCPDTMFObserver& /*aObserver*/ )
       
  2935     {
       
  2936     SVPDEBUG1( "CSVPController::AddObserverL MCCPDTMFObserver" )
       
  2937     }
       
  2938 
       
  2939 // ---------------------------------------------------------------------------
       
  2940 // CSVPController::RemoveObserver
       
  2941 // ---------------------------------------------------------------------------
       
  2942 //
       
  2943 TInt CSVPController::RemoveObserver( const MCCPDTMFObserver& /*aObserver*/ )
       
  2944     {
       
  2945     SVPDEBUG1( "CSVPController::RemoveObserver MCCPDTMFObserver" )
       
  2946     return KErrNotSupported;
       
  2947     }
       
  2948 
       
  2949   
       
  2950 // refer observer
       
  2951   
       
  2952 // ---------------------------------------------------------------------------
       
  2953 // CSVPController::ReferStateChanged
       
  2954 // ---------------------------------------------------------------------------
       
  2955 //
       
  2956 void CSVPController::ReferStateChanged( CMceRefer& aRefer,
       
  2957         TMceTransactionDataContainer* aContainer )
       
  2958     {
       
  2959     SVPDEBUG1( "CSVPController::ReferStateChanged In" )
       
  2960     
       
  2961     iContainer = *aContainer;
       
  2962     TInt ind = KErrNotFound;
       
  2963 
       
  2964     // loop session array and check refer
       
  2965     for ( TInt s = 0; s < iSessionArray.Count() && 
       
  2966           KErrNotFound == ind; s++ )
       
  2967         { 
       
  2968         if ( iSessionArray[ s ]->IsMceRefer( aRefer ) )
       
  2969             {
       
  2970             ind = s;
       
  2971             } 
       
  2972         }
       
  2973 
       
  2974     if ( KErrNotFound != ind )
       
  2975         {
       
  2976         SVPDEBUG2(" CSVPController::ReferStateChanged ind: %d", ind );
       
  2977         TInt statusCode = iContainer.GetStatusCode();
       
  2978 
       
  2979         iSessionArray[ ind ]->ReferStateChanged( aRefer, statusCode );
       
  2980         }
       
  2981     
       
  2982     SVPDEBUG1( "CSVPController::ReferStateChanged Out" )
       
  2983     }
       
  2984 
       
  2985 // ---------------------------------------------------------------------------
       
  2986 // CSVPController::ReferConnectionStateChanged
       
  2987 // ---------------------------------------------------------------------------
       
  2988 //
       
  2989 void CSVPController::ReferConnectionStateChanged( CMceRefer& /*aRefer*/,
       
  2990         TBool /*aActive*/ )
       
  2991     {
       
  2992     SVPDEBUG1( "CSVPController::ReferConnectionStateChanged" )
       
  2993     }
       
  2994 
       
  2995 // ---------------------------------------------------------------------------
       
  2996 // CSVPController::Failed
       
  2997 // ---------------------------------------------------------------------------
       
  2998 //
       
  2999 #ifdef _DEBUG
       
  3000 void CSVPController::Failed( CMceRefer& /*aRefer*/, TInt aError )
       
  3001 #else
       
  3002 void CSVPController::Failed( CMceRefer& /*aRefer*/, TInt /*aError*/ )
       
  3003 #endif // _DEBUG
       
  3004     {
       
  3005     SVPDEBUG2( "CSVPController::Failed Refer failed with error: %d", aError )
       
  3006     }
       
  3007 
       
  3008 
       
  3009 // Mce DMTF observer
       
  3010 // ---------------------------------------------------------------------------
       
  3011 // CSVPController::DtmfToneReceived
       
  3012 // ---------------------------------------------------------------------------
       
  3013 //
       
  3014 void CSVPController::DtmfToneReceived( CMceSession& /*aSession*/,
       
  3015         CMceAudioStream& /*aStream*/, const TChar& /*aTone*/ )
       
  3016     {
       
  3017     // Not supported
       
  3018     SVPDEBUG1( "CSVPController:: DtmfToneReceived - Not supported" )
       
  3019     }
       
  3020     
       
  3021 // ---------------------------------------------------------------------------
       
  3022 // CSVPController::DtmfEventReceived
       
  3023 // ---------------------------------------------------------------------------
       
  3024 //
       
  3025 void CSVPController::DtmfEventReceived( CMceSession& aSession,
       
  3026                                         CMceAudioStream& /*aStream*/,
       
  3027                                         CMceMediaSource& /*aSource*/,
       
  3028                                         TMceDtmfEvent aEvent )
       
  3029     {
       
  3030     SVPDEBUG3( "CSVPController::DtmfEventReceived In, aEvent: %d, iDtmfStringSending: %d",
       
  3031                    aEvent, iDtmfStringSending )
       
  3032     
       
  3033     // find what session received the event
       
  3034     const TInt index = FindSVPSession( aSession );
       
  3035     
       
  3036     if ( KErrNotFound != index )
       
  3037         {
       
  3038          // match dtmf event
       
  3039         MCCPDTMFObserver::TCCPDtmfEvent dtmfEvent = 
       
  3040             iSVPUtility->GetDtmfEvent( aEvent, iDtmfStringSending );
       
  3041         
       
  3042         // dtmf string
       
  3043         if ( iDtmfStringSending ) 
       
  3044             { 
       
  3045             // only start event received from mce
       
  3046             // logic below needed so that stop events can be sent
       
  3047             if ( MCCPDTMFObserver::ECCPDtmfSequenceStart == dtmfEvent )
       
  3048                 {
       
  3049                 if ( !iFirstDtmfSent )
       
  3050                     {
       
  3051                     SVPDEBUG1( "CSVPController::DtmfEventReceived FIRST SEND" )
       
  3052                     
       
  3053                     // send start
       
  3054                     iFirstDtmfSent = ETrue;
       
  3055                      // call back event to application
       
  3056                     iSessionArray[ index ]->
       
  3057                         DtmfObserver().HandleDTMFEvent( dtmfEvent, 
       
  3058                                                         KErrNone, 
       
  3059                                                         iDtmfStringLex.Peek() );
       
  3060                     }  
       
  3061                 else
       
  3062                     {
       
  3063                     SVPDEBUG1( "CSVPController::DtmfEventReceived STOP TO PREVIOUS" )
       
  3064                     
       
  3065                     // send stop event to the previous character in string 
       
  3066                     iSessionArray[ index ]->DtmfObserver().HandleDTMFEvent( 
       
  3067                         MCCPDTMFObserver::ECCPDtmfSequenceStop, 
       
  3068                         KErrNone, 
       
  3069                         iDtmfStringLex.Get() );
       
  3070                      SVPDEBUG1("CSVPController::DtmfEventReceived START TO CURRENT");
       
  3071                     // send start event to the current character in string
       
  3072                     iSessionArray[ index ]->DtmfObserver().HandleDTMFEvent( 
       
  3073                         dtmfEvent, 
       
  3074                         KErrNone, 
       
  3075                         iDtmfStringLex.Peek() );
       
  3076                     }
       
  3077                 }
       
  3078              else
       
  3079                 {
       
  3080                 SVPDEBUG1( "CSVPController::DtmfEventReceived STOP TO PREVIOUS AND LAST" )
       
  3081                 
       
  3082                 // send stop event to the previous character in string 
       
  3083                 iSessionArray[ index ]->DtmfObserver().HandleDTMFEvent( 
       
  3084                         MCCPDTMFObserver::ECCPDtmfSequenceStop, 
       
  3085                         KErrNone, 
       
  3086                         iDtmfStringLex.Peek() );
       
  3087                 
       
  3088                 SVPDEBUG1( "CSVPController::DtmfEventReceived COMPLETE" )
       
  3089                 
       
  3090                 // send sequence stop event
       
  3091                 iSessionArray[ index ]->DtmfObserver().HandleDTMFEvent( 
       
  3092                      MCCPDTMFObserver::ECCPDtmfStringSendingCompleted, 
       
  3093                      KErrNone, 
       
  3094                      iDtmfStringLex.Peek() );
       
  3095                 // sequence complete, clear flags
       
  3096                 iDtmfStringSending = EFalse;
       
  3097                 iFirstDtmfSent = EFalse;
       
  3098                
       
  3099                 delete iDtmfString;
       
  3100                 iDtmfString = NULL;
       
  3101                 }
       
  3102             }
       
  3103         // manual dtmf
       
  3104         else
       
  3105             {
       
  3106             // call back event to application
       
  3107             iSessionArray[ index ]->DtmfObserver().HandleDTMFEvent( 
       
  3108                                             dtmfEvent, 
       
  3109                                             KErrNone, 
       
  3110                                             iDtmfTone );
       
  3111             }
       
  3112         }
       
  3113     
       
  3114     else if ( iEmergencySession )
       
  3115         {
       
  3116         const MCCPDTMFObserver& dtmfObs = iEmergencySession->DtmfObserver();
       
  3117         SVPDEBUG2("CSVPController::DtmfEventReceived, %d = DtmfObserver()", &dtmfObs )
       
  3118          // match dtmf event
       
  3119         MCCPDTMFObserver::TCCPDtmfEvent dtmfEvent = 
       
  3120             iSVPUtility->GetDtmfEvent( aEvent, iDtmfStringSending );
       
  3121         
       
  3122         // dtmf string
       
  3123         if ( iDtmfStringSending && NULL != &dtmfObs ) 
       
  3124             { 
       
  3125             // only start event received from mce
       
  3126             // logic below needed so that stop events can be sent
       
  3127             if ( MCCPDTMFObserver::ECCPDtmfSequenceStart == dtmfEvent )
       
  3128                 {
       
  3129                 if ( !iFirstDtmfSent )
       
  3130                     {
       
  3131                     SVPDEBUG1(
       
  3132                     "CSVPController::DtmfEventReceived, emergency FIRST SEND")
       
  3133                     
       
  3134                     // send start
       
  3135                     iFirstDtmfSent = ETrue;
       
  3136                      // call back event to application
       
  3137                     dtmfObs.HandleDTMFEvent( dtmfEvent, KErrNone, iDtmfStringLex.Peek() );
       
  3138                     }  
       
  3139                 else
       
  3140                     {
       
  3141                     SVPDEBUG1("CSVPController::DtmfEventReceived,\
       
  3142                      emergency STOP TO PREVIOUS")
       
  3143                     
       
  3144                     // send stop event to the previous character in string 
       
  3145                     dtmfObs.HandleDTMFEvent( 
       
  3146                         MCCPDTMFObserver::ECCPDtmfSequenceStop, 
       
  3147                         KErrNone, 
       
  3148                         iDtmfStringLex.Get() );
       
  3149                      SVPDEBUG1("CSVPController::DtmfEventReceived,\
       
  3150                       emergency START TO CURRENT")
       
  3151                     // send start event to the current character in string
       
  3152                     dtmfObs.HandleDTMFEvent( 
       
  3153                         dtmfEvent, 
       
  3154                         KErrNone, 
       
  3155                         iDtmfStringLex.Peek() );
       
  3156                     }
       
  3157                 }
       
  3158              else
       
  3159                 {
       
  3160                 SVPDEBUG1("CSVPController::DtmfEventReceived,\
       
  3161                  emergency STOP TO PREVIOUS AND LAST")
       
  3162                 
       
  3163                 // send stop event to the previous character in string 
       
  3164                 dtmfObs.HandleDTMFEvent( 
       
  3165                     MCCPDTMFObserver::ECCPDtmfSequenceStop, 
       
  3166                     KErrNone, 
       
  3167                     iDtmfStringLex.Peek() );
       
  3168                 
       
  3169                 SVPDEBUG1("CSVPController::DtmfEventReceived,\
       
  3170                  emergency COMPLETE")
       
  3171                 
       
  3172                 // send sequence stop event
       
  3173                 dtmfObs.HandleDTMFEvent( 
       
  3174                      MCCPDTMFObserver::ECCPDtmfStringSendingCompleted, 
       
  3175                      KErrNone, 
       
  3176                      iDtmfStringLex.Peek() );
       
  3177                 // sequence complete, clear flags
       
  3178                 iDtmfStringSending = EFalse;
       
  3179                 iFirstDtmfSent = EFalse;
       
  3180                 
       
  3181                 delete iDtmfString;
       
  3182                 iDtmfString = NULL;
       
  3183                 }
       
  3184             }
       
  3185         // manual dtmf
       
  3186         else if( NULL != &dtmfObs )
       
  3187             {
       
  3188             SVPDEBUG1("CSVPController::DtmfEventReceived,\
       
  3189                     manual dtmf ,  call back event to application")
       
  3190             dtmfObs.HandleDTMFEvent( dtmfEvent, KErrNone, iDtmfTone );
       
  3191             }
       
  3192         else
       
  3193             {
       
  3194             SVPDEBUG1("CSVPController::DtmfEventReceived, DtmfObs not set")
       
  3195             }
       
  3196         }
       
  3197     
       
  3198     SVPDEBUG1( "CSVPController::DtmfEventReceived Out" )
       
  3199     }
       
  3200                                   
       
  3201 // ---------------------------------------------------------------------------
       
  3202 // CSVPController::DtmfErrorOccured
       
  3203 // ---------------------------------------------------------------------------
       
  3204 //
       
  3205  void CSVPController::DtmfErrorOccured( CMceSession& aSession,
       
  3206          CMceAudioStream& /*aStream*/,CMceMediaSource& /*aSource*/,
       
  3207          TInt aError )
       
  3208     {
       
  3209     SVPDEBUG2( "CSVPController::DtmfErrorOccured In, aError: %d", aError )
       
  3210     
       
  3211     // find what session received the event
       
  3212     const TInt index = FindSVPSession( aSession );
       
  3213     if ( KErrNotFound != index )
       
  3214         {
       
  3215         // match dtmf event, unknown set as default in error case, 'tis ok?
       
  3216         const MCCPDTMFObserver::TCCPDtmfEvent dtmfEvent = 
       
  3217             MCCPDTMFObserver::ECCPDtmfUnknown;
       
  3218         
       
  3219         // default tone char
       
  3220         TChar dtmfToneChar('0');
       
  3221         
       
  3222         // call back error
       
  3223         iSessionArray[ index ]->
       
  3224             DtmfObserver().HandleDTMFEvent( dtmfEvent, 
       
  3225                                             aError, 
       
  3226                                             dtmfToneChar );  
       
  3227         }
       
  3228     
       
  3229     SVPDEBUG1( "CSVPController::DtmfErrorOccured Out" )
       
  3230     }
       
  3231 
       
  3232 // ---------------------------------------------------------------------------
       
  3233 // CSVPController::FinalizeSessionCreationL
       
  3234 // ---------------------------------------------------------------------------
       
  3235 //
       
  3236 void CSVPController::FinalizeSessionCreationL( CSVPSessionBase* aSession )
       
  3237     {
       
  3238     SVPDEBUG2( "CSVPController::FinalizeSessionCreationL In, aSession: 0x%x",
       
  3239         aSession )
       
  3240     
       
  3241     __ASSERT_ALWAYS( aSession, User::Leave( KErrArgument ) );
       
  3242     
       
  3243     if ( iCCPDtmfObserver )
       
  3244       	{
       
  3245        	aSession->SetDtmfObserver( *iCCPDtmfObserver );
       
  3246        	}
       
  3247     
       
  3248     iRtpObserver->AddSessionForObservingL( aSession );
       
  3249     iSessionArray.AppendL( aSession );
       
  3250     
       
  3251     SVPDEBUG1( "CSVPController::FinalizeSessionCreationL Out" )
       
  3252     }
       
  3253 
       
  3254 // ---------------------------------------------------------------------------
       
  3255 // CSVPController::ExecCbErrorOccurred
       
  3256 // ---------------------------------------------------------------------------
       
  3257 // 
       
  3258 TInt CSVPController::ExecCbErrorOccurred( MCCPObserver::TCCPError aError )
       
  3259     {
       
  3260     SVPDEBUG2( "CSVPController::ExecCbErrorOccurred In, aError=%d", aError )
       
  3261     
       
  3262     TInt status = KErrNotFound;
       
  3263     
       
  3264     if ( iCCPMonitor )
       
  3265         {
       
  3266         status = KErrNone;
       
  3267         iCCPMonitor->ErrorOccurred( aError );
       
  3268         }
       
  3269     
       
  3270     SVPDEBUG2( "CSVPController::ExecCbErrorOccurred Out return=%d", status )
       
  3271     return status;
       
  3272     }
       
  3273 
       
  3274 // ---------------------------------------------------------------------------
       
  3275 // CSVPController::IncomingCall
       
  3276 // ---------------------------------------------------------------------------
       
  3277 // 
       
  3278 TInt CSVPController::ExecCbIncomingCall( MCCPCall* aCall )
       
  3279     {
       
  3280     SVPDEBUG2( "CSVPController::ExecCbIncomingCall In, aCall= 0x%x", aCall )
       
  3281 
       
  3282     TInt status = KErrNotFound;
       
  3283     
       
  3284     if ( iCCPMonitor )
       
  3285         {
       
  3286         status = KErrNone;
       
  3287         iCCPMonitor->IncomingCall( aCall );
       
  3288         }
       
  3289     
       
  3290     SVPDEBUG2( "CSVPController::ExecCbIncomingCall Out return=%d", status )
       
  3291     return status;
       
  3292     }
       
  3293 
       
  3294 // ---------------------------------------------------------------------------
       
  3295 // CSVPController::ExecCbIncomingCall
       
  3296 // ---------------------------------------------------------------------------
       
  3297 // 
       
  3298 TInt CSVPController::ExecCbIncomingCall( MCCPCall* aCall, MCCPCall& aTempCall )
       
  3299     {
       
  3300     SVPDEBUG2( "CSVPController::ExecCbIncomingCall In, aCall= 0x%x", aCall )
       
  3301     SVPDEBUG2( "CSVPController::ExecCbIncomingCall aTempCall= 0x%x", &aTempCall )
       
  3302     
       
  3303     TInt status = KErrNotFound;
       
  3304     
       
  3305     if ( iCCPMonitor )
       
  3306         {
       
  3307         status = KErrNone;
       
  3308         iCCPMonitor->IncomingCall( aCall, aTempCall );
       
  3309         }
       
  3310     
       
  3311     SVPDEBUG2( "CSVPController::ExecCbIncomingCall Out return=%d", status )
       
  3312     return status;
       
  3313     }
       
  3314 
       
  3315 // ---------------------------------------------------------------------------
       
  3316 // CSVPController::ExecCbCallCreated
       
  3317 // ---------------------------------------------------------------------------
       
  3318 // 
       
  3319 TInt CSVPController::ExecCbCallCreated( MCCPCall* aNewTransferCall,
       
  3320         MCCPCall* aOriginator, TBool aAttended )
       
  3321     {
       
  3322     SVPDEBUG2( "CSVPController::ExecCbCallCreated In, aNewTransferCall= 0x%x", aNewTransferCall )
       
  3323     SVPDEBUG2( "CSVPController::ExecCbCallCreated          aOriginator= 0x%x", aOriginator )
       
  3324     SVPDEBUG2( "CSVPController::ExecCbCallCreated            aAttended= %d", aAttended )
       
  3325     
       
  3326     TInt status = KErrNotFound;
       
  3327     
       
  3328     if ( iCCPMonitor )
       
  3329         {
       
  3330         status = KErrNone;
       
  3331         iCCPMonitor->CallCreated( aNewTransferCall, aOriginator, aAttended );
       
  3332         }
       
  3333     
       
  3334     SVPDEBUG2( "CSVPController::ExecCbCallCreated Out return=%d", status )
       
  3335     return status;
       
  3336     }
       
  3337 
       
  3338 // ---------------------------------------------------------------------------
       
  3339 // CSVPController::ParseRecipientDtmfSuffixL
       
  3340 // ---------------------------------------------------------------------------
       
  3341 // 
       
  3342 HBufC* CSVPController::ParseRecipientDtmfSuffixL( const TDesC& aRecipient ) const
       
  3343     {
       
  3344     __ASSERT_ALWAYS( &aRecipient, User::Leave( KErrArgument ) );
       
  3345 
       
  3346     SVPDEBUG2( "CSVPController::ParseRecipientDtmfSuffixL In, aRecipient=%S", &aRecipient )
       
  3347     
       
  3348     HBufC* result = aRecipient.AllocLC(); // CS:1
       
  3349     
       
  3350     TInt recipientLength = result->Length();
       
  3351     if ( recipientLength )
       
  3352         {
       
  3353         if ( IsValidDtmfRecipientL( *result ) )
       
  3354             {
       
  3355             TInt loopCount = 0;
       
  3356             if (  KErrNotFound != KSVPDtmfTelNumRange().Locate( result->Des()[loopCount] ) )
       
  3357                 {
       
  3358                 loopCount++;
       
  3359                 TBool doLoop = ETrue;
       
  3360                 do
       
  3361                     {
       
  3362                     if ( loopCount < recipientLength )
       
  3363                         {
       
  3364                         if ( KErrNotFound != 
       
  3365                             KSVPDtmfDelimiterRange().Locate( result->Des()[loopCount] ) )
       
  3366                             {
       
  3367                             TInt suffixLength = recipientLength - loopCount;
       
  3368                             result->Des().Delete( loopCount, suffixLength );
       
  3369                             doLoop = EFalse;
       
  3370                             SVPDEBUG1(
       
  3371                                  "CSVPController::ParseRecipientDtmfSuffixL, DTMF suffix removed" )
       
  3372                             }
       
  3373                         else 
       
  3374                             {
       
  3375                             loopCount++;
       
  3376                             }
       
  3377                         }
       
  3378                     else
       
  3379                         {
       
  3380                         doLoop = EFalse;
       
  3381                         }
       
  3382                     } while ( doLoop );
       
  3383                 }
       
  3384             }
       
  3385         }
       
  3386     SVPDEBUG2( "CSVPController::ParseRecipientDtmfSuffixL Out, result=%S", result )
       
  3387     CleanupStack::Pop( result ); // CS:0
       
  3388     return result;
       
  3389     }
       
  3390 
       
  3391 // ---------------------------------------------------------------------------
       
  3392 // CSVPController::IsValidDtmfRecipientL
       
  3393 // ---------------------------------------------------------------------------
       
  3394 // 
       
  3395 TBool CSVPController::IsValidDtmfRecipientL( const TDesC& aRecipient ) const
       
  3396     {
       
  3397     __ASSERT_ALWAYS( &aRecipient, User::Leave( KErrArgument ) );
       
  3398 
       
  3399     SVPDEBUG1( "CSVPController::IsValidDtmfRecipientL In" )
       
  3400 
       
  3401     TBool result = ETrue;
       
  3402     if ( aRecipient.Length() )
       
  3403         {
       
  3404         TBool loopDo = ETrue;
       
  3405         TInt loopCount = 0;
       
  3406         do
       
  3407             {
       
  3408             if ( loopCount < aRecipient.Length() )
       
  3409                 {
       
  3410                 if ( KErrNotFound == KSVPDtmfAllValidChars().Locate( aRecipient[loopCount] ) )
       
  3411                     {
       
  3412                     result = EFalse;
       
  3413                     loopDo = EFalse;
       
  3414                     }
       
  3415                 else
       
  3416                     {
       
  3417                     loopCount++;
       
  3418                     }
       
  3419                 }
       
  3420             else
       
  3421                 {
       
  3422                 loopDo = EFalse;
       
  3423                 }
       
  3424             } while ( loopDo );
       
  3425         }
       
  3426     else
       
  3427         {
       
  3428         SVPDEBUG1( "CSVPController::IsValidDtmfRecipientL, Invalid recipient length" )
       
  3429         result = EFalse;
       
  3430         }
       
  3431     SVPDEBUG2( "CSVPController::IsValidDtmfRecipientL Out, result=%d" , result )
       
  3432     return result;
       
  3433     }
       
  3434 
       
  3435 // ---------------------------------------------------------------------------
       
  3436 // CSVPController::CheckCallEventToBeSent
       
  3437 // ---------------------------------------------------------------------------
       
  3438 //
       
  3439 void CSVPController::CheckCallEventToBeSent( CSVPSessionBase* aNewSVPSession, 
       
  3440                      CSVPSessionBase* aOldSVPSession ) const
       
  3441     {
       
  3442     SVPDEBUG1( "CSVPController::CheckCallEventToBeSent In" )
       
  3443 
       
  3444     if ( aOldSVPSession->IsSecured() != aNewSVPSession->IsSecured() )
       
  3445         {
       
  3446         // Session secure status changed, need to send proper event
       
  3447         if ( aNewSVPSession->IsSecured() )
       
  3448             {
       
  3449             SVPDEBUG1( "CSVPController::CheckCallEventToBeSent, unsecure -> secure case" )
       
  3450             aNewSVPSession->SetCallEventToBeSent( MCCPCallObserver::ECCPSecureCall );
       
  3451             }
       
  3452         else
       
  3453             {
       
  3454             SVPDEBUG1( "CSVPController::CheckCallEventToBeSent, secure -> unsecure case" )
       
  3455             aNewSVPSession->SetCallEventToBeSent( MCCPCallObserver::ECCPNotSecureCall );
       
  3456             }
       
  3457         }
       
  3458     else
       
  3459         {
       
  3460         // remoteparty will be updated anyway after attended transfer
       
  3461         SVPDEBUG1( "CSVPController::CheckCallEventToBeSent, remoteparty will be updated after attended transfer" )
       
  3462         aNewSVPSession->SetCallEventToBeSent( MCCPCallObserver::ECCPNotifyRemotePartyInfoChange );
       
  3463         }
       
  3464     SVPDEBUG1( "CSVPController::CheckCallEventToBeSent Out" )
       
  3465     }
       
  3466 
       
  3467 // ---------------------------------------------------------------------------
       
  3468 // From class MSIPObserver
       
  3469 // CSVPController::IncomingRequest
       
  3470 // ---------------------------------------------------------------------------
       
  3471 // 
       
  3472 void CSVPController::IncomingRequest( 
       
  3473     TUint32 /*aIapId*/, CSIPServerTransaction* /*aTransaction*/ )
       
  3474     {
       
  3475     SVPDEBUG1( "CSVPController::IncomingRequest" )
       
  3476     }
       
  3477 
       
  3478 // ---------------------------------------------------------------------------
       
  3479 // From class MSIPObserver
       
  3480 // CSVPController::TimedOut
       
  3481 // ---------------------------------------------------------------------------
       
  3482 //     
       
  3483 void CSVPController::TimedOut( 
       
  3484     CSIPServerTransaction& /*aSIPServerTransaction*/ )
       
  3485     {
       
  3486     SVPDEBUG1( "CSVPController::TimedOut" )
       
  3487     }
       
  3488 
       
  3489 // ---------------------------------------------------------------------------
       
  3490 // From class MSIPProfileRegistryObserver
       
  3491 // CSVPController::ProfileRegistryErrorOccurred
       
  3492 // ---------------------------------------------------------------------------
       
  3493 //  
       
  3494 void CSVPController::ProfileRegistryErrorOccurred( 
       
  3495     TUint32 /*aSIPProfileId*/, TInt /*aError*/ )
       
  3496     {
       
  3497     SVPDEBUG1( "CSVPController::ProfileRegistryErrorOccurred" )
       
  3498     }
       
  3499 
       
  3500 // ---------------------------------------------------------------------------
       
  3501 // From class MSIPProfileRegistryObserver
       
  3502 // CSVPController::ProfileRegistryEventOccurred
       
  3503 // ---------------------------------------------------------------------------
       
  3504 //  
       
  3505 void CSVPController::ProfileRegistryEventOccurred( 
       
  3506     TUint32 /*aProfileId*/, TEvent /*aEvent*/ )
       
  3507     {
       
  3508     SVPDEBUG1( "CSVPController::ProfileRegistryEventOccurred" )
       
  3509     }
       
  3510