--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwsupport/commselements/serverden/src/sd_mintercept.cpp Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,963 @@
+// Copyright (c) 2008-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:
+// messageintercept.cpp
+//
+//
+
+/**
+ @file
+*/
+
+#include "sd_mintercept.h"
+#include <elements/sd_log.h>
+#include <elements/metatype.h>
+#include <e32debug.h>
+#include <elements/interfacetable.h>
+
+
+#ifdef _DEBUG
+// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
+// (if it could happen through user error then you should give it an explicit, documented, category + code)
+_LIT(KSpecAssert_ElemSvrDenMIntC, "ElemSvrDenMIntC");
+#endif
+
+using namespace Messages;
+using namespace Meta;
+using namespace NetInterfaces;
+using namespace Elements;
+using namespace Den;
+
+_LIT(KMessageInterceptPanic, "message intercept panic");
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+_LIT(KInitalisationTimePanic, "Panic during initialisation of message intercept");
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+
+// Constants
+//----------
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+const TUint KMaxExpectedRegisteredNodes = 32;
+const TUint KMaxExpectedPatterns = 32;
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+// Helper function for comparing two TMessageId
+//---------------------------------------------
+TInt CompareTMessageId(const TNodeSignal::TMessageId& aMsg1, const TNodeSignal::TMessageId& aMsg2)
+ {
+ // return 0 is the objects are equal
+ // return negative value if first is less than second
+ // return positive if first is greater than second
+ if (aMsg1.Realm()==aMsg2.Realm())
+ {
+ return aMsg1.MessageId() - aMsg2.MessageId();
+ }
+ return aMsg1.Realm() - aMsg2.Realm();
+ }
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+
+// AFallibleTestControl (control interface)
+//-----------------------------------------
+void AFallibleTestControl::InitL(const RArray<TNodeSignal::TMessageId>& aArray)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ //copying the memory, not the array as its lifetime is temporary
+ iFallibleMessages.Reset();
+ TLinearOrder<TNodeSignal::TMessageId> order(CompareTMessageId);
+ for (TInt i=0; i<aArray.Count(); i++)
+ {
+ const TNodeSignal::TMessageId& msg = aArray[i];
+ // not allowing duplicate, leave with KErrAlreadyExists if so
+ iFallibleMessages.InsertInOrderL(msg, order);
+ }
+#else
+ // Fixing unused local variable warnings.
+ (void)aArray;
+
+ User::Leave(KErrNotSupported);
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ };
+
+// CMessageInterceptRegister
+//--------------------------
+CMessageInterceptRegister::CMessageInterceptRegister()
+: TIfStaticFetcherNearestInHierarchy(this),
+ iPatternList(),
+ iRegisteredNodeTable(),
+ iState(EResetState)
+ {}
+
+CMessageInterceptRegister* CMessageInterceptRegister::SetGlobal(CMessageInterceptRegister* aContext)
+ {
+ CMessageInterceptRegister* previous = reinterpret_cast<CMessageInterceptRegister*>(Dll::Tls());
+ __ASSERT_DEBUG(!previous || !aContext, User::Panic(KSpecAssert_ElemSvrDenMIntC, 1));
+ Dll::SetTls(aContext);
+ return previous;
+ }
+
+//Only to be used by CCommonWorkerThread
+CMessageInterceptRegister& CMessageInterceptRegister::GetGlobal()
+ {
+ CMessageInterceptRegister* context = reinterpret_cast<CMessageInterceptRegister*>(Dll::Tls());
+ __ASSERT_DEBUG(context, User::Panic(KSpecAssert_ElemSvrDenMIntC, 2));
+ return *context;
+ }
+
+TInt CMessageInterceptRegister::MatchIncomingEvent(const TEventSummaryTriple& aEvent, TAction& aAction)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // Fetch the current expression (from the current pattern) that we are waiting on next
+ const TEventExpression& expression = iPatternList.CurrentPattern().CurrentExpression();
+
+ // First need to look up sender and receiver in the node register
+ // as both need to have been registered to make anything of the incoming event
+ TNodeSpecifier senderNode;
+ TNodeSpecifier receiverNode;
+
+ TInt errorTx = FetchRegisteredNodeInfo(aEvent.SenderId(), senderNode);
+ TInt errorRx = FetchRegisteredNodeInfo(aEvent.ReceiverId(), receiverNode);
+
+ TInt matchResult;
+
+ if(errorTx == KErrNone && errorRx == KErrNone)
+ {
+ // Create full event info (incoming event info + provider info fetched from node register)
+ TEventInfo fullEventInfo(senderNode, aEvent.Message(), receiverNode);
+
+ // Compare against current expression we are matching against and return any action if a match
+ matchResult = CompareEventWithExpression(fullEventInfo, expression);
+
+ // If we matched then advance the list of expressions
+ if(matchResult == KErrNone)
+ {
+ iPatternList.CurrentPattern().Expressions().Advance();
+
+ // Advance the pattern itself if necessary
+ if(iPatternList.CurrentPattern().IsComplete())
+ {
+ aAction = iPatternList.CurrentPattern().Action();
+ iPatternList.Advance();
+ return KErrNone;
+ }
+ else
+ return KErrNotFound;
+ }
+ else
+ return KErrNotFound;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+#else
+ // Fixing unused local variable warnings.
+ (void)aEvent;
+ (void)aAction;
+
+ return KErrNotSupported;
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+
+TInt CMessageInterceptRegister::CompareEventWithExpression(
+ const TEventInfo& aEvent,
+ const TEventExpression& aExpression)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // Compare MESSAGE type first (quickest test and more often than not only a single test needed)
+ TBool msgMatch = aExpression.MessageExpression().Compare(aEvent.Message());
+
+ // If we are already not matched then no use continuing
+ if(!msgMatch)
+ {
+ return KErrNotFound;
+ }
+ else
+ {
+ // Now compare the SENDER properties against what we are expecting
+ TBool senderMatch = aExpression.SenderExpression().Compare(aEvent.Sender());
+
+ // If we aren't matched then no use continuing
+ if(!senderMatch)
+ {
+ return KErrNotFound;
+ }
+ else
+ {
+ // Firstly do we need to update tag in the node register
+ if(aExpression.SenderExpression().SetTagOnMatch())
+ {
+ iRegisteredNodeTable.SetNodeTag(aEvent.Sender().Id(), aExpression.SenderExpression().TagToSet());
+ }
+
+ // Now compare the RECEIVER
+ TBool receiverMatch = aExpression.ReceiverExpression().Compare(aEvent.Receiver());
+
+ // If we aren't matched then no use continuing
+ if(!receiverMatch)
+ {
+ return KErrNotFound;
+ }
+ else
+ {
+ // Firstly do we need to update tag in the node register
+ if(aExpression.ReceiverExpression().SetTagOnMatch())
+ {
+ iRegisteredNodeTable.SetNodeTag(aEvent.Receiver().Id(), aExpression.ReceiverExpression().TagToSet());
+ }
+
+ // ### COMPLETE MATCH ###
+ // We have every element so a full match
+ return KErrNone;
+ }
+ }
+ }
+#else
+ // Fixing unused local variable warnings.
+ (void)aEvent;
+ (void)aExpression;
+
+ return KErrNotSupported;
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+CMessageInterceptRegister* CMessageInterceptRegister::NewL()
+ {
+ CMessageInterceptRegister* self = new(ELeave) CMessageInterceptRegister();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+void CMessageInterceptRegister::ConstructL()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // Create the worker lock used to synchronise access to the message intercept register
+ // We absolutely need it so out of here if we can't create it
+ TInt error = iSynchronisedUseLock.CreateLocal();
+ User::LeaveIfError(error);
+
+ // Resize the node register as we need it
+ iRegisteredNodeTable.ReserveL(KMaxExpectedRegisteredNodes);
+
+ // Need to make sure we reserve space for at least as many patterns to register
+ // Don't want to be allocating memory during operation
+ iPatternList.ReserveL(KMaxExpectedPatterns);
+ iPatternList.SetOwner(this);
+#else
+ User::Leave(KErrNotSupported);
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+/** Look up a previously registered node */
+TInt CMessageInterceptRegister::FetchRegisteredNodeInfo(const TNodeId& aNodeId, TNodeSpecifier& aNode)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ TInt index = iRegisteredNodeTable.FindNode(aNodeId);
+ if (index < 0)
+ {
+ return index;
+ }
+ else
+ {
+ aNode = iRegisteredNodeTable[index];
+ return KErrNone;
+ }
+#else
+ // Fixing unused local variable warnings.
+ (void)aNodeId;
+ (void)aNode;
+
+ return KErrNotSupported;
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Destructor
+CMessageInterceptRegister::~CMessageInterceptRegister()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ iRegisteredNodeTable.Reset();
+ iPatternList.ResetAndDestroy();
+ iSynchronisedUseLock.Close();
+ iFallibleMessages.Close();
+#endif//#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+void CMessageInterceptRegister::ResetStatusVariables()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ iState = EResetState;
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+void CMessageInterceptRegister::SetComplete(TAny* aFrom)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ (void)(aFrom != NULL); //keep compiler happy
+ __ASSERT_DEBUG(static_cast<TAny*>(aFrom) == static_cast<TAny*>(&iPatternList), User::Panic(KSpecAssert_ElemSvrDenMIntC, 3));
+ iState = EPassedState;
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Register set complete:")));
+#else
+ // Fixing unused local variable warnings.
+ (void)aFrom;
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+#ifdef _DEBUG
+void CMessageInterceptRegister::PrintAllFallibleMessages()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ for (TInt i = 0; i < iFallibleMessages.Count(); i++)
+ {
+ RDebug::Print( _L("Fallible Message: %d, Id = %d, Realm = %d\n"), i+1, iFallibleMessages[i].MessageId(),
+ iFallibleMessages[i].Realm());
+ }
+#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+#endif // _DEBUG
+
+void CMessageInterceptRegister::RelinguishAccessOperation(TAny* aPtr)
+ {
+ CMessageInterceptRegister *obj = reinterpret_cast<CMessageInterceptRegister*> (aPtr);
+ __ASSERT_DEBUG(obj, User::Panic(KSpecAssert_ElemSvrDenMIntC, 4));
+ obj->RelinquishAccess();
+ }
+
+// EXPORTED
+
+EXPORT_C NetInterfaces::TInterfaceControl& CMessageInterceptRegister::GetInterfaceControl()
+ {
+ CMessageInterceptRegister* context = reinterpret_cast<CMessageInterceptRegister*>(Dll::Tls());
+ __ASSERT_DEBUG(context, User::Panic(KSpecAssert_ElemSvrDenMIntC, 5));
+ return *context;
+ }
+
+// Enable the register
+EXPORT_C TInt CMessageInterceptRegister::Enable()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Must reset before re-enabling if already been completed
+ __ASSERT_DEBUG(iState == EResetState, User::Panic(KSpecAssert_ElemSvrDenMIntC, 6));
+ iState = ERunningState;
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Enabled:")));
+ iMode = EPatternMatch;
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return KErrNone;
+#else
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// MPatternMatchControl (control interface)
+//-----------------------------------------
+
+// Reset the message intercept register (but retain the register of nodes, including any tags applied)
+EXPORT_C TInt CMessageInterceptRegister::SoftReset()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Disable the register (stop it intercepting if it is currently)
+ Disable();
+
+ // Clear the pattern table
+ ResetStatusVariables();
+ iPatternList.ResetForReuse(ETrue);
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Soft reset:")));
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return KErrNone;
+#else
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Reset the whole register (patterns and node instances)
+EXPORT_C TInt CMessageInterceptRegister::HardReset()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Disable the register
+ Disable();
+
+ // Clear both registers
+ ResetStatusVariables();
+ iPatternList.ResetForReuse(ETrue);
+ iRegisteredNodeTable.Reset();
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Hard reset:")));
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return KErrNone;
+#else
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Allow the client to query the completion of the message pattern matching
+EXPORT_C TInt CMessageInterceptRegister::QueryComplete()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ TInt state = static_cast<TInt>(iState);
+ //COMMONLOG(_L8("Query complete: status:%d"), state);
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return state;
+#else
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+EXPORT_C TInt CMessageInterceptRegister::AppendPattern(const CPattern* aPatternToAppend)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Take ownership by appending to our list of patterns
+ TRAPD(error, iPatternList.AppendL(aPatternToAppend));
+ //COMMONLOG(_L8("Append pattern: err:%d"), error);
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return error;
+#else
+ // Fixing unused local variable warnings.
+ (void)aPatternToAppend;
+
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Append a new pattern to the pattern matching schedule
+EXPORT_C TInt CMessageInterceptRegister::AppendExpression(const TEventExpression& aExpression)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ TInt error = KErrNone;
+
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Do we need a new temporary holding list
+ if(!iExpressionHoldingList)
+ {
+ iExpressionHoldingList = new RExpressionList();
+ if(!iExpressionHoldingList)
+ {
+ User::Panic(KInitalisationTimePanic, KErrNoMemory);
+ }
+
+ TRAPD(error, iExpressionHoldingList->ReserveDefaultSpaceL());
+ if(error != KErrNone)
+ {
+ User::Panic(KInitalisationTimePanic, error);
+ }
+ }
+
+ // Append our expression to the list
+ error = iExpressionHoldingList->Append(aExpression);
+ if(error != KErrNone)
+ {
+ User::Panic(KInitalisationTimePanic, error);
+ }
+
+ //COMMONLOG(_L8("Append expression: err:%d"), error);
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return KErrNone;
+#else
+ // Fixing unused local variable warnings.
+ (void)aExpression;
+
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+EXPORT_C TInt CMessageInterceptRegister::AppendAction(const TAction& aAction)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Must have a list of expressions that we are terminating with this action
+ __ASSERT_DEBUG(iExpressionHoldingList, User::Panic(KSpecAssert_ElemSvrDenMIntC, 7));
+ __ASSERT_DEBUG(iExpressionHoldingList->Count() > 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 8));
+ TInt error;
+ CPattern* newPattern = NULL;
+ TRAP(error, newPattern = CPattern::NewL(*iExpressionHoldingList, aAction));
+ if(error == KErrNone)
+ {
+ TRAP(error, iPatternList.AppendL(newPattern));
+ }
+
+ //COMMONLOG(_L8("Appended action:0x%x ErrorCode:0x%x err:%d"), aAction.Action(), aAction.Error(), error);
+
+ // Refresh the holding store for new expressions
+ delete iExpressionHoldingList;
+ iExpressionHoldingList = NULL;
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return error;
+#else
+ // Fixing unused local variable warnings.
+ (void)aAction;
+
+ return KErrNotSupported;
+#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Enable the register using the counter
+EXPORT_C TInt CMessageInterceptRegister::Enable(const TInt aMsgCount)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ Disable();
+ ResetStatusVariables();
+
+ // Must reset before re-enabling if already been completed
+ __ASSERT_DEBUG(iState == EResetState, User::Panic(KSpecAssert_ElemSvrDenMIntC, 9));
+ iState = ERunningState;
+ iCount = aMsgCount;
+ iErrInjectedFlag = EFalse;
+
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Enabled with counter:")));
+
+ iMode = EFallibleTest;
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return KErrNone;
+#else
+ // Fixing unused local variable warnings.
+ (void)aMsgCount;
+
+ return KErrNotSupported;
+#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Check
+EXPORT_C TBool CMessageInterceptRegister::CheckFinished()
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ TBool Result = EFalse;
+
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ if (iCount > 0)
+ {
+ Result = ETrue;
+ }
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return Result;
+#else
+ return EFalse;
+#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// MNodeIntercept (interface for nodes in to the register during opertion)
+//------------------------------------------------------------------------
+
+// Register a newly constructed node
+EXPORT_C TInt CMessageInterceptRegister::RegisterNewNode(const TNodeSpecifier& aNodeToRegister)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ TInt error = KErrNone;
+
+ // Cheaply return if not running
+ if(!IsRunning())
+ return KErrNone;
+
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // Yes we need to check again as we were not under the protection of the register's mutex
+ // when we decided not to cheaply return above
+ if(IsRunning())
+ {
+ // Something wrong if we already exist in the table
+ __ASSERT_DEBUG(iRegisteredNodeTable.FindNode(aNodeToRegister.Id()) < 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 10));
+ error = iRegisteredNodeTable.InsertNode(aNodeToRegister);
+
+ //COMMONLOG(_L8("Registered node: 0x%x err:%d"), aNodeToRegister.Id().Ptr(), error);
+ }
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ return error;
+#else
+ // Fixing unused local variable warnings.
+ (void)aNodeToRegister;
+
+ return KErrNotSupported;
+#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ }
+
+// Perform message interception on an incoming message
+EXPORT_C void CMessageInterceptRegister::QueryMessageInterceptL(const TEventSummaryTriple& aIncomingEvent)
+ {
+#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+ TAction resultingAction;
+
+ // Cheaply return if not running
+ if(!IsRunning())
+ return;
+
+ switch (iMode)
+ {
+ case EFallibleTest:
+ {
+ // Perform message interception on an incoming message for testing all fallible messages
+
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+ CleanupStack::PushL(TCleanupItem(RelinguishAccessOperation, this));
+
+ if (iErrInjectedFlag)
+ {
+ CleanupStack::PopAndDestroy(); // RelinquishAccess() is called
+ return; // Ignore error propagation messages
+ }
+
+ // Ignore messages already tested
+ if (iCount > 0)
+ {
+ --iCount;
+ }
+
+ if (iCount == 0)
+ {
+ TLinearOrder<TNodeSignal::TMessageId> order(CompareTMessageId);
+ if (iFallibleMessages.FindInOrder(aIncomingEvent.Message().MessageId(), order) != KErrNotFound)
+ {
+ iErrInjectedFlag = ETrue;
+
+ // TBC Error configured by client
+ User::Leave(KErrNoMemory);
+ }
+ else
+ {
+ // set back the counter which is used by CheckFinished
+ // this tells that the last msg is not a fallible one
+ iCount = 1;
+ }
+ }
+ CleanupStack::Pop(); // simply pop the TCleanupItem
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+ }
+ break;
+
+ case EPatternMatch:
+ {
+ TInt error = KErrNotFound;
+
+ // ### SYNCHRONISE ACCESS ###
+ WaitForAccess();
+
+ // We must be running at least
+ // Yes we need to check again as we were not under the protection of the register's mutex
+ // when we decided not to cheaply return above
+ if(IsRunning())
+ {
+ // Query if the new event matches the event we are waiting for
+ // Need to peek inside the sender as NodePtr will fail as sender not necessarily in it own thread
+ //COMMONLOG(_L8("Event: tx:0x%x msg:%d rx:0x%x err:%d"), aIncomingEvent.SenderId().Ptr(), aIncomingEvent.Message().MessageId().MessageId(), aIncomingEvent.ReceiverId().Ptr(), error);
+ error = MatchIncomingEvent(aIncomingEvent, resultingAction);
+ }
+
+ // ### SYNCHRONISE ACCESS ###
+ RelinquishAccess();
+
+ // If have found Cause action specified by querying the register or return as expected
+ if(error == KErrNone)
+ {
+ //COMMONLOG(_L8("Executing action:0x%x ErrorCode:0x%x"), resultingAction.Action(), resultingAction.Error());
+ resultingAction.ExecuteActionL();
+ }
+ }
+ break;
+
+ default:
+ __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 11));
+ break;
+ }
+#else
+ // Fixing unused local variable warnings.
+ (void)aIncomingEvent;
+
+ User::Leave(KErrNotSupported);
+#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE
+}
+
+
+// RExpressionList
+//----------------
+void RExpressionList::Advance()
+ {
+ // Can't advance an empty list
+ __ASSERT_DEBUG(Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 12));
+ __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 13));
+
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Expression list advanced:")));
+
+ if((++iCurrentIndex) == Count())
+ {
+ __ASSERT_DEBUG(iOwner, User::Panic(KSpecAssert_ElemSvrDenMIntC, 14));
+ iOwner->SetComplete(this);
+ }
+ }
+
+void CPattern::SetComplete(TAny* aFrom)
+ {
+ (void)(aFrom != NULL); //keep compiler happy
+ __ASSERT_DEBUG(static_cast<TAny*>(aFrom) == static_cast<TAny*>(&iExpressions), User::Panic(KSpecAssert_ElemSvrDenMIntC, 15));
+ iIsComplete = ETrue;
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Pattern set complete:")));
+ }
+
+
+const TEventExpression& RExpressionList::CurrentExpression() const
+ {
+ // Get the current expression
+ __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 16));
+ return this->operator[](iCurrentIndex);
+ }
+
+// TMsgExpression
+//---------------
+TBool TMsgExpression::Compare(const TNodeSignal& aMessage) const
+ {
+ // We consider the messages to be the same if they have the same type id
+ // ie. they are the same type of message and we don't consider any parameters
+ return (aMessage.MessageId().MessageId() == iMessageId) && (aMessage.MessageId().Realm() == iRealm);
+ }
+
+// RPatternList
+//-------------
+CPattern& RPatternList::CurrentPattern()
+ {
+ // Get the current pattern
+ __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 17));
+ return *(this->operator[](iCurrentIndex));
+ }
+
+void RPatternList::Advance()
+ {
+ // Advance the list of expressions which will notify the parent register if necessary
+ // Shouldn't be trying to advance an empty list
+ __ASSERT_DEBUG(Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 18));
+ __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 19));
+
+ COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Pattern list advanced:")));
+
+ if((++iCurrentIndex) == Count())
+ {
+ __ASSERT_DEBUG(iOwner, User::Panic(KSpecAssert_ElemSvrDenMIntC, 20));
+ iOwner->SetComplete(this);
+ }
+ }
+
+void RPatternList::ResetForReuse(TBool aSameOwner)
+ {
+ ResetAndDestroy();
+ iCurrentIndex = 0;
+ if(!aSameOwner)
+ {
+ iOwner = NULL;
+ }
+ }
+
+// CPattern
+//---------
+EXPORT_C CPattern* CPattern::NewL(const RExpressionList& aExpressionList, const TAction& aAction)
+ {
+ CPattern* self = new(ELeave) CPattern(aExpressionList, aAction);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+void CPattern::ConstructL()
+ {
+ }
+
+CPattern::~CPattern()
+ {
+ iExpressions.Reset();
+ }
+
+const TEventExpression& CPattern::CurrentExpression() const
+ {
+ return iExpressions.CurrentExpression();
+ }
+
+TInt CPattern::AppendExpression(TEventExpression& aExpression)
+ {
+ return iExpressions.Append(aExpression);
+ }
+
+void CPattern::InitAction(const TAction& aAction)
+ {
+ // Simply assign the new action and mark ourselves as now terminated
+ __ASSERT_DEBUG(!iIsTerminated, User::Panic(KSpecAssert_ElemSvrDenMIntC, 21));
+ SetAction(aAction);
+ iIsTerminated = ETrue;
+ }
+
+TBool CPattern::IsTerminated() const
+ {
+ return iIsTerminated;
+ }
+
+void CPattern::SetAction(const TAction& aAction)
+ {
+ iAction = aAction;
+ }
+
+// RRegisteredNodeList
+//--------------------
+TInt RRegisteredNodeList::SetNodeTag(const TNodeId& aNodeId, TNodeTag aTag)
+ {
+ // Lookup the tag in the
+ TInt index = FindInUnsignedKeyOrder(aNodeId);
+
+ // We are in some sort of trouble if we couldn't find the
+ if(index < 0)
+ return index;
+ else
+ {
+ // Set the tag - can't already be tagged
+ __ASSERT_DEBUG(operator[](index).Tag().Length() == 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 22));
+ operator[](index).SetTag(aTag);
+ }
+
+ return KErrNone;
+ }
+
+TInt RRegisteredNodeList::Compare(const TNodeSpecifier& aLHS, const TNodeSpecifier& aRHS)
+ {
+ // How about just being ultra sure that nothing has changed in the world of TCookie
+ __ASSERT_DEBUG(aLHS.Id().Size() == 12, User::Panic(KSpecAssert_ElemSvrDenMIntC, 23));
+
+ // Simply compare the cookies
+ const TUint* LHS = (reinterpret_cast<const TUint*>(&(aLHS.Id())));
+ const TUint* RHS = (reinterpret_cast<const TUint*>(&(aRHS.Id())));
+
+ if(LHS[0] < RHS[0])
+ {
+ return -1;
+ }
+ else if(LHS[0] > RHS[0])
+ {
+ return 1;
+ }
+ else if(LHS[1] > RHS[1])
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+
+// TNodeExpression
+//----------------
+TBool TNodeExpression::Compare(const TNodeSpecifier& aNode) const
+ {
+ TBool areEqual(EFalse);
+
+ switch (iMatchType)
+ {
+ case EMatchByInstance:
+ {
+ // Compare only on the basis of earier applied identity (descriptor tag)
+ areEqual = (iMatchTag == aNode.Tag());
+ }
+ break;
+
+ case EMatchByUid:
+ {
+ // Compare only on the basis of UID
+ areEqual = (iUid == aNode.Uid());
+ }
+ break;
+
+ default:
+ __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 24));
+ break;
+ }
+
+ return areEqual;
+ }
+
+// TAction
+//--------
+TInt TAction::ExecuteActionL()
+ {
+ // Simply execute the action specified
+ switch(iAction)
+ {
+ case ENoAction:
+ return KErrNone;
+ //break;
+
+ case ELeaveAction:
+ User::Leave(iError);
+ break;
+
+ case EPanicAction:
+ User::Panic(KMessageInterceptPanic, iError);
+ break;
+
+ default:
+ return KErrArgument;
+ //break;
+ }
+
+ // For what its worth
+ return KErrNone;
+ }
+
+
+