omadrm/drmengine/notifier/src/DRMNotifierSession.cpp
changeset 0 95b198f216e5
child 2 76350b5be3d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/notifier/src/DRMNotifierSession.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,521 @@
+/*
+* Copyright (c) 2004-2009 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:  This class handles all client requests.
+*
+*/
+
+
+// INCLUDE FILES
+#include <s32file.h>
+#include <f32file.h>
+#include "drmcommon.h"
+#include "DRMNotifierSession.h"
+#include "DRMNotifierServer.h"
+#include "drmnotifierclientserver.h"
+#include <e32test.h>
+
+// NAMESPACES
+using namespace DRMNotifier;
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES  
+// CONSTANTS
+
+
+// MACROS
+#ifdef _DRM_TESTING
+#define LOG( a ) ( ( CDRMNotifierServer* )( Server() ) )->Log( a )
+#else
+#define LOG( a )
+#endif
+
+// LOCAL CONSTANTS AND MACROS
+
+const TInt KSanityDataLengthLow = 0;
+const TInt KSanityDataLengthHigh = 32768;
+
+// MODULE DATA STRUCTURES
+// DATA TYPES
+// LOCAL FUNCTIONS
+
+
+// -----------------------------------------------------------------------------
+// SanitizeL
+// Performs a sanity check on length parameters
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void SanitizeL( TInt aParam )
+    {
+    if( aParam <= KSanityDataLengthLow || aParam > KSanityDataLengthHigh )
+        {
+        User::Leave(KErrArgument);
+        }
+    }
+
+// FORWARD DECLARATIONS
+// ============================ MEMBER FUNCTIONS ===============================
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CDRMNotifierSession* CDRMNotifierSession::NewL( CDRMMessageStorage* aStorage) 
+    {
+    CDRMNotifierSession* self = new( ELeave ) CDRMNotifierSession( aStorage );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop(); // self
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::~CDRMNotifierSession
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CDRMNotifierSession::~CDRMNotifierSession()
+    {
+    TInt error = KErrNone;
+    TInt i = 0;
+
+    if( iStorage )
+        {
+        TRAP(error, iStorage->CancelL( this ) );
+        }
+
+    if(error)
+        {
+        LOG( _L8( " Something went wrong with Cancelling the notifications " ) );
+        }
+
+    for( i = 0; i < iMessageQueue.Count(); i++ )
+        {
+        iStorage->UpdateMessage(iMessageQueue[i]);
+        }
+
+    iMessageQueue.Reset();
+
+    for( i = 0; i < iContentIDList.Count(); i++ )
+        {
+        if( iContentIDList[i]->iContentID )
+            {
+            delete iContentIDList[i]->iContentID;
+            iContentIDList[i]->iContentID = NULL;
+            }
+        delete iContentIDList[i];
+        iContentIDList[i] = NULL;
+        }
+    iContentIDList.Reset();
+
+    LOG( _L8( "Notifier session closed." ) );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::SendNotificationL
+// This method sends a notification to the client or if it's not active adds it
+// to the queue and the next time a registration happens the client will get
+// notified.
+// -----------------------------------------------------------------------------
+//
+TBool CDRMNotifierSession::SendNotificationL( CDRMMessageStorage::TMessageData* aMessage )
+    {
+    if( !CanNotify( aMessage ) )
+        {
+        User::Leave(KErrNotFound);
+        }
+
+    if( !iIsListening || iMessageQueue.Count() )
+        {
+        iMessageQueue.Append( aMessage );
+        return ETrue;
+        }
+    NotifyL( aMessage, EFalse );
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::ServiceL
+// This method runs DispatchL() under TRAP harness, since every error case
+// can be handled ==> no need to let this function leave.
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::ServiceL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "ServiceL called" ) );
+    // Trap possible errors...
+    
+    TRAPD( error, DispatchL( aMessage ) );
+    
+    if ( error )
+        {
+        LOG( _L8( "DispatcL threw an exception" ) );
+        // ...and complete the request in case of an error.
+        aMessage.Complete( error );
+        return;
+        }
+
+    // The message has already completed successfully.
+    LOG( _L8( "DispatchL completed successfully" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::CDRMNotifierSession
+// Default constructor.
+// -----------------------------------------------------------------------------
+//
+CDRMNotifierSession::CDRMNotifierSession( CDRMMessageStorage* aStorage ) : 
+    // Base class' constructor is called first.
+    iStorage( aStorage )
+    {
+    // Nothing.
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::ConstructL
+// Second phase constructor. Initializes the log tool in DRM internal testing.
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::DispatchL
+// Checks which command the user requested, and forwards the request to 
+// appropriate private method. This helps to keep the code more readable.
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::DispatchL( const RMessage2& aMessage ) 
+    {
+		RDebug::Printf(">>> [%s] %d", _S8(__PRETTY_FUNCTION__), aMessage.Function());
+    switch ( aMessage.Function() )
+        {
+        case ENotifyClients:
+            NotifyClientsL( aMessage );
+            break;
+        case ERecieveNotification:
+            RecieveNotificationL( aMessage );
+            break;
+        case ECancelNotification:
+            CancelNotificationL( aMessage );
+            break;
+        case ERegister:
+            RegisterL( aMessage );
+            break;
+        case EUnRegister:
+            UnRegisterL( aMessage );
+            break;
+        case ERegisterURI:
+            RegisterURIL( aMessage );
+            break;
+        case EUnRegisterURI:
+            UnRegisterURIL( aMessage );
+            break;
+        default:
+            LOG( _L8( "DispatchL: Invalid command" ) );
+            User::Leave( KErrNotSupported );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::NotifyClientsL
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::NotifyClientsL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "NotifyClientsL" ) );
+    TDRMEventType eventType;
+
+    eventType = aMessage.Int1();
+
+    iStorage->NotifyL(eventType,aMessage);
+
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::RecieveNotificationL
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::RecieveNotificationL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "RecieveNotificationL" ) );
+    TInt error = KErrNone;
+    TPckg<TInt> package(0);
+    TDRMEventType eventType;
+
+    package.Set(reinterpret_cast<TUint8*>(&eventType),sizeof(TDRMEventType),sizeof(TDRMEventType));
+    TRAP(error, aMessage.ReadL(1, package));
+
+    // Set the status of listening
+    iIsListening = ETrue;
+
+    // Set this to message as listener
+    iListener = aMessage;
+
+    if( !iIsInStorage )
+        {
+        iIsInStorage = ETrue;
+        iStorage->AddSession( this );
+        }
+
+    // Check if there are any notifications in queue if so process first one
+    if( iMessageQueue.Count() )
+        {
+        NotifyL( iMessageQueue[0], ETrue );
+        }
+ 
+    // Message complete will be set elsewhere.
+    // All done.
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::CancelNotificationL
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::CancelNotificationL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "CancelNotificationL" ) );
+    TInt error = KErrNone;
+    TInt i = 0;
+
+    TRAP(error, iStorage->CancelL( this ) );
+    if( error && error != KErrNotFound )
+        {
+        LOG(  _L8( "CDRMNotifierSession:: Something went wrong with Cancelling the notifications " ) );
+        }
+
+    for( i = 0; i < iMessageQueue.Count(); i++ )
+        {
+        iStorage->UpdateMessage(iMessageQueue[i]);
+        }
+    iMessageQueue.Reset();
+
+    for( i = 0; i < iContentIDList.Count(); i++ )
+        {
+        if( iContentIDList[i]->iContentID )
+            {
+            delete iContentIDList[i]->iContentID;
+            iContentIDList[i]->iContentID = NULL;
+            }
+        delete iContentIDList[i];
+        iContentIDList[i] = NULL;
+        }
+    iContentIDList.Reset();
+
+    iIsInStorage = EFalse;
+
+	iIsListening = EFalse;
+	
+	if ( !iListener.IsNull() )
+		{
+		iListener.Complete( KErrCancel );
+		}
+	
+    aMessage.Complete( KErrNone );
+    }
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::RegisterURIL
+// Get the information from the client, construct a rights object, and add 
+// it to the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::RegisterL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "RegisterL" ) );
+    TPckg<TInt> package(0);
+    TDRMEventType eventType = 0;
+    TContentData* content = 0;
+
+    package.Set(reinterpret_cast<TUint8*>(&eventType),sizeof(TDRMEventType),sizeof(TDRMEventType));
+    aMessage.ReadL(0, package);
+
+    content = new (ELeave) TContentData;
+
+    content->iContentID = NULL;
+    content->iEventType = eventType;
+
+    iContentIDList.Append( content );
+
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::UnRegisterURIL
+// Get the information from the client, construct a rights object, and add 
+// it to the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::UnRegisterL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "UnRegisterL" ) );
+    TPckg<TInt> package(0);
+    TDRMEventType eventType = 0;
+
+    package.Set(reinterpret_cast<TUint8*>(&eventType),sizeof(TDRMEventType),sizeof(TDRMEventType));
+    aMessage.ReadL(0, package);
+
+    for( TInt i = 0; i < iContentIDList.Count(); i++ )
+        {
+        if( !iContentIDList[i]->iContentID &&
+            iContentIDList[i]->iEventType == eventType )
+            {
+            delete iContentIDList[i];
+            iContentIDList[i] = NULL;
+
+            iContentIDList.Remove(i);
+            break;
+            }
+        }
+
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::RegisterURIL
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::RegisterURIL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "RegisterURIL" ) );
+    TPckg<TInt> package(0);
+    TDRMEventType eventType = 0;
+    TContentData* content = 0;
+    TInt length = 0;
+
+    HBufC8* contentID = 0;
+    TPtr8 packageData(NULL,0);
+
+    length = aMessage.GetDesLength(0);
+
+    SanitizeL( length );
+
+    contentID = HBufC8::NewLC(length);
+    packageData.Set(contentID->Des());
+
+    aMessage.ReadL(0, packageData);
+
+    package.Set(reinterpret_cast<TUint8*>(&eventType),sizeof(TDRMEventType),sizeof(TDRMEventType));
+    aMessage.ReadL(1, package);
+
+    content = new (ELeave) TContentData;
+
+    content->iContentID = contentID;
+    content->iEventType = eventType;
+
+    iContentIDList.Append( content );
+
+    CleanupStack::Pop();
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::UnRegisterURIL
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::UnRegisterURIL( const RMessage2& aMessage )
+    {
+    LOG( _L8( "UnRegisterURIL" ) );
+    TPckg<TInt> package(0);
+    TDRMEventType eventType = 0;
+    TInt length = 0;
+
+    HBufC8* contentID = 0;
+    TPtr8 packageData(NULL,0);
+
+    length = aMessage.GetDesLength(0);
+
+    SanitizeL( length );
+
+    contentID = HBufC8::NewLC(length);
+    packageData.Set(contentID->Des());
+
+    aMessage.ReadL(0, packageData);
+
+    package.Set(reinterpret_cast<TUint8*>(&eventType),sizeof(TDRMEventType),sizeof(TDRMEventType));
+    aMessage.ReadL(1, package);
+
+    for( TInt i = 0; i < iContentIDList.Count(); i++ )
+        {
+        if( iContentIDList[i]->iContentID &&
+            iContentIDList[i]->iEventType == eventType &&
+            !iContentIDList[i]->iContentID->Compare( contentID->Des() ) )
+            {
+            if( iContentIDList[i]->iContentID )
+                {
+                delete iContentIDList[i]->iContentID;
+                iContentIDList[i]->iContentID = NULL;
+                }
+            delete iContentIDList[i];
+            iContentIDList[i] = NULL;
+
+            iContentIDList.Remove(i);
+            break;
+            }
+        }
+    CleanupStack::PopAndDestroy();
+    aMessage.Complete( KErrNone );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::NotifyL
+// -----------------------------------------------------------------------------
+//
+void CDRMNotifierSession::NotifyL( CDRMMessageStorage::TMessageData *aMessage, TBool aFromQueue )
+    {
+    LOG( _L8( "NotifyL" ) );
+    TPtr8 data( reinterpret_cast<TUint8*>(&aMessage->iEventType),
+                sizeof(TDRMEventType),
+                sizeof(TDRMEventType));
+    TPtr8 event( aMessage->iMessageData, DRMNotifier::KDRMSizeOfMessage, 
+                 DRMNotifier::KDRMSizeOfMessage );
+
+    iListener.WriteL(0, event);
+    iListener.WriteL(1, data);
+
+    iListener.Complete( KErrNone );
+
+    // Remove the message from the queue
+    if( aFromQueue )
+        {
+        // Reduce the counter and release the message if needed
+        iStorage->UpdateMessage( aMessage );
+
+        iMessageQueue.Remove(0);
+        }
+    iIsListening = EFalse;
+    }
+// -----------------------------------------------------------------------------
+// CDRMNotifierSession::CanNotifyL
+// -----------------------------------------------------------------------------
+//
+TBool CDRMNotifierSession::CanNotify( CDRMMessageStorage::TMessageData *aMessage )
+    {
+    for( TInt i = 0; i < iContentIDList.Count(); i++ )
+        {
+        if( iContentIDList[i]->iEventType == aMessage->iEventType &&
+            (!iContentIDList[i]->iContentID ||
+            !iContentIDList[i]->iContentID->Compare( aMessage->iData->Des() ) ) )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+//  End of File