multimediacommsengine/mmcesrv/mmceserver/src/mcesipextensions.cpp
changeset 0 1bce908db942
--- /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 <badesca.h>
+#include <sipservertransaction.h>
+#include <sipclienttransaction.h>
+#include <sipstrings.h>
+#include <sipstrconsts.h>
+#include <sipmessageelements.h>
+#include <siprequireheader.h>
+#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<TLevel>( 
+	        	static_cast<TInt>(extMethods[ index ]), ESupported );
+	    CleanupStack::PushL( extObj );
+	    aDictionary.AddL( extObj );
+	    CleanupStack::Pop( extObj );
+    	}
+    CleanupStack::PopAndDestroy( &extMethods );
+    
+    // 100rel
+    CMceDictionaryItem* item100rel = 
+        new( ELeave ) CMceKeyTValuePair<TLevel>( E100rel, ESupported );
+    CleanupStack::PushL( item100rel );
+    aDictionary.AddL( item100rel );
+    CleanupStack::Pop( item100rel );
+    
+    // QOS preconditions
+    CMceDictionaryItem* itemQosPreconds = 
+        new( ELeave ) CMceKeyTValuePair<TLevel>( EQosPreconds, ESupported );
+    CleanupStack::PushL( itemQosPreconds );
+    aDictionary.AddL( itemQosPreconds );
+    CleanupStack::Pop( itemQosPreconds );
+    
+    //SEC precondition
+    CMceDictionaryItem* itemSecPreconds = 
+        new( ELeave ) CMceKeyTValuePair<TLevel>( 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<TLevel>* pair = static_cast<CMceKeyTValuePair<TLevel>*>
+        ( aDictionary.Pair( aExtension ) );
+    if ( pair )
+        {
+        ret = pair->Value();
+        }
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceSipExtensions::SetLevel
+// -----------------------------------------------------------------------------
+//
+void CMceSipExtensions::SetLevel( CMceDictionary& aDictionary, 
+                                  TExtension aExtension, 
+                                  TLevel aLevel )
+    {
+    CMceKeyTValuePair<TLevel>* pair = static_cast<CMceKeyTValuePair<TLevel>*>
+        ( 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<TInt>& 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<TExtension>& 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