How to implement a server interface with subsessions

Provides code snippets to help you to implement a server interface with subsessions.

A server side subsession is represented by an instance of a class derived from CObject .

The following sections refer to an example server, known as the count server. The code fragments are taken from the example that can be found at ...\examples\Base\IPC\ClientServer\complex .

In the example, a server side session is represented by the CSession2 derived class CCountSession . The server session can have any number of subsessions, referred to as counters in the example. The subsessions are instances of the CCountSubSession class and these are derived from CObject .

Unlike the implementation for a simple server interface, as shown in the example that can be found at ...\examples\Base\IPC\ClientServer\simple , the functions to service client requests, e.g. Increase() , are in class CCountSubSession rather than CCountSession .

The important points to note are:

  • the CCountSession class contains the object container for all the subsession objects which belong to this session.

  • the CCountServer class contains the one and only object container index through which all object containers within the server are produced.

  • the CCountSession class contains an object index through which a handle number can be generated for the subsession.

Server session representation

The CCountSession class is defined as:

       
        
       
       class CCountSession : public CSession2
    {
public:
      // Create the session
    static CCountSession* NewL();
    
public:
      // Constructor
    CCountSession();
    
      // Called by client/server framework after 
      // session has been successfully created
    void CreateL(); 
        
      // Service request
    void ServiceL(const RMessage2& aMessage);
    void DispatchMessageL(const RMessage2& aMessage);

      // Creates new subsession
    void NewCounterL(const RMessage2& aMessage);  
      
      // Closes the session
    void CloseSession();
    
      // Gets the number of resources (i.e. CCountSubSession objects)
    void NumResources(const RMessage2& aMessage);
    
      // Utility to return the CCountSubSession (subsession) object
    CCountSubSession* CounterFromHandle(const RMessage2& aMessage,TInt aHandle);    

      // Delete the subsession object through its handle.
    void DeleteCounter(TInt aHandle);
      
      // Gets the number of server-side subsession objects.
    TInt CountResources();
      
      // Panics client
    void PanicClient(const RMessage2& aMessage,TInt aPanic) const;

private:
      // Object container for this session.
    CObjectCon *iContainer;

      // Object index which stores objects
      // (CCountSubSession instances) for this session.
    CObjectIx* iCountersObjectIndex;

      // Total number of resources. In this example
      // a resource is just the number of CCountSubSession objects.
    TInt iResourceCount;
    };
      

Notes

  • The data member iCountersObjectIndex is a pointer to an object index . Once a subsession object has been created and stored in its object container , it is then added to the object index to generate a unique handle number for the counter ( subsession object ).

  • The CCounterFromHandle() function returns the subsession object corresponding to a specified handle number.

  • The NewCounterL() function creates a new subsession object.

  • The DeleteCounter() function deletes a subsession object. This is called when the client program requests to close a subsession.

Subsession object representation

The CCountSubSession class which represents the subsession is defined as:

       
        
       
       class CCountSubSession : public CObject
    {
public:
      // creates a new CCountSubSession object.
    static CCountSubSession* NewL(CCountSession* aSession);
    
public: 
    CCountSubSession(CCountSession* aSession);    
    void ConstructL(CCountSession* aSession);
    void SetFromStringL(const RMessage2& aMessage);
    void Increase();
    void IncreaseBy(const RMessage2& aMessage);
    void Decrease();
    void DecreaseBy(const RMessage2& aMessage);
    void Reset();
    void CounterValue(const RMessage2& aMessage);
   
protected:
      // The session that owns this CCountSubSession object.
    CCountSession* iSession;
    
private:
      // The counter value
    TInt iCount;
    };
      

Notes

  • The NewL() function creates and returns a new instance of the subsession object. This is called when the client requests the creation of a new subsession.

  • The message service functions Increase() , IncreaseBy() etc. respond appropriately to client requests.

Implementing a subsession request

Subsession requests are handled in a similar way to session requests.

A subsession request is initially handled by the associated session, i.e. it is passed to the appropriate CSession2::ServiceL() .

       
        
       
       void CCountSession::ServiceL(const RMessage2& aMessage)
    {
    TRAPD(err,DispatchMessageL(aMessage));
    aMessage.Complete(err);
    }
      

The appropriate service function is called via DispatchMessageL() and the asynchronous request is completed with aMessage.Complete() . This applies to messages targeted at sessions and subsessions.

DispatchMessageL()

The following code fragment shows important parts of this function:

       
        
       
       void CCountSession::DispatchMessageL(const RMessage2& aMessage)
    {
        // First check for session-relative requests
    switch (aMessage.Function())
        {
    case ECountServCreateSubSession:// Request to create a subsession
        NewCounterL(aMessage);
        return;
    case ECountServCloseSession:    // Request to delete a subsession
        CloseSession();
        return;
        ...
        }
    ...
 
                             // Must be a subsession request
                             // Find out Which subsession and
                             // forward the request to it.
    CCountSubSession* counter=CounterFromHandle(aMessage,aMessage.Int3())
    switch (aMessage.Function())
        {
        ...
    case ECountServValue:
        counter->CounterValue(aMessage);
        return;
    default:
        PanicClient(EBadRequest);
        return;
        }
    }
      
       
        
       
       CCountSubSession* CCountSession::CounterFromHandle(const RMessage2& aMessage,TInt aHandle)
    {
    CCountSubSession* counter = (CCountSubSession*)iCountersObjectIndex->At(aHandle);
    if (counter == NULL)
        {
        PanicClient(aMessage, EBadSubsessionHandle); 
        }
    return counter;
    }
      

Notes

  • The function first checks for messages which are specific to a session and this includes those requests to create and delete a subsession.

  • After deciding that messages must be forwarded to a subsession, the function uses the handle number supplied through the fourth parameter in the message argument array and the CounterFromHandle() function to retrieve the appropriate subsession object.

  • It then invokes the appropriate message service function on that subsession to deal with the client request.

  • The At() function is provided by the CObject base class.