keepalive/flextimer/server/src/flextimersession.cpp
changeset 32 5c4486441ae6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keepalive/flextimer/server/src/flextimersession.cpp	Mon May 24 20:51:35 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 <e32def.h>
+#include <e32cmn.h>
+#include <hal.h>
+
+// 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<TInt64> ( 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<TInt64> ( static_cast<TReal64> ( 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 );
+    }