diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmceserver/src/mcesipextensions.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcesrv/mmceserver/src/mcesipextensions.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,610 @@ +/* +* Copyright (c) 2005 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: +* +*/ + + + +#include +#include +#include +#include +#include +#include +#include +#include "mcesipextensions.h" +#include "mcedictionary.h" +#include "mcesip.h" +#include "mcecomsession.h" + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::CMceSipExtensions +// ----------------------------------------------------------------------------- +// +CMceSipExtensions* CMceSipExtensions::NewL() + { + CMceSipExtensions* self = new( ELeave ) CMceSipExtensions(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::CMceSipExtensions +// ----------------------------------------------------------------------------- +// +CMceSipExtensions::CMceSipExtensions() + { + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::ConstructL +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::ConstructL() + { + iLocal = new( ELeave ) CMceDictionary(); + AddDefaultsL( *iLocal ); + iRemote = new( ELeave ) CMceDictionary(); + AddDefaultsL( *iRemote ); + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::~CMceSipExtensions +// ----------------------------------------------------------------------------- +// +CMceSipExtensions::~CMceSipExtensions() + { + delete iLocal; + delete iRemote; + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::Local +// ----------------------------------------------------------------------------- +// +CMceSipExtensions::TLevel CMceSipExtensions::Local( TExtension aExtension ) + { + return Level( *iLocal, aExtension ); + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::Remote +// ----------------------------------------------------------------------------- +// +CMceSipExtensions::TLevel CMceSipExtensions::Remote( TExtension aExtension ) + { + return Level( *iRemote, aExtension ); + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::SetLocal +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::SetLocal( TExtension aExtension, TLevel aLevel ) + { + SetLevel( *iLocal, aExtension, aLevel ); + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::SetRemote +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::SetRemote( TExtension aExtension, TLevel aLevel ) + { + SetLevel( *iRemote, aExtension, aLevel ); + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::AddDefaultsL +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::AddDefaultsL( CMceDictionary& aDictionary ) + { + // Addin all the MCE extension headers Update, Subscribe, Prack, Refer, Notify + RArray< TExtension > extMethods; + CleanupClosePushL( extMethods ); + LocalSipExtensionsL( extMethods ); + + for (TInt index=0; index < extMethods.Count(); index++ ) + { + CMceDictionaryItem* extObj = + new( ELeave ) CMceKeyTValuePair( + static_cast(extMethods[ index ]), ESupported ); + CleanupStack::PushL( extObj ); + aDictionary.AddL( extObj ); + CleanupStack::Pop( extObj ); + } + CleanupStack::PopAndDestroy( &extMethods ); + + // 100rel + CMceDictionaryItem* item100rel = + new( ELeave ) CMceKeyTValuePair( E100rel, ESupported ); + CleanupStack::PushL( item100rel ); + aDictionary.AddL( item100rel ); + CleanupStack::Pop( item100rel ); + + // QOS preconditions + CMceDictionaryItem* itemQosPreconds = + new( ELeave ) CMceKeyTValuePair( EQosPreconds, ESupported ); + CleanupStack::PushL( itemQosPreconds ); + aDictionary.AddL( itemQosPreconds ); + CleanupStack::Pop( itemQosPreconds ); + + //SEC precondition + CMceDictionaryItem* itemSecPreconds = + new( ELeave ) CMceKeyTValuePair( ESecPreconds, ESupported ); + CleanupStack::PushL( itemSecPreconds ); + aDictionary.AddL( itemSecPreconds ); + CleanupStack::Pop( itemSecPreconds ); + + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::Level +// ----------------------------------------------------------------------------- +// +CMceSipExtensions::TLevel CMceSipExtensions::Level( + const CMceDictionary& aDictionary, + TExtension aExtension ) const + { + TLevel ret = ENotSupported; + CMceKeyTValuePair* pair = static_cast*> + ( aDictionary.Pair( aExtension ) ); + if ( pair ) + { + ret = pair->Value(); + } + return ret; + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::SetLevel +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::SetLevel( CMceDictionary& aDictionary, + TExtension aExtension, + TLevel aLevel ) + { + CMceKeyTValuePair* pair = static_cast*> + ( aDictionary.Pair( aExtension ) ); + if ( pair ) + { + pair->SetValue( aLevel ); + } + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::LevelL +// ----------------------------------------------------------------------------- +// +CMceSipExtensions::TLevel CMceSipExtensions::LevelL( + CSIPTransactionBase& aTransaction, + CMceSipExtensions::TExtension aExtension ) + { + CMceSipExtensions::TLevel level = CMceSipExtensions::ENotSupported; + TInt reqInd = SipStrConsts::ERequireHeader; + TInt suppInd = SipStrConsts::ESupportedHeader; + TInt allowInd = SipStrConsts::EAllowHeader; + + const CSIPMessageElements* elements = MceSip::ToMessageElements( aTransaction ); + if ( elements ) + { + switch ( aExtension ) + { + case CMceSipExtensions::E100rel: + { + if ( MceSip::HasHeaderValueL( *elements, reqInd, KMceSip100Rel ) ) + { + level = CMceSipExtensions::ERequired; + } + else if ( MceSip::HasHeaderValueL( *elements, + suppInd, + KMceSip100Rel ) ) + { + level = CMceSipExtensions::ESupported; + } + else + { + // NOP + } + break; + } + case CMceSipExtensions::EQosPreconds: + case CMceSipExtensions::ESecPreconds: + { + if ( MceSip::HasHeaderValueL( *elements, reqInd, KMceSipPrecondition ) ) + { + level = CMceSipExtensions::ERequired; + } + else if ( MceSip::HasHeaderValueL( *elements, + suppInd, + KMceSipPrecondition ) ) + { + level = CMceSipExtensions::ESupported; + } + else + { + // NOP + } + break; + } + case CMceSipExtensions::EUpdate: + { + if ( MceSip::HasHeaderValueL( *elements, allowInd, + SIPStrings::StringF( SipStrConsts::EUpdate ).DesC() ) ) + { + level = CMceSipExtensions::ESupported; + } + break; + } + case CMceSipExtensions::ESubscribe: + { + if ( MceSip::HasHeaderValueL( *elements, allowInd, + SIPStrings::StringF( SipStrConsts::ESubscribe ).DesC() ) ) + { + level = CMceSipExtensions::ESupported; + } + break; + } + case CMceSipExtensions::ERefer: + { + if ( MceSip::HasHeaderValueL( *elements, allowInd, + SIPStrings::StringF( SipStrConsts::ERefer ).DesC() ) ) + { + level = CMceSipExtensions::ESupported; + } + break; + } + case CMceSipExtensions::ENotify: + { + if ( MceSip::HasHeaderValueL( *elements, allowInd, + SIPStrings::StringF( SipStrConsts::ENotify ).DesC() ) ) + { + level = CMceSipExtensions::ESupported; + } + break; + } + case CMceSipExtensions::EPrack: + { + if ( MceSip::HasHeaderValueL( *elements, allowInd, + SIPStrings::StringF( SipStrConsts::EPrack ).DesC() ) ) + { + level = CMceSipExtensions::ESupported; + } + break; + } + default: + { + // NOP + break; + } + } + } + return level; + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::UpdateL +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::UpdateL( CSIPServerTransaction& aTransaction ) + { + const CSIPMessageElements* msg = MceSip::ToMessageElements( aTransaction ); + User::LeaveIfError( msg ? KErrNone : KErrArgument ); + + // Get the values before updating anything. If a leave happens, the + // values remain not modified. + TLevel remote100rel = LevelL( aTransaction, CMceSipExtensions::E100rel ); + + TLevel remoteQosPrecond = LevelL( aTransaction, + CMceSipExtensions::EQosPreconds ); + TLevel remoteSecPrecond = LevelL( aTransaction, + CMceSipExtensions::ESecPreconds ); + + // Check if the local valus will be modified + TLevel local100rel = Local( CMceSipExtensions::E100rel ); + if ( remote100rel == CMceSipExtensions::ERequired ) + { + if ( local100rel == CMceSipExtensions::ENotSupported ) + { + User::Leave( KErrNotSupported ); + } + else + { + local100rel = remote100rel; + } + } + + TLevel localQosPrecond = Local( CMceSipExtensions::EQosPreconds ); + if ( remoteQosPrecond == CMceSipExtensions::ERequired ) + { + if ( localQosPrecond == CMceSipExtensions::ENotSupported ) + { + User::Leave( KErrNotSupported ); + } + else + { + localQosPrecond = remoteQosPrecond; + } + } + + TLevel localSecPrecond = Local( CMceSipExtensions::ESecPreconds ); + if ( remoteSecPrecond == CMceSipExtensions::ERequired ) + { + if ( localSecPrecond == CMceSipExtensions::ENotSupported && + localQosPrecond == CMceSipExtensions::ENotSupported ) + { + User::Leave( KErrNotSupported ); + } + else + { + localSecPrecond = remoteSecPrecond; + } + } + + // Finally set the values, first local + // 100rel + SetLocal( CMceSipExtensions::E100rel, local100rel ); + + // precond + SetLocal( CMceSipExtensions::EQosPreconds, localQosPrecond ); + + // sec precond + SetLocal( CMceSipExtensions::ESecPreconds, localSecPrecond ); + + // then remote + // 100rel + SetRemote( CMceSipExtensions::E100rel, remote100rel ); + + // precond + SetRemote( CMceSipExtensions::EQosPreconds, remoteQosPrecond ); + + //sec precond + SetRemote( CMceSipExtensions::ESecPreconds, remoteSecPrecond ); + + // MCE sipextension allow header : UPDATE, PRACk, Subscribe, REfer, Notify + + SetExtensionAllowHeadersL( msg ); + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::UpdateL +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::UpdateL( CSIPClientTransaction& aTransaction ) + { + const CSIPMessageElements* msg = MceSip::ToMessageElements( aTransaction ); + User::LeaveIfError( msg ? KErrNone : KErrArgument ); + + if ( MceSip::ResponseCode( aTransaction ) == KMceSipExtensionRequired ) + { + TBool reqPreconds = MceSip::HasHeaderValueL( + *msg, + SipStrConsts::ERequireHeader, + KMceSipPrecondition ); + if ( reqPreconds ) + { + // needs to require preconditions locally, if possible + if ( Local( CMceSipExtensions::EQosPreconds ) != + CMceSipExtensions::ENotSupported ) + { + SetLocal( CMceSipExtensions::EQosPreconds, + CMceSipExtensions::ERequired ); + } + else if (Local( CMceSipExtensions::ESecPreconds ) != + CMceSipExtensions::ENotSupported && + Local( CMceSipExtensions::EQosPreconds ) == + CMceSipExtensions::ENotSupported ) + { + SetLocal( CMceSipExtensions::ESecPreconds, + CMceSipExtensions::ERequired ); + } + else + { + User::Leave( KErrNotSupported ); + } + } + else + { + // "Require: precondition" is the only extension required in 421 response + // that may lead to a retried INVITE. + // All the other required extensions to the initial INVITE terminate the + // session. + User::Leave( KErrNotSupported ); + } + } + else if ( MceSip::ResponseType( aTransaction ) == E1XX || + MceSip::ResponseType( aTransaction ) == E2XX ) + { + if ( MceSip::ResponseType( aTransaction ) == E1XX && + Local( CMceSipExtensions::E100rel ) == + CMceSipExtensions::ERequired ) + { + // use of 100rel extension is required locally, + // check, that provisional response is sent reliably + TBool req100Rel = MceSip::HasHeaderValueL( + *msg, + SipStrConsts::ERequireHeader, + KMceSip100Rel ); + User::LeaveIfError( req100Rel ? KErrNone : KErrNotSupported ); + } + + SetExtensionAllowHeadersL( msg ); + } + else + { + // NOP + } + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::Update +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::Update( CMceComSession& aBody ) + { + for ( TInt i = 0; i< aBody.iSessionModifiers.Count(); i++ ) + { + Update( i, aBody.Modifier( i ) ); + } + } + +// ----------------------------------------------------------------------------- +// CMceSipExtensions::Update +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::Update( TMceSessionModifier aModifier, TUint aValue ) + { + TInt extension = KErrNotFound; + TInt level = KErrNotFound; + + switch ( aModifier ) + { + case KMcePreconditions: + { + extension = CMceSipExtensions::EQosPreconds; + if ( aValue == KMcePreconditionsNotUsed ) + { + level = CMceSipExtensions::ENotSupported; + } + else if ( aValue == KMcePreconditionsSupported ) + { + level = CMceSipExtensions::ESupported; + } + else + { + // NOP + } + break; + } + case KMceSecPreconditions: + { + extension = CMceSipExtensions::ESecPreconds; + if ( aValue == KMcePreconditionsNotUsed ) + { + level = CMceSipExtensions::ENotSupported; + } + else if ( aValue == KMcePreconditionsE2ESupported ) + { + level = CMceSipExtensions::ESupported; + } + else + { + // NOP + } + break; + } + case KMce100Rel: + { + extension = CMceSipExtensions::E100rel; + if ( aValue == KMce100RelNotUsed ) + { + level = CMceSipExtensions::ENotSupported; + } + else if ( aValue == KMce100RelSupported ) + { + level = CMceSipExtensions::ESupported; + } + else if ( aValue == KMce100RelRequired ) + { + level = CMceSipExtensions::ERequired; + } + else + { + // NOP + } + break; + } + default: + { + // NOP + break; + } + } + if ( extension != KErrNotFound && level != KErrNotFound ) + { + SetLocal( ( CMceSipExtensions::TExtension ) ( extension ), + ( CMceSipExtensions::TLevel ) ( level ) ); + } + } +// ----------------------------------------------------------------------------- +// CMceSipExtensions::RemoteIMSRel5 +// ----------------------------------------------------------------------------- +// +TBool CMceSipExtensions::RemoteIMSRel5() + { + CMceSipExtensions::TLevel localQos = + Local( CMceSipExtensions::EQosPreconds ); + + return ( localQos == CMceSipExtensions::ERequired ); + } + + // ----------------------------------------------------------------------------- +// CMceSipExtensions::ExtensionAllowMethods +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::ExtensionAllowMethodsL( RArray& aArray ) + { + User::LeaveIfError( aArray.Append( SipStrConsts::EUpdate )); + User::LeaveIfError( aArray.Append( SipStrConsts::EPrack )); + User::LeaveIfError( aArray.Append( SipStrConsts::ESubscribe )); + User::LeaveIfError( aArray.Append( SipStrConsts::ERefer )); + User::LeaveIfError( aArray.Append( SipStrConsts::ENotify )); + } + + // ----------------------------------------------------------------------------- +// CMceSipExtensions::LocalSipExtensions +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::LocalSipExtensionsL( RArray& aArray ) + { + User::LeaveIfError( aArray.Append( CMceSipExtensions::EUpdate )); + User::LeaveIfError( aArray.Append( CMceSipExtensions::EPrack )); + User::LeaveIfError( aArray.Append( CMceSipExtensions::ESubscribe )); + User::LeaveIfError( aArray.Append( CMceSipExtensions::ERefer )); + User::LeaveIfError( aArray.Append( CMceSipExtensions::ENotify )); + } + + // ----------------------------------------------------------------------------- +// CMceSipExtensions::SetExtensionAllowHeaders +// ----------------------------------------------------------------------------- +// +void CMceSipExtensions::SetExtensionAllowHeadersL( const CSIPMessageElements* aMessage ) + { + RArray< TExtension > localExts; + CleanupClosePushL( localExts ); + RArray< TInt> extMethods; + CleanupClosePushL( extMethods ); + TInt index = 0; + LocalSipExtensionsL( localExts ); + ExtensionAllowMethodsL( extMethods ); + + for ( index=0; index < extMethods.Count(); index++ ) + { + + TBool extMethod = MceSip::HasHeaderValueL( + *aMessage, + SipStrConsts::EAllowHeader, + SIPStrings::StringF( extMethods[index] ).DesC() ); + + SetRemote( localExts[ index ], extMethod ? + ESupported : ENotSupported ); + } + CleanupStack::PopAndDestroy( &extMethods ); + CleanupStack::PopAndDestroy( &localExts ); + } +// End of file