|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // messageintercept.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 #include "sd_mintercept.h" |
|
23 #include <elements/sd_log.h> |
|
24 #include <elements/metatype.h> |
|
25 #include <e32debug.h> |
|
26 #include <elements/interfacetable.h> |
|
27 |
|
28 |
|
29 #ifdef _DEBUG |
|
30 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
31 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
32 _LIT(KSpecAssert_ElemSvrDenMIntC, "ElemSvrDenMIntC"); |
|
33 #endif |
|
34 |
|
35 using namespace Messages; |
|
36 using namespace Meta; |
|
37 using namespace NetInterfaces; |
|
38 using namespace Elements; |
|
39 using namespace Den; |
|
40 |
|
41 _LIT(KMessageInterceptPanic, "message intercept panic"); |
|
42 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
43 _LIT(KInitalisationTimePanic, "Panic during initialisation of message intercept"); |
|
44 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
45 |
|
46 // Constants |
|
47 //---------- |
|
48 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
49 const TUint KMaxExpectedRegisteredNodes = 32; |
|
50 const TUint KMaxExpectedPatterns = 32; |
|
51 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
52 |
|
53 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
54 // Helper function for comparing two TMessageId |
|
55 //--------------------------------------------- |
|
56 TInt CompareTMessageId(const TNodeSignal::TMessageId& aMsg1, const TNodeSignal::TMessageId& aMsg2) |
|
57 { |
|
58 // return 0 is the objects are equal |
|
59 // return negative value if first is less than second |
|
60 // return positive if first is greater than second |
|
61 if (aMsg1.Realm()==aMsg2.Realm()) |
|
62 { |
|
63 return aMsg1.MessageId() - aMsg2.MessageId(); |
|
64 } |
|
65 return aMsg1.Realm() - aMsg2.Realm(); |
|
66 } |
|
67 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
68 |
|
69 // AFallibleTestControl (control interface) |
|
70 //----------------------------------------- |
|
71 void AFallibleTestControl::InitL(const RArray<TNodeSignal::TMessageId>& aArray) |
|
72 { |
|
73 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
74 //copying the memory, not the array as its lifetime is temporary |
|
75 iFallibleMessages.Reset(); |
|
76 TLinearOrder<TNodeSignal::TMessageId> order(CompareTMessageId); |
|
77 for (TInt i=0; i<aArray.Count(); i++) |
|
78 { |
|
79 const TNodeSignal::TMessageId& msg = aArray[i]; |
|
80 // not allowing duplicate, leave with KErrAlreadyExists if so |
|
81 iFallibleMessages.InsertInOrderL(msg, order); |
|
82 } |
|
83 #else |
|
84 // Fixing unused local variable warnings. |
|
85 (void)aArray; |
|
86 |
|
87 User::Leave(KErrNotSupported); |
|
88 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
89 }; |
|
90 |
|
91 // CMessageInterceptRegister |
|
92 //-------------------------- |
|
93 CMessageInterceptRegister::CMessageInterceptRegister() |
|
94 : TIfStaticFetcherNearestInHierarchy(this), |
|
95 iPatternList(), |
|
96 iRegisteredNodeTable(), |
|
97 iState(EResetState) |
|
98 {} |
|
99 |
|
100 CMessageInterceptRegister* CMessageInterceptRegister::SetGlobal(CMessageInterceptRegister* aContext) |
|
101 { |
|
102 CMessageInterceptRegister* previous = reinterpret_cast<CMessageInterceptRegister*>(Dll::Tls()); |
|
103 __ASSERT_DEBUG(!previous || !aContext, User::Panic(KSpecAssert_ElemSvrDenMIntC, 1)); |
|
104 Dll::SetTls(aContext); |
|
105 return previous; |
|
106 } |
|
107 |
|
108 //Only to be used by CCommonWorkerThread |
|
109 CMessageInterceptRegister& CMessageInterceptRegister::GetGlobal() |
|
110 { |
|
111 CMessageInterceptRegister* context = reinterpret_cast<CMessageInterceptRegister*>(Dll::Tls()); |
|
112 __ASSERT_DEBUG(context, User::Panic(KSpecAssert_ElemSvrDenMIntC, 2)); |
|
113 return *context; |
|
114 } |
|
115 |
|
116 TInt CMessageInterceptRegister::MatchIncomingEvent(const TEventSummaryTriple& aEvent, TAction& aAction) |
|
117 { |
|
118 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
119 // Fetch the current expression (from the current pattern) that we are waiting on next |
|
120 const TEventExpression& expression = iPatternList.CurrentPattern().CurrentExpression(); |
|
121 |
|
122 // First need to look up sender and receiver in the node register |
|
123 // as both need to have been registered to make anything of the incoming event |
|
124 TNodeSpecifier senderNode; |
|
125 TNodeSpecifier receiverNode; |
|
126 |
|
127 TInt errorTx = FetchRegisteredNodeInfo(aEvent.SenderId(), senderNode); |
|
128 TInt errorRx = FetchRegisteredNodeInfo(aEvent.ReceiverId(), receiverNode); |
|
129 |
|
130 TInt matchResult; |
|
131 |
|
132 if(errorTx == KErrNone && errorRx == KErrNone) |
|
133 { |
|
134 // Create full event info (incoming event info + provider info fetched from node register) |
|
135 TEventInfo fullEventInfo(senderNode, aEvent.Message(), receiverNode); |
|
136 |
|
137 // Compare against current expression we are matching against and return any action if a match |
|
138 matchResult = CompareEventWithExpression(fullEventInfo, expression); |
|
139 |
|
140 // If we matched then advance the list of expressions |
|
141 if(matchResult == KErrNone) |
|
142 { |
|
143 iPatternList.CurrentPattern().Expressions().Advance(); |
|
144 |
|
145 // Advance the pattern itself if necessary |
|
146 if(iPatternList.CurrentPattern().IsComplete()) |
|
147 { |
|
148 aAction = iPatternList.CurrentPattern().Action(); |
|
149 iPatternList.Advance(); |
|
150 return KErrNone; |
|
151 } |
|
152 else |
|
153 return KErrNotFound; |
|
154 } |
|
155 else |
|
156 return KErrNotFound; |
|
157 } |
|
158 else |
|
159 { |
|
160 return KErrNotFound; |
|
161 } |
|
162 #else |
|
163 // Fixing unused local variable warnings. |
|
164 (void)aEvent; |
|
165 (void)aAction; |
|
166 |
|
167 return KErrNotSupported; |
|
168 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
169 } |
|
170 |
|
171 |
|
172 TInt CMessageInterceptRegister::CompareEventWithExpression( |
|
173 const TEventInfo& aEvent, |
|
174 const TEventExpression& aExpression) |
|
175 { |
|
176 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
177 // Compare MESSAGE type first (quickest test and more often than not only a single test needed) |
|
178 TBool msgMatch = aExpression.MessageExpression().Compare(aEvent.Message()); |
|
179 |
|
180 // If we are already not matched then no use continuing |
|
181 if(!msgMatch) |
|
182 { |
|
183 return KErrNotFound; |
|
184 } |
|
185 else |
|
186 { |
|
187 // Now compare the SENDER properties against what we are expecting |
|
188 TBool senderMatch = aExpression.SenderExpression().Compare(aEvent.Sender()); |
|
189 |
|
190 // If we aren't matched then no use continuing |
|
191 if(!senderMatch) |
|
192 { |
|
193 return KErrNotFound; |
|
194 } |
|
195 else |
|
196 { |
|
197 // Firstly do we need to update tag in the node register |
|
198 if(aExpression.SenderExpression().SetTagOnMatch()) |
|
199 { |
|
200 iRegisteredNodeTable.SetNodeTag(aEvent.Sender().Id(), aExpression.SenderExpression().TagToSet()); |
|
201 } |
|
202 |
|
203 // Now compare the RECEIVER |
|
204 TBool receiverMatch = aExpression.ReceiverExpression().Compare(aEvent.Receiver()); |
|
205 |
|
206 // If we aren't matched then no use continuing |
|
207 if(!receiverMatch) |
|
208 { |
|
209 return KErrNotFound; |
|
210 } |
|
211 else |
|
212 { |
|
213 // Firstly do we need to update tag in the node register |
|
214 if(aExpression.ReceiverExpression().SetTagOnMatch()) |
|
215 { |
|
216 iRegisteredNodeTable.SetNodeTag(aEvent.Receiver().Id(), aExpression.ReceiverExpression().TagToSet()); |
|
217 } |
|
218 |
|
219 // ### COMPLETE MATCH ### |
|
220 // We have every element so a full match |
|
221 return KErrNone; |
|
222 } |
|
223 } |
|
224 } |
|
225 #else |
|
226 // Fixing unused local variable warnings. |
|
227 (void)aEvent; |
|
228 (void)aExpression; |
|
229 |
|
230 return KErrNotSupported; |
|
231 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
232 } |
|
233 |
|
234 CMessageInterceptRegister* CMessageInterceptRegister::NewL() |
|
235 { |
|
236 CMessageInterceptRegister* self = new(ELeave) CMessageInterceptRegister(); |
|
237 CleanupStack::PushL(self); |
|
238 self->ConstructL(); |
|
239 CleanupStack::Pop(); |
|
240 return self; |
|
241 } |
|
242 |
|
243 void CMessageInterceptRegister::ConstructL() |
|
244 { |
|
245 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
246 // Create the worker lock used to synchronise access to the message intercept register |
|
247 // We absolutely need it so out of here if we can't create it |
|
248 TInt error = iSynchronisedUseLock.CreateLocal(); |
|
249 User::LeaveIfError(error); |
|
250 |
|
251 // Resize the node register as we need it |
|
252 iRegisteredNodeTable.ReserveL(KMaxExpectedRegisteredNodes); |
|
253 |
|
254 // Need to make sure we reserve space for at least as many patterns to register |
|
255 // Don't want to be allocating memory during operation |
|
256 iPatternList.ReserveL(KMaxExpectedPatterns); |
|
257 iPatternList.SetOwner(this); |
|
258 #else |
|
259 User::Leave(KErrNotSupported); |
|
260 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
261 } |
|
262 |
|
263 /** Look up a previously registered node */ |
|
264 TInt CMessageInterceptRegister::FetchRegisteredNodeInfo(const TNodeId& aNodeId, TNodeSpecifier& aNode) |
|
265 { |
|
266 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
267 TInt index = iRegisteredNodeTable.FindNode(aNodeId); |
|
268 if (index < 0) |
|
269 { |
|
270 return index; |
|
271 } |
|
272 else |
|
273 { |
|
274 aNode = iRegisteredNodeTable[index]; |
|
275 return KErrNone; |
|
276 } |
|
277 #else |
|
278 // Fixing unused local variable warnings. |
|
279 (void)aNodeId; |
|
280 (void)aNode; |
|
281 |
|
282 return KErrNotSupported; |
|
283 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
284 } |
|
285 |
|
286 // Destructor |
|
287 CMessageInterceptRegister::~CMessageInterceptRegister() |
|
288 { |
|
289 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
290 iRegisteredNodeTable.Reset(); |
|
291 iPatternList.ResetAndDestroy(); |
|
292 iSynchronisedUseLock.Close(); |
|
293 iFallibleMessages.Close(); |
|
294 #endif//#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
295 } |
|
296 |
|
297 void CMessageInterceptRegister::ResetStatusVariables() |
|
298 { |
|
299 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
300 iState = EResetState; |
|
301 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
302 } |
|
303 |
|
304 void CMessageInterceptRegister::SetComplete(TAny* aFrom) |
|
305 { |
|
306 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
307 (void)(aFrom != NULL); //keep compiler happy |
|
308 __ASSERT_DEBUG(static_cast<TAny*>(aFrom) == static_cast<TAny*>(&iPatternList), User::Panic(KSpecAssert_ElemSvrDenMIntC, 3)); |
|
309 iState = EPassedState; |
|
310 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Register set complete:"))); |
|
311 #else |
|
312 // Fixing unused local variable warnings. |
|
313 (void)aFrom; |
|
314 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
315 } |
|
316 |
|
317 #ifdef _DEBUG |
|
318 void CMessageInterceptRegister::PrintAllFallibleMessages() |
|
319 { |
|
320 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
321 for (TInt i = 0; i < iFallibleMessages.Count(); i++) |
|
322 { |
|
323 RDebug::Print( _L("Fallible Message: %d, Id = %d, Realm = %d\n"), i+1, iFallibleMessages[i].MessageId(), |
|
324 iFallibleMessages[i].Realm()); |
|
325 } |
|
326 #endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
327 } |
|
328 #endif // _DEBUG |
|
329 |
|
330 void CMessageInterceptRegister::RelinguishAccessOperation(TAny* aPtr) |
|
331 { |
|
332 CMessageInterceptRegister *obj = reinterpret_cast<CMessageInterceptRegister*> (aPtr); |
|
333 __ASSERT_DEBUG(obj, User::Panic(KSpecAssert_ElemSvrDenMIntC, 4)); |
|
334 obj->RelinquishAccess(); |
|
335 } |
|
336 |
|
337 // EXPORTED |
|
338 |
|
339 EXPORT_C NetInterfaces::TInterfaceControl& CMessageInterceptRegister::GetInterfaceControl() |
|
340 { |
|
341 CMessageInterceptRegister* context = reinterpret_cast<CMessageInterceptRegister*>(Dll::Tls()); |
|
342 __ASSERT_DEBUG(context, User::Panic(KSpecAssert_ElemSvrDenMIntC, 5)); |
|
343 return *context; |
|
344 } |
|
345 |
|
346 // Enable the register |
|
347 EXPORT_C TInt CMessageInterceptRegister::Enable() |
|
348 { |
|
349 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
350 // ### SYNCHRONISE ACCESS ### |
|
351 WaitForAccess(); |
|
352 |
|
353 // Must reset before re-enabling if already been completed |
|
354 __ASSERT_DEBUG(iState == EResetState, User::Panic(KSpecAssert_ElemSvrDenMIntC, 6)); |
|
355 iState = ERunningState; |
|
356 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Enabled:"))); |
|
357 iMode = EPatternMatch; |
|
358 |
|
359 // ### SYNCHRONISE ACCESS ### |
|
360 RelinquishAccess(); |
|
361 |
|
362 return KErrNone; |
|
363 #else |
|
364 return KErrNotSupported; |
|
365 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
366 } |
|
367 |
|
368 // MPatternMatchControl (control interface) |
|
369 //----------------------------------------- |
|
370 |
|
371 // Reset the message intercept register (but retain the register of nodes, including any tags applied) |
|
372 EXPORT_C TInt CMessageInterceptRegister::SoftReset() |
|
373 { |
|
374 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
375 // ### SYNCHRONISE ACCESS ### |
|
376 WaitForAccess(); |
|
377 |
|
378 // Disable the register (stop it intercepting if it is currently) |
|
379 Disable(); |
|
380 |
|
381 // Clear the pattern table |
|
382 ResetStatusVariables(); |
|
383 iPatternList.ResetForReuse(ETrue); |
|
384 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Soft reset:"))); |
|
385 |
|
386 // ### SYNCHRONISE ACCESS ### |
|
387 RelinquishAccess(); |
|
388 |
|
389 return KErrNone; |
|
390 #else |
|
391 return KErrNotSupported; |
|
392 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
393 } |
|
394 |
|
395 // Reset the whole register (patterns and node instances) |
|
396 EXPORT_C TInt CMessageInterceptRegister::HardReset() |
|
397 { |
|
398 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
399 // ### SYNCHRONISE ACCESS ### |
|
400 WaitForAccess(); |
|
401 |
|
402 // Disable the register |
|
403 Disable(); |
|
404 |
|
405 // Clear both registers |
|
406 ResetStatusVariables(); |
|
407 iPatternList.ResetForReuse(ETrue); |
|
408 iRegisteredNodeTable.Reset(); |
|
409 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Hard reset:"))); |
|
410 |
|
411 // ### SYNCHRONISE ACCESS ### |
|
412 RelinquishAccess(); |
|
413 |
|
414 return KErrNone; |
|
415 #else |
|
416 return KErrNotSupported; |
|
417 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
418 } |
|
419 |
|
420 // Allow the client to query the completion of the message pattern matching |
|
421 EXPORT_C TInt CMessageInterceptRegister::QueryComplete() |
|
422 { |
|
423 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
424 // ### SYNCHRONISE ACCESS ### |
|
425 WaitForAccess(); |
|
426 |
|
427 TInt state = static_cast<TInt>(iState); |
|
428 //COMMONLOG(_L8("Query complete: status:%d"), state); |
|
429 |
|
430 // ### SYNCHRONISE ACCESS ### |
|
431 RelinquishAccess(); |
|
432 |
|
433 return state; |
|
434 #else |
|
435 return KErrNotSupported; |
|
436 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
437 } |
|
438 |
|
439 EXPORT_C TInt CMessageInterceptRegister::AppendPattern(const CPattern* aPatternToAppend) |
|
440 { |
|
441 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
442 // ### SYNCHRONISE ACCESS ### |
|
443 WaitForAccess(); |
|
444 |
|
445 // Take ownership by appending to our list of patterns |
|
446 TRAPD(error, iPatternList.AppendL(aPatternToAppend)); |
|
447 //COMMONLOG(_L8("Append pattern: err:%d"), error); |
|
448 |
|
449 // ### SYNCHRONISE ACCESS ### |
|
450 RelinquishAccess(); |
|
451 |
|
452 return error; |
|
453 #else |
|
454 // Fixing unused local variable warnings. |
|
455 (void)aPatternToAppend; |
|
456 |
|
457 return KErrNotSupported; |
|
458 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
459 } |
|
460 |
|
461 // Append a new pattern to the pattern matching schedule |
|
462 EXPORT_C TInt CMessageInterceptRegister::AppendExpression(const TEventExpression& aExpression) |
|
463 { |
|
464 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
465 TInt error = KErrNone; |
|
466 |
|
467 // ### SYNCHRONISE ACCESS ### |
|
468 WaitForAccess(); |
|
469 |
|
470 // Do we need a new temporary holding list |
|
471 if(!iExpressionHoldingList) |
|
472 { |
|
473 iExpressionHoldingList = new RExpressionList(); |
|
474 if(!iExpressionHoldingList) |
|
475 { |
|
476 User::Panic(KInitalisationTimePanic, KErrNoMemory); |
|
477 } |
|
478 |
|
479 TRAPD(error, iExpressionHoldingList->ReserveDefaultSpaceL()); |
|
480 if(error != KErrNone) |
|
481 { |
|
482 User::Panic(KInitalisationTimePanic, error); |
|
483 } |
|
484 } |
|
485 |
|
486 // Append our expression to the list |
|
487 error = iExpressionHoldingList->Append(aExpression); |
|
488 if(error != KErrNone) |
|
489 { |
|
490 User::Panic(KInitalisationTimePanic, error); |
|
491 } |
|
492 |
|
493 //COMMONLOG(_L8("Append expression: err:%d"), error); |
|
494 |
|
495 // ### SYNCHRONISE ACCESS ### |
|
496 RelinquishAccess(); |
|
497 |
|
498 return KErrNone; |
|
499 #else |
|
500 // Fixing unused local variable warnings. |
|
501 (void)aExpression; |
|
502 |
|
503 return KErrNotSupported; |
|
504 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
505 } |
|
506 |
|
507 EXPORT_C TInt CMessageInterceptRegister::AppendAction(const TAction& aAction) |
|
508 { |
|
509 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
510 // ### SYNCHRONISE ACCESS ### |
|
511 WaitForAccess(); |
|
512 |
|
513 // Must have a list of expressions that we are terminating with this action |
|
514 __ASSERT_DEBUG(iExpressionHoldingList, User::Panic(KSpecAssert_ElemSvrDenMIntC, 7)); |
|
515 __ASSERT_DEBUG(iExpressionHoldingList->Count() > 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 8)); |
|
516 TInt error; |
|
517 CPattern* newPattern = NULL; |
|
518 TRAP(error, newPattern = CPattern::NewL(*iExpressionHoldingList, aAction)); |
|
519 if(error == KErrNone) |
|
520 { |
|
521 TRAP(error, iPatternList.AppendL(newPattern)); |
|
522 } |
|
523 |
|
524 //COMMONLOG(_L8("Appended action:0x%x ErrorCode:0x%x err:%d"), aAction.Action(), aAction.Error(), error); |
|
525 |
|
526 // Refresh the holding store for new expressions |
|
527 delete iExpressionHoldingList; |
|
528 iExpressionHoldingList = NULL; |
|
529 |
|
530 // ### SYNCHRONISE ACCESS ### |
|
531 RelinquishAccess(); |
|
532 |
|
533 return error; |
|
534 #else |
|
535 // Fixing unused local variable warnings. |
|
536 (void)aAction; |
|
537 |
|
538 return KErrNotSupported; |
|
539 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
540 } |
|
541 |
|
542 // Enable the register using the counter |
|
543 EXPORT_C TInt CMessageInterceptRegister::Enable(const TInt aMsgCount) |
|
544 { |
|
545 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
546 // ### SYNCHRONISE ACCESS ### |
|
547 WaitForAccess(); |
|
548 |
|
549 Disable(); |
|
550 ResetStatusVariables(); |
|
551 |
|
552 // Must reset before re-enabling if already been completed |
|
553 __ASSERT_DEBUG(iState == EResetState, User::Panic(KSpecAssert_ElemSvrDenMIntC, 9)); |
|
554 iState = ERunningState; |
|
555 iCount = aMsgCount; |
|
556 iErrInjectedFlag = EFalse; |
|
557 |
|
558 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Enabled with counter:"))); |
|
559 |
|
560 iMode = EFallibleTest; |
|
561 |
|
562 // ### SYNCHRONISE ACCESS ### |
|
563 RelinquishAccess(); |
|
564 |
|
565 return KErrNone; |
|
566 #else |
|
567 // Fixing unused local variable warnings. |
|
568 (void)aMsgCount; |
|
569 |
|
570 return KErrNotSupported; |
|
571 #endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
572 } |
|
573 |
|
574 // Check |
|
575 EXPORT_C TBool CMessageInterceptRegister::CheckFinished() |
|
576 { |
|
577 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
578 TBool Result = EFalse; |
|
579 |
|
580 // ### SYNCHRONISE ACCESS ### |
|
581 WaitForAccess(); |
|
582 |
|
583 if (iCount > 0) |
|
584 { |
|
585 Result = ETrue; |
|
586 } |
|
587 |
|
588 // ### SYNCHRONISE ACCESS ### |
|
589 RelinquishAccess(); |
|
590 |
|
591 return Result; |
|
592 #else |
|
593 return EFalse; |
|
594 #endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
595 } |
|
596 |
|
597 // MNodeIntercept (interface for nodes in to the register during opertion) |
|
598 //------------------------------------------------------------------------ |
|
599 |
|
600 // Register a newly constructed node |
|
601 EXPORT_C TInt CMessageInterceptRegister::RegisterNewNode(const TNodeSpecifier& aNodeToRegister) |
|
602 { |
|
603 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
604 TInt error = KErrNone; |
|
605 |
|
606 // Cheaply return if not running |
|
607 if(!IsRunning()) |
|
608 return KErrNone; |
|
609 |
|
610 // ### SYNCHRONISE ACCESS ### |
|
611 WaitForAccess(); |
|
612 |
|
613 // Yes we need to check again as we were not under the protection of the register's mutex |
|
614 // when we decided not to cheaply return above |
|
615 if(IsRunning()) |
|
616 { |
|
617 // Something wrong if we already exist in the table |
|
618 __ASSERT_DEBUG(iRegisteredNodeTable.FindNode(aNodeToRegister.Id()) < 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 10)); |
|
619 error = iRegisteredNodeTable.InsertNode(aNodeToRegister); |
|
620 |
|
621 //COMMONLOG(_L8("Registered node: 0x%x err:%d"), aNodeToRegister.Id().Ptr(), error); |
|
622 } |
|
623 |
|
624 // ### SYNCHRONISE ACCESS ### |
|
625 RelinquishAccess(); |
|
626 |
|
627 return error; |
|
628 #else |
|
629 // Fixing unused local variable warnings. |
|
630 (void)aNodeToRegister; |
|
631 |
|
632 return KErrNotSupported; |
|
633 #endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
634 } |
|
635 |
|
636 // Perform message interception on an incoming message |
|
637 EXPORT_C void CMessageInterceptRegister::QueryMessageInterceptL(const TEventSummaryTriple& aIncomingEvent) |
|
638 { |
|
639 #ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
640 TAction resultingAction; |
|
641 |
|
642 // Cheaply return if not running |
|
643 if(!IsRunning()) |
|
644 return; |
|
645 |
|
646 switch (iMode) |
|
647 { |
|
648 case EFallibleTest: |
|
649 { |
|
650 // Perform message interception on an incoming message for testing all fallible messages |
|
651 |
|
652 // ### SYNCHRONISE ACCESS ### |
|
653 WaitForAccess(); |
|
654 CleanupStack::PushL(TCleanupItem(RelinguishAccessOperation, this)); |
|
655 |
|
656 if (iErrInjectedFlag) |
|
657 { |
|
658 CleanupStack::PopAndDestroy(); // RelinquishAccess() is called |
|
659 return; // Ignore error propagation messages |
|
660 } |
|
661 |
|
662 // Ignore messages already tested |
|
663 if (iCount > 0) |
|
664 { |
|
665 --iCount; |
|
666 } |
|
667 |
|
668 if (iCount == 0) |
|
669 { |
|
670 TLinearOrder<TNodeSignal::TMessageId> order(CompareTMessageId); |
|
671 if (iFallibleMessages.FindInOrder(aIncomingEvent.Message().MessageId(), order) != KErrNotFound) |
|
672 { |
|
673 iErrInjectedFlag = ETrue; |
|
674 |
|
675 // TBC Error configured by client |
|
676 User::Leave(KErrNoMemory); |
|
677 } |
|
678 else |
|
679 { |
|
680 // set back the counter which is used by CheckFinished |
|
681 // this tells that the last msg is not a fallible one |
|
682 iCount = 1; |
|
683 } |
|
684 } |
|
685 CleanupStack::Pop(); // simply pop the TCleanupItem |
|
686 // ### SYNCHRONISE ACCESS ### |
|
687 RelinquishAccess(); |
|
688 } |
|
689 break; |
|
690 |
|
691 case EPatternMatch: |
|
692 { |
|
693 TInt error = KErrNotFound; |
|
694 |
|
695 // ### SYNCHRONISE ACCESS ### |
|
696 WaitForAccess(); |
|
697 |
|
698 // We must be running at least |
|
699 // Yes we need to check again as we were not under the protection of the register's mutex |
|
700 // when we decided not to cheaply return above |
|
701 if(IsRunning()) |
|
702 { |
|
703 // Query if the new event matches the event we are waiting for |
|
704 // Need to peek inside the sender as NodePtr will fail as sender not necessarily in it own thread |
|
705 //COMMONLOG(_L8("Event: tx:0x%x msg:%d rx:0x%x err:%d"), aIncomingEvent.SenderId().Ptr(), aIncomingEvent.Message().MessageId().MessageId(), aIncomingEvent.ReceiverId().Ptr(), error); |
|
706 error = MatchIncomingEvent(aIncomingEvent, resultingAction); |
|
707 } |
|
708 |
|
709 // ### SYNCHRONISE ACCESS ### |
|
710 RelinquishAccess(); |
|
711 |
|
712 // If have found Cause action specified by querying the register or return as expected |
|
713 if(error == KErrNone) |
|
714 { |
|
715 //COMMONLOG(_L8("Executing action:0x%x ErrorCode:0x%x"), resultingAction.Action(), resultingAction.Error()); |
|
716 resultingAction.ExecuteActionL(); |
|
717 } |
|
718 } |
|
719 break; |
|
720 |
|
721 default: |
|
722 __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 11)); |
|
723 break; |
|
724 } |
|
725 #else |
|
726 // Fixing unused local variable warnings. |
|
727 (void)aIncomingEvent; |
|
728 |
|
729 User::Leave(KErrNotSupported); |
|
730 #endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
731 } |
|
732 |
|
733 |
|
734 // RExpressionList |
|
735 //---------------- |
|
736 void RExpressionList::Advance() |
|
737 { |
|
738 // Can't advance an empty list |
|
739 __ASSERT_DEBUG(Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 12)); |
|
740 __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 13)); |
|
741 |
|
742 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Expression list advanced:"))); |
|
743 |
|
744 if((++iCurrentIndex) == Count()) |
|
745 { |
|
746 __ASSERT_DEBUG(iOwner, User::Panic(KSpecAssert_ElemSvrDenMIntC, 14)); |
|
747 iOwner->SetComplete(this); |
|
748 } |
|
749 } |
|
750 |
|
751 void CPattern::SetComplete(TAny* aFrom) |
|
752 { |
|
753 (void)(aFrom != NULL); //keep compiler happy |
|
754 __ASSERT_DEBUG(static_cast<TAny*>(aFrom) == static_cast<TAny*>(&iExpressions), User::Panic(KSpecAssert_ElemSvrDenMIntC, 15)); |
|
755 iIsComplete = ETrue; |
|
756 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Pattern set complete:"))); |
|
757 } |
|
758 |
|
759 |
|
760 const TEventExpression& RExpressionList::CurrentExpression() const |
|
761 { |
|
762 // Get the current expression |
|
763 __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 16)); |
|
764 return this->operator[](iCurrentIndex); |
|
765 } |
|
766 |
|
767 // TMsgExpression |
|
768 //--------------- |
|
769 TBool TMsgExpression::Compare(const TNodeSignal& aMessage) const |
|
770 { |
|
771 // We consider the messages to be the same if they have the same type id |
|
772 // ie. they are the same type of message and we don't consider any parameters |
|
773 return (aMessage.MessageId().MessageId() == iMessageId) && (aMessage.MessageId().Realm() == iRealm); |
|
774 } |
|
775 |
|
776 // RPatternList |
|
777 //------------- |
|
778 CPattern& RPatternList::CurrentPattern() |
|
779 { |
|
780 // Get the current pattern |
|
781 __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 17)); |
|
782 return *(this->operator[](iCurrentIndex)); |
|
783 } |
|
784 |
|
785 void RPatternList::Advance() |
|
786 { |
|
787 // Advance the list of expressions which will notify the parent register if necessary |
|
788 // Shouldn't be trying to advance an empty list |
|
789 __ASSERT_DEBUG(Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 18)); |
|
790 __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 19)); |
|
791 |
|
792 COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Pattern list advanced:"))); |
|
793 |
|
794 if((++iCurrentIndex) == Count()) |
|
795 { |
|
796 __ASSERT_DEBUG(iOwner, User::Panic(KSpecAssert_ElemSvrDenMIntC, 20)); |
|
797 iOwner->SetComplete(this); |
|
798 } |
|
799 } |
|
800 |
|
801 void RPatternList::ResetForReuse(TBool aSameOwner) |
|
802 { |
|
803 ResetAndDestroy(); |
|
804 iCurrentIndex = 0; |
|
805 if(!aSameOwner) |
|
806 { |
|
807 iOwner = NULL; |
|
808 } |
|
809 } |
|
810 |
|
811 // CPattern |
|
812 //--------- |
|
813 EXPORT_C CPattern* CPattern::NewL(const RExpressionList& aExpressionList, const TAction& aAction) |
|
814 { |
|
815 CPattern* self = new(ELeave) CPattern(aExpressionList, aAction); |
|
816 CleanupStack::PushL(self); |
|
817 self->ConstructL(); |
|
818 CleanupStack::Pop(); |
|
819 return self; |
|
820 } |
|
821 |
|
822 void CPattern::ConstructL() |
|
823 { |
|
824 } |
|
825 |
|
826 CPattern::~CPattern() |
|
827 { |
|
828 iExpressions.Reset(); |
|
829 } |
|
830 |
|
831 const TEventExpression& CPattern::CurrentExpression() const |
|
832 { |
|
833 return iExpressions.CurrentExpression(); |
|
834 } |
|
835 |
|
836 TInt CPattern::AppendExpression(TEventExpression& aExpression) |
|
837 { |
|
838 return iExpressions.Append(aExpression); |
|
839 } |
|
840 |
|
841 void CPattern::InitAction(const TAction& aAction) |
|
842 { |
|
843 // Simply assign the new action and mark ourselves as now terminated |
|
844 __ASSERT_DEBUG(!iIsTerminated, User::Panic(KSpecAssert_ElemSvrDenMIntC, 21)); |
|
845 SetAction(aAction); |
|
846 iIsTerminated = ETrue; |
|
847 } |
|
848 |
|
849 TBool CPattern::IsTerminated() const |
|
850 { |
|
851 return iIsTerminated; |
|
852 } |
|
853 |
|
854 void CPattern::SetAction(const TAction& aAction) |
|
855 { |
|
856 iAction = aAction; |
|
857 } |
|
858 |
|
859 // RRegisteredNodeList |
|
860 //-------------------- |
|
861 TInt RRegisteredNodeList::SetNodeTag(const TNodeId& aNodeId, TNodeTag aTag) |
|
862 { |
|
863 // Lookup the tag in the |
|
864 TInt index = FindInUnsignedKeyOrder(aNodeId); |
|
865 |
|
866 // We are in some sort of trouble if we couldn't find the |
|
867 if(index < 0) |
|
868 return index; |
|
869 else |
|
870 { |
|
871 // Set the tag - can't already be tagged |
|
872 __ASSERT_DEBUG(operator[](index).Tag().Length() == 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 22)); |
|
873 operator[](index).SetTag(aTag); |
|
874 } |
|
875 |
|
876 return KErrNone; |
|
877 } |
|
878 |
|
879 TInt RRegisteredNodeList::Compare(const TNodeSpecifier& aLHS, const TNodeSpecifier& aRHS) |
|
880 { |
|
881 // How about just being ultra sure that nothing has changed in the world of TCookie |
|
882 __ASSERT_DEBUG(aLHS.Id().Size() == 12, User::Panic(KSpecAssert_ElemSvrDenMIntC, 23)); |
|
883 |
|
884 // Simply compare the cookies |
|
885 const TUint* LHS = (reinterpret_cast<const TUint*>(&(aLHS.Id()))); |
|
886 const TUint* RHS = (reinterpret_cast<const TUint*>(&(aRHS.Id()))); |
|
887 |
|
888 if(LHS[0] < RHS[0]) |
|
889 { |
|
890 return -1; |
|
891 } |
|
892 else if(LHS[0] > RHS[0]) |
|
893 { |
|
894 return 1; |
|
895 } |
|
896 else if(LHS[1] > RHS[1]) |
|
897 { |
|
898 return 1; |
|
899 } |
|
900 return 0; |
|
901 } |
|
902 |
|
903 |
|
904 // TNodeExpression |
|
905 //---------------- |
|
906 TBool TNodeExpression::Compare(const TNodeSpecifier& aNode) const |
|
907 { |
|
908 TBool areEqual(EFalse); |
|
909 |
|
910 switch (iMatchType) |
|
911 { |
|
912 case EMatchByInstance: |
|
913 { |
|
914 // Compare only on the basis of earier applied identity (descriptor tag) |
|
915 areEqual = (iMatchTag == aNode.Tag()); |
|
916 } |
|
917 break; |
|
918 |
|
919 case EMatchByUid: |
|
920 { |
|
921 // Compare only on the basis of UID |
|
922 areEqual = (iUid == aNode.Uid()); |
|
923 } |
|
924 break; |
|
925 |
|
926 default: |
|
927 __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 24)); |
|
928 break; |
|
929 } |
|
930 |
|
931 return areEqual; |
|
932 } |
|
933 |
|
934 // TAction |
|
935 //-------- |
|
936 TInt TAction::ExecuteActionL() |
|
937 { |
|
938 // Simply execute the action specified |
|
939 switch(iAction) |
|
940 { |
|
941 case ENoAction: |
|
942 return KErrNone; |
|
943 //break; |
|
944 |
|
945 case ELeaveAction: |
|
946 User::Leave(iError); |
|
947 break; |
|
948 |
|
949 case EPanicAction: |
|
950 User::Panic(KMessageInterceptPanic, iError); |
|
951 break; |
|
952 |
|
953 default: |
|
954 return KErrArgument; |
|
955 //break; |
|
956 } |
|
957 |
|
958 // For what its worth |
|
959 return KErrNone; |
|
960 } |
|
961 |
|
962 |
|
963 |