mediator/src/Server/MediatorServerSession.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mediator/src/Server/MediatorServerSession.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,2030 @@
+/*
+* Copyright (c) 2005-2008 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 implementation class for Mediator Server
+*
+*/
+
+
+// INCLUDE FILES
+#include    <e32base.h>
+#include    <s32mem.h>
+
+#include    "MediatorServerSession.h"
+#include    "MediatorCommon.h"
+#include    "MediatorServer.h"
+#include    "MediatorServiceDefs.h"
+#include    "mediatorqueitem.h"
+#include    "MediatorDebug.h"
+#include    "Debug.h"
+using namespace MediatorService;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CMediatorServerSession
+// -----------------------------------------------------------------------------
+//
+CMediatorServerSession::CMediatorServerSession() :iNotificationsRegistered( EFalse ),
+                                                  iNotificationQueue( _FOFF(CMediatorQueItem,iSlink) )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::NewL
+// -----------------------------------------------------------------------------
+//
+CMediatorServerSession* CMediatorServerSession::NewL()
+	{
+	LOG(_L("[Mediator Server]\t CMediatorServerSession::NewL"));
+	return new( ELeave ) CMediatorServerSession();
+	}
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::~CMediatorServerSession
+// -----------------------------------------------------------------------------
+//    
+CMediatorServerSession::~CMediatorServerSession()
+	{
+	LOG(_L("[Mediator Server]\t CMediatorServerSession::~CMediatorServerSession"));
+
+    // cancel all asynchronous waiting procedures
+    CancelAll( KErrCancel );
+
+    // cancel pending commands
+    Server().CommandHandler().CancelCommands( this, this );
+
+	// Unregister all subscriptions
+	// Get handler
+    CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+    objectHandler.ClearRegistrations( this, this, this );
+    
+    iEventServiceList.ResetAndDestroy();
+	iCommandServiceList.ResetAndDestroy();
+	
+	if ( iDataBuffer )
+	    {
+	    delete iDataBuffer;
+	    }
+	
+	CleanNotificationQueue();
+	}
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CleanNotificationQueue
+// -----------------------------------------------------------------------------
+// 
+void CMediatorServerSession::CleanNotificationQueue()
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::CleanNotificationQueue"));
+    
+    // release memory allocated to notification queue items
+    TSglQueIter<CMediatorQueItem> iter( iNotificationQueue );
+    CMediatorQueItem* item;
+    
+    while ( ( item = iter++ ) != NULL)
+        {
+        iNotificationQueue.Remove( *item );
+        delete item;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::Server
+// Returns a reference to server
+// -----------------------------------------------------------------------------
+//
+CMediatorServer& CMediatorServerSession::Server()
+    {
+    return *static_cast<CMediatorServer*>(const_cast<CServer2*>(CSession2::Server()));
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ServiceL
+// Implements CSession2 -derived ServiceL -method.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::ServiceL(const RMessage2& aMessage)
+	{
+	LOG(_L("[Mediator Server]\t CMediatorServerSession::ServiceL"));
+	
+	// If ServiceL leaves, default implementation in server framework
+	// completes the RMessage2 with the leave code.
+	DispatchMessageL( aMessage );
+	}
+	
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ServiceError
+// Implements CSession2 -derived ServiceError -method.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::ServiceError(const RMessage2& aMessage,TInt aError)
+    {
+    ERROR_TRACE(Print(_L("[Mediator] CMediatorServerSession::ServiceError: opcode=%d, aError=%d\n"), aMessage.Function(), aError ));
+    
+    RMediatorDebug::LogError(aMessage, aError);
+    
+    CSession2::ServiceError(aMessage, aError);
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ReadCategoryL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//   
+TMediatorCategory CMediatorServerSession::ReadCategoryL( 
+                                        const RMessage2& aMessage,
+                                        const TInt aMessageSlot )
+    {
+    TMediatorCategoryBuffer categoryBuffer;
+    aMessage.ReadL( aMessageSlot, categoryBuffer );
+    TMediatorCategory category = categoryBuffer();
+    return category;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WriteCategoryL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//   
+void CMediatorServerSession::WriteCategoryL( TUid aDomain,
+                                             TUid aCategory,
+                                             const RMessage2& aMessage,
+                                             const TInt aMessageSlot  )
+    {
+    TMediatorCategory category;
+    category.iDomain = aDomain;
+    category.iCategory = aCategory;
+    TMediatorCategoryRetBuffer categoryBuffer( category );
+    aMessage.WriteL( aMessageSlot, categoryBuffer );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WriteEventL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//       
+void CMediatorServerSession::WriteEventL( TInt aEventId,
+                                          const RMessage2& aMessage,
+                                          const TInt aMessageSlot )
+    {
+    MediatorService::TEvent event;
+    event.iEventId = aEventId;
+    TEventRetBuffer buffer( event );
+    aMessage.WriteL( aMessageSlot, buffer );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WriteCommandL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//       
+void CMediatorServerSession::WriteCommandL( TInt aCommandId,
+                                            TVersion aVersion,
+                                            const RMessage2& aMessage,
+                                            const TInt aMessageSlot )
+    {
+    MediatorService::TCommand command;
+    command.iCommandId  = aCommandId;
+    command.iVersion    = aVersion;
+    TCommandRetBuffer buffer( command );
+    aMessage.WriteL( aMessageSlot, buffer );
+    }
+    
+   
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ReadEventListL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+// 
+REventList CMediatorServerSession::ReadEventListL( const RMessage2& aMessage,
+                                                   const TInt aMessageSlot )
+    {
+     // Read event list information from Message
+    REventList eventList;
+    CleanupClosePushL( eventList );
+    
+    // Create input pointer for data
+    TInt size = aMessage.GetDesMaxLength( aMessageSlot );
+    TInt count = size / ( sizeof(MediatorService::TEvent) );
+    
+    if ( count <= 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+    
+    for ( TInt index = 0; index < count; index ++ )
+        {
+        TEvent event;
+        eventList.AppendL( event );
+        }
+    TPtr8 arrayPtr( (TUint8*)&eventList[0], size );
+    
+    // Read data from message
+    aMessage.ReadL( aMessageSlot, arrayPtr );
+    
+    CleanupStack::Pop( &eventList );
+    return eventList;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::EventListFitsToClientMemory
+// -----------------------------------------------------------------------------
+// 
+TBool CMediatorServerSession::EventListFitsToClientMemory( const REventList& aEvents,
+                                                           const RMessage2& aMessage,
+                                                           const TInt aMessageSlot )
+    {
+    TBool retval( ETrue );
+    
+    if ( aEvents.Count() > 0 )
+        {
+        TInt arraySize( ( sizeof(MediatorService::TEvent) ) * aEvents.Count() );
+    
+        // Check that there's enough space before writing the answer
+        TInt space( aMessage.GetDesMaxLength( aMessageSlot ) ); 
+        
+        retval = ( arraySize <= space );
+        }
+    
+    return retval;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CommandListFitsToClientMemory
+// -----------------------------------------------------------------------------
+// 
+TBool CMediatorServerSession::CommandListFitsToClientMemory( const RCommandList& aCommands,
+                                                             const RMessage2& aMessage,
+                                                             const TInt aMessageSlot )
+    {
+    TBool retval( ETrue );
+    
+    if ( aCommands.Count() > 0 )
+        {
+        TInt arraySize( ( sizeof(MediatorService::TCommand) ) * aCommands.Count() );
+        
+        // Check that there's enough space before writing the answer
+        TInt space( aMessage.GetDesMaxLength( aMessageSlot ) ); 
+                
+        retval = ( arraySize <= space );
+        }
+    
+    return retval;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WriteEventListL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//   
+void CMediatorServerSession::WriteEventListL( const REventList& aEvents,
+                                              const RMessage2& aMessage,
+                                              const TInt aMessageSlot )
+    {
+    if ( aEvents.Count() > 0 )
+        {
+        TInt arraySize = ( sizeof(MediatorService::TEvent) ) * aEvents.Count();
+        TInt space( aMessage.GetDesMaxLength( aMessageSlot ) );
+        
+        // the method assumes that there's enought space in client memory to accommadate the events
+        __ASSERT_DEBUG( space >= arraySize, User::Invariant() );
+        
+        if ( arraySize > space )
+            {
+            arraySize = space; // ensure that we don't overflow client buffer in any circumstances
+            }
+
+        TPtr8 arrayPtr( (TUint8*)&aEvents[0], arraySize, arraySize );
+        aMessage.WriteL( aMessageSlot, arrayPtr );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ReadCommandListL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+// 
+RCommandList CMediatorServerSession::ReadCommandListL( const RMessage2& aMessage,
+                                                       const TInt aMessageSlot )
+    {
+     // Read command list information from Message
+    RCommandList commandList;
+    CleanupClosePushL( commandList );
+    
+    // Create input pointer for data
+    TInt size = aMessage.GetDesMaxLength( aMessageSlot );
+    TInt count = size / ( sizeof(MediatorService::TCommand) );
+    for ( TInt index = 0; index < count; index ++ )
+        {
+        TCommand command;
+        commandList.AppendL( command );
+        }
+    TPtr8 arrayPtr( (TUint8*)&commandList[0], size );
+    
+    // Read data from message
+    aMessage.ReadL( aMessageSlot, arrayPtr );
+    
+    CleanupStack::Pop( &commandList );
+    return commandList;
+    }
+   
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WriteCommandListL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//   
+void CMediatorServerSession::WriteCommandListL( const RCommandList& aCommands,
+                                                const RMessage2& aMessage,
+                                                const TInt aMessageSlot )
+    {
+    // Write the command list back to client
+    if ( ( aCommands.Count() > 0 ) )
+        {
+        TInt arraySize( ( sizeof(MediatorService::TCommand) ) * aCommands.Count() );
+
+        // Check that there's enough space before writing the answer
+        TInt space( aMessage.GetDesMaxLength( aMessageSlot ) ); 
+        
+        // this method assumes that there's enough space in client side
+        __ASSERT_DEBUG( arraySize <= space, User::Invariant() );
+        
+        if ( arraySize > space ) // overflow prevention
+            {
+            arraySize = space;
+            }
+        
+        TPtr8 arrayPtr( (TUint8*)&aCommands[0], arraySize, arraySize );    
+        aMessage.WriteL( aMessageSlot, arrayPtr );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ReadDataL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//     
+HBufC8* CMediatorServerSession::ReadDataLC( const RMessage2& aMessage,
+                                            const TInt aMessageSlot )
+    {
+     // Then read parameter data from slot 2
+    TInt dataSize = aMessage.GetDesLength( aMessageSlot );
+
+    if ( dataSize < 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    HBufC8* data = HBufC8::NewLC( dataSize );
+    TPtr8 ptr( data->Des() );
+	aMessage.ReadL( aMessageSlot, ptr );
+	return data;
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WriteDataL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//   
+void CMediatorServerSession::WriteDataL( const TDesC8& aData,
+                                         const RMessage2& aMessage,
+                                         const TInt aMessageSlot )
+    {
+    // Read max data length
+    TInt space = aMessage.GetDesMaxLength( aMessageSlot );
+    if ( space >= aData.Length() )
+        {
+        aMessage.WriteL( aMessageSlot, aData );
+        }
+    else    // Not enough space to write
+        {
+        // Store the data to temporary buffer --> it is fetched from client side
+        // synchronously
+        if ( iDataBuffer )
+            {
+            delete iDataBuffer;
+            iDataBuffer = NULL;
+            }
+        iDataBuffer = aData.AllocL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ReadEventL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//       
+MediatorService::TEvent CMediatorServerSession::ReadEventL( 
+                                    const RMessage2& aMessage,
+                                    const TInt aMessageSlot )
+    {
+    TEventBuffer eventBuffer;
+    aMessage.ReadL( aMessageSlot, eventBuffer );
+    return eventBuffer();
+    }
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::ReadCommandL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//       
+MediatorService::TCommand CMediatorServerSession::ReadCommandL( 
+                                    const RMessage2& aMessage,
+                                    const TInt aMessageSlot )
+    {
+    TCommandBuffer commandBuffer;
+    aMessage.ReadL( aMessageSlot, commandBuffer );
+    return commandBuffer();
+    }
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::DispatchMessageL
+// Dispatches message according to its opcode
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::DispatchMessageL( const RMessage2 &aMessage )
+    {
+	LOG(_L("[Mediator Server]\t CMediatorServerSession::DispatchMessageL"));
+	
+	RMediatorDebug::Log(aMessage, *this);
+	
+    switch ( aMessage.Function() )
+        {
+        case ERegisterEventList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: ERegisterEventList"));
+            RegisterEventListL( aMessage );
+            break;
+            }    
+        case ERegisterCommandList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: ERegisterCommand"));
+            RegisterCommandListL( aMessage );
+            break;
+            }
+        case EUnregisterEventList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EUnregisterEventList"));
+            UnregisterEventListL( aMessage );
+            break;
+            }
+         case EUnregisterCommandList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EUnregisterCommandList"));
+            UnregisterCommandListL( aMessage );
+            break;
+            }
+        case ESubscribeEventList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: ESubscribeEvent"));
+            SubscribeEventListL( aMessage );
+            break;
+            }
+        case EUnsubscribeEventList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EUnsubscribeEvent"));
+            UnsubscribeEventListL( aMessage );
+            break;
+            }
+        case ERaiseEvent:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: ERaiseEvent"));
+            RaiseEventL( aMessage );
+            break;
+            }
+        case EIssueCommand:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: IssueCommandL"));
+            IssueCommandL( aMessage );
+            break;
+            }  
+         case ECancelCommand:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: CancelCommandL"));
+            CancelCommandL( aMessage );
+            break;
+            }
+         case EIssueResponse:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EIssueResponse"));
+            IssueResponseL( aMessage );
+            break;
+            }
+        case EGetDomains:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EGetDomains"));
+            GetDomainsL( aMessage );
+            break;
+            }
+        case EGetCategories:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EGetCategories"));
+            GetCategoriesL( aMessage );
+            break;
+            }
+        case EGetCommands:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EGetCommands"));
+            GetCommandsL( aMessage );
+            break;
+            }
+        case EGetEvents:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EGetEvents"));
+            GetEventsL( aMessage );
+            break;
+            }
+        case EWaitForEvent:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EWaitForEvent"));
+            WaitForEventsL( aMessage );
+            break;
+            }
+        case EWaitForCommand:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EWaitForCommand"));
+            WaitForCommandsL( aMessage );
+            break;
+            }
+        case EWaitForNotifications:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EWaitForNotifications"));
+            WaitForNotificationsL( aMessage );
+            break;
+            }
+        case ECancelNotifications:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: ECancelNotifications"));
+            CancelNotificationsL( aMessage );
+            break;
+            }
+        case EWaitForCommandResponse:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EWaitForCommandResponse"));
+            WaitForCommandResponseL( aMessage );
+            break;
+            }
+        case EFetchParameterData:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EFetchParameterData"));
+            FetchParameterDataL( aMessage );
+            break;
+            }
+        case ECancelAll:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: ECancelAll"));
+            CancelAll( aMessage );
+            break;
+            }
+            
+        case EFetchNotificationEventList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EFetchNotificationEventList"));
+            FetchNotificationEventListL( aMessage );
+            break;    
+            }
+        
+        case EFetchNotificationCommandList:
+            {
+            LOG(_L("[Mediator Server]\t DispatchMessageL: EFetchNotificationCommandList"));
+            FetchNotificationCommandListL( aMessage );
+            break;
+            }
+        default:
+            {
+            // Unknown opcode --> panic client
+            ERROR_TRACE(Print(_L("[Mediator] CMediatorServerSession::DispatchMessageL: Unknown opcode=%d\n"), aMessage.Function()));
+            CMediatorServer::PanicClient( aMessage, EMediatorClientBadRequest );
+            break;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorCommandL
+// Callback from command handler when command is issued
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorCommandL( TUid aDomain,
+                                               TUid aCategory, 
+                                               TInt aCommandId,
+                                               TVersion aVersion, 
+                                               const TDesC8& aData )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorCommandL"));
+    
+    if ( !iCommandInitMessage.IsNull() )
+        {
+        // Write domain & category information
+        WriteCategoryL( aDomain, aCategory, iCommandInitMessage, 0 );
+        
+        // Write event to slot 1
+        WriteCommandL( aCommandId, aVersion, iCommandInitMessage, 1 );
+        
+        // Write data to slot 2
+        WriteDataL( aData, iCommandInitMessage, 2 );
+        
+        // Complete message with data size
+        iCommandInitMessage.Complete( aData.Length() );
+        }
+    else    // Append command to service list
+        {
+        // Create a new command object
+        CCommand* newCommand = CCommand::NewL( aCommandId );
+        CleanupStack::PushL( newCommand );
+        newCommand->SetParameterDataL( aData );
+        newCommand->SetDomain( aDomain );
+        newCommand->SetCategory( aCategory );
+        newCommand->SetVersion( aVersion );
+        iCommandServiceList.AppendL( newCommand );  // Last to queue
+        CleanupStack::Pop( newCommand );  // ownership is in the array
+        TRACE(Print(_L("[Mediator Server]\t Session %d - command buffer %d\n"), this, iCommandServiceList.Count() ));
+        }
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CancelMediatorCommandL
+// Callback from command handler when command processing is cancelled
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::CancelMediatorCommandL( TUid aDomain,
+                                                     TUid aCategory, 
+                                                     TInt aCommandId )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::CancelMediatorCommand"));
+    
+    // Check the service list and remove the command from there if exists
+    // At this point it has not been delivered to responder yet
+    TBool found = EFalse;
+    for ( TInt index = 0; index < iCommandServiceList.Count() && !found; index++ )
+        {
+        CCommand* commandPtr = iCommandServiceList[index];
+        if ( commandPtr )
+            {
+            if ( commandPtr->Domain() == aDomain
+                 && commandPtr->Category() == aCategory
+                 && commandPtr->Id() == aCommandId 
+                 && commandPtr->Status() == ECommandPending )
+                {
+                iCommandServiceList.Remove( index );
+                delete commandPtr;
+                commandPtr = NULL;
+                found = ETrue;
+                }
+            }
+        }
+    
+    // Write domain & category information to slot 0
+    if ( iCommandInitMessage.Handle() && !found )
+        {
+        WriteCategoryL( aDomain, aCategory, iCommandInitMessage, 0 );
+    
+        // Write command id and version to slot 1
+        TVersion version( 0, 0, 0 );
+        WriteCommandL( aCommandId, version, iCommandInitMessage, 1 );
+        
+        // Status to slot 2
+        TPckg<TInt> statusBuffer( KErrCancel );
+        iCommandInitMessage.WriteL( 2, statusBuffer );
+        
+        // Write data to slot 3
+        WriteDataL( KNullDesC8, iCommandInitMessage, 2 );
+        
+        // Complete message
+        iCommandInitMessage.Complete( KErrCancel );
+        }
+    // The command hs been delivered, but the responder is busy or otherwise is not
+    // yet ready to handle the command cancellation, add to the list with cancelled status
+    else if ( !iCommandInitMessage.Handle() && !found )
+        {
+        // Create a new command object
+        CCommand* newCommand = CCommand::NewL( aCommandId );
+        CleanupStack::PushL( newCommand );
+        newCommand->SetDomain( aDomain );
+        newCommand->SetCategory( aCategory );
+        newCommand->SetStatus( ECommandCanceled );
+        iCommandServiceList.AppendL( newCommand );  // Last to queue
+        CleanupStack::Pop( newCommand );  // ownership is in the array
+        }
+            
+
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CancelMediatorCommandL
+// Callback from command handler when command processing is cancelled
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorCommandTimeoutL( TUid aDomain,
+                                                      TUid aCategory, 
+                                                      TInt aCommandId )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorCommandTimeoutL"));
+    
+    // Check the service list and remove the command from there if exists
+    // At this point it has not been delivered to responder yet
+    TBool found = EFalse;
+    for ( TInt index = 0; index < iCommandServiceList.Count() && !found; index++ )
+        {
+        CCommand* commandPtr = iCommandServiceList[index];
+        if ( commandPtr )
+            {
+            if ( commandPtr->Domain() == aDomain
+                 && commandPtr->Category() == aCategory
+                 && commandPtr->Id() == aCommandId
+                 && commandPtr->Status() == ECommandPending ) // only pending commands are completed with timeout
+                {
+                iCommandServiceList.Remove( index );
+                delete commandPtr;
+                commandPtr = NULL;
+                found = ETrue;
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CommandResponseL
+// Callback from command handler when command processing is cancelled
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::CommandResponseL( TUid aDomain,
+                                               TUid aCategory, 
+                                               TInt aCommandId,
+                                               TInt aStatus, 
+                                               const TDesC8& aData )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::CommandResponseL"));
+    
+    if ( !iCommandResponseMessage.IsNull() )
+        {
+        // Write domain & category information
+        WriteCategoryL( aDomain, aCategory, iCommandResponseMessage, 0 );
+        
+        // Write command to slot 1
+        TVersion version( 0, 0, 0 );
+        WriteCommandL( aCommandId, version, iCommandResponseMessage, 1 );
+        
+        // Write data to slot 2
+        WriteDataL( aData, iCommandResponseMessage, 2 );
+        
+        // Status to slot 3
+        TPckg<TInt> statusBuffer( aStatus );
+        iCommandResponseMessage.WriteL( 3, statusBuffer );
+        
+        // Complete message with data size
+        iCommandResponseMessage.Complete( aData.Length() );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorEventL
+// Callback from event handler when event occurs
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorEventL( TUid aDomain,
+                                             TUid aCategory, 
+                                             TInt aEventId, 
+                                             const TDesC8& aData )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorEventL"));   
+    if ( !iEventNotificationMessage.IsNull() )
+        {
+        // Write domain & category information
+        WriteCategoryL( aDomain, aCategory, iEventNotificationMessage, 0 );
+        
+        // Write event to slot 1
+        WriteEventL( aEventId, iEventNotificationMessage, 1 );
+        
+        // Write data to slot 2
+        WriteDataL( aData, iEventNotificationMessage, 2 );
+        
+        // Complete message with data size
+        iEventNotificationMessage.Complete( aData.Length() );
+        }
+    else    // Append event to service list
+        {
+        // Create a new event object
+        CEvent* newEvent = CEvent::NewL( aEventId );
+        CleanupStack::PushL( newEvent );
+        newEvent->SetParameterDataL( aData );
+        newEvent->SetDomain( aDomain );
+        newEvent->SetCategory( aCategory );
+        iEventServiceList.AppendL( newEvent );  // Last to queue
+        CleanupStack::Pop( newEvent );  // ownership is in the array
+        TRACE(Print(_L("[Mediator Server]\t Session %d - event buffer %d\n"),this ,iEventServiceList.Count() ));
+        }
+    
+    }
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorEventsAddedL
+// Callback from event handler when an event is added
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorEventsAddedL( TUid aDomain, 
+                                                   TUid aCategory, 
+                                                   const REventList& aEvents )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorEventsAddedL"));
+    
+    HandleMediatorEventsChangedL( EMediatorEventsRegistered, aDomain, aCategory, aEvents );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::HandleMediatorEventsChangedL
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::HandleMediatorEventsChangedL( TMediatorNotificationType aNotificationType,
+                                                         const TUid& aDomain, 
+                                                         const TUid& aCategory, 
+                                                         const REventList& aEvents )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::HandleMediatorEventsChangedL"));
+    
+    if ( !iNotificationMessage.IsNull() )
+        {
+        TBool eventsPassed( ETrue );
+        
+        DoMediatorEventsChangedL( aNotificationType, aDomain, aCategory, aEvents, eventsPassed );
+        
+        if ( !eventsPassed )
+            {
+            // store events for next EFetchNotificationEventList
+            CMediatorQueItem* eventsBuffer = CEventListQueItem::NewL( aNotificationType, aDomain, aCategory, aEvents );
+            iNotificationQueue.AddFirst( *eventsBuffer );
+            }
+        }
+    else if ( iNotificationsRegistered )
+        {
+        LOG(_L("[Mediator Server]\t CMediatorServerSession::HandleMediatorEventsChangedL: received events buffered"));
+        
+        // store events for next EWaitForNotifications
+        CMediatorQueItem* eventsBuffer = CEventListQueItem::NewL( aNotificationType, aDomain, aCategory, aEvents );
+        iNotificationQueue.AddLast( *eventsBuffer );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::DoMediatorEventsChangedL
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::DoMediatorEventsChangedL( TMediatorNotificationType aNotificationType,
+                                                     const TUid& aDomain, 
+                                                     const TUid& aCategory, 
+                                                     const REventList& aEvents,
+                                                     TBool& aEventsPassedToClient )
+    {
+    TRACE( Print( _L("[Mediator Server]\t CMediatorServerSession::DoMediatorEventsChangedL: D=0x%x C=0x%x, count=%d"),
+                    aDomain.iUid, aCategory.iUid, aEvents.Count() ) );
+    
+    // Write category information to message slot 0
+    WriteCategoryL( aDomain, aCategory, iNotificationMessage, 0 );
+    
+    // Write notification type to slot 1
+    TNotificationTypeRetBuffer typeBuffer( aNotificationType );
+    iNotificationMessage.WriteL( 1, typeBuffer );
+    
+    // Write event list
+    if ( EventListFitsToClientMemory( aEvents, iNotificationMessage, 2 ) )
+        {
+        WriteEventListL( aEvents, iNotificationMessage, 2 );
+        aEventsPassedToClient = ETrue;
+        }
+    else
+        {
+        aEventsPassedToClient = EFalse;
+        }
+    
+    // Complete message
+    iNotificationMessage.Complete( aEvents.Count() );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::PurgeNextBufferedNotificationL
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::PurgeNextBufferedNotificationL()
+    {
+    if ( !iNotificationQueue.IsEmpty() )
+         {
+         TBool completed( ETrue );
+         CMediatorQueItem* notification = iNotificationQueue.First();
+         
+         TRACE( Print( _L("[Mediator Server]\t CMediatorServerSession::PurgeNextBufferedNotificationL: type=%d"),
+                       notification->NofiticationType() ) );
+         // remove now, notification will be pushed back to queue if cannot be delivered with the current client request
+         iNotificationQueue.Remove( *notification ); 
+         CleanupStack::PushL( notification );
+         
+         switch ( notification->NofiticationType() )
+             {
+             case EMediatorEventsRegistered:
+             case EMediatorEventsUnregistered:    
+                 DoMediatorEventsChangedL( notification->NofiticationType(),
+                                           notification->Domain(),
+                                           notification->Category(),
+                                           *(notification->Events()),
+                                           completed ); 
+                 break;
+
+             case EMediatorCommandsRegistered:
+             case EMediatorCommandsUnregistered:
+                 DoMediatorCommandsChangedL( notification->NofiticationType(),
+                                             notification->Domain(),
+                                             notification->Category(),
+                                             *(notification->Commands()),
+                                             completed );
+                 break;
+                 
+             case EMediatorCategoryUnregistered:
+                 DoMediatorCategoryRemovedL( notification->Domain(), 
+                                             notification->Category() );    
+                 break;
+             
+             default:
+                 __ASSERT_DEBUG( EFalse, User::Invariant() );
+             }
+         
+         if ( completed )
+             {
+             // no longer needed, cleanup
+             CleanupStack::PopAndDestroy( notification );
+             }
+         else // could not be completed without further client request
+             {
+             iNotificationQueue.AddFirst( *notification );
+             CleanupStack::Pop( notification );
+             }
+
+         }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorCommandsAddedL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorCommandsAddedL( TUid aDomain, 
+                                                     TUid aCategory,
+                                                     const RCommandList& aCommands )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorCommandsAddedL"));
+    
+    HandleMediatorCommandsChangedL( EMediatorCommandsRegistered, aDomain, aCategory, aCommands);
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::HandleMediatorCommandsChangedL
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::HandleMediatorCommandsChangedL( TMediatorNotificationType aNotificationType,
+                                                             const TUid& aDomain, 
+                                                             const TUid& aCategory, 
+                                                             const RCommandList& aCommands )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::HandleMediatorCommandsChangedL"));
+    if ( !iNotificationMessage.IsNull() )
+        {
+        TBool commandListPassed( ETrue );
+               
+        DoMediatorCommandsChangedL( aNotificationType, aDomain, aCategory, aCommands, commandListPassed );
+       
+        if ( !commandListPassed )
+            {
+            // store commands for next EFetchNotificationCommandList
+            CMediatorQueItem* commandsItem = CCommandListQueItem::NewL( aNotificationType, aDomain, aCategory, aCommands );
+            iNotificationQueue.AddFirst( *commandsItem );
+            }
+        }
+    else if ( iNotificationsRegistered )
+        {
+        LOG(_L("[Mediator Server]\t CMediatorServerSession::HandleMediatorCommandsChangedL: received commands buffered"));
+       
+        // store commands for next EWaitForNotifications
+        CMediatorQueItem* commandsItem = CCommandListQueItem::NewL( aNotificationType, aDomain, aCategory, aCommands );
+        iNotificationQueue.AddLast( *commandsItem );
+       }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::DoMediatorCommandsChangedL
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::DoMediatorCommandsChangedL( TMediatorNotificationType aNotificationType, 
+                                                         const TUid& aDomain, 
+                                                         const TUid& aCategory, 
+                                                         const RCommandList& aCommands,
+                                                         TBool& aCommandsPassedToClient )
+    {
+    TRACE( Print( _L("[Mediator Server]\t CMediatorServerSession::DoMediatorCommandsChangedL: D=0x%x, C=0x%x, count=%d" ),
+                  aDomain.iUid, aCategory.iUid, aCommands.Count() ) );
+    
+    // Write category information to message slot 0
+    WriteCategoryL( aDomain, aCategory, iNotificationMessage, 0 );
+    
+    // Write notification type to slot 1
+    TMediatorNotificationType notificationType = aNotificationType;
+    TNotificationTypeRetBuffer typeBuffer( notificationType );
+    iNotificationMessage.WriteL( 1, typeBuffer );
+    
+    // Write command list to slot 3
+    if ( CommandListFitsToClientMemory( aCommands, iNotificationMessage, 3 ) )
+        {
+        WriteCommandListL( aCommands, iNotificationMessage, 3 );
+        aCommandsPassedToClient = ETrue;
+        }
+    else
+        {
+        aCommandsPassedToClient = EFalse;
+        }
+    
+    // Complete message
+    iNotificationMessage.Complete( aCommands.Count() );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::DoMediatorCategoryRemovedL
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::DoMediatorCategoryRemovedL( const TUid& aDomain, 
+                                                         const TUid& aCategory )
+    {
+    TRACE( Print( _L("[Mediator Server]\t CMediatorServerSession::DoMediatorCategoryRemovedL: D=0x%x, C=0x%x"),
+           aDomain.iUid, aCategory.iUid ) );
+    
+    // Write category information to message slot 0
+    WriteCategoryL( aDomain, aCategory, iNotificationMessage, 0 );
+        
+    // Write notification type to slot 1
+    TMediatorNotificationType notificationType = EMediatorCategoryUnregistered;
+    TNotificationTypeRetBuffer typeBuffer( notificationType );
+    iNotificationMessage.WriteL( 1, typeBuffer );
+        
+    // Complete message
+    iNotificationMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorEventL
+// Callback from event handler when event occurs
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorCategoryRemovedL( TUid aDomain, TUid aCategory )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorCategoryRemovedL"));
+    
+    if ( !iNotificationMessage.IsNull() )
+        {
+        DoMediatorCategoryRemovedL( aDomain, aCategory );
+        }
+    else if ( iNotificationsRegistered )
+        {
+        LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorCategoryRemovedL: buffering"));
+            
+        // store category removal for next EWaitForNotifications
+        CMediatorQueItem* notification = CCategoryQueItem::NewL( aDomain, aCategory );
+        iNotificationQueue.AddLast( *notification );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorEventL
+// Callback from event handler when event occurs
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorEventsRemovedL( TUid aDomain, 
+                                                     TUid aCategory,
+                                                     const REventList& aEvents )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorEventsRemovedL"));
+    
+    HandleMediatorEventsChangedL( EMediatorEventsUnregistered, aDomain, aCategory, aEvents );
+    }
+                                     
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::MediatorCommandsRemovedL
+// Callback from event handler when event occurs
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::MediatorCommandsRemovedL( TUid aDomain, 
+                                                       TUid aCategory,
+                                                       const RCommandList& aCommands )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::MediatorCommandsRemovedL"));
+    
+    HandleMediatorCommandsChangedL( EMediatorCommandsUnregistered, aDomain, aCategory, aCommands );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::RegisterEventListL
+// Helper method to register event list. Uses Event handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::RegisterEventListL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::RegisterEventListL"));
+    
+    // Read domain & category
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Read event list
+    REventList eventList = ReadEventListL( aMessage, 1 );
+    CleanupClosePushL( eventList );
+    
+    RMediatorDebug::LogData(aMessage, *this, eventList);
+    
+    // Get handler
+    CMediatorServerEventHandler& eventHandler = Server().EventHandler();
+    
+    // Register events
+    eventHandler.RegisterEventListL( category, eventList, aMessage.SecureId() );
+    
+    // Cleanup
+    CleanupStack::PopAndDestroy( &eventList );
+    
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+    
+    RMediatorDebug::LogStatus();
+    }
+
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::RegisterCommandListL
+// Helper function to register command. Uses Command Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::RegisterCommandListL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::RegisterCommandListL"));
+
+    // Read domain & category
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+     // Read command list information from Message
+    RCommandList commandList = ReadCommandListL( aMessage, 1 );
+    CleanupClosePushL( commandList );
+    
+    RMediatorDebug::LogData(aMessage, *this, commandList);
+    
+    // Get handler
+    CMediatorServerCommandHandler& commandHandler = Server().CommandHandler();
+    
+    // Register commands
+    commandHandler.RegisterCommandListL( category, 
+                                         commandList, 
+                                         aMessage.SecureId(),
+                                         this );
+    
+    // cleanup
+    CleanupStack::PopAndDestroy( &commandList );
+    
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+
+    RMediatorDebug::LogStatus();
+    }
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::UnregisterEventListL
+// Helper method to unregister event(s). Uses Event handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::UnregisterEventListL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::UnregisterEventListL"));
+    
+    // Read domain & category
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+     // Read event list information from Message
+    REventList eventList = ReadEventListL( aMessage, 1 );
+    CleanupClosePushL( eventList );
+    
+    RMediatorDebug::LogData(aMessage, *this, eventList);
+    
+    // Get handler
+    CMediatorServerEventHandler& eventHandler = Server().EventHandler();
+    
+    // Register events
+    eventHandler.UnregisterEventListL( category, eventList, aMessage.SecureId() );
+    
+    // cleanup
+    CleanupStack::PopAndDestroy( &eventList );
+
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+
+    RMediatorDebug::LogStatus();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::UnregisterCommandListL
+// Helper method to unregister command(s). Uses Command handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::UnregisterCommandListL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::UnregisterCommandListL"));
+    
+    // Read domain & category
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Read command list information from Message
+    RCommandList commandList = ReadCommandListL( aMessage, 1 );
+    CleanupClosePushL( commandList );
+    
+    RMediatorDebug::LogData(aMessage, *this, commandList);
+    
+    // Get handler
+    CMediatorServerCommandHandler& commandHandler = Server().CommandHandler();
+    
+    // Unregister commands
+    commandHandler.UnregisterCommandListL( category, commandList, aMessage.SecureId() );
+    
+    // cleanup
+    CleanupStack::PopAndDestroy( &commandList );
+
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+    
+    RMediatorDebug::LogStatus();    
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::SubscribeEventL
+// Helper method to subscribes to event(s). Uses Event handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::SubscribeEventListL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::SubscribeEventListL"));
+  
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+     // Read event list information from Message
+    REventList eventList = ReadEventListL( aMessage, 1 );
+    CleanupClosePushL( eventList );
+    
+    RMediatorDebug::LogData(aMessage, *this, eventList);
+    
+    // Get handler
+    CMediatorServerEventHandler& eventHandler = Server().EventHandler();
+    
+    // Subscribe to events
+    TSecurityInfo messageCaps( aMessage );
+    eventHandler.SubscribeEventListL( category, eventList, messageCaps.iCaps, this );
+    
+    // Cleanup 
+    CleanupStack::PopAndDestroy( &eventList );
+    
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone ); 
+    
+    RMediatorDebug::LogStatus();
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::UnsubscribeEventL
+// Helper method to subscribes to event(s). Uses Event handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::UnsubscribeEventListL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::UnsubscribeEventListL"));
+    
+    // Read domain & category
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Read event list from slot 1
+    REventList eventList = ReadEventListL( aMessage, 1 );
+    CleanupClosePushL( eventList );
+    
+    RMediatorDebug::LogData(aMessage, *this, eventList);
+    
+    // Get handler
+    CMediatorServerEventHandler& eventHandler = Server().EventHandler();
+    
+    // Unsubscribe to events
+    eventHandler.UnsubscribeEventListL( category, eventList, this );
+    
+    // Cleanup
+    CleanupStack::PopAndDestroy( &eventList );
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+
+    RMediatorDebug::LogStatus();
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::GetDomainsL
+// Helper method return registered events. Uses Object handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::GetDomainsL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::GetDomainsL"));
+    
+    // Construct array to hold registered domains
+    RDomainList domainList;
+    CleanupClosePushL( domainList );
+    
+    // Get handler
+    CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+    
+    // Get the list of events
+    objectHandler.GetDomainsL( domainList );
+
+    RMediatorDebug::LogData(aMessage, *this, domainList);
+    
+    // Write the information back to client
+    // 2 is for key information
+    TInt arraySize = ( sizeof(TUid) ) * domainList.Count();
+    
+    // Check that there's enough space before writing the answer
+    TInt space = aMessage.GetDesMaxLength(0);   // Slot 0
+    if ( ( domainList.Count() > 0 ) && ( arraySize <= space  ) )
+        {
+        TPtr8 arrayPtr( (TUint8*)&domainList[0], arraySize, arraySize );
+        aMessage.WriteL( 0, arrayPtr );
+        }
+    
+    // Complete message in case of no errors with domain count
+    aMessage.Complete( domainList.Count() );
+    
+    // Clean up
+    CleanupStack::PopAndDestroy( &domainList );
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::GetCategoriesL
+// Helper method return registered events. Uses Object handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::GetCategoriesL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::GetCategoriesL"));
+    
+    // Read domain information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Construct array to hold registered categories
+    RCategoryList categoryList;
+    CleanupClosePushL( categoryList );
+    
+    // Get handler
+    CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+    
+    // Get the list of events
+    objectHandler.GetCategoriesL( category, categoryList );
+    
+    RMediatorDebug::LogData(aMessage, *this, categoryList);
+    
+    // Write the information back to client
+    // 2 is for key information
+    TInt arraySize = ( sizeof(TUid) ) * categoryList.Count();
+    
+    // Check that there's enough space before writing the answer
+    TInt space = aMessage.GetDesMaxLength(1);   // Slot 1
+    if ( ( categoryList.Count() > 0 ) && ( arraySize <= space  ) )
+        {
+        TPtr8 arrayPtr( (TUint8*)&categoryList[0], arraySize, arraySize );
+        aMessage.WriteL( 1, arrayPtr );
+        }
+    
+    // Complete message in case of no errors with category count
+    aMessage.Complete( categoryList.Count() );
+    
+    // Clean up
+    CleanupStack::PopAndDestroy( &categoryList );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::GetCommandsL
+// Helper method return registered commands. Uses Object handler.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::GetCommandsL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::GetCommandsL"));
+    
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Construct array to hold registered events
+    RCommandList commandList;
+    CleanupClosePushL( commandList );
+    
+    // Get command list using Object handler
+    CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+    objectHandler.GetCommandsL( category, commandList );
+   
+    RMediatorDebug::LogData(aMessage, *this, commandList);
+    
+    // Write command list to slot 1
+    if ( CommandListFitsToClientMemory( commandList, aMessage, 1 ) )
+        {
+        WriteCommandListL( commandList, aMessage, 1 );
+        }
+    // if the list does not fit to memory, the client library makes a new synchronous request
+    //  with a large enough write buffer
+    // Complete message in case of no errors with command count
+    aMessage.Complete( commandList.Count() );
+       
+     // Clean up
+    CleanupStack::PopAndDestroy( &commandList );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::GetEventsL
+// Helper method return registered events. Uses Object Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::GetEventsL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::GetEventsL"));
+    
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Construct array to hold registered events
+    REventList eventList;
+    CleanupClosePushL( eventList );
+    
+    // Get events using Event handler
+    CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+    objectHandler.GetEventsL( category, eventList );
+    
+    RMediatorDebug::LogData(aMessage, *this, eventList);
+    
+    // Write event list to slot 1
+    if ( EventListFitsToClientMemory( eventList, aMessage, 1 ) )
+        {
+        WriteEventListL( eventList, aMessage, 1 );
+        } 
+    // if the list does not fit to memory, the client library makes a new synchronous request
+    //  with a large enough write buffer
+    
+    // Complete message in case of no errors with command count
+    aMessage.Complete( eventList.Count() );
+       
+     // Clean up
+    CleanupStack::PopAndDestroy( &eventList );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::RaiseEventL
+// Helper method to raise events. Uses Event Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::RaiseEventL( const RMessage2& aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::RaiseEventL"));
+    
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+    
+    // Read event information
+    TEvent raiseEvent = ReadEventL( aMessage, 1 );
+    
+    // Then read parameter data from slot 2
+    HBufC8* eventData = ReadDataLC( aMessage, 2 );
+
+    RMediatorDebug::LogData(aMessage, *this, raiseEvent);
+    RMediatorDebug::LogData(aMessage, *this, *eventData);
+    
+    // Get handler
+    CMediatorServerEventHandler& eventHandler = Server().EventHandler();
+    
+    // Raise event
+    eventHandler.RaiseEventL( category, raiseEvent, *eventData );
+    
+    // Cleanup
+    CleanupStack::PopAndDestroy( eventData );
+
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::IssueCommandL
+// Helper function to handle command request. Uses Command Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::IssueCommandL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::IssueCommandL"));
+
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+     
+    // Read command information
+    TCommand issueCommand = ReadCommandL( aMessage, 1 ); 
+    
+    // Then read parameter data from slot 2
+    HBufC8* commandData = ReadDataLC( aMessage, 2 );
+    
+    RMediatorDebug::LogData(aMessage, *this, issueCommand);
+    RMediatorDebug::LogData(aMessage, *this, *commandData);
+    
+    // Get handler & issue command
+    TSecurityInfo messageCaps( aMessage );
+    CMediatorServerCommandHandler& commandHandler = Server().CommandHandler();
+    commandHandler.IssueCommandL( category,
+                                  issueCommand,
+                                  *commandData,
+                                  messageCaps.iCaps,
+                                  this );
+    
+    
+    // cleanup
+    CleanupStack::PopAndDestroy( commandData );
+
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CancelCommandL
+// Cancels ongoing command processing. Uses Command Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::CancelCommandL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::CancelCommandL"));
+
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+     
+    // Read command information
+    TCommand cancelCommand = ReadCommandL( aMessage, 1 ); 
+    
+    RMediatorDebug::LogData(aMessage, *this, cancelCommand);
+    
+    // Get handler & cancel command
+    CMediatorServerCommandHandler& commandHandler = Server().CommandHandler();
+    commandHandler.CancelCommand( category, cancelCommand );
+                                   
+    // Complete initiators async request with KErrCancel
+    if ( iCommandResponseMessage.Handle() )
+        {
+        
+        // Write domain & category information to slot 0
+        WriteCategoryL( category.iDomain, 
+                        category.iCategory, 
+                        iCommandResponseMessage, 
+                        0 );
+        
+        // Write event to slot 1
+        TVersion version( 0, 0, 0 );
+        WriteCommandL( cancelCommand.iCommandId, 
+                       version, 
+                       iCommandResponseMessage, 
+                       1 );
+        
+        // Status to slot 2
+        TPckg<TInt> statusBuffer( KErrCancel );
+        iCommandResponseMessage.WriteL( 2, statusBuffer );
+        
+        // Write data to slot 3
+        WriteDataL( KNullDesC8, iCommandResponseMessage, 2 );
+        
+        iCommandResponseMessage.Complete( KErrCancel );
+        }
+
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::IssueResponseL
+// Helper function to handle command response. Uses Command Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::IssueResponseL( const RMessage2 &aMessage )
+    {
+    LOG(_L("[Mediator Server]\t CMediatorServerSession::IssueResponseL"));
+
+    // Read domain & category information
+    TMediatorCategory category = ReadCategoryL( aMessage, 0 );
+     
+    // Read command information
+    TCommand responseCommand = ReadCommandL( aMessage, 1 ); 
+    
+    // Then read status data from slot 2
+    TPckgBuf<TInt> statusBuffer;
+    aMessage.ReadL( 2, statusBuffer );
+    TInt status = statusBuffer();
+    
+    // And result data from slot 3
+    HBufC8* responseData = ReadDataLC( aMessage, 3 );
+    
+    RMediatorDebug::LogData(aMessage, *this, responseCommand);
+    RMediatorDebug::LogData(aMessage, *this, *responseData);
+    
+    // Get handler & respond to command
+    TSecurityInfo messageCaps( aMessage );
+    CMediatorServerCommandHandler& commandHandler = Server().CommandHandler();
+    
+    TInt err = commandHandler.IssueResponse( category,
+                                             responseCommand,
+                                             *responseData,
+                                             status );
+                                             
+    if ( err != KErrNone )
+        {
+        // If command is not found, it means that the command initiator has cancelled the command
+        
+        // Check the command service list and remove the cancelled command if found, because responder 
+        // can interpret the return value as a cancellation and further notifications are thus not needed
+        TBool found = EFalse;
+        for ( TInt index = 0; index < iCommandServiceList.Count() && !found; index++ )
+            {
+            CCommand* commandPtr = iCommandServiceList[index];
+            if ( commandPtr )
+                {
+                if ( commandPtr->Domain() == category.iDomain
+                    && commandPtr->Category() == category.iCategory
+                    && commandPtr->Id() == responseCommand.iCommandId
+                    && commandPtr->Status() == ECommandCanceled )
+                    {
+                    iCommandServiceList.Remove( index );
+                    delete commandPtr;
+                    commandPtr = NULL;
+                    found = ETrue;
+                    }
+                }
+            }
+        
+        User::Leave( err );
+        }
+    
+    // cleanup
+    CleanupStack::PopAndDestroy( responseData );
+
+    // Complete message in case of no errors
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WaitForEventsL
+// Helper method to receive events
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::WaitForEventsL( const RMessage2& aMessage )
+    {
+    // Check if we have already events to be notified
+    if ( iEventServiceList.Count() > 0 )
+        {
+        CEvent* eventPtr = iEventServiceList[0];    // Take the first event
+        CleanupStack::PushL( eventPtr );
+        iEventServiceList.Remove(0);
+        
+        // Write domain & category to slot 0
+        WriteCategoryL( eventPtr->Domain(), eventPtr->Category(), aMessage, 0 );
+        
+        // Write event to slot 1
+        WriteEventL( eventPtr->Id(), aMessage, 1 );
+        
+        // Write data to slot 2
+        WriteDataL( eventPtr->ParameterData(), aMessage, 2 );
+       
+        // Complete message with data amount
+        aMessage.Complete( eventPtr->ParameterData().Length() );
+        
+        //Cleanup
+        CleanupStack::PopAndDestroy( eventPtr );
+        
+        TRACE(Print(_L("[Mediator Server]\t Session %d - event buffer %d\n"), this, iEventServiceList.Count() ));
+        }
+    else    // Start async waiting
+        {
+        iEventNotificationMessage = aMessage;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WaitForCommandsL
+// Helper method to receive commands.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::WaitForCommandsL( const RMessage2& aMessage )
+    {
+    // Check if we have already commands to be delivered
+    if ( iCommandServiceList.Count() > 0 )
+        {
+        CCommand* commandPtr = iCommandServiceList[0];    // Take the first command
+        CleanupStack::PushL( commandPtr );
+        iCommandServiceList.Remove(0);
+        
+        // If it's a pending command it can now be delivered
+        if ( commandPtr->Status() == ECommandPending )
+            {
+            // Write domain & category to slot 0
+            WriteCategoryL( commandPtr->Domain(), commandPtr->Category(), aMessage, 0 );
+        
+            // Write event to slot 1
+            WriteCommandL( commandPtr->Id(), commandPtr->Version(), aMessage, 1 );
+        
+            // Write data to slot 2
+            WriteDataL( commandPtr->ParameterData(), aMessage, 2 );
+       
+            // Complete message with data amount
+            aMessage.Complete( commandPtr->ParameterData().Length() );
+    
+            }
+        // If it's a cancelled command then the responder will be notified about cancellation that
+        // it was not able to handle before   
+        else if ( commandPtr->Status() == ECommandCanceled )
+            {
+            // Write domain & category to slot 0
+            WriteCategoryL( commandPtr->Domain(), commandPtr->Category(), aMessage, 0 );
+            
+            // Write command id and version to slot 1
+            WriteCommandL( commandPtr->Id(), commandPtr->Version(), aMessage, 1 );
+            
+            // Status to slot 2
+            TPckg<TInt> statusBuffer( KErrCancel );
+            aMessage.WriteL( 2, statusBuffer );
+        
+            // Write data to slot 3
+            WriteDataL( KNullDesC8, aMessage, 2 );
+        
+            // Complete message
+            aMessage.Complete( KErrCancel );
+            }
+            
+        //Cleanup
+        CleanupStack::PopAndDestroy( commandPtr );            
+                
+        TRACE(Print(_L("[Mediator Server]\t Session %d - command buffer %d\n"), this, iCommandServiceList.Count() ));
+        }
+    else    // Start async waiting
+        {
+        iCommandInitMessage = aMessage;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WaitForNotificationsL
+// Starts async notification waiting. Uses Object Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::WaitForNotificationsL( const RMessage2& aMessage )
+    {
+    if ( !iNotificationMessage.Handle() )
+        {
+        if ( !iNotificationsRegistered )
+            {
+            // Get handler
+            CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+            objectHandler.AddObserverL( this );
+            iNotificationsRegistered = ETrue;
+            }
+        iNotificationMessage = aMessage;
+        
+        if ( !iNotificationQueue.IsEmpty() )
+            {
+            PurgeNextBufferedNotificationL();
+            }
+        }
+    else
+        {
+        ERROR_LOG(_L("[Mediator] CMediatorServerSession::WaitForNotificationsL: KErrAlreadyExists\n"));
+        User::Leave( KErrAlreadyExists );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CancelNotificationsL
+// Stops async notification waiting.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::CancelNotificationsL( const RMessage2& aMessage )
+    {
+    CleanNotificationQueue();
+    
+    if ( iNotificationMessage.Handle() )
+        {
+        iNotificationMessage.Complete( KErrCancel );
+        }   
+    if ( iNotificationsRegistered )
+        {
+        // Get handler
+        CMediatorServerObjectHandler& objectHandler = Server().ObjectHandler();
+        objectHandler.RemoveObserverL( this );
+        iNotificationsRegistered = EFalse;
+        }
+    else
+        {
+        ERROR_LOG(_L("[Mediator] CMediatorServerSession::CancelNotificationsL: KErrNotFound\n"));
+        User::Leave( KErrNotFound );
+        }
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::WaitForCommandResponseL
+// Async waiting for command responses
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::WaitForCommandResponseL( const RMessage2& aMessage )
+    {
+    // Just take message to member variable to future use
+    if ( !iCommandResponseMessage.Handle() )
+        {
+        iCommandResponseMessage = aMessage;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::FetchParameterDataL
+// Async waiting for command responses
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::FetchParameterDataL( const RMessage2& aMessage )
+    {
+    // Write data buffer to message slot 0 and complete with size of the buffer
+    if ( iDataBuffer )
+        {
+        WriteDataL( *iDataBuffer, aMessage, 0 );
+        aMessage.Complete( iDataBuffer->Length() );
+        delete iDataBuffer;
+        iDataBuffer = NULL;
+        }
+    else
+        {
+        aMessage.Complete( 0 ); // Just complete with zero sized data
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::FetchNotificationEventListL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::FetchNotificationEventListL( const RMessage2& aMessage )
+    {
+    // Write event list to message slot 0 and complete with count of events in the list
+    CMediatorQueItem* eventList = iNotificationQueue.First();
+    iNotificationQueue.Remove( *eventList );
+    CleanupStack::PushL( eventList );
+    const REventList* events( eventList->Events() );
+    
+    if ( !events )
+        {
+        // should not ever end up leaving here, as this indicates a
+        // problem with queue management i.e. a programming error
+        ERROR_LOG( _L("[Mediator] CMediatorServerSession::FetchNotificationEventListL: notif queue corrupted\n") );
+        User::Leave( KErrCorrupt );
+        }
+    
+    WriteEventListL( *events, aMessage, 0 );
+    aMessage.Complete( events->Count() );
+    CleanupStack::PopAndDestroy( eventList );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::FetchNotificationCommandListL
+// 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::FetchNotificationCommandListL( const RMessage2& aMessage )
+    {
+    // Write command list buffer to message slot 0 and complete count of commands in the list
+    CMediatorQueItem* commandList = iNotificationQueue.First();
+    iNotificationQueue.Remove( *commandList );
+    CleanupStack::PushL( commandList );
+    const RCommandList* commands( commandList->Commands() );
+    
+    if ( !commands )
+        {
+        // should not ever end up leaving here, as this indicates a
+        // problem with queue management i.e. a programming error
+        ERROR_LOG( _L("[Mediator] CMediatorServerSession::FetchNotificationCommandListL: notif queue corrupted\n") );
+        User::Leave( KErrCorrupt );
+        }
+    
+    WriteCommandListL( *commands, aMessage, 0 );
+    aMessage.Complete( commands->Count() );
+    CleanupStack::PopAndDestroy( commandList );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CancelAll
+// Async waiting for command responses
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::CancelAll( const RMessage2& aMessage )
+    {
+    // Cancel all possible async wait operations
+    CancelAll( KErrCancel );
+    // Finally complete own message
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMediatorServerSession::CancelAll
+// Async waiting for command responses
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMediatorServerSession::CancelAll( TInt aError )
+    {
+    // Cancel all possible async wait operations
+    if ( iCommandResponseMessage.Handle() )
+        {
+        iCommandResponseMessage.Complete( aError );
+        }
+    if ( iCommandInitMessage.Handle() )
+        {
+        iCommandInitMessage.Complete( aError );
+        }
+    if ( iNotificationMessage.Handle() )
+        {
+        CleanNotificationQueue();
+        iNotificationMessage.Complete( aError );
+        }
+    if ( iEventNotificationMessage.Handle() )
+        {
+        iEventNotificationMessage.Complete( aError );
+        }
+    }
+
+// End of File