voipplugins/voipadapters/voipxmlprovisioning/voipxmlprocessor/src/voipxmlsiphandler.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 19 Aug 2010 09:45:22 +0300
branchRCL_3
changeset 20 65a3ef1d5bd0
parent 18 8c9c07ad8b6b
permissions -rw-r--r--
Revision: 201031 Kit: 201033

/*
* Copyright (c) 2009-2010 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:  SIP handler for VoIP XML processor
*
*/


#include <e32cmn.h>
#include <coecntrl.h>
#include <sipmanagedprofile.h>
#include <sipmanagedprofileregistry.h>
#include <sysutil.h>
#include <wlaninternalpskeys.h>
#include <pathinfo.h>
#include <authority16.h>
#include <StringLoader.h>
#include <escapeutils.h>

#include "voipxmlutils.h"
#include "voipxmlsiphandler.h"
#include "voipxmlprocessorlogger.h"
#include "voipxmlprocessordefaults.h"

// ---------------------------------------------------------------------------
// CVoipXmlSipHandler::CVoipXmlSipHandler
// ---------------------------------------------------------------------------
//
CVoipXmlSipHandler::CVoipXmlSipHandler()
    {
    }

// ---------------------------------------------------------------------------
// CVoipXmlSipHandler::NewL
// ---------------------------------------------------------------------------
//
CVoipXmlSipHandler* CVoipXmlSipHandler::NewL()
    {
    CVoipXmlSipHandler* self = new ( ELeave ) CVoipXmlSipHandler;
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// CVoipXmlSipHandler::ConstructL
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::ConstructL()
    {
    DBG_PRINT( "CVoipXmlSipHandler::ConstructL begin" );

    // SIP Managed Profile Registry.
    iRegistry = CSIPManagedProfileRegistry::NewL( *this );

    // Create an empty SIP profile in which all settings will be set.
    iProfileType.iSIPProfileClass = TSIPProfileTypeInfo::EInternet;
    iProfileType.iSIPProfileName.Copy( KIetf() );
    iProfile = iRegistry->CreateL( iProfileType );

    iProxyUri           = HBufC8::NewL( KMaxNodeValueLength );
    iProxyTransport     = EAutomatic;
    iProxyPort          = KErrNotFound;
    iLr                 = EFalse;
    iRegistrarUri       = HBufC8::NewL( KMaxNodeValueLength );
    iRegistrarTransport = EAutomatic;
    iRegistrarPort      = KErrNotFound;

    const TInt ipTosShift( 2 );
    const TUint32 tosBits( KDefaultSigQos << ipTosShift );
    iProfile->SetParameter( KSIPSoIpTOS, tosBits );

    DBG_PRINT( "CVoipXmlSipHandler::ConstructL end" );
    }

// ---------------------------------------------------------------------------
// CVoipXmlSipHandler::~CVoipXmlSipHandler
// ---------------------------------------------------------------------------
//
CVoipXmlSipHandler::~CVoipXmlSipHandler()
    {
    delete iProfile;
    delete iRegistry;
    delete iProxyUri;
    delete iRegistrarUri;
    }

// ---------------------------------------------------------------------------
// Sets SIP setting.
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::SetSetting( TInt aType, TInt aParam, 
    const TDesC8& aValue )
    {
    // Ignore too long descriptors.
    if ( KMaxNodeValueLength < aValue.Length() )
        {
        return;
        }

    switch ( aParam )
        {
        case EName:
            {
            TRAPD( err, CreateProviderNameL( aValue ) );
            if ( KErrNone == err )
                {
                iSettingsSet = ETrue;
                }
            break;
            }
        case ESignalingQos:
            {
            // We need to do bitshifting on the IP TOS, because it's the 
            // upper 6 bits that are set and settings provide us the IP TOS
            // as the lower 6 bits.
            // The lower 2 bits are reserver for explicit congestion
            // notification. 
            // See also more from:
            // Symbian Developer Library 
            //    => in_sock.h Global variables
            //       => KSoIpTOS
            const TInt ipTosShift( 2 );
            TInt value( KErrNotFound );
            // don't need to check return value because 'TInt value' is checked
            // coverity[check_return] coverity[unchecked_value]
            VoipXmlUtils::Des8ToInt( aValue, value );
            if ( 0 <= value )
                {
                const TUint32 tosBits( value << ipTosShift );
                iProfile->SetParameter( KSIPSoIpTOS, tosBits );
                iSettingsSet = ETrue;
                }
            break;
            }
        case EType:
            {
            TBuf8<KMaxNodeValueLength> value;
            value.Copy( aValue );
            value.UpperCase();
            if ( 0 == value.Compare( KIms() ) )
                {
                iProfileType.iSIPProfileClass = TSIPProfileTypeInfo::EIms;
                value.LowerCase();
                iProfileType.iSIPProfileName.Copy( value );
                iProfile->SetType( iProfileType );
                iSettingsSet = ETrue;
                }
            else if ( 0 == value.Compare( KIetf() ) )
                {
                iProfileType.iSIPProfileClass = 
                    TSIPProfileTypeInfo::EInternet;
                iProfileType.iSIPProfileName.Copy( value );
                iProfile->SetType( iProfileType );
                iSettingsSet = ETrue;
                }
            else
                {
                iProfileType.iSIPProfileClass = TSIPProfileTypeInfo::EOther;
                iProfileType.iSIPProfileName.Copy( aValue );
                iProfile->SetType( iProfileType );
                iSettingsSet = ETrue;
                }
            break;
            }
        case EPublicUserId:
            {
            TBuf8<KMaxNodeValueLength> value;
            value.Copy( aValue );
            TRAPD( err, ModifyPuidL( value ) );
            if ( KErrNone == err )
                {
                iProfile->SetParameter( KSIPUserAor, value );
                iSettingsSet = ETrue;
                }
            break;
            }
        case ESignalCompression:
            {
            TInt value;
            if ( KErrNone == VoipXmlUtils::Des8ToInt( aValue, value ) )
                {
                iProfile->SetParameter( KSIPSigComp, (TBool)value );
                iSettingsSet = ETrue;
                }
            break;
            }
        case ESecurityNegotiation:
            {
            TInt value;
            if ( KErrNone == VoipXmlUtils::Des8ToInt( aValue, value ) )
                {
                iProfile->SetParameter( 
                    KSIPSecurityNegotiation, (TBool)value );
                iSettingsSet = ETrue;
                }
            break;
            }
        case EProfileLock:
            {
            TInt value;
            if ( KErrNone == VoipXmlUtils::Des8ToInt( aValue, value ) )
                {
                iProfile->SetParameter( KSIPProfileLocked, (TBool)value );
                iSettingsSet = ETrue;
                }
            break;
            }
        case EAutoRegistration:
            {
            TInt value;
            if ( KErrNone == VoipXmlUtils::Des8ToInt( aValue, value ) )
                {
                iProfile->SetParameter( KSIPAutoRegistration, (TBool)value );
                iSettingsSet = ETrue;
                }
            break;
            }
        case EUri:
            {
            TBuf8<KMaxNodeValueLength> tempBuf( KNullDesC8 );
            if ( 0 != aValue.Find( KSip() ) &&
                0 != aValue.Find( KSips() ) )
                {
                tempBuf.Copy( KSip() );
                }
            tempBuf.Append( aValue );
            //lint -e{960} No need for else statement here
            if ( EProxy == aType )
                {
                iProxyUri->Des().Copy( tempBuf );
                iSettingsSet = ETrue;
                }
            else if ( ERegistrar == aType )
                {
                iRegistrarUri->Des().Copy( tempBuf );
                iSettingsSet = ETrue;
                }
            break;
            }
        case ETransport:
            {
            //lint -e{960} No need for else statement here
            if ( EProxy == aType )
                {
                iProxyTransport = ValidateTransport( aValue );
                iSettingsSet = ETrue;
                }
            else if ( ERegistrar == aType )
                {
                iRegistrarTransport = ValidateTransport( aValue );
                iSettingsSet = ETrue;
                }
            break;
            }
        case EPort:
            {
            TInt value;
            TInt err = VoipXmlUtils::Des8ToInt( aValue, value );
            //lint -e{960} No need for else statement here
            if ( EProxy == aType && KErrNone == err )
                {
                iProxyPort = value;
                iSettingsSet = ETrue;
                }
            else if ( ERegistrar == aType && KErrNone == err )
                {
                iRegistrarPort = value;
                iSettingsSet = ETrue;
                }
            break;
            }
        case ELooseRouting:
            {
            TInt value;
            if ( EProxy == aType && 
                KErrNone == VoipXmlUtils::Des8ToInt( aValue, value ) )
                {
                iLr = (TBool)value;
                iSettingsSet = ETrue;
                }
            break;
            }
        case EUsername:
            {
            //lint -e{960} No need for else statement here
            if ( EProxy == aType )
                {
                if ( TSIPProfileTypeInfo::EInternet == 
                    iProfileType.iSIPProfileClass )
                    {
                    iProfile->SetParameter( KSIPOutboundProxy, 
                        KSIPDigestUserName, aValue );
                    iSettingsSet = ETrue;
                    }
                else
                    {
                    iProfile->SetParameter( KSIPPrivateIdentity, aValue );
                    iSettingsSet = ETrue;
                    }
                }
            else if ( ERegistrar == aType )
                {
                if ( TSIPProfileTypeInfo::EInternet == 
                    iProfileType.iSIPProfileClass )
                    {
                    iProfile->SetParameter( KSIPRegistrar, KSIPDigestUserName,
                        aValue );
                    iSettingsSet = ETrue;
                    }
                else
                    {
                    iProfile->SetParameter( KSIPPrivateIdentity, aValue );
                    iSettingsSet = ETrue;
                    }
                }
            break;
            }
        case EPassword:
            {
            //lint -e{960} No need for else statement here
            if ( EProxy == aType )
                {
                iProfile->SetParameter( KSIPOutboundProxy, KSIPDigestPassword,
                    aValue );
                iSettingsSet = ETrue;
                }
            else if ( ERegistrar == aType )
                {
                iProfile->SetParameter( KSIPRegistrar, KSIPDigestPassword,
                    aValue );
                iSettingsSet = ETrue;
                }
            break;
            }
        default:
            break;
        }
    }

// ---------------------------------------------------------------------------
// Stores settings to SIP managed profile registry.
// ---------------------------------------------------------------------------
//
TInt CVoipXmlSipHandler::StoreSettings()
    {
    if ( !iSettingsSet )
        {
        // No settings to be stored => method not supported.
        return KErrNotSupported;
        }

    TBuf8<KMaxNodeValueLength> tempBuf( KNullDesC8 );

    // ==============================
    // Set components to proxy URI.
    // ==============================
    //
    if ( KErrNotFound != iProxyPort )
        {
        tempBuf.Copy( KColon() );
        tempBuf.AppendNum( iProxyPort );
        }
    //lint -e{960} No need for else statement here
    if ( EUdp == iProxyTransport )
        {
        tempBuf.Append( KTransport() );
        tempBuf.Append( KUdp() );
        }
    else if ( ETcp == iProxyTransport )
        {
        tempBuf.Append( KTransport() );
        tempBuf.Append( KTcp() );
        }
    else if ( ETls == iProxyTransport )
        {
        tempBuf.Append( KTransport() );
        tempBuf.Append( KTls() );
        }
    if ( iLr )
        {
        tempBuf.Append( KLr() );
        }

    if ( iProxyUri->Des().MaxLength() >= 
        ( iProxyUri->Des().Length() + tempBuf.Length() ) )
        {
        iProxyUri->Des().Append( tempBuf );
        }
    iProfile->SetParameter( KSIPOutboundProxy, KSIPServerAddress, 
        iProxyUri->Des() );

    // ==============================
    // Set components to registrar URI.
    // ==============================
    //
    tempBuf.Zero();
    if ( KErrNotFound != iRegistrarPort )
        {
        tempBuf.Copy( KColon() );
        tempBuf.AppendNum( iRegistrarPort );
        }
    //lint -e{960} No need for else statement here
    if ( EUdp == iRegistrarTransport )
        {
        tempBuf.Append( KTransport() );
        tempBuf.Append( KUdp() );
        }
    else if ( ETcp == iRegistrarTransport )
        {
        tempBuf.Append( KTransport() );
        tempBuf.Append( KTcp() );
        }
    else if ( ETls == iProxyTransport )
        {
        tempBuf.Append( KTransport() );
        tempBuf.Append( KTls() );
        }
    if ( iRegistrarUri->Des().MaxLength() >= 
        ( iRegistrarUri->Des().Length() + tempBuf.Length() ) )
        {
        iRegistrarUri->Des().Append( tempBuf );
        }
    iProfile->SetParameter( KSIPRegistrar, KSIPServerAddress, 
        iRegistrarUri->Des() );

    TRAPD( err, iRegistry->SaveL( *iProfile ) );
    if ( KErrNone != err )
        {
        // No need for specifying what went wrong because paramhandler
        // is only intrested in KErrNotSupported, KErrCompletion and KErrNone.
        err = KErrCompletion;
        }
    // Store SIP settings ID for later use.
    iProfile->GetParameter( KSIPProfileId, iProfileId );
    return err;
    }

// ---------------------------------------------------------------------------
// Returns the profile ID if the profile saved in StoreSettings.
// ---------------------------------------------------------------------------
//
TUint32 CVoipXmlSipHandler::SettingsId()
    {
    return iProfileId;
    }

// ---------------------------------------------------------------------------
// Saves linkage information.
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::LinkSettings( TInt aType, TUint32 aSettingsId )
    {
    if ( EDestination == aType && aSettingsId )
        {
        iProfile->SetParameter( KSIPSnapId, aSettingsId );
        }
    }

// ---------------------------------------------------------------------------
// Finalizes settings saving.
// ---------------------------------------------------------------------------
//
TInt CVoipXmlSipHandler::FinalizeSettings()
    {
    TRAPD( err, iRegistry->SaveL( *iProfile ) );
    if ( KErrNone != err )
        {
        // ParamHandler is only intrested in KErrNone and KErrCompletion.
        err = KErrCompletion;
        }
    return err;
    }

// ---------------------------------------------------------------------------
// From class MSIPProfileRegistryObserver.
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::ProfileRegistryEventOccurred( 
    TUint32 /*aSIPProfileId*/, TEvent /*aEvent*/ )
    {
    }

// ---------------------------------------------------------------------------
// From class MSIPProfileRegistryObserver. 
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::ProfileRegistryErrorOccurred( 
    TUint32 /*aSIPProfileId*/, TInt /*aError*/ )
    {
    }

// ---------------------------------------------------------------------------
// CVoipXmlSipHandler::CreateProviderNameL
// Checks if duplicate named SIP profiles. Renames if same.
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::CreateProviderNameL( const TDesC8& aName )
    {
    DBG_PRINT( "CVoipXmlSipHandler::CreateProviderNameL begin" );
    
    const TInt maxModifyLength = 
        KMaxNodeNameLength - KMaxProfileNameAppendLength;
    
    RPointerArray<CSIPProfile> profiles;
    CleanupResetAndDestroyL( profiles ); // CS:1
    
    // Get all profiles based on profile types.
    iRegistry->ProfilesL( profiles );
    const TInt profileCount = profiles.Count();
    
    // Go through loaded profiles and check for name duplicates.
    HBufC8* name = HBufC8::NewLC( KMaxNodeNameLength ); // CS:2
    name->Des().Copy( aName.Left( maxModifyLength ) );
    TUint i( 1 ); // Add number to the name if name already in use.
    const TInt count( profiles.Count() );
    for ( TInt counter = 0; counter < count; counter++ )
        {
        CSIPManagedProfile* profile = 
            static_cast<CSIPManagedProfile*>( profiles[counter] );
        const TDesC8* existingName;
        profile->GetParameter( KSIPProviderName, existingName );
        if ( 0 == existingName->Compare( *name ) )
            {
            name->Des().Copy( aName.Left( maxModifyLength ) );
            name->Des().Append( KOpenParenthesis8() );
            name->Des().AppendNum( i );
            name->Des().Append( KClosedParenthesis8() );  
            counter = 0;
            i++;
            if ( KMaxProfileNames < i )
                {
                User::Leave( KErrBadName );
                }
            }
        }
    iProfile->SetParameter( KSIPProviderName, name->Des() );

    // name, &profiles
    CleanupStack::PopAndDestroy( 2, &profiles ); // CS:0
    DBG_PRINT( "CVoipXmlSipHandler::CreateProviderNameL end" );
    }

// ---------------------------------------------------------------------------
// Modifies public user ID, i.e. escapes and adds sip: prefix if necessary.
// ---------------------------------------------------------------------------
//
void CVoipXmlSipHandler::ModifyPuidL( TDes8& aValue )
    {
    if ( KErrNotFound == aValue.Find( KEscaped() ) )
        {
        HBufC8* tempPuid = EscapeUtils::EscapeEncodeL( aValue,
            EscapeUtils::EEscapeNormal );
        aValue.Copy( tempPuid->Des() );
        delete tempPuid;
        tempPuid = NULL;
        }
    if ( 0 != aValue.Find( KSip() ) && 0 != aValue.Find( KSips() ) )
        {
        if ( aValue.MaxLength() >= ( aValue.Length() + KSip().Length() ) )
            {
            aValue.Insert( 0, KSip() );
            }
        else
            {
            User::Leave( KErrTooBig );
            }
        }
    }

// ---------------------------------------------------------------------------
// Validates transport type.
// ---------------------------------------------------------------------------
//
CVoipXmlSipHandler::TTransportType CVoipXmlSipHandler::ValidateTransport( 
    const TDesC8& aValue )
    {
    TBuf8<KMaxNodeValueLength> value;
    value.Copy( aValue );
    value.UpperCase();
    if ( 0 == value.Compare( KUdp() ) )
        {
        return EUdp;
        }
    else if ( 0 == value.Compare( KTcp() ) )
        {
        return ETcp;
        }
    else if ( 0 == value.Compare( KTls() ) )
        {
        return ETls;
        }
    else
        {
        return EAutomatic;
        }
    }

// End of file.