1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lnn_state_machine.h"
17
18 #include <stdlib.h>
19
20 #include <securec.h>
21
22 #include "lnn_log.h"
23 #include "softbus_adapter_mem.h"
24 #include "softbus_def.h"
25 #include "softbus_errcode.h"
26
IsDuplicateState(FsmStateMachine * fsm,FsmState * state)27 static bool IsDuplicateState(FsmStateMachine *fsm, FsmState *state)
28 {
29 struct ListNode *item = NULL;
30
31 LIST_FOR_EACH(item, &fsm->stateList) {
32 if (item == (struct ListNode *)state) {
33 return true;
34 }
35 }
36 return false;
37 }
38
FreeFsmHandleMsg(SoftBusMessage * msg)39 static void FreeFsmHandleMsg(SoftBusMessage *msg)
40 {
41 if (msg != NULL) {
42 if (msg->obj != NULL) {
43 SoftBusFree(msg->obj);
44 }
45 SoftBusFree(msg);
46 }
47 }
48
FreeFsmHandleMsgObj(FsmCtrlMsgObj * ctrlMsgObj)49 static void FreeFsmHandleMsgObj(FsmCtrlMsgObj *ctrlMsgObj)
50 {
51 if (ctrlMsgObj == NULL) {
52 return;
53 }
54 if (ctrlMsgObj->obj != NULL) {
55 SoftBusFree(ctrlMsgObj->obj);
56 ctrlMsgObj->obj = NULL;
57 }
58 }
59
CreateFsmHandleMsg(FsmStateMachine * fsm,int32_t what,uint64_t arg1,uint64_t arg2,void * obj)60 static SoftBusMessage *CreateFsmHandleMsg(FsmStateMachine *fsm,
61 int32_t what, uint64_t arg1, uint64_t arg2, void *obj)
62 {
63 SoftBusMessage *msg = NULL;
64 FsmCtrlMsgObj *ctrlMsgObj = NULL;
65
66 msg = SoftBusCalloc(sizeof(*msg));
67 if (msg == NULL) {
68 LNN_LOGE(LNN_STATE, "calloc msg failed");
69 return NULL;
70 }
71 msg->what = what;
72 msg->arg1 = arg1;
73 msg->arg2 = arg2;
74 msg->handler = &fsm->handler;
75 msg->FreeMessage = FreeFsmHandleMsg;
76
77 ctrlMsgObj = SoftBusMalloc(sizeof(*ctrlMsgObj));
78 if (ctrlMsgObj == NULL) {
79 LNN_LOGE(LNN_STATE, "calloc ctrl msg obj failed");
80 SoftBusFree(msg);
81 return NULL;
82 }
83 ctrlMsgObj->fsm = fsm;
84 ctrlMsgObj->obj = obj;
85 msg->obj = ctrlMsgObj;
86 return msg;
87 }
88
ProcessStartMessage(SoftBusMessage * msg)89 static void ProcessStartMessage(SoftBusMessage *msg)
90 {
91 FsmCtrlMsgObj *ctrlMsgObj = msg->obj;
92 FsmStateMachine *fsm = NULL;
93 FsmState *state = NULL;
94
95 if (ctrlMsgObj == NULL) {
96 LNN_LOGE(LNN_STATE, "unexpected state in start msg process");
97 return;
98 }
99 fsm = ctrlMsgObj->fsm;
100 state = (FsmState *)ctrlMsgObj->obj;
101 if (fsm == NULL || state == NULL) {
102 return;
103 }
104 if (fsm->curState != NULL || (fsm->flag & FSM_FLAG_RUNNING) != 0) {
105 LNN_LOGE(LNN_STATE, "unexpected state in start msg process");
106 return;
107 }
108 if (IsDuplicateState(fsm, state) == true) {
109 fsm->curState = state;
110 if (fsm->curState->enter != NULL) {
111 fsm->curState->enter(fsm);
112 }
113 fsm->flag |= FSM_FLAG_RUNNING;
114 }
115 }
116
ProcessDataMessage(SoftBusMessage * msg)117 static void ProcessDataMessage(SoftBusMessage *msg)
118 {
119 FsmCtrlMsgObj *ctrlMsgObj = msg->obj;
120 FsmStateMachine *fsm = NULL;
121
122 if (ctrlMsgObj == NULL) {
123 LNN_LOGE(LNN_STATE, "unexpected state in data msg=%{public}d process, ctrlMsgObj is null", (int32_t)msg->arg1);
124 return;
125 }
126 fsm = ctrlMsgObj->fsm;
127 if (fsm == NULL) {
128 LNN_LOGE(LNN_STATE, "unexpected state in data msg=%{public}d process, fsm is null", (int32_t)msg->arg1);
129 return;
130 }
131 if (fsm->curState == NULL || (fsm->flag & FSM_FLAG_RUNNING) == 0) {
132 LNN_LOGE(LNN_STATE, "unexpected state in data msg process, arg1=%{public}d, flag=0x%{public}x",
133 (int32_t)msg->arg1, fsm->flag);
134 return;
135 }
136 if (fsm->curState->process != NULL) {
137 fsm->curState->process(fsm, (int32_t)msg->arg1, ctrlMsgObj->obj);
138 }
139 }
140
ProcessStopMessage(SoftBusMessage * msg)141 static void ProcessStopMessage(SoftBusMessage *msg)
142 {
143 FsmCtrlMsgObj *ctrlMsgObj = msg->obj;
144 FsmStateMachine *fsm = NULL;
145
146 if (ctrlMsgObj == NULL) {
147 return;
148 }
149 fsm = ctrlMsgObj->fsm;
150 if (fsm == NULL) {
151 LNN_LOGE(LNN_STATE, "unexpected state in stop msg process");
152 return;
153 }
154 if (fsm->curState == NULL || (fsm->flag & FSM_FLAG_RUNNING) == 0) {
155 LNN_LOGE(LNN_STATE, "unexpected state in stop msg process");
156 return;
157 }
158 fsm->curState = NULL;
159 fsm->flag &= ~FSM_FLAG_RUNNING;
160 }
161
162 /* remove message when return 0, else return 1 */
RemoveAllMessageFunc(const SoftBusMessage * msg,void * para)163 static int32_t RemoveAllMessageFunc(const SoftBusMessage *msg, void *para)
164 {
165 (void)para;
166
167 FreeFsmHandleMsgObj((FsmCtrlMsgObj *)msg->obj);
168 return 0;
169 }
170
ProcessDeinitMessage(SoftBusMessage * msg)171 static void ProcessDeinitMessage(SoftBusMessage *msg)
172 {
173 FsmCtrlMsgObj *ctrlMsgObj = msg->obj;
174 FsmStateMachine *fsm = NULL;
175
176 if (ctrlMsgObj == NULL) {
177 LNN_LOGE(LNN_STATE, "unexpected state in deinit msg process");
178 return;
179 }
180 fsm = ctrlMsgObj->fsm;
181 if (fsm == NULL) {
182 LNN_LOGE(LNN_STATE, "fsm is null in deinit msg process");
183 return;
184 }
185 if (fsm->looper != NULL) {
186 fsm->looper->RemoveMessageCustom(fsm->looper, &fsm->handler, RemoveAllMessageFunc, NULL);
187 }
188 if (fsm->deinitCallback != NULL) {
189 fsm->deinitCallback(fsm);
190 }
191 }
192
FsmStateMsgHandler(SoftBusMessage * msg)193 static void FsmStateMsgHandler(SoftBusMessage *msg)
194 {
195 if (msg == NULL) {
196 LNN_LOGE(LNN_STATE, "process msg is null");
197 return;
198 }
199
200 if (msg->what != FSM_CTRL_MSG_DATA) {
201 LNN_LOGI(LNN_STATE, "process fsm ctrl msgType=%{public}d", msg->what);
202 }
203 switch (msg->what) {
204 case FSM_CTRL_MSG_START:
205 ProcessStartMessage(msg);
206 break;
207 case FSM_CTRL_MSG_DATA:
208 ProcessDataMessage(msg);
209 break;
210 case FSM_CTRL_MSG_STOP:
211 ProcessStopMessage(msg);
212 break;
213 case FSM_CTRL_MSG_DEINIT:
214 ProcessDeinitMessage(msg);
215 break;
216 default:
217 break;
218 }
219 }
220
PostMessageToFsm(FsmStateMachine * fsm,int32_t what,uint64_t arg1,uint64_t arg2,void * obj)221 static int32_t PostMessageToFsm(FsmStateMachine *fsm, int32_t what, uint64_t arg1,
222 uint64_t arg2, void *obj)
223 {
224 SoftBusMessage *msg = NULL;
225
226 msg = CreateFsmHandleMsg(fsm, what, arg1, arg2, obj);
227 if (msg == NULL) {
228 LNN_LOGE(LNN_STATE, "create fsm handle msg fail");
229 return SOFTBUS_ERR;
230 }
231 fsm->looper->PostMessage(fsm->looper, msg);
232 return SOFTBUS_OK;
233 }
234
235 /* remove message when return 0, else return 1 */
RemoveMessageFunc(const SoftBusMessage * msg,void * para)236 static int32_t RemoveMessageFunc(const SoftBusMessage *msg, void *para)
237 {
238 int32_t msgType;
239
240 if (msg == NULL || para == NULL) {
241 return 1;
242 }
243 msgType = (int32_t)(intptr_t)para;
244 if (msg->what == FSM_CTRL_MSG_DATA && (int32_t)msg->arg1 == msgType) {
245 LNN_LOGI(LNN_STATE, "remove fsm data msgType=%{public}d", msgType);
246 FreeFsmHandleMsgObj((FsmCtrlMsgObj *)msg->obj);
247 return 0;
248 }
249 return 1;
250 }
251
LnnFsmInit(FsmStateMachine * fsm,SoftBusLooper * looper,char * name,FsmDeinitCallback cb)252 int32_t LnnFsmInit(FsmStateMachine *fsm, SoftBusLooper *looper, char *name, FsmDeinitCallback cb)
253 {
254 if (fsm == NULL || name == NULL) {
255 return SOFTBUS_INVALID_PARAM;
256 }
257
258 (void)memset_s(fsm, sizeof(*fsm), 0, sizeof(*fsm));
259 ListInit(&fsm->stateList);
260 fsm->looper = looper == NULL ? GetLooper(LOOP_TYPE_DEFAULT) : looper;
261 if (fsm->looper == NULL) {
262 LNN_LOGE(LNN_STATE, "get looper fail");
263 return SOFTBUS_ERR;
264 }
265 fsm->handler.name = name;
266 fsm->handler.HandleMessage = FsmStateMsgHandler;
267 fsm->handler.looper = fsm->looper;
268 fsm->deinitCallback = cb;
269 return SOFTBUS_OK;
270 }
271
LnnFsmDeinit(FsmStateMachine * fsm)272 int32_t LnnFsmDeinit(FsmStateMachine *fsm)
273 {
274 if (fsm == NULL || fsm->looper == NULL) {
275 return SOFTBUS_INVALID_PARAM;
276 }
277 return PostMessageToFsm(fsm, FSM_CTRL_MSG_DEINIT, 0, 0, NULL);
278 }
279
LnnFsmAddState(FsmStateMachine * fsm,FsmState * state)280 int32_t LnnFsmAddState(FsmStateMachine *fsm, FsmState *state)
281 {
282 if (fsm == NULL || fsm->looper == NULL || state == NULL) {
283 return SOFTBUS_INVALID_PARAM;
284 }
285
286 if (IsDuplicateState(fsm, state)) {
287 LNN_LOGE(LNN_STATE, "already exist state");
288 return SOFTBUS_ERR;
289 }
290 ListInit(&state->list);
291 ListAdd(&fsm->stateList, &state->list);
292 return SOFTBUS_OK;
293 }
294
LnnFsmStart(FsmStateMachine * fsm,FsmState * initialState)295 int32_t LnnFsmStart(FsmStateMachine *fsm, FsmState *initialState)
296 {
297 if (fsm == NULL || fsm->looper == NULL || initialState == NULL) {
298 return SOFTBUS_INVALID_PARAM;
299 }
300 return PostMessageToFsm(fsm, FSM_CTRL_MSG_START, 0, 0, initialState);
301 }
302
LnnFsmStop(FsmStateMachine * fsm)303 int32_t LnnFsmStop(FsmStateMachine *fsm)
304 {
305 if (fsm == NULL || fsm->looper == NULL) {
306 return SOFTBUS_INVALID_PARAM;
307 }
308 return PostMessageToFsm(fsm, FSM_CTRL_MSG_STOP, 0, 0, NULL);
309 }
310
LnnFsmPostMessage(FsmStateMachine * fsm,uint32_t msgType,void * data)311 int32_t LnnFsmPostMessage(FsmStateMachine *fsm, uint32_t msgType, void *data)
312 {
313 if (fsm == NULL || fsm->looper == NULL) {
314 return SOFTBUS_INVALID_PARAM;
315 }
316 return PostMessageToFsm(fsm, FSM_CTRL_MSG_DATA, msgType, 0, data);
317 }
318
LnnFsmPostMessageDelay(FsmStateMachine * fsm,uint32_t msgType,void * data,uint64_t delayMillis)319 int32_t LnnFsmPostMessageDelay(FsmStateMachine *fsm, uint32_t msgType,
320 void *data, uint64_t delayMillis)
321 {
322 SoftBusMessage *msg = NULL;
323
324 if (fsm == NULL || fsm->looper == NULL) {
325 return SOFTBUS_INVALID_PARAM;
326 }
327 msg = CreateFsmHandleMsg(fsm, FSM_CTRL_MSG_DATA, msgType, 0, data);
328 if (msg == NULL) {
329 LNN_LOGE(LNN_STATE, "create fsm handle msg fail");
330 return SOFTBUS_ERR;
331 }
332 fsm->looper->PostMessageDelay(fsm->looper, msg, delayMillis);
333 return SOFTBUS_OK;
334 }
335
LnnFsmRemoveMessageByType(FsmStateMachine * fsm,int32_t what)336 int32_t LnnFsmRemoveMessageByType(FsmStateMachine *fsm, int32_t what)
337 {
338 if (fsm == NULL || fsm->looper == NULL) {
339 return SOFTBUS_INVALID_PARAM;
340 }
341 fsm->looper->RemoveMessage(fsm->looper, &fsm->handler, what);
342 return SOFTBUS_OK;
343 }
344
LnnFsmRemoveMessage(FsmStateMachine * fsm,int32_t msgType)345 int32_t LnnFsmRemoveMessage(FsmStateMachine *fsm, int32_t msgType)
346 {
347 if (fsm == NULL || fsm->looper == NULL) {
348 return SOFTBUS_INVALID_PARAM;
349 }
350 fsm->looper->RemoveMessageCustom(fsm->looper, &fsm->handler,
351 RemoveMessageFunc, (void *)(intptr_t)msgType);
352 return SOFTBUS_OK;
353 }
354
LnnFsmRemoveMessageSpecific(FsmStateMachine * fsm,int32_t (* customFunc)(const SoftBusMessage *,void *),void * args)355 int32_t LnnFsmRemoveMessageSpecific(FsmStateMachine *fsm,
356 int32_t (*customFunc)(const SoftBusMessage*, void*), void *args)
357 {
358 if (fsm == NULL || fsm->looper == NULL) {
359 return SOFTBUS_INVALID_PARAM;
360 }
361 fsm->looper->RemoveMessageCustom(fsm->looper, &fsm->handler,
362 customFunc == NULL ? RemoveMessageFunc : customFunc, args);
363 return SOFTBUS_OK;
364 }
365
366 /* we must change state of state machine during its procedure, otherwise it will introduce concurrency */
LnnFsmTransactState(FsmStateMachine * fsm,FsmState * state)367 int32_t LnnFsmTransactState(FsmStateMachine *fsm, FsmState *state)
368 {
369 if (fsm == NULL || state == NULL) {
370 return SOFTBUS_INVALID_PARAM;
371 }
372
373 if (fsm->curState == NULL || (fsm->flag & FSM_FLAG_RUNNING) == 0) {
374 LNN_LOGE(LNN_STATE, "unexpected state in change state process");
375 return SOFTBUS_ERR;
376 }
377
378 if (IsDuplicateState(fsm, state)) {
379 if (fsm->curState->exit != NULL) {
380 fsm->curState->exit(fsm);
381 }
382 fsm->curState = state;
383 if (fsm->curState->enter != NULL) {
384 fsm->curState->enter(fsm);
385 }
386 }
387 return SOFTBUS_OK;
388 }
389