--- a/voipplugins/sipmxresolver/src/sipmxresolver.cpp Tue Feb 02 00:05:57 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,734 +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 <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