当前位置:   article > 正文

软总线源码分析5: 组网状态机_软总线组网

软总线组网

组网过程首先需要经过设备认证,认证成功后又要交换设备状态信息,成功后设备间才算组完成工。为了管理组网过程中状态的迁移过程和对应处理,组网模块使用状态机来完成整体的业务逻辑。

一.状态机机制

状态机由函数LnnFsmInit完成初始化,其源码如下:

  1. int32_t LnnFsmInit(FsmStateMachine *fsm, char *name, FsmDinitCallback cb)
  2. {
  3. if (fsm == NULL || name == NULL) {
  4. return SOFTBUS_INVALID_PARAM;
  5. }
  6. (void)memset_s(fsm, sizeof(*fsm), 0, sizeof(*fsm));
  7. ListInit(&fsm->stateList);
  8. fsm->looper = GetLooper(LOOP_TYPE_DEFAULT);
  9. if (fsm->looper == NULL) {
  10. LOG_ERR("get looper fail");
  11. return SOFTBUS_ERR;
  12. }
  13. fsm->handler.name = name;
  14. fsm->handler.HandleMessage = FsmStateMsgHandler;
  15. fsm->handler.looper = fsm->looper;
  16. fsm->deinitCallback = cb;
  17. return SOFTBUS_OK;
  18. }

我们可以看到,状态机的结构体为FsmStateMachine,其内部有一个指向Default Looper的指针和对应的handler,为什么状态机要维护Looper和handler呢?

我们可以看一下另外两个接口:1.CreateFsmHandleMsg生成一条提交给状态机的消息;2.PostMessageToFsm将消息提交给状态机。

CreateFsmHandleMsg的源码如下:

  1. static SoftBusMessage *CreateFsmHandleMsg(FsmStateMachine *fsm,
  2. int32_t what, uint64_t arg1, uint64_t arg2, void *obj)
  3. {
  4. SoftBusMessage *msg = NULL;
  5. FsmCtrlMsgObj *ctrlMsgObj = NULL;
  6. msg = SoftBusCalloc(sizeof(*msg));
  7. if (msg == NULL) {
  8. return NULL;
  9. }
  10. msg->what = what;
  11. msg->arg1 = arg1;
  12. msg->arg2 = arg2;
  13. msg->handler = &fsm->handler;
  14. msg->FreeMessage = FreeFsmHandleMsg;
  15. ctrlMsgObj = SoftBusMalloc(sizeof(*ctrlMsgObj));
  16. if (ctrlMsgObj == NULL) {
  17. SoftBusFree(msg);
  18. return NULL;
  19. }
  20. ctrlMsgObj->fsm = fsm;
  21. ctrlMsgObj->obj = obj;
  22. msg->obj = ctrlMsgObj;
  23. return msg;
  24. }

CreateFsmHandleMsg生成一条消息,其结构体为SoftBusMessage,其handler即为状态机维护的handler,关键的HandleMessage函数指针指向的函数为FsmStateMsgHandler。

PostMessageToFsm的源码如下:

  1. static int32_t PostMessageToFsm(FsmStateMachine *fsm, int32_t what, uint64_t arg1, uint64_t arg2, void *obj)
  2. {
  3. SoftBusMessage *msg = NULL;
  4. msg = CreateFsmHandleMsg(fsm, what, arg1, arg2, obj);
  5. if (msg == NULL) {
  6. LOG_ERR("create fsm handle msg fail");
  7. return SOFTBUS_ERR;
  8. }
  9. fsm->looper->PostMessage(fsm->looper, msg);
  10. return SOFTBUS_OK;
  11. }

即调用looper的PostMessage方法,将消息提交给状态机的Looper。

关于Looper的机制,我们在前面的章节介绍过,每当有消息提交到Looper内部的消息队列后,LoopTask函数会根据当前的时间和消息中的时间戳,来判断是否处理该消息。如果消息中的时间戳早于或等于当前时间的话,则调用消息中的HandleMessage函数指针处理该消息。

如前面所说,我们状态机的HandleMessage函数指针指向的函数为FsmStateMsgHandler,其源码如下所示:

  1. static void FsmStateMsgHandler(SoftBusMessage *msg)
  2. {
  3. if (msg == NULL) {
  4. return;
  5. }
  6. if (msg->what != FSM_CTRL_MSG_DATA) {
  7. LOG_INFO("process fsm ctrl msg: %d", msg->what);
  8. }
  9. switch (msg->what) {
  10. case FSM_CTRL_MSG_START:
  11. ProcessStartMessage(msg);
  12. break;
  13. case FSM_CTRL_MSG_CHANGE_STATE:
  14. ProcessChangeStateMessage(msg);
  15. break;
  16. case FSM_CTRL_MSG_DATA:
  17. ProcessDataMessage(msg);
  18. break;
  19. case FSM_CTRL_MSG_STOP:
  20. ProcessStopMessage(msg);
  21. break;
  22. case FSM_CTRL_MSG_DEINIT:
  23. ProcessDeinitMessage(msg);
  24. break;
  25. default:
  26. break;
  27. }
  28. }

即根据消息中的what字段,选择相应的处理。主要分为五种类型:状态启动,状态迁移,消息处理,消息停止,卸载:

下面依次介绍这几种类型对应的函数处理:

1.状态启动

状态启动的函数为ProcessStartMessage,其源码如下:

  1. static void ProcessStartMessage(SoftBusMessage *msg)
  2. {
  3. FsmCtrlMsgObj *ctrlMsgObj = msg->obj;
  4. FsmStateMachine *fsm = NULL;
  5. FsmState *state = NULL;
  6. if (ctrlMsgObj == NULL) {
  7. return;
  8. }
  9. fsm = ctrlMsgObj->fsm;
  10. state = (FsmState *)ctrlMsgObj->obj;
  11. if (fsm == NULL || state == NULL) {
  12. return;
  13. }
  14. if (fsm->curState != NULL || (fsm->flag & FSM_FLAG_RUNNING) != 0) {
  15. LOG_ERR("unexpected state");
  16. return;
  17. }
  18. if (IsDuplicateState(fsm, state) =&#
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/339880
推荐阅读
相关标签
  

闽ICP备14008679号