voipplugins/sipmxresolver/src/sipmxresolver.cpp
changeset 0 a4daefaec16c
child 8 7117cbf1600a
equal deleted inserted replaced
-1:000000000000 0:a4daefaec16c
       
     1 /*
       
     2 * Copyright (c) 2007-2008 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:  implementation of sipmxresolver
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "sipmxresolver.h"
       
    21 #include "csipclientresolverutils.h"
       
    22 #include <e32base.h>
       
    23 #include <e32std.h>
       
    24 #include <e32property.h>
       
    25 
       
    26 //for checking CS call status
       
    27 #include <ctsydomainpskeys.h>
       
    28 
       
    29 //SIP message content parsing APIs
       
    30 #include <sipheaderbase.h>
       
    31 #include <sipacceptcontactheader.h>
       
    32 #include <sipaddress.h>
       
    33 #include <sdpdocument.h>
       
    34 #include <sdpmediafield.h>
       
    35 #include <sdpcodecstringpool.h>
       
    36 #include <sdpcodecstringconstants.h>
       
    37 #include <sdpattributefield.h>
       
    38 #include <sipstrings.h>
       
    39 
       
    40 //For checking dynamic voip status and MuS availability
       
    41 #include <featmgr.h>
       
    42 #include <centralrepository.h>
       
    43 #include <settingsinternalcrkeys.h>
       
    44 
       
    45 //Multimedia Sharing client API
       
    46 #include <musmanager.h>
       
    47 
       
    48 //Incoming Call Monitor API
       
    49 #include <icmapi.h>
       
    50 
       
    51 
       
    52 // CONSTANTS
       
    53 _LIT8( KFTagChar, "+" ); 						// All feature tags start with +
       
    54 _LIT8( KVSFeatureTag, "+g.3gpp.cs-voice" );		// For checking VS specific tag
       
    55 _LIT8( KPoCFeatureTag, "+g.poc.talkburst" ); 	// PoC specific tag (for ruling out)
       
    56 _LIT8( KContentType, "application/sdp" );		// For content-type header
       
    57 _LIT8( KMediaTypeApp, "application" );        	// For content-type header checks
       
    58 _LIT8( KMediaSubtypeSdp, "sdp" );            	// For content-type header checks
       
    59 _LIT8( KSendOnly, "sendonly" );            		// For attribute checks
       
    60 _LIT8( KApplicationAttr, "application" );   	// For attribute checks
       
    61 _LIT8( KXApplicationAttr, "X-application" );	// For attribute checks
       
    62 _LIT8( KNokiaRtvs, "com.nokia.rtvs" );       	// For attribute checks 
       
    63 
       
    64 /**
       
    65  * Cleanup function for RPointerArray
       
    66  * Called in case of a leave in SupportedSdpMediasL
       
    67  */
       
    68 void CleanupSdpMediasArray( TAny* aObj )
       
    69     {
       
    70     if ( aObj )
       
    71         {
       
    72         static_cast<RPointerArray<CSdpMediaField>*>( aObj )->ResetAndDestroy();
       
    73         }
       
    74     }
       
    75 
       
    76 
       
    77 // ============================ MEMBER FUNCTIONS =============================
       
    78 // ---------------------------------------------------------------------------
       
    79 // CSipMXResolver::CSipMXResolver
       
    80 // C++ default constructor can NOT contain any code, that
       
    81 // might leave.
       
    82 // ---------------------------------------------------------------------------
       
    83 //
       
    84 CSipMXResolver::CSipMXResolver() 
       
    85     {
       
    86     }
       
    87 
       
    88 
       
    89 // ---------------------------------------------------------------------------
       
    90 // CSipMXResolver::ConstructL
       
    91 // Symbian 2nd phase constructor can leave.
       
    92 // ---------------------------------------------------------------------------
       
    93 // 
       
    94 void CSipMXResolver::ConstructL()
       
    95     {
       
    96     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::ConstructL()" )
       
    97     
       
    98     // Open sdp string pool (needed in media field checks)
       
    99     TRAPD( err, SdpCodecStringPool::OpenL() );
       
   100     
       
   101     switch ( err )
       
   102 	    {
       
   103     	case KErrNone:
       
   104 	    	{
       
   105 	    	//close pool at destructor, not opened by others
       
   106 			iCloseStringPool = ETrue;
       
   107 			break;
       
   108 	    	}
       
   109 	    
       
   110 	    case KErrAlreadyExists:
       
   111 	    	{
       
   112 	    	//already opened, do not try to close at destructor
       
   113 	    	iCloseStringPool = EFalse;
       
   114 	    	break;
       
   115 	    	}
       
   116 	    
       
   117 	    default:
       
   118 	    	{
       
   119 	    	User::Leave( err );
       
   120 	    	}
       
   121 	    }
       
   122     
       
   123     // Check VoIP and Multimedia Sharing availability
       
   124     FeatureManager::InitializeLibL();
       
   125     
       
   126     TInt dynvoip = 0;
       
   127     CRepository* repository = CRepository::NewL( KCRUidTelephonySettings );
       
   128     repository->Get( KDynamicVoIP, dynvoip );
       
   129     delete repository;
       
   130     
       
   131     iVoIPEnabled = ( dynvoip && FeatureManager::FeatureSupported( KFeatureIdCommonVoip ) );
       
   132     
       
   133     if ( FeatureManager::FeatureSupported( KFeatureIdMultimediaSharing ) )
       
   134         {
       
   135         iMuSManager = CMusManager::NewL();
       
   136         }
       
   137     
       
   138     FeatureManager::UnInitializeLib();
       
   139     
       
   140     // initialize media type strings
       
   141     iAudioType = SdpCodecStringPool::StringPoolL().StringF(
       
   142                     SdpCodecStringConstants::EMediaAudio,
       
   143                         SdpCodecStringPool::StringTableL() );
       
   144     
       
   145     iVideoType = SdpCodecStringPool::StringPoolL().StringF(
       
   146                     SdpCodecStringConstants::EMediaVideo,
       
   147                         SdpCodecStringPool::StringTableL() );
       
   148     
       
   149     SIPMXRLOG( "[SIPMXRESOLVER] <- CSipMXResolver::ConstructL()" )
       
   150     }
       
   151 
       
   152 
       
   153 // ---------------------------------------------------------------------------
       
   154 // CSipMXResolver::NewL
       
   155 // Two-phased constructor.
       
   156 // ---------------------------------------------------------------------------
       
   157 // 
       
   158 CSipMXResolver* CSipMXResolver::NewL()
       
   159     {
       
   160     CSipMXResolver* self = new( ELeave ) CSipMXResolver;
       
   161     CleanupStack::PushL( self );
       
   162     self->ConstructL();
       
   163     CleanupStack::Pop( self);
       
   164     return self;
       
   165     }
       
   166 
       
   167 
       
   168 // Destructor
       
   169 CSipMXResolver::~CSipMXResolver()
       
   170     {
       
   171     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::~CSipMXResolver()" )
       
   172     
       
   173     delete iMuSManager;
       
   174     iAudioType.Close();
       
   175     iVideoType.Close();
       
   176     
       
   177     if ( iCloseStringPool )
       
   178 	    {
       
   179 	    SdpCodecStringPool::Close();
       
   180 	    }
       
   181     
       
   182     SIPMXRLOG( "[SIPMXRESOLVER] <- CSipMXResolver::~CSipMXResolver()" )
       
   183     }
       
   184 
       
   185 
       
   186 // ---------------------------------------------------------------------------
       
   187 // CSipMXResolver::MatchAcceptContactsL
       
   188 // ---------------------------------------------------------------------------
       
   189 // 
       
   190 TBool CSipMXResolver::MatchAcceptContactsL(
       
   191             RStringF aMethod,
       
   192             const CUri8& /*aRequestUri*/,
       
   193             const RPointerArray<CSIPHeaderBase>& aHeaders,
       
   194             const TDesC8& /*aContent*/,
       
   195             const CSIPContentTypeHeader* /*aContentType*/,
       
   196             TUid& aClientUid )
       
   197     {
       
   198     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::MatchAcceptContactsL()" )
       
   199     
       
   200     TBool match = EFalse;
       
   201     
       
   202     // check if we have active CS call
       
   203     // and MM Sharing is enabled (otherwise this can't be MuS)
       
   204     if ( iMuSManager && IsCSCallActive() )
       
   205         {
       
   206         if ( CheckForACHeaderTagL( aHeaders, KVSFeatureTag ) )
       
   207             {
       
   208             match = ETrue;
       
   209             aClientUid = ResolveVSUidL( aMethod );
       
   210             }
       
   211         }
       
   212     
       
   213     SIPMXRLOGP( \
       
   214     "[SIPMXRESOLVER] <- CSipMXResolver::MatchAcceptContactsL(), ret:%d", match )
       
   215     return match;
       
   216     }
       
   217 
       
   218 
       
   219 // ---------------------------------------------------------------------------
       
   220 // CSipMXResolver::MatchEventL
       
   221 // ---------------------------------------------------------------------------
       
   222 // 
       
   223 TBool CSipMXResolver::MatchEventL(
       
   224             RStringF /*aMethod*/,
       
   225             const CUri8& /*aRequestUri*/,
       
   226             const RPointerArray<CSIPHeaderBase>& /*aHeaders*/,
       
   227             const TDesC8& /*aContent*/,
       
   228             const CSIPContentTypeHeader* /*aContentType*/,
       
   229             TUid& /*aClientUid*/)
       
   230     {
       
   231     //SipMXResolver returns always EFalse for MatchEventL calls
       
   232     SIPMXRLOG( "[SIPMXRESOLVER] <-> CSipMXResolver::MatchEventL()" )
       
   233     return EFalse;
       
   234     }
       
   235 
       
   236 
       
   237 // ---------------------------------------------------------------------------
       
   238 // CSipMXResolver::MatchRequestL
       
   239 // ---------------------------------------------------------------------------
       
   240 // 
       
   241 TBool CSipMXResolver::MatchRequestL(
       
   242             RStringF aMethod,
       
   243             const CUri8& aRequestUri,
       
   244             const RPointerArray<CSIPHeaderBase>& aHeaders,
       
   245             const TDesC8& aContent,
       
   246             const CSIPContentTypeHeader* aContentType,
       
   247             TUid& aClientUid )
       
   248     {
       
   249     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::MatchRequestL()" )
       
   250     
       
   251     TBool match = EFalse;
       
   252     
       
   253     //poc specific requests will not be processed
       
   254     TBool poc = CheckForACHeaderTagL( aHeaders, KPoCFeatureTag );
       
   255     
       
   256     //OPTIONS and INVITE requests are processed
       
   257     TBool requestok = ( aMethod == SIPStrings::StringF( SipStrConsts::EOptions ) ||
       
   258          aMethod == SIPStrings::StringF( SipStrConsts::EInvite ) );
       
   259     
       
   260     //application/sdp content type is required
       
   261     TBool contentok = ( aContent.Length() > 0 && aContentType &&
       
   262          aContentType->MediaType().CompareF( KMediaTypeApp ) == 0 &&
       
   263          aContentType->MediaSubtype().CompareF( KMediaSubtypeSdp ) == 0 );
       
   264     
       
   265     // do further checks only if we have either VoIP and/or MuS active,
       
   266     // content type must be valid and accept-contact is not poc specific
       
   267     if ( ( iVoIPEnabled || iMuSManager ) && requestok && contentok && !poc )
       
   268         {
       
   269         CSdpDocument* sdpDocument = CSdpDocument::DecodeLC( aContent );
       
   270         
       
   271         // determine the parameters
       
   272         TBool hasAudio = CheckForMedia( sdpDocument, iAudioType );
       
   273         TBool hasVideo = CheckForMedia( sdpDocument, iVideoType );
       
   274         TBool cscall = IsCSCallActive();
       
   275         
       
   276         if ( iMuSManager && hasVideo && hasAudio && cscall )
       
   277             {
       
   278             // both audio and video medias present and cs call on
       
   279             // and multimedia sharing enabled =>
       
   280             // we need to do some further resolving for client
       
   281             if ( CheckForVSAttributes( sdpDocument->MediaFields() ) )
       
   282                 {
       
   283                 // this is VS
       
   284                 match = ETrue;
       
   285                 aClientUid = ResolveVSUidL( aMethod );
       
   286                 }
       
   287             else if ( iVoIPEnabled )
       
   288                 {
       
   289                 // no vs attributes and voip status is enabled
       
   290                 match = ETrue;
       
   291                 ResolveCPPluginUidL( aClientUid, aRequestUri );
       
   292                 }
       
   293             else
       
   294                 {
       
   295                 // possible voip match, but voip not activated
       
   296                 match = EFalse;
       
   297                 }
       
   298             }
       
   299         else if ( iMuSManager && hasVideo && cscall )
       
   300             {
       
   301             //video media only && cs call ongoing && multimedia sharing enabled
       
   302             // => Multimedia Sharing
       
   303             match = ETrue;
       
   304             aClientUid = ResolveVSUidL( aMethod );
       
   305             }
       
   306         else if ( hasAudio && iVoIPEnabled )
       
   307             {
       
   308             // audio only or audio and video and no cs call + voip supported
       
   309             // => this is VoIP
       
   310             match = ETrue;
       
   311             ResolveCPPluginUidL( aClientUid, aRequestUri );
       
   312             }
       
   313         else
       
   314             {
       
   315             // no medias or has video but no CS call or has audio
       
   316             // but voip status is disabled 
       
   317             // => no match
       
   318             match = EFalse;
       
   319             }
       
   320         
       
   321         CleanupStack::PopAndDestroy( sdpDocument );
       
   322         }
       
   323     else if ( aMethod == SIPStrings::StringF( SipStrConsts::EInvite ) &&
       
   324     		  iVoIPEnabled && !poc && aContent.Length() == 0 )
       
   325     	{
       
   326     	// Pull model: this is a re-Invite without content
       
   327     	ResolveCPPluginUidL( aClientUid, aRequestUri );
       
   328     	match = ETrue;
       
   329     	}
       
   330     else
       
   331     	{
       
   332     	//no match
       
   333     	match = EFalse;
       
   334         }
       
   335     
       
   336     SIPMXRLOGP( \
       
   337     "[SIPMXRESOLVER] <- CSipMXResolver::MatchRequestL(), ret:%d", match )
       
   338     return match;
       
   339     }
       
   340 
       
   341 
       
   342 // ---------------------------------------------------------------------------
       
   343 // CSipMXResolver::ConnectSupported
       
   344 // ---------------------------------------------------------------------------
       
   345 // 
       
   346 TBool CSipMXResolver::ConnectSupported()
       
   347     {
       
   348     return ETrue;
       
   349     }
       
   350 
       
   351 
       
   352 // ---------------------------------------------------------------------------
       
   353 // CSipMXResolver::ConnectL
       
   354 // ---------------------------------------------------------------------------
       
   355 //
       
   356 void CSipMXResolver::ConnectL( const TUid& aClientUid )
       
   357     {
       
   358     SIPMXRLOGP(\
       
   359     "[SIPMXRESOLVER] -> CSipMXResolver::ConnectL(), uid:%d", aClientUid.iUid )
       
   360     
       
   361     // If Uid matches with MuS, forward to MusManager
       
   362     if ( iMuSManager &&
       
   363          ( aClientUid.iUid == CMusManager::ESipOptions ||
       
   364            aClientUid.iUid == CMusManager::ESipInviteDesired ||
       
   365            aClientUid.iUid == CMusManager::ESipInviteNotDesired ) )
       
   366         {
       
   367         iMuSManager->HandleSipRequestL(
       
   368                   ( CMusManager::TRequestType ) aClientUid.iUid );
       
   369         }
       
   370     else
       
   371         {
       
   372         // start through ICM
       
   373         TInt result = RProperty::Set( KPSUidICMIncomingCall,
       
   374         		KPropertyKeyICMPluginUID, aClientUid.iUid );
       
   375         User::LeaveIfError( result );
       
   376         }
       
   377     
       
   378     SIPMXRLOG( "[SIPMXRESOLVER] <- CSipMXResolver::ConnectL()" )
       
   379     }
       
   380 
       
   381 
       
   382 // ---------------------------------------------------------------------------
       
   383 // CSipMXResolver::CancelConnect
       
   384 // ---------------------------------------------------------------------------
       
   385 // 
       
   386 void CSipMXResolver::CancelConnect( const TUid& /*aClientUid*/ )
       
   387     {
       
   388     SIPMXRLOG( "[SIPMXRESOLVER] <-> CSipMXResolver::CancelConnect()" )
       
   389     // No implementation for VoIP / MuS.
       
   390     }
       
   391 
       
   392 
       
   393 // ---------------------------------------------------------------------------
       
   394 // CSipMXResolver::SupportedContentTypesL
       
   395 // ---------------------------------------------------------------------------
       
   396 // 
       
   397 RPointerArray<CSIPContentTypeHeader> CSipMXResolver::SupportedContentTypesL()
       
   398     {
       
   399     RPointerArray<CSIPContentTypeHeader> ret;
       
   400     
       
   401     CSIPContentTypeHeader* ctype = CSIPContentTypeHeader::DecodeL( KContentType );
       
   402     CleanupStack::PushL( ctype );
       
   403     ret.AppendL( ctype );
       
   404     CleanupStack::Pop( ctype );
       
   405     
       
   406     return ret;
       
   407     }
       
   408 
       
   409 
       
   410 // ---------------------------------------------------------------------------
       
   411 // CSipMXResolver::SupportedSdpMediasL
       
   412 // ---------------------------------------------------------------------------
       
   413 // 
       
   414 RPointerArray<CSdpMediaField> CSipMXResolver::SupportedSdpMediasL()
       
   415     {
       
   416     // Initialise return array
       
   417     RPointerArray<CSdpMediaField> ret;
       
   418     TCleanupItem tci( CleanupSdpMediasArray, &ret );
       
   419     CleanupStack::PushL( tci );
       
   420     
       
   421     // media field descriptors
       
   422     _LIT8( KMuSField1, "m=video 0 RTP/AVP 96\r\na=application:com.nokia.rtvs\r\na=X-application:com.nokia.rtvs\r\n" );
       
   423     _LIT8( KMuSField2, "m=audio 0 RTP/AVP 97\r\n" );
       
   424     _LIT8( KVoIPField1, "m=video 0 RTP/AVP 0\r\n" );
       
   425     _LIT8( KVoIPField2, "m=application 0 tcp wb\r\n" );
       
   426     _LIT8( KVoIPField3, "m=audio 0 RTP/AVP 0\r\n" );
       
   427     _LIT8( KVoIPField4, "m=audio 0 RTP/SAVP 0\r\n" );
       
   428     
       
   429     CSdpMediaField* field = NULL;
       
   430     
       
   431     // add media fields to array
       
   432     if ( iMuSManager )
       
   433         {
       
   434         field = CSdpMediaField::DecodeLC( KMuSField1 );
       
   435         ret.AppendL( field ); // ownership to array
       
   436         CleanupStack::Pop( field );
       
   437         
       
   438         field = CSdpMediaField::DecodeLC( KMuSField2 );
       
   439         ret.AppendL( field );
       
   440         CleanupStack::Pop( field );
       
   441         }
       
   442     
       
   443     if ( iVoIPEnabled )
       
   444         {
       
   445         field = CSdpMediaField::DecodeLC( KVoIPField1 );
       
   446         ret.AppendL( field );
       
   447         CleanupStack::Pop( field );
       
   448         
       
   449         field = CSdpMediaField::DecodeLC( KVoIPField2 );
       
   450         ret.AppendL( field );
       
   451         CleanupStack::Pop( field );
       
   452         
       
   453         field = CSdpMediaField::DecodeLC( KVoIPField3 );
       
   454         ret.AppendL( field );
       
   455         CleanupStack::Pop( field );
       
   456         
       
   457         field = CSdpMediaField::DecodeLC( KVoIPField4 );
       
   458         ret.AppendL( field );
       
   459         CleanupStack::Pop( field );
       
   460         }
       
   461     
       
   462     CleanupStack::Pop(); // tcleanupitem
       
   463     return ret;
       
   464     }
       
   465 
       
   466 
       
   467 // ---------------------------------------------------------------------------
       
   468 // CSipMXResolver::AddClientSpecificHeadersForOptionsResponseL
       
   469 // ---------------------------------------------------------------------------
       
   470 // 
       
   471 void CSipMXResolver::AddClientSpecificHeadersForOptionsResponseL(
       
   472     RPointerArray<CSIPHeaderBase>& /*aHeaders*/ )
       
   473     {
       
   474     }
       
   475 
       
   476 
       
   477 // ---------------------------------------------------------------------------
       
   478 // CSipMXResolver::IsCsCallActive
       
   479 // ---------------------------------------------------------------------------
       
   480 // 
       
   481 TBool CSipMXResolver::IsCSCallActive() const
       
   482     {
       
   483     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::IsCSCallActive()" )
       
   484     
       
   485     TBool retval = EFalse;
       
   486     
       
   487     TInt callType = KErrNone;
       
   488     RProperty::Get( KPSUidCtsyCallInformation,
       
   489     		KCTsyCallType, callType );
       
   490     
       
   491     if ( EPSCTsyCallTypeCSVoice == callType )
       
   492         {
       
   493         TInt callState = KErrNone;
       
   494         RProperty::Get( KPSUidCtsyCallInformation,
       
   495         		KCTsyCallState, callState );
       
   496         
       
   497         if ( EPSCTsyCallStateConnected == callState ||
       
   498              EPSCTsyCallStateHold == callState )
       
   499             {
       
   500             retval = ETrue;
       
   501             }
       
   502         }
       
   503     
       
   504     SIPMXRLOGP( \
       
   505     "[SIPMXRESOLVER] <- CSipMXResolver::IsCSCallActive(), ret:%d", retval )
       
   506     
       
   507     return retval;
       
   508     }
       
   509 
       
   510 // -----------------------------------------------------------------------------
       
   511 // CSipMXResolver::CheckForMedia
       
   512 // -----------------------------------------------------------------------------
       
   513 //
       
   514 TBool CSipMXResolver::CheckForMedia( CSdpDocument* aSdpDoc,
       
   515     const RStringF& aMediaType ) const
       
   516     {
       
   517     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::CheckForMedia()" )
       
   518     
       
   519     TBool present = EFalse;
       
   520     
       
   521     if ( aSdpDoc )
       
   522         {
       
   523         RPointerArray<CSdpMediaField>& mFields = aSdpDoc->MediaFields();
       
   524         const TInt count = mFields.Count();
       
   525         
       
   526         // if there is media fields, check them for type
       
   527         for ( TInt i = 0; i < count && !present; i++ )
       
   528             {
       
   529             if ( aMediaType == mFields[ i ]->Media() )
       
   530                 {
       
   531                 present = ETrue;
       
   532                 }
       
   533             }
       
   534         }
       
   535     
       
   536     SIPMXRLOGP( \
       
   537     "[SIPMXRESOLVER] <- CSipMXResolver::CheckForMedia(), ret:%d", present )
       
   538     
       
   539     return present;
       
   540     }
       
   541 
       
   542 
       
   543 // ---------------------------------------------------------------------------
       
   544 // CSipMXResolver::CheckForACHeaderTagL
       
   545 // ---------------------------------------------------------------------------
       
   546 // 
       
   547 TBool CSipMXResolver::CheckForACHeaderTagL(
       
   548     const RPointerArray<CSIPHeaderBase>& aHeaders,
       
   549     const TDesC8& aTag ) const
       
   550     {
       
   551     TBool match = EFalse;
       
   552     TInt ftagcount = 0;
       
   553     
       
   554     for ( TInt i = 0; i < aHeaders.Count(); i++ )
       
   555         {
       
   556         if ( aHeaders[i]->Name() ==
       
   557              SIPStrings::StringF( SipStrConsts::EAcceptContactHeader ) ||
       
   558              aHeaders[i]->Name() ==
       
   559              SIPStrings::StringF( SipStrConsts::EAcceptContactHeaderCompact ) )
       
   560             {
       
   561             RStringF featureTagStr = SIPStrings::Pool().OpenFStringL( aTag );
       
   562             CleanupClosePushL( featureTagStr );
       
   563             
       
   564             CSIPAcceptContactHeader* ach = 
       
   565                 static_cast<CSIPAcceptContactHeader*>(aHeaders[i]);
       
   566             TInt pcount = ach->ParamCount();
       
   567             
       
   568             for ( TInt p = 0; p < pcount; p++ )
       
   569                 {
       
   570                 RStringF mparam;
       
   571                 CleanupClosePushL( mparam );
       
   572                 
       
   573                 if ( KErrNone == ach->Param( p, mparam ) )
       
   574                     {
       
   575                     //we need to count all feature tags
       
   576                     if ( mparam.DesC().Left(1).Compare( KFTagChar ) == 0 )
       
   577                         {
       
   578                         ftagcount++;
       
   579                         }
       
   580                     if ( mparam == featureTagStr )
       
   581                         {
       
   582                         match = ETrue;
       
   583                         //loop is continued after match to count feature tags
       
   584                         }
       
   585                     }
       
   586                 
       
   587                 CleanupStack::PopAndDestroy( 1 ); //mparam
       
   588                 }
       
   589             
       
   590             // Use the dynamic string.
       
   591             CleanupStack::PopAndDestroy( 1 ); // featureTagStr
       
   592             }
       
   593         }
       
   594     
       
   595     //return ETrue only if there's only one feature tag and it is MuS specific
       
   596     return ( match && ftagcount == 1 );
       
   597     }
       
   598 
       
   599 
       
   600 // ---------------------------------------------------------------------------
       
   601 // CSipMXResolver::CheckForVSAttributesL
       
   602 // ---------------------------------------------------------------------------
       
   603 // 
       
   604 TBool CSipMXResolver::CheckForVSAttributes(
       
   605     RPointerArray<CSdpMediaField>& aFields ) const
       
   606     {
       
   607     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::CheckForVSAttributes()" )
       
   608     
       
   609     TBool vsattributefound = EFalse;
       
   610     TInt sendonlycount = 0; 
       
   611     TInt videofields = 0;
       
   612     const TInt fieldcount = aFields.Count();
       
   613     
       
   614     for ( TInt i = 0; i < fieldcount; i++ )
       
   615         {
       
   616         CSdpMediaField* mField = aFields[i];
       
   617         
       
   618         //only check audio/video fields
       
   619         TBool audio = mField->Media() == iAudioType;
       
   620         TBool video = mField->Media() == iVideoType;
       
   621         
       
   622         if ( video )
       
   623             {
       
   624             videofields++;
       
   625             }
       
   626         
       
   627         if ( video || audio )
       
   628             {
       
   629             RPointerArray< CSdpAttributeField > attrList =
       
   630                 mField->AttributeFields();
       
   631             
       
   632             TInt attrCount = attrList.Count();
       
   633             for (TInt j = 0; j < attrCount && !vsattributefound; j++ )
       
   634                 {
       
   635                 CSdpAttributeField* attributeField = attrList[j];
       
   636                 RStringF attribute = attributeField->Attribute();
       
   637                 
       
   638                 // for each sendonly attribute, add counter
       
   639                 if ( KErrNotFound != attribute.DesC().FindF( KSendOnly ) )
       
   640                     {
       
   641                     sendonlycount++;                        
       
   642                     }
       
   643                 
       
   644                 // check m=video fields for com.nokia.rtvs attribute
       
   645                 if ( video )
       
   646                     {
       
   647                     if ( ( KErrNotFound !=
       
   648                            attribute.DesC().FindF( KApplicationAttr ) ||
       
   649                            KErrNotFound !=
       
   650                            attribute.DesC().FindF( KXApplicationAttr ) ) &&
       
   651                          KErrNotFound !=
       
   652                          attributeField->Value().FindF( KNokiaRtvs ) )
       
   653                         {
       
   654                         //attribute found
       
   655                         vsattributefound = ETrue;
       
   656                         }
       
   657                     }
       
   658                 }
       
   659             }
       
   660         }
       
   661     
       
   662     // Video Sharing is assumed if nokia vs specific attributes are found
       
   663     // or if there is at least one m=video line and all media fields have
       
   664     // sendonly attribute.
       
   665     TBool retval = ( vsattributefound ||
       
   666         		     ( videofields > 0 && fieldcount == sendonlycount ) );
       
   667     
       
   668     SIPMXRLOGP( \
       
   669     "[SIPMXRESOLVER] <- CSipMXResolver::CheckForVSAttributes(),ret:%d", retval )
       
   670     
       
   671     return retval;
       
   672     }
       
   673 
       
   674 
       
   675 // ---------------------------------------------------------------------------
       
   676 // CSipMXResolver::ResolveVSUid
       
   677 // ---------------------------------------------------------------------------
       
   678 // 
       
   679 TUid CSipMXResolver::ResolveVSUidL( const RStringF& aMethod )
       
   680     {
       
   681     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::ResolveVSUidL()" )
       
   682     
       
   683     TUid muid  = KNullUid;
       
   684     
       
   685     if ( iMuSManager )
       
   686         {
       
   687         if ( aMethod == SIPStrings::StringF( SipStrConsts::EOptions ) )
       
   688             {
       
   689             muid.iUid = ( TInt32 ) CMusManager::ESipOptions;
       
   690             }
       
   691         else
       
   692             {
       
   693             MultimediaSharing::TMusAvailabilityStatus capability =
       
   694             	iMuSManager->AvailabilityL();
       
   695             
       
   696             //check if availability value is from non-error-range
       
   697             if( capability >= KErrNone &&
       
   698                 capability < MultimediaSharing::EErrSipRegistration )
       
   699                 {
       
   700                 muid.iUid = ( TInt32 ) CMusManager::ESipInviteDesired;
       
   701                 }
       
   702             else
       
   703                 {
       
   704                 muid.iUid = ( TInt32 ) CMusManager::ESipInviteNotDesired;
       
   705                 }
       
   706             }
       
   707         }
       
   708     
       
   709     SIPMXRLOGP( \
       
   710     "[SIPMXRESOLVER] <- CSipMXResolver::ResolveVSUidL(), ret:%d", muid.iUid )
       
   711     
       
   712     return muid;
       
   713     }
       
   714 
       
   715 
       
   716 // -----------------------------------------------------------------------------
       
   717 // CSipMXResolver::ResolveCPPluginUidL
       
   718 // -----------------------------------------------------------------------------
       
   719 // 
       
   720 void CSipMXResolver::ResolveCPPluginUidL( TUid& aUid, const CUri8& aRequestUri )
       
   721     {
       
   722     SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::ResolveCPPluginUidL()" )
       
   723     
       
   724     CSipClientResolverUtils* resolver = CSipClientResolverUtils::NewLC();
       
   725     resolver->GetImplementationUidWithUserL(
       
   726     		aRequestUri.Uri().Extract( EUriUserinfo ), aUid );
       
   727     CleanupStack::PopAndDestroy( resolver );
       
   728     
       
   729     SIPMXRLOGP( \
       
   730     "[SIPMXRESOLVER] <- CSipMXResolver::ResolveCPPluginUidL(),uID:%d", aUid.iUid )
       
   731     }
       
   732 
       
   733 
       
   734 //  End of File