--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-FAE3F35C-04C1-5CF4-8090-9DF58AD1C02A.dita Thu Jan 21 18:18:20 2010 +0000
@@ -0,0 +1,200 @@
+<?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& 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;
+ };
+</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& 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;
+ };</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& 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& 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;
+ }
+ }</codeblock> <codeblock id="GUID-F0C7D2A2-FC3E-5CC0-A776-7D7B7047D758" xml:space="preserve">CCountSubSession* CCountSession::CounterFromHandle(const RMessage2& aMessage,TInt aHandle)
+ {
+ CCountSubSession* counter = (CCountSubSession*)iCountersObjectIndex->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>
\ No newline at end of file