videoscheduler/SchedulerServer/src/CCseSchedulerServer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Mar 2010 09:48:59 +0200
changeset 15 6c92a12abac0
parent 0 822a42b6c3f1
child 16 ae43a6765dd5
permissions -rw-r--r--
Revision: 201005 Kit: 201011

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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 Scheduler server's Server class*
*/




// INCLUDE FILES
#include "CCseSchedulerServer.h"                // Header file for this class
#include "CCseSchedulerServerSession.h"         // Server session
#include "CCseSchedulerServerEngine.h"          // Server intelligence aka engine
#include <ipvideo/cseschedulerclientservercommon.h>     // Common defines for client and server
#include "CseSchedulerServer.pan"               // Server panic codes
#include "CseDebug.h"                           // Debug macros
#include <e32svr.h>
#include <e32math.h>
#include <e32uid.h>
#include <e32def.h>


// EXTERNAL DATA STRUCTURES
// None

// EXTERNAL FUNCTION PROTOTYPES  
// None

// CONSTANTS
// Platform security. Custom check is applied to all IPCs.
static const int KRangeCount( 1 );

static const TInt SecurityRanges[KRangeCount] =
    {
    0, // Range is from 0 to KMaxTInt
    };

static const TUint8 SecurityRangesPolicy[KRangeCount] =
    {
    CPolicyServer::ECustomCheck
    };

static const CPolicyServer::TPolicy Policy =
    {
    CPolicyServer::EAlwaysPass,
    KRangeCount,
    SecurityRanges,
    SecurityRangesPolicy,
    NULL,
    };


// MACROS
// None

// LOCAL CONSTANTS AND MACROS
const TInt KDbStartTimeout              = 2000000;

// MODULE DATA STRUCTURES
// None

// LOCAL FUNCTION PROTOTYPES
// None

// FORWARD DECLARATIONS
// None

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

// -----------------------------------------------------------------------------
// CCseSchedulerServer::CCseSchedulerServer()
// C++ constructor 
// -----------------------------------------------------------------------------
//
CCseSchedulerServer::CCseSchedulerServer()
    : CPolicyServer( EPriorityRealTimeServer, Policy, ESharableSessions ),
    iContainerIx( NULL ),
    iObjectCon( NULL ),
    iSessionCount( 0 ),
    iSchedulerEngine( NULL )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::CCseSchedulerServer");
    __DECLARE_NAME( _S( "CCseSchedulerServer" ) );
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::CCseSchedulerServer");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::NewLC()
// 
// -----------------------------------------------------------------------------
//
CCseSchedulerServer* CCseSchedulerServer::NewLC( )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::NewLC");
    
    CCseSchedulerServer* self = new ( ELeave ) CCseSchedulerServer;
    CleanupStack::PushL( self );
    
    self->ConstructL( );
    
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::NewLC");
    return self;
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::ConstructL()
// second-phase constructor; create the object container index.
// -----------------------------------------------------------------------------
//
void CCseSchedulerServer::ConstructL( )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::ConstructL");
    iContainerIx = CObjectConIx::NewL();
    iObjectCon = iContainerIx->CreateL(); 
    StartL( KCseSchedulerServerName );
    GetEngineObjectL();
    iStarterBreaker = CPeriodic::NewL( CActive::EPriorityStandard );
    
    // break call chain
	if( !iStarterBreaker->IsActive() )
        {
        // Give client 2 secs to make server session before we check 
        // if server is needed or not.
        iStarterBreaker->Start( KDbStartTimeout,
                                KDbStartTimeout,
                                TCallBack( StarterCallback, this ));
        }
    else
        {
        CSELOGSTRING_HIGH_LEVEL(
            "CCseSchedulerServer::ConstructL - Breaker already active");
        }
    
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::ConstructL");    
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::~CCseSchedulerServer()
// Destructor.
// -----------------------------------------------------------------------------
//
CCseSchedulerServer::~CCseSchedulerServer()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::~CCseSchedulerServer");
    DeleteSchedulerEngine();
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::~CCseSchedulerServer");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::ThreadFunction()
// The active scheduler is installed and started here.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CCseSchedulerServer::ThreadFunction( )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::ThreadFunction");
	CTrapCleanup* cleanupStack = CTrapCleanup::New();    
    if ( !cleanupStack )
        {
        PanicServer( ECseCreateTrapCleanup );
        }

    TRAPD( err, ThreadFunctionL( ) );
    if ( err )
        {
        PanicServer( ECseSrvCreateServer );
        }

    delete cleanupStack;    
    
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::ThreadFunction");
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::ThreadFunctionL()
//
// -----------------------------------------------------------------------------
//
void CCseSchedulerServer::ThreadFunctionL( )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::ThreadFunctionL");

    // Construct active scheduler
    CActiveScheduler* activeScheduler = new ( ELeave ) CActiveScheduler;
    CleanupStack::PushL( activeScheduler ); // |-> 1

    // Install active scheduler. 
    // We don't need to check whether an active scheduler is already installed
    // as this is a new thread, so there won't be one
    CActiveScheduler::Install( activeScheduler );

    // Construct our server, pushed cleanup stack and leaved there
    CCseSchedulerServer* server = CCseSchedulerServer::NewLC( );  // |-> 2    
    
    // Signal server is up
    RProcess::Rendezvous( KErrNone );

    // Start handling requests
    CActiveScheduler::Start();

    CleanupStack::PopAndDestroy( server ); // 2<-|
    CleanupStack::PopAndDestroy( activeScheduler ); // 1<-|
    
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::ThreadFunctionL");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::PanicServer
// Utility - panic the server
// (other items were commented in a header).
// -----------------------------------------------------------------------------
void CCseSchedulerServer::PanicServer( TCseSchedulerServPanic aPanic )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::PanicServer");
    _LIT( KSchedulerServer, "SchedulerServer" );
    User::Panic( KSchedulerServer, aPanic );
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::PanicServer");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::GetEngineObjectL()
//
// -----------------------------------------------------------------------------
//
CCseSchedulerServerEngine* CCseSchedulerServer::GetEngineObjectL()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::GetEngineObjectL");
        
    if ( iObjectCon->Count() == 0 )
        {
        // Create scheduler engine
        iSchedulerEngine = CCseSchedulerServerEngine::NewL( *this );
       
        // Add our engine to container
        iObjectCon->AddL( iSchedulerEngine );
        }
    else
        {
        // default implementation return KErrNone.
        if ( KErrNone != iSchedulerEngine->Open() )
            {
            User::Leave( KErrGeneral );
            }
        }
    
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::GetEngineObjectL");
    
    // We have only one object in our container
    return iSchedulerEngine;
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::Inc()
// 
// -----------------------------------------------------------------------------
//
void CCseSchedulerServer::Inc()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::Inc");
    if ( iSessionCount!=KErrNotFound )
        {
        iSessionCount++;
        }
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::Inc");
    }

// -----------------------------------------------------------------------------
// CCseRTPServer::Dec()
// 
// -----------------------------------------------------------------------------
//
void CCseSchedulerServer::Dec()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::Dec");
    iSessionCount--;

    if ( iSessionCount<=0 )
        {
        StopServer();
        }
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::Dec");
    }
    
// -----------------------------------------------------------------------------
// CCseSchedulerServer::DeleteSchedulerEngine
// Stops active scheduler and deletes object container and other objects.
// -----------------------------------------------------------------------------
void CCseSchedulerServer::DeleteSchedulerEngine()
    {
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::DeleteSchedulerEngine");
    
    if ( iContainerIx )
        {
        iSchedulerEngine->Close();
        iContainerIx->Remove( iObjectCon );
        delete iContainerIx; 
		iContainerIx = NULL;
		iSchedulerEngine = NULL;
        }

    if( iStarterBreaker->IsActive() )
        {
        iStarterBreaker->Cancel();
        }
    delete iStarterBreaker;    
    iStarterBreaker = NULL;
    
    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::DeleteSchedulerEngine");
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServer::NewSessionL()
// 
// -----------------------------------------------------------------------------
//

CSession2* CCseSchedulerServer::NewSessionL( const TVersion& aVersion,
                                             const RMessage2& /*aMessage*/ ) const
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::NewSessionL");
    
    // Check version is ok
    TVersion v( KCseServMajorVersionNumber,
                KCseServMinorVersionNumber,
                KCseServBuildVersionNumber );
    
    if ( !User::QueryVersionSupported( v, aVersion ) )
        {
        User::Leave( KErrNotSupported );
        }
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::NewSessionL");        
    
    // Make new session
	return CCseSchedulerServerSession::NewL( ( CCseSchedulerServer* ) this );
    }
    
// -----------------------------------------------------------------------------
// CCseSchedulerServer::StopServer
// Stops the server thread if no sessions active.
// -----------------------------------------------------------------------------
//
void CCseSchedulerServer::StopServer()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::StopServer");
    TBool schedulerActive( iSchedulerEngine->IsSchedulerActive() );    
    CSELOGSTRING2_HIGH_LEVEL("CCseSchedulerServer::StopServer - Session count: %d", iSessionCount);    
    if ( (iSessionCount<=0) && (schedulerActive == EFalse))
        {
        CSELOGSTRING_HIGH_LEVEL("CCseSchedulerServer::StopServer - Call ActiveScheduler::Stop()");
        CActiveScheduler::Stop();
        }        

    CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::StopServer");
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================
// -----------------------------------------------------------------------------
// StartThread()
// Start the server thread. This is called from the client.
// -----------------------------------------------------------------------------
//
TInt CCseSchedulerServer::StartThread()
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::StartThread");
#if _DEBUG
    __UHEAP_MARK;
#endif
       
    // Check server not already started
    TFindServer findCountServer( KCseSchedulerServerName );
    TFullName name;
    if ( findCountServer.Next( name ) == KErrNone )
        { 
        // Found server already
        RProcess::Rendezvous( KErrNone );
        CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::StartThread - Return value: KErrAlreadyExists");
        return KErrAlreadyExists;
        }

    ThreadFunction( );

#if _DEBUG
    __UHEAP_MARKEND;
#endif    
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::StartThread - Server down!");
	
    // All well
    return KErrNone;
    }

// --------------------------------------------------------------------------
// CCseSchedulerServer::CustomSecurityCheckL()
// --------------------------------------------------------------------------
//
CPolicyServer::TCustomResult CCseSchedulerServer::CustomSecurityCheckL(
    const RMessage2& aMsg,
    TInt& /*aAction*/,
    TSecurityInfo& /*aMissing*/ )
    {
    CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::CustomSecurityCheckL");
    TCustomResult retVal ( EFail );
    
    // Check the messagge function range
    if ( aMsg.Function() > ECseRequestBase && 
         aMsg.Function() < ECseRequestLast )
        {
        
        // Check if the client has required capabilities
        // From .mmp-file capablity NetworkControl
        if( // From .mmp-file following are CAP_SERVER capabilities
            ! aMsg.HasCapability(ECapabilityNetworkServices ) ||
            ! aMsg.HasCapability(ECapabilityLocalServices ) ||
            ! aMsg.HasCapability(ECapabilityLocation ) ||
            ! aMsg.HasCapability(ECapabilityReadUserData ) ||
            ! aMsg.HasCapability(ECapabilityWriteUserData ) ||
            ! aMsg.HasCapability(ECapabilityReadDeviceData ) ||
            ! aMsg.HasCapability(ECapabilityWriteDeviceData ) ||        
            ! aMsg.HasCapability(ECapabilityUserEnvironment ) ||
            ! aMsg.HasCapability(ECapabilitySwEvent ) )
            {         
            CSELOGSTRING2_HIGH_LEVEL(
                "CCseSchedulerServer::CustomSecurityCheckL() No capability for message %d!!!",
                aMsg.Function() );                 
            }
        else
            {
            CSELOGSTRING2_HIGH_LEVEL(
                "CCseSchedulerServer::CustomSecurityCheckL() Message %d inside range and capabilities ok",
                aMsg.Function() );
            retVal = EPass;
            }
        }
    else
        {
        CSELOGSTRING2_HIGH_LEVEL(
            "CCseSchedulerServer::CustomSecurityCheckL() Message %d outside known range!!!",
            aMsg.Function() );            
        }
    
    if( retVal == EPass )
        {
        CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::CustomSecurityCheckL - Passed");
        }
    else
        {
        CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::CustomSecurityCheckL - Failed");
        }    
    return retVal;
    }

// -----------------------------------------------------------------------------
// CCseSchedulerServerEngine::StarterCallback
// -----------------------------------------------------------------------------
//
TInt CCseSchedulerServer::StarterCallback( TAny* aPtr )
	{
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::StarterCallback");
	TBool retVal( EFalse);
	retVal = static_cast<CCseSchedulerServer*>( aPtr )->HandleStarterCallback();
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::StarterCallback");
	return retVal;
	}

// -----------------------------------------------------------------------------
// CCseSchedulerServerEngine::HandleCompletitionCallback
// -----------------------------------------------------------------------------
//
TInt CCseSchedulerServer::HandleStarterCallback() 
	{
	CSELOGSTRING_HIGH_LEVEL(">>>CCseSchedulerServer::HandleStarterCallback ");
	
	// We dont want to use periodic anymore, so we cancel it. We just wanted to
	// make call here 2 secs after server has been created.
	iStarterBreaker->Cancel();  
	
	// Check if server can be stopped.
    iSchedulerEngine->RequestReschedule();
	
	CSELOGSTRING_HIGH_LEVEL("<<<CCseSchedulerServer::HandleStarterCallback ");
	return EFalse;
	}

// -----------------------------------------------------------------------------
// E32Main()
// Server startup
// Returns: KErrNone
// -----------------------------------------------------------------------------
//
GLDEF_C TInt E32Main()
    {
    return CCseSchedulerServer::StartThread();
    }

// End of File