Symbian3/SDK/Source/GUID-FAE3F35C-04C1-5CF4-8090-9DF58AD1C02A.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 15:24:34 +0100
changeset 9 59758314f811
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 23 contribution of PDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"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: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-FAE3F35C-04C1-5CF4-8090-9DF58AD1C02A" xml:lang="en"><title>How
to implement a server interface with subsessions</title><shortdesc>Provides code snippets to help you to implement a server interface
with subsessions.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>A server side subsession is represented by an instance of a class derived
from <codeph>CObject</codeph>. </p>
<p>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 <filepath>...\examples\Base\IPC\ClientServer\complex</filepath>. </p>
<p>In the example, a server side session is represented by the <codeph>CSession2</codeph> derived
class <codeph>CCountSession</codeph>. The server session can have any number
of subsessions, referred to as counters in the example. The subsessions are
instances of the <codeph>CCountSubSession</codeph> class and these are derived
from <codeph>CObject</codeph>. </p>
<p>Unlike the implementation for a simple server interface, as shown in the
example that can be found at <filepath>...\examples\Base\IPC\ClientServer\simple</filepath>,
the functions to service client requests, e.g. <codeph>Increase()</codeph>,
are in class <codeph>CCountSubSession</codeph> rather than <codeph>CCountSession</codeph>. </p>
<p>The important points to note are: </p>
<ul>
<li id="GUID-98D487B0-ECFF-5A83-BEF0-C66475836888"><p>the <codeph>CCountSession</codeph> class
contains the object container for all the subsession objects which belong
to this session. </p> </li>
<li id="GUID-BCE1BF57-FC9E-58CF-9E77-1AD48632DFC0"><p>the <codeph>CCountServer</codeph> class
contains the <i>one and only</i> object container index through which all
object containers within the server are produced. </p> </li>
<li id="GUID-78880ABD-904A-5D3C-988A-646CE2998050"><p>the <codeph>CCountSession</codeph> class
contains an object index through which a handle number can be generated for
the subsession. </p> </li>
</ul>
<section id="GUID-D49A6975-81B7-4BEE-8F46-C0F850CB4974"><title>Server session representation</title> <p>The <codeph>CCountSession</codeph> class
is defined as: </p> <codeblock id="GUID-F8FED60B-823A-5965-97F2-0BF6EC24620D" xml:space="preserve">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&amp; aMessage);
    void DispatchMessageL(const RMessage2&amp; aMessage);

      // Creates new subsession
    void NewCounterL(const RMessage2&amp; aMessage);  
      
      // Closes the session
    void CloseSession();
    
      // Gets the number of resources (i.e. CCountSubSession objects)
    void NumResources(const RMessage2&amp; aMessage);
    
      // Utility to return the CCountSubSession (subsession) object
    CCountSubSession* CounterFromHandle(const RMessage2&amp; 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&amp; 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;
    };
</codeblock> <p><b>Notes</b> </p> <ul>
<li id="GUID-DD9D1AE3-315E-5ADF-A251-5F9BAAF24EED"><p>The data member <codeph>iCountersObjectIndex</codeph> is
a pointer to an <i>object index</i>. Once a subsession object has been created
and stored in its <i>object container</i>, it is then added to the <i>object
index</i> to generate a unique handle number for the counter (<keyword>subsession
object</keyword>). </p> </li>
<li id="GUID-0AE88EE6-1E87-5699-92FF-F55225320DF8"><p>The <codeph>CCounterFromHandle()</codeph> function
returns the subsession object corresponding to a specified handle number. </p> </li>
<li id="GUID-64A79B53-B798-50DA-B4F5-0DA5881F964E"><p>The <codeph>NewCounterL()</codeph> function
creates a new subsession object. </p> </li>
<li id="GUID-C9C9619D-EE0D-5B3F-B51C-354C9D7066D1"><p>The <codeph>DeleteCounter()</codeph> function
deletes a subsession object. This is called when the client program requests
to close a subsession. </p> </li>
</ul> </section>
<section id="GUID-CB7E6555-DE45-426A-B816-3736E72904FE"><title>Subsession object representation</title> <p>The <codeph>CCountSubSession</codeph> class
which represents the subsession is defined as: </p> <codeblock id="GUID-A91DD957-4A51-58E1-B0A0-843DAF9FF483" xml:space="preserve">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&amp; aMessage);
    void Increase();
    void IncreaseBy(const RMessage2&amp; aMessage);
    void Decrease();
    void DecreaseBy(const RMessage2&amp; aMessage);
    void Reset();
    void CounterValue(const RMessage2&amp; aMessage);
   
protected:
      // The session that owns this CCountSubSession object.
    CCountSession* iSession;
    
private:
      // The counter value
    TInt iCount;
    };</codeblock> <p><b>Notes</b> </p> <ul>
<li id="GUID-04B1ACC9-AA68-56C7-B42A-DC7DAA0749B0"><p>The <codeph>NewL()</codeph> function
creates and returns a new instance of the subsession object. This is called
when the client requests the creation of a new subsession. </p> </li>
<li id="GUID-8BF98800-E081-5120-914F-60AE09C1A70A"><p>The <i>message service
functions</i> <codeph>Increase()</codeph>, <codeph>IncreaseBy()</codeph> etc.
respond appropriately to client requests. </p> </li>
</ul> </section>
<section id="GUID-1031D378-90C7-42A4-B1E5-C8BA10145B86"><title>Implementing a subsession request</title> <p>Subsession requests
are handled in a similar way to session requests. </p> <p>A subsession request
is initially handled by the associated session, i.e. it is passed to the appropriate <codeph>CSession2::ServiceL()</codeph>. </p> <codeblock id="GUID-AE6EDE6F-54B2-56DC-A793-A6AE630A223A" xml:space="preserve">void CCountSession::ServiceL(const RMessage2&amp; aMessage)
    {
    TRAPD(err,DispatchMessageL(aMessage));
    aMessage.Complete(err);
    }
</codeblock> <p>The appropriate service function is called via <codeph>DispatchMessageL()</codeph> and
the asynchronous request is completed with <codeph>aMessage.Complete()</codeph>.
This applies to messages targeted at sessions and subsessions. </p> <p><b>DispatchMessageL()</b> </p> <p>The following code fragment shows important parts of this function: </p> <codeblock id="GUID-EB719B38-AA2C-5C19-B7BE-2332BD853057" xml:space="preserve">void CCountSession::DispatchMessageL(const RMessage2&amp; 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-&gt;CounterValue(aMessage);
        return;
    default:
        PanicClient(EBadRequest);
        return;
        }
    }</codeblock> <codeblock id="GUID-F0C7D2A2-FC3E-5CC0-A776-7D7B7047D758" xml:space="preserve">CCountSubSession* CCountSession::CounterFromHandle(const RMessage2&amp; aMessage,TInt aHandle)
    {
    CCountSubSession* counter = (CCountSubSession*)iCountersObjectIndex-&gt;At(aHandle);
    if (counter == NULL)
        {
        PanicClient(aMessage, EBadSubsessionHandle); 
        }
    return counter;
    }
</codeblock> <p><b>Notes</b> </p> <ul>
<li id="GUID-55B94E1E-C761-5D39-9EBF-9A2E600E26A3"><p>The function first checks
for messages which are specific to a session and this includes those requests
to create and delete a subsession. </p> </li>
<li id="GUID-D65039AA-E45E-5CA6-8A25-E8F3680CDA72"><p>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 <codeph>CounterFromHandle()</codeph> function
to retrieve the appropriate subsession object. </p> </li>
<li id="GUID-54BC7669-BBA9-5134-857A-8F4060059EB7"><p>It then invokes the
appropriate message service function on that subsession to deal with the client
request. </p> </li>
<li id="GUID-7CA3D0C0-E7DB-58FC-A89D-2584C25A7685"><p>The <codeph>At()</codeph> function
is provided by the <codeph>CObject</codeph> base class. </p> </li>
</ul> </section>
</conbody></concept>