|
1 // Copyright (c) 2006-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 // COREPRACTIVITIES.CPP |
|
15 // Core PR Activities |
|
16 // THIS API IS INTERNAL TO NETWORKING AND IS SUBJECT TO CHANGE AND NOT FOR EXTERNAL USE |
|
17 // |
|
18 // |
|
19 |
|
20 /** |
|
21 @file |
|
22 @internalComponent |
|
23 */ |
|
24 |
|
25 #define SYMBIAN_NETWORKING_UPS |
|
26 |
|
27 #include "ss_corepractivities.h" |
|
28 |
|
29 |
|
30 #include <comms-infras/ss_log.h> |
|
31 #include "ss_internal_activities.h" |
|
32 #include <comms-infras/ss_coreprstates.h> |
|
33 #include <comms-infras/ss_subconnprov.h> |
|
34 #include <comms-infras/ss_mcprnodemessages.h> |
|
35 |
|
36 #include <comms-infras/ss_protocolparameterset.h> |
|
37 #include <ss_glob.h> |
|
38 |
|
39 |
|
40 #include <elements/nm_messages_child.h> |
|
41 #include <elements/nm_messages_peer.h> |
|
42 #include <elements/nm_messages_errorrecovery.h> |
|
43 #include "ss_nodemessages_dataclient.h" |
|
44 #include "ss_nodemessages_serviceprovider.h" |
|
45 #include <comms-infras/ss_nodemessages_rejoiningprovider.h> |
|
46 #include <comms-infras/ss_nodemessages_flow.h> |
|
47 #include "ss_nodemessages_factory.h" |
|
48 #include <comms-infras/ss_nodemessages_internal_esock.h> |
|
49 |
|
50 |
|
51 #ifdef _DEBUG |
|
52 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
53 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
54 _LIT(KSpecAssert_ESockCrStaCPRAC, "ESockCrStaCPRAC"); |
|
55 #endif |
|
56 |
|
57 #if defined __CFLOG_ACTIVE || defined ESOCK_EXTLOG_ACTIVE |
|
58 #define KCoreProviderStatesTag KESockCoreProviderTag |
|
59 _LIT8(KCoreProviderStatesSubTag, "coreprovstate"); |
|
60 #endif |
|
61 |
|
62 using namespace NetStateMachine; |
|
63 using namespace CoreStates; |
|
64 using namespace CoreNetStates; |
|
65 using namespace PRStates; |
|
66 using namespace PRActivities; |
|
67 using namespace CoreActivities; |
|
68 using namespace ESock; |
|
69 using namespace CorePanics; |
|
70 using namespace Elements; |
|
71 using namespace Messages; |
|
72 using namespace MeshMachine; |
|
73 using namespace Factories; |
|
74 |
|
75 |
|
76 #ifdef _DEBUG |
|
77 _LIT (KCorePrPanic,"CorePrPanic"); |
|
78 #endif |
|
79 |
|
80 namespace CoreErrorActivity |
|
81 { //Special parallel activity, must be started as the last one |
|
82 DEFINE_EXPORT_CUSTOM_NODEACTIVITY(ECFActivityError, CoreError, TEBase::TError, CErrorActivity::NewL) |
|
83 FIRST_NODEACTIVITY_ENTRY(CErrorActivity::TCFAwaitingError, MeshMachine::TNoTag) |
|
84 NODEACTIVITY_ENTRY(KNoTag, CErrorActivity::TSendErrorRecoveryReq, MeshMachine::TAwaitingMessageState<TEErrorRecovery::TErrorRecoveryResponse>, MeshMachine::TNoTag) |
|
85 LAST_NODEACTIVITY_ENTRY(KNoTag, CErrorActivity::TDoErrorRecovery) |
|
86 NODEACTIVITY_END() |
|
87 } |
|
88 |
|
89 namespace PRProvisionActivity |
|
90 { |
|
91 DECLARE_DEFINE_NODEACTIVITY(ECFActivityStoreProvision, PrProvision, TCFDataClient::TProvisionConfig) |
|
92 NODEACTIVITY_ENTRY(KNoTag, PRStates::TStoreProvision, CoreNetStates::TAwaitingProvision, MeshMachine::TNoTag) |
|
93 NODEACTIVITY_END() |
|
94 } |
|
95 |
|
96 namespace PRControlClientJoinActivity |
|
97 { |
|
98 DEFINE_EXPORT_NODEACTIVITY(ECFActivityClientJoin, PRControlClientJoin, TNodeSignal::TNullMessageId) //May be waiting for both messages |
|
99 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TAddControlClientAndSendJoinCompleteIfRequest, CoreNetStates::TAwaitingControlClientJoin, MeshMachine::TNoTag) |
|
100 NODEACTIVITY_END() |
|
101 } |
|
102 |
|
103 namespace PRDataClientJoinActivity |
|
104 { //This activity needs the activity object (& it can fail on AddClientL, so no point converting) |
|
105 DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientJoin, PRDataClientJoin, TCFPeer::TJoinRequest) |
|
106 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientJoinRequest, MeshMachine::TNoTag) |
|
107 LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TAddDataClientAndRespond) |
|
108 NODEACTIVITY_END() |
|
109 } |
|
110 |
|
111 namespace PRClientLeaveActivity |
|
112 {//This activity will wait for ECFActivityBinderRequest to complete |
|
113 DEFINE_EXPORT_NODEACTIVITY(ECFActivityClientLeave, PRClientLeave, TNodeSignal::TNullMessageId) //May be waiting for both messages |
|
114 NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessClientLeave, CoreStates::TAwaitingClientLeave, MeshMachine::TNoTag) |
|
115 NODEACTIVITY_END() |
|
116 } |
|
117 |
|
118 namespace PRDataClientIdleActivity |
|
119 { |
|
120 DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientIdle, PRDataClientIdle, TCFControlProvider::TIdle) |
|
121 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::THandleDataClientIdle, CoreNetStates::TAwaitingDataClientIdle, MeshMachine::TNoTag) |
|
122 NODEACTIVITY_END() |
|
123 } |
|
124 |
|
125 namespace PRDataClientActiveActivity |
|
126 { |
|
127 DEFINE_EXPORT_NODEACTIVITY(ECFActivityDataClientActive, PRDataClientActive, TCFControlProvider::TActive) |
|
128 NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TAwaitingDataClientActive, MeshMachine::TNoTag) |
|
129 NODEACTIVITY_END() |
|
130 } |
|
131 |
|
132 namespace PRDestroyActivity |
|
133 { |
|
134 //The generic Destroy activity. Carries out the node's goodbye handshake. |
|
135 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, PRDestroy, TEChild::TDestroy, CoreActivities::CDestroyActivity::New) |
|
136 FIRST_NODEACTIVITY_ENTRY(MeshMachine::TAwaitingDestroy, CoreActivities::CDestroyActivity::TNoTagBlockedByActivitiesOrLeavingDataClient) |
|
137 |
|
138 //Stop self first |
|
139 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreStates::TNoTagOrNoClients) |
|
140 |
|
141 //The node mustn't go out of scope with clients present. The node must get rid of them first. |
|
142 NODEACTIVITY_ENTRY(KNoTag, CoreActivities::CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave, CoreStates::TAwaitingClientLeave, CDestroyActivity::TNoTagOrNoTagBackwards) |
|
143 THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::CDestroyActivity::TProcessClientLeave, TTag<KNoClients>) |
|
144 |
|
145 THROUGH_NODEACTIVITY_ENTRY(KNoClients, PRStates::TProcessDestroy, MeshMachine::TNoTag) |
|
146 NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards) |
|
147 LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingAndRemoveControlProvider) |
|
148 NODEACTIVITY_END() |
|
149 } |
|
150 |
|
151 namespace PRSetParamsRequest |
|
152 { |
|
153 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
154 DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRSetParams, TCFScpr::TSetParamsRequest) |
|
155 FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, CoreNetStates::TNoTagOrBearerPresent) |
|
156 NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TPassToServiceProvider, CoreNetStates::TAwaitingParamResponse, MeshMachine::TTag<CoreNetStates::KBearerPresent>) |
|
157 LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TStoreParamsAndPostToOriginators) |
|
158 LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TStoreAndRespondWithCurrentParams) |
|
159 NODEACTIVITY_END() |
|
160 #else |
|
161 DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRSetParams, TNodeSignal::TNullMessageId) |
|
162 NODEACTIVITY_END() |
|
163 #endif |
|
164 } |
|
165 |
|
166 // no Store in case of GetParamsRequest |
|
167 namespace PRGetParamsRequest |
|
168 { |
|
169 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
170 DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRGetParams, TCFScpr::TGetParamsRequest) |
|
171 FIRST_NODEACTIVITY_ENTRY(PRStates::TAwaitingParamRequest, CoreNetStates::TNoTagOrBearerPresent) |
|
172 NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, PRStates::TPassToServiceProvider, CoreNetStates::TAwaitingParamResponse, MeshMachine::TTag<CoreNetStates::KBearerPresent>) |
|
173 LAST_NODEACTIVITY_ENTRY(CoreNetStates::KBearerPresent, CoreStates::TPostToOriginators) |
|
174 LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TRespondWithRetrievedParams) |
|
175 NODEACTIVITY_END() |
|
176 #else |
|
177 DEFINE_EXPORT_NODEACTIVITY(ECFActivityParamRequest, PRGetParams, TNodeSignal::TNullMessageId) |
|
178 NODEACTIVITY_END() |
|
179 #endif |
|
180 } |
|
181 |
|
182 namespace PRBindToActivity |
|
183 { |
|
184 //PRBindToActivity is responsible for handling TCFDataClient::TBindTo; |
|
185 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityBindTo, PRBindTo, TCFDataClient::TBindTo, CBindToActivity::NewL) |
|
186 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingBindTo, CBindToActivity::TNoTagOrBearerReady) |
|
187 //TBindTo can hold: |
|
188 //[KNoTag] - a valid serviceProvider cookie that this node isn't bound to; |
|
189 //[KBearerReady] - a valid serviceProvider cookie that this node is already bound to; |
|
190 //[KBearerReady] - a NULL serviceProvider (this node is at the stack's bottom); |
|
191 |
|
192 //{ JOINING NEW SERVICE PROVIDER |
|
193 //a valid serviceProvider supplied, new to this node, let's join it; |
|
194 NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TSendControlClientJoinRequest, CoreStates::TAwaitingJoinComplete, TTag<KBearerReady>) |
|
195 //} |
|
196 |
|
197 //serviceProvider provisionally joined. Now the activity needs to propagate iteslf (TBindTo) to its dataclients. |
|
198 //The dataclients are either present or not. If not this activity will assume this is the layer construction phase |
|
199 //and will attempt to construct a default dataclient. |
|
200 THROUGH_NODEACTIVITY_ENTRY(KBearerReady, MeshMachine::TDoNothing, CBindToActivity::TNoTagOrDataClientReady) |
|
201 |
|
202 //{ DATA CLIENT CREATION |
|
203 //No dataclients present, assume this is the layer creation phase. Attempt to create a dataclient. |
|
204 NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TCreateDataClient, TAcceptErrorState<CoreNetStates::TAwaitingDataClientJoin>, MeshMachine::TErrorTagOr<CBindToActivity::TNoTagOrBindToComplete>) |
|
205 //BindTo activity is the pre-start layer builder, hence it always requests the dataclient from the factory. |
|
206 //The factory (being aware of the phase) may decide to: |
|
207 //1. create a new dataclient -> process dataclient creation [KNoTag] |
|
208 //2. return a preexisting dataclient -> bind the client [KDataClientReady] |
|
209 //3. not to create a dataclient -> send TBindToComplete to the originator [KBindToComplete] |
|
210 THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientCreation, TTag<KDataClientReady>) |
|
211 //} |
|
212 |
|
213 THROUGH_NODEACTIVITY_ENTRY(KDataClientReady, MeshMachine::TDoNothing, CBindToActivity::TNoTagOrBearerReadyOrBindToComplete) |
|
214 //{ BINDING DATACLIENTS LOOP |
|
215 //Dataclient(s) is/are ready. Depending on whether the node has the lower layer or not, |
|
216 //we will [KNoTag] or will not [KNoBearer] need to request a binder for the dataclient. |
|
217 |
|
218 //{SERVICE PROVIDER PRESENT |
|
219 NODEACTIVITY_ENTRY(KNoTag, CBindToActivity::TRequestCommsBinder, TAcceptErrorState<CoreNetStates::TAwaitingBinderResponse>, TErrorTagOr<TTag<KBearerReady> >) |
|
220 //} |
|
221 NODEACTIVITY_ENTRY(KBearerReady, PRActivities::CBindToActivity::TSendBindTo, CBindToActivity::TAwaitingBindToCompleteOrError, |
|
222 TErrorTagOr<TTag<KDataClientReady | NetStateMachine::EBackward> >) |
|
223 //} |
|
224 |
|
225 //Binding is finished. If this is not autocommit (see TCFDataClient::TBindTo), the activity will reply TCFDataClient::TBindToComplete |
|
226 //to the sender await for the confirmation (TCFDataClient::TCommitBindTo) or cancelation (TBase::TCancel) from the sender. |
|
227 //If this is autommit, the activity will skip awaiting for TCFDataClient::TCommitBindTo and commit itself. |
|
228 THROUGH_NODEACTIVITY_ENTRY(KBindToComplete, CBindToActivity::TSendBindToComplete, CBindToActivity::TNoTagOrCommit) |
|
229 NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, MeshMachine::TAwaitingMessageState<TCFDataClient::TCommitBindTo>, TErrorTagOr<TTag<KCommit> >) |
|
230 |
|
231 //commiting (either implicit or explicit). |
|
232 NODEACTIVITY_ENTRY(KCommit, CBindToActivity::TCommit, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) |
|
233 |
|
234 //This is not autocommit and the sender has just explicitly cancelled. Alternativelly this is an error path. |
|
235 //Cancelling/processing error entiles sending TCancel to all dataclients awaiting confirmation |
|
236 //as well as it entiles leaving the new service provider. |
|
237 NODEACTIVITY_ENTRY(KErrorTag, CBindToActivity::TCancel, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) |
|
238 |
|
239 LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) |
|
240 NODEACTIVITY_END() |
|
241 } |
|
242 |
|
243 namespace PRStartActivity |
|
244 { |
|
245 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, PRStart, TCFServiceProvider::TStart, PRActivities::CStartActivity::NewL) |
|
246 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStart, CoreNetStates::TNoTagOrBearerPresentBlockedByStop) |
|
247 NODEACTIVITY_ENTRY(KBearerPresent, CoreNetStates::TBindSelfToPresentBearer, CoreNetStates::TAwaitingBindToComplete, TTag<KBearerPresent>) |
|
248 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendNoBearer, MeshMachine::TAwaitingMessageState<TCFControlProvider::TBearer>, CoreNetStates::TNoTagOrBearerPresentOrErrorTag) |
|
249 |
|
250 //Start the service provider, use the default cancellation. |
|
251 //Forward TCancel to the service provider, wait for TStarted or TError (via the Error Activity) |
|
252 //When TStarted arrives after TCancel the activity will move to the nearest KErrorTag |
|
253 NODEACTIVITY_ENTRY(KBearerPresent, CoreNetStates::TStartServiceProviderRetry, CoreNetStates::TAwaitingStarted, MeshMachine::TNoTagOrErrorTag) |
|
254 LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) |
|
255 //Start data clients, use the default cancellation. |
|
256 //Forward TCancel to the self, wait for TCFDataClient::TStarted or TError (via the Error Activity) |
|
257 //When TCFDataClient::TStarted arrives after TCancel the activity will move to the nearest KErrorTag |
|
258 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStartSelf, CoreNetStates::TAwaitingDataClientStarted, MeshMachine::TNoTagOrErrorTag) |
|
259 NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TErrorTag) |
|
260 LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) |
|
261 LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStarted) |
|
262 NODEACTIVITY_END() |
|
263 } |
|
264 |
|
265 namespace PRStopActivity |
|
266 { |
|
267 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, PRStop, TCFServiceProvider::TStop, MeshMachine::CNodeRetryActivity::NewL) |
|
268 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingStop, TActiveOrNoTagBlockedByBindTo) |
|
269 THROUGH_NODEACTIVITY_ENTRY(KActiveTag, CoreNetStates::TCancelDataClientStart, MeshMachine::TNoTag) |
|
270 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientStopped, CoreNetStates::TNoTagOrNoBearer) |
|
271 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendStop, CoreNetStates::TAwaitingStopped, MeshMachine::TNoTag) |
|
272 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, TTag<CoreNetStates::KNoBearer>) |
|
273 LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, PRStates::TSendStoppedAndGoneDown) |
|
274 NODEACTIVITY_END() |
|
275 } |
|
276 |
|
277 namespace PRDataClientStartActivity |
|
278 { |
|
279 DECLARE_DEFINE_NODEACTIVITY(ECFActivityStartDataClient, PRDataClientStart, TCFDataClient::TStart) |
|
280 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStart, CoreNetStates::TNoTagOrNoDataClients) |
|
281 NODEACTIVITY_ENTRY(KNoTag, PRStates::TStartDataClients, TAcceptErrorState<CoreNetStates::TAwaitingDataClientsStarted>, MeshMachine::TErrorTagOr<MeshMachine::TTag<CoreNetStates::KNoDataClients> >) |
|
282 LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoDataClients, PRStates::TSendDataClientStarted) |
|
283 |
|
284 NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TStopSelf, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TErrorTag) |
|
285 LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TRaiseAndClearActivityError) |
|
286 NODEACTIVITY_END() |
|
287 } |
|
288 |
|
289 namespace PRDataClientStopActivity |
|
290 { |
|
291 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStopDataClient, PRDataClientStop, TCFDataClient::TStop, MeshMachine::CNodeRetryActivity::NewL) |
|
292 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientStop, MeshMachine::TNoTag) |
|
293 THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TProcessDataClientStop, CoreNetStates::TNoTagOrDataClientsToStopBlockedByStarting) |
|
294 |
|
295 NODEACTIVITY_ENTRY(CoreNetStates::KDataClientsToStop, CoreNetStates::TStopDataClients, CoreNetStates::TAwaitingDataClientsStopped, MeshMachine::TNoTag) |
|
296 THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, CoreNetStates::TNoTagOrUnbindOnStop) |
|
297 |
|
298 NODEACTIVITY_ENTRY(CoreNetStates::KUnbind, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) |
|
299 THROUGH_NODEACTIVITY_ENTRY(KNoTag, PRStates::TDestroyOrphanedDataClients, MeshMachine::TNoTag) |
|
300 LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendDataClientStopped) |
|
301 NODEACTIVITY_END() |
|
302 } |
|
303 |
|
304 |
|
305 namespace PRForwardStateChangeActivity |
|
306 { |
|
307 DECLARE_DEFINE_NODEACTIVITY(ECFActivityForwardStateChange, PRForwardStateChange, TCFMessage::TStateChange) |
|
308 NODEACTIVITY_ENTRY(KNoTag, PRStates::TForwardStateChange, MeshMachine::TAwaitingMessageState<TCFMessage::TStateChange>, MeshMachine::TNoTag) |
|
309 NODEACTIVITY_END() |
|
310 } |
|
311 |
|
312 namespace PRDataClientStatusChangeActivity |
|
313 { |
|
314 DECLARE_DEFINE_NODEACTIVITY(ECFActivityDataClientStatusChange, PRDataClientStatusChange, TCFControlProvider::TDataClientStatusChange) |
|
315 NODEACTIVITY_ENTRY(KNoTag, PRStates::THandleDataClientStatusChangeAndDestroyOrphans, CoreNetStates::TAwaitingDataClientStatusChange, MeshMachine::TNoTag) |
|
316 NODEACTIVITY_END() |
|
317 } |
|
318 |
|
319 namespace PRGoneDownActivity |
|
320 { |
|
321 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGoneDown, PRGoneDown, TCFControlClient::TGoneDown, CGoneDownActivity::NewL) |
|
322 // Our Service Provider has gone down unexpectedly (we haven't issued a TStop) |
|
323 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneDown, MeshMachine::TNoTag) |
|
324 THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TCancelAndCloseZone0ClientExtIfaces, MeshMachine::TNoTag) |
|
325 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProvider, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) |
|
326 NODEACTIVITY_ENTRY(KNoTag, CGoneDownActivity::TSendErrorRecoveryReq, MeshMachine::TAwaitingErrorRecoveryResponseOrError, CoreStates::TRetryOrIgnoreOrPropagate) |
|
327 THROUGH_NODEACTIVITY_ENTRY(CoreStates::KRetry, MeshMachine::TDoNothing, CGoneDownActivity::TIgnoreOrPropagate) |
|
328 LAST_NODEACTIVITY_ENTRY(CoreStates::KIgnore, MeshMachine::TDoNothing) |
|
329 NODEACTIVITY_ENTRY(CoreStates::KPropagate, CoreNetStates::TCancelStartAndStopSelf, CoreNetStates::TAwaitingDataClientStopped, MeshMachine::TNoTag) |
|
330 LAST_NODEACTIVITY_ENTRY(KNoTag, PRStates::TSendGoneDown) |
|
331 NODEACTIVITY_END() |
|
332 } |
|
333 |
|
334 |
|
335 namespace PRGoneUpActivity |
|
336 { |
|
337 // This Activity forward the TGoneUp event to the Control Clients nodes that are |
|
338 // not in the originator lis |
|
339 |
|
340 DECLARE_DEFINE_NODEACTIVITY(ECFActivityGoneUp, PRGoneUp, TCFControlClient::TGoneUp) |
|
341 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneUp, MeshMachine::TNoTag) |
|
342 LAST_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendGoneUp) |
|
343 NODEACTIVITY_END() |
|
344 } |
|
345 |
|
346 namespace PRLegacyRMessage2HandlerActivity |
|
347 { |
|
348 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityLegacyRMessage2Handler, PRLegacyRMessage2Handler, TNodeSignal::TNullMessageId, MeshMachine::CNodeParallelMessageStoreActivityBase::NewL) |
|
349 FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingLegacyRMessage2Ext, MeshMachine::TNoTag) |
|
350 NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TProcessOrForwardRMessage2Ext, CoreNetStates::TAwaitingRMessage2Processed, MeshMachine::TNoTag) |
|
351 LAST_NODEACTIVITY_ENTRY(KNoTag, CoreStates::TPostToOriginators) |
|
352 NODEACTIVITY_END() |
|
353 } |
|
354 |
|
355 |
|
356 namespace CoreActivities |
|
357 { |
|
358 DECLARE_DEFINE_ACTIVITY_MAP(coreActivitiesAll) |
|
359 ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError) //Must be first in the table |
|
360 ACTIVITY_MAP_END() |
|
361 |
|
362 //-========================================================= |
|
363 // |
|
364 //Error Activity |
|
365 // |
|
366 //-========================================================= |
|
367 MeshMachine::CNodeActivityBase* CErrorActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ) |
|
368 { |
|
369 TUint c = GetNextActivityCountL(aActivitySig,aNode); |
|
370 return new(ELeave)CErrorActivity(aActivitySig, aNode, c); |
|
371 } |
|
372 |
|
373 CErrorActivity::CErrorActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount) |
|
374 : MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aActivitiesCount), iErroredActivityId(MeshMachine::KActivityNull) |
|
375 { |
|
376 } |
|
377 |
|
378 CErrorActivity::~CErrorActivity() |
|
379 { |
|
380 if (Error() != KErrNone) |
|
381 { |
|
382 CNodeActivityBase* a = iNode.FindActivityById(iErroredActivityId); |
|
383 if (a) |
|
384 { |
|
385 a->SetError(Error()); |
|
386 a->SetIdle(); |
|
387 } |
|
388 } |
|
389 SetError(KErrNone); |
|
390 } |
|
391 |
|
392 TBool CErrorActivity::IsIdle() const |
|
393 { |
|
394 return NetStateMachine::ACore::IsIdle(); |
|
395 } |
|
396 |
|
397 void CErrorActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& /*aOriginator*/, const TStateTriple& aFirst) |
|
398 { |
|
399 __ASSERT_DEBUG(IsIdle(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 1)); |
|
400 MESH_LOG_ACTIVITY_EXT(KESockMeshMachine, this, &aContext, (_L8("CErrorActivity %08x:\tStartL->starting activity"), this)); |
|
401 |
|
402 NetStateMachine::ACore::Start(&aContext, aFirst); |
|
403 |
|
404 MESH_LOG_ACTIVITY_EXT(KESockMeshMachine, this, &aContext, (_L8("CErrorActivity %08x:\tStartL->activity started"),this)); |
|
405 } |
|
406 |
|
407 TBool CErrorActivity::Next(TNodeContextBase& aContext) |
|
408 { |
|
409 TBool ret = EFalse; |
|
410 |
|
411 |
|
412 if (aContext.iMessage.IsMessage<TEBase::TCancel>()) |
|
413 { |
|
414 CNodeActivityBase* a = iNode.FindActivityById(iErroredActivityId); |
|
415 //Special handling for TCancel. |
|
416 if (a && a->FindOriginator(aContext.iSender) != KErrNotFound) |
|
417 { |
|
418 ret = ETrue; |
|
419 //iActiviy could have handled it, but chose not to. |
|
420 Cancel(aContext); |
|
421 //consume the message, otherwise the iActivity will get idled and iActivity reference |
|
422 //will become invalid. |
|
423 aContext.iMessage.ClearMessageId(); |
|
424 } |
|
425 } |
|
426 else |
|
427 { |
|
428 //If we have sent TErrorRecoveryRequest, we had to have set PostedToId() to the recipient (ControlProvider) |
|
429 //as otherwise there would be no path for propagating the potential TCancel. |
|
430 //The response however (TErrorRecoveryResponse or TError) will not necesserily come from that recipient (CP) |
|
431 //(for example it could be coming from the MCpr and we could be the SCpr). |
|
432 //Normally this would be a problem because any unrelated TError message arriving to the node |
|
433 //and presented to the awaiting state would easily be confused with the response (TError == no recovery on the MCpr == EPropagate). |
|
434 //We avoid the problem by checking all arriving messages if they are adressed to our activity (but we don't |
|
435 //check the sender. |
|
436 const TNodeCtxId* recipient = address_cast<const TNodeCtxId>(&aContext.iRecipient); |
|
437 if (recipient && (ActivityId() == recipient->NodeCtx())) |
|
438 { |
|
439 ret = ACore::Next(&aContext); |
|
440 if(ret) |
|
441 { |
|
442 MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CNodeActivityBase %08x:\tNext->transition"), this)); |
|
443 } |
|
444 } |
|
445 } |
|
446 return ret; |
|
447 } |
|
448 |
|
449 EXPORT_DEFINE_SMELEMENT(CErrorActivity::TAwaitingError, NetStateMachine::MState, CErrorActivity::TContext) |
|
450 EXPORT_C TBool CErrorActivity::TAwaitingError::Accept() |
|
451 { |
|
452 if (! iContext.iMessage.IsMessage<TEBase::TError>()) |
|
453 { |
|
454 return EFalse; |
|
455 } |
|
456 |
|
457 TEBase::TError& errorMessage = message_cast<TEBase::TError>(iContext.iMessage); |
|
458 |
|
459 //Diagnostic panic only. TError message should not be travelling around with KErrNone. |
|
460 //If you see this panic, please send a proper error code. |
|
461 __ASSERT_DEBUG(errorMessage.iValue != KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 2)); |
|
462 |
|
463 MeshMachine::CNodeActivityBase* aa = iContext.Node().FindAddressedActivity(iContext); |
|
464 |
|
465 //TError is always a response. If there is no activity addressed by the TError, |
|
466 //then we assume the activity hasn't bothered waiting for the result. |
|
467 //We hence ignore the error. |
|
468 if (aa) |
|
469 { |
|
470 aa->SetError(errorMessage.iValue); |
|
471 aa->SetIdle(); |
|
472 } |
|
473 errorMessage.ClearMessageId(); |
|
474 return EFalse; |
|
475 } |
|
476 |
|
477 DEFINE_SMELEMENT(CErrorActivity::TCFAwaitingError, NetStateMachine::MState, CErrorActivity::TContext) |
|
478 EXPORT_C TBool CErrorActivity::TCFAwaitingError::Accept() |
|
479 { |
|
480 if (! iContext.iMessage.IsMessage<TEBase::TError>()) |
|
481 { |
|
482 return EFalse; |
|
483 } |
|
484 |
|
485 TEBase::TError& errorMessage = message_cast<TEBase::TError>(iContext.iMessage); |
|
486 |
|
487 //Diagnostic panic only. TError message should not be travelling around with KErrNone. |
|
488 //If you see this panic, please send a proper error code. |
|
489 __ASSERT_DEBUG(errorMessage.iValue != KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 3)); |
|
490 |
|
491 RNodeInterface* client = iContext.Node().FindClient(iContext.iSender); |
|
492 if (client && |
|
493 client->Type() & TCFClientType::EServProvider && |
|
494 iContext.Node().ControlProvider() != NULL && |
|
495 iContext.Node().CountActivities(ECFActivityDestroy) == 0) |
|
496 { |
|
497 //this is the only way out into the activity and into error recovery steps |
|
498 //that error activity is responsible for doing. |
|
499 return ETrue; |
|
500 } |
|
501 |
|
502 return CErrorActivity::TAwaitingError::Accept(); |
|
503 } |
|
504 |
|
505 //Simply leaving from this DoL will NOT have the effect of sending TError to originators |
|
506 //of the Errored activity! iContext.iNodeActivity is the Error activity. |
|
507 //Reassign iContext.iNodeActivity before leaving or handle the error. |
|
508 EXPORT_DEFINE_SMELEMENT(CErrorActivity::TSendErrorRecoveryReq, NetStateMachine::MStateTransition, CErrorActivity::TContext) |
|
509 EXPORT_C void CErrorActivity::TSendErrorRecoveryReq::DoL() |
|
510 { |
|
511 //Find matching activity, if any |
|
512 MeshMachine::CNodeActivityBase* aa = iContext.Node().FindAddressedActivity(iContext); |
|
513 //we are started based on the fact the the last message iContext.Node()'s received is TError |
|
514 TEBase::TError& errmsg = message_cast<TEBase::TError>(iContext.iMessage); |
|
515 |
|
516 //The error comes from someone else than our Data Client (or we wouldn't be here). |
|
517 //It may be our Service Provider or it can be some other node which has originated |
|
518 //an activity on us (in which case the errored activity must be present). |
|
519 if (aa==NULL) |
|
520 { |
|
521 __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ASendErrorRecoveryReq::DoL - TError but no addressed activity - ignoring"))); |
|
522 #ifdef SYMBIAN_NETWORKING_UPS |
|
523 // Terminate the error activity (not UPS specific). |
|
524 iContext.iNodeActivity->SetIdle(); |
|
525 #endif //SYMBIAN_NETWORKING_UPS |
|
526 return; |
|
527 } |
|
528 |
|
529 AContextStore* intf = NULL; |
|
530 if (aa->SupportsExtInterface(AContextStore::KInterfaceId)) |
|
531 { |
|
532 //FetchExtInterfaceL below can never leave because it is being checked few lines above in the "if" |
|
533 intf = reinterpret_cast<AContextStore*>(aa->FetchExtInterfaceL(AContextStore::KInterfaceId)); |
|
534 } |
|
535 |
|
536 //Check if there is any point in sending Error Recovery Request |
|
537 if (intf==NULL || !intf->IsStored() || !iContext.Node().ControlProvider()) |
|
538 { |
|
539 __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ERROR: ASendErrorRecoveryReq::DoL - KErrNotSupported"))); |
|
540 iContext.iNodeActivity->SetIdle(); |
|
541 aa->SetError(errmsg.iValue); |
|
542 aa->SetIdle(); |
|
543 return; |
|
544 } |
|
545 |
|
546 //Determine who TErrorRecoveryRequest should be sent to. |
|
547 //If there is no ControlProvider we send a RecoveryRequest to ourselves to recover from the error, |
|
548 //otherwise we sned the RecoveryRequest up to our ControlProvider. |
|
549 //MCPrs typically put all of the error recovery function in a single error recovery activity therefore |
|
550 //it makes sense even for MCPrs to send TErrorRecoveryRequest to their error recovery function. By |
|
551 //posting a TErrorRecoveryRequest sub-classes of the MCPrs get a chance to override the default error |
|
552 //recovery. |
|
553 RNodeInterface* errorRecoverer = iContext.Node().ControlProvider() ? iContext.Node().ControlProvider() : &iContext.Node().SelfInterface(); |
|
554 |
|
555 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
556 CoreActivities::CErrorActivity& activity = static_cast<CoreActivities::CErrorActivity&>(*iContext.iNodeActivity); |
|
557 __ASSERT_DEBUG(activity.iErroredActivityId==MeshMachine::KActivityNull, User::Panic(KSpecAssert_ESockCrStaCPRAC, 4)); |
|
558 // Save a reference to the activity and a point |
|
559 // Each time we use the activity, query it from the node, because the activity may have gone away (originator left node etc) |
|
560 activity.iErroredActivityId = aa->ActivityId(); |
|
561 |
|
562 activity.SetError(errmsg.iValue); |
|
563 activity.iMessageId = errmsg.iMsgId; |
|
564 |
|
565 TErrContext ctx(iContext.NodeId(), errmsg.iMsgId, aa->ActivitySigId(), TStateChange(0, errmsg.iValue)); |
|
566 TEErrorRecovery::TErrorRecoveryRequest msg(ctx); |
|
567 |
|
568 activity.PostRequestTo( |
|
569 *errorRecoverer,//ControlProvider() verified above |
|
570 TCFSafeMessage::TRequestCarrierEast<TEErrorRecovery::TErrorRecoveryRequest>(msg).CRef() |
|
571 ); |
|
572 |
|
573 //The original activiy might have set 'sent to', but that's surely |
|
574 //not meaningful anymore (we've just received a response from that 'sent to'). |
|
575 //We could have pretended that the orginal activity knows it's sent |
|
576 //error recovery to the control provider but it's best just to clear |
|
577 //'sent to' (and handle TCancel from here (CErrorActivity::Next()). |
|
578 aa->ClearPostedTo(); |
|
579 } |
|
580 |
|
581 EXPORT_DEFINE_SMELEMENT(CErrorActivity::TDoErrorRecovery, NetStateMachine::MStateTransition, CErrorActivity::TContext) |
|
582 EXPORT_C void CErrorActivity::TDoErrorRecovery::DoL() |
|
583 { |
|
584 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
585 CoreActivities::CErrorActivity* act = static_cast<CoreActivities::CErrorActivity*>(iContext.iNodeActivity); |
|
586 CNodeActivityBase* a = iContext.Node().FindActivityById(act->iErroredActivityId); |
|
587 if (a == NULL) |
|
588 { |
|
589 iContext.iNodeActivity->SetIdle(); |
|
590 return; |
|
591 } |
|
592 |
|
593 if (iContext.iMessage.IsMessage<TEErrorRecovery::TErrorRecoveryResponse>()) |
|
594 { |
|
595 TErrResponse& resp = message_cast<TEErrorRecovery::TErrorRecoveryResponse>(iContext.iMessage).iErrResponse; |
|
596 if (resp.iAction == TErrResponse::ERetry) |
|
597 { //rerun current transition |
|
598 __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ADoErrorRecovery::DoL - instructed to retry"))); |
|
599 __ASSERT_DEBUG(a->SupportsExtInterface(AContextStore::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
600 |
|
601 AContextStore* intf = reinterpret_cast<AContextStore*>(a->FetchExtInterfaceL(AContextStore::KInterfaceId)); |
|
602 __ASSERT_DEBUG(intf->IsStored(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 5)); |
|
603 intf->Retry(*a,iContext); |
|
604 if (iContext.iReturn == KErrNone) |
|
605 { //retry succeded |
|
606 act->SetError(KErrNone); |
|
607 } |
|
608 //if Retry had failed, then the d'tor of act will raise the error on |
|
609 //and terminate act->iActivity, |
|
610 } |
|
611 else if (resp.iAction == TErrResponse::EPropagate) |
|
612 { //set new error values and fall through |
|
613 __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, _L8("ADoErrorRecovery::DoL - instructed to propagate the error"))); |
|
614 act->iMessageId = resp.iMessageId; |
|
615 a->SetError(resp.iError); |
|
616 } |
|
617 else //if (resp.iAction == TErrResponse::EIgnore) |
|
618 { |
|
619 __CFLOG_VAR((KCoreProviderStatesTag, KCoreProviderStatesSubTag, |
|
620 _L8("WARNING: ADoErrorRecovery::DoL() - instructed to ignore the error!"))); |
|
621 } |
|
622 } |
|
623 } |
|
624 |
|
625 |
|
626 //-========================================================= |
|
627 // |
|
628 //Destroy Activity - will delete the node when destructed |
|
629 // |
|
630 //-========================================================= |
|
631 |
|
632 EXPORT_C MeshMachine::CNodeActivityBase* CDestroyActivity::New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
633 { |
|
634 TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CDestroyActivity)); |
|
635 CDestroyActivity* self = new (space) CDestroyActivity(aActivitySig, aNode); |
|
636 self->InsertPreallocatedDestroyActivity(); //Destructing preallocated activity |
|
637 return self; |
|
638 } |
|
639 |
|
640 CDestroyActivity::CDestroyActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
641 : CNodeRetryActivity(aActivitySig, aNode), |
|
642 APreallocatedOriginators<1>(iOriginators) |
|
643 { |
|
644 //Mark the provider for deletion, so that it's not served by the factory from now on. |
|
645 static_cast<ESock::CMMCommsProviderBase&>(iNode).MarkMeForDeletion(); |
|
646 } |
|
647 |
|
648 void CDestroyActivity::Destroy() |
|
649 { |
|
650 ReturnPreallocatedSpace(this); |
|
651 this->~CDestroyActivity(); //Run the destructor |
|
652 |
|
653 //Delete the provider. |
|
654 static_cast<ESock::CMMCommsProviderBase&>(iNode).DeleteMeNow(); |
|
655 } |
|
656 |
|
657 TBool CDestroyActivity::Next(TNodeContextBase& aContext) |
|
658 { |
|
659 if (aContext.iMessage.IsMessage<TEBase::TCancel>()) |
|
660 { |
|
661 return ETrue; |
|
662 } |
|
663 else |
|
664 return CNodeActivityBase::Next(aContext); |
|
665 } |
|
666 |
|
667 EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) |
|
668 EXPORT_C TInt CDestroyActivity::TNoTagOrNoTagBackwards::TransitionTag() |
|
669 { |
|
670 if (iContext.iMessage.IsMessage<TEChild::TLeft>()) |
|
671 { |
|
672 TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData|TCFClientType::ECtrl)); |
|
673 __ASSERT_DEBUG(iter[0], User::Panic(KSpecAssert_ESockCrStaCPRAC, 7)); //One leaving client must still be there. |
|
674 return iter[1] == NULL ? MeshMachine::KNoTag : MeshMachine::KNoTag | NetStateMachine::EBackward; |
|
675 } |
|
676 else if (iContext.iMessage.IsMessage<TEPeer::TLeaveComplete>()) |
|
677 { |
|
678 __ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl|TCFClientType::EData))==NULL, |
|
679 User::Panic(KCorePrPanic, KPanicClientsStillPresent)); |
|
680 if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider))==NULL) |
|
681 { |
|
682 return NetStateMachine::EForward | MeshMachine::KNoTag; |
|
683 } |
|
684 return NetStateMachine::EBackward | MeshMachine::KNoTag; //Loop back to the same triple (& remove the peer) |
|
685 } |
|
686 __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCrStaCPRAC, 8)); |
|
687 return KNoTag; |
|
688 } |
|
689 |
|
690 EXPORT_DEFINE_SMELEMENT(CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave, NetStateMachine::MStateTransition, PRStates::TContext) |
|
691 EXPORT_C void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::DoL() |
|
692 { |
|
693 if (iContext.iMessage.IsMessage<TEChild::TLeft>()) |
|
694 { |
|
695 ProcessClientLeaveL(); |
|
696 } |
|
697 else |
|
698 { |
|
699 MakeClientsLeaveL(); |
|
700 } |
|
701 } |
|
702 |
|
703 void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::MakeClientsLeaveL() |
|
704 { |
|
705 __ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::ECtrl))==NULL, |
|
706 User::Panic(KCorePrPanic, KPanicClientsStillPresent)); |
|
707 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
708 iContext.iNodeActivity->ClearPostedTo(); |
|
709 |
|
710 //MZTODO: this asserion may need to be changed since TDestroy can |
|
711 //come while data client is active etc. |
|
712 __ASSERT_DEBUG(iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, TCFClientType::EActive|TCFClientType::EActivating|TCFClientType::EStarting|TCFClientType::EStarted))==NULL, |
|
713 User::Panic(KCorePrPanic, KPanicClientsStillPresent)); |
|
714 |
|
715 TClientIter<TDefaultClientMatchPolicy> dciter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData), TClientType(0, TCFClientType::ELeaving)); |
|
716 RNodeInterface* dc = NULL; |
|
717 while ((dc = dciter[0]) != NULL) //always inspect the first elem as we're invalidating the iterator with each hit. |
|
718 { |
|
719 dc->PostMessage(iContext.NodeId(), TEChild::TDestroy().CRef()); |
|
720 dc->SetFlags(TCFClientType::ELeaving); |
|
721 } |
|
722 } |
|
723 |
|
724 void CDestroyActivity::TMakeClientsLeaveOrProcessClientLeave::ProcessClientLeaveL() |
|
725 { |
|
726 CDestroyActivity::TProcessClientLeave processClientLeave(iContext); |
|
727 processClientLeave.DoL(); |
|
728 } |
|
729 |
|
730 |
|
731 //-========================================================= |
|
732 // |
|
733 //Loppin Activity |
|
734 // |
|
735 //-========================================================= |
|
736 EXPORT_C ACountLoopActivity::~ACountLoopActivity() |
|
737 { |
|
738 } |
|
739 |
|
740 |
|
741 EXPORT_C MeshMachine::CNodeActivityBase* CCountLoopActivityBase::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
742 { |
|
743 return new (ELeave) CCountLoopActivityBase(aActivitySig, aNode); |
|
744 } |
|
745 |
|
746 EXPORT_C CCountLoopActivityBase::CCountLoopActivityBase(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
747 : MeshMachine::CNodeActivityBase(aActivitySig, aNode), |
|
748 TIfStaticFetcherNearestInHierarchy(this) |
|
749 { |
|
750 } |
|
751 |
|
752 EXPORT_C CCountLoopActivityBase::~CCountLoopActivityBase() |
|
753 { |
|
754 } |
|
755 |
|
756 EXPORT_DEFINE_SMELEMENT(ACountLoopActivity::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, PRStates::TContext) |
|
757 EXPORT_C TInt ACountLoopActivity::TNoTagOrNoTagBackwards::TransitionTag() |
|
758 { |
|
759 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
760 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ACountLoopActivity::KInterfaceId),User::Panic(KCorePrPanic, KPanicInterfaceNotSupported)); |
|
761 ACountLoopActivity* countLoopActivity = static_cast<ACountLoopActivity*>(iContext.iNodeActivity->FetchExtInterface(ACountLoopActivity::KInterfaceId)); |
|
762 if (countLoopActivity->DecCount() > 0) |
|
763 { |
|
764 return KNoTag | NetStateMachine::EBackward; |
|
765 } |
|
766 return KNoTag | NetStateMachine::EForward; |
|
767 } |
|
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 //-========================================================= |
|
774 // |
|
775 // |
|
776 //Binding Activity |
|
777 // |
|
778 // |
|
779 //-========================================================= |
|
780 EXPORT_C ABindingActivity::~ABindingActivity() |
|
781 { |
|
782 //Handle premature termination of the ABindingActivity object |
|
783 //by responding to the originator |
|
784 //If the originator has not been replied to yet, reply now with an error code |
|
785 if (IsBinding()) |
|
786 { |
|
787 ReplyToOriginator(KErrAbort); |
|
788 } |
|
789 } |
|
790 |
|
791 EXPORT_C void ABindingActivity::StoreOriginator(const TRuntimeCtxId& aNodeCtxId) |
|
792 { |
|
793 //Check if the originator wasn't set before. If it was, it must be replied to before storing ths new one. |
|
794 __ASSERT_DEBUG(iOriginator.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 9)); |
|
795 iOriginator = aNodeCtxId; |
|
796 } |
|
797 |
|
798 EXPORT_C void ABindingActivity::ReplyToOriginator(TInt aError) |
|
799 { |
|
800 //NOTE: Please do not make this diagnostic panic conditional. |
|
801 //Please allow it to server everyone equally. |
|
802 //Please handle the error conditions properly so that you obey this API's semantics. |
|
803 //If you are not providing a clean error handling solution for your activity, |
|
804 //please use IsBinding() before calling this API! |
|
805 __ASSERT_DEBUG(!iOriginator.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 10)); //The iOriginator must be set. |
|
806 RClientInterface::OpenPostMessageClose(iOurNode, iOriginator, TCFDataClient::TBindToComplete(aError).CRef()); |
|
807 iOriginator.SetNull(); |
|
808 } |
|
809 |
|
810 EXPORT_DEFINE_SMELEMENT(ABindingActivity::TSendBindToComplete, NetStateMachine::MStateTransition, CoreStates::TContext) |
|
811 EXPORT_C void ABindingActivity::TSendBindToComplete::DoL() |
|
812 { |
|
813 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
814 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId), User::Panic(KSpecAssert_ESockCrStaCPRAC, 11)); |
|
815 ABindingActivity* bindingActivity = reinterpret_cast<ABindingActivity*>(iContext.iNodeActivity->FetchExtInterfaceL(ABindingActivity::KInterfaceId)); |
|
816 bindingActivity->ReplyToOriginator(iContext.iNodeActivity->Error()); |
|
817 } |
|
818 |
|
819 EXPORT_DEFINE_SMELEMENT(ABindingActivity::TSendBindToCompleteIfExpected, NetStateMachine::MStateTransition, CoreStates::TContext) |
|
820 EXPORT_C void ABindingActivity::TSendBindToCompleteIfExpected::DoL() |
|
821 { |
|
822 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
823 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(ABindingActivity::KInterfaceId), User::Panic(KSpecAssert_ESockCrStaCPRAC, 12)); |
|
824 ABindingActivity* bindingActivity = reinterpret_cast<ABindingActivity*>(iContext.iNodeActivity->FetchExtInterfaceL(ABindingActivity::KInterfaceId)); |
|
825 if (bindingActivity->IsBinding()) |
|
826 { |
|
827 bindingActivity->ReplyToOriginator(iContext.iNodeActivity->Error()); |
|
828 } |
|
829 } |
|
830 |
|
831 void ABindingActivity::FinalReplyToOriginator(TInt aError) |
|
832 /** |
|
833 Intended to be called from derived class destructors to arrange for a TBindToComplete reply to be sent |
|
834 before any other messages in those derived class destructors (for example TDestroy). |
|
835 */ |
|
836 { |
|
837 if (IsBinding()) |
|
838 { |
|
839 ReplyToOriginator(aError); |
|
840 // Ensure that we don't send another reply in ~ABindingActivity. |
|
841 iOriginator = Messages::TNodeCtxId(); |
|
842 } |
|
843 } |
|
844 |
|
845 } // CoreActivities |
|
846 |
|
847 |
|
848 namespace PRActivities |
|
849 { |
|
850 DECLARE_DEFINE_ACTIVITY_MAP(coreActivitiesPR) |
|
851 ACTIVITY_MAP_ENTRY(PRDataClientJoinActivity, PRDataClientJoin) |
|
852 ACTIVITY_MAP_ENTRY(PRControlClientJoinActivity, PRControlClientJoin) |
|
853 ACTIVITY_MAP_ENTRY(PRClientLeaveActivity, PRClientLeave) |
|
854 ACTIVITY_MAP_ENTRY(PRForwardStateChangeActivity, PRForwardStateChange) |
|
855 ACTIVITY_MAP_ENTRY(PRBindToActivity, PRBindTo) |
|
856 ACTIVITY_MAP_ENTRY(PRDataClientStartActivity, PRDataClientStart) |
|
857 ACTIVITY_MAP_ENTRY(PRDataClientStopActivity, PRDataClientStop) |
|
858 ACTIVITY_MAP_END_BASE(CoreActivities,coreActivitiesAll) |
|
859 |
|
860 //Activity Map provided by CorePr to be used by SCprs. |
|
861 //(it is further extended in CoreSCpr). |
|
862 DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesSCpr) |
|
863 ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) |
|
864 ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) |
|
865 ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) |
|
866 ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) |
|
867 ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) |
|
868 ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) |
|
869 ACTIVITY_MAP_ENTRY(PRGoneDownActivity, PRGoneDown) |
|
870 ACTIVITY_MAP_ENTRY(PRGoneUpActivity, PRGoneUp) //robertomaro |
|
871 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
872 ACTIVITY_MAP_ENTRY(PRSetParamsRequest, PRSetParams) |
|
873 ACTIVITY_MAP_ENTRY(PRGetParamsRequest, PRGetParams) |
|
874 #endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
875 ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) |
|
876 ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) |
|
877 |
|
878 //Activity Map provided by CorePr to be used by Cprs. |
|
879 //(it is further extended in CoreCpr). |
|
880 DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesCpr) |
|
881 ACTIVITY_MAP_ENTRY(PRProvisionActivity, PrProvision) |
|
882 ACTIVITY_MAP_ENTRY(PRStartActivity, PRStart) |
|
883 ACTIVITY_MAP_ENTRY(PRStopActivity, PRStop) |
|
884 ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) |
|
885 ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) |
|
886 ACTIVITY_MAP_ENTRY(PRDestroyActivity, PRDestroy) |
|
887 ACTIVITY_MAP_ENTRY(PRGoneDownActivity, PRGoneDown) |
|
888 ACTIVITY_MAP_ENTRY(PRGoneUpActivity, PRGoneUp) //robertomaro |
|
889 ACTIVITY_MAP_ENTRY(PRDataClientStatusChangeActivity, PRDataClientStatusChange) |
|
890 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
891 ACTIVITY_MAP_ENTRY(PRSetParamsRequest, PRSetParams) |
|
892 ACTIVITY_MAP_ENTRY(PRGetParamsRequest, PRGetParams) |
|
893 #endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
|
894 ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) |
|
895 ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) |
|
896 |
|
897 //Activity Map provided by CorePr to be used by MCprs. |
|
898 //(it is further extended in CoreMCpr). |
|
899 DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesMCpr) |
|
900 ACTIVITY_MAP_ENTRY(PRDataClientIdleActivity, PRDataClientIdle) |
|
901 ACTIVITY_MAP_ENTRY(PRDataClientActiveActivity, PRDataClientActive) |
|
902 ACTIVITY_MAP_ENTRY(PRDataClientStatusChangeActivity, PRDataClientStatusChange) |
|
903 ACTIVITY_MAP_ENTRY(PRLegacyRMessage2HandlerActivity, PRLegacyRMessage2Handler) |
|
904 ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) |
|
905 |
|
906 //Activity Map provided by CorePr to be used by TMs. |
|
907 //(it is further extended in CoreTM). |
|
908 DEFINE_EXPORT_ACTIVITY_MAP(coreActivitiesTM) |
|
909 ACTIVITY_MAP_END_BASE(PRActivities,coreActivitiesPR) |
|
910 |
|
911 |
|
912 |
|
913 |
|
914 //-========================================================= |
|
915 // |
|
916 //CBindToActivity |
|
917 // |
|
918 //-========================================================= |
|
919 EXPORT_C CBindToActivity::CBindToActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TInt aNextActivityCount) |
|
920 : MeshMachine::CNodeParallelActivityBase(aActivitySig, aNode, aNextActivityCount), |
|
921 CoreActivities::ABindingActivity(aNode.Id()), |
|
922 TIfStaticFetcherNearestInHierarchy(this) |
|
923 { |
|
924 } |
|
925 |
|
926 EXPORT_C MeshMachine::CNodeActivityBase* CBindToActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
927 { |
|
928 //there can be only one BindTo activity running at a time. |
|
929 TUint c = GetNextActivityCountL(aActivitySig,aNode); |
|
930 __ASSERT_DEBUG(c == 1,User::Panic(KCorePrPanic, KPanicPeerMisbehaving)); |
|
931 if (c > 1) |
|
932 { |
|
933 User::Leave(KErrInUse); |
|
934 } |
|
935 return new (ELeave) CBindToActivity(aActivitySig, aNode, c); |
|
936 } |
|
937 |
|
938 EXPORT_C CBindToActivity::~CBindToActivity() |
|
939 { |
|
940 //If the activity is aborted then no cleanup will be performed (the destroy activity will do |
|
941 //that for us) so we should not assert that iSuccessfulDataClients is empty or iNewServiceProvider |
|
942 //is null. |
|
943 |
|
944 //CBindToActivity::TCommit or CBindToActivity::TCancel should have been executed |
|
945 //and rendered iSuccessfulDataClients empty. |
|
946 //__ASSERT_DEBUG(iSuccessfulDataClients.Count() == 0, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
947 |
|
948 //CBindToActivity::iNewServiceProvider should have been cleared by CBindToActivity::TCommit or CBindToActivity::TCancel |
|
949 //__ASSERT_DEBUG(iNewServiceProvider == NULL, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
950 |
|
951 iSuccessfulDataClients.Close(); |
|
952 } |
|
953 |
|
954 Messages::RNodeInterface* CBindToActivity::NextDataClient() |
|
955 { |
|
956 TClientIter<TDefaultClientMatchPolicy> iter = iNode.GetClientIter<TDefaultClientMatchPolicy>( |
|
957 /*include*/TClientType(TCFClientType::EData), |
|
958 /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint)); |
|
959 iCurrentDataClient = iter++; |
|
960 while (iCurrentDataClient && (iSuccessfulDataClients.Find(iCurrentDataClient) != KErrNotFound)) |
|
961 { |
|
962 iCurrentDataClient = iter++; |
|
963 }; |
|
964 return iCurrentDataClient; |
|
965 } |
|
966 |
|
967 TBool CBindToActivity::DataClientsAutocommit() |
|
968 { |
|
969 TInt nonLeavingDataClients = iNode.CountClients<TDefaultClientMatchPolicy>( |
|
970 /*include*/TClientType(TCFClientType::EData), |
|
971 /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint)); |
|
972 return nonLeavingDataClients <=1 && IsAutocommit(); |
|
973 } |
|
974 |
|
975 |
|
976 void CBindToActivity::AddClientAsSuccessfulL(Messages::RNodeInterface* aDataClient) |
|
977 { |
|
978 __ASSERT_DEBUG(aDataClient, User::Panic(KCorePrPanic, KPanicDataClient)); |
|
979 __ASSERT_DEBUG(iSuccessfulDataClients.Find(aDataClient) == KErrNotFound, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
980 iSuccessfulDataClients.Append(aDataClient); |
|
981 } |
|
982 |
|
983 void CBindToActivity::RemoveClientFromSuccessful(Messages::RNodeInterface* aDataClient) |
|
984 { |
|
985 TInt index = iSuccessfulDataClients.Find(aDataClient); |
|
986 __ASSERT_DEBUG(index >= 0, User::Panic(KCorePrPanic, KPanicDataClient)); |
|
987 iSuccessfulDataClients.Remove(index); |
|
988 } |
|
989 |
|
990 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendControlClientJoinRequest, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
991 void CBindToActivity::TSendControlClientJoinRequest::DoL() |
|
992 { |
|
993 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
994 CBindToActivity& activity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
995 const TCFDataClient::TBindTo& bindToMsg(message_cast<const TCFDataClient::TBindTo>(iContext.iMessage)); |
|
996 |
|
997 __ASSERT_DEBUG(!bindToMsg.iNodeId.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); |
|
998 RNodeInterface* newServiceProvider = iContext.Node().AddClientL(bindToMsg.iNodeId, |
|
999 TClientType(TCFClientType::EServProvider, TCFClientType::EActivating)); |
|
1000 __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); |
|
1001 activity.iNewServiceProvider = bindToMsg.iNodeId; |
|
1002 //Join the new service provider |
|
1003 iContext.Activity()->PostRequestTo(*newServiceProvider, |
|
1004 TCFControlClient::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::ECtrl)).CRef()); |
|
1005 } |
|
1006 |
|
1007 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TAwaitingBindToCompleteOrError, NetStateMachine::MState, CRejoinDataClientActivity::TContext) |
|
1008 TBool CBindToActivity::TAwaitingBindToCompleteOrError::Accept() |
|
1009 { |
|
1010 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1011 CBindToActivity& activity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1012 if (CoreNetStates::TAwaitingBindToComplete(iContext).Accept()) |
|
1013 { |
|
1014 if (activity.IsBinding()) |
|
1015 { |
|
1016 //Activity is binding (i.e.: we havent received TBindToComplete as a response |
|
1017 //to null-carrying TBindTo. |
|
1018 activity.ReplyToOriginator(KErrNone); |
|
1019 } |
|
1020 activity.ResetCurrentDataClient(); |
|
1021 return ETrue; |
|
1022 } |
|
1023 else if (iContext.iMessage.IsMessage<TEBase::TError>()) |
|
1024 { |
|
1025 activity.ReplyToOriginator(message_cast<TEBase::TError>(iContext.iMessage).iValue); |
|
1026 activity.RemoveClientFromSuccessful(activity.CurrentDataClient()); |
|
1027 activity.ResetCurrentDataClient(); |
|
1028 return ETrue; |
|
1029 } |
|
1030 return EFalse; |
|
1031 } |
|
1032 |
|
1033 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrDataClientReady, NetStateMachine::MStateFork, CBindToActivity::TContext) |
|
1034 TInt CBindToActivity::TNoTagOrDataClientReady::TransitionTag() |
|
1035 { |
|
1036 //Any non-leaving dataclients already present? |
|
1037 if (iContext.Node().CountClients<TDefaultClientMatchPolicy>( |
|
1038 /*include*/TClientType(TCFClientType::EData), |
|
1039 /*exclude*/TClientType(0, TCFClientType::ELeaving | TCFClientType::EConfigAccessPoint))) |
|
1040 { |
|
1041 return KDataClientReady; |
|
1042 } |
|
1043 return KNoTag; |
|
1044 } |
|
1045 |
|
1046 |
|
1047 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TRequestCommsBinder, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
1048 void CBindToActivity::TRequestCommsBinder::DoL() |
|
1049 { |
|
1050 __ASSERT_DEBUG(iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData)),User::Panic(KCorePrPanic, KPanicDataClient)); |
|
1051 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1052 CBindToActivity& activity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1053 |
|
1054 //The service provider has been joined already and must be found here |
|
1055 __ASSERT_DEBUG(!activity.iNewServiceProvider.IsNull(), User::Panic(KCorePrPanic, KPanicNoServiceProvider)); |
|
1056 RNodeInterface* newServiceProvider = iContext.Node().FindClient(activity.iNewServiceProvider); |
|
1057 __ASSERT_DEBUG(newServiceProvider, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); |
|
1058 //We must not be in this transition if dc was not found |
|
1059 __ASSERT_DEBUG(activity.CurrentDataClient(), User::Panic(KCorePrPanic, KPanicDataClient)); |
|
1060 |
|
1061 // Also if it is not so common to have multiple DataClient (except |
|
1062 // for the relation "SCPR<-CPR"), there are situation where it happens |
|
1063 // and where only one of them is marked as Default. |
|
1064 // So, we check if this is the case and, in case the |
|
1065 // Originator of this activity is NOT a Default one, send ECreateNew. |
|
1066 |
|
1067 // If the Current DC is marked as Default, we ask to the lower layer |
|
1068 // to "AttachToDefault". If it is not, we ask "CreateNew". |
|
1069 TInt subConnOpenType = (activity.CurrentDataClient()->Flags() & TCFClientType::EDefault) ? |
|
1070 TSubConnOpen::EAttachToDefault : TSubConnOpen::ECreateNew; |
|
1071 |
|
1072 // --- WORKAROUND START --- |
|
1073 // [399TODO] There are situation were we don't have any DataClient marked |
|
1074 // as Default, but, asking for ECreateNew, the lower layer doesn't |
|
1075 // manage the request very well. |
|
1076 // This is a WORKAROUND and need fixing (see DEF113154). |
|
1077 // In the meanwhile, we count the number of "DefaultDataClient" and, |
|
1078 // if the result is "0", we ask the lower layer "AttachToDefault" |
|
1079 TInt numberOfDefaultDataClient = iContext.Node().CountClients<TDefaultClientMatchPolicy>( |
|
1080 TClientType(TCFClientType::EData, TCFClientType::EDefault) |
|
1081 ); |
|
1082 if (numberOfDefaultDataClient == 0) |
|
1083 { |
|
1084 subConnOpenType = TSubConnOpen::EAttachToDefault; |
|
1085 } |
|
1086 // --- WORKAROUND END --- |
|
1087 |
|
1088 // Send "TCommsBinderRequest" to the Current ServiceProvider |
|
1089 activity.PostRequestTo( |
|
1090 *newServiceProvider, |
|
1091 TCFServiceProvider::TCommsBinderRequest(subConnOpenType).CRef() |
|
1092 ); |
|
1093 } |
|
1094 |
|
1095 |
|
1096 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCreateDataClient, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
1097 void CBindToActivity::TCreateDataClient::DoL() |
|
1098 { |
|
1099 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1100 |
|
1101 IssuePeerCreationRequestL (); |
|
1102 } |
|
1103 |
|
1104 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendBindTo, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
1105 void CBindToActivity::TSendBindTo::DoL() |
|
1106 { |
|
1107 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1108 CBindToActivity& bindToActivity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1109 |
|
1110 //Provisionally stash the current dataclient as successful. If it fails to bind, we'll unstash it |
|
1111 //We're doing this now, as stashing may fail and we don't want that to be the sole reason for |
|
1112 //unrolling. |
|
1113 bindToActivity.AddClientAsSuccessfulL(bindToActivity.CurrentDataClient()); |
|
1114 |
|
1115 TCFServiceProvider::TCommsBinderResponse* commsBinderResponse = message_cast<TCFServiceProvider::TCommsBinderResponse>(&iContext.iMessage); |
|
1116 Messages::TNodeId commsBinder = commsBinderResponse ? commsBinderResponse->iNodeId : Messages::TNodeId::NullId(); |
|
1117 |
|
1118 bindToActivity.PostRequestTo(*bindToActivity.CurrentDataClient(), |
|
1119 TCFDataClient::TBindTo(commsBinder, !bindToActivity.DataClientsAutocommit()).CRef()); |
|
1120 } |
|
1121 |
|
1122 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TSendBindToComplete, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
1123 void CBindToActivity::TSendBindToComplete::DoL() |
|
1124 { |
|
1125 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1126 iContext.iNodeActivity->PostToOriginators(TCFDataClient::TBindToComplete().CRef()); |
|
1127 } |
|
1128 |
|
1129 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrCommit, NetStateMachine::MStateFork, CBindToActivity::TContext) |
|
1130 TInt CBindToActivity::TNoTagOrCommit::TransitionTag() |
|
1131 { |
|
1132 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1133 CBindToActivity& bindToActivity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1134 if (bindToActivity.IsAutocommit()) |
|
1135 { |
|
1136 return KCommit; |
|
1137 } |
|
1138 return KNoTag; |
|
1139 } |
|
1140 |
|
1141 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBindToComplete, NetStateMachine::MStateFork, CBindToActivity::TContext) |
|
1142 EXPORT_C TInt CBindToActivity::TNoTagOrBindToComplete::TransitionTag() |
|
1143 { |
|
1144 TCFFactory::TPeerFoundOrCreated& dcJoined = message_cast<TCFFactory::TPeerFoundOrCreated>(iContext.iMessage); |
|
1145 |
|
1146 if (dcJoined.iNodeId.IsNull()) |
|
1147 { |
|
1148 //Factory decided not to create a dataclient; |
|
1149 return KBindToComplete; |
|
1150 } |
|
1151 |
|
1152 //factory created a new citizen. |
|
1153 return KNoTag; |
|
1154 } |
|
1155 |
|
1156 |
|
1157 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBearerReady, NetStateMachine::MStateFork, CBindToActivity::TContext) |
|
1158 TInt CBindToActivity::TNoTagOrBearerReady::TransitionTag() |
|
1159 { |
|
1160 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1161 CBindToActivity& bindToActivity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1162 TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(iContext.iMessage); |
|
1163 bindToActivity.SetAutocommit(!bindToReq.iValue); |
|
1164 |
|
1165 if (bindToReq.iNodeId.IsNull()) |
|
1166 //received a null service provider, the node is at the stack's bottom. |
|
1167 { |
|
1168 return KBearerReady; |
|
1169 } |
|
1170 |
|
1171 RNodeInterface* sp = iContext.Node().ServiceProvider(); |
|
1172 if (sp && bindToReq.iNodeId == sp->RecipientId()) |
|
1173 { |
|
1174 //received the same service provider, it's already bound to. |
|
1175 bindToActivity.iNewServiceProvider = sp->RecipientId(); |
|
1176 return KBearerReady; |
|
1177 } |
|
1178 RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToReq.iNodeId); |
|
1179 if (newServiceProvider) |
|
1180 { |
|
1181 __ASSERT_DEBUG(newServiceProvider->Type() == TCFClientType::EServProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
1182 //Ok, we've received a TBindTo holding a service provider that we already know of and that is not |
|
1183 //our current service provider. We're going to assume this node tolerates multiple service providers (like MCPRs do). |
|
1184 //the current service provider will be swapped, but won't be dropped. |
|
1185 bindToActivity.iNewServiceProvider = bindToReq.iNodeId; |
|
1186 newServiceProvider->SetFlags(TCFClientType::EActivating); |
|
1187 bindToActivity.SetDontLeaveServiceProvider(); |
|
1188 return KBearerReady; |
|
1189 } |
|
1190 else |
|
1191 { |
|
1192 bindToActivity.iNewServiceProvider = TNodeId::NullId(); |
|
1193 } |
|
1194 //The node received a new service provider... |
|
1195 return KNoTag; |
|
1196 } |
|
1197 |
|
1198 |
|
1199 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TNoTagOrBearerReadyOrBindToComplete, NetStateMachine::MStateFork, CBindToActivity::TContext) |
|
1200 TInt CBindToActivity::TNoTagOrBearerReadyOrBindToComplete::TransitionTag() |
|
1201 { |
|
1202 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1203 CBindToActivity& bindToActivity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1204 |
|
1205 if (!bindToActivity.NextDataClient()) |
|
1206 { |
|
1207 //No more dataclients to bind |
|
1208 return KBindToComplete; |
|
1209 } |
|
1210 |
|
1211 if (bindToActivity.iNewServiceProvider.IsNull()) |
|
1212 { |
|
1213 //There is no service provider (new or old) below us. |
|
1214 return KBearerReady; |
|
1215 } |
|
1216 |
|
1217 return KNoTag; |
|
1218 } |
|
1219 |
|
1220 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCommit, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
1221 void CBindToActivity::TCommit::DoL() |
|
1222 { |
|
1223 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1224 CBindToActivity& bindToActivity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1225 |
|
1226 TInt count = bindToActivity.DataClientsAutocommit() ? 0 : bindToActivity.iSuccessfulDataClients.Count(); |
|
1227 while (count ) |
|
1228 { |
|
1229 bindToActivity.PostRequestTo(*bindToActivity.iSuccessfulDataClients[--count], TCFDataClient::TCommitBindTo().CRef()); |
|
1230 }; |
|
1231 bindToActivity.iSuccessfulDataClients.Reset(); |
|
1232 RNodeInterface* sp = iContext.Node().ServiceProvider(); |
|
1233 |
|
1234 if (sp && sp->RecipientId() != bindToActivity.iNewServiceProvider) |
|
1235 { |
|
1236 if (bindToActivity.ShouldLeaveServiceProvider()) |
|
1237 { |
|
1238 bindToActivity.PostRequestTo(*sp, TEPeer::TLeaveRequest().CRef()); |
|
1239 sp->SetFlags(TCFClientType::ELeaving); |
|
1240 } |
|
1241 else |
|
1242 { |
|
1243 //Didn't leave, no need for waiting for TLeaveComplete; |
|
1244 bindToActivity.SetIdle(); |
|
1245 } |
|
1246 sp->ClearFlags(TCFClientType::EActive); |
|
1247 } |
|
1248 else |
|
1249 { |
|
1250 //Didn't leave, no need for waiting for TLeaveComplete; |
|
1251 bindToActivity.SetIdle(); |
|
1252 } |
|
1253 |
|
1254 if (!bindToActivity.iNewServiceProvider.IsNull() && (sp == NULL || sp->RecipientId() != bindToActivity.iNewServiceProvider)) |
|
1255 { |
|
1256 RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); |
|
1257 if (newServiceProvider) |
|
1258 { |
|
1259 __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
1260 newServiceProvider->ClearFlags(TCFClientType::EActivating); |
|
1261 newServiceProvider->SetFlags(TCFClientType::EActive); |
|
1262 // Note: iContext.Node().ServiceProvider() must be re-evaluated in the ASSERT below (i.e. don't use any previously cached value). |
|
1263 __ASSERT_DEBUG(iContext.Node().ServiceProvider() == newServiceProvider, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
1264 } |
|
1265 } |
|
1266 bindToActivity.iNewServiceProvider = TNodeId::NullId(); |
|
1267 } |
|
1268 |
|
1269 EXPORT_DEFINE_SMELEMENT(CBindToActivity::TCancel, NetStateMachine::MStateTransition, CBindToActivity::TContext) |
|
1270 void CBindToActivity::TCancel::DoL() |
|
1271 { |
|
1272 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1273 CBindToActivity& bindToActivity = static_cast<CBindToActivity&>(*iContext.iNodeActivity); |
|
1274 TInt count = bindToActivity.iSuccessfulDataClients.Count(); |
|
1275 while (count ) |
|
1276 { |
|
1277 bindToActivity.PostRequestTo(*bindToActivity.iSuccessfulDataClients[--count], TEBase::TCancel().CRef()); |
|
1278 }; |
|
1279 bindToActivity.iSuccessfulDataClients.Reset(); |
|
1280 |
|
1281 TBool setIdle = ETrue; |
|
1282 if (!bindToActivity.iNewServiceProvider.IsNull()) |
|
1283 { |
|
1284 RNodeInterface* newServiceProvider = iContext.Node().FindClient(bindToActivity.iNewServiceProvider); |
|
1285 if (newServiceProvider && newServiceProvider != iContext.Node().ServiceProvider()) |
|
1286 { |
|
1287 __ASSERT_DEBUG(newServiceProvider->Flags() & TCFClientType::EActivating, User::Panic(KCorePrPanic, KPanicIncorrectState)); |
|
1288 newServiceProvider->ClearFlags(TCFClientType::EActivating); |
|
1289 if (bindToActivity.ShouldLeaveServiceProvider()) |
|
1290 { |
|
1291 bindToActivity.PostRequestTo(*newServiceProvider, TEPeer::TLeaveRequest().CRef()); |
|
1292 newServiceProvider->SetFlags(TCFClientType::ELeaving); |
|
1293 setIdle = EFalse; |
|
1294 } |
|
1295 } |
|
1296 } |
|
1297 |
|
1298 if (setIdle) |
|
1299 { |
|
1300 bindToActivity.SetIdle(); |
|
1301 } |
|
1302 bindToActivity.iNewServiceProvider = TNodeId::NullId(); |
|
1303 } |
|
1304 |
|
1305 |
|
1306 //-========================================================= |
|
1307 // |
|
1308 //Rejoin DataClient Activity |
|
1309 // |
|
1310 //-========================================================= |
|
1311 EXPORT_C MeshMachine::CNodeActivityBase* CRejoinDataClientActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1312 { |
|
1313 TUint c = GetNextActivityCountL(aActivitySig,aNode); |
|
1314 return new(ELeave)CRejoinDataClientActivity(aActivitySig, c, aNode); |
|
1315 } |
|
1316 |
|
1317 CRejoinDataClientActivity::~CRejoinDataClientActivity() |
|
1318 { |
|
1319 if ( iDataClients.Count() ) |
|
1320 { |
|
1321 if (Error() != KErrNone) |
|
1322 { |
|
1323 //An error has occured when processing rejoin as the activity hasn't been properly wrapped |
|
1324 //up. This error must have happened before any of the clients have been added to the new |
|
1325 //owner as such addition must either collectively succeed or collectively fail. Reinstall |
|
1326 //clients in at the current owner. |
|
1327 for (TInt i = 0; i < iDataClients.Count(); i++) |
|
1328 { |
|
1329 if (!(iDataClients[i].iDataClient.Flags() & TCFClientType::EActive)) |
|
1330 { |
|
1331 #ifndef __GCCXML__ |
|
1332 //If the dataclient managed to report idle in the mean time, have him destroyed |
|
1333 RClientInterface::OpenPostMessageClose(iNode.Id(), iDataClients[i].iDataClient.RecipientId(), TEChild::TDestroy().CRef()); |
|
1334 #endif |
|
1335 } |
|
1336 iDataClients[i].iDataClient.ClearFlags(TCFClientType::EActivating); |
|
1337 #ifndef __GCCXML__ |
|
1338 //Simulate client leaving on the new owner. |
|
1339 RClientInterface::OpenPostMessageClose(iDataClients[i].iDataClient.RecipientId(), iDataClients[i].iNewOwner, |
|
1340 TEChild::TLeft().CRef()); |
|
1341 #endif |
|
1342 } |
|
1343 } |
|
1344 else |
|
1345 { |
|
1346 //All clear. Remove the clients for good. |
|
1347 for (TInt i = 0; i < iDataClients.Count(); i++) |
|
1348 { |
|
1349 iNode.RemoveClient(iDataClients[i].iDataClient.RecipientId()); |
|
1350 } |
|
1351 } |
|
1352 } |
|
1353 iDataClients.Reset(); |
|
1354 } |
|
1355 |
|
1356 |
|
1357 void CRejoinDataClientActivity::TCFDataClientJoiningRequest::DispatchL(const TRuntimeCtxId& aSender, const TRuntimeCtxId& aRecipient) |
|
1358 { |
|
1359 const TNodeId& nodeId = address_cast<const TNodeId>(aRecipient); //This message type operates on nodes |
|
1360 MeshMachine::AMMNodeBase* nodeBase = reinterpret_cast<MeshMachine::AMMNodeBase*>(nodeId.Node().FetchNodeInterfaceL(AMMNodeBase::KInterfaceId)); |
|
1361 RNodeInterface* client = NULL; |
|
1362 client = nodeBase->AddClientL(iDataClient, iDataClientType); |
|
1363 client->SetFlags(TCFClientType::EJoining|TCFClientType::EStarted); |
|
1364 RClientInterface::OpenPostMessageClose(nodeId, aSender, TCFPeer::TJoinComplete().CRef()); |
|
1365 } |
|
1366 |
|
1367 |
|
1368 EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TAwaitingJoinComplete, NetStateMachine::MState, CRejoinDataClientActivity::TContext) |
|
1369 TBool CRejoinDataClientActivity::TAwaitingJoinComplete::Accept() |
|
1370 { |
|
1371 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 13)); |
|
1372 if (iContext.iMessage.IsMessage<TCFPeer::TJoinComplete>()) |
|
1373 { |
|
1374 return ETrue; |
|
1375 } |
|
1376 else if (iContext.iMessage.IsMessage<TEBase::TError>()) |
|
1377 { |
|
1378 iContext.iNodeActivity->SetError(message_cast<TEBase::TError>(iContext.iMessage).iValue); |
|
1379 iContext.iNodeActivity->SetIdle(); |
|
1380 iContext.iMessage.ClearMessageId(); |
|
1381 } |
|
1382 return EFalse; |
|
1383 } |
|
1384 |
|
1385 |
|
1386 EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TRejoinDataClient, NetStateMachine::MStateTransition, CRejoinDataClientActivity::TContext) |
|
1387 EXPORT_C void CRejoinDataClientActivity::TRejoinDataClient::DoL() |
|
1388 { |
|
1389 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 14)); |
|
1390 CRejoinDataClientActivity* rejoinActivity = static_cast<CRejoinDataClientActivity*>(iContext.iNodeActivity); |
|
1391 |
|
1392 TCFRejoiningProvider::TRejoinDataClientRequest& rejoinDCMsg = message_cast<TCFRejoiningProvider::TRejoinDataClientRequest>(iContext.iMessage); |
|
1393 RNodeInterface* subject = iContext.Node().FindClient(rejoinDCMsg.iNodeId1); |
|
1394 if (NULL == subject //client not found |
|
1395 || subject->Flags() & TCFClientType::ELeaving //client leaving/gone |
|
1396 || !(subject->Flags() & TCFClientType::EActive)) //client reported idle or never bound to |
|
1397 { |
|
1398 User::Leave(KErrNotFound); |
|
1399 } |
|
1400 if (subject->Flags() & TCFClientType::EActivating) //client requested by someone |
|
1401 { |
|
1402 User::Leave(KErrInUse); |
|
1403 } |
|
1404 |
|
1405 rejoinActivity->iDataClients.AppendL(TMigrationPairs(*subject, rejoinDCMsg.iNodeId2)); |
|
1406 |
|
1407 CRejoinDataClientActivity::TCFDataClientJoiningRequest msg(subject->RecipientId(), subject->ClientType()); |
|
1408 |
|
1409 RClientInterface::OpenPostMessageClose( |
|
1410 iContext.NodeId(), |
|
1411 rejoinDCMsg.iNodeId2, |
|
1412 msg); |
|
1413 |
|
1414 //Set Client being migrated to a new owner.. reference handed over. secure lifetime. |
|
1415 subject->SetFlags(TCFClientType::EActivating); |
|
1416 } |
|
1417 |
|
1418 EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TApplyRejoin, NetStateMachine::MStateTransition, CRejoinDataClientActivity::TContext) |
|
1419 void CRejoinDataClientActivity::TApplyRejoin::DoL() |
|
1420 { |
|
1421 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 15)); |
|
1422 CRejoinDataClientActivity* rejoinActivity = static_cast<CRejoinDataClientActivity*>(iContext.iNodeActivity); |
|
1423 __ASSERT_DEBUG(rejoinActivity->iDataClients.Count(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 16)); |
|
1424 for (TInt i = 0; i < rejoinActivity->iDataClients.Count(); i++) |
|
1425 { |
|
1426 RClientInterface::OpenPostMessageClose(iContext.NodeId(), rejoinActivity->iDataClients[i].iDataClient.RecipientId(), |
|
1427 TCFFlow::TRejoin(rejoinActivity->iDataClients[i].iNewOwner).CRef()); |
|
1428 rejoinActivity->iDataClients[i].iDataClient.SetFlags(TCFClientType::ELeaving); |
|
1429 } |
|
1430 rejoinActivity->PostRequestTo(iContext.NodeId(), TCFScpr::TApplyRequest().CRef()); |
|
1431 } |
|
1432 |
|
1433 EXPORT_DEFINE_SMELEMENT(CRejoinDataClientActivity::TRejoinLoopTag,NetStateMachine::MStateFork, CRejoinDataClientActivity::TContext) |
|
1434 EXPORT_C TInt CRejoinDataClientActivity::TRejoinLoopTag::TransitionTag() |
|
1435 { |
|
1436 if (iContext.iMessage.IsMessage<TCFRejoiningProvider::TRejoinDataClientRequest>()) |
|
1437 { |
|
1438 return CoreStates::KLoopTag | NetStateMachine::EBackward; |
|
1439 } |
|
1440 return MeshMachine::KNoTag | NetStateMachine::EForward; |
|
1441 } |
|
1442 |
|
1443 //-========================================================= |
|
1444 // |
|
1445 // CommsBinderActivity (parallel) |
|
1446 // |
|
1447 //-========================================================= |
|
1448 |
|
1449 EXPORT_C MeshMachine::CNodeActivityBase* CCommsBinderActivity::NewL( const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode ) |
|
1450 { |
|
1451 TUint c = GetNextActivityCountL(aActivitySig,aNode); |
|
1452 return new(ELeave)CCommsBinderActivity(aActivitySig, aNode, c); |
|
1453 } |
|
1454 |
|
1455 EXPORT_C CCommsBinderActivity::CCommsBinderActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aNextActivityCount) |
|
1456 : MeshMachine::CNodeRetryParallelActivity(aActivitySig, aNode, aNextActivityCount), |
|
1457 TIfStaticFetcherNearestInHierarchy(this) |
|
1458 { |
|
1459 } |
|
1460 |
|
1461 //-========================================================= |
|
1462 // |
|
1463 // CCommsBinderActivity |
|
1464 // |
|
1465 // Aggregate class containing common functionality for |
|
1466 // CommsBinderActivity and CCommsBinderCombiningActivity. |
|
1467 // |
|
1468 //-========================================================= |
|
1469 |
|
1470 EXPORT_C TBool CCommsBinderActivity::TDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) |
|
1471 { |
|
1472 TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); |
|
1473 __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 17)); //Diagnostic |
|
1474 if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext)) |
|
1475 { |
|
1476 return EFalse; |
|
1477 } |
|
1478 return ETrue; |
|
1479 } |
|
1480 |
|
1481 EXPORT_C TBool CCommsBinderActivity::TDefaultDataClientMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) |
|
1482 { |
|
1483 TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); |
|
1484 __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 18)); //Diagnostic |
|
1485 if (c == 1 || CCommsBinderActivity::IsDataClientPresent(aContext, TCFClientType::EDefault)) |
|
1486 { |
|
1487 return EFalse; |
|
1488 } |
|
1489 return ETrue; |
|
1490 } |
|
1491 |
|
1492 EXPORT_C /*virtual*/ CCommsBinderActivity::~CCommsBinderActivity() |
|
1493 { |
|
1494 if(!iBinderRequestParameters.IsNull()) |
|
1495 { |
|
1496 iBinderRequestParameters.Close(); |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 EXPORT_C void CCommsBinderActivity::StoreBinder(RNodeInterface* aDataClient) |
|
1501 { |
|
1502 __ASSERT_DEBUG(iPendingBinder == aDataClient || iPendingBinder == NULL, User::Panic(KSpecAssert_ESockCrStaCPRAC, 19)); |
|
1503 iPendingBinder = aDataClient; |
|
1504 } |
|
1505 |
|
1506 EXPORT_C RNodeInterface* CCommsBinderActivity::Binder() const |
|
1507 { |
|
1508 return iPendingBinder; |
|
1509 } |
|
1510 |
|
1511 EXPORT_C void CCommsBinderActivity::StoreBinderRequestParameters(const RCFParameterFamilyBundleC& aBinderRequestParameters) |
|
1512 { |
|
1513 __ASSERT_DEBUG(iBinderRequestParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 20)); |
|
1514 if(! aBinderRequestParameters.IsNull()) |
|
1515 { |
|
1516 iBinderRequestParameters.Open(aBinderRequestParameters); |
|
1517 } |
|
1518 } |
|
1519 |
|
1520 void CCommsBinderActivity::SendCustomFlowProvision() |
|
1521 /** |
|
1522 Send a custom message that provisions a flow with flow parameters |
|
1523 */ |
|
1524 { |
|
1525 __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 21)); |
|
1526 |
|
1527 // Only send the message if we have parameters to send |
|
1528 if(!iBinderRequestParameters.IsNull()) |
|
1529 { |
|
1530 RParameterFamily parameterFamily = |
|
1531 iBinderRequestParameters.FindFamily(KFlowParametersFamily); |
|
1532 |
|
1533 if(!parameterFamily.IsNull()) |
|
1534 { |
|
1535 STypeId typeId = STypeId::CreateSTypeId(CFlowRequestParameters::EUid, CFlowRequestParameters::EType); |
|
1536 CFlowRequestParameters* flowParams = static_cast<CFlowRequestParameters*>(parameterFamily.FindParameterSet(typeId, RParameterFamily::ERequested)); |
|
1537 |
|
1538 iPendingBinder->PostMessage( |
|
1539 iNode.Id(), |
|
1540 TCFInternalEsock::TFlowProvision( |
|
1541 flowParams->GetFlowParams() |
|
1542 ).CRef() |
|
1543 ); |
|
1544 } |
|
1545 } |
|
1546 } |
|
1547 |
|
1548 |
|
1549 void CCommsBinderActivity::SendBinderResponseToOriginator() |
|
1550 /** |
|
1551 Send out CommsBinderResponse to all originators. |
|
1552 |
|
1553 We send to all originators that have joined up until this point, and store this count |
|
1554 in iOriginatorsCountSnapshot. See comment in ProcessBindToComplete(). |
|
1555 */ |
|
1556 { |
|
1557 __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 22)); |
|
1558 |
|
1559 PostRequestTo( |
|
1560 address_cast<Messages::TNodeId>(FirstOriginator().RecipientId()), |
|
1561 TCFServiceProvider::TCommsBinderResponse(iPendingBinder->RecipientId()).CRef()); |
|
1562 |
|
1563 iPendingBinder->SetFlags(TCFClientType::EActivating); |
|
1564 } |
|
1565 |
|
1566 void CCommsBinderActivity::BindToComplete() |
|
1567 { |
|
1568 __ASSERT_DEBUG(iPendingBinder, User::Panic(KSpecAssert_ESockCrStaCPRAC, 23)); |
|
1569 TUint c = iNode.CountActivities(ActivitySigId()); |
|
1570 // Note: this routine can be used with parallel and non-parallel binder activities. In the |
|
1571 // former case we start with multiple activities and eventually end up with a single one. In |
|
1572 // the latter case we have a single activity throughout. |
|
1573 if(c == 1) |
|
1574 { |
|
1575 iPendingBinder->ClearFlags(TCFClientType::EActivating); |
|
1576 } |
|
1577 iPendingBinder = NULL; |
|
1578 } |
|
1579 |
|
1580 // |
|
1581 // CCommsBinderActivity methods that are embedded transitions/states/stateforks |
|
1582 // |
|
1583 |
|
1584 EXPORT_C RNodeInterface* CCommsBinderActivity::IsDataClientPresent(TNodeContextBase& aContext, TUint aClientFlags) |
|
1585 /** |
|
1586 Check if we have a data client and, if so, store it as the binder for this activity. |
|
1587 |
|
1588 @param aContext Node context |
|
1589 @param aClientFlags client flags to use in iterator check |
|
1590 @return ETrue if data client present, else EFalse. |
|
1591 */ |
|
1592 { |
|
1593 // Be careful not to use a client to which we have already sent TDestroy previously. |
|
1594 // Find the first data client that does not have the ELeaving flag set. If all are |
|
1595 // marked ELeaving then return EFalse - they are on the way out and will disappear |
|
1596 // eventually. The effect will be that a new data client will be created. |
|
1597 RNodeInterface* dataClient = aContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData, aClientFlags), TClientType(0, TCFClientType::ELeaving)); |
|
1598 return dataClient; |
|
1599 } |
|
1600 |
|
1601 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrUseExisting, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) |
|
1602 EXPORT_C TInt CCommsBinderActivity::TNoTagOrUseExisting::TransitionTag() |
|
1603 { |
|
1604 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 24)); |
|
1605 TCFServiceProvider::TCommsBinderRequest& msg = message_cast<TCFServiceProvider::TCommsBinderRequest>(iContext.iMessage); |
|
1606 |
|
1607 // Save away the parameters sent to us so that they are accessible during the activity |
|
1608 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1609 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1610 intf->StoreBinderRequestParameters(msg.iFamilyBundle); |
|
1611 |
|
1612 if(msg.iValue == TSubConnOpen::EAttachToDefault) |
|
1613 { |
|
1614 RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext); |
|
1615 if (dc) |
|
1616 { |
|
1617 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1618 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1619 |
|
1620 intf->StoreBinder(dc); |
|
1621 return CoreStates::KUseExisting; |
|
1622 } |
|
1623 } |
|
1624 return MeshMachine::KNoTag; |
|
1625 } |
|
1626 |
|
1627 //MZTODO - logic of: |
|
1628 //TNoTagOrWaitForIncomingOrUseExisting |
|
1629 //& |
|
1630 //TNoTagOrWaitForIncomingOrUseExistingDefault |
|
1631 //has been copied but does not seem right, as both use EDefault? |
|
1632 //Why? |
|
1633 |
|
1634 //[401TODO] DL : Only one of TNoTagOrWaitForIncomingOrUseExisting(Default) is used, is it ok to nuke one? |
|
1635 |
|
1636 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExisting, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) |
|
1637 EXPORT_C TInt CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExisting::TransitionTag() |
|
1638 { |
|
1639 TCFServiceProvider::TCommsBinderRequest& msg = message_cast<TCFServiceProvider::TCommsBinderRequest>(iContext.iMessage); |
|
1640 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 25)); |
|
1641 |
|
1642 if (msg.iValue == TSubConnOpen::EWaitForIncoming) |
|
1643 { |
|
1644 return CoreNetStates::KWaitForIncoming; |
|
1645 } |
|
1646 |
|
1647 else |
|
1648 { |
|
1649 RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext, TCFClientType::EDefault); |
|
1650 if (dc) |
|
1651 { |
|
1652 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1653 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1654 |
|
1655 intf->StoreBinder(dc); |
|
1656 return CoreStates::KUseExisting; |
|
1657 } |
|
1658 } |
|
1659 |
|
1660 return MeshMachine::KNoTag; |
|
1661 } |
|
1662 |
|
1663 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefault, NetStateMachine::MStateFork, CCommsBinderActivity::TContext) |
|
1664 EXPORT_C TInt CCommsBinderActivity::TNoTagOrWaitForIncomingOrUseExistingDefault::TransitionTag() |
|
1665 { |
|
1666 TCFServiceProvider::TCommsBinderRequest& msg = message_cast<TCFServiceProvider::TCommsBinderRequest>(iContext.iMessage); |
|
1667 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 26)); |
|
1668 |
|
1669 if(msg.iValue == TSubConnOpen::EAttachToDefault) |
|
1670 { |
|
1671 RNodeInterface* dc = CCommsBinderActivity::IsDataClientPresent(iContext, TCFClientType::EDefault); |
|
1672 if (dc) |
|
1673 { |
|
1674 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1675 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1676 |
|
1677 intf->StoreBinder(dc); |
|
1678 return CoreStates::KUseExisting; |
|
1679 } |
|
1680 } |
|
1681 else if (msg.iValue == TSubConnOpen::EWaitForIncoming) |
|
1682 { |
|
1683 return CoreNetStates::KWaitForIncoming; |
|
1684 } |
|
1685 return MeshMachine::KNoTag; |
|
1686 } |
|
1687 |
|
1688 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TStorePendingBinder, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) |
|
1689 EXPORT_C void CCommsBinderActivity::TStorePendingBinder::DoL() |
|
1690 { |
|
1691 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 27)); |
|
1692 message_cast<TCFFactory::TPeerFoundOrCreated>(iContext.iMessage); |
|
1693 |
|
1694 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1695 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1696 |
|
1697 intf->StoreBinder(iContext.iPeer); |
|
1698 } |
|
1699 |
|
1700 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TSendBinderResponse, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) |
|
1701 EXPORT_C void CCommsBinderActivity::TSendBinderResponse::DoL() |
|
1702 { |
|
1703 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 28)); |
|
1704 |
|
1705 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1706 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1707 |
|
1708 intf->SendBinderResponseToOriginator(); |
|
1709 } |
|
1710 |
|
1711 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TSendCustomFlowProvision, NetStateMachine::MStateTransition, CCommsBinderActivity::TContext) |
|
1712 EXPORT_C void CCommsBinderActivity::TSendCustomFlowProvision::DoL() |
|
1713 { |
|
1714 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 29)); |
|
1715 |
|
1716 __ASSERT_DEBUG(iContext.iNodeActivity->SupportsExtInterface(CCommsBinderActivity::KInterfaceId), User::Panic(KCorePrPanic, KPanicExtInterfaceNotSupported)); |
|
1717 CCommsBinderActivity* intf = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1718 |
|
1719 intf->SendCustomFlowProvision(); |
|
1720 } |
|
1721 |
|
1722 EXPORT_DEFINE_SMELEMENT(CCommsBinderActivity::TAwaitingBindToComplete, NetStateMachine::MState, PRStates::TContext) |
|
1723 EXPORT_C TBool CCommsBinderActivity::TAwaitingBindToComplete::Accept() |
|
1724 { |
|
1725 CoreNetStates::TAwaitingBindToComplete awaitingBindToComplete(iContext); |
|
1726 if (awaitingBindToComplete.Accept()) |
|
1727 { |
|
1728 CCommsBinderActivity* binderActivity = reinterpret_cast<CCommsBinderActivity*>(iContext.iNodeActivity->FetchExtInterface(CCommsBinderActivity::KInterfaceId)); |
|
1729 __ASSERT_DEBUG(binderActivity, User::Panic(KSpecAssert_ESockCrStaCPRAC, 30)); |
|
1730 binderActivity->BindToComplete(); |
|
1731 iContext.Node().DestroyOrphanedDataClients(); |
|
1732 return ETrue; |
|
1733 } |
|
1734 return EFalse; |
|
1735 } |
|
1736 |
|
1737 //-========================================================= |
|
1738 // |
|
1739 //CNoBearer Activity |
|
1740 // |
|
1741 //-========================================================= |
|
1742 |
|
1743 CNoBearer::CNoBearer(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode, TUint aActivitiesCount) |
|
1744 : MeshMachine::CNodeRetryParallelActivity(aActivitySig, aNode, aActivitiesCount), |
|
1745 ABindingActivity(aNode.Id()), |
|
1746 TIfStaticFetcherNearestInHierarchy(this) |
|
1747 { |
|
1748 } |
|
1749 |
|
1750 /*virtual*/ CNoBearer::~CNoBearer() |
|
1751 { |
|
1752 iNoBearerParameters.Close(); |
|
1753 } |
|
1754 |
|
1755 EXPORT_C MeshMachine::CNodeActivityBase* CNoBearer::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1756 { |
|
1757 TUint c = GetNextActivityCountL(aActivitySig,aNode); |
|
1758 return new(ELeave)CNoBearer(aActivitySig, aNode, c); |
|
1759 } |
|
1760 |
|
1761 EXPORT_C TNodePeerId& CNoBearer::GetOriginator() |
|
1762 { |
|
1763 __ASSERT_DEBUG(iOriginators.Count() == 1, User::Panic(KSpecAssert_ESockCrStaCPRAC, 31)); |
|
1764 return iOriginators[0]; |
|
1765 } |
|
1766 |
|
1767 EXPORT_C void CNoBearer::ReturnInterfacePtrL(CoreActivities::ABindingActivity*& aInterface) |
|
1768 { |
|
1769 aInterface = this; |
|
1770 } |
|
1771 |
|
1772 EXPORT_C TBool CNoBearer::TServiceProviderMutex::IsBlocked(MeshMachine::TNodeContextBase& aContext) |
|
1773 { |
|
1774 TInt c = aContext.Node().CountActivities(aContext.iNodeActivity->ActivitySigId()); |
|
1775 __ASSERT_DEBUG(c>0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 32)); //Diagnostic |
|
1776 if (c == 1 || aContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider)) != 0) |
|
1777 { |
|
1778 return EFalse; |
|
1779 } |
|
1780 return ETrue; |
|
1781 } |
|
1782 |
|
1783 EXPORT_DEFINE_SMELEMENT(CNoBearer::TRequestCommsBinder, NetStateMachine::MStateTransition, CNoBearer::TContext) |
|
1784 EXPORT_C void CNoBearer::TRequestCommsBinder::DoL() |
|
1785 { |
|
1786 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1787 CNoBearer& noBearer = static_cast<CNoBearer&>(*iContext.iNodeActivity); |
|
1788 |
|
1789 RNodeInterface* sp = iContext.Node().ServiceProvider(); |
|
1790 __ASSERT_DEBUG(sp, User::Panic(KCorePrPanic, KPanicNoServiceProvider)); |
|
1791 |
|
1792 TSubConnOpen::TSubConnType type = TSubConnOpen::EAttachToDefault; |
|
1793 if (!(noBearer.GetOriginator().Flags() & TCFClientType::EDefault)) |
|
1794 { |
|
1795 type = TSubConnOpen::ECreateNew; |
|
1796 } |
|
1797 |
|
1798 noBearer.PostRequestTo( |
|
1799 *sp, |
|
1800 TCFServiceProvider::TCommsBinderRequest( |
|
1801 type, noBearer.iNoBearerParameters |
|
1802 ).CRef() |
|
1803 ); |
|
1804 } |
|
1805 |
|
1806 EXPORT_DEFINE_SMELEMENT(CNoBearer::TStoreRequestParameters, NetStateMachine::MStateTransition, CNoBearer::TContext) |
|
1807 EXPORT_C void CNoBearer::TStoreRequestParameters::DoL() |
|
1808 { |
|
1809 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1810 CNoBearer& noBearer = static_cast<CNoBearer&>(*iContext.iNodeActivity); |
|
1811 const TCFControlProvider::TNoBearer& noBearerMessage = message_cast<TCFControlProvider::TNoBearer>(iContext.iMessage); |
|
1812 __ASSERT_DEBUG(noBearer.iNoBearerParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 33)); // handle should be empty when this fn is called |
|
1813 if(noBearerMessage.iFamilyBundle.IsNull()) |
|
1814 { |
|
1815 noBearer.iNoBearerParameters.Open(); |
|
1816 } |
|
1817 else |
|
1818 { |
|
1819 noBearer.iNoBearerParameters.Open(noBearerMessage.iFamilyBundle); |
|
1820 } |
|
1821 } |
|
1822 |
|
1823 EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrDataClientsToStart, NetStateMachine::MStateFork, CNoBearer::TContext) |
|
1824 TInt CNoBearer::TNoTagOrDataClientsToStart::TransitionTag() |
|
1825 { |
|
1826 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1827 CNoBearer& activity = static_cast<CNoBearer&>(*iContext.iNodeActivity); |
|
1828 |
|
1829 const TNodePeerId& originator = activity.GetOriginator(); |
|
1830 __ASSERT_DEBUG(originator.Type() & TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRAC, 34)); |
|
1831 |
|
1832 if (activity.Error() == KErrNone && (originator.Flags() & (TCFClientType::EStarting|TCFClientType::EStarted|TCFClientType::ELeaving)) == 0) |
|
1833 { |
|
1834 //Start dc |
|
1835 return CoreNetStates::KDataClientsToStart; |
|
1836 } |
|
1837 //Finish the activity |
|
1838 return MeshMachine::KNoTag; |
|
1839 } |
|
1840 |
|
1841 EXPORT_DEFINE_SMELEMENT(CNoBearer::TStartOriginatingDataClient, NetStateMachine::MStateTransition, CNoBearer::TContext) |
|
1842 void CNoBearer::TStartOriginatingDataClient::DoL() |
|
1843 { |
|
1844 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1845 CNoBearer& activity = static_cast<CNoBearer&>(*iContext.iNodeActivity); |
|
1846 TNodePeerId& originator = activity.GetOriginator(); |
|
1847 __ASSERT_DEBUG(originator.Type() & TCFClientType::EData, User::Panic(KSpecAssert_ESockCrStaCPRAC, 35)); |
|
1848 activity.PostRequestTo(originator.Peer(), TCFDataClient::TStart().CRef()); |
|
1849 originator.SetFlags(TCFClientType::EStarting); |
|
1850 } |
|
1851 |
|
1852 EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrBearerPresent, NetStateMachine::MStateFork, CNoBearer::TContext) |
|
1853 EXPORT_C TInt CNoBearer::TNoTagOrBearerPresent::TransitionTag() |
|
1854 { |
|
1855 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1856 CNoBearer& noBearer = static_cast<CNoBearer&>(*iContext.iNodeActivity); |
|
1857 const TCFControlProvider::TNoBearer& noBearerMessage = message_cast<TCFControlProvider::TNoBearer>(iContext.iMessage); |
|
1858 __ASSERT_DEBUG(noBearer.iNoBearerParameters.IsNull(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 36)); // should not yet be set when this fn is called |
|
1859 noBearer.iNoBearerParameters.Open(noBearerMessage.iFamilyBundle); |
|
1860 |
|
1861 CoreNetStates::TNoTagOrBearerPresent fork(iContext); |
|
1862 return fork.TransitionTag(); |
|
1863 } |
|
1864 |
|
1865 EXPORT_DEFINE_SMELEMENT(CNoBearer::TNoTagOrBearerPresentForAutostart, NetStateMachine::MStateFork, CNoBearer::TContext) |
|
1866 EXPORT_C TInt CNoBearer::TNoTagOrBearerPresentForAutostart::TransitionTag() |
|
1867 { |
|
1868 TInt cntrlClients = iContext.Node().CountClients<TDefaultClientMatchPolicy>( |
|
1869 /*include*/TClientType(TCFClientType::ECtrl)); |
|
1870 if (cntrlClients > 0 && |
|
1871 iContext.Node().ServiceProvider() && |
|
1872 !(iContext.Node().ServiceProvider()->Flags() & TCFClientType::EStarted)) |
|
1873 { |
|
1874 //This fork calculates if the NoBearer activity (which this fork has been implemented for) |
|
1875 //should attempt to autostart the service provider when returning it to the sender of TNoBearer. |
|
1876 //The philosphy here is that if the local node doesn't have a control client, then there's noone |
|
1877 //that could posibly start it. It will hence decide to autostart as the top layer of what looks |
|
1878 //like an implicit connection. In the future this autostart behaviour should become a specialty |
|
1879 //of someone more concrete (rather than generic function). We are speculating about the implicit |
|
1880 //top layer that could acquire this function if it ever comes into being. |
|
1881 return CoreNetStates::KBearerPresent; |
|
1882 } |
|
1883 return KNoTag; |
|
1884 } |
|
1885 |
|
1886 |
|
1887 //-========================================================= |
|
1888 // |
|
1889 //CStartActivity Activity |
|
1890 // |
|
1891 //-========================================================= |
|
1892 CStartActivity::CStartActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1893 : MeshMachine::CNodeRetryActivity(aActivitySig, aNode), |
|
1894 CoreActivities::ABindingActivity(aNode.Id()), |
|
1895 TIfStaticFetcherNearestInHierarchy(this) |
|
1896 { |
|
1897 } |
|
1898 |
|
1899 EXPORT_C CStartActivity::~CStartActivity() |
|
1900 { |
|
1901 } |
|
1902 |
|
1903 EXPORT_C MeshMachine::CNodeActivityBase* CStartActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1904 { |
|
1905 return new (ELeave) CStartActivity(aActivitySig, aNode); |
|
1906 } |
|
1907 |
|
1908 //-========================================================= |
|
1909 // |
|
1910 //Gone Down Activity |
|
1911 // |
|
1912 //-========================================================= |
|
1913 MeshMachine::CNodeActivityBase* CGoneDownActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1914 { |
|
1915 CGoneDownActivity* self = new (ELeave) CGoneDownActivity(aActivitySig,aNode); |
|
1916 return self; |
|
1917 } |
|
1918 |
|
1919 CGoneDownActivity::CGoneDownActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) |
|
1920 : MeshMachine::CNodeRetryActivity(aActivitySig, aNode) |
|
1921 { |
|
1922 } |
|
1923 |
|
1924 CGoneDownActivity::~CGoneDownActivity() |
|
1925 { |
|
1926 //This is a gone down activity. Error mode is its only/natural state |
|
1927 //CGoneDownActivity inherits ultimatelly from CNodeActivityBase, which |
|
1928 //will attempt to interpret the error mode as a failure to execute (and |
|
1929 //auto respond to orignators), which we don't want. Hence clearing |
|
1930 //the error and allowing 'this' to die peacefully. |
|
1931 SetError(KErrNone); |
|
1932 } |
|
1933 |
|
1934 void CGoneDownActivity::StartL(TNodeContextBase& aContext, const Messages::XNodePeerId& aOriginator, const TStateTriple& aFirst) |
|
1935 { |
|
1936 //399TODO: for the moment ignore duplicated TGoneDown messages |
|
1937 //but this needs to be fixed (someone is sending TGoneDown from TSendDataClientStopped |
|
1938 //hence the problem) |
|
1939 |
|
1940 //ASSERT(IsIdle()); |
|
1941 if (!IsIdle()) |
|
1942 { |
|
1943 return; |
|
1944 } |
|
1945 |
|
1946 //This activity provides service for only one single requestor at a time. |
|
1947 __ASSERT_DEBUG(iOriginators.Count()==0, User::Panic(KSpecAssert_ESockCrStaCPRAC, 37)); //Diagnostic panic |
|
1948 |
|
1949 TCFControlClient::TGoneDown& msg = message_cast<TCFControlClient::TGoneDown>(aContext.iMessage); |
|
1950 SetError(msg.iValue1); |
|
1951 iGoneDownApId = msg.iValue2; |
|
1952 |
|
1953 MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CGoneDownActivity %08x:\tStartL->starting activity"), this)); |
|
1954 NetStateMachine::ACore::Start(&aContext, aFirst); |
|
1955 |
|
1956 MESH_LOG_ACTIVITY_EXT(KMeshMachineSubTag, this, &aContext, (_L8("CGoneDownActivity %08x:\tStartL->activity started"), this)); |
|
1957 (void)aOriginator; |
|
1958 } |
|
1959 |
|
1960 //Find next DC to rebind |
|
1961 TBool CGoneDownActivity::IsIdle() const |
|
1962 { |
|
1963 return NetStateMachine::ACore::IsIdle(); |
|
1964 } |
|
1965 |
|
1966 DEFINE_SMELEMENT(CGoneDownActivity::TSendErrorRecoveryReq, NetStateMachine::MStateTransition, CGoneDownActivity::TContext) |
|
1967 void CGoneDownActivity::TSendErrorRecoveryReq::DoL() |
|
1968 { |
|
1969 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
1970 CGoneDownActivity& activity = static_cast<CGoneDownActivity&>(*iContext.iNodeActivity); |
|
1971 |
|
1972 //TInt error = ExtractErrorCode(iContext.iMessage); |
|
1973 TErrContext ctx(iContext.NodeId(), TCFControlClient::TGoneDown::Id(), activity.ActivitySigId(), TStateChange(0, activity.Error())); |
|
1974 ctx.iInfo = (TAny*)activity.iGoneDownApId; |
|
1975 TEErrorRecovery::TErrorRecoveryRequest msg(ctx); |
|
1976 |
|
1977 //We can not set SetSentTo() to Control Provider, because the response may not be coming from it |
|
1978 //(for example it could be coming from the MCpr and we could be the SCpr). |
|
1979 //Normally this would be a problem because any unrelated TError message arriving to the node |
|
1980 //and presented to the awaiting state would easily be confused with the response (TError == |
|
1981 //no recovery on the MCpr == EPropagate). |
|
1982 //We avoid the problem by checking all arriving TError messages if they are adressed to our activity. |
|
1983 __ASSERT_DEBUG(iContext.Node().ControlProvider(), User::Panic(KCorePrPanic, KPanicNoControlProvider)); |
|
1984 activity.PostRequestTo(*iContext.Node().ControlProvider(), |
|
1985 TCFSafeMessage::TRequestCarrierEast<TEErrorRecovery::TErrorRecoveryRequest>(msg).CRef()); |
|
1986 activity.ClearPostedTo(); |
|
1987 } |
|
1988 |
|
1989 DEFINE_SMELEMENT(CGoneDownActivity::TIgnoreOrPropagate, NetStateMachine::MStateFork, CGoneDownActivity::TContext) |
|
1990 TInt CGoneDownActivity::TIgnoreOrPropagate::TransitionTag() |
|
1991 { |
|
1992 __ASSERT_DEBUG(iContext.iMessage.IsMessage<TEErrorRecovery::TErrorRecoveryResponse>(), User::Panic(KSpecAssert_ESockCrStaCPRAC, 38)); |
|
1993 RNodeInterface* sp = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EServProvider, TCFClientType::EStarted)); |
|
1994 if (sp) |
|
1995 { |
|
1996 return CoreStates::KIgnore | NetStateMachine::EForward; |
|
1997 } |
|
1998 //There is no started service provider, the reconnection, mobility, etc must have failed, |
|
1999 //continue with tearing this layer down. |
|
2000 CGoneDownActivity& activity = static_cast<CGoneDownActivity&>(*iContext.iNodeActivity); |
|
2001 TErrResponse& resp = message_cast<TEErrorRecovery::TErrorRecoveryResponse>(iContext.iMessage).iErrResponse; |
|
2002 resp.iAction=TErrResponse::EPropagate; |
|
2003 __ASSERT_DEBUG(activity.Error()!=KErrNone, User::Panic(KSpecAssert_ESockCrStaCPRAC, 39)); |
|
2004 resp.iError = activity.Error(); |
|
2005 return CoreStates::KPropagate | NetStateMachine::EForward; |
|
2006 } |
|
2007 |
|
2008 |
|
2009 EXPORT_DEFINE_SMELEMENT(CStartActivity::TAwaitingBindToCompleteOrCancel, NetStateMachine::MState, CStartActivity::TContext) |
|
2010 TBool CStartActivity::TAwaitingBindToCompleteOrCancel::Accept() |
|
2011 { |
|
2012 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KCorePrPanic, KPanicNoActivity)); |
|
2013 if (iContext.iMessage.IsMessage<TEBase::TCancel>()) |
|
2014 { |
|
2015 iContext.iNodeActivity->SetError(KErrCancel); |
|
2016 iContext.iMessage.ClearMessageId(); |
|
2017 return EFalse; |
|
2018 } |
|
2019 else |
|
2020 { |
|
2021 CoreNetStates::TAwaitingBindToComplete state(iContext); |
|
2022 return state.Accept(); |
|
2023 } |
|
2024 } |
|
2025 } //PRActivities |
|
2026 |
|
2027 EXPORT_DEFINE_SMELEMENT(PRDataClientStopActivity::TNoTagOrProviderStopped, NetStateMachine::MStateFork, PRDataClientStopActivity::TContext) |
|
2028 EXPORT_C TInt PRDataClientStopActivity::TNoTagOrProviderStopped::TransitionTag() |
|
2029 { |
|
2030 iContext.iNodeActivity->SetError(message_cast<TCFDataClient::TStop>(iContext.iMessage).iValue); |
|
2031 if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>( |
|
2032 TClientType(TCFClientType::EData, TCFClientType::EStarted)) != NULL) |
|
2033 { |
|
2034 // At least one started data client |
|
2035 return MeshMachine::KNoTag; |
|
2036 } |
|
2037 return CoreNetStates::KProviderStopped; |
|
2038 } |
|
2039 |
|
2040 |
|
2041 |