examples/Base/IPC/ClientServer/Gettingstarted/transient/src/server.cpp

00001 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
00002 // All rights reserved.
00003 // This component and the accompanying materials are made available
00004 // under the terms of "Eclipse Public License v1.0"
00005 // which accompanies this distribution, and is available
00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
00007 //
00008 // Initial Contributors:
00009 // Nokia Corporation - initial contribution.
00010 //
00011 // Contributors:
00012 //
00013 // Description:
00014 // Transient server example - server implementation
00015 //
00016 
00017 #include "server.h"
00018 
00019 inline CShutdown::CShutdown()
00020         :CTimer(-1)
00021         {CActiveScheduler::Add(this);}
00022 inline void CShutdown::ConstructL()
00023         {CTimer::ConstructL();}
00024 inline void CShutdown::Start()
00025         {After(KMyShutdownDelay);}
00026 
00027 inline CMyServer::CMyServer()
00028         :CServer2(0,ESharableSessions)
00029         {}
00030 
00031 inline CMySession::CMySession()
00032         {}
00033 inline CMyServer& CMySession::Server()
00034         {return *static_cast<CMyServer*>(const_cast<CServer2*>(CSession2::Server()));}
00035 inline TBool CMySession::ReceivePending() const
00036         {return !iReceiveMsg.IsNull();}
00037 
00038 
00040 
00041 void CMySession::CreateL()
00042 //
00043 // 2nd phase construct for sessions - called by the CServer framework
00044 //
00045         {
00046         Server().AddSession();
00047         }
00048 
00049 CMySession::~CMySession()
00050         {
00051         Server().DropSession();
00052         }
00053 
00054 void CMySession::Send(const TDesC& aMessage)
00055 //
00056 // Deliver the message to the client, truncating if required
00057 // If the write fails, panic the client, not the sender
00058 //
00059         {
00060         if (ReceivePending())
00061                 {
00062                 TPtrC m(aMessage);
00063                 if (iReceiveLen<aMessage.Length())
00064                         m.Set(m.Left(iReceiveLen));
00065                 TInt r=iReceiveMsg.Write(0,m);
00066                 if (r==KErrNone)
00067                         iReceiveMsg.Complete(KErrNone);
00068                 else
00069                         PanicClient(iReceiveMsg,EPanicBadDescriptor);
00070                 }
00071         }
00072 
00073 void CMySession::ServiceL(const RMessage2& aMessage)
00074 //
00075 // Handle a client request.
00076 // Leaving is handled by CMyServer::ServiceError() which reports
00077 // the error code to the client
00078 //
00079         {
00080         switch (aMessage.Function())
00081                 {
00082         case ESend:
00083                 {
00084                 TBuf<KMaxMyMessage> message;
00085                 aMessage.ReadL(0,message);
00086                 Server().Send(message);
00087                 aMessage.Complete(KErrNone);
00088                 break;
00089                 }
00090         case EReceive:
00091                 if (ReceivePending())
00092                         PanicClient(aMessage,EPanicAlreadyReceiving);
00093                 else
00094                         {
00095                         iReceiveMsg=aMessage;
00096                         iReceiveLen=aMessage.Int1();
00097                         }
00098                 break;
00099         case ECancelReceive:
00100                 if (ReceivePending())
00101                         iReceiveMsg.Complete(KErrCancel);
00102                 aMessage.Complete(KErrNone);
00103                 break;
00104         default:
00105                 PanicClient(aMessage,EPanicIllegalFunction);
00106                 break;
00107                 }
00108         }
00109 
00110 void CMySession::ServiceError(const RMessage2& aMessage,TInt aError)
00111 //
00112 // Handle an error from CMySession::ServiceL()
00113 // A bad descriptor error implies a badly programmed client, so panic it;
00114 // otherwise use the default handling (report the error to the client)
00115 //
00116         {
00117         if (aError==KErrBadDescriptor)
00118                 PanicClient(aMessage,EPanicBadDescriptor);
00119         CSession2::ServiceError(aMessage,aError);
00120         }
00121 
00122 void CShutdown::RunL()
00123 //
00124 // Initiate server exit when the timer expires
00125 //
00126         {
00127         CActiveScheduler::Stop();
00128         }
00129 
00130 CServer2* CMyServer::NewLC()
00131         {
00132         CMyServer* self=new(ELeave) CMyServer;
00133         CleanupStack::PushL(self);
00134         self->ConstructL();
00135         return self;
00136         }
00137 
00138 void CMyServer::ConstructL()
00139 //
00140 // 2nd phase construction - ensure the timer and server objects are running
00141 //
00142         {
00143         StartL(KMyServerName);
00144         iShutdown.ConstructL();
00145         // ensure that the server still exits even if the 1st client fails to connect
00146         iShutdown.Start();
00147         }
00148 
00149 
00150 CSession2* CMyServer::NewSessionL(const TVersion&,const RMessage2&) const
00151 //
00152 // Cretae a new client session. This should really check the version number.
00153 //
00154         {
00155         return new(ELeave) CMySession();
00156         }
00157 
00158 void CMyServer::AddSession()
00159 //
00160 // A new session is being created
00161 // Cancel the shutdown timer if it was running
00162 //
00163         {
00164         ++iSessionCount;
00165         iShutdown.Cancel();
00166         }
00167 
00168 void CMyServer::DropSession()
00169 //
00170 // A session is being destroyed
00171 // Start the shutdown timer if it is the last session.
00172 //
00173         {
00174         if (--iSessionCount==0)
00175                 iShutdown.Start();
00176         }
00177 
00178 void CMyServer::Send(const TDesC& aMessage)
00179 //
00180 // Pass on the signal to all clients
00181 //
00182         {
00183         iSessionIter.SetToFirst();
00184         CSession2* s;
00185         while ((s=iSessionIter++)!=0)
00186                 static_cast<CMySession*>(s)->Send(aMessage);
00187         }
00188 
00189 void PanicClient(const RMessagePtr2& aMessage,TMyPanic aPanic)
00190 //
00191 // RMessage::Panic() also completes the message. This is:
00192 // (a) important for efficient cleanup within the kernel
00193 // (b) a problem if the message is completed a second time
00194 //
00195         {
00196         _LIT(KPanic,"MyServer");
00197         aMessage.Panic(KPanic,aPanic);
00198         }
00199 
00200 static void RunServerL()
00201 //
00202 // Perform all server initialisation, in particular creation of the
00203 // scheduler and server and then run the scheduler
00204 //
00205         {
00206         // naming the server thread after the server helps to debug panics
00207         User::LeaveIfError(RThread::RenameMe(KMyServerName));
00208         //
00209         // create and install the active scheduler we need
00210         CActiveScheduler* s=new(ELeave) CActiveScheduler;
00211         CleanupStack::PushL(s);
00212         CActiveScheduler::Install(s);
00213         //
00214         // create the server (leave it on the cleanup stack)
00215         CMyServer::NewLC();
00216         //
00217         // Initialisation complete, now signal the client
00218         RProcess::Rendezvous(KErrNone);
00219         //
00220         // Ready to run
00221         CActiveScheduler::Start();
00222         //
00223         // Cleanup the server and scheduler
00224         CleanupStack::PopAndDestroy(2);
00225         }
00226 
00227 TInt E32Main()
00228 //
00229 // Server process entry-point
00230 //
00231         {
00232         __UHEAP_MARK;
00233         //
00234         CTrapCleanup* cleanup=CTrapCleanup::New();
00235         TInt r=KErrNoMemory;
00236         if (cleanup)
00237                 {
00238                 TRAP(r,RunServerL());
00239                 delete cleanup;
00240                 }
00241         //
00242         __UHEAP_MARKEND;
00243         return r;
00244         }

Generated by  doxygen 1.6.2