phoneclientserver/phoneserver/Src/Standard/CPhSrvSession.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:15:03 +0100
branchRCL_3
changeset 20 987c9837762f
parent 19 7d48bed6ce0c
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2002-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:  Session.
*
*/



// INCLUDE FILES
#include "CPhSrvServer.h"
#include "CPhSrvSession.h"
#include "CPhSrvSubSessionBase.h"
#include "PhSrvSubSessionFactory.h"
#include "PhCltClientServer.h"

// CONSTANTS



// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CPhSrvSession::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CPhSrvSession* CPhSrvSession::NewL( CPhSrvServer& aServer )   
    {
    CPhSrvSession* self = new ( ELeave ) CPhSrvSession();
    CleanupStack::PushL( self );
    self->ConstructL( aServer );
    CleanupStack::Pop();
    return self;
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::CPhSrvSession
// C++ constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CPhSrvSession::CPhSrvSession() 
    {
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::~CPhSrvSession
// Destructor.
// -----------------------------------------------------------------------------
//

CPhSrvSession::~CPhSrvSession()
    {
    if ( iServer )
        {
        iServer->CancelCreateAll( *this );
        }

    delete iObjectIx;

    if ( iContainer )
        {
        //coverity[var_deref_model]
        iServer->RemoveContainer( iContainer );
        iContainer = NULL;
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::ServiceL
// 
// Calls DispatchMessageL under trap harness.
// -----------------------------------------------------------------------------
//
void CPhSrvSession::ServiceL( const RMessage2& aMessage )  
    {
    TRAPD( err, ProcessRequestL( aMessage ) );
    if ( err != KErrNone )
        {
        aMessage.Complete( err );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::ProcessRequestL
// 
// Checks the function specified by the client message
// and depending on the type, performs an appropriate action.
//
// If the function is one of the "special" factory sub-session
// creation op-codes, then this session will process it.
//
// If the function is a generic subsession function, then the
// subsession which can handle this function is identified by
// it's unique handle, and it is asked to process the request.
//
// -----------------------------------------------------------------------------
//
void CPhSrvSession::ProcessRequestL( const RMessage2& aMessage )
    {
    if ( HandleCommandL( aMessage ) )
        {
        return;
        }

    const TInt function = aMessage.Function();
    const TUint32 sid = aMessage.SecureId().iId;
    
    // Is this a message that results in a new subsession?
    if  ( PhSrvSubSessionFactory::PhSrvSubSessionFactoryIsCreationFunction( 
          function ) )
        {
        if ( !PhSrvSubSessionFactory::PhSrvSubSessionFactoryIsCreationAllowed(
            function,
            sid ) )
            {
            aMessage.Complete( KErrPermissionDenied );
            }
        else
            {
            // Need to create a new subsession
            CPhSrvSubSessionBase* subSession = 
                PhSrvSubSessionFactory::PhSrvSubSessionFactoryCreateLC( 
                    function, 
                    *this );

            // Add to container (takes ownership)
            iContainer->AddL( subSession );
            if (function != EPhoneServerImageHandlerSubSessionOpen )
                {
                CleanupStack::Pop( subSession );    
                }
            // Get a handle for the object
            const TInt handle = iObjectIx->AddL( subSession );

            // Inform client of the handle its been allocated
            TPckg<TInt> handlePckg( handle );
            Write( 
                aMessage,
                3,
                handlePckg );

            if ( !aMessage.IsNull() )
                {
                // Complete the message
                aMessage.Complete( KErrNone );
                }
             }    
         }
    else
        {
        // Find an appropriate object and pass the message to it
        // for processing...
        const TInt handle = aMessage.Int3();

        // Fetch the sub-session by its handle
        CObject* object = iObjectIx->At( handle );
        if ( !object )
            {
            PanicClient(
                aMessage,
                EPhCltServerInitiatedPanicInvalidHandle );
            }

        // We can cast the object to a subsession instance, since that's
        // all we store in the object container
        CPhSrvSubSessionBase* subSession = 
            static_cast< CPhSrvSubSessionBase* >( object );
        
        if ( subSession )
            {
	        // Check that the subsession can handle this request
	        if ( !subSession->PhSrvMessageDecoderCanProcessMessage( function ) )
	            {
	            PanicClient(
	                aMessage,
	                EPhCltServerInitiatedPanicInvalidHandle );
	            }
	        else
	            {
	            // Get it to process this request
	            subSession->PhSrvMessageProcessorHandleMessageL( aMessage );
	            }
            }            
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::SubSessionCount
// 
// Return the number of subsessions
// -----------------------------------------------------------------------------
//
TInt CPhSrvSession::SubSessionCount() const
    {
    return iContainer->Count();
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::SubSessionA
// 
// Return a subsession from an index
// -----------------------------------------------------------------------------
//
CPhSrvSubSessionBase& CPhSrvSession::SubSessionAt( TInt aIndex ) const
    {
    return *static_cast< CPhSrvSubSessionBase* >( ( *iContainer )[ aIndex ] );
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::CloseSubsession
// 
// Remove object from object index
// -----------------------------------------------------------------------------
//
void CPhSrvSession::CloseSubSession( const RMessage2& aMessage )
    {
    TInt handle = aMessage.Int3();

    CObject* obj = iObjectIx->At( handle );  
    __ASSERT_ALWAYS( obj, 
        PanicClient(
            aMessage,
            EPhCltServerInitiatedPanicInvalidHandle ) );
    iObjectIx->Remove( handle );

    if ( !aMessage.IsNull() )
        {
        aMessage.Complete( KErrNone );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::PanicClient
// 
// Panic the client's thread
// -----------------------------------------------------------------------------
//
void CPhSrvSession::PanicClient(
    const RMessage2& aMessage,
    TPhCltServerInitiatedPanic aPanic ) const    
    {
    if ( !aMessage.IsNull() )
        {
        _LIT( KPhServerPanicCategory, "PhSrvServer" );
        aMessage.Panic( KPhServerPanicCategory, aPanic );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::ConstructL
// 
// Symbian OS 2nd phase constructor
// -----------------------------------------------------------------------------
//
void CPhSrvSession::ConstructL( CPhSrvServer& aServer )
    {
    iContainer = aServer.NewContainerL();
    iObjectIx = CObjectIx::NewL();   
    
    iServer = &aServer;
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::SubSessionUniqueHandle
// 
// Return the unique handle for the specified subsession
// -----------------------------------------------------------------------------
//
TInt CPhSrvSession::SubSessionUniqueHandle( 
    const CPhSrvSubSessionBase& aSubSession ) const
    {
    // Ensure that the handle really is unique.
    // return iObjectIx->At( &aSubSession ); is unique only in same session.
    return reinterpret_cast<TInt>( &aSubSession );
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::PhoneServer
// 
// Returns the Phone Server
// -----------------------------------------------------------------------------
//
CPhSrvServer& CPhSrvSession::PhoneServer() const
    {
    return *static_cast< CPhSrvServer* >( const_cast< CServer2* >( Server() ) );
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::Write
// 
// Write to the client address space. Panic client upon error
// -----------------------------------------------------------------------------
//
void CPhSrvSession::Write( 
    const RMessage2& aMessage,
    TInt aLocation,
    const TDesC8& aDes,
    TInt aOffset )
    {
    TInt ret = aMessage.Write( aLocation, aDes, aOffset );
    if ( ret != KErrNone )
        {
        PanicClient( 
            aMessage,
            EPhCltServerInitiatedPanicBadDescriptor );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::Read
// 
// Read from the client address space. Panic client upon error
// -----------------------------------------------------------------------------
//
void CPhSrvSession::Read(
    const RMessage2& aMessage,
    TInt aLocation,
    TDes8& aDes,
    TInt aOffset )
    {
    TInt ret = aMessage.Read( aLocation, aDes, aOffset );
    if ( ret != KErrNone )
        {
        PanicClient( 
            aMessage,
            EPhCltServerInitiatedPanicBadDescriptor );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::Read
// 
// Read from the client address space. Panic client upon error
// -----------------------------------------------------------------------------
//
void CPhSrvSession::Read(
    const RMessage2& aMessage,
    TInt aLocation,
    TDes& aDes,
    TInt aOffset )
    {
    TInt ret = aMessage.Read( aLocation, aDes, aOffset );
    if ( ret != KErrNone )
        {
        PanicClient( 
            aMessage,
            EPhCltServerInitiatedPanicBadDescriptor );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::CompleteCreateAll
// -----------------------------------------------------------------------------
//
void CPhSrvSession::CompleteCreateAll( TInt aError )
    {
    if ( iCreateAll )
        {
        iCreateAll = EFalse;
        iCreateAllMsg.Complete( aError );
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvSession::HandleCommandL
// -----------------------------------------------------------------------------
//
TBool CPhSrvSession::HandleCommandL( const RMessage2& aMessage )
    {
    TBool result = EFalse;

    switch ( aMessage.Function() )
        {
        case EPhoneCreateAll:
            result = ETrue;
            
            iServer->CancelCreateAll( *this );
            iServer->CreateAllL( *this );
            
            iCreateAll = ETrue;
            iCreateAllMsg = aMessage;
            break;
        
        default:
            break;
        }

    return result;
    }


//  End of File