--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/voipplugins/sipmxresolver/src/sipmxresolver.cpp Mon Jan 18 20:12:36 2010 +0200
@@ -0,0 +1,734 @@
+/*
+* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: implementation of sipmxresolver
+*
+*/
+
+
+// INCLUDE FILES
+#include "sipmxresolver.h"
+#include "csipclientresolverutils.h"
+#include <e32base.h>
+#include <e32std.h>
+#include <e32property.h>
+
+//for checking CS call status
+#include <ctsydomainpskeys.h>
+
+//SIP message content parsing APIs
+#include <sipheaderbase.h>
+#include <sipacceptcontactheader.h>
+#include <sipaddress.h>
+#include <sdpdocument.h>
+#include <sdpmediafield.h>
+#include <sdpcodecstringpool.h>
+#include <sdpcodecstringconstants.h>
+#include <sdpattributefield.h>
+#include <sipstrings.h>
+
+//For checking dynamic voip status and MuS availability
+#include <featmgr.h>
+#include <centralrepository.h>
+#include <settingsinternalcrkeys.h>
+
+//Multimedia Sharing client API
+#include <musmanager.h>
+
+//Incoming Call Monitor API
+#include <icmapi.h>
+
+
+// CONSTANTS
+_LIT8( KFTagChar, "+" ); // All feature tags start with +
+_LIT8( KVSFeatureTag, "+g.3gpp.cs-voice" ); // For checking VS specific tag
+_LIT8( KPoCFeatureTag, "+g.poc.talkburst" ); // PoC specific tag (for ruling out)
+_LIT8( KContentType, "application/sdp" ); // For content-type header
+_LIT8( KMediaTypeApp, "application" ); // For content-type header checks
+_LIT8( KMediaSubtypeSdp, "sdp" ); // For content-type header checks
+_LIT8( KSendOnly, "sendonly" ); // For attribute checks
+_LIT8( KApplicationAttr, "application" ); // For attribute checks
+_LIT8( KXApplicationAttr, "X-application" ); // For attribute checks
+_LIT8( KNokiaRtvs, "com.nokia.rtvs" ); // For attribute checks
+
+/**
+ * Cleanup function for RPointerArray
+ * Called in case of a leave in SupportedSdpMediasL
+ */
+void CleanupSdpMediasArray( TAny* aObj )
+ {
+ if ( aObj )
+ {
+ static_cast<RPointerArray<CSdpMediaField>*>( aObj )->ResetAndDestroy();
+ }
+ }
+
+
+// ============================ MEMBER FUNCTIONS =============================
+// ---------------------------------------------------------------------------
+// CSipMXResolver::CSipMXResolver
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CSipMXResolver::CSipMXResolver()
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::ConstructL
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CSipMXResolver::ConstructL()
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::ConstructL()" )
+
+ // Open sdp string pool (needed in media field checks)
+ TRAPD( err, SdpCodecStringPool::OpenL() );
+
+ switch ( err )
+ {
+ case KErrNone:
+ {
+ //close pool at destructor, not opened by others
+ iCloseStringPool = ETrue;
+ break;
+ }
+
+ case KErrAlreadyExists:
+ {
+ //already opened, do not try to close at destructor
+ iCloseStringPool = EFalse;
+ break;
+ }
+
+ default:
+ {
+ User::Leave( err );
+ }
+ }
+
+ // Check VoIP and Multimedia Sharing availability
+ FeatureManager::InitializeLibL();
+
+ TInt dynvoip = 0;
+ CRepository* repository = CRepository::NewL( KCRUidTelephonySettings );
+ repository->Get( KDynamicVoIP, dynvoip );
+ delete repository;
+
+ iVoIPEnabled = ( dynvoip && FeatureManager::FeatureSupported( KFeatureIdCommonVoip ) );
+
+ if ( FeatureManager::FeatureSupported( KFeatureIdMultimediaSharing ) )
+ {
+ iMuSManager = CMusManager::NewL();
+ }
+
+ FeatureManager::UnInitializeLib();
+
+ // initialize media type strings
+ iAudioType = SdpCodecStringPool::StringPoolL().StringF(
+ SdpCodecStringConstants::EMediaAudio,
+ SdpCodecStringPool::StringTableL() );
+
+ iVideoType = SdpCodecStringPool::StringPoolL().StringF(
+ SdpCodecStringConstants::EMediaVideo,
+ SdpCodecStringPool::StringTableL() );
+
+ SIPMXRLOG( "[SIPMXRESOLVER] <- CSipMXResolver::ConstructL()" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::NewL
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CSipMXResolver* CSipMXResolver::NewL()
+ {
+ CSipMXResolver* self = new( ELeave ) CSipMXResolver;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self);
+ return self;
+ }
+
+
+// Destructor
+CSipMXResolver::~CSipMXResolver()
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::~CSipMXResolver()" )
+
+ delete iMuSManager;
+ iAudioType.Close();
+ iVideoType.Close();
+
+ if ( iCloseStringPool )
+ {
+ SdpCodecStringPool::Close();
+ }
+
+ SIPMXRLOG( "[SIPMXRESOLVER] <- CSipMXResolver::~CSipMXResolver()" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::MatchAcceptContactsL
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::MatchAcceptContactsL(
+ RStringF aMethod,
+ const CUri8& /*aRequestUri*/,
+ const RPointerArray<CSIPHeaderBase>& aHeaders,
+ const TDesC8& /*aContent*/,
+ const CSIPContentTypeHeader* /*aContentType*/,
+ TUid& aClientUid )
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::MatchAcceptContactsL()" )
+
+ TBool match = EFalse;
+
+ // check if we have active CS call
+ // and MM Sharing is enabled (otherwise this can't be MuS)
+ if ( iMuSManager && IsCSCallActive() )
+ {
+ if ( CheckForACHeaderTagL( aHeaders, KVSFeatureTag ) )
+ {
+ match = ETrue;
+ aClientUid = ResolveVSUidL( aMethod );
+ }
+ }
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::MatchAcceptContactsL(), ret:%d", match )
+ return match;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::MatchEventL
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::MatchEventL(
+ RStringF /*aMethod*/,
+ const CUri8& /*aRequestUri*/,
+ const RPointerArray<CSIPHeaderBase>& /*aHeaders*/,
+ const TDesC8& /*aContent*/,
+ const CSIPContentTypeHeader* /*aContentType*/,
+ TUid& /*aClientUid*/)
+ {
+ //SipMXResolver returns always EFalse for MatchEventL calls
+ SIPMXRLOG( "[SIPMXRESOLVER] <-> CSipMXResolver::MatchEventL()" )
+ return EFalse;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::MatchRequestL
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::MatchRequestL(
+ RStringF aMethod,
+ const CUri8& aRequestUri,
+ const RPointerArray<CSIPHeaderBase>& aHeaders,
+ const TDesC8& aContent,
+ const CSIPContentTypeHeader* aContentType,
+ TUid& aClientUid )
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::MatchRequestL()" )
+
+ TBool match = EFalse;
+
+ //poc specific requests will not be processed
+ TBool poc = CheckForACHeaderTagL( aHeaders, KPoCFeatureTag );
+
+ //OPTIONS and INVITE requests are processed
+ TBool requestok = ( aMethod == SIPStrings::StringF( SipStrConsts::EOptions ) ||
+ aMethod == SIPStrings::StringF( SipStrConsts::EInvite ) );
+
+ //application/sdp content type is required
+ TBool contentok = ( aContent.Length() > 0 && aContentType &&
+ aContentType->MediaType().CompareF( KMediaTypeApp ) == 0 &&
+ aContentType->MediaSubtype().CompareF( KMediaSubtypeSdp ) == 0 );
+
+ // do further checks only if we have either VoIP and/or MuS active,
+ // content type must be valid and accept-contact is not poc specific
+ if ( ( iVoIPEnabled || iMuSManager ) && requestok && contentok && !poc )
+ {
+ CSdpDocument* sdpDocument = CSdpDocument::DecodeLC( aContent );
+
+ // determine the parameters
+ TBool hasAudio = CheckForMedia( sdpDocument, iAudioType );
+ TBool hasVideo = CheckForMedia( sdpDocument, iVideoType );
+ TBool cscall = IsCSCallActive();
+
+ if ( iMuSManager && hasVideo && hasAudio && cscall )
+ {
+ // both audio and video medias present and cs call on
+ // and multimedia sharing enabled =>
+ // we need to do some further resolving for client
+ if ( CheckForVSAttributes( sdpDocument->MediaFields() ) )
+ {
+ // this is VS
+ match = ETrue;
+ aClientUid = ResolveVSUidL( aMethod );
+ }
+ else if ( iVoIPEnabled )
+ {
+ // no vs attributes and voip status is enabled
+ match = ETrue;
+ ResolveCPPluginUidL( aClientUid, aRequestUri );
+ }
+ else
+ {
+ // possible voip match, but voip not activated
+ match = EFalse;
+ }
+ }
+ else if ( iMuSManager && hasVideo && cscall )
+ {
+ //video media only && cs call ongoing && multimedia sharing enabled
+ // => Multimedia Sharing
+ match = ETrue;
+ aClientUid = ResolveVSUidL( aMethod );
+ }
+ else if ( hasAudio && iVoIPEnabled )
+ {
+ // audio only or audio and video and no cs call + voip supported
+ // => this is VoIP
+ match = ETrue;
+ ResolveCPPluginUidL( aClientUid, aRequestUri );
+ }
+ else
+ {
+ // no medias or has video but no CS call or has audio
+ // but voip status is disabled
+ // => no match
+ match = EFalse;
+ }
+
+ CleanupStack::PopAndDestroy( sdpDocument );
+ }
+ else if ( aMethod == SIPStrings::StringF( SipStrConsts::EInvite ) &&
+ iVoIPEnabled && !poc && aContent.Length() == 0 )
+ {
+ // Pull model: this is a re-Invite without content
+ ResolveCPPluginUidL( aClientUid, aRequestUri );
+ match = ETrue;
+ }
+ else
+ {
+ //no match
+ match = EFalse;
+ }
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::MatchRequestL(), ret:%d", match )
+ return match;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::ConnectSupported
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::ConnectSupported()
+ {
+ return ETrue;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::ConnectL
+// ---------------------------------------------------------------------------
+//
+void CSipMXResolver::ConnectL( const TUid& aClientUid )
+ {
+ SIPMXRLOGP(\
+ "[SIPMXRESOLVER] -> CSipMXResolver::ConnectL(), uid:%d", aClientUid.iUid )
+
+ // If Uid matches with MuS, forward to MusManager
+ if ( iMuSManager &&
+ ( aClientUid.iUid == CMusManager::ESipOptions ||
+ aClientUid.iUid == CMusManager::ESipInviteDesired ||
+ aClientUid.iUid == CMusManager::ESipInviteNotDesired ) )
+ {
+ iMuSManager->HandleSipRequestL(
+ ( CMusManager::TRequestType ) aClientUid.iUid );
+ }
+ else
+ {
+ // start through ICM
+ TInt result = RProperty::Set( KPSUidICMIncomingCall,
+ KPropertyKeyICMPluginUID, aClientUid.iUid );
+ User::LeaveIfError( result );
+ }
+
+ SIPMXRLOG( "[SIPMXRESOLVER] <- CSipMXResolver::ConnectL()" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::CancelConnect
+// ---------------------------------------------------------------------------
+//
+void CSipMXResolver::CancelConnect( const TUid& /*aClientUid*/ )
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] <-> CSipMXResolver::CancelConnect()" )
+ // No implementation for VoIP / MuS.
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::SupportedContentTypesL
+// ---------------------------------------------------------------------------
+//
+RPointerArray<CSIPContentTypeHeader> CSipMXResolver::SupportedContentTypesL()
+ {
+ RPointerArray<CSIPContentTypeHeader> ret;
+
+ CSIPContentTypeHeader* ctype = CSIPContentTypeHeader::DecodeL( KContentType );
+ CleanupStack::PushL( ctype );
+ ret.AppendL( ctype );
+ CleanupStack::Pop( ctype );
+
+ return ret;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::SupportedSdpMediasL
+// ---------------------------------------------------------------------------
+//
+RPointerArray<CSdpMediaField> CSipMXResolver::SupportedSdpMediasL()
+ {
+ // Initialise return array
+ RPointerArray<CSdpMediaField> ret;
+ TCleanupItem tci( CleanupSdpMediasArray, &ret );
+ CleanupStack::PushL( tci );
+
+ // media field descriptors
+ _LIT8( KMuSField1, "m=video 0 RTP/AVP 96\r\na=application:com.nokia.rtvs\r\na=X-application:com.nokia.rtvs\r\n" );
+ _LIT8( KMuSField2, "m=audio 0 RTP/AVP 97\r\n" );
+ _LIT8( KVoIPField1, "m=video 0 RTP/AVP 0\r\n" );
+ _LIT8( KVoIPField2, "m=application 0 tcp wb\r\n" );
+ _LIT8( KVoIPField3, "m=audio 0 RTP/AVP 0\r\n" );
+ _LIT8( KVoIPField4, "m=audio 0 RTP/SAVP 0\r\n" );
+
+ CSdpMediaField* field = NULL;
+
+ // add media fields to array
+ if ( iMuSManager )
+ {
+ field = CSdpMediaField::DecodeLC( KMuSField1 );
+ ret.AppendL( field ); // ownership to array
+ CleanupStack::Pop( field );
+
+ field = CSdpMediaField::DecodeLC( KMuSField2 );
+ ret.AppendL( field );
+ CleanupStack::Pop( field );
+ }
+
+ if ( iVoIPEnabled )
+ {
+ field = CSdpMediaField::DecodeLC( KVoIPField1 );
+ ret.AppendL( field );
+ CleanupStack::Pop( field );
+
+ field = CSdpMediaField::DecodeLC( KVoIPField2 );
+ ret.AppendL( field );
+ CleanupStack::Pop( field );
+
+ field = CSdpMediaField::DecodeLC( KVoIPField3 );
+ ret.AppendL( field );
+ CleanupStack::Pop( field );
+
+ field = CSdpMediaField::DecodeLC( KVoIPField4 );
+ ret.AppendL( field );
+ CleanupStack::Pop( field );
+ }
+
+ CleanupStack::Pop(); // tcleanupitem
+ return ret;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::AddClientSpecificHeadersForOptionsResponseL
+// ---------------------------------------------------------------------------
+//
+void CSipMXResolver::AddClientSpecificHeadersForOptionsResponseL(
+ RPointerArray<CSIPHeaderBase>& /*aHeaders*/ )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::IsCsCallActive
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::IsCSCallActive() const
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::IsCSCallActive()" )
+
+ TBool retval = EFalse;
+
+ TInt callType = KErrNone;
+ RProperty::Get( KPSUidCtsyCallInformation,
+ KCTsyCallType, callType );
+
+ if ( EPSCTsyCallTypeCSVoice == callType )
+ {
+ TInt callState = KErrNone;
+ RProperty::Get( KPSUidCtsyCallInformation,
+ KCTsyCallState, callState );
+
+ if ( EPSCTsyCallStateConnected == callState ||
+ EPSCTsyCallStateHold == callState )
+ {
+ retval = ETrue;
+ }
+ }
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::IsCSCallActive(), ret:%d", retval )
+
+ return retval;
+ }
+
+// -----------------------------------------------------------------------------
+// CSipMXResolver::CheckForMedia
+// -----------------------------------------------------------------------------
+//
+TBool CSipMXResolver::CheckForMedia( CSdpDocument* aSdpDoc,
+ const RStringF& aMediaType ) const
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::CheckForMedia()" )
+
+ TBool present = EFalse;
+
+ if ( aSdpDoc )
+ {
+ RPointerArray<CSdpMediaField>& mFields = aSdpDoc->MediaFields();
+ const TInt count = mFields.Count();
+
+ // if there is media fields, check them for type
+ for ( TInt i = 0; i < count && !present; i++ )
+ {
+ if ( aMediaType == mFields[ i ]->Media() )
+ {
+ present = ETrue;
+ }
+ }
+ }
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::CheckForMedia(), ret:%d", present )
+
+ return present;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::CheckForACHeaderTagL
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::CheckForACHeaderTagL(
+ const RPointerArray<CSIPHeaderBase>& aHeaders,
+ const TDesC8& aTag ) const
+ {
+ TBool match = EFalse;
+ TInt ftagcount = 0;
+
+ for ( TInt i = 0; i < aHeaders.Count(); i++ )
+ {
+ if ( aHeaders[i]->Name() ==
+ SIPStrings::StringF( SipStrConsts::EAcceptContactHeader ) ||
+ aHeaders[i]->Name() ==
+ SIPStrings::StringF( SipStrConsts::EAcceptContactHeaderCompact ) )
+ {
+ RStringF featureTagStr = SIPStrings::Pool().OpenFStringL( aTag );
+ CleanupClosePushL( featureTagStr );
+
+ CSIPAcceptContactHeader* ach =
+ static_cast<CSIPAcceptContactHeader*>(aHeaders[i]);
+ TInt pcount = ach->ParamCount();
+
+ for ( TInt p = 0; p < pcount; p++ )
+ {
+ RStringF mparam;
+ CleanupClosePushL( mparam );
+
+ if ( KErrNone == ach->Param( p, mparam ) )
+ {
+ //we need to count all feature tags
+ if ( mparam.DesC().Left(1).Compare( KFTagChar ) == 0 )
+ {
+ ftagcount++;
+ }
+ if ( mparam == featureTagStr )
+ {
+ match = ETrue;
+ //loop is continued after match to count feature tags
+ }
+ }
+
+ CleanupStack::PopAndDestroy( 1 ); //mparam
+ }
+
+ // Use the dynamic string.
+ CleanupStack::PopAndDestroy( 1 ); // featureTagStr
+ }
+ }
+
+ //return ETrue only if there's only one feature tag and it is MuS specific
+ return ( match && ftagcount == 1 );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::CheckForVSAttributesL
+// ---------------------------------------------------------------------------
+//
+TBool CSipMXResolver::CheckForVSAttributes(
+ RPointerArray<CSdpMediaField>& aFields ) const
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::CheckForVSAttributes()" )
+
+ TBool vsattributefound = EFalse;
+ TInt sendonlycount = 0;
+ TInt videofields = 0;
+ const TInt fieldcount = aFields.Count();
+
+ for ( TInt i = 0; i < fieldcount; i++ )
+ {
+ CSdpMediaField* mField = aFields[i];
+
+ //only check audio/video fields
+ TBool audio = mField->Media() == iAudioType;
+ TBool video = mField->Media() == iVideoType;
+
+ if ( video )
+ {
+ videofields++;
+ }
+
+ if ( video || audio )
+ {
+ RPointerArray< CSdpAttributeField > attrList =
+ mField->AttributeFields();
+
+ TInt attrCount = attrList.Count();
+ for (TInt j = 0; j < attrCount && !vsattributefound; j++ )
+ {
+ CSdpAttributeField* attributeField = attrList[j];
+ RStringF attribute = attributeField->Attribute();
+
+ // for each sendonly attribute, add counter
+ if ( KErrNotFound != attribute.DesC().FindF( KSendOnly ) )
+ {
+ sendonlycount++;
+ }
+
+ // check m=video fields for com.nokia.rtvs attribute
+ if ( video )
+ {
+ if ( ( KErrNotFound !=
+ attribute.DesC().FindF( KApplicationAttr ) ||
+ KErrNotFound !=
+ attribute.DesC().FindF( KXApplicationAttr ) ) &&
+ KErrNotFound !=
+ attributeField->Value().FindF( KNokiaRtvs ) )
+ {
+ //attribute found
+ vsattributefound = ETrue;
+ }
+ }
+ }
+ }
+ }
+
+ // Video Sharing is assumed if nokia vs specific attributes are found
+ // or if there is at least one m=video line and all media fields have
+ // sendonly attribute.
+ TBool retval = ( vsattributefound ||
+ ( videofields > 0 && fieldcount == sendonlycount ) );
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::CheckForVSAttributes(),ret:%d", retval )
+
+ return retval;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CSipMXResolver::ResolveVSUid
+// ---------------------------------------------------------------------------
+//
+TUid CSipMXResolver::ResolveVSUidL( const RStringF& aMethod )
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::ResolveVSUidL()" )
+
+ TUid muid = KNullUid;
+
+ if ( iMuSManager )
+ {
+ if ( aMethod == SIPStrings::StringF( SipStrConsts::EOptions ) )
+ {
+ muid.iUid = ( TInt32 ) CMusManager::ESipOptions;
+ }
+ else
+ {
+ MultimediaSharing::TMusAvailabilityStatus capability =
+ iMuSManager->AvailabilityL();
+
+ //check if availability value is from non-error-range
+ if( capability >= KErrNone &&
+ capability < MultimediaSharing::EErrSipRegistration )
+ {
+ muid.iUid = ( TInt32 ) CMusManager::ESipInviteDesired;
+ }
+ else
+ {
+ muid.iUid = ( TInt32 ) CMusManager::ESipInviteNotDesired;
+ }
+ }
+ }
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::ResolveVSUidL(), ret:%d", muid.iUid )
+
+ return muid;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSipMXResolver::ResolveCPPluginUidL
+// -----------------------------------------------------------------------------
+//
+void CSipMXResolver::ResolveCPPluginUidL( TUid& aUid, const CUri8& aRequestUri )
+ {
+ SIPMXRLOG( "[SIPMXRESOLVER] -> CSipMXResolver::ResolveCPPluginUidL()" )
+
+ CSipClientResolverUtils* resolver = CSipClientResolverUtils::NewLC();
+ resolver->GetImplementationUidWithUserL(
+ aRequestUri.Uri().Extract( EUriUserinfo ), aUid );
+ CleanupStack::PopAndDestroy( resolver );
+
+ SIPMXRLOGP( \
+ "[SIPMXRESOLVER] <- CSipMXResolver::ResolveCPPluginUidL(),uID:%d", aUid.iUid )
+ }
+
+
+// End of File