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

Generated by  doxygen 1.6.2