diff -r 7e41d162e158 -r abbed5a4b42a networkcontrol/ipcprshim/src/shimclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkcontrol/ipcprshim/src/shimclient.cpp Tue Aug 31 16:45:15 2010 +0300 @@ -0,0 +1,733 @@ +// Copyright (c) 2005-2009 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: +// This is part of an ECOM plug-in +// +// + +#include +#include "shimnifmansconn.h" +#include "es_prot.h" + + +/** +@internalComponent +*/ +const TUint KMicrosecondsInASecond = 1000000; +const TInt KMaxTimerPeriod = KMaxTInt32/KMicrosecondsInASecond; //< max period of a CTimer using After() + + +CSubConnectionLinkShimClient::CSubConnectionLinkShimClient(const CConnection& aConnection, CNifManSubConnectionShim& aSubConnectionShim) : + iConnection(aConnection), + iSubConnectionShim(aSubConnectionShim), + iOutstandingProgressNotification(EFalse), + iOutstandingDataSentNotification(EFalse), + iOutstandingDataReceivedNotification(EFalse), + iOutstandingSubConnectionActivity(EFalse) +/** +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tCSubConnectionLinkShimClient() created for id %d, iConnection %08x"), + this, aSubConnectionShim.Id(), &iConnection)); + } + +CSubConnectionLinkShimClient::~CSubConnectionLinkShimClient() +/** +Complete all outstanding RMessages + +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\t~CSubConnectionLinkShimClient(), id %d, iSubConnectionShim %08x"), + this, iSubConnectionShim.Id(), this, &iSubConnectionShim)); + + if(iActivityTimer) + { + iActivityTimer->Cancel(); + delete iActivityTimer; + iActivityTimer = NULL; + } + + if(iOutstandingProgressNotification) + iOutstandingProgressNotificationMessage.Complete(KErrCancel); + if(iOutstandingDataSentNotification) + iOutstandingDataSentNotificationMessage.Complete(KErrCancel); + if(iOutstandingDataReceivedNotification) + iOutstandingDataReceivedNotificationMessage.Complete(KErrCancel); + if(iOutstandingSubConnectionActivity) + iOutstandingSubConnectionActivityMessage.Complete(KErrCancel); + if (iSubConnectionShim.DataTransferShim()) + { + iSubConnectionShim.DataTransferShim()->DeRegisterClient(*this); + } + } + +TBool CSubConnectionLinkShimClient::Match(const CConnection& aConnection) const + { + return &iConnection == &aConnection; + } + +TSubConnectionUniqueId CSubConnectionLinkShimClient::Id() + { + return iSubConnectionShim.Id(); + } + +TInt CSubConnectionLinkShimClient::ReturnCode() const + { + return iReturnCode; + } + +TInt CSubConnectionLinkShimClient::GetCurrentProgress(TNifProgress& aProgress) +/** +Return the current progress state + +@param aProgress On return, contains the current progress from the subconnection +@return KErrNone if successful; otherwise one of the system-wide error codes +*/ + { + aProgress = iCurrentProgress; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tGetCurrentProgress() => (%d, %d)"), + this, aProgress.iStage, aProgress.iError)); + return KErrNone; + } + +TBool CSubConnectionLinkShimClient::StopL(const RMessage2& aMessage) + { + TInt stopCode = 0; + RConnection::TConnStopType stopType = static_cast(aMessage.Int1()); + switch (stopType) + { + case RConnection::EStopNormal: + stopCode = KErrCancel; + break; + case RConnection::EStopAuthoritative: + stopCode = KErrConnectionTerminated; + break; + default: + stopCode = KErrCancel; // to remove compile warning + User::Leave(KErrArgument); + } + + TInt ret = iSubConnectionShim.Provider().Stop(iSubConnectionShim.Id(), stopCode, &aMessage); + if (ret != KErrNone) + { + User::Leave(ret); + } + return ETrue; + } + +TBool CSubConnectionLinkShimClient::DataTransferredL(const RMessage2& aMessage) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataTransferredL(), id %d"), + this, iSubConnectionShim.Id())); + + TUint uplinkDataVolume; + TUint downlinkDataVolume; + + TInt ret = iSubConnectionShim.DataTransferShim()->DataTransferred(uplinkDataVolume, downlinkDataVolume); + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataTransferredL(), ret %d, uplink %d, downlink %d"), + this, ret, uplinkDataVolume, downlinkDataVolume)); + + if (KErrNone == ret) + { + TPckg uplinkDataVolumePckg(uplinkDataVolume); + TPckg downlinkDataVolumePckg(downlinkDataVolume); + + aMessage.WriteL(1, uplinkDataVolumePckg); + aMessage.WriteL(2, downlinkDataVolumePckg); + } + SetReturnCode(ret); + return ETrue; + } + +TBool CSubConnectionLinkShimClient::DataTransferredCancel(const RMessage2& /*aMessage*/) + { + return ETrue; + } + +TBool CSubConnectionLinkShimClient::RequestSubConnectionProgressNotificationL(const RMessage2& aMessage) +/** +Request from client for notification of new progress + +@pre No outstanding request for data sent notifications for this subconnection on this RConnection +@param aMessage The client message +@return ETrue if the client message is to be completed immediately +@leave leaves with KErrInUse if there is already an outstanding RMessage for progress notification +*/ + { + if(iOutstandingProgressNotification) + User::Leave(KErrInUse); + + TInt clientRequestedProgress = 0; + clientRequestedProgress = static_cast(aMessage.Int2()); + // if - the last progress we sent to the client differs from the current one + // and - the current progress is the same as the client requested progress OR + // the client has no requested progress... + if(iLastProgressToClient!=iCurrentProgress.iStage && + (iCurrentProgress.iStage == clientRequestedProgress || clientRequestedProgress==0)) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tRequestSubConnectionProgressNotificationL() returning progress (%d, %d)"), + this, iCurrentProgress.iStage, iCurrentProgress.iError)); + + // ...send the current progress back + TPckg prog(iCurrentProgress); + aMessage.WriteL(1, prog); + return ETrue; + } + else // store the client message until the next progress value arrives + { + //__FLOG_STATIC1(_L("ESock: "), _L("CSubConnectionLinkShimClient"), + // _L("[id: %d]: client requested progress notification; storing client message for later completion"), + // iSubConnectionsUniqueId); + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tRequestSubConnectionProgressNotificationL() storing client message for later completion"), this)); + + iClientRequestedProgress = clientRequestedProgress; // may be 0 + iOutstandingProgressNotificationMessage = aMessage; + iOutstandingProgressNotification = ETrue; + return EFalse; + } + } + +TBool CSubConnectionLinkShimClient::CancelSubConnectionProgressNotification(const RMessage2& /*aMessage*/) +/** +Complete outstanding progress notification RMessage + +@param aMessage The client message +@return ETrue if the client message is to be completed immediately +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tCancelSubConnectionProgressNotification(), id %d, iSubConnectionShim %08x"), + iSubConnectionShim.Id(), this)); + + if(iOutstandingProgressNotification) + { + iOutstandingProgressNotificationMessage.Complete(KErrCancel); + iOutstandingProgressNotification = EFalse; + } + return ETrue; + } + +TBool CSubConnectionLinkShimClient::DataSentNotificationRequestL(const RMessage2& aMessage) +/** +Request notification when the specified (absolute or relative) volume of data has been sent + +@pre No outstanding request for data sent notifications for this subconnection on this RConnection +@param aMessage The client message +@return ETrue if the client message is to be completed immeadiately +@leave leaves with KErrInUse if there is already an outstanding RMessage for data sent notification +*/ + { + if(iOutstandingDataSentNotification) + User::Leave(KErrInUse); + + TUint requestedUplinkGranularity = static_cast(aMessage.Int1()); + if(requestedUplinkGranularity) // the client is working in relative mode + { + iRemainingUplinkGranularity = requestedUplinkGranularity; + iDataSentNotificationsInAbsoluteMode = EFalse; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataSentNotificationRequestL(), id %d (relative mode: %d bytes)"), + this, iSubConnectionShim.Id(), iRemainingUplinkGranularity)); + } + else // the client is working in absolute mode + { + TPckg iUplinkVolumeBuf(iUplinkDataNotificationVolume); + aMessage.ReadL(2, iUplinkVolumeBuf); + iDataSentNotificationsInAbsoluteMode = ETrue; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataSentNotificationRequestL() id %d (absolute mode: %d bytes)"), + this, iSubConnectionShim.Id(), iUplinkDataNotificationVolume)); + + if(iUplinkDataNotificationVolume >= iUplinkDataVolume) // we've already sent this amount of data + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataSentNotificationRequestL() id %d (completed immediately"), + this, iSubConnectionShim.Id())); + return ETrue; + } + } + + iOutstandingDataSentNotificationMessage = aMessage; + iOutstandingDataSentNotification = ETrue; + + iSubConnectionShim.DataTransferShim()->DataSentNotificationRequest(requestedUplinkGranularity, iUplinkDataNotificationVolume); + + return EFalse; + } + +TBool CSubConnectionLinkShimClient::DataSentNotificationCancel(const RMessage2& /*aMessage*/) +/** +Complete outstanding data sent notification RMessage + +@param aMessage The client message +@return ETrue if the client message is to be completed immediately +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataSentNotificationCancel() id %d"), + this, iSubConnectionShim.Id())); + iSubConnectionShim.DataTransferShim()->DataSentNotificationCancel(); + + if(iOutstandingDataSentNotification) + { + iOutstandingDataSentNotificationMessage.Complete(KErrCancel); + iOutstandingDataSentNotification= EFalse; + } + return ETrue; + } + +TBool CSubConnectionLinkShimClient::DataReceivedNotificationRequestL(const RMessage2& aMessage) +/** +Request notification when the specified (absolute or relative) volume of data has been sent + +@pre No outstanding request for data sent notifications for this subconnection on this RConnection +@param aMessage The client message +@return ETrue if the client message is to be completed immediately +@leave leaves with KErrInUse if there is already an outstanding RMessage for data received notification +*/ + { + + if(iOutstandingDataReceivedNotification) + User::Leave(KErrInUse); + + TUint requestedDownlinkGranularity = static_cast(aMessage.Int1()); + if(requestedDownlinkGranularity) // the client is working in relative mode + { + iRemainingDownlinkGranularity = requestedDownlinkGranularity; + iDataReceivedNotificationsInAbsoluteMode = EFalse; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataReceivedNotificationRequestL() id %d (relative mode: %d bytes)"), + this, iSubConnectionShim.Id(), iRemainingDownlinkGranularity)); + } + else // the client is working in absolute mode + { + TPckg iDownlinkVolumeBuf(iDownlinkDataNotificationVolume); + aMessage.ReadL(2, iDownlinkVolumeBuf); + iDataReceivedNotificationsInAbsoluteMode = ETrue; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataReceivedNotificationRequestL() id %d (absolute mode: %d bytes)"), + this, iSubConnectionShim.Id(), iDownlinkDataNotificationVolume)); + + if(iDownlinkDataNotificationVolume >= iDownlinkDataVolume) // we've already received this amount of data + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataReceivedNotificationRequestL() id %d(completed immediately)"), + this, iSubConnectionShim.Id())); + return ETrue; + } + } + + iOutstandingDataReceivedNotificationMessage = aMessage; + iOutstandingDataReceivedNotification = ETrue; + + iSubConnectionShim.DataTransferShim()->DataReceivedNotificationRequest(requestedDownlinkGranularity, iDownlinkDataNotificationVolume); + + return EFalse; + } + +TBool CSubConnectionLinkShimClient::DataReceivedNotificationCancel(const RMessage2& /*aMessage*/) +/** +Complete outstanding data received notification RMessage + +@param aMessage The client message +@return ETrue if the client message is to be completed immediately +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tDataReceivedNotificationCancel() id %d"), + this, iSubConnectionShim.Id())); + + iSubConnectionShim.DataTransferShim()->DataReceivedNotificationCancel(); + + if(iOutstandingDataReceivedNotification) + { + iOutstandingDataReceivedNotificationMessage.Complete(KErrCancel); + iOutstandingDataReceivedNotification = EFalse; + } + return ETrue; + } + +TBool CSubConnectionLinkShimClient::IsSubConnectionActiveRequestL(const RMessage2& aMessage) +/** +Indicate whether the subconnection is active or not + +@note Checks at a period defined in the RMessage +@note Only returns when the state varies from that provided by the client +@param aMessage The client message +@return ETrue if the client message is to be completed immediately +*/ + { + if(iOutstandingSubConnectionActivity) + User::Leave(KErrInUse); + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tIsSubConnectionActiveRequestL() id %d"), + this, iSubConnectionShim.Id())); + + // Create the activity timer if it doesn't already exist (from a previous request) + if(!iActivityTimer) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tIsSubConnectionActiveRequestL() id %d - creating timer"), + this, iSubConnectionShim.Id())); + + iActivityTimer = CActivityTimer::NewL(this, KActivityTimerPriority); + } + + TPckg subConnectionActiveBuf(iClientBelievesSubConnectionActive); + aMessage.ReadL(2, subConnectionActiveBuf); + + iSubConnectionShim.DataTransferShim()->DataTransferred(iPreviousUplinkDataVolume, iPreviousDownlinkDataVolume); + + // get clients request timer period and check validity + TInt timeInSeconds = static_cast(aMessage.Int1()); + if(timeInSeconds > KMaxTimerPeriod) // secs; underlying CTimer limitation + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tIsSubConnectionActiveRequestL() id %d - rejecting timer request (%d secs)"), + this, iSubConnectionShim.Id(), timeInSeconds)); + + SetReturnCode(KErrArgument); + return ETrue; + } + + // store in microsecs + iRequestedClientTimerPeriod = timeInSeconds * KMicrosecondsInASecond; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tIsSubConnectionActiveRequestL() id %d, iClientBelievesSubConnectionActive %d, iRequestedClientTimerPeriod %d - Starting timer."), + this, iSubConnectionShim.Id(), iClientBelievesSubConnectionActive, iRequestedClientTimerPeriod)); + + iOutstandingSubConnectionActivity = ETrue; + iOutstandingSubConnectionActivityMessage = aMessage; + + iActivityTimer->After(iRequestedClientTimerPeriod); + return EFalse; + } + +TBool CSubConnectionLinkShimClient::IsSubConnectionActiveCancel(const RMessage2& /*aMessage*/) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tIsSubConnectionActiveCancel() id %d, connection %08x"), + this, iSubConnectionShim.Id(), &iConnection)); + + if(iOutstandingSubConnectionActivity) + { + iActivityTimer->Cancel(); + ASSERT(iOutstandingSubConnectionActivity); // assert that the timer cancelled rather than completing + iOutstandingSubConnectionActivityMessage.Complete(KErrCancel); + iOutstandingSubConnectionActivity = EFalse; + } + return ETrue; + } + +TInt CSubConnectionLinkShimClient::GetSubConnectionInfo(const RMessage2& aMessage) + { + TUint index = static_cast(aMessage.Int0()); + + TInt result = KErrNone; + TRAP(result, + + // Find the size of the clients descriptor + TInt sizeOfSubConnInfo = aMessage.GetDesLengthL(1); + + // Create an appropriately sized descriptor server-side + HBufC8* subConnectionInfo; + subConnectionInfo = HBufC8::NewL(sizeOfSubConnInfo); + CleanupStack::PushL (subConnectionInfo); + + TPtr8 subConnInfoPtr(subConnectionInfo->Des()); + + // and read the client data across + aMessage.ReadL(1, subConnInfoPtr); + + // Pass it down to the connection provider using the appropriate call + if(index==KUseEmbeddedUniqueId) + { + result = iSubConnectionShim.Provider().GetSubConnectionInfo(subConnInfoPtr); + } + else + { + result = iSubConnectionShim.Provider().GetSubConnectionInfo(index, subConnInfoPtr); + } + + if (KErrNone == result) + { + // Write result back into client's address space + aMessage.WriteL(1, subConnInfoPtr); + } + + CleanupStack::PopAndDestroy (subConnectionInfo); + ); // END TRAP + + SetReturnCode(result); + return ETrue; + } + +void CSubConnectionLinkShimClient::ProgressNotification(TInt aStage, TInt aError, const TDesC8& /*aInfo*/) +/** +Notification of new progress stage from nif/agent via Nifman and CInterface + +@param aStage The progress stage that has been reached +@param aError Any errors that have occured +@param aInfo No idea what this is, it's inserted by CInterface and is currently null +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tProgressNotification(%d, %d) id %d"), + this, aStage, aError, iSubConnectionShim.Id())); + + iCurrentProgress.iStage = aStage; + iCurrentProgress.iError = aError; + + if(iOutstandingProgressNotification) + { + if(iLastProgressToClient!=iCurrentProgress.iStage && /* we could assume this since we've probably just received a new progress value */ + (iCurrentProgress.iStage == iClientRequestedProgress || iClientRequestedProgress==0)) + { + TPckg prog(iCurrentProgress); + TInt err= iOutstandingProgressNotificationMessage.Write(1, prog); + iOutstandingProgressNotificationMessage.Complete(err); + iOutstandingProgressNotification= EFalse; + } + } + } + +TInt CSubConnectionLinkShimClient::NotifyDataSent(TUint aUplinkVolume, TUint aCurrentGranularity) +/** +Upcall from connection provider, via MConnDataTransferNotify. Update the sent bytes count, and if necessary +complete any outstanding RMessages + +@param aUplinkVolume The total number of bytes sent on this subconnection +@note Upcall from CInterface via CConnection +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tNotifyDataSent(aUplinkVolume %d, aCurrentGranularity %d) id %d"), + this, aUplinkVolume, aCurrentGranularity, iSubConnectionShim.Id())); + + iUplinkDataVolume = aUplinkVolume; + + TBool completeMessage = EFalse; + + if(iOutstandingDataSentNotification) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - outstanding client request"), + this, iSubConnectionShim.Id())); + switch(iDataSentNotificationsInAbsoluteMode) + { + case ETrue: + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - %d bytes remaining to be sent before client completion (absolute mode)"), + this, iSubConnectionShim.Id(), (iUplinkDataNotificationVolume - iUplinkDataVolume))); + + if (iUplinkDataVolume >= iUplinkDataNotificationVolume) + { + completeMessage = ETrue; + } + break; + + case EFalse: // in relative mode + iRemainingUplinkGranularity -= aCurrentGranularity; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - %d bytes remaining to be sent before client completion (relative mode)."), + this, iSubConnectionShim.Id(), iRemainingUplinkGranularity)); + + if(iRemainingUplinkGranularity <= 0) + { + completeMessage = ETrue; + } + break; + + default: + break; + } + } + + if(completeMessage) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - completing client request."), + iSubConnectionShim.Id(), this)); + TPckg iUplinkDataVolumePckg(iUplinkDataVolume); + TInt ret= iOutstandingDataSentNotificationMessage.Write(2, iUplinkDataVolumePckg); + iOutstandingDataSentNotificationMessage.Complete(ret); + iOutstandingDataSentNotification= EFalse; + } + return KErrNone; + } + +TInt CSubConnectionLinkShimClient::NotifyDataReceived(TUint aDownlinkVolume, TUint aCurrentGranularity) +/** +Update the received bytes count, and if necessary complete any outstanding RMessages + +@param aDownlinkVolume The total number of bytes sent on this subconnection +@param aCurrentGranularity The currently set granularity of notifications from the CInterface object +@note Upcall from CInterface via CConnection +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tNotifyDataReceived(aDownlinkVolume %d, aCurrentGranularity %d)"), + this, iSubConnectionShim.Id(), aDownlinkVolume, aCurrentGranularity)); + + iDownlinkDataVolume = aDownlinkVolume; + + TBool completeMessage = EFalse; + + if(iOutstandingDataReceivedNotification) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - outstanding client request"), + this, iSubConnectionShim.Id())); + switch(iDataReceivedNotificationsInAbsoluteMode) + { + case ETrue: + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - %d bytes remaining to be sent before client completion (absolute mode)."), + this, iSubConnectionShim.Id(), (iDownlinkDataNotificationVolume - iDownlinkDataVolume))); + + if (iDownlinkDataVolume >= iDownlinkDataNotificationVolume) + { + completeMessage = ETrue; + } + break; + + case EFalse: // in relative mode + iRemainingDownlinkGranularity -= aCurrentGranularity; + + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - %d bytes remaining to be sent before client completion (relative mode)."), + this, iSubConnectionShim.Id(), iRemainingDownlinkGranularity)); + + if(iRemainingDownlinkGranularity <= 0) + { + completeMessage = ETrue; + } + break; + + default: + break; + } + } + + if(completeMessage) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - completing client request."), + this, &iSubConnectionShim)); + TPckg iDownlinkDataVolumePckg(iDownlinkDataVolume); + TInt ret= iOutstandingDataReceivedNotificationMessage.Write(2, iDownlinkDataVolumePckg); + iOutstandingDataReceivedNotificationMessage.Complete(ret); + iOutstandingDataReceivedNotification= EFalse; + } + return KErrNone; + } + +TInt CSubConnectionLinkShimClient::NotifyDataTransferred(const TUint aUplinkVolume, const TUint aDownlinkVolume) +/** +Upcall from CConnection, indicating that it has performed a DataTransferred request and notifying us of the results + +@param aUplinkVolume The total amount of data sent so far on this subconnection +@param aDownlinkVolume The total amount of data received so far on this subconnection +*/ + { + // Update internal data counters, complete any outstanding RMessages if appropriate + // No granularities because we don't know what they are, and because we're taking the + // opportunity of using the client's call to update our counters, ie. it's not an + // actual notification + NotifyDataSent(aUplinkVolume, 0); + NotifyDataReceived(aDownlinkVolume, 0); + return KErrNone; + } + +void CSubConnectionLinkShimClient::CheckSubConnectionActivity() +/** +Check for activity on the subconnection since the last call (to IsSubConnectionActiveRequest() ) + +*/ + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tCheckSubConnectionActivity() id %d"), + this, iSubConnectionShim.Id())); + + ASSERT(iOutstandingSubConnectionActivity); + + TUint newUplinkDataVolume; + TUint newDownlinkDataVolume; + + iSubConnectionShim.DataTransferShim()->DataTransferred(newUplinkDataVolume, newDownlinkDataVolume); + + TBool dataTransferred = (newUplinkDataVolume!=iPreviousUplinkDataVolume) || + (newDownlinkDataVolume!=iPreviousDownlinkDataVolume); + + // If the data transferred volumes haven't change but the client thinks the connection is active... + if(iClientBelievesSubConnectionActive) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - client believes subconnection active"), + this, iSubConnectionShim.Id())); + + if(dataTransferred) // ...and it is, so just start another timer cycle + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - ...and it is. Restart timer for another cycle."), + this, iSubConnectionShim.Id())); + + iPreviousUplinkDataVolume = newUplinkDataVolume; + iPreviousDownlinkDataVolume = newDownlinkDataVolume; + iActivityTimer->After(iRequestedClientTimerPeriod); + } + else // ...tell them it's not + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - ...and it isn't. Notify client."), + this, iSubConnectionShim.Id())); + + TPckg subConnectionActiveBuf(dataTransferred); + TInt ret= iOutstandingSubConnectionActivityMessage.Write(2, subConnectionActiveBuf); + iOutstandingSubConnectionActivityMessage.Complete(ret); + iOutstandingSubConnectionActivity = EFalse; + } + } + else // client believes subconnection is idle... + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - client believes subconnection idle..."), + this, iSubConnectionShim.Id())); + + if(dataTransferred) + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - ...and it isn't. Notify client."), + this, iSubConnectionShim.Id())); + + TPckg subConnectionActiveBuf(dataTransferred); + TInt ret= iOutstandingSubConnectionActivityMessage.Write(2, subConnectionActiveBuf); + iOutstandingSubConnectionActivityMessage.Complete(ret); + iOutstandingSubConnectionActivity = EFalse; + } + else // ...and it is, so just start another timer cycle + { + __CFLOG_VAR((KShimScprTag, KShimScprClientTag, _L8("CSubConnectionLinkShimClient %08x:\tid %d - ...and it is. Restart timer for another cycle."), + this, iSubConnectionShim.Id())); + + iPreviousUplinkDataVolume = newUplinkDataVolume; + iPreviousDownlinkDataVolume = newDownlinkDataVolume; + iActivityTimer->After(iRequestedClientTimerPeriod); + } + } + } + +CSubConnectionLinkShimClient::CActivityTimer* CSubConnectionLinkShimClient::CActivityTimer::NewL(CSubConnectionLinkShimClient* aOwner, TInt aPriority) +/** +Construct a new CActivityTimer() + +@param aOwner The owning CSubConnectionLinkShimClient (on which we call methods upon timer completion) +@param aPriority The priority of the active object underlying this timer object +@return A pointer to the newly constructed CActivityTimer object +*/ + { + CSubConnectionLinkShimClient::CActivityTimer* newActivityTimer = + new(ELeave) CSubConnectionLinkShimClient::CActivityTimer(aOwner, aPriority); + + CleanupStack::PushL(newActivityTimer); + newActivityTimer->ConstructL(); + CleanupStack::Pop(newActivityTimer); + return newActivityTimer; + } + +void CSubConnectionLinkShimClient::CActivityTimer::RunL() +/** +Call the owning object's check activity method + +*/ + { + iOwner->CheckSubConnectionActivity(); + }