ncdengine/engine/src/catalogsclientserverclientsession.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 RCatalogsClientServerClientSession
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "catalogsclientserverclientsession.h"
       
    20 #include "catalogsclientserverserver.h"
       
    21 #include "catalogsserverdefines.h"
       
    22 #include "catalogsclientserverasynctask.h"
       
    23 #include "catalogsclientserverallocutils.h"
       
    24 #include "catalogsdebug.h"
       
    25 
       
    26 // Amount of attempts to create and connect to server before giving up
       
    27 const TInt KCatalogsServerStartAttempts( 5 );
       
    28 // Amount of sleep between retries
       
    29 const TInt KRetryInterval( 100000 ); // tenth of a second
       
    30 
       
    31 // Amount of time before we quit on waiting on the semaphore and go on
       
    32 const TInt KSemaphoreTimeout( 1000000 * 3 ); // 3 seconds
       
    33 
       
    34 // ======== LOCAL FUNCTIONS ========
       
    35 
       
    36 static TInt CreateServerProcess()
       
    37     {
       
    38     DLTRACEIN((""));    
       
    39     RProcess server;
       
    40 
       
    41     TInt result = server.Create( KCatalogsServerFilename, KNullDesC );
       
    42     if ( result != KErrNone )
       
    43         {
       
    44         DLERROR(( "Failed to create server process: err %d", result ));
       
    45         DLTRACEOUT(( "%d", result ));    
       
    46         return result;
       
    47         }
       
    48     
       
    49     // Resume server thread and close handle
       
    50     server.Resume();
       
    51     server.Close();  
       
    52 
       
    53     return KErrNone;
       
    54     }
       
    55 
       
    56 static TInt StartServer()
       
    57     {
       
    58     DLTRACEIN((""));
       
    59 
       
    60     // Check if the server is already running
       
    61     TFindServer findServer( KCatalogsServerName );
       
    62     TFullName name;
       
    63 
       
    64     TInt result = findServer.Next( name );
       
    65     if ( result == KErrNone )
       
    66         {
       
    67         // Server is running
       
    68         return KErrNone;
       
    69         }
       
    70 
       
    71     // Create a semaphore so we can wait while the server starts
       
    72     RSemaphore semaphore;
       
    73     result = semaphore.CreateGlobal( KCatalogsServerSemaphoreName, 0 );
       
    74     if ( result != KErrNone )
       
    75         {
       
    76         DLERROR(( "Failed to create semaphore: err %d", result ));
       
    77         DLTRACEOUT(( "%d", result ));    
       
    78         return result;
       
    79         }
       
    80 
       
    81     // Create new Engine service process 
       
    82     result = CreateServerProcess();            
       
    83     if ( result != KErrNone )
       
    84         {
       
    85         DLTRACEOUT(( "%d", result ));
       
    86         semaphore.Close();    
       
    87         return result;
       
    88         }
       
    89 
       
    90     // Wait while the server starts, if the timeout occurs, we can
       
    91     // assume the server didn't start correctly
       
    92     TInt err = semaphore.Wait( KSemaphoreTimeout );
       
    93 
       
    94     // Semaphore has been signaled, close and return
       
    95     semaphore.Close();
       
    96 
       
    97     DLTRACEOUT(("error: %d", err ));
       
    98     return err;
       
    99     }
       
   100     
       
   101 
       
   102 // ======== MEMBER FUNCTIONS ========
       
   103     
       
   104 
       
   105 RCatalogsClientServerClientSession::RCatalogsClientServerClientSession() :
       
   106     iSessionStatus( EClosed )
       
   107     {
       
   108     }
       
   109 
       
   110 // ---------------------------------------------------------------------------
       
   111 // This is function to create server process if it does not exist and to
       
   112 // to connect to the server. Notice that if the current server is going
       
   113 // down the StartServer() still does not create a new server. If this happens
       
   114 // then the CreateSession returns -15. If this happens we try the
       
   115 // server creation for a few times. We also have a sleep between tries
       
   116 // that halts this thread.
       
   117 // ---------------------------------------------------------------------------
       
   118 //
       
   119 TInt RCatalogsClientServerClientSession::Connect( TUid aClientUid )
       
   120     {
       
   121     DLTRACEIN((""));
       
   122     if ( iSessionStatus == EOpen )
       
   123         {
       
   124         return KErrNone;
       
   125         }
       
   126     
       
   127     TInt err( KErrNone );
       
   128     TInt startTryCounter( 0 );
       
   129     while( startTryCounter < KCatalogsServerStartAttempts )
       
   130         {
       
   131         DLINFO(( "Trying to start server, try nro: %d", startTryCounter + 1 ));
       
   132         err = KErrNone; // reset before a new try
       
   133         
       
   134         // StartServer() does not return error even if the current server is
       
   135         // shutting down.
       
   136         err = StartServer();
       
   137         DLINFO(( "startserver %d", err ));
       
   138         if ( KErrNone == err )
       
   139             {
       
   140             // If current server is dying, this returns error
       
   141             err = CreateSession(
       
   142                 KCatalogsServerName,
       
   143                 Version(),
       
   144                 KCatalogsDefaultMessageSlots );
       
   145             DLINFO(( "createsession %d", err ));
       
   146             if ( err == KErrNone )
       
   147                 {
       
   148                 iSessionStatus = EOpen;
       
   149                 
       
   150                 TIpcArgs args( aClientUid.iUid );
       
   151                 err = SendSync( ECatalogsCreateContext, args );
       
   152                 }
       
   153             }        
       
   154         
       
   155         if ( err == KErrNone )
       
   156             {
       
   157             break;
       
   158             }
       
   159             
       
   160         ++startTryCounter;        
       
   161         DLINFO(( "Did not succeed in connecting, entering sleep... " ));
       
   162         User::After( KRetryInterval ); // This halts the whole thread
       
   163         DLINFO(( "Retrying connect." ));
       
   164         }
       
   165 
       
   166     DLTRACEOUT(("err: %d", err));
       
   167     return err;
       
   168     }
       
   169     
       
   170 void RCatalogsClientServerClientSession::Disconnect()
       
   171     {
       
   172     DLTRACEIN((""));
       
   173     // Before cleaning up the iTasks, we ensure that if there
       
   174     // possibly still are pending tasks, server-side objects don't
       
   175     // complete them anymore. Also we assume that everything
       
   176     // possible is already done to ensure that there are no
       
   177     // tasks pending.
       
   178     if ( iSessionStatus == EOpen )
       
   179         {
       
   180         // Have to be sure so that we don't try to
       
   181         // send message using invalid handle
       
   182         TIpcArgs args = TIpcArgs();
       
   183         SendSync( ECatalogsClientSideDown, args );
       
   184         }
       
   185     
       
   186     // We trust that disconnect is always said, so contents of
       
   187     // iTasks is destroyed here
       
   188     iTasks.ResetAndDestroy();
       
   189 
       
   190 	RHandleBase::Close(); //close handle (this) to the server-side session
       
   191 	
       
   192 	iSessionStatus = EClosed;
       
   193 	DLTRACEOUT((""));
       
   194     }
       
   195 
       
   196 // ---------------------------------------------------------------------------
       
   197 // Creation of a provider uses a internal message type
       
   198 // to tell the server-side to create the desired provider.
       
   199 // ---------------------------------------------------------------------------
       
   200 //
       
   201 void RCatalogsClientServerClientSession::CreateProvider(
       
   202                                                     TInt aUid,
       
   203                                                     TRequestStatus& aStatus,
       
   204                                                     TInt& aHandle,
       
   205                                                     TUint32 aOptions )
       
   206     {
       
   207     DLTRACEIN((""));
       
   208 
       
   209     aStatus = KRequestPending;
       
   210 
       
   211     CCatalogsClientServerAsyncTask* task = NULL;
       
   212     TRAPD( error, GetAsyncTaskL( task ) );
       
   213     if ( error != KErrNone )
       
   214         {
       
   215         // This is called before setActive in client?
       
   216         // Is that a problem?
       
   217         DLTRACEOUT(("error=%X",error));
       
   218         TRequestStatus* status = &aStatus;
       
   219         User::RequestComplete( status, error );
       
   220         return;
       
   221         }
       
   222 
       
   223     DLTRACE(("CreateProvider using task"));
       
   224     task->CreateProvider( aUid, aStatus, aHandle, aOptions );
       
   225 
       
   226     DLTRACEOUT(("RCatalogsClientServerClientSession end"));
       
   227     }
       
   228 
       
   229 // ---------------------------------------------------------------------------
       
   230 // Replace all asynchronous SendReceives in this class with this 
       
   231 // SendAsync so we get all asynchronous sending into one function
       
   232 // ---------------------------------------------------------------------------
       
   233 //
       
   234 void RCatalogsClientServerClientSession::SendAsync( 
       
   235     TCatalogsServerFunction aMessageType,
       
   236     const TIpcArgs& aArgs,
       
   237     TRequestStatus& aStatus )
       
   238     {
       
   239     aStatus = KRequestPending;
       
   240     SendReceive( aMessageType, aArgs, aStatus );
       
   241     }
       
   242 
       
   243 // ---------------------------------------------------------------------------
       
   244 // Replace all synchronous SendReceives in this class with this
       
   245 // SendSync so we get all synchronous sending into one function
       
   246 // ---------------------------------------------------------------------------
       
   247 //
       
   248 TInt RCatalogsClientServerClientSession::SendSync( 
       
   249     TCatalogsServerFunction aMessageType,
       
   250     const TIpcArgs& aArgs )
       
   251     {
       
   252     return SendReceive( aMessageType, aArgs );
       
   253     }
       
   254 
       
   255 void RCatalogsClientServerClientSession::TaskCompleted(
       
   256     CCatalogsClientServerAsyncTask* aCompletedTask )
       
   257     {
       
   258     DLTRACEIN((""));
       
   259     TInt index( iTasks.Find( aCompletedTask ) );
       
   260     iTasks.Remove( index );
       
   261     delete aCompletedTask;
       
   262 #ifdef CATALOGS_BUILD_CONFIG_DEBUG    
       
   263 /*
       
   264     RThread currentThread;
       
   265     
       
   266     TInt semCount = currentThread.RequestCount();
       
   267     DLTRACE(("semCount: %d", semCount ));
       
   268     currentThread.Close();
       
   269 */    
       
   270 #endif    
       
   271     
       
   272     DLTRACEOUT((""));
       
   273     }
       
   274 
       
   275 TInt RCatalogsClientServerClientSession::DeleteIncompleteMessage( 
       
   276     TInt aHandle )
       
   277     {
       
   278     DLTRACEIN((""));
       
   279     TPckgBuf<TInt> handle( aHandle );
       
   280     TIpcArgs args = TIpcArgs();
       
   281     args.Set( 1, &handle );
       
   282     return SendReceive( ECatalogsRemoveIncompleteMessage,
       
   283                         args );    
       
   284     }
       
   285     
       
   286 
       
   287 TVersion RCatalogsClientServerClientSession::Version() const
       
   288     {
       
   289     return TVersion( KCatalogsServerMajorVersionNumber, 
       
   290                      KCatalogsServerMinorVersionNumber, 
       
   291                      KCatalogsServerBuildVersionNumber );
       
   292     }
       
   293     
       
   294     
       
   295 TInt RCatalogsClientServerClientSession::SendSync( TInt aFunction,
       
   296                                                    const TDesC8& aInput,
       
   297                                                    TDes8& aOutput,
       
   298                                                    TInt aHandle )
       
   299     {
       
   300     DLTRACEIN(("Handle: %d", aHandle));
       
   301     // Actually these would not need to be in TPckgBuf
       
   302     // when they are not used for returning purposes.
       
   303     TPckgBuf<TInt> function( aFunction );
       
   304     TPckgBuf<TInt> handle( aHandle );
       
   305  
       
   306     return SendReceive( ECatalogsExternalMessage,
       
   307                         TIpcArgs( &function,
       
   308                                   &handle,
       
   309                                   &aInput,
       
   310                                   &aOutput ));
       
   311     }
       
   312 
       
   313 
       
   314 TInt RCatalogsClientServerClientSession::SendSync( TInt aFunction,
       
   315                                                    const TDesC16& aInput,
       
   316                                                    TDes16& aOutput,
       
   317                                                    TInt aHandle )
       
   318     {
       
   319     DLTRACEIN(("Handle: %d", aHandle));
       
   320     // Actually these would not need to be in TPckgBuf
       
   321     // when they are not used for returning purposes.
       
   322     TPckgBuf<TInt> function( aFunction );
       
   323     TPckgBuf<TInt> handle( aHandle );
       
   324  
       
   325     return SendReceive( ECatalogsExternalMessage,
       
   326                          TIpcArgs( &function,
       
   327                                    &handle,
       
   328                                    &aInput,
       
   329                                    &aOutput ));
       
   330     }
       
   331 
       
   332 
       
   333 TInt RCatalogsClientServerClientSession::SendSync( TInt aFunction,
       
   334                                                    const TDesC16& aInput,
       
   335                                                    TInt& aOutputInt,
       
   336                                                    TInt aHandle )
       
   337     {
       
   338     DLTRACEIN(("Handle: %d", aHandle));
       
   339 
       
   340     // Actually these would not need to be in TPckgBuf
       
   341     // when they are not used for returning purposes.
       
   342     TPckgBuf<TInt> function( aFunction );
       
   343     TPckgBuf<TInt> handle( aHandle );
       
   344 
       
   345     TPckgBuf<TInt> integerReturnBuf;
       
   346 
       
   347     DLTRACE(("Sending message to server"));
       
   348     
       
   349     TInt returnValue = SendReceive( ECatalogsExternalMessage,
       
   350                                     TIpcArgs( &function,
       
   351                                               &handle,
       
   352                                               &aInput,
       
   353                                               &integerReturnBuf ));
       
   354     
       
   355     DLTRACE(("Done, err: %i, handle: %d", returnValue, aHandle ));
       
   356     
       
   357     aOutputInt = integerReturnBuf();
       
   358     return returnValue;
       
   359     }
       
   360 
       
   361 TInt RCatalogsClientServerClientSession::SendSync( TInt aFunction,
       
   362                                                    const TDesC8& aInput,
       
   363                                                    TInt& aOutputInt,
       
   364                                                    TInt aHandle )
       
   365     {
       
   366     DLTRACEIN(("Handle: %d", aHandle));
       
   367 
       
   368     // Actually these would not need to be in TPckgBuf
       
   369     // when they are not used for returning purposes.
       
   370     TPckgBuf<TInt> function( aFunction );
       
   371     TPckgBuf<TInt> handle( aHandle );
       
   372 
       
   373     TPckgBuf<TInt> integerReturnBuf;
       
   374 
       
   375     DLTRACE(("Sending message to server"));
       
   376     
       
   377     TInt returnValue = SendReceive( ECatalogsExternalMessage,
       
   378                                     TIpcArgs( &function,
       
   379                                               &handle,
       
   380                                               &aInput,
       
   381                                               &integerReturnBuf ));
       
   382     
       
   383     DLTRACE(("Done, err: %i, handle: %d", returnValue, aHandle ));
       
   384     
       
   385     aOutputInt = integerReturnBuf();
       
   386     return returnValue;
       
   387     }
       
   388 
       
   389 
       
   390 // ---------------------------------------------------------------------------
       
   391 // When noticed the need for 16-bit versions of functions, thought that
       
   392 // because asynchronous functions would not work by converting the call
       
   393 // from 16-bit to 8-bit in an inline function, we put all the functions into
       
   394 // the interface and add implementations here. Also thought that
       
   395 // as we have functions to put the 16-bit descriptor through the
       
   396 // client-server we use them instead of pushing the 16-bit descriptors in
       
   397 // 8-bit descriptors to the other side.
       
   398 // Now we can see that this last decision makes up some repitition when
       
   399 // it comes to synchronous alloc-functions.
       
   400 //
       
   401 // Note: If good ideas come up, replace variants of alloc functions that
       
   402 //       do same things only to different kind of descriptors
       
   403 //       (8- and 16-bit variants) with possibly only one implementation.
       
   404 // ---------------------------------------------------------------------------
       
   405 //
       
   406 TInt RCatalogsClientServerClientSession::SendSyncAlloc( TInt aFunction,
       
   407                                                         const TDesC8& aInput,
       
   408                                                         HBufC8*& aOutput,
       
   409                                                         TInt aHandle,
       
   410                                                         TInt aLength )
       
   411     {
       
   412     DLTRACEIN(("Handle: %d", aHandle));
       
   413     
       
   414     // Although aOutput should be null, it is deleted to be sure that
       
   415     // no memory is leaked
       
   416     delete aOutput;
       
   417     aOutput = NULL;
       
   418     
       
   419     HBufC8* tempReturnBuf( NULL );
       
   420     TInt returnValue = AllocReturnBuf( aLength, tempReturnBuf );
       
   421     if ( returnValue != KErrNone )
       
   422         {
       
   423         return returnValue;        
       
   424         }
       
   425         
       
   426     TPtr8 tempWritableReturnBuf( NULL, 0 );
       
   427     tempWritableReturnBuf.Set( tempReturnBuf->Des() );
       
   428 
       
   429     // Actually these would not need to be in TPckgBuf
       
   430     // when they are not used for returning purposes.
       
   431     TPckgBuf<TInt> function( aFunction );
       
   432     TPckgBuf<TInt> handle( aHandle );
       
   433  
       
   434     TInt outcome = SendReceive( ECatalogsExternalAllocMessage,
       
   435                                 TIpcArgs( &function,
       
   436                                           &handle,
       
   437                                           &aInput,
       
   438                                           &tempWritableReturnBuf ));
       
   439 
       
   440     if ( outcome == KCatalogsErrorTooSmallDescriptor )
       
   441         {
       
   442         TInt incompleteMessageHandle = -1;
       
   443         TInt error = RetrieveNewDescLengthAndReAlloc(
       
   444                          tempReturnBuf,
       
   445                          incompleteMessageHandle );
       
   446         if ( error != KErrNone )
       
   447             {
       
   448             if ( incompleteMessageHandle != -1 )
       
   449                 {
       
   450                 DeleteIncompleteMessage( incompleteMessageHandle );
       
   451                 }            
       
   452             aOutput = NULL;
       
   453             delete tempReturnBuf;
       
   454             return error;
       
   455             }
       
   456                 
       
   457         // to be sure
       
   458         tempWritableReturnBuf.Set( tempReturnBuf->Des() );
       
   459 
       
   460         TPckgBuf<TInt> handle( incompleteMessageHandle );
       
   461         TIpcArgs args = TIpcArgs();
       
   462         args.Set( 1, &handle );
       
   463         args.Set( 3, &tempWritableReturnBuf );
       
   464         outcome = SendReceive( ECatalogsCompleteMessage,
       
   465                                args );
       
   466              
       
   467         }
       
   468         
       
   469         
       
   470     if ( outcome == KCatalogsErrorTooSmallDescriptor || outcome < 0 )
       
   471         {
       
   472         aOutput = NULL;
       
   473         delete tempReturnBuf;
       
   474         }
       
   475     else
       
   476         {
       
   477         aOutput = tempReturnBuf;
       
   478         }
       
   479     DLTRACEOUT(("outcome: %d, handle: %d", outcome, aHandle));
       
   480     return outcome;
       
   481     }
       
   482 
       
   483 TInt RCatalogsClientServerClientSession::SendSyncAlloc( TInt aFunction,
       
   484                                                         const TDesC16& aInput,
       
   485                                                         HBufC16*& aOutput,
       
   486                                                         TInt aHandle,
       
   487                                                         TInt aLength )
       
   488     {
       
   489     DLTRACEIN(("Handle: %d", aHandle));
       
   490 
       
   491     // Although aOutput should be null, it is deleted to be sure that
       
   492     // no memory is leaked
       
   493     delete aOutput;
       
   494     aOutput = NULL;
       
   495 
       
   496     HBufC16* tempReturnBuf( NULL );
       
   497     TInt returnValue = AllocReturnBuf( aLength, tempReturnBuf );
       
   498     if ( returnValue != KErrNone )
       
   499         {
       
   500         return returnValue;        
       
   501         }
       
   502         
       
   503     TPtr16 tempWritableReturnBuf( NULL, 0 );
       
   504     tempWritableReturnBuf.Set( tempReturnBuf->Des() );
       
   505 
       
   506     // Actually these would not need to be in TPckgBuf
       
   507     // when they are not used for returning purposes.
       
   508     TPckgBuf<TInt> function( aFunction );
       
   509     TPckgBuf<TInt> handle( aHandle );
       
   510  
       
   511     TInt outcome = SendReceive( ECatalogsExternalAllocMessage,
       
   512                                 TIpcArgs( &function,
       
   513                                           &handle,
       
   514                                           &aInput,
       
   515                                           &tempWritableReturnBuf ));
       
   516 
       
   517     if ( outcome == KCatalogsErrorTooSmallDescriptor )
       
   518         {
       
   519         TInt incompleteMessageHandle = -1;
       
   520         TInt error = RetrieveNewDescLengthAndReAlloc(
       
   521                          tempReturnBuf,
       
   522                          incompleteMessageHandle );
       
   523         if ( error != KErrNone )
       
   524             {
       
   525             if ( incompleteMessageHandle != -1 )
       
   526                 {
       
   527                 DeleteIncompleteMessage( incompleteMessageHandle );
       
   528                 }            
       
   529             aOutput = NULL;
       
   530             delete tempReturnBuf;
       
   531             return error;
       
   532             }
       
   533                 
       
   534         // to be sure
       
   535         tempWritableReturnBuf.Set( tempReturnBuf->Des() );
       
   536 
       
   537         TPckgBuf<TInt> handle( incompleteMessageHandle );
       
   538         TIpcArgs args = TIpcArgs();
       
   539         args.Set( 1, &handle );
       
   540         args.Set( 3, &tempWritableReturnBuf );
       
   541         outcome = SendReceive( ECatalogsCompleteMessageWide,
       
   542                                args );
       
   543              
       
   544         }
       
   545         
       
   546         
       
   547     if ( outcome == KCatalogsErrorTooSmallDescriptor || outcome < 0 )
       
   548         {
       
   549         aOutput = NULL;
       
   550         delete tempReturnBuf;
       
   551         }
       
   552     else
       
   553         {
       
   554         aOutput = tempReturnBuf;
       
   555         }
       
   556 
       
   557     DLTRACEOUT(("outcome: %d, handle: %d", outcome, aHandle));
       
   558     return outcome;
       
   559     }
       
   560     
       
   561     
       
   562     
       
   563 RFile RCatalogsClientServerClientSession::SendSyncFileOpenL( 
       
   564     TInt aFunction,
       
   565     const TDesC8& aInput, 
       
   566     TInt aHandle )
       
   567     {
       
   568     DLTRACEIN(("Handle: %d", aHandle));
       
   569 
       
   570     // Actually these would not need to be in TPckgBuf
       
   571     // when they are not used for returning purposes.
       
   572     TPckgBuf<TInt> function( aFunction );
       
   573     TPckgBuf<TInt> handle( aHandle );
       
   574 
       
   575     TPckgBuf<TInt> fileHandleBuf;
       
   576 
       
   577     DLTRACE(("Sending message to server"));
       
   578     
       
   579     TInt fsHandle = SendReceive( ECatalogsExternalMessage,
       
   580                                     TIpcArgs( &function,
       
   581                                               &handle,
       
   582                                               &aInput,
       
   583                                               &fileHandleBuf ));
       
   584     
       
   585     TInt fileHandle = fileHandleBuf();
       
   586     DLTRACE(("AdoptFromServer( %d, %d )", fsHandle, fileHandle ));
       
   587     RFile file;
       
   588     User::LeaveIfError( file.AdoptFromServer( fsHandle, fileHandle ) );
       
   589     
       
   590     DLTRACE(("Done, handle: %d", aHandle ));
       
   591     
       
   592     
       
   593     return file;    
       
   594     }
       
   595     
       
   596     
       
   597     
       
   598 void RCatalogsClientServerClientSession::SendAsync( TInt aFunction,
       
   599                                                     const TDesC8& aInput,
       
   600                                                     TDes8& aOutput,
       
   601                                                     TInt aHandle,
       
   602                                                     TRequestStatus& aStatus )
       
   603     {
       
   604     DLTRACEIN(("Handle: %d", aHandle));
       
   605     aStatus = KRequestPending;
       
   606 
       
   607     CCatalogsClientServerAsyncTask* task = NULL;
       
   608     TRAPD( error, GetAsyncTaskL( task ) );
       
   609     if ( error != KErrNone )
       
   610         {
       
   611         DLERROR(( "Error getting an async task: %d", error ));
       
   612         // This is called before setActive in client?
       
   613         // Is that a problem?
       
   614         TRequestStatus* status = &aStatus;
       
   615         User::RequestComplete( status, error );
       
   616         return;
       
   617         }
       
   618 
       
   619     task->SendAsync( aFunction, aInput, aOutput, aHandle, aStatus );
       
   620     }
       
   621     
       
   622     
       
   623 void RCatalogsClientServerClientSession::SendAsyncAlloc( 
       
   624                                                     TInt aFunction,
       
   625                                                     const TDesC8& aInput,
       
   626                                                     HBufC8*& aOutput,
       
   627                                                     TInt aHandle,
       
   628                                                     TRequestStatus& aStatus,
       
   629                                                     TInt aLength )
       
   630     {
       
   631     DLTRACEIN(("Handle: %d", aHandle));
       
   632 
       
   633     // Although aOutput should be null, it is deleted to be sure that
       
   634     // no memory is leaked
       
   635     delete aOutput;
       
   636     aOutput = NULL;
       
   637 
       
   638     aStatus = KRequestPending;
       
   639     
       
   640     CCatalogsClientServerAsyncTask* task = NULL;
       
   641     TRAPD( error, GetAsyncTaskL( task ) );
       
   642     if ( error != KErrNone )
       
   643         {
       
   644         // This is called before setActive in client?
       
   645         // Is that a problem?
       
   646         DLERROR(("Error %d occurred when retrieving new async task", error ));
       
   647         TRequestStatus* status = &aStatus;
       
   648         User::RequestComplete( status, error );        
       
   649         return;
       
   650         }
       
   651 
       
   652     task->SendAsyncAlloc( aFunction,
       
   653                           aInput,
       
   654                           aOutput, 
       
   655                           aHandle,
       
   656                           aStatus,
       
   657                           aLength );
       
   658     DLTRACEOUT((""));
       
   659     }
       
   660 
       
   661 void RCatalogsClientServerClientSession::AsyncMessageSenderDown(
       
   662     TRequestStatus& aStatus )
       
   663     {
       
   664     // Go through all messages
       
   665     TInt indexer( iTasks.Count() - 1 );
       
   666     while ( indexer > -1 )
       
   667         {
       
   668         // If the message sender's TRequestStatus is the same as the
       
   669         // given TRequestStatus, the async task should complete
       
   670         // the request immediately and continue to wait for the completion
       
   671         // of the server side message. Comparation done by comparing
       
   672         // pointers to the request statuses.
       
   673         if ( &aStatus == iTasks[indexer]->SendersRequestStatus() )
       
   674             {
       
   675             iTasks[indexer]->SenderDown();
       
   676             }
       
   677         --indexer;
       
   678         }
       
   679     // If no tasks were found with given sender and there has
       
   680     // actually been task(s) that should complete request it is possible
       
   681     // that the request has been recently completed but the completion
       
   682     // has not yet been handled by active scheduler (?) and passed to
       
   683     // the sender.
       
   684     }
       
   685     
       
   686 void RCatalogsClientServerClientSession::GetAsyncTaskL( 
       
   687     CCatalogsClientServerAsyncTask*& aTask )
       
   688     {
       
   689     CCatalogsClientServerAsyncTask* requestedTask = 
       
   690         CCatalogsClientServerAsyncTask::NewLC( *this );
       
   691     
       
   692     iTasks.AppendL( requestedTask );
       
   693     CleanupStack::Pop( requestedTask );
       
   694     
       
   695     aTask = requestedTask;
       
   696     }