diff -r fc7b30ed2058 -r 05bc53fe583b keepalive/flextimer/server/src/flextimersession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keepalive/flextimer/server/src/flextimersession.cpp Tue Aug 31 15:35:44 2010 +0300 @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Nokia Corporation - initial contribution. + * + * Contributors: + * + * Description: Implementation of CFlexTimerSession class. + * + */ +/* + * %version: 1 % + */ + +// System include files +#include +#include +#include + +// User include files go here: +#include "flextimercommon.h" +#include "flextimersession.h" +#include "mflextimerservice.h" +#include "OstTraceDefinitions.h" +#ifdef OST_TRACE_COMPILER_IN_USE +#include "flextimersessionTraces.h" +#endif + +// Constants + +// ======== MEMBER FUNCTIONS ======== + +// -------------------------------------------------------------------------- +// Constructor +// -------------------------------------------------------------------------- +// +CFlexTimerSession::CFlexTimerSession( MFlexTimerService* aFlexTimerService ) +: iService( aFlexTimerService ), + iTimerWinSize( 0 ), + iUseDefaultWin( ETrue ) + { + OstTrace1( TRACE_INTERNAL, + CFLEXTIMERSESSION, + "CFlexTimerSession::CFlexTimerSession; this=%x", + ( TUint )this ); + } + +// -------------------------------------------------------------------------- +// Destructor +// -------------------------------------------------------------------------- +// +CFlexTimerSession::~CFlexTimerSession() + { + OstTrace1( TRACE_INTERNAL, + CFLEXTIMERSESSIOND, + "CFlexTimerSession::~CFlexTimerSession; this=%x", + ( TUint )this ); + } + +// -------------------------------------------------------------------------- +// Function called from CFlexTimerService::RunL for messages targeted to +// this session +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::ServiceL( const RMessage2& aMessage ) + { + TInt msgType( aMessage.Function() ); + + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_MSG, + "CFlexTimerSession::ServiceL; this=%x; msgType=%d", + ( TInt )this, + msgType ); + + // Check message type and pass it to correct handler. Handler either + // stores the message or completes it immediately. + switch ( msgType ) + { + case EFlexTimerServCancelRequest: + CancelTimer( aMessage ); + break; + case EFlexTimerServAtRequest: + NewAtTimer( aMessage ); + break; + case EFlexTimerServAtUTCRequest: + NewAtUtcTimer( aMessage ); + break; + case EFlexTimerServAfterRequest: + NewAfterTimer( aMessage ); + break; + case EFlexTimerServAfterTicksRequest: + NewAfterTicksTimer( aMessage ); + break; + case EFlexTimerServConfigureRequest: + ConfigureParameters( aMessage ); + break; + default: + OstTrace1( + TRACE_INTERNAL, + CFLEXTIMERSESSION_ERROR, + "CFlexTimerSession::ServiceL: Unknown message; this=%x", + ( TUint )this ); + aMessage.Complete( KErrNotSupported ); + } + } + +// -------------------------------------------------------------------------- +// Timeout handler for triggering timers +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::Timeout() const + { + // Check for the validity of pending timeout request + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_TIMEOUT, + "CFlexTimerSession::Timeout; this=%x; msg=%x", + ( TUint )this, + ( TUint )iPendingTimeoutMsg.Handle() ); + // Complete message, this sets message pointer to NULL + iPendingTimeoutMsg.Complete( KErrNone ); + } + else + { + // No valid message pointer, nothing we can do here + OstTrace1( TRACE_INTERNAL, + CFLEXTIMERSESSION_TIMEOUT_ERROR, + "CFlexTimerSession::Timeout: No Pending message; this=%x", + ( TUint )this ); + } + } + +// -------------------------------------------------------------------------- +// Function for aborting At-timer +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::Abort( TInt aReason ) const + { + // Check for the validity of pending timeout request + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_ABORT, + "CFlexTimerSession::Abort; this=%x; msg=%x", + ( TUint )this, + ( TUint )iPendingTimeoutMsg.Handle() ); + // Complete message, this sets message pointer to NULL + iPendingTimeoutMsg.Complete( aReason ); + } + else + { + // No valid message pointer, nothing we can do here + OstTrace1( + TRACE_INTERNAL, + CFLEXTIMERSESSION_ABORT_ERROR, + "CFlexTimerSession::Abort: No Pending message; this=%x", + ( TUint )this ); + + } + } + +// -------------------------------------------------------------------------- +// Handler function for starting At() -timer +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::NewAtTimer( const RMessage2& aMessage ) + { + + // Check that we do not have a pending timer request + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_ATPANIC, + "CFlexTimerSession::NewAtTimer: Already pending; " + "this=%x; msg=%x", + ( TUint )this, + ( TUint )iPendingTimeoutMsg.Handle() ); + + aMessage.Panic( KRFlexTimerPanicCat, + EFlexTimerServerErrorPendingTimer ); + return; + } + + // Get interval from current time to the requested timestamp + TTime refTime; + refTime.HomeTime(); + TTimeIntervalMicroSeconds interval; + GetIntervalToMsgTime( aMessage, refTime, interval ); + + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_ATTIMER, + "CFlexTimerSession::NewAtTimer; this=%x; interval=%lld", + ( TUint )this, + interval.Int64() ); + + // Add the timer to engine + DoAddTimer( aMessage, interval, ETrue ); + + } + +// -------------------------------------------------------------------------- +// Handler function for starting AtUTC() -timer +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::NewAtUtcTimer( const RMessage2& aMessage ) + { + + // Check that we do not have a pending timer request + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_ATUTCPANIC, + "CFlexTimerSession::NewAtUtcTimer: Already pending; " + "this=%x; msg=%x", + ( TUint )this, + ( TUint )iPendingTimeoutMsg.Handle() ); + + aMessage.Panic( KRFlexTimerPanicCat, + EFlexTimerServerErrorPendingTimer ); + return; + } + + TTime refTime; + refTime.UniversalTime(); + TTimeIntervalMicroSeconds interval; + GetIntervalToMsgTime( aMessage, refTime, interval ); + + OstTraceExt2( + TRACE_INTERNAL, + CFLEXTIMERSESSION_ATUTCTIMER, + "CFlexTimerSession::NewAtUtcTimer; this=%x; interval=%lld", + ( TUint )this, + interval.Int64() ); + + // Add the timer to engine + DoAddTimer( aMessage, interval, ETrue ); + + } + +// -------------------------------------------------------------------------- +// Handler function for starting After()-timer +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::NewAfterTimer( const RMessage2& aMessage ) + { + + // Check that we do not have a pending timer request + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_AFTERPANIC, + "CFlexTimerSession::NewAfterTimer: Already pending; " + "this=%x; msg=%x", + ( TUint )this, + ( TUint )iPendingTimeoutMsg.Handle() ); + + aMessage.Panic( KRFlexTimerPanicCat, + EFlexTimerServerErrorPendingTimer ); + return; + } + + TInt64 timeStamp = MAKE_TINT64( aMessage.Int1(), aMessage.Int0() ); + TTimeIntervalMicroSeconds interval( timeStamp ); + + OstTraceExt2( + TRACE_INTERNAL, + CFLEXTIMERSESSION_AFTERTIMER, + "CFlexTimerSession::NewAfterTimer; this=%x; interval=%llu", + ( TUint )this, + interval.Int64() ); + + // Add the timer to engine, request cancellation if the secure time + // is not available + DoAddTimer( aMessage, interval, EFalse ); + } + +// -------------------------------------------------------------------------- +// Handler function for starting AfterTicks()-timer +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::NewAfterTicksTimer( const RMessage2& aMessage ) + { + + // Check that we do not have a pending timer request + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTraceExt2( + TRACE_INTERNAL, + CFLEXTIMERSESSION_AFTERTICKSPANIC, + "CFlexTimerSession::NewAfterTicksTimer: Already pending; " + "this=%x; msg=%x", + ( TUint )this, + ( TUint )iPendingTimeoutMsg.Handle() ); + + aMessage.Panic( KRFlexTimerPanicCat, + EFlexTimerServerErrorPendingTimer ); + return; + } + + // Get the tick period from HAL and convert ticks to microseconds + TInt tickUs; + HAL::Get( HAL::ESystemTickPeriod, tickUs ); + + TTimeIntervalMicroSeconds interval = + static_cast ( aMessage.Int0() ) * tickUs; + + OstTraceExt2( + TRACE_INTERNAL, + CFLEXTIMERSESSION_AFTERTICKSTIMER, + "CFlexTimerSession::NewAfterTicksTimer; this=%x; interval=%llu", + ( TUint )this, + interval.Int64() ); + + // Add the timer to engine + DoAddTimer( aMessage, interval, EFalse ); + } + +// -------------------------------------------------------------------------- +// Handler function for cancelling running timer +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::CancelTimer( const RMessage2& aMessage ) + { + TInt ret; + // Check that we have a pending timer request + if ( iPendingTimeoutMsg.IsNull() ) + { + OstTrace1( + TRACE_INTERNAL, + CFLEXTIMERSESSION_CANCELERROR, + "CFlexTimerSession::CancelTimer: no pending msg; this=%x", + ( TUint )this ); + ret = KErrNotFound; + } + else + { + ret = iService->CancelTimer( this ); + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_CANCEL, + "CFlexTimerSession::CancelTimer; this=%x; ret=%d", + ( TUint )this, + ret ); + + // Complete pending message, this sets message pointer to NULL + iPendingTimeoutMsg.Complete( KErrCancel ); + } + + // Complete cancel message + aMessage.Complete( ret ); + } + +// -------------------------------------------------------------------------- +// Handler function for configuring timer parameters +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::ConfigureParameters( const RMessage2& aMessage ) + { + TInt ret( KErrNone ); + + // Configuration is not allowed when there is a pending message + if ( !iPendingTimeoutMsg.IsNull() ) + { + OstTrace1( TRACE_INTERNAL, + CFLEXTIMERSESSION_CONFIGERROR, + "CFlexTimerSession::ConfigureParameters: Timer pending; " + "this=%x", + ( TUint )this ); + ret = KErrInUse; + } + else + { + TInt paramType( aMessage.Int0() ); + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_CONFIG, + "CFlexTimerSession::ConfigureParameters; this=%x; " + "paramType=%d", + ( TUint )this, + paramType ); + + switch ( paramType ) + { + case EConfigureRequestWindowSize: + { + TInt winLo = aMessage.Int1(); + TInt winHi = aMessage.Int2(); + + iTimerWinSize = MAKE_TINT64( winHi, winLo ); + iUseDefaultWin = EFalse; + + OstTraceExt1( TRACE_INTERNAL, + CFLEXTIMERSESSION_CONFIGWIN, + "CFlexTimerSession::ConfigureParameters; " + "iTimerWinSize=%lld", + iTimerWinSize.Int64() ); + + if ( iTimerWinSize.Int64() < 0 || + iTimerWinSize.Int64() > KFlexTimerMaxTimerLength ) + { + aMessage.Panic( KRFlexTimerPanicCat, + EFlexTimerServerIllegalTimerValue ); + // Return after panicing the client -- completing the + // message afterwards panics the server with USER 70. + return; + } + break; + } + default: + OstTrace0( TRACE_INTERNAL, + CFLEXTIMERSESSION_CONFIGUNKNOWN, + "CFlexTimerSession::ConfigureParameters: " + "ERROR - Invalid parameter type" ); + ret = KErrNotSupported; + break; + } + } + aMessage.Complete( ret ); + } + +// -------------------------------------------------------------------------- +// Function for adding timer to engine and handling its return value +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::DoAddTimer( const RMessage2& aMessage, + TTimeIntervalMicroSeconds& aWinEnd, + TBool aRequestAbort ) + { + OstTraceExt4( TRACE_INTERNAL, + CFLEXTIMERSESSION_ADDTIMER, + "CFlexTimerSession::DoAddTimer; this=%x; msg=%x; aWinEnd=%llu;" + " aRequestAbort=%d", + ( TUint )this, + ( TUint )aMessage.Handle(), + aWinEnd.Int64(), + aRequestAbort ); + + // Check that the timer has valid values. + if ( aWinEnd.Int64() < 0 || aWinEnd.Int64() > KFlexTimerMaxTimerLength) + { + OstTraceExt4( TRACE_INTERNAL, + CFLEXTIMERSESSION_DOADDTIMER, + "CFlexTimerSession::DoAddTimer;Invalid parameters " + "- panicing client;this=%x;aMessage=%x;aWinEnd=%llu;" + "aRequestAbort=%d", + ( TUint )this, + ( TUint )aMessage.Handle(), + aWinEnd.Int64(), + aRequestAbort ); + aMessage.Panic( KRFlexTimerPanicCat, + EFlexTimerServerIllegalTimerValue ); + return; + } + + TTimeIntervalMicroSeconds winStart; + TTimeIntervalMicroSeconds window = iTimerWinSize; + + if ( iUseDefaultWin ) + { + window = static_cast ( static_cast ( aWinEnd.Int64() ) + * KDefaultWindowMultiplier ); + } + + winStart = aWinEnd.Int64() - window.Int64(); + + // Store pending message. Not completed until timer expires. + // Note that in case of zero or negative timer value, message can + // be completed through Timeout() even before AddTimer returns. This + // implementation saves some checks and timer stopping/starting in engine. + iPendingTimeoutMsg = aMessage; + + // Add timer to engine + TInt ret = iService->AddTimer( winStart, aWinEnd, aRequestAbort, this ); + + if ( KErrNone != ret ) + { + // Failed, pass error code to client side + OstTraceExt2( TRACE_INTERNAL, + CFLEXTIMERSESSION_ADDERROR, + "CFlexTimerSession::DoAddTimer: Error; this=%x, ret=%d", + ( TUint )this, + ret ); + // Complete pending message, this sets message pointer to NULL + iPendingTimeoutMsg.Complete( ret ); + } + } + +// -------------------------------------------------------------------------- +// From CSession2 +// Function for handling unintentional termination of the client +// -------------------------------------------------------------------------- +// +void CFlexTimerSession::Disconnect( const RMessage2 &aMessage ) + { + // The client of this session has died. + + // Remove timer from engine. + iService->CancelTimer( this ); + + // Disconnect() must end with a call to the base class implementation, + // which will delete the session object and complete the disconnect + // message. + CSession2::Disconnect( aMessage ); + }