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

00001 /*
00002 Copyright (c) 2000-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description: Transient server example - server implementation  
00028 */
00029 
00030 
00031 #include "server.h"
00032 
00033 inline CShutdown::CShutdown()
00034         :CTimer(-1)
00035         {CActiveScheduler::Add(this);}
00036 inline void CShutdown::ConstructL()
00037         {CTimer::ConstructL();}
00038 inline void CShutdown::Start()
00039         {After(KMyShutdownDelay);}
00040 
00041 inline CMyServer::CMyServer()
00042         :CServer2(0,ESharableSessions)
00043         {}
00044 
00045 inline CMySession::CMySession()
00046         {}
00047 inline CMyServer& CMySession::Server()
00048         {return *static_cast<CMyServer*>(const_cast<CServer2*>(CSession2::Server()));}
00049 inline TBool CMySession::ReceivePending() const
00050         {return !iReceiveMsg.IsNull();}
00051 
00052 
00054 
00055 void CMySession::CreateL()
00056 //
00057 // 2nd phase construct for sessions - called by the CServer framework
00058 //
00059         {
00060         Server().AddSession();
00061         }
00062 
00063 CMySession::~CMySession()
00064         {
00065         Server().DropSession();
00066         }
00067 
00068 void CMySession::Send(const TDesC& aMessage)
00069 //
00070 // Deliver the message to the client, truncating if required
00071 // If the write fails, panic the client, not the sender
00072 //
00073         {
00074         if (ReceivePending())
00075                 {
00076                 TPtrC m(aMessage);
00077                 if (iReceiveLen<aMessage.Length())
00078                         m.Set(m.Left(iReceiveLen));
00079                 TInt r=iReceiveMsg.Write(0,m);
00080                 if (r==KErrNone)
00081                         iReceiveMsg.Complete(KErrNone);
00082                 else
00083                         PanicClient(iReceiveMsg,EPanicBadDescriptor);
00084                 }
00085         }
00086 
00087 void CMySession::ServiceL(const RMessage2& aMessage)
00088 //
00089 // Handle a client request.
00090 // Leaving is handled by CMyServer::ServiceError() which reports
00091 // the error code to the client
00092 //
00093         {
00094         switch (aMessage.Function())
00095                 {
00096         case ESend:
00097                 {
00098                 TBuf<KMaxMyMessage> message;
00099                 aMessage.ReadL(0,message);
00100                 Server().Send(message);
00101                 aMessage.Complete(KErrNone);
00102                 break;
00103                 }
00104         case EReceive:
00105                 if (ReceivePending())
00106                         PanicClient(aMessage,EPanicAlreadyReceiving);
00107                 else
00108                         {
00109                         iReceiveMsg=aMessage;
00110                         iReceiveLen=aMessage.Int1();
00111                         }
00112                 break;
00113         case ECancelReceive:
00114                 if (ReceivePending())
00115                         iReceiveMsg.Complete(KErrCancel);
00116                 aMessage.Complete(KErrNone);
00117                 break;
00118         default:
00119                 PanicClient(aMessage,EPanicIllegalFunction);
00120                 break;
00121                 }
00122         }
00123 
00124 void CMySession::ServiceError(const RMessage2& aMessage,TInt aError)
00125 //
00126 // Handle an error from CMySession::ServiceL()
00127 // A bad descriptor error implies a badly programmed client, so panic it;
00128 // otherwise use the default handling (report the error to the client)
00129 //
00130         {
00131         if (aError==KErrBadDescriptor)
00132                 PanicClient(aMessage,EPanicBadDescriptor);
00133         CSession2::ServiceError(aMessage,aError);
00134         }
00135 
00136 void CShutdown::RunL()
00137 //
00138 // Initiate server exit when the timer expires
00139 //
00140         {
00141         CActiveScheduler::Stop();
00142         }
00143 
00144 CServer2* CMyServer::NewLC()
00145         {
00146         CMyServer* self=new(ELeave) CMyServer;
00147         CleanupStack::PushL(self);
00148         self->ConstructL();
00149         return self;
00150         }
00151 
00152 void CMyServer::ConstructL()
00153 //
00154 // 2nd phase construction - ensure the timer and server objects are running
00155 //
00156         {
00157         StartL(KMyServerName);
00158         iShutdown.ConstructL();
00159         // ensure that the server still exits even if the 1st client fails to connect
00160         iShutdown.Start();
00161         }
00162 
00163 
00164 CSession2* CMyServer::NewSessionL(const TVersion&,const RMessage2&) const
00165 //
00166 // Cretae a new client session. This should really check the version number.
00167 //
00168         {
00169         return new(ELeave) CMySession();
00170         }
00171 
00172 void CMyServer::AddSession()
00173 //
00174 // A new session is being created
00175 // Cancel the shutdown timer if it was running
00176 //
00177         {
00178         ++iSessionCount;
00179         iShutdown.Cancel();
00180         }
00181 
00182 void CMyServer::DropSession()
00183 //
00184 // A session is being destroyed
00185 // Start the shutdown timer if it is the last session.
00186 //
00187         {
00188         if (--iSessionCount==0)
00189                 iShutdown.Start();
00190         }
00191 
00192 void CMyServer::Send(const TDesC& aMessage)
00193 //
00194 // Pass on the signal to all clients
00195 //
00196         {
00197         iSessionIter.SetToFirst();
00198         CSession2* s;
00199         while ((s=iSessionIter++)!=0)
00200                 static_cast<CMySession*>(s)->Send(aMessage);
00201         }
00202 
00203 void PanicClient(const RMessagePtr2& aMessage,TMyPanic aPanic)
00204 //
00205 // RMessage::Panic() also completes the message. This is:
00206 // (a) important for efficient cleanup within the kernel
00207 // (b) a problem if the message is completed a second time
00208 //
00209         {
00210         _LIT(KPanic,"MyServer");
00211         aMessage.Panic(KPanic,aPanic);
00212         }
00213 
00214 static void RunServerL()
00215 //
00216 // Perform all server initialisation, in particular creation of the
00217 // scheduler and server and then run the scheduler
00218 //
00219         {
00220         // naming the server thread after the server helps to debug panics
00221         User::LeaveIfError(RThread::RenameMe(KMyServerName));
00222         //
00223         // create and install the active scheduler we need
00224         CActiveScheduler* s=new(ELeave) CActiveScheduler;
00225         CleanupStack::PushL(s);
00226         CActiveScheduler::Install(s);
00227         //
00228         // create the server (leave it on the cleanup stack)
00229         CMyServer::NewLC();
00230         //
00231         // Initialisation complete, now signal the client
00232         RProcess::Rendezvous(KErrNone);
00233         //
00234         // Ready to run
00235         CActiveScheduler::Start();
00236         //
00237         // Cleanup the server and scheduler
00238         CleanupStack::PopAndDestroy(2);
00239         }
00240 
00241 TInt E32Main()
00242 //
00243 // Server process entry-point
00244 //
00245         {
00246         __UHEAP_MARK;
00247         //
00248         CTrapCleanup* cleanup=CTrapCleanup::New();
00249         TInt r=KErrNoMemory;
00250         if (cleanup)
00251                 {
00252                 TRAP(r,RunServerL());
00253                 delete cleanup;
00254                 }
00255         //
00256         __UHEAP_MARKEND;
00257         return r;
00258         }

Generated by  doxygen 1.6.2