os/kernelhwsrv/kernel/eka/euser/cbase/ub_svr.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\euser\cbase\ub_svr.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "ub_std.h"
sl@0
    19
//#define __DEBUG_IMAGE__ 1
sl@0
    20
#if defined(__DEBUG_IMAGE__) && defined (__EPOC32__)
sl@0
    21
#include "e32svr.h" 
sl@0
    22
#define __IF_DEBUG(t) {RDebug debug;debug.t;}
sl@0
    23
#else
sl@0
    24
#define __IF_DEBUG(t)
sl@0
    25
#endif
sl@0
    26
sl@0
    27
sl@0
    28
sl@0
    29
_LIT(KSessionPanicCategory,"CSession");
sl@0
    30
_LIT(KServerPanicCategory,"CServer");
sl@0
    31
sl@0
    32
sl@0
    33
sl@0
    34
/**
sl@0
    35
Default constructor.
sl@0
    36
sl@0
    37
This constructor is empty.
sl@0
    38
*/
sl@0
    39
EXPORT_C CSession2::CSession2()
sl@0
    40
	{}
sl@0
    41
sl@0
    42
sl@0
    43
sl@0
    44
/**
sl@0
    45
Destructor.
sl@0
    46
sl@0
    47
It frees resources prior to destruction of the object.
sl@0
    48
Specifically, it removes this session object from the server
sl@0
    49
active object’s list of sessions.
sl@0
    50
*/
sl@0
    51
EXPORT_C CSession2::~CSession2()
sl@0
    52
	{
sl@0
    53
	if (iLink.iNext)
sl@0
    54
		iLink.Deque();
sl@0
    55
	}
sl@0
    56
sl@0
    57
sl@0
    58
sl@0
    59
/**
sl@0
    60
Completes construction of this server-side client session object.
sl@0
    61
sl@0
    62
The function is called by the server active object, the CServer2 derived
sl@0
    63
class instance, when a client makes a connection request.
sl@0
    64
sl@0
    65
The connection request results in the creation of this session object,
sl@0
    66
followed by a call to this function.
sl@0
    67
sl@0
    68
The default implementation is empty.
sl@0
    69
sl@0
    70
@see CServer2::NewSessionL()
sl@0
    71
*/
sl@0
    72
EXPORT_C void CSession2::CreateL()
sl@0
    73
	{
sl@0
    74
	}
sl@0
    75
sl@0
    76
/**
sl@0
    77
Designates the (master or slave) server that is to service this session.
sl@0
    78
sl@0
    79
This may be called from the NewSessionL() method of the CServer2-derived
sl@0
    80
class or from the CreateL() method of the CSession2-derived class.
sl@0
    81
sl@0
    82
It must not be called after CreateL() has finished, as this is the point
sl@0
    83
at which the session binding become irrevocable.
sl@0
    84
sl@0
    85
@see CServer::DoConnect()
sl@0
    86
*/
sl@0
    87
EXPORT_C void CSession2::SetServer(const CServer2* aServer)
sl@0
    88
	{
sl@0
    89
	ASSERT(iLink.iNext == NULL);
sl@0
    90
	ASSERT(aServer);
sl@0
    91
	iServer = aServer;
sl@0
    92
	}
sl@0
    93
sl@0
    94
/**
sl@0
    95
Handles the situation when a call to CSession2::ServiceL(), which services
sl@0
    96
a client request, leaves.
sl@0
    97
sl@0
    98
Servers are active objects, and the call to CSession2::ServiceL() to handle
sl@0
    99
a client request is executed as part of the server's active object RunL()
sl@0
   100
function. If the RunL() leaves, the active object framework calls the active
sl@0
   101
object's RunError() function. The server framework implements this as a call
sl@0
   102
to ServiceError()
sl@0
   103
sl@0
   104
The default behaviour of this function is to complete the message, using
sl@0
   105
the leave value, if it has not already been completed.
sl@0
   106
sl@0
   107
Servers can re-implement this as appropriate.
sl@0
   108
sl@0
   109
@param aMessage The message containing the details of the client request that
sl@0
   110
                caused the leave.
sl@0
   111
@param aError   The leave code.
sl@0
   112
sl@0
   113
@see CActive::RunL()
sl@0
   114
@see CActive::RunError()
sl@0
   115
*/
sl@0
   116
EXPORT_C void CSession2::ServiceError(const RMessage2& aMessage,TInt aError)
sl@0
   117
	{
sl@0
   118
	if(!aMessage.IsNull())
sl@0
   119
		aMessage.Complete(aError);
sl@0
   120
	}
sl@0
   121
sl@0
   122
sl@0
   123
sl@0
   124
/**
sl@0
   125
Called by a server when it receives a disconnect message for the session.
sl@0
   126
	
sl@0
   127
This message is sent by the kernel when all client handles to the session have
sl@0
   128
been closed.
sl@0
   129
This method deletes the session object and completes the disconnect message.
sl@0
   130
sl@0
   131
A derived session implementation may overide this virtual method if it needs to
sl@0
   132
perform any asynchronous cleanup actions, these actions must end with a call to the
sl@0
   133
base class implementation of this method, which will delete the session object
sl@0
   134
and complete the disconnect message
sl@0
   135
sl@0
   136
@param aMessage The disconnect message.
sl@0
   137
sl@0
   138
@post 'this' session object has been deleted.
sl@0
   139
*/
sl@0
   140
EXPORT_C void CSession2::Disconnect(const RMessage2& aMessage)
sl@0
   141
	{
sl@0
   142
	delete this;
sl@0
   143
	aMessage.Complete(0);
sl@0
   144
	}
sl@0
   145
sl@0
   146
sl@0
   147
sl@0
   148
/**
sl@0
   149
Marks the start of resource count checking.
sl@0
   150
sl@0
   151
It sets up a starting value for resource count checking.
sl@0
   152
sl@0
   153
The function sets up a starting value for resource count checking by using
sl@0
   154
the value returned by a call to CSession2::CountResources(), and is the value
sl@0
   155
that will be used for comparison if CSession2::ResourceCountMarkEnd() is called
sl@0
   156
at some later time.
sl@0
   157
sl@0
   158
The client/server framework does not call this function (nor
sl@0
   159
does it call CSession2::ResourceCountMarkEnd()), but is available for servers
sl@0
   160
to use, if appropriate.
sl@0
   161
sl@0
   162
@see CSession2::CountResources()
sl@0
   163
@see CSession2::ResourceCountMarkEnd()
sl@0
   164
*/
sl@0
   165
EXPORT_C void CSession2::ResourceCountMarkStart()
sl@0
   166
	{
sl@0
   167
	iResourceCountMark=CountResources();
sl@0
   168
	}
sl@0
   169
sl@0
   170
sl@0
   171
sl@0
   172
/**
sl@0
   173
Marks the end of resource count checking.
sl@0
   174
sl@0
   175
The function takes the current resource count by
sl@0
   176
calling CSession2::CountResources(), and compares it with the resource count
sl@0
   177
value saved when CSession2::ResourceCountMarkStart() was called.
sl@0
   178
If the resource counts differ, then the client thread is panicked (CSession 2)".
sl@0
   179
sl@0
   180
The client/server framework does not call this function (nor does it call 
sl@0
   181
CSession2::ResourceCountMarkStart()), but the function is available for
sl@0
   182
servers to use, if appropriate.
sl@0
   183
sl@0
   184
@param aMessage Represents the details of the client request that is requesting
sl@0
   185
                this resource check.
sl@0
   186
sl@0
   187
@see CSession2::CountResources()
sl@0
   188
@see CSession2::ResourceCountMarkStart()
sl@0
   189
*/
sl@0
   190
EXPORT_C void CSession2::ResourceCountMarkEnd(const RMessage2& aMessage)
sl@0
   191
	{
sl@0
   192
	if (iResourceCountMark!=CountResources())
sl@0
   193
		aMessage.Panic(KSessionPanicCategory,ESesFoundResCountHeaven);
sl@0
   194
	}
sl@0
   195
sl@0
   196
sl@0
   197
sl@0
   198
/**
sl@0
   199
Gets the number of resources currently in use.
sl@0
   200
sl@0
   201
Derived classes must provide a suitable implementation.
sl@0
   202
The meaning of a resource depends on the design intent of the server.
sl@0
   203
sl@0
   204
The default implementation panics the calling thread (CSession 1)
sl@0
   205
before returning KErrGeneral.
sl@0
   206
sl@0
   207
@return The current number of resources in use.
sl@0
   208
sl@0
   209
@see CSession2::ResourceCountmarkStart()
sl@0
   210
@see CSession2::ResourceCountmarkEnd()
sl@0
   211
*/
sl@0
   212
EXPORT_C TInt CSession2::CountResources()
sl@0
   213
	{
sl@0
   214
	User::Panic(KSessionPanicCategory,ESesCountResourcesNotImplemented);
sl@0
   215
	return KErrGeneral;
sl@0
   216
	}
sl@0
   217
sl@0
   218
sl@0
   219
sl@0
   220
/**
sl@0
   221
Extension function
sl@0
   222
sl@0
   223
sl@0
   224
*/
sl@0
   225
EXPORT_C TInt CSession2::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
sl@0
   226
	{
sl@0
   227
	return CBase::Extension_(aExtensionId, a0, a1);
sl@0
   228
	}
sl@0
   229
sl@0
   230
sl@0
   231
sl@0
   232
sl@0
   233
/**
sl@0
   234
Constructs the server object, specifying the server type and the active
sl@0
   235
object priority.
sl@0
   236
sl@0
   237
Derived classes must define and implement a constructor through which
sl@0
   238
the priority can be specified. A typical implementation calls this server
sl@0
   239
base class constructor through a constructor initialization list.
sl@0
   240
sl@0
   241
@param aPriority The priority of this active object.
sl@0
   242
@param aType     Indicates the type of session that the server creates.
sl@0
   243
                 If not explicitly stated, then the server creates
sl@0
   244
                 a session that is not sharable with other threads.
sl@0
   245
*/
sl@0
   246
EXPORT_C CServer2::CServer2(TInt aPriority, TServerType aType)
sl@0
   247
	:	CActive(aPriority),
sl@0
   248
		iSessionType((TUint8)aType),
sl@0
   249
		iSessionQ(_FOFF(CSession2,iLink)),
sl@0
   250
		iSessionIter(iSessionQ)
sl@0
   251
	{
sl@0
   252
	ASSERT(iSessionType == aType);
sl@0
   253
	__ASSERT_COMPILE(EServerRole_Default == 0);
sl@0
   254
	__ASSERT_COMPILE(EServerOpt_PinClientDescriptorsDefault == 0);
sl@0
   255
	}
sl@0
   256
sl@0
   257
sl@0
   258
sl@0
   259
/**
sl@0
   260
Frees resources prior to destruction.
sl@0
   261
sl@0
   262
Specifically, it cancels any outstanding request for messages, and 
sl@0
   263
deletes all server-side client session objects.
sl@0
   264
*/
sl@0
   265
EXPORT_C CServer2::~CServer2()
sl@0
   266
	{
sl@0
   267
	Cancel();
sl@0
   268
	while (!iSessionQ.IsEmpty())
sl@0
   269
		{
sl@0
   270
		CSession2 *pS=iSessionQ.First();
sl@0
   271
		pS->iLink.Deque();
sl@0
   272
		pS->iLink.iNext=0;
sl@0
   273
		delete pS;
sl@0
   274
		}
sl@0
   275
	iServer.Close();
sl@0
   276
	}
sl@0
   277
sl@0
   278
sl@0
   279
/**
sl@0
   280
Sets whether the kernel will pin descriptors passed to this server in the context of the client
sl@0
   281
thread.
sl@0
   282
sl@0
   283
Setting this is one way of ensuring that the server will not take page faults when accessing client
sl@0
   284
descriptors, which would otherwise happen if the data was paged out.
sl@0
   285
sl@0
   286
This method overrides the default pinning policy of the server which is for the server 
sl@0
   287
to pin its client's descriptors if the process creating the server is not data paged.
sl@0
   288
I.e. if CServer2::SetPinClientDescriptors() is not invoked on the server and 
sl@0
   289
RProcess::DefaultDataPaged() of the process creating the server returns EFalse, 
sl@0
   290
the server will pin its client's descriptors, otherwise the server will not pin its
sl@0
   291
client's descriptors.
sl@0
   292
sl@0
   293
This method must be called prior to starting the server by calling the Start() method.
sl@0
   294
sl@0
   295
@param aPin	Set to ETrue for the server to pin its client's descriptors, set to 
sl@0
   296
			EFalse otherwise.
sl@0
   297
@panic E32USER-CBase 106 When this method is invoked after the server has been started.
sl@0
   298
@see CServer2::Start()
sl@0
   299
sl@0
   300
@prototype
sl@0
   301
*/
sl@0
   302
EXPORT_C void CServer2::SetPinClientDescriptors(TBool aPin)
sl@0
   303
	{
sl@0
   304
	if (iServer.Handle() != KNullHandle)
sl@0
   305
		{// Server already started so too late to make it a pinning one.
sl@0
   306
		Panic(ECServer2InvalidSetPin);
sl@0
   307
		}
sl@0
   308
	iServerOpts &= ~EServerOpt_PinClientDescriptorsMask;
sl@0
   309
	if (aPin)
sl@0
   310
		iServerOpts |= EServerOpt_PinClientDescriptorsEnable;
sl@0
   311
	else
sl@0
   312
		iServerOpts |= EServerOpt_PinClientDescriptorsDisable;
sl@0
   313
	}
sl@0
   314
sl@0
   315
/**
sl@0
   316
Assigns a role (master or slave) for this server.
sl@0
   317
sl@0
   318
The master server is typically named, and receives all Connect messages
sl@0
   319
from clients. It can hand off some sessions to be processed by one or
sl@0
   320
more anonymous slave servers, each running in a separate thread.
sl@0
   321
sl@0
   322
Both master and slave servers must call this function before calling
sl@0
   323
Start(), in order to define their roles.  Once the server is started,
sl@0
   324
its role cannot be changed.
sl@0
   325
sl@0
   326
@panic E32USER-CBase-? When this method is invoked after the server has been started.
sl@0
   327
@see CServer2::Start()
sl@0
   328
sl@0
   329
@prototype
sl@0
   330
*/
sl@0
   331
EXPORT_C void CServer2::SetMaster(const CServer2* aServer)
sl@0
   332
	{
sl@0
   333
	// Roles can only be assigned before the call to Start()
sl@0
   334
	ASSERT(Server().Handle() == KNullHandle);
sl@0
   335
sl@0
   336
	if (aServer == NULL)
sl@0
   337
		iServerRole = EServerRole_Standalone;
sl@0
   338
	else if (aServer == this)
sl@0
   339
		iServerRole = EServerRole_Master;
sl@0
   340
	else
sl@0
   341
		iServerRole = EServerRole_Slave;
sl@0
   342
	}
sl@0
   343
sl@0
   344
sl@0
   345
/**
sl@0
   346
Adds the server with the specified name to the active scheduler,
sl@0
   347
and issues the first request for messages.
sl@0
   348
sl@0
   349
If KNullDesC is specified for the name, then an anonymous server will be created.
sl@0
   350
To create a session to such a server, an overload of RSessionBase::CreateSession()
sl@0
   351
which takes RServer2 object as a parameter can be used.
sl@0
   352
sl@0
   353
@param aName The name of the server.
sl@0
   354
             KNullDesC, to create anonymous servers.
sl@0
   355
@return KErrNone, if successful, otherwise one of the other system wide error codes.
sl@0
   356
sl@0
   357
@capability ProtServ if aName starts with a '!' character
sl@0
   358
*/
sl@0
   359
EXPORT_C TInt CServer2::Start(const TDesC& aName)
sl@0
   360
	{
sl@0
   361
	TInt r = iServer.CreateGlobal(aName, iSessionType, iServerRole, iServerOpts);
sl@0
   362
	if (r == KErrNone)
sl@0
   363
		{
sl@0
   364
		CActiveScheduler::Add(this);
sl@0
   365
		ReStart();
sl@0
   366
		}
sl@0
   367
	return r;
sl@0
   368
	}
sl@0
   369
sl@0
   370
sl@0
   371
	
sl@0
   372
/**
sl@0
   373
Adds the server with the specified name to the active scheduler,
sl@0
   374
and issues the first request for messages, and leaves if the operation fails.
sl@0
   375
sl@0
   376
If KNullDesC is specified for the name, then an anonymous server will be created.
sl@0
   377
To create a session to such a server, the overload of RSessionBase::CreateSession() 
sl@0
   378
which takes an RServer2 object as a parameter can be used.
sl@0
   379
sl@0
   380
@param aName The name of the server.
sl@0
   381
             KNullDesC, to create anonymous servers.
sl@0
   382
@capability  ProtServ if aName starts with a '!' character
sl@0
   383
*/
sl@0
   384
EXPORT_C void CServer2::StartL(const TDesC& aName)
sl@0
   385
	{
sl@0
   386
	User::LeaveIfError(Start(aName));
sl@0
   387
	}
sl@0
   388
sl@0
   389
sl@0
   390
sl@0
   391
/**
sl@0
   392
Implements the cancellation of any outstanding request for messages.
sl@0
   393
*/
sl@0
   394
EXPORT_C void CServer2::DoCancel()
sl@0
   395
	{
sl@0
   396
sl@0
   397
	iServer.Cancel();
sl@0
   398
	}
sl@0
   399
sl@0
   400
sl@0
   401
sl@0
   402
void CServer2::Connect(const RMessage2& aMessage)
sl@0
   403
//
sl@0
   404
// Handle a connect request. Ptr0()==Version.
sl@0
   405
// NOTE: We don't want this to leave as that may kill the server
sl@0
   406
//
sl@0
   407
	{
sl@0
   408
sl@0
   409
	if (aMessage.Session())
sl@0
   410
		{
sl@0
   411
		aMessage.Panic(KServerPanicCategory,ESessionAlreadyConnected);
sl@0
   412
		return;
sl@0
   413
		}
sl@0
   414
	DoConnect(aMessage);
sl@0
   415
	}
sl@0
   416
sl@0
   417
sl@0
   418
sl@0
   419
//
sl@0
   420
//This is all of the Leaving code for connection creation.
sl@0
   421
//This is in a seperate function in an effort to force compilers to store aSession
sl@0
   422
//on the stack which enables cleanup to perform correctly when a Leave occurs
sl@0
   423
//
sl@0
   424
void CServer2::DoConnectL(const RMessage2& aMessage,CSession2* volatile& aSession)
sl@0
   425
	{
sl@0
   426
	TVersion v;
sl@0
   427
	*(TInt*)&v = aMessage.Int0();
sl@0
   428
	aSession = NewSessionL(v, aMessage);
sl@0
   429
	if (!aSession->iServer)
sl@0
   430
		aSession->iServer = this;
sl@0
   431
	aSession->CreateL();
sl@0
   432
	iSessionQ.AddLast(*aSession);
sl@0
   433
	Exec::SetSessionPtr(aMessage.Handle(), aSession);
sl@0
   434
	}
sl@0
   435
sl@0
   436
sl@0
   437
sl@0
   438
/**
sl@0
   439
Handles the connect request from the client.  We trap Leaves, to ensure
sl@0
   440
that existing sessions aren't affected by failure to create a new one.
sl@0
   441
sl@0
   442
@param aMessage The Connect message sent by the client requesting the
sl@0
   443
                connection. aMessage.Ptr0() is the required Version.
sl@0
   444
*/
sl@0
   445
EXPORT_C void CServer2::DoConnect(const RMessage2& aMessage)
sl@0
   446
	{
sl@0
   447
	ASSERT(aMessage.Function() == RMessage2::EConnect);
sl@0
   448
	ASSERT(aMessage.Session() == NULL);
sl@0
   449
	ASSERT(!aMessage.IsNull());
sl@0
   450
sl@0
   451
	CSession2* newSession = NULL;
sl@0
   452
	TRAPD(err, DoConnectL(aMessage, newSession));
sl@0
   453
	if (err != KErrNone)
sl@0
   454
		{
sl@0
   455
		// Connect failed
sl@0
   456
		delete newSession;
sl@0
   457
		aMessage.Complete(err);
sl@0
   458
		}
sl@0
   459
	else
sl@0
   460
		{
sl@0
   461
		ASSERT(newSession != NULL);
sl@0
   462
		CServer2* sessionServer = const_cast<CServer2*>(newSession->Server());
sl@0
   463
		ASSERT(sessionServer != NULL);
sl@0
   464
sl@0
   465
		// The return value of Server() will be 'this', unless it was
sl@0
   466
		// changed by a call to SetServer().
sl@0
   467
		if (sessionServer == this)
sl@0
   468
			{
sl@0
   469
			// no SetServer() call, so just complete the Connect message
sl@0
   470
			aMessage.Complete(err);
sl@0
   471
			}
sl@0
   472
		else
sl@0
   473
			{
sl@0
   474
			// Transfer the new Csession to the specified slave Cserver
sl@0
   475
			newSession->iLink.Deque();
sl@0
   476
			sessionServer->iSessionQ.AddLast(*newSession);
sl@0
   477
sl@0
   478
			// Ask the kernel to transfer the DSession to the slave DServer.
sl@0
   479
			// Note: this Exec call also completes the Connect message.
sl@0
   480
			TInt msgHandle = aMessage.iHandle;
sl@0
   481
			const_cast<TInt&>(aMessage.iHandle) = 0;
sl@0
   482
			ASSERT(msgHandle);
sl@0
   483
			Exec::TransferSession(msgHandle, sessionServer->Server().Handle());
sl@0
   484
			}
sl@0
   485
		}
sl@0
   486
sl@0
   487
	ASSERT(aMessage.IsNull());
sl@0
   488
	}
sl@0
   489
sl@0
   490
sl@0
   491
sl@0
   492
/**
sl@0
   493
Handles the situation where a call to CServer2::RunL(), leaves.
sl@0
   494
sl@0
   495
This is the server active object's implementation of the active object
sl@0
   496
framework's RunError() function.
sl@0
   497
sl@0
   498
In practice, the leave can only be caused by a session's ServiceL() function,
sl@0
   499
which is called from this RunL(); this error is reflected back to that session
sl@0
   500
by calling its ServiceError() function.
sl@0
   501
sl@0
   502
@param aError The leave code.
sl@0
   503
sl@0
   504
@return KErrNone.
sl@0
   505
sl@0
   506
@see CActive::RunL()
sl@0
   507
@see CActive::RunError()
sl@0
   508
@see CSession2::ServiceError()
sl@0
   509
*/
sl@0
   510
EXPORT_C TInt CServer2::RunError(TInt aError)
sl@0
   511
	{
sl@0
   512
	Message().Session()->ServiceError(Message(),aError);
sl@0
   513
	if (!IsActive())
sl@0
   514
		ReStart();
sl@0
   515
	return KErrNone;
sl@0
   516
	}
sl@0
   517
sl@0
   518
sl@0
   519
sl@0
   520
/**
sl@0
   521
Restarts the server.
sl@0
   522
sl@0
   523
The function issues a request for messages.
sl@0
   524
*/
sl@0
   525
EXPORT_C void CServer2::ReStart()
sl@0
   526
	{
sl@0
   527
sl@0
   528
	iServer.Receive(iMessage,iStatus);
sl@0
   529
	SetActive();
sl@0
   530
	}
sl@0
   531
sl@0
   532
sl@0
   533
sl@0
   534
#ifndef __CSERVER_MACHINE_CODED__
sl@0
   535
/**
sl@0
   536
Handles the receipt of a message.
sl@0
   537
*/
sl@0
   538
EXPORT_C void CServer2::RunL()
sl@0
   539
	{
sl@0
   540
	TInt fn = Message().Function();
sl@0
   541
sl@0
   542
	if(fn>=0)
sl@0
   543
		{
sl@0
   544
		// Service the message
sl@0
   545
		CSession2* session=Message().Session();
sl@0
   546
		if(session)
sl@0
   547
			session->ServiceL(Message());
sl@0
   548
		else
sl@0
   549
			NotConnected(Message());
sl@0
   550
		}
sl@0
   551
	else if(fn==RMessage2::EConnect)
sl@0
   552
		{
sl@0
   553
		Connect(Message());
sl@0
   554
		}
sl@0
   555
	else if(fn==RMessage2::EDisConnect)
sl@0
   556
		{
sl@0
   557
		Disconnect(Message());
sl@0
   558
		}
sl@0
   559
	else
sl@0
   560
		{
sl@0
   561
		BadMessage(Message());
sl@0
   562
		}
sl@0
   563
	// Queue reception of next message if it hasn't already been done
sl@0
   564
	if(!IsActive())
sl@0
   565
		ReStart();
sl@0
   566
	}
sl@0
   567
sl@0
   568
#endif
sl@0
   569
sl@0
   570
sl@0
   571
sl@0
   572
void CServer2::Disconnect(const RMessage2& aMessage)
sl@0
   573
//
sl@0
   574
// Process a disconnect message
sl@0
   575
//
sl@0
   576
	{
sl@0
   577
	CSession2* session=Message().Session();
sl@0
   578
	if(!session)
sl@0
   579
		{
sl@0
   580
		// Session not created yet, so just complete message.
sl@0
   581
		aMessage.Complete(0);
sl@0
   582
		return;
sl@0
   583
		}
sl@0
   584
	session->Disconnect(aMessage);
sl@0
   585
	}
sl@0
   586
sl@0
   587
sl@0
   588
sl@0
   589
void CServer2::BadMessage(const RMessage2& aMessage)
sl@0
   590
	{
sl@0
   591
	aMessage.Panic(KServerPanicCategory,EBadMessageNumber);
sl@0
   592
	}
sl@0
   593
sl@0
   594
sl@0
   595
sl@0
   596
void CServer2::NotConnected(const RMessage2& aMessage)
sl@0
   597
	{
sl@0
   598
	aMessage.Panic(KServerPanicCategory,ESessionNotConnected);
sl@0
   599
	}
sl@0
   600
sl@0
   601
	
sl@0
   602
sl@0
   603
/**
sl@0
   604
Extension function
sl@0
   605
sl@0
   606
sl@0
   607
*/
sl@0
   608
EXPORT_C TInt CServer2::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
sl@0
   609
	{
sl@0
   610
	return CActive::Extension_(aExtensionId, a0, a1);
sl@0
   611
	}