ncdengine/engine/src/catalogsclientserverserversession.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Implementation of CCatalogsClientServerServerSession
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32kpan.h>
       
    20 
       
    21 #include "catalogsclientserverserversession.h"
       
    22 #include "catalogsserverdefines.h"
       
    23 #include "catalogscommunicable.h"
       
    24 #include "catalogsbasemessageimpl.h"
       
    25 #include "catalogsincompletemessage.h"
       
    26 #include "catalogscontextimpl.h"
       
    27 #include "catalogsdebug.h"
       
    28 
       
    29 
       
    30 // ======== LOCAL FUNCTIONS ========
       
    31 
       
    32 // ---------------------------------------------------------------------------
       
    33 // Cleanupfunction for cleanupitem usage. Closes CObject based
       
    34 // object as many times as needed to destroy it when removed
       
    35 // from cleanupstack.
       
    36 // ---------------------------------------------------------------------------
       
    37 //    
       
    38 void CCatalogsClientServerServerSession::CleanupCObjectBasedClass( TAny* aCObject )
       
    39 	{
       
    40 	CObject* convertedCObject = ( static_cast< CObject* > ( aCObject ) );
       
    41 	TInt accessCount = convertedCObject->AccessCount();
       
    42     while ( accessCount > 0 )
       
    43         {
       
    44         convertedCObject->Close();
       
    45         --accessCount;
       
    46         }
       
    47     // Now that last reference is closed, aCObject is destroyed
       
    48 	}
       
    49 
       
    50 
       
    51 // ======== MEMBER FUNCTIONS ========
       
    52 
       
    53 CCatalogsClientServerServerSession* CCatalogsClientServerServerSession::NewL(
       
    54     RThread& aClient,
       
    55     CCatalogsClientServerServer& aServer )
       
    56     {
       
    57     CCatalogsClientServerServerSession* self = 
       
    58         CCatalogsClientServerServerSession::NewLC( aClient, aServer );
       
    59     CleanupStack::Pop(self) ;
       
    60     return self ;
       
    61     }
       
    62 
       
    63 CCatalogsClientServerServerSession* CCatalogsClientServerServerSession::
       
    64     NewLC( RThread& aClient, CCatalogsClientServerServer& aServer )
       
    65     {
       
    66     CCatalogsClientServerServerSession* self = 
       
    67         new (ELeave) CCatalogsClientServerServerSession( aClient, aServer,
       
    68             aServer.NewInstanceId() );
       
    69     CleanupStack::PushL( self );
       
    70     self->ConstructL();
       
    71     return self;
       
    72     }
       
    73 
       
    74 CCatalogsClientServerServerSession::CCatalogsClientServerServerSession(
       
    75     RThread& /*aClient*/,
       
    76     CCatalogsClientServerServer& aServer,
       
    77     TInt aInstanceId ) :
       
    78     CSession2(),
       
    79     iClientSideDownAnnounced( ENotInformed ),
       
    80     iServer( aServer ),
       
    81     iInstanceId( aInstanceId )
       
    82     {
       
    83     }
       
    84 
       
    85 CCatalogsClientServerServerSession::~CCatalogsClientServerServerSession()
       
    86     {
       
    87     DLTRACEIN((""));
       
    88     ClientSideSessionDown();   
       
    89     DLTRACE(("Deleting context")); 
       
    90     delete iContext;
       
    91     iServer.DecrementSessions();    
       
    92     DLTRACEOUT((""));
       
    93     }
       
    94 
       
    95 void CCatalogsClientServerServerSession::ConstructL() 
       
    96     {    
       
    97     iServer.IncrementSessions();
       
    98     iMessageHandlers = CObjectIx::NewL();
       
    99     iIncompleteMessageContainer = iServer.NewContainerL();
       
   100     iIncompleteMessages = CObjectIx::NewL();
       
   101 
       
   102     }
       
   103 
       
   104 void CCatalogsClientServerServerSession::ClientSideSessionDown()
       
   105     {
       
   106     DLTRACEIN((""));
       
   107     if ( iClientSideDownAnnounced == ENotInformed )
       
   108         {
       
   109         DLTRACE(("Delete incomplete messages"));
       
   110         // Incomplete messages act as receivers of messages as well
       
   111         // as nodes etc.
       
   112         delete iIncompleteMessages;
       
   113         iIncompleteMessages = NULL;
       
   114 
       
   115         // In examples, container is simply deleted, but here
       
   116         // this ends up making a KERN-EXEC 3. Probably container is 
       
   117         // removed for a second time when the container-index is removed.
       
   118         if ( iIncompleteMessageContainer != NULL )
       
   119             {
       
   120             DLTRACE(("Remove container"));
       
   121             iServer.RemoveContainer( iIncompleteMessageContainer );
       
   122             DLTRACE(("Container removed"));
       
   123             }
       
   124         iIncompleteMessageContainer = NULL;
       
   125         
       
   126         
       
   127         CloseMessageHandlers();
       
   128         
       
   129         DLTRACE(("Handle session removal"));
       
   130         // Inform possibly interested objects of session removal
       
   131         // so they know that this session does not exist anymore
       
   132         iServer.HandleSessionRemoval( *this );
       
   133         
       
   134         iClientSideDownAnnounced = EInformed;        
       
   135         }
       
   136         
       
   137     DLTRACEOUT((""));
       
   138     }
       
   139     
       
   140 
       
   141 TInt CCatalogsClientServerServerSession::WriteToLargerDesL(
       
   142     const TDesC8& aOutputData,
       
   143     TInt aStatus )
       
   144     {
       
   145     CCatalogsIncompleteMessage* incompleteMessage =
       
   146         CCatalogsIncompleteMessage::NewL();
       
   147 
       
   148     // NOTICE: Because a CObject-derived object cannot be deleted
       
   149     //         when its reference count is not zero, we use a
       
   150     //         cleanup-item. Another way could be to do it in the
       
   151     //         destructor of the CObject-derived object, but
       
   152     //         it could enable unintended destruction of the object.?
       
   153     TCleanupItem cleanupCObjectInfo( CleanupCObjectBasedClass,
       
   154                                  incompleteMessage );
       
   155     CleanupStack::PushL( cleanupCObjectInfo );    
       
   156     
       
   157     incompleteMessage->SetMessageL( aOutputData, aStatus );
       
   158     iIncompleteMessageContainer->AddL( incompleteMessage );
       
   159     TInt handle = iIncompleteMessages->AddL( incompleteMessage );
       
   160 
       
   161     CleanupStack::Pop( incompleteMessage );
       
   162     return handle;
       
   163     }
       
   164 
       
   165 TInt CCatalogsClientServerServerSession::WriteToLargerDesL(
       
   166     const TDesC16& aOutputData,
       
   167     TInt aStatus )
       
   168     {
       
   169     CCatalogsIncompleteMessage* incompleteMessage =
       
   170         CCatalogsIncompleteMessage::NewL();
       
   171 
       
   172     // NOTICE: Because a CObject-derived object cannot be deleted
       
   173     //         when its reference count is not zero, we use a
       
   174     //         cleanup-item. Another way could be to do it in the
       
   175     //         destructor of the CObject-derived object, but
       
   176     //         it could enable unintended destruction of the object.?
       
   177     TCleanupItem cleanupCObjectInfo( CleanupCObjectBasedClass,
       
   178                                  incompleteMessage );
       
   179     CleanupStack::PushL( cleanupCObjectInfo );
       
   180     
       
   181     incompleteMessage->SetMessageL( aOutputData, aStatus );
       
   182     iIncompleteMessageContainer->AddL( incompleteMessage );
       
   183     TInt handle = iIncompleteMessages->AddL( incompleteMessage );
       
   184 
       
   185     CleanupStack::Pop( incompleteMessage );
       
   186     return handle;
       
   187     }
       
   188 
       
   189 void CCatalogsClientServerServerSession::RemoveIncompleteMessage( TInt aHandle )
       
   190     {
       
   191     iIncompleteMessages->Remove( aHandle );
       
   192     }
       
   193 
       
   194 void CCatalogsClientServerServerSession::ServiceL( const RMessage2& aMessage )
       
   195     {
       
   196     DLTRACEIN((""));
       
   197     
       
   198     // If ServiceL leaves, the framework calls ServiceError which by default
       
   199     // completes the message with the leave code if it has not been completed
       
   200     // yet
       
   201     HandleMessageL( aMessage );
       
   202     }
       
   203 
       
   204 TInt CCatalogsClientServerServerSession::AddObjectL(
       
   205     CObject* aObject )
       
   206     {
       
   207     iServer.AddObjectToContainerL( aObject );
       
   208     TInt handle( iMessageHandlers->AddL( aObject ) );
       
   209     // Because add to the ix does not call Open() of the CObject,
       
   210     // we have to do it ourselves
       
   211     User::LeaveIfError( aObject->Open() );
       
   212     return handle;
       
   213     }
       
   214 
       
   215 void CCatalogsClientServerServerSession::RemoveObject( TInt aHandle )
       
   216     {
       
   217     // This closes the CObject once.
       
   218     iMessageHandlers->Remove( aHandle );
       
   219     }
       
   220 
       
   221 MCatalogsContext& CCatalogsClientServerServerSession::Context()
       
   222     {
       
   223     return *iContext;
       
   224     }
       
   225 
       
   226 
       
   227 const MCatalogsContext* CCatalogsClientServerServerSession::ContextPtr() const
       
   228     {
       
   229     return iContext;
       
   230     }
       
   231 
       
   232 
       
   233 void CCatalogsClientServerServerSession::HandleMessageL(
       
   234     const RMessage2& aMessage )
       
   235     {
       
   236     DLTRACEIN(("Function: %X", aMessage.Function() ));
       
   237 
       
   238     // NOTICE: If aMessage has to be stored and used later
       
   239     //         then copy it and use the copy instead.
       
   240 
       
   241     if ( iClientSideDownAnnounced == EInformed )
       
   242         {
       
   243         // Do not communicate to client anymore
       
   244         // client-side session is going down
       
   245         return;
       
   246         }
       
   247     else if( ( aMessage.Function() != ECatalogsCreateContext ) 
       
   248              && ( iContext == NULL ) )
       
   249         {
       
   250         DLERROR(( "Completing message with KErrNotReady" ));
       
   251         aMessage.Complete( KErrNotReady );
       
   252         }
       
   253 
       
   254     
       
   255     if( aMessage.Function() == ECatalogsExternalMessage 
       
   256         || aMessage.Function() == ECatalogsExternalAllocMessage )
       
   257         {
       
   258         HandleExternalMessageL( aMessage );
       
   259         }
       
   260     else
       
   261         {
       
   262         HandleInternalMessageL( aMessage );
       
   263         }
       
   264     DLTRACEOUT((""));
       
   265     }
       
   266 
       
   267 void CCatalogsClientServerServerSession::HandleExternalMessageL(
       
   268     const RMessage2& aMessage )
       
   269     {
       
   270     DLTRACEIN((""));
       
   271     TPckgBuf<TInt> handle;
       
   272     aMessage.ReadL( 1, handle );
       
   273 
       
   274 
       
   275     CCatalogsCommunicable* receiver = ReceiverFromHandle( handle() );
       
   276     
       
   277     DLTRACE(("Receiver for message: %X", receiver ));
       
   278 
       
   279     if( !receiver )
       
   280         {
       
   281         PanicClient( aMessage, EBadHandle );
       
   282         return;
       
   283         }
       
   284     
       
   285 
       
   286     CCatalogsBaseMessageImpl* baseMessage = 
       
   287         CCatalogsBaseMessageImpl::NewLC( aMessage,
       
   288                                          *this,
       
   289                                          handle() );
       
   290     TPckgBuf<TInt> funcNumber;
       
   291     aMessage.ReadL( 0, funcNumber );
       
   292         
       
   293     CleanupStack::Pop( baseMessage );
       
   294 
       
   295     DLTRACE(("Passing message"));
       
   296 
       
   297     // Now the message is already passed to the receiver
       
   298     // and it is its duty to use it to inform of possible
       
   299     // error situations
       
   300     //      -> Nothing is done here            
       
   301     receiver->ReceiveMessage( baseMessage, funcNumber() );
       
   302     
       
   303     DLTRACEOUT(("Message passed"));    
       
   304     }
       
   305 
       
   306 void CCatalogsClientServerServerSession::HandleInternalMessageL(
       
   307     const RMessage2& aMessage )
       
   308     {
       
   309     DLTRACEIN((""));
       
   310     switch( aMessage.Function() )
       
   311         {
       
   312         case ECatalogsCompleteMessage:
       
   313             {
       
   314             DLTRACE(("ECatalogsCompleteMessage"));
       
   315             TPckgBuf<TInt> handle;
       
   316             aMessage.ReadL( 1, handle );
       
   317             
       
   318             CCatalogsIncompleteMessage* incompleteMessage =
       
   319                 IncompleteMessageFromHandle( handle() );
       
   320             if( !incompleteMessage )
       
   321                 {
       
   322                 PanicClient( aMessage, EBadHandle );
       
   323                 return;
       
   324                 }
       
   325             
       
   326             const TDesC8& message = incompleteMessage->Message();
       
   327             TInt returnValue = incompleteMessage->ReturnValue();
       
   328             
       
   329             DLINFO(( "Writing message" ));
       
   330             TRAPD( error, aMessage.WriteL( 3, message ) );                        
       
   331             if ( error != KErrNone )
       
   332                 {
       
   333                 RemoveIncompleteMessage( handle() );
       
   334                 User::Leave( error );
       
   335                 }
       
   336 
       
   337             DLINFO(( "Completing message with %d", returnValue ));
       
   338             aMessage.Complete( returnValue );
       
   339             
       
   340             RemoveIncompleteMessage( handle() );            
       
   341             break;
       
   342             }
       
   343             
       
   344             
       
   345         case ECatalogsCompleteMessageWide:
       
   346             {
       
   347             DLTRACE(("ECatalogsCompleteMessageWide"));
       
   348             TPckgBuf<TInt> handle;
       
   349             aMessage.ReadL( 1, handle );
       
   350             
       
   351             CCatalogsIncompleteMessage* incompleteMessage =
       
   352                 IncompleteMessageFromHandle( handle() );
       
   353             if( !incompleteMessage )
       
   354                 {
       
   355                 PanicClient( aMessage, EBadHandle );
       
   356                 return;
       
   357                 }
       
   358             
       
   359             const TDesC16& message = incompleteMessage->MessageWide();
       
   360             TInt returnValue = incompleteMessage->ReturnValue();
       
   361 
       
   362             DLINFO(( "Writing message" ));
       
   363             TRAPD( error, aMessage.WriteL( 3, message ) );
       
   364             if ( error != KErrNone )
       
   365                 {
       
   366                 RemoveIncompleteMessage( handle() );
       
   367                 User::Leave( error );
       
   368                 }
       
   369 
       
   370             DLINFO(( "Completing message with %d", returnValue ));
       
   371             aMessage.Complete( returnValue );
       
   372             RemoveIncompleteMessage( handle() );
       
   373             break;
       
   374             }
       
   375                         
       
   376         case ECatalogsRemoveIncompleteMessage:
       
   377             {
       
   378             DLTRACE(("ECatalogsRemoveIncompleteMessage"));
       
   379             TPckgBuf<TInt> handle;
       
   380             aMessage.ReadL( 1, handle );
       
   381             RemoveIncompleteMessage( handle() );
       
   382             DLINFO(( "Completing message with KErrNone" ));
       
   383             aMessage.Complete( KErrNone );
       
   384             
       
   385             break;
       
   386             }
       
   387         case ECatalogsClientSideDown:
       
   388             {
       
   389             DLTRACE(("ECatalogsClientSideDown"));
       
   390             ClientSideSessionDown();
       
   391             DLINFO(( "Completing message with KErrNone" ));
       
   392             aMessage.Complete( KErrNone );
       
   393             break;
       
   394             }
       
   395 
       
   396         case ECatalogsCreateProvider:
       
   397             {
       
   398             DLTRACE(("Create Provider"));
       
   399             
       
   400             CreateProviderL( aMessage );
       
   401             DLTRACE(("Create Provider done"));
       
   402             break;
       
   403             }
       
   404 
       
   405         case ECatalogsCreateContext:
       
   406             {
       
   407             DLTRACE(("ECatalogsCreateContext"));
       
   408             CreateContextL( aMessage );
       
   409             break;
       
   410             }
       
   411 
       
   412         default:
       
   413             {
       
   414             }
       
   415         }    
       
   416     }
       
   417 
       
   418 void CCatalogsClientServerServerSession::CreateProviderL(
       
   419     const RMessage2& aMessage )
       
   420     {
       
   421     DLTRACEIN((""));
       
   422 
       
   423     TInt providerUid = aMessage.Int0();
       
   424     TUint32 providerOptions = aMessage.Int2();
       
   425     
       
   426     // We have to have a integer which contains the handle to be
       
   427     // able to write it into client side later.
       
   428     TInt tempHandle( 0 );
       
   429     
       
   430     TRAPD( outcome,
       
   431         iServer.CreateProviderL( 
       
   432             *this, providerUid, tempHandle, providerOptions ) );
       
   433     
       
   434     // KErrNone and positive codes are a success. Cache cleaning
       
   435     // can cause positive leaves
       
   436     if ( outcome >= KErrNone ) 
       
   437         {
       
   438         DLTRACE(("Writing the provider handle to the message"));
       
   439         TPckgBuf<TInt> handleBuf( tempHandle );
       
   440     
       
   441         TRAPD( err, aMessage.WriteL( 1, handleBuf ) );
       
   442         if ( err != KErrNone )
       
   443             {
       
   444             DLTRACE(("Couldn't pass the handle back"));
       
   445             // If we can't pass the handle back, there is no use
       
   446             // to try to continue normally.
       
   447             RemoveObject( tempHandle );
       
   448             outcome = err;
       
   449             }
       
   450         }
       
   451     DLTRACE(("Completing message with: %d", outcome ));    
       
   452     aMessage.Complete( outcome );    
       
   453     }
       
   454 
       
   455 
       
   456 void CCatalogsClientServerServerSession::CreateContextL(
       
   457     const RMessage2& aMessage )
       
   458     {
       
   459     DLTRACEIN((""));
       
   460     if ( iContext != NULL )
       
   461         {
       
   462         DLERROR(( "Completing message with KErrAlreadyExists" ));
       
   463         aMessage.Complete( KErrAlreadyExists );
       
   464         return;
       
   465         }
       
   466     
       
   467     TInt familyIdTint = aMessage.Int0();
       
   468     TUid familyIdUid = TUid::Uid( familyIdTint );    
       
   469     TSecureId secureId = aMessage.SecureId();
       
   470 
       
   471     iContext = CCatalogsContextImpl::NewL( familyIdUid, secureId, iInstanceId );
       
   472 
       
   473     // cancel shutdown operations for this family
       
   474     iServer.OperateShutdownOperations( Context(), EFalse );
       
   475     
       
   476     DLINFO(( "Completing message with KErrNone" ));
       
   477     aMessage.Complete( KErrNone );
       
   478     DLTRACEOUT((""));
       
   479     }
       
   480 
       
   481 void CCatalogsClientServerServerSession::PanicClient(
       
   482     const RMessage2& aMessage, TInt aPanic ) const
       
   483     {
       
   484     DLTRACEIN((""));
       
   485     // NOTICE: KTxtCatalogsSession should not exceed 16 characters.
       
   486     //         If it does, it will result in USER 23. So it seems
       
   487     //         that RMEssage2::Panic does not truncate the characters
       
   488     //         that exceed those 16 characters.
       
   489     _LIT( KTxtCatalogsSession,"CCatalogsSession" );
       
   490     aMessage.Panic( KTxtCatalogsSession, aPanic );
       
   491     }
       
   492 
       
   493 CCatalogsCommunicable* 
       
   494     CCatalogsClientServerServerSession::ReceiverFromHandle( TInt aHandle )
       
   495     {
       
   496     DLTRACEIN((""));
       
   497     if ( iMessageHandlers == NULL )
       
   498         {
       
   499         return NULL;
       
   500         }
       
   501     // Normal situation
       
   502     CCatalogsCommunicable* handler = 
       
   503         static_cast<CCatalogsCommunicable*>( iMessageHandlers->At( aHandle ) );
       
   504 	DLTRACEOUT((""));
       
   505     return handler;
       
   506     }
       
   507 
       
   508 CCatalogsIncompleteMessage* 
       
   509     CCatalogsClientServerServerSession::IncompleteMessageFromHandle( TInt aHandle )
       
   510     {
       
   511     DLTRACEIN((""));
       
   512     if ( iIncompleteMessages == NULL )
       
   513         {
       
   514         return NULL;
       
   515         }
       
   516     
       
   517     // Normal situation    
       
   518     CCatalogsIncompleteMessage* message =
       
   519         static_cast<CCatalogsIncompleteMessage*>( 
       
   520             iIncompleteMessages->At( aHandle ) ); 
       
   521     DLTRACEOUT((""));
       
   522     return message;   
       
   523     }
       
   524     
       
   525 void CCatalogsClientServerServerSession::CloseMessageHandlers()
       
   526     {
       
   527     DLTRACEIN((""));
       
   528     TInt communicableCount( iMessageHandlers->Count() );
       
   529     for ( TInt index = 0; index < communicableCount; ++index )
       
   530         {
       
   531         CCatalogsCommunicable* handler = 
       
   532             static_cast<CCatalogsCommunicable*>( ( *iMessageHandlers )[index] );
       
   533         // If handlers have been removed, iMessageHandlers seem to contain
       
   534         // null pointers in place of those removed handlers
       
   535         if ( handler != NULL )
       
   536             {
       
   537             handler->CounterPartLost( *this );
       
   538             }
       
   539         }
       
   540         
       
   541     // Deletion closes all referenced objects once
       
   542     delete iMessageHandlers;
       
   543     iMessageHandlers = NULL;
       
   544 
       
   545     DLTRACEOUT((""));
       
   546     }