# examples/Base/IPC/ClientServer/Simple/SimpleServer.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 // The implementation of our simple server that increments and decrements a simple counter value.
    00015 // **NOTE**: The example does not demonstrate any security features - its purpose is simply
    00016 // to demonstrate the basic principles of client/server interaction.
    00017 //
    00018
    00019
    00020 #include "ClientServer.h"
    00021 #include "SimpleServer.h"
    00022 #include <e32svr.h>
    00023 #include <e32uid.h>
    00024
    00025
    00026 //**********************************
    00027 //CCountServServer - implementations
    00028 //**********************************
    00029
    00040 CCountServServer::CCountServServer(CActive::TPriority aActiveObjectPriority)
    00041         : CServer2(aActiveObjectPriority)
    00042         {
    00043         }
    00044
    00045
    00049 CSession2* CCountServServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
    00050     {
    00051       // Check that the version is OK
    00052     TVersion v(KCountServMajorVersionNumber,KCountServMinorVersionNumber,KCountServBuildVersionNumber);
    00053         if (!User::QueryVersionSupported(v,aVersion))
    00054                 User::Leave(KErrNotSupported);
    00055
    00056         // CAN USE THE aMessage argument to check client's security and identity
    00057         // can make use of this later but for now ignore. AH 4/5/05
    00058         // the connect message is delivered via the RMessage2 object passed.
    00059
    00060         // do something with this later (and move it to the start of the function?)
    00061
    00062           // Create the session.
    00063         return new (ELeave) CCountServSession;
    00064         }
    00065
    00066
    00070 void CCountServServer::PanicServer(TCountServPanic aPanic)
    00071         {
    00072         _LIT(KTxtServerPanic,"Count server panic");
    00073         User::Panic(KTxtServerPanic,aPanic);
    00074         }
    00075
    00076
    00077 //***********************************
    00078 //CCountServSession - implementations
    00079 //***********************************
    00080
    00081
    00085 CCountServSession::CCountServSession()
    00086         {
    00087     }
    00088
    00092 void CCountServSession::ServiceL(const RMessage2& aMessage)
    00093         {
    00094         TRAPD(err,DispatchMessageL(aMessage));
    00095         aMessage.Complete(err);
    00096         }
    00097
    00104 void CCountServSession::DispatchMessageL(const RMessage2& aMessage)
    00105         {
    00106         switch (aMessage.Function())
    00107         {
    00108         case ECountServSetFromString:
    00109                 SetFromStringL(aMessage);
    00110                 return;
    00111         case ECountServIncrease:
    00112                 Increase();
    00113                 return;
    00114         case ECountServIncreaseBy:
    00115                 IncreaseBy(aMessage);
    00116                 return;
    00117         case ECountServDecrease:
    00118                 Decrease();
    00119                 return;
    00120         case ECountServDecreaseBy:
    00121                 DecreaseBy(aMessage);
    00122                 return;
    00123         case ECountServReset:
    00124                 Reset();
    00125                 return;
    00126         case ECountServValue:
    00127                 CounterValueL(aMessage);
    00128                 return;
    00129
    00130           // This is an example of a request that we know about, but don't support.
    00131           // We cause KErrNotSupported to be returned to the client.
    00132         case ECountServUnsupportedRequest:
    00133                 User::Leave(KErrNotSupported);
    00134
    00135          //  Requests that we don't understand at all are a different matter.
    00136          //  This is considered a client programming error, so we panic the
    00137          //  client - this also completes the message.
    00138         default:
    00139                 PanicClient(aMessage,EBadRequest);
    00140                 return;
    00141         }
    00142         }
    00143
    00149 void CCountServSession::SetFromStringL(const RMessage2& aMessage)
    00150         {
    00151
    00152           // length of passed descriptor (1st parameter passed from client)
    00153         TInt deslen = aMessage.GetDesLength(0);
    00154
    00155           // Passed data will be saved in this descriptor.
    00156     RBuf buffer;
    00157
    00158       // Max length set to the value of "deslen", but current length is zero
    00159     buffer.CreateL(deslen);
    00160
    00161       // Do the right cleanup if anything subsequently goes wrong
    00162     buffer.CleanupClosePushL();
    00163
    00164       // Copy the client's descriptor data into our buffer.
    00165     aMessage.ReadL(0,buffer,0);
    00166
    00167       // Now do a validation to make sure that the string only has digits
    00168     if (buffer.Length() == 0)
    00169         {
    00170         User::Leave(ENonNumericString);
    00171         }
    00172
    00173     TLex16 lexer;
    00174
    00175     lexer.Assign(buffer);
    00176     while (!lexer.Eos())
    00177         {
    00178         TChar thechar;
    00179
    00180         thechar = lexer.Peek();
    00181         if (!thechar.IsDigit())
    00182             {
    00183                 User::Leave(ENonNumericString);
    00184             }
    00185         lexer.Inc();
    00186         }
    00187
    00188       // Convert to a simple TInt value.
    00189     lexer.Assign(buffer);
    00190     if (lexer.Val(iCount))
    00191         {
    00192         User::Leave(ENonNumericString);
    00193         }
    00194
    00195           // Clean up the memory acquired by the RBuf variable "buffer"
    00196         CleanupStack::PopAndDestroy();
    00197         }
    00198
    00199
    00203 void CCountServSession::Increase()
    00204         {
    00205         iCount++;
    00206         }
    00207
    00208
    00212 void CCountServSession::IncreaseBy(const RMessage2& aMessage)
    00213         {
    00214         iCount = iCount + aMessage.Int0();
    00215         }
    00216
    00220 void CCountServSession::Decrease()
    00221         {
    00222         iCount--;
    00223         }
    00224
    00225
    00229 void CCountServSession::DecreaseBy(const RMessage2& aMessage)
    00230         {
    00231         iCount = iCount - aMessage.Int0();
    00232         }
    00233
    00234
    00238 void CCountServSession::Reset()
    00239         {
    00240         iCount=0;
    00241         }
    00242
    00243
    00248 void CCountServSession::CounterValueL(const RMessage2& aMessage)
    00249         {
    00250         TPckgBuf<TInt> p(iCount);
    00251         aMessage.WriteL(0,p);
    00252         }
    00253
    00254
    00258 void CCountServSession::PanicClient(const RMessage2& aMessage,TInt aPanic) const
    00259         {
    00260         _LIT(KTxtServer,"CountServ server");
    00261         aMessage.Panic(KTxtServer,aPanic);
    00262         }
    00263
    00264
    00265
    00266 //**********************************
    00267 //Global functions
    00268 //**********************************
    00269
    00270 // The count server thread function that initialises the server.
    00271 GLDEF_C TInt CCountServServer::ThreadFunction(TAny* )
    00272         {
    00273           // get clean-up stack
    00274         CTrapCleanup* cleanup=CTrapCleanup::New();
    00275         if (cleanup == NULL)
    00276             {
    00277                 CCountServServer::PanicServer(ECreateTrapCleanup);
    00278             }
    00279
    00280           // create an active scheduler and server
    00281         CActiveScheduler *pA=new CActiveScheduler;
    00282         __ASSERT_ALWAYS(pA!=NULL,CCountServServer::PanicServer(EMainSchedulerError));
    00283         CCountServServer *pS=new CCountServServer(EPriorityStandard);
    00284         __ASSERT_ALWAYS(pS!=NULL,CCountServServer::PanicServer(ESvrCreateServer));
    00285
    00286           //Install the active scheduler
    00287         CActiveScheduler::Install(pA);
    00288
    00289           // Start the server
    00290         TInt err = pS->Start(KCountServerName);
    00291         if (err != KErrNone)
    00292             {
    00293                 CCountServServer::PanicServer(ESvrStartServer);
    00294             }
    00295
    00296       // Let everyone know that we are ready to
    00297       // deal with requests.
    00298     RThread::Rendezvous(KErrNone);
    00299
    00300           // And start fielding requests from client(s).
    00301         CActiveScheduler::Start();
    00302
    00303       // Tidy up...
    00304     delete pS;
    00305     delete pA;
    00306     delete cleanup;
    00307
    00308           // ...although we should never get here!
    00309         return(KErrNone);
    00310         }
    00311
    00312
    00320 EXPORT_C TInt StartThread(RThread& aServerThread)
    00321     {
    00322         TInt res=KErrNone;
    00323
    00324           // Create the server, if one with this name does not already exist.
    00325         TFindServer findCountServer(KCountServerName);
    00326         TFullName   name;
    00327
    00328           // Need to check that the server exists.
    00329         if (findCountServer.Next(name)!=KErrNone)
    00330                 {
    00331                   // Create the thread for the server.
    00332                 res=aServerThread.Create(KCountServerName,
    00333                         CCountServServer::ThreadFunction,
    00334                         KDefaultStackSize,
    00335                         KDefaultHeapSize,
    00336                         KDefaultHeapSize,
    00337                         NULL
    00338                         );
    00339
    00340           // The thread has been created OK so get it started - however
    00341           // we need to make sure that it has started before we continue.
    00342                 if (res==KErrNone)
    00343                         {
    00344                         TRequestStatus rendezvousStatus;
    00345
    00346                         aServerThread.SetPriority(EPriorityNormal);
    00347                         aServerThread.Rendezvous(rendezvousStatus);
    00348                         aServerThread.Resume();
    00349                         User::WaitForRequest(rendezvousStatus);
    00350                         }
    00351
    00352                   // The thread has not been created - clearly there's been a problem.
    00353                 else
    00354                         {
    00355                         aServerThread.Close();
    00356                         }
    00357                 }
    00358     return res;
    00359     }