diff -r 65a3ef1d5bd0 -r f742655b05bf voipplugins/sipmxresolver/src/sipmxresolver.cpp --- a/voipplugins/sipmxresolver/src/sipmxresolver.cpp Thu Aug 19 09:45:22 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,759 +0,0 @@ -/* -* 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 -#include -#include - -//for checking CS call status -#include - -//SIP message content parsing APIs -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//For checking dynamic voip status and MuS availability -#include -#include -#include - -//Multimedia Sharing client API -#include - -//Incoming Call Monitor API -#include - - -// 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 -_LIT8( KSIPMethodsInAllowHeader, "INVITE,ACK,CANCEL,OPTIONS,BYE,PRACK,SUBSCRIBE,REFER,NOTIFY,UPDATE"); // SIP Methods allowed by various plugins -_LIT8( KSIPExtensionsSupported, "100rel,timer,sec-agree"); //Extensions supported by various plugins - -/** - * Cleanup function for RPointerArray - * Called in case of a leave in SupportedSdpMediasL - */ -void CleanupSdpMediasArray( TAny* aObj ) - { - if ( aObj ) - { - static_cast*>( 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& 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& /*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& 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 CSipMXResolver::SupportedContentTypesL() - { - RPointerArray ret; - - CSIPContentTypeHeader* ctype = CSIPContentTypeHeader::DecodeL( KContentType ); - CleanupStack::PushL( ctype ); - ret.AppendL( ctype ); - CleanupStack::Pop( ctype ); - - return ret; - } - - -// --------------------------------------------------------------------------- -// CSipMXResolver::SupportedSdpMediasL -// --------------------------------------------------------------------------- -// -RPointerArray CSipMXResolver::SupportedSdpMediasL() - { - // Initialise return array - RPointerArray 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& aHeaders ) - { - SIPMXRLOG( "[SIPMXRESOLVER] -> \ - CSipMXResolver::AddClientSpecificHeadersForOptionsResponseL()" ) - //Add Allow Header - RPointerArray allowheaders = - CSIPAllowHeader::DecodeL(KSIPMethodsInAllowHeader); - TInt count = allowheaders.Count(); - for(TInt i = 0; i supportedheaders = - CSIPSupportedHeader::DecodeL(KSIPExtensionsSupported); - count = supportedheaders.Count(); - for(TInt j = 0; j 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& 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& 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(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& 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