00001 /* 00002 * ============================================================================== 00003 * Name : timeserver.cpp 00004 * Part of : CSAsync 00005 * Interface : 00006 * Description : 00007 * Version : 00008 * 00009 * Copyright (c) 2004-2006 Nokia Corporation. 00010 * This material, including documentation and any related 00011 * computer programs, is protected by copyright controlled by 00012 * Nokia Corporation. 00013 * ============================================================================== 00014 */ 00015 00016 00017 // INCLUDE FILES 00018 #include <e32svr.h> 00019 #include <e32math.h> 00020 00021 #include "TimeServer.h" 00022 #include "ClientServerCommon.h" 00023 #include "TimeSession.h" 00024 00025 // ========================= MEMBER FUNCTIONS ================================== 00026 00027 // ----------------------------------------------------------------------------- 00028 // CTimeServer::NewL() 00029 // Two-phased constructor. 00030 // ----------------------------------------------------------------------------- 00031 // 00032 CTimeServer* CTimeServer::NewL() 00033 { 00034 CTimeServer* timeServer = CTimeServer::NewLC(); 00035 CleanupStack::Pop( timeServer ); 00036 return timeServer; 00037 } 00038 00039 // ----------------------------------------------------------------------------- 00040 // CTimeServer::NewLC() 00041 // Two-phased constructor. 00042 // ----------------------------------------------------------------------------- 00043 // 00044 CTimeServer* CTimeServer::NewLC() 00045 { 00046 CTimeServer* timeServer = new ( ELeave ) CTimeServer( EPriorityNormal ); 00047 CleanupStack::PushL( timeServer ); 00048 timeServer->ConstructL(); 00049 return timeServer; 00050 } 00051 00052 // ----------------------------------------------------------------------------- 00053 // CTimeServer::ConstructL() 00054 // Symbian 2nd phase constructor can leave. 00055 // ----------------------------------------------------------------------------- 00056 // 00057 void CTimeServer::ConstructL() 00058 { 00059 StartL( KTimeServerName ); 00060 } 00061 00062 // ----------------------------------------------------------------------------- 00063 // CTimeServer::CTimeServer() 00064 // C++ default constructor can NOT contain any code, that might leave. 00065 // ----------------------------------------------------------------------------- 00066 // 00067 CTimeServer::CTimeServer( TInt aPriority ) 00068 : CServer2( aPriority ) 00069 { 00070 // Implementation not required 00071 } 00072 00073 // ----------------------------------------------------------------------------- 00074 // CTimeServer::~CTimeServer() 00075 // Destructor. 00076 // ----------------------------------------------------------------------------- 00077 // 00078 CTimeServer::~CTimeServer() 00079 { 00080 delete iHeartbeat; 00081 iHeartbeat = NULL; 00082 } 00083 00084 // ----------------------------------------------------------------------------- 00085 // CTimeServer::NewSessionL() 00086 // Creates a time server session. 00087 // ----------------------------------------------------------------------------- 00088 // 00089 CSession2* CTimeServer::NewSessionL( const TVersion& aVersion, 00090 const RMessage2& /*aMessage*/ ) const 00091 { 00092 // Check we are the right version 00093 if ( !User::QueryVersionSupported( TVersion( KTimeServMajorVersionNumber, 00094 KTimeServMinorVersionNumber, 00095 KTimeServBuildVersionNumber ), 00096 aVersion ) ) 00097 { 00098 User::Leave( KErrNotSupported ); 00099 } 00100 00101 // Make new session 00102 //RThread client = Message().Client(); 00103 return CTimeServerSession::NewL( *const_cast<CTimeServer*> ( this ) ); 00104 } 00105 00106 // ----------------------------------------------------------------------------- 00107 // CTimeServer::IncrementSessions() 00108 // Increments the count of the active sessions for this server. 00109 // ----------------------------------------------------------------------------- 00110 // 00111 void CTimeServer::IncrementSessions() 00112 { 00113 iSessionCount++; 00114 } 00115 00116 // ----------------------------------------------------------------------------- 00117 // CTimeServer::DecrementSessions() 00118 // Decrements the count of the active sessions for this server. 00119 // ----------------------------------------------------------------------------- 00120 // 00121 void CTimeServer::DecrementSessions() 00122 { 00123 iSessionCount--; 00124 if ( iSessionCount <= 0 ) 00125 { 00126 CActiveScheduler::Stop(); 00127 } 00128 } 00129 00130 // ----------------------------------------------------------------------------- 00131 // CTimeServer::RunError() 00132 // Processes any errors. 00133 // ----------------------------------------------------------------------------- 00134 // 00135 TInt CTimeServer::RunError( TInt aError ) 00136 { 00137 if ( aError == KErrBadDescriptor ) 00138 { 00139 // A bad descriptor error implies a badly programmed client, 00140 // so panic it; otherwise report the error to the client 00141 PanicClient( Message(), EBadDescriptor ); 00142 } 00143 else 00144 { 00145 Message().Complete( aError ); 00146 } 00147 00148 // The leave will result in an early return from CServer::RunL(), skipping 00149 // the call to request another message. So do that now in order to keep the 00150 // server running. 00151 ReStart(); 00152 00153 return KErrNone; // Handled the error fully 00154 } 00155 00156 // ----------------------------------------------------------------------------- 00157 // CTimeServer::PanicClient() 00158 // Panics the client. 00159 // ----------------------------------------------------------------------------- 00160 // 00161 void CTimeServer::PanicClient( const RMessage2& aMessage, TTimeServPanic aPanic ) 00162 { 00163 aMessage.Panic( KCSAsyncServer, aPanic ); 00164 } 00165 00166 // ----------------------------------------------------------------------------- 00167 // CTimeServer::PanicServer() 00168 // Panics the server. 00169 // ----------------------------------------------------------------------------- 00170 // 00171 void CTimeServer::PanicServer( TTimeServPanic aPanic ) 00172 { 00173 User::Panic( KCSAsyncServer, aPanic ); 00174 } 00175 00176 // ----------------------------------------------------------------------------- 00177 // CTimeServer::WaitForTickL() 00178 // Activates the heartbeat. 00179 // ----------------------------------------------------------------------------- 00180 // 00181 void CTimeServer::WaitForTickL() 00182 { 00183 if ( !iHeartbeat ) 00184 { 00185 iHeartbeat = CHeartbeat::NewL( EPriorityHigh ); 00186 iHeartbeat->Start( ETwelveOClock, this ); 00187 } 00188 } 00189 00190 // ----------------------------------------------------------------------------- 00191 // CTimeServer::Beat() 00192 // A clock tick has occured. 00193 // ----------------------------------------------------------------------------- 00194 // 00195 void CTimeServer::Beat() 00196 { 00197 SendTimeToSessions(); 00198 } 00199 00200 // ----------------------------------------------------------------------------- 00201 // CTimeServer::Synchronize() 00202 // Several clock ticks have occured. 00203 // ----------------------------------------------------------------------------- 00204 // 00205 void CTimeServer::Synchronize() 00206 { 00207 SendTimeToSessions(); 00208 } 00209 00210 // ----------------------------------------------------------------------------- 00211 // CTimeServer::SendTimeToSessions() 00212 // Informs all the clients that a time change has occured. 00213 // ----------------------------------------------------------------------------- 00214 // 00215 void CTimeServer::SendTimeToSessions() 00216 { 00217 iSessionIter.SetToFirst(); 00218 CTimeServerSession* session; 00219 session = reinterpret_cast<CTimeServerSession*>( iSessionIter++ ); 00220 while ( session ) 00221 { 00222 session->SendTimeToClient(); 00223 session = reinterpret_cast<CTimeServerSession*>( iSessionIter++ ); 00224 } 00225 } 00226 00227 // ----------------------------------------------------------------------------- 00228 // CTimeServer::ThreadFunctionL() 00229 // Second stage startup for the server thread. 00230 // ----------------------------------------------------------------------------- 00231 // 00232 void CTimeServer::ThreadFunctionL() 00233 { 00234 // Construct active scheduler 00235 CActiveScheduler* activeScheduler = new ( ELeave ) CActiveScheduler; 00236 CleanupStack::PushL( activeScheduler ); 00237 00238 // Install active scheduler 00239 // We don't need to check whether an active scheduler is already installed 00240 // as this is a new thread, so there won't be one 00241 CActiveScheduler::Install( activeScheduler ); 00242 00243 // Construct our server 00244 CTimeServer::NewLC(); // Anonymous 00245 00246 RSemaphore semaphore; 00247 User::LeaveIfError( semaphore.OpenGlobal( KTimeServerSemaphoreName ) ); 00248 00249 // Semaphore opened ok 00250 semaphore.Signal(); 00251 semaphore.Close(); 00252 00253 // Start handling requests 00254 CActiveScheduler::Start(); 00255 00256 CleanupStack::PopAndDestroy( 2, activeScheduler ); //Anonymous CTimeServer 00257 } 00258 00259 // ----------------------------------------------------------------------------- 00260 // CTimeServer::ThreadFunction() 00261 // Main function for the server thread. 00262 // ----------------------------------------------------------------------------- 00263 // 00264 TInt CTimeServer::ThreadFunction( TAny* /*aNone*/ ) 00265 { 00266 CTrapCleanup* cleanupStack = CTrapCleanup::New(); 00267 if ( !( cleanupStack ) ) 00268 { 00269 PanicServer( ECreateTrapCleanup ); 00270 } 00271 00272 TRAPD( err, ThreadFunctionL() ); 00273 if ( err != KErrNone ) 00274 { 00275 PanicServer( ESrvCreateServer ); 00276 } 00277 00278 delete cleanupStack; 00279 cleanupStack = NULL; 00280 00281 return KErrNone; 00282 } 00283 00284 00285 // ----------------------------------------------------------------------------- 00286 // E32Main() 00287 // Provides the API for the operating system to start the executable. 00288 // Returns the address of the function to be called. 00289 // ----------------------------------------------------------------------------- 00290 // 00291 TInt E32Main() 00292 { 00293 return CTimeServer::ThreadFunction( NULL ); 00294 } 00295 00296 00297 00298 // End of File