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.
In the example, a count server session is represented by the
CSession
derived class CCountServSession
. The server
session can have any number of subsessions, referred to as counters in the
example. The subsessions are instances of the CCounter
class and
these are derived from CObject
.
Unlike the implementation for a simple server interface, the
functions to service client requests, i.e. Increase()
, are in
class CCounter
rather than CCountServSession
.
The important points to note are:
the CCountServSession
class contains the object
container for all the subsession objects which belong to this session.
the CCountServServer
class contains the one
and only object container index through which all object containers
within the server are produced.
the CCountServSession
class contains an object index
through which a handle number can be generated for the subsesssion.
The CCountServSession
class is defined as:
class CCountServSession : public CSession
{
public:
static CCountServSession* NewL(RThread& aClient, CCountServServer* aServer);
CCountServSession(RThread& aClient);
void ConstructL(CCountServServer* aServer);
void CloseSession();
CCounter* CounterFromHandle(TUint aHandle);
void ServiceL(const RMessage& aMessage);
void DispatchMessageL(const RMessage& aMessage);
void NewCounterL();
void DeleteCounter(TUint aHandle);
void NumResources();
TInt CountResources();
void Write(const TAny* aPtr,const TDesC8& aDes,TInt anOffset=0);
void PanicClient(TInt aPanic) const;
private:
CObjectCon *iContainer;
CObjectIx* iCounters;
CCountServServer *iCountSvr;
TInt iResourceCount;
};
The data member iCounters
is a pointer to an
object index. Once a counter (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
counter (the subsession object) corresponding to a specified
handle number.
The NewCounterL()
function creates a new counter
(a subsession object).
The DeleteCounter()
function deletes a counter
(a subsession object). This is called when the client program
requests to close a subsession.
The function NewCounterL()
has the following
implementation:
void CCountServSession::NewCounterL()
{
CCounter* counter=CCounter::NewL(this);
iContainer->AddL(counter);
TInt handle=iCounters->AddL(counter);
TPckg<TInt> handlePckg(handle);
TRAPD(res,WriteL(Message().Ptr3(),handlePckg));
if (res!=KErrNone)
{
iCounters->Remove(handle);
PanicClient(EBadDescriptor);
return;
}
iResourceCount++;
}
iContainer->AddL(counter)
adds the new
counter to the object container.
iCounters->AddL(counter)
adds the new counter
to the object index which returns this subsession object's handle
number.
The handle number is written back to the client address space
using CSession::WriteL()
. The important point is that the
fourth parameter of the message argument is the location
within the client address space where the handle number is to be
written.
The CCounter
class which represents the subsession is
defined as:
class CCounter : public CObject
{
public:
static CCounter * NewL(CCountServSession* aSession);
void ConstructL(CCountServSession *aSession);
void SetFromString(const RMessage &aMessage);
void Increase();
void IncreaseBy();
void Decrease();
void DecreaseBy();
void Reset();
void CounterValue();
void CloseCounter();
const RMessage& Message() const;
protected:
CCountServSession *iSession;
private:
TInt iCount;
};
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 CloseCounter()
function deletes the subsession
object from the server session’s object index. This is
called when a client program requests the termination of a subsession. Deleting
the subsession object also has the effect of removing it from its
object container.
The message service functions
Increase()
, IncreaseBy()
etc. respond appropriately
to client requests.
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 CSession::ServiceL()
.
void CCountServSession::ServiceL(const RMessage& 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 CCountServSession::DispatchMessageL(const RMessage& aMessage)
{
switch (aMessage.Function())
{
case ECountServCreateSubSession:// Request to create a subsession
NewCounterL();
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.
CCounter* counter=CounterFromHandle(aMessage.Int3());
switch (aMessage.Function())
{
...
case ECountServValue:
counter->CounterValue();
return;
default:
PanicClient(EBadRequest);
return;
}
}
CCounter* CCountServSession::CounterFromHandle(TUint aHandle)
{
CCounter* counter = (CCounter*)iCounters->At(aHandle);
if (counter == NULL)
{
... // bad subsession handle
}
return counter;
}
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.