diff -r 000000000000 -r 4e1aa6a622a0 mediator/src/Server/MediatorServerCommandHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mediator/src/Server/MediatorServerCommandHandler.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,551 @@ +/* +* 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: Managing of commands registered to Mediator +* +*/ + + +// INCLUDE FILES +#include + +#include "MediatorServerCommandHandler.h" +#include "MediatorServerObjects.h" +#include "MediatorServiceDefs.h" +#include "Debug.h" + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::CMediatorServerCommandHandler +// ----------------------------------------------------------------------------- +// +CMediatorServerCommandHandler::CMediatorServerCommandHandler( + CMediatorServerObjectHandler& aObjectHandler ) + : iObjectHandler( aObjectHandler ) + { + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::ConstructL +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::ConstructL() + { + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::NewL +// ----------------------------------------------------------------------------- +// +CMediatorServerCommandHandler* CMediatorServerCommandHandler::NewL( + CMediatorServerObjectHandler& aObjectHandler ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::NewL")); + CMediatorServerCommandHandler* self + = new( ELeave ) CMediatorServerCommandHandler( aObjectHandler ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::~CMediatorServerCommandHandler +// ----------------------------------------------------------------------------- +// +CMediatorServerCommandHandler::~CMediatorServerCommandHandler() + { + iCommandPendingList.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::RegisterCommandListL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::RegisterCommandListL( + TMediatorCategory aCategory, + const RCommandList& aCommands, + TSecureId aSecureId, + MMediatorCommandObserver* aObserver ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::RegisterCommandListL")); + // Check that domain exists --> if not add new + CDomain* domain = iObjectHandler.FindDomain( aCategory.iDomain ); + if ( !domain ) + { + domain = iObjectHandler.AddDomainL( aCategory.iDomain ); + } + + // Check that category exists --> if not add new + TInt ignore = 0; // not used here + CCategory* category = domain->FindCategory( aCategory.iCategory, ignore ); + if ( !category ) + { + category = domain->AddCategoryL( aCategory.iCategory ); + } + + // Loop through the commands and add them to list + // Take the possible error to variable + TInt error = KErrNone; + TBool stop = EFalse; + TInt index = 0; + for ( index = 0; index < aCommands.Count() && !stop; index++ ) + { + CCommand* newCommand = CCommand::NewL( aCommands[index] ); + CleanupStack::PushL( newCommand ); + newCommand->SetSecureId( aSecureId ); // For unregistering + newCommand->SetObserver( aObserver ); // For getting the commands + newCommand->SetCommitState( CItem::EAdded ); // For transaction handling + TInt addError = category->AddCommand( newCommand ); + if ( addError ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerCommandHandler::RegisterCommandListL: addError=%d\n"), addError ) ); + ERROR_TRACE(Print(_L("[Mediator] Failed to add command %d to category %d of domain %d\n"), newCommand->Id(), + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + // in case of error, delete event and take error + CleanupStack::PopAndDestroy( newCommand ); + error = addError; + stop = ETrue; + } + else + { + // Event has been added properly --> just pop + CleanupStack::Pop( newCommand ); + } + newCommand = NULL; + } + + TRACE(Print(_L("[Mediator Server]\t Commands registered:\n"))); + TRACE(Print(_L("[Mediator Server]\t Success/count: %d/%d \tstatus: %d"), index, aCommands.Count(), error )); + + // Check error if we need to do partial recovery + if ( error != KErrNone ) + { + // Remove the registered commands + category->RollbackCommands(); + } + else + { + // Complete command registration + category->CommitCommands(); + + // Use the object handler to notify command registration + iObjectHandler.CommandsAdded( aCategory.iDomain, + aCategory.iCategory, + aCommands ); + } + // In the end leave if error --> client gets error code + User::LeaveIfError( error ); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::UnregisterCommandListL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::UnregisterCommandListL( TMediatorCategory aCategory, + const RCommandList& aCommands, + TSecureId aSecureId ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::UnregisterCommandListL")); + CCategory* category = iObjectHandler.CategoryL( aCategory ); + TInt error = KErrNone; + if ( category ) + { + TBool stop = EFalse; + TInt index = 0; + + // Loop through the list of commands and unregister those. + for ( index = 0; index < aCommands.Count() && !stop; index++ ) + { + TInt commandIndex = 0; + TCommand removeCommand = aCommands[index]; + CCommand* commandPtr = category->FindCommand( removeCommand.iCommandId, + commandIndex ); + if ( !commandPtr ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerCommandHandler::UnregisterCommandListL: Command not found\n") ); + ERROR_TRACE(Print(_L("[Mediator] Failed to remove command %d in category %d of domain %d\n"), removeCommand.iCommandId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + error = KErrMediatorCommandNotFound; + stop = ETrue; + } + else + { + // Found the command --> is it own registration? + if ( commandPtr->SecureId() != aSecureId ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerCommandHandler::UnregisterCommandListL: Secure ID mismatch\n") ); + ERROR_TRACE(Print(_L("[Mediator] commandPtr()->SecureId()=0x%x, aSecureId=0x%x\n"), commandPtr->SecureId().iId, + aSecureId.iId ) ); + error = KErrMediatorSecureIdMismatch; + stop = ETrue; + } + else // Should be ok to unregister + { + commandPtr->SetCommitState( CItem::ERemoved ); + } + } + } + + TRACE(Print(_L("[Mediator Server]\t Commands unregistered:\n"))); + TRACE(Print(_L("[Mediator Server]\t Processed/Total: %d/%d \tstatus: %d"), index, aCommands.Count(), error )); + + // Check error status --> if there's error, need to roll back + if ( error != KErrNone ) + { + category->RollbackCommands(); + } + else + { + category->CommitCommands(); + + // loop through unregistered commands, and if they can be found from pending commands list, + // inform the command issuer + for ( TInt i = 0; i < aCommands.Count(); i++ ) + { + // ignore return value + IssueResponse( aCategory, aCommands[i], KNullDesC8, KErrMediatorCommandRemoved ); + } + + // Use the object handler to notify command registration + iObjectHandler.CommandsRemoved( aCategory.iDomain, + aCategory.iCategory, + aCommands ); + } + + } + // Leave in case of error situation + User::LeaveIfError( error ); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::IssueCommandL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::IssueCommandL( + TMediatorCategory aCategory, + MediatorService::TCommand aCommand, + const TDesC8& aData, + TCapabilitySet aCaps, + MMediatorCommandResponseObserver* aObserver ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::IssueCommandL")); + CCategory* category = iObjectHandler.CategoryL( aCategory ); + if ( category ) + { + // Find the command from register list + TInt ignore = 0; + CCommand* commandPtr = category->FindCommand( aCommand.iCommandId, ignore ); + if ( !commandPtr ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerCommandHandler::IssueCommandL: Command %d not found in category %d of domain %d\n"), aCommand.iCommandId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + + User::Leave( KErrMediatorCommandNotFound ); + } + // Then check the capabilities && the version information + // Capabilities are checked so that boolean ETrue is returned + // when all parameter caps can be found from aCaps + if ( !aCaps.HasCapabilities( commandPtr->Policy() ) ) + { +#ifdef _DEBUG + for ( TInt index = 0; index < ECapability_Limit; index++ ) + { + TCapabilitySet commandCaps = commandPtr->Policy(); + TBool command = commandCaps.HasCapability( (TCapability) index ); + TBool requestor = aCaps.HasCapability( (TCapability) index ); + if ( command && !requestor ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerCommandHandler::IssueCommandL: capability %d missing\n"), index )); + ERROR_TRACE(Print(_L("[Mediator] Capability error when issuing command %d in category %d of domain %d\n"), aCommand.iCommandId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + } + } +#endif + User::Leave( KErrPermissionDenied ); + } + // Check (major) version match + if ( aCommand.iVersion.iMajor != commandPtr->Version().iMajor ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerCommandHandler::IssueCommandL: registered=%d, issued=%d\n"), + commandPtr->Version().iMajor, + aCommand.iVersion.iMajor )); + ERROR_TRACE(Print(_L("[Mediator] Version error when issuing command %d in category %d of domain %d\n"), aCommand.iCommandId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + // There's a major version mismatch + User::Leave( KErrMediatorVersionMismatch ); + } + + // If ok, issue to command to client + // Make the new command, set initiator and responder + // We don't need to command data for the pending list + CCommand* newCommand = CCommand::NewL( aCommand ); + CleanupStack::PushL( newCommand ); + + newCommand->SetResponseObserver( aObserver ); + newCommand->SetObserver( commandPtr->Observer() ); + newCommand->SetDomain( aCategory.iDomain ); + newCommand->SetCategory( aCategory.iCategory ); + newCommand->SetTimeout( commandPtr->Timeout() ); + + // Start command timing, if it is not an infinite command + if ( commandPtr->Timeout() != KMediatorTimeoutInfinite ) + { + // Start timeout timer ( request callback here ) + newCommand->StartTimer( this ); + } + + iCommandPendingList.AppendL( newCommand ); + + CleanupStack::Pop( newCommand ); + + // Now send the command to correct responder --> we have it pending + commandPtr->Observer()->MediatorCommandL( aCategory.iDomain, + aCategory.iCategory, + aCommand.iCommandId, + aCommand.iVersion, + aData ); + } + } + + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::CancelCommandL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::CancelCommand( + TMediatorCategory aCategory, + MediatorService::TCommand aCommand ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::CancelCommand")); + TBool found = EFalse; + for ( TInt index = 0; index < iCommandPendingList.Count() && !found; index ++ ) + { + CCommand* commandPtr = iCommandPendingList[index]; + if ( commandPtr ) + { + TUid domain = aCategory.iDomain; + TUid category = aCategory.iCategory; + TInt commandId = aCommand.iCommandId; + if ( ( domain == commandPtr->Domain() ) + && ( category == commandPtr->Category() ) + && ( commandId == commandPtr->Id() ) ) + { + // We have found the correct command --> cancel it + TRAP_IGNORE( commandPtr->Observer()->CancelMediatorCommandL( domain, + category, + commandId ) ); + // Remove the command from list, free memory && stop looping + iCommandPendingList.Remove( index ); + delete commandPtr; + commandPtr = NULL; + found = ETrue; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::CancelCommands +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::CancelCommands( MMediatorCommandObserver* aObserver, + MMediatorCommandResponseObserver* aResponseObserver ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::CancelCommand")); + + // loop through list of pending commands + for ( TInt i = iCommandPendingList.Count()-1; i >= 0; i-- ) + { + + CCommand* commandPtr = iCommandPendingList[i]; + + if ( commandPtr ) + { + + TBool commandCanceled = EFalse; + + // This client has registered the command, and some other client has issued it + // -> give an error response to the issuer + if ( aObserver == commandPtr->Observer() ) + { + TRAP_IGNORE( commandPtr->ResponseObserver()->CommandResponseL( commandPtr->Domain(), + commandPtr->Category(), + commandPtr->Id(), + KErrMediatorCommandRemoved, + KNullDesC8 ) ); + commandCanceled = ETrue; + } + + // This client has issued the command + // -> inform the client which registered the command that it is canceled + if ( aResponseObserver == commandPtr->ResponseObserver() ) + { + TRAP_IGNORE( commandPtr->Observer()->CancelMediatorCommandL( commandPtr->Domain(), + commandPtr->Category(), + commandPtr->Id() ) ); + commandCanceled = ETrue; + } + + // pending command was registered and/or issued by this client, so now it can be removed + // from the list + if ( commandCanceled ) + { + iCommandPendingList.Remove( i ); + delete commandPtr; + } + + } + + } + + } + + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::IssueResponse +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CMediatorServerCommandHandler::IssueResponse( + TMediatorCategory aCategory, + MediatorService::TCommand aCommand, + const TDesC8& aData, + TInt aStatus ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::IssueResponse")); + TBool found = EFalse; + for ( TInt index = 0; index < iCommandPendingList.Count() && !found; index ++ ) + { + CCommand* commandPtr = iCommandPendingList[index]; + if ( commandPtr ) + { + TUid domain = aCategory.iDomain; + TUid category = aCategory.iCategory; + TInt commandId = aCommand.iCommandId; + if ( ( domain == commandPtr->Domain() ) + && ( category == commandPtr->Category() ) + && ( commandId == commandPtr->Id() ) ) + { + // We have found the correct command --> ignore the leave + TRAP_IGNORE( commandPtr->ResponseObserver()->CommandResponseL( domain, + category, + commandId, + aStatus, + aData ) ); + // Remove the command from list, free memory && stop looping + iCommandPendingList.Remove( index ); + delete commandPtr; + commandPtr = NULL; + found = ETrue; + } + } + } + + if ( !found ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerCommandHandler::IssueResponse: Command %d not found in category %d of domain %d\n"), aCommand.iCommandId, + aCategory.iDomain.iUid ) ); + } + + return found ? KErrNone : KErrMediatorCommandNotFound; + + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::IssueResponseL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::IssueResponseL( + TMediatorCategory aCategory, + MediatorService::TCommand aCommand, + const TDesC8& aData, + TInt aStatus ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::IssueResponseL")); + + TInt err = IssueResponse( aCategory, aCommand, aData, aStatus ); + + if ( err != KErrNone ) + { + User::Leave( KErrMediatorCommandNotFound ); + } + } + +// ----------------------------------------------------------------------------- +// CMediatorServerCommandHandler::TimerCallBack +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerCommandHandler::TimerCallBack( TUid aDomain, + TUid aCategory, + TInt aCommandId ) + { + LOG(_L("[Mediator Server]\t CMediatorServerCommandHandler::TimerCallBack")); + TBool found = EFalse; + for ( TInt index = 0; index < iCommandPendingList.Count() && !found; index ++ ) + { + CCommand* commandPtr = iCommandPendingList[index]; + if ( commandPtr ) + { + if ( ( aDomain == commandPtr->Domain() ) + && ( aCategory == commandPtr->Category() ) + && ( aCommandId == commandPtr->Id() ) ) + { + // We have found the correct command --> ignore the leave + // Send the response to initiator with timeout error + TRAP_IGNORE( commandPtr->ResponseObserver()->CommandResponseL( aDomain, + aCategory, + aCommandId, + KErrMediatorTimeout, + KNullDesC8 ) ); + // And clear the responder side also + TRAP_IGNORE( commandPtr->Observer()->MediatorCommandTimeoutL( aDomain, + aCategory, + aCommandId ) ); + // Remove the command from list, free memory && stop looping + iCommandPendingList.Remove( index ); + delete commandPtr; + commandPtr = NULL; + found = ETrue; + } + } + } + } + + + +// End of File