|
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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalTechnology |
|
19 */ |
|
20 |
|
21 #ifndef SYMBIAN_ELEMENTS_MSGINTERCEPT_H |
|
22 #define SYMBIAN_ELEMENTS_MSGINTERCEPT_H |
|
23 |
|
24 #include <elements/interfacetable.h> |
|
25 #include <elements/rworkerlock.h> |
|
26 #include <elements/cftransport.h> |
|
27 #include <elements/sd_apiextension.h> |
|
28 #include <elements/sd_minterceptmsgs.h> |
|
29 |
|
30 |
|
31 #ifdef _DEBUG |
|
32 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
33 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
34 _LIT(KSpecAssert_ElemSvrDenMIntH, "ElemSvrDenMIntH"); |
|
35 #endif |
|
36 |
|
37 //[MZ]: Please consider connecting MI at the transport level. |
|
38 // The macro solution does not scale too well. |
|
39 |
|
40 /* ELEMENTS_DEBUG_MESSAGES_THUNK_POINT |
|
41 // to be reviewed since Message interceptor is decoupled from esock |
|
42 Elements debug messages currently fit the MIR well as it's a disconnect global blob (mostly disconnected; |
|
43 worker thread knows about it for init & cleanup & everybody else has macro hiding it). But for some |
|
44 debugging features closer coupling is required & many of the key classes aren't exported, ie the |
|
45 obvious home for the debugging code is inside ESOCK. Making them the debug dispatches friends isn't |
|
46 very good either as it risks hard-to-debug problems where ESOCKSVR is compiled without the support but |
|
47 the helper DLL is & so dereferences non-existant debug members, etc (and this is particularly likely |
|
48 on hardware where people always juggle weird mixes of UDEB & UREL to get a small enough ROM & this will |
|
49 be very hard to debug) |
|
50 |
|
51 Hence the addition of code ptrs to this MIR structure - poor man's vtbl. Really this shouldn't be in the MIR |
|
52 but a general debug DLL but (a) it's very slim functionality and (b) the MIR is already a bit ambiguous whether |
|
53 it's "a" debug DLL or "the". |
|
54 */ |
|
55 namespace Den |
|
56 { |
|
57 // Matching result codes |
|
58 enum TState {EResetState, ERunningState, EStoppedState, EPassedState, EFailedState}; |
|
59 // Use of Message Interceptor |
|
60 enum TMode {EPatternMatch, EFallibleTest}; |
|
61 |
|
62 // Interfaces |
|
63 //----------- |
|
64 // Interface for test client control thru self despatching msg interface |
|
65 //No need for CExtItfMsgPluginInfo for MI since messages already registered |
|
66 class APatternMatchControl : public AIpcExtensionInterface<0,0> |
|
67 { |
|
68 public: |
|
69 static const TInt KInterfaceId = 0x10285CB9; //Allocated 18/04/2008 |
|
70 |
|
71 public: |
|
72 virtual TInt Enable() = 0; |
|
73 virtual TInt SoftReset() = 0; |
|
74 virtual TInt HardReset() = 0; |
|
75 virtual TInt QueryComplete() = 0; |
|
76 virtual TInt AppendPattern(const CPattern* aPatternToAppend) = 0; |
|
77 virtual TInt AppendExpression(const TEventExpression& aExpressionToAppend) = 0; |
|
78 virtual TInt AppendAction(const TAction& aExpressionToAppend) = 0; |
|
79 virtual TInt Open(TUint /*aClientId*/) |
|
80 { |
|
81 return KErrNone; |
|
82 }; |
|
83 virtual void Close(TUint /*aClientId*/) |
|
84 { |
|
85 }; |
|
86 }; |
|
87 |
|
88 // Interface thru which fallible messages are tested |
|
89 //No need for CExtItfMsgPluginInfo for MI since messages already registered |
|
90 class AFallibleTestControl : public AIpcExtensionInterface<0,0> |
|
91 { |
|
92 public: |
|
93 static const TInt KInterfaceId = 0x10285CBA; //Allocated 18/04/2008 |
|
94 |
|
95 public: |
|
96 virtual TInt Enable(const TInt aMsgCount) = 0; |
|
97 virtual TBool CheckFinished() = 0; |
|
98 void InitL(const RArray<Messages::TNodeSignal::TMessageId>& aArray); |
|
99 virtual TInt Open(TUint /*aClientId*/) |
|
100 { |
|
101 return KErrNone; |
|
102 }; |
|
103 virtual void Close(TUint /*aClientId*/) |
|
104 { |
|
105 }; |
|
106 |
|
107 protected: |
|
108 // List of fallible messages. TBC Lookup from a configuration file. |
|
109 RArray<Messages::TNodeSignal::TMessageId> iFallibleMessages; |
|
110 }; |
|
111 |
|
112 // Interface thru which nodes call in to the message intercept and register with it |
|
113 //No need for CExtItfMsgPluginInfo for MI since messages already registered |
|
114 class ANodeIntercept : public AIpcExtensionInterface<0,0> |
|
115 { |
|
116 public: |
|
117 static const TInt KInterfaceId = 0x10285CBB; //Allocated 18/04/2008 |
|
118 |
|
119 public: |
|
120 virtual TInt RegisterNewNode(const TNodeSpecifier& aNodeToRegister) = 0; |
|
121 virtual void QueryMessageInterceptL(const TEventSummaryTriple& aIncomingEvent) = 0; |
|
122 virtual TInt Open(TUint /*aClientId*/) |
|
123 { |
|
124 return KErrNone; |
|
125 }; |
|
126 virtual void Close(TUint /*aClientId*/) |
|
127 { |
|
128 }; |
|
129 }; |
|
130 |
|
131 class MCompleteNotify |
|
132 { |
|
133 public: |
|
134 static const TInt KInterfaceId = 0x10285CBC; //Allocated 18/04/2008 |
|
135 |
|
136 public: |
|
137 virtual void SetComplete(TAny* aFrom) = 0; |
|
138 }; |
|
139 |
|
140 // |
|
141 // |
|
142 class RPatternList : public RPointerArray<CPattern> |
|
143 { |
|
144 public: |
|
145 RPatternList() : RPointerArray<CPattern>() {} |
|
146 CPattern& CurrentPattern(); |
|
147 void Advance(); |
|
148 void AppendEmptyPattern(); |
|
149 void SetOwner(MCompleteNotify* aToBeNotified) {__ASSERT_DEBUG(aToBeNotified, User::Panic(KSpecAssert_ElemSvrDenMIntH, 1)); iOwner = aToBeNotified;} |
|
150 void ResetForReuse(TBool aSameOwner); |
|
151 |
|
152 private: |
|
153 TUint iCurrentIndex; |
|
154 MCompleteNotify* iOwner; |
|
155 }; |
|
156 |
|
157 |
|
158 class RExpressionList : public RArray<TEventExpression> |
|
159 { |
|
160 public: |
|
161 RExpressionList() : |
|
162 RArray<TEventExpression>(), iCurrentIndex(0), iOwner(0) {} |
|
163 const TEventExpression& CurrentExpression() const; |
|
164 void Advance(); |
|
165 void ReserveDefaultSpaceL() |
|
166 { |
|
167 ReserveL(KMaxExpectedExpressions); |
|
168 } |
|
169 |
|
170 void SetOwner(MCompleteNotify* aToBeNotified) {__ASSERT_DEBUG(aToBeNotified, User::Panic(KSpecAssert_ElemSvrDenMIntH, 2)); iOwner = aToBeNotified;} |
|
171 |
|
172 private: |
|
173 static const TUint KMaxExpectedExpressions = 16; |
|
174 TUint iCurrentIndex; |
|
175 |
|
176 MCompleteNotify* iOwner; |
|
177 }; |
|
178 |
|
179 class TNodeSpecifier |
|
180 { |
|
181 public: |
|
182 TNodeSpecifier(TUid aUid, const Messages::TNodeId& aNode) : |
|
183 iUid(aUid), iNodeId(aNode) {} |
|
184 |
|
185 TNodeSpecifier(const Messages::TNodeId& aNodeId) : |
|
186 iUid(TUid::Uid(0)), iNodeId(aNodeId) {} |
|
187 |
|
188 TNodeSpecifier() : iUid(TUid::Uid(0)) {} |
|
189 const Messages::TNodeId& Id() const {return iNodeId;} |
|
190 const TNodeTag& Tag() const {return iTag;} |
|
191 const TUid Uid() const {return iUid;} |
|
192 |
|
193 void SetTag(TNodeTag& aTag) {iTag = aTag;} |
|
194 static TInt Compare(const TNodeSpecifier& aLHS, const TNodeSpecifier& aRHS); |
|
195 |
|
196 private: |
|
197 Messages::TNodeId iNodeId; |
|
198 enum TNodeType {EGeneralPurposeNode, EMeshBasedNode}; |
|
199 TUid iUid; |
|
200 TNodeTag iTag; |
|
201 }; |
|
202 |
|
203 /** Ordered list (by TNodeId) of nodes that have registered */ |
|
204 class RRegisteredNodeList : public RArray<TNodeSpecifier> |
|
205 { |
|
206 public: |
|
207 TInt SetNodeTag(const Messages::TNodeId& aNodeId, TNodeTag aTag); |
|
208 RRegisteredNodeList() : RArray<TNodeSpecifier>() {} |
|
209 |
|
210 TInt FindNode(const Messages::TNodeId& aCookieOfNodeToFind) |
|
211 { |
|
212 return FindInOrder(TNodeSpecifier(aCookieOfNodeToFind), TLinearOrder<TNodeSpecifier>(Compare)); |
|
213 } |
|
214 |
|
215 TInt InsertNode(const TNodeSpecifier& aNodeToInsert) |
|
216 { |
|
217 return RArray<TNodeSpecifier>::InsertInOrder(aNodeToInsert, Compare); |
|
218 } |
|
219 |
|
220 private: |
|
221 static TInt Compare(const TNodeSpecifier& aLHS, const TNodeSpecifier& aRHS); |
|
222 }; |
|
223 |
|
224 class TEventSummaryTriple |
|
225 { |
|
226 public: |
|
227 TEventSummaryTriple(Messages::TNodeId aSender, Messages::TNodeSignal& aMessage, Messages::TNodeId aReceiver) : |
|
228 iSenderId(aSender), iMessage(aMessage), iReceiverId(aReceiver) {} |
|
229 |
|
230 Messages::TNodeSignal& Message() const {return iMessage;}; |
|
231 const Messages::TNodeId& SenderId() const {return iSenderId;}; |
|
232 const Messages::TNodeId& ReceiverId() const {return iReceiverId;}; |
|
233 |
|
234 private: |
|
235 Messages::TNodeId iSenderId; |
|
236 Messages::TNodeSignal& iMessage; |
|
237 Messages::TNodeId iReceiverId; |
|
238 }; |
|
239 |
|
240 class CPattern : public CBase, public MCompleteNotify |
|
241 { |
|
242 public: |
|
243 IMPORT_C static CPattern* NewL(const RExpressionList& aExpressionList, const TAction& aAction); |
|
244 CPattern(const RExpressionList& aList, const TAction& aAction) : |
|
245 iExpressions(aList), iAction(aAction), iIsComplete(EFalse) |
|
246 {iExpressions.SetOwner(this);} |
|
247 ~CPattern(); |
|
248 |
|
249 // Accessors |
|
250 const TAction Action () const {return iAction;}; |
|
251 const RExpressionList& Expressions() const {return iExpressions;} |
|
252 RExpressionList& Expressions() {return iExpressions;} |
|
253 const TEventExpression& CurrentExpression() const; |
|
254 TBool IsTerminated() const; |
|
255 TBool IsComplete() const {return iIsComplete;} |
|
256 |
|
257 // Mutators |
|
258 TInt AppendExpression(TEventExpression& aExpression); |
|
259 void InitAction(const TAction& aAction); |
|
260 |
|
261 private: |
|
262 void ConstructL(); |
|
263 void SetAction(const TAction& aAction); |
|
264 |
|
265 // MCompleteNotify |
|
266 void SetComplete(TAny* aFrom); |
|
267 |
|
268 // List of event expressions and single resulting action |
|
269 RExpressionList iExpressions; |
|
270 TAction iAction; |
|
271 TBool iIsComplete; |
|
272 TBool iIsTerminated; |
|
273 }; |
|
274 |
|
275 /** Encapsulates full record of incoming event, as opposed to summary which is only the TCookies of the messages */ |
|
276 class TEventInfo |
|
277 { |
|
278 public: |
|
279 TEventInfo(TNodeSpecifier& aSender, Messages::TNodeSignal& aMsg, TNodeSpecifier& aReceiver) : |
|
280 iSenderNode(aSender), iMessage(aMsg), iReceiverNode(aReceiver) {} |
|
281 |
|
282 const Messages::TNodeSignal& Message() const {return iMessage;} |
|
283 const TNodeSpecifier& Sender() const {return iSenderNode;} |
|
284 const TNodeSpecifier& Receiver() const {return iReceiverNode;} |
|
285 |
|
286 private: |
|
287 TNodeSpecifier& iSenderNode; |
|
288 Messages::TNodeSignal& iMessage; |
|
289 TNodeSpecifier& iReceiverNode; |
|
290 }; |
|
291 |
|
292 // |
|
293 //CMessageInterceptRegister |
|
294 class CMessageInterceptRegister : public CBase, public NetInterfaces::TInterfaceControl, |
|
295 public APatternMatchControl, public AFallibleTestControl, public ANodeIntercept, public MCompleteNotify, |
|
296 public ITFHIERARCHY_3(CMessageInterceptRegister, APatternMatchControl, AFallibleTestControl, ANodeIntercept) |
|
297 { |
|
298 friend class CCommonWorkerThread; //consruction/destruction/broadcast |
|
299 |
|
300 public: |
|
301 typedef ITFHIERARCHY_3(CMessageInterceptRegister, APatternMatchControl, AFallibleTestControl, ANodeIntercept) TIfStaticFetcherNearestInHierarchy; |
|
302 |
|
303 public: |
|
304 // Context |
|
305 IMPORT_C static NetInterfaces::TInterfaceControl& GetInterfaceControl(); |
|
306 virtual ~CMessageInterceptRegister(); |
|
307 |
|
308 void ReturnInterfacePtrL(APatternMatchControl*& aInterface) |
|
309 { |
|
310 aInterface = this; |
|
311 } |
|
312 |
|
313 void ReturnInterfacePtrL(AFallibleTestControl*& aInterface) |
|
314 { |
|
315 aInterface = this; |
|
316 } |
|
317 |
|
318 void ReturnInterfacePtrL(ANodeIntercept*& aInterface) |
|
319 { |
|
320 aInterface = this; |
|
321 } |
|
322 |
|
323 private: |
|
324 //Only to be used by CCommonWorkerThread, must stay private |
|
325 static CMessageInterceptRegister* NewL(); |
|
326 static CMessageInterceptRegister& GetGlobal(); |
|
327 static CMessageInterceptRegister* SetGlobal(CMessageInterceptRegister* aContext); |
|
328 void ConstructL(); |
|
329 CMessageInterceptRegister(); |
|
330 |
|
331 // MCompleteNotify |
|
332 //---------------- |
|
333 void SetComplete(TAny* aFrom); |
|
334 |
|
335 // MPatternMatchControl |
|
336 //--------------------- |
|
337 IMPORT_C TInt Enable(); |
|
338 IMPORT_C TInt SoftReset(); |
|
339 IMPORT_C TInt HardReset(); |
|
340 IMPORT_C TInt QueryComplete(); |
|
341 |
|
342 IMPORT_C TInt AppendPattern(const CPattern* aPatternToAppend); |
|
343 IMPORT_C TInt AppendExpression(const TEventExpression& aExpressionToAppend); |
|
344 IMPORT_C TInt AppendAction(const TAction& aExpressionToAppend); |
|
345 |
|
346 // AFallibleTestControl |
|
347 //--------------------- |
|
348 IMPORT_C TInt Enable(const TInt aMsgCount); |
|
349 IMPORT_C TBool CheckFinished(); |
|
350 |
|
351 // MNodeIntercept |
|
352 //--------------- |
|
353 IMPORT_C TInt RegisterNewNode(const TNodeSpecifier& aNodeToRegister); |
|
354 IMPORT_C void QueryMessageInterceptL(const TEventSummaryTriple& aIncomingEvent); |
|
355 |
|
356 TInt MatchIncomingEvent(const TEventSummaryTriple& aEvent, TAction& aAction); |
|
357 TInt FetchRegisteredNodeInfo(const Messages::TNodeId& aNodeId, TNodeSpecifier& aNode); |
|
358 TInt CompareEventWithExpression( |
|
359 const TEventInfo& aEventInfo, |
|
360 const TEventExpression& aEventExpression); |
|
361 |
|
362 void ResetStatusVariables(); |
|
363 void Disable() {iState = EStoppedState;} |
|
364 // Caution: This routine used outside the protection of mutex that otherwise |
|
365 // manages concurrent access of the whole message register |
|
366 TBool IsRunning() const {return (iState == ERunningState);} |
|
367 void WaitForAccess() {iSynchronisedUseLock.Wait();} |
|
368 void RelinquishAccess() {iSynchronisedUseLock.Signal();} |
|
369 |
|
370 static void RelinguishAccessOperation(TAny* aPtr); |
|
371 |
|
372 // Print out the array of fallible messages |
|
373 void PrintAllFallibleMessages(); |
|
374 |
|
375 RPatternList iPatternList; |
|
376 RExpressionList* iExpressionHoldingList; |
|
377 RRegisteredNodeList iRegisteredNodeTable; |
|
378 RWorkerLock iSynchronisedUseLock; |
|
379 |
|
380 TState iState; |
|
381 TMode iMode; |
|
382 |
|
383 TInt iCount; |
|
384 TBool iErrInjectedFlag; |
|
385 }; |
|
386 } // Den |
|
387 |
|
388 #endif //SYMBIAN_ELEMENTS_MSGINTERCEPT_H |
|
389 |
|
390 |