mediator/src/Server/MediatorServer.cpp
author Tapani Kanerva <Tapani.Kanerva@nice.fi>
Thu, 11 Nov 2010 14:35:29 +0000
branchRCL_3
changeset 86 79105dd92dc2
parent 0 4e1aa6a622a0
permissions -rw-r--r--
Export meaningful default HWRM policy files, to fix Bug 3852

/*
* 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:  Main functions to start the server
*
*/


#include    <e32base.h>
#include    <barsc.h>       // RResourceFile
#include    <barsread.h>    // TResourceReader

#include    "MediatorServer.h"
#include    "MediatorCommon.h"
#include    "MediatorServerSession.h"
#include    "MediatorServerEventHandler.h"
#include    "MediatorServerCommandHandler.h"
#include    "MediatorServerObjectHandler.h"
#include    "MediatorServerPluginHandler.h"

#include    <allowedsids.rsg>
#include    "MediatorDebug.h"
#include    "Debug.h"

// CONSTANTS
// Resource directory
_LIT(KResourceEventDir, "z:\\private\\10207449\\events\\");

// Resource file containing exceptionally handled SIDs
_LIT(KAllowedSidsFile, "z:\\private\\10207449\\allowedsids.rsc");

// Domain resource index ( = 1)
const TInt KEventResourceIndex  = 1;

// Version number count within TVersion structure
const TInt KVersionNumberCount  = 3;

// NAMESPACE
using namespace MediatorService;

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

// -----------------------------------------------------------------------------
// CMediatorServer::CMediatorServer
// -----------------------------------------------------------------------------
//
CMediatorServer::CMediatorServer()
	: CPolicyServer( CActive::EPriorityHigh, KMediatorServerPolicy )
	{
	LOG(_L("[Mediator Server]\t CMediatorServer::CMediatorServer"));
	}

// -----------------------------------------------------------------------------
// CMediatorServer::ConstructL
// -----------------------------------------------------------------------------
//
void CMediatorServer::ConstructL()
    {
    LOG(_L("[Mediator Server]\t CMediatorServer::ConstructL"));
    StartL( KMediatorServerName );
    
    // Create object, event and command handlers
    iObjectHandler = CMediatorServerObjectHandler::NewL();
    iEventHandler = CMediatorServerEventHandler::NewL( *iObjectHandler );
    iCommandHandler = CMediatorServerCommandHandler::NewL( *iObjectHandler );
    iPluginHandler = CMediatorServerPluginHandler::NewL();
    
    RFs fsSession;
    User::LeaveIfError( fsSession.Connect() );
    CleanupClosePushL( fsSession );
    
    // Do static event registrations
    ProcessResourceEventsL( fsSession );
    
    // read SIDs
    ReadAllowedSidsFileL( fsSession );
    
    CleanupStack::PopAndDestroy( &fsSession );
    
    RMediatorDebug::Initialize( this );
    
    LOG(_L("[Mediator Server]\t CMediatorServer::ConstructL end"));
    }

// -----------------------------------------------------------------------------
// CMediatorServer::NewLC
// -----------------------------------------------------------------------------
//
CMediatorServer* CMediatorServer::NewLC()
	{
	LOG(_L("[Mediator Server]\t CMediatorServer::NewLC"));
	CMediatorServer *self = new (ELeave) CMediatorServer();
	CleanupStack::PushL( self );
	self->ConstructL();
	return self;
	}

// -----------------------------------------------------------------------------
// CMediatorServer::~CMediatorServer
// -----------------------------------------------------------------------------
//    
CMediatorServer::~CMediatorServer()
	{
	RMediatorDebug::Uninitialize();
	
	LOG(_L("[Mediator Server]\t CMediatorServer::~CMediatorServer"));
	delete iEventHandler;
	delete iCommandHandler;
	delete iObjectHandler;
	delete iPluginHandler;
	iAllowedSids.Close();
	}


// -----------------------------------------------------------------------------
// CMediatorServer::NewSessionL
// Creates a new session to the server if version information is correct.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CSession2 *CMediatorServer::NewSessionL( const TVersion &aVersion, 
										 const RMessage2 &/*aMessage*/) const
	{
	LOG(_L("[Mediator Server]\t CMediatorServer::NewSessionL"));
	// check we're the right version
	TVersion version( KMediatorServerMajor, 
					  KMediatorServerMinor, 
					  KMediatorServerBuild);
	if( !User::QueryVersionSupported( version, aVersion ) )
	    {
	    ERROR_LOG(_L("[Mediator] CMediatorServer::NewSessionL: Version conflict!\n") );
	    ERROR_TRACE(Print(_L("[Mediator] Current version:%d.%d.%d\n"), version.iMajor, version.iMinor, version.iBuild ) );
	    ERROR_TRACE(Print(_L("[Mediator] Connected version:%d.%d.%d\n"), aVersion.iMajor, aVersion.iMinor, aVersion.iBuild ) );
	    User::Leave( KErrNotSupported );
	    }
		
	// make new session
	return CMediatorServerSession::NewL();
	}

// -----------------------------------------------------------------------------
// CMediatorServer::EventHandler
// Returns a reference to event handler
// -----------------------------------------------------------------------------
//
CMediatorServerEventHandler& CMediatorServer::EventHandler()
    {
    __ASSERT_DEBUG( iEventHandler, PanicServer( EMediatorServerNoEventHandler ));
    return *iEventHandler;
    }
        
// -----------------------------------------------------------------------------
// CMediatorServer::EventHandler
// Returns a reference to command handler
// -----------------------------------------------------------------------------
//
CMediatorServerCommandHandler& CMediatorServer::CommandHandler()
    {
    __ASSERT_DEBUG( iCommandHandler, PanicServer( EMediatorServerNoCommandHandler ));
    return *iCommandHandler;
    }

// -----------------------------------------------------------------------------
// CMediatorServer::ObjectHandler
// Returns a reference to object handler
// -----------------------------------------------------------------------------
//
CMediatorServerObjectHandler& CMediatorServer::ObjectHandler()
    {
    __ASSERT_DEBUG( iObjectHandler, PanicServer( EMediatorServerNoObjectHandler ));
    return *iObjectHandler;
    }

// -----------------------------------------------------------------------------
// CMediatorServer::PluginHandler
// Returns a reference to plugin handler
// -----------------------------------------------------------------------------
//
CMediatorServerPluginHandler& CMediatorServer::PluginHandler()
    {
    __ASSERT_DEBUG( iPluginHandler, PanicServer( EMediatorServerNoPluginHandler ));
    return *iPluginHandler;
    }

// -----------------------------------------------------------------------------
// CMediatorServer::CustomSecurityCheckL
// Performs a custom security check.
// -----------------------------------------------------------------------------
//

CPolicyServer::TCustomResult CMediatorServer::CustomSecurityCheckL( const RMessage2& aMsg, 
                                                                    TInt& /*aAction*/,
                                                                    TSecurityInfo& /*aMissing*/ )
    {
    LOG(_L("[Mediator Server]\t CMediatorServer::CustomSecurityCheckL"));
    // firstly check if this SwEvent capability, which is OK
    if ( aMsg.HasCapability( ECapabilitySwEvent ) )
        {
        return EPass;
        }
    
    // secondly check if special treatment for this SID is allowed
    if ( AllowCapabilityException( static_cast<TUid>( aMsg.SecureId() ) ) )
        {
        return EPass;
        }
    
    ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::CustomSecurityCheckL: security check fail for client 0x%08X\n"), aMsg.SecureId().iId));

    // client has no right to send this message
    return EFail;
    }

// -----------------------------------------------------------------------------
// CMediatorServer::ProcessResourceEventsL
// Does static event resource registration processing
// -----------------------------------------------------------------------------
//
void CMediatorServer::ProcessResourceEventsL( RFs& aFsSession )
    {
    LOG(_L("[Mediator Server]\t CMediatorServer::ProcessResourceEventsL"));
    
    // Gather all files from registration directory
    CDir* resourceList;
	
    TInt err = aFsSession.GetDir( KResourceEventDir,
		                         KEntryAttNormal,
		                         ESortByName, 
		                         resourceList );
    
    // If events-directory does not exist, it means that there are no static events registered
    if ( err != KErrNone && err != KErrPathNotFound )
        {
        ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::ProcessResourceEventsL: err=%d\n"), err ) );
        User::Leave( err );
        }
    
    if ( err != KErrPathNotFound )    		                                  
        {
        CleanupStack::PushL( resourceList );
        TRACE(Print(_L("[Mediator Server]\t ProcessResourceEventsL file count %d\n"), resourceList->Count() ));
    
        // Loop through the resource files and process the resources
        for ( TInt index = 0; index < resourceList->Count(); index++ )
            {
            TEntry resourceFile = (*resourceList)[ index ];
            TBufC<KMaxFileName> fileName = resourceFile.iName;
            // TRAP error, but continue
            TRAPD( error, ProcessResourceFileL( aFsSession, fileName ) );
            
            if ( error != KErrNone )
                {
                ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::ProcessResourceEventsL: error=%d\n"), error ) );
                }
                
            TRACE(Print(_L("[Mediator Server]\t ProcessResourceEventsL file %d process status %d\n"), index, error )); 
            }
        CleanupStack::PopAndDestroy( resourceList );
        }
    }

// -----------------------------------------------------------------------------
// CMediatorServer::ProcessResourceFileL
// Processes one resource file
// -----------------------------------------------------------------------------
//
void CMediatorServer::ProcessResourceFileL( RFs& aFsSession, const TDesC& aFileName )
    {
    LOG(_L("[Mediator Server]\t CMediatorServer::ProcessResourceFileL"));
    
    // Parse full file name
    TParse parse;
    parse.Set( aFileName, &KResourceEventDir, NULL );
    TFileName fullName = parse.FullName();
    
    // Get this thread's secure id
    RThread thread = RThread();
    TSecureId secureId = thread.SecureId();
    
    // Open resource file
    RResourceFile resourceFile;
    resourceFile.OpenL( aFsSession, fullName );
	CleanupClosePushL( resourceFile );
		
    // Read resource information		
	HBufC8* domainResource = resourceFile.AllocReadLC( KEventResourceIndex );
	TResourceReader reader;
	reader.SetBuffer( domainResource );
	
	// Read domain from resource
	TUid domainUid = TUid::Uid( reader.ReadInt32() );
	// Process categories
	TInt categoryCount = reader.ReadInt16();
	for ( TInt index = 0; index < categoryCount; index++ )
	    {
	    TUid categoryUid = TUid::Uid( reader.ReadInt32() );
	    // Process events within category
	    TInt eventCount = reader.ReadInt16();
	    REventList eventList;
	    for ( TInt index2 = 0; index2 < eventCount; index2++ )
	        {
	        MediatorService::TEvent newEvent = ReadEvent( reader );
	        eventList.AppendL( newEvent );
	        }
	    // Register events to event handler, if there's something to register
	    if ( eventList.Count() > 0 )
	        {
	        TMediatorCategory newCategory;
    	    newCategory.iDomain = domainUid;
    	    newCategory.iCategory = categoryUid;
    	    // TRAP error, but continue anyway
    	    TRAPD( error, 
    	           EventHandler().RegisterEventListL( newCategory, 
    	                                              eventList, 
    	                                              secureId ) );
            
            if ( error != KErrNone )
                {
                ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::ProcessResourceFileL: error=%d\n"), error ) );
                }
            
    	                                              
    	    TRACE(Print(_L("[Mediator Server]\t ProcessResourceFileL events registered with status %d\n"), error ));                                          
	        }  
	    eventList.Close();
	    }
		
	CleanupStack::PopAndDestroy( domainResource);
	CleanupStack::PopAndDestroy( &resourceFile );
    }


// -----------------------------------------------------------------------------
// CMediatorServer::ReadEvent
// Reads one event from resource
// -----------------------------------------------------------------------------
//
MediatorService::TEvent CMediatorServer::ReadEvent( TResourceReader& aReader )
    {
    MediatorService::TEvent newEvent;
    
    // Read Event id
    newEvent.iEventId =  aReader.ReadInt16();
    
    TRACE(Print(_L("[Mediator Server]\t ProcessResourceFileL new event id %d\n"), newEvent.iEventId )); 
    
    // Read required capabilities
    TCapabilitySet capabilitySet;
    capabilitySet.SetEmpty();
    TInt capabilityCount = aReader.ReadInt16();
    for ( TInt index = 0; index < capabilityCount; index++ )
        {
        TCapability newCapability = (TCapability) aReader.ReadInt16();
        capabilitySet.AddCapability( newCapability );  
        }
    newEvent.iCaps = capabilitySet;
    
    // Read version information
    TInt versionCount = aReader.ReadInt16();
    if ( versionCount == KVersionNumberCount ) // Should have 3 values in version structure
        {
        TInt major = aReader.ReadInt16();
        TInt minor = aReader.ReadInt16();
        TInt build = aReader.ReadInt16();
        newEvent.iVersion = TVersion( major, minor, build );
        }
    else
        {
        ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::ReadEvent: Event %d has invalid data, versionCount=%d\n"), newEvent.iEventId, versionCount ) );
        // Something wrong with the resource --> use zeros as version info
        newEvent.iVersion = TVersion( 0, 0, 0 );
        }    
    // Return event 
    return newEvent;
    }

// -----------------------------------------------------------------------------
// CMediatorServer::ReadAllowedSidsFileL
// Read resource file containing exeptionally handled SIDs
// -----------------------------------------------------------------------------
//
void CMediatorServer::ReadAllowedSidsFileL( RFs& aFsSession )
    {
    LOG(_L("[Mediator Server]\t CMediatorServer::ReadAllowedSidsFileL"));
    
    // read settings from resource files
    TFileName resourceFileName (KAllowedSidsFile);
    
    RResourceFile resourceFile;
    resourceFile.OpenL(aFsSession, resourceFileName);
    
    CleanupClosePushL(resourceFile);
    
    // Read the SID structure
    HBufC8* res = resourceFile.AllocReadLC(SID_INFO);
    TResourceReader theReader;
    theReader.SetBuffer(res);

    TInt sidCount = theReader.ReadUint16();
    
    // read SIDs
    TUid sid;
        
    for (TInt i = 0; i < sidCount; i++)
        {
        sid.iUid = theReader.ReadUint32();
        TRACE(Print(_L("[Mediator Server]\t Allowed SID: 0x%08X\n"), sid.iUid)); 
        User::LeaveIfError( iAllowedSids.Append( sid ) );
        }    
    
    CleanupStack::PopAndDestroy( res );
    CleanupStack::PopAndDestroy( &resourceFile );
    }

// -----------------------------------------------------------------------------
// CMediatorServer::AllowCapabilityException
// Returns whether capability requirements can be ignored for the specified client.
// -----------------------------------------------------------------------------
//
TBool CMediatorServer::AllowCapabilityException( const TUid& aSid )
    {
    return ( ( iAllowedSids.Find ( aSid ) != KErrNotFound ) ? ETrue : EFalse );
    }

    
// -----------------------------------------------------------------------------
// PanicServer
// Server panic handler
// Panic our own thread
// -----------------------------------------------------------------------------
//
void CMediatorServer::PanicServer(TInt aPanic)
    {
    ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::PanicServer: Reason = %d\n"), aPanic));
    User::Panic( KMediatorServerPanic, aPanic );
    }

// -----------------------------------------------------------------------------
// PanicClient
// Client panic handler
// RMessage2::Panic() also completes the message. This is:
// (a) important for efficient cleanup within the kernel
// (b) a problem if the message is completed a second time
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMediatorServer::PanicClient( const RMessage2& aMessage, TInt aPanic )
    {
    ERROR_TRACE(Print(_L("[Mediator] CMediatorServer::PanicClient: Reason = %d\n"), aPanic));
    aMessage.Panic( KMediatorServerPanic, aPanic );
    }

// End of File