#ifndef RVC_MOD_UPGRADETASK_FSM_H_ #define RVC_MOD_UPGRADETASK_FSM_H_ #include "stdafx.h" #include "SimpleString.h" #include "SpBase.h" #include "SpFSM.h" #include #include #include #include "IHttpFunc.h" #define DOWNLOAD_CONTENT_EACH_LEN 512*1024 #define DOWNLOAD_TIMEOUT 2*60 #define QUERY_NO_TASK_WARN_LIMIT 15 #define QUERY_IS_WORK_WARN_LIMIT 10 using namespace std; #define WARN_TASK_COPY_FILE_ZERO 0x50620022 //升级copy文件夹文件个数为0 #define ERR_TASK_QUERY_PRE_NEW_TASK_FAIL 0x50620023 //查询新任务报错 #define ERR_TASK_QUERY_CONTINUE_NEW_TASK_FAIL 0x50620024 //查询继续新任务报错 #define ERR_TASK_QUERY_CONTINUE_NEW_TASK_ERR 0x50620025 //查询继续新任务异常 //#define WARN_BLACK_FILE_SUM 0x50600023 //黑名单文件数量 #define UpgradeMgr_VERSION_DOWNLOAD_ID "QLR0402506Z10101" #define UpgradeMgr_VERSION_INSTALL_ID "QLR0402506Z10201" #define UpgradeMgr_VERSION_SWTICH_ID "QLR0402506Z10301" #define UpgradeMgr_VERSION_START_ID "QLR0402506Z10401" #define UpgradeMgr_OUTSIDE_SYSTEM_DOWNLOAD_ID "QLR0402506Z10102" #define UpgradeMgr_OUTSIDE_SYSTEM_INSTALL_ID "QLR0402506Z10202" #define UpgradeMgr_OUTSIDE_SYSTEM_SWTICH_ID "QLR0402506Z10302" #define UpgradeMgr_OUTSIDE_SYSTEM_START_ID "QLR0402506Z10405" #define UpgradeMgr_PerTask_HTTP_ERR "QLR0402506Z10501" #define UpgradeMgr_DOWNLOAD_ID "QLR0402506Z101" #define UpgradeMgr_INSTALL_ID "QLR0402506Z102" #define UpgradeMgr_SWTICH_ID "QLR0402506Z103" #define UpgradeMgr_START_ID "QLR0402506Z104" #define UpgradeMgr_ROLLBACK_ID "QLR0402506Z201" #define UpgradeMgr_ROLLBACK_SWTICH_ID "QLR0402506Z202" #define UpgradeMgr_ROLLBACK_START_ID "QLR0402506Z203" namespace HttpStruct { //发送文件hash列表接口 struct SendSM3TaskReq : CHTTPReq { string m_reqStr; string ToJson() { return m_reqStr; } }; struct SendSM3TaskRet : CHTTPRet { string m_retStr; bool Parse(string strData) { m_retStr=strData; return true; } }; //更新任务状态接口 struct UpdateTaskStatusReq : CHTTPReq { string m_reqStr; string ToJson() { return m_reqStr; } }; struct UpdateTaskStatusRet : CHTTPRet { string m_retStr; bool Parse(string strData) { m_retStr=strData; return true; } }; //查询当前任务 struct QueryCurrTaskReq : CHTTPReq { string m_reqStr; string ToJson() { return m_reqStr; } }; struct QueryCurrTaskRet : CHTTPRet { string m_retStr; bool Parse(string strData) { m_retStr=strData; return true; } }; //查询新任务 struct QueryNewTaskReq : CHTTPReq { string m_reqStr; string ToJson() { return m_reqStr; } }; struct QueryNewTaskRet : CHTTPRet { string m_retStr; bool Parse(string strData) { m_retStr=strData; return true; } }; //断点下载升级包 struct DownloadPackTaskRet{ long content_length; long origin_file_length; bool bfinish; string sm3; }; } // 升级任务状态机 class CUpgradeTaskFSM : public FSMImpl, public IFSMStateHooker, public ISysVarListener { public: enum { Event_Start = EVT_USER+1, Event_StartDealTask, Event_DealCurrTask, Event_EndUpdateTask, Event_EndQueryCurrTask, Event_StartPoll, Event_EndPoll, Event_EndPrePoll, Event_EndSendSM3Task, Event_EndContinuePoll, Event_StartDownload, Event_EndQueryTaskStatus, Event_Download_Idle, Event_EndDownload, Event_Download_Fail, Event_CancelTask, Event_StartInstall, Event_EndUnzipPackTask, Event_EndStopMediaPlayTask, Event_EndInstallPackTask, Event_EndInstall, Event_EndRollBackCheckTask, Event_StartSwitch, Event_PreRestart, }; struct SendSM3TaskEvent:public FSMEvent { bool isSucc;//是否写入成功 SendSM3TaskEvent(bool isSendSucc) : FSMEvent(Event_EndSendSM3Task), isSucc(isSendSucc) {} }; struct UpdateTaskStatusEvent:public FSMEvent { bool isSucc;//是否更新成功 UpdateTaskStatusEvent(bool isSendSucc) : FSMEvent(Event_EndUpdateTask), isSucc(isSendSucc) {} }; struct QueryCurrTaskEvent:public FSMEvent { bool isSucc;//是否查询成功 bool isTask_valid;//任务是否有效 QueryCurrTaskEvent(bool isSendSucc,bool isValid) : FSMEvent(Event_EndQueryCurrTask), isSucc(isSendSucc),isTask_valid(isValid) {} }; struct QueryNewTaskEvent:public FSMEvent { bool isSucc;//是否查询成功 QueryNewTaskEvent(bool isSendSucc) : FSMEvent(Event_EndPoll), isSucc(isSendSucc) {} }; struct QueryNewContinueTaskEvent:public FSMEvent { int retParam;//是否查询成功 QueryNewContinueTaskEvent(int ret) : FSMEvent(Event_EndContinuePoll) { retParam = ret; } }; struct QueryNewPreTaskEvent:public FSMEvent { bool isSucc;//是否查询成功 QueryNewPreTaskEvent(bool isSendSucc) : FSMEvent(Event_EndPrePoll), isSucc(isSendSucc) {} }; struct QueryTaskStatusEvent:public FSMEvent { bool isSucc;//是否查询成功 bool isTask_valid;//任务是否有效 QueryTaskStatusEvent(bool isSendSucc,bool isValid) : FSMEvent(Event_EndQueryTaskStatus), isSucc(isSendSucc),isTask_valid(isValid) {} }; struct DownloadPackTaskEvent:public FSMEvent { bool isSucc; DownloadPackTaskEvent(bool isDownloadSucc) : FSMEvent(Event_EndDownload), isSucc(isDownloadSucc) {} }; struct DownloadPackTaskFailEvent:public FSMEvent { string errMsg;//错误信息 DownloadPackTaskFailEvent(string errorMsg) : FSMEvent(Event_Download_Fail), errMsg(errorMsg) {} }; struct StopMediaPlayTaskEvent:public FSMEvent { bool isSucc; StopMediaPlayTaskEvent(bool isStopSucc) : FSMEvent(Event_EndStopMediaPlayTask), isSucc(isStopSucc) {} }; struct UnzipPackTaskEvent:public FSMEvent { bool isSucc; UnzipPackTaskEvent(bool isUnzipSucc) : FSMEvent(Event_EndUnzipPackTask), isSucc(isUnzipSucc) {} }; struct RollBackCheckTaskEvent :public FSMEvent { bool isSucc; CSimpleStringA errMsg; string failReason; RollBackCheckTaskEvent(bool isInstallSucc, CSimpleStringA errMsgStr, string strfailReason) : FSMEvent(Event_EndRollBackCheckTask), isSucc(isInstallSucc), errMsg(errMsgStr), failReason(strfailReason) {} }; struct InstallPackTaskEvent:public FSMEvent { bool isSucc; CSimpleStringA errMsg; int failStatus; InstallPackTaskEvent(bool isInstallSucc,CSimpleStringA errMsgStr,int iFailStatus) : FSMEvent(Event_EndInstallPackTask), isSucc(isInstallSucc),errMsg(errMsgStr),failStatus(iFailStatus) {} }; struct CInstallStep { //不存储到运行时 int stepSeq; //步骤序号 CSimpleStringA cmdType; //升级安装需执行命令类型:Delete、Copy、Run int cmdFail; //0:执行失败认为升级失败 1:执行失败忽略继续升级 CSimpleStringA srcPathType; //0:相对路径 1:绝对路径 2:当前版本相对路径 3:升级包相对路径 CSimpleStringA srcPath; CSimpleStringA dstPathType; //0:相对路径 1:绝对路径 2:当前版本相对路径 3:升级版本相对路径 4:升级包相对路径 CSimpleStringA dstPath; }; // 待安装任务信息(运行时保存的中间变量) struct CTaskInfo { //存储到运行时 CSimpleStringA upgradeTaskId; //升级任务编号 CSimpleStringA createTaskVersion;//创建升级任务时的版本号 CSimpleStringA cPendingState; // 已下载D、安装中I、等待切换S、任务结果确认T CSimpleStringA NewVersion; // 任务升级后的版本号 CSimpleStringA pack_name; //升级包名 CSimpleStringA task_type; //任务类型 U:升级任务 R:回退任务 CSimpleStringA depNewVersion; //适配器新版本号 //CSimpleStringA task_class; //任务类别 A:应用版本任务 D:适配器任务 T:体系外任务 //不存储到运行时 CSimpleStringA pack_version; //升级包指定的版本号 bool stop_media_play; //停止广告播放(0:不停止 1:停止) int reboot_type; //重启策略类型(0:不启动 1:重启框架 2:重启系统) CSimpleStringA file_path; //升级包路径 CSimpleStringA download_url; //升级包下载地址 CSimpleStringA pack_hash; //升级包hash值 long pack_length; //升级包长度(服务端暂时不传) queue install_step;//安装步骤队列 }; struct CTaskProcess { CSimpleStringA strPackName;//包名 CSimpleStringA installVersion;//安装版本号 CSimpleStringA CurrentVersion;//当前版本号 CSimpleStringA cInstallState;//升级状态 CSimpleStringA strInstallComment;//升级状态备注 }; struct CenterUrl { string updateTaskUrl; //更新升级任务url string queryCurrTaskUrl; //查询当前任务url string queryNewTaskUrl; //查询新任务url(旧版本使用) string queryPreTaskUrl; //预查询新任务url string queryContinueTaskUrl; //继续查询新任务url string queryTaskStatus; //查询当前任务是否有效url string sendSM3TaskUrl; //发送文件hashurl }; struct HashScanSet { CSimpleStringA relativeDir; //相对路径 CSimpleStringA absoluteDir; //绝对路径 CSimpleStringA currVerDir; //当前版本相对路径 CSimpleStringA blackFile; //不纳入扫描的文件名称 CSimpleStringA blackDir; //不纳入扫描的文件夹 }; public: CUpgradeTaskFSM(){ isSendHash = false;//默认查询策略不发送hash m_isSM3HashSucc = false;//默认hash计算失败 m_bDownloadIdle = false; m_bTaskCancel=false; m_fileSM3ListHash="";//终端hash列表64位hash值 m_fileSM3List = "";//终端hash列表值 m_strPreTaskId="";//预检查任务ID m_bNeedHash=0;//预检查是否需要hash m_newEachDownloadLen=DOWNLOAD_CONTENT_EACH_LEN; m_PrintHttpLog =false; m_startFlag = false; m_iBlackFileCount=0; m_bSwitchFlag = false; m_bRollbackTask = false; m_TempDepUpgradeFlag = false;//默认非适配器升级 m_queryNewTaskInterval = 240;//默认查询任务时间间隔 m_installStopCopyDep = false;//默认拷贝 m_downloadBreakOffCount = 0; m_queryIsWorkCount = 0; } ~CUpgradeTaskFSM(){} //具体实现方法 ErrorCodeEnum CreateNewVersion(CVersion NewSoftwareVersion,CSimpleStringA &strErrInfo);//创建新版本 ErrorCodeEnum ClearUpgradeFailVersion(CVersion NewSoftwareVersion);//清理升级新版本临时文件 bool GetSysUpgradeResult(const char *pszResultLog, CSimpleStringA &eErrorCode, CSimpleStringA &strErrMsg);//从体系外生成的result.log文件中获取结果 //安装执行步骤方法 int ExecInstall(CSimpleStringA &strErrMsg);//升级安装 0:失败 1:成功 -1:未知 int ExecRunCmd(CSimpleStringA &strErrMsg,CInstallStep* ins); bool ExecDeleteCmd(CSimpleStringA &strErrMsg,CInstallStep* ins); bool ExecCpoyCmd(CSimpleStringA &strErrMsg,CInstallStep* ins); bool GetRootTypePath(int rootType,CSimpleStringA &rootPath);//1:相对路径 2:当前版本相对路径 3:升级版本相对路径 4:升级包相对路径 ErrorCodeEnum CopyFileOperate(const char* srcPath, const char* destPath, int nCopyMode, CSimpleStringA &strErrMsg); ErrorCodeEnum SetRunSucceed(const char* pPackFile);//成功切换新版本 ErrorCodeEnum UpgradeToNewVersion();//设置新版本状态 ErrorCodeEnum RollBackToHistoryVersion(CVersion historyVersion);//回退到某个历史版本 void RecursiveGetSubFiles(const char *pszDir, const char *pszTrimStart, list& retList); bool IsFileMatch(const char *pszFilter, const char *pszFileName); bool RecursiveCopyDir(const char *pszSourceDir, const char *pszDestDir,CSimpleStringA &strErrInfo);//可以合并 CSimpleStringA GetFileDirectory(const char *pszFullPath);//查找文件的父路径 int system_on(string cmdFilePath, bool isWait,CSimpleStringA &errMsg);//cmd窗口程序 int waitSystem(string cmd, const char * par, bool nShow,CSimpleStringA &errMsg);//起进程执行cmd ErrorCodeEnum UnzipPack(const char* unZipPackName);//解压文件 ErrorCodeEnum DeleteUnzipDir();//清理临时解压包文件 ErrorCodeEnum RollBackVersionCheck(string &failReason, CSimpleStringA& strErrMsg);//回退版本检查 C:一般错误 X:终端找不到需要回退的版本文件夹 、回退版本比现在版本高 void SendUpgradeTaskProgress(CTaskProcess &process, CSimpleStringA logCodeStr, CSimpleStringA rtaStr = ""); ErrorCodeEnum GetRunConfigStrValue(const char *pszSection, const char *pszKey, CSimpleStringA &strValue); ErrorCodeEnum SetRunConfigStrValue(const char *pszSection, const char *pszKey, const char *pszValue); bool ClearCurrTaskInfo();//任务无效清除运行时记录和残留下载包 bool ClearInstallStep();//清理历史任务安装步骤 ErrorCodeEnum LoadPersistTaskInfo();//启动开始加载运行时文件 ErrorCodeEnum loadCenterCfgInfo();//启动开始加载集中配置文件 bool GetFileLength(const char* filePath,long &fileLen);//获取文件长度 ErrorCodeEnum GetSM3List(CSimpleStringA &strSM3List);//获取版本文件hash集合字符串 ErrorCodeEnum ScanSM3ByType(int type,CSimpleStringA pathFilter); ErrorCodeEnum NewSM3Folder(CSimpleStringA scanFilter,CSimpleStringA replaceDir);//新的hash扫描文件夹实现 //新国密SM3函数,isSub表示是否截取新国密中间一段密文 ErrorCodeEnum SM3FileToStr(CSimpleStringA strFilePath, CSimpleStringA &strSM3,bool isSub); ErrorCodeEnum SM3DataToStr(CSimpleStringA strData, CSimpleStringA &strSM3,bool isSub); ErrorCodeEnum SM3_Str(CSimpleStringA &strSM3,BYTE * SM3Byte,bool isSub); bool IsPackDownloaded(const char *pPackName,const char* packHash,long packLen);//判断安装包是否已下载成功 bool DownloadFileWrite(byte* content,long contentLen,const char* filePath); bool CheckIfCanSwitchNow();//是否允许切换 ErrorCodeEnum SwitchUpgradeNow();//切换版本 ErrorCodeEnum DownloadProgress(long tempFileLen,long fileSumLen);//返回下载进度 char GetInstallState(int nState);//根据状态机获取升级状态 ErrorCodeEnum GetUpgradeState(bool &bInstalling, CSimpleStringA &strPackFile, CSimpleStringA &strExecID, char &cInstallState, bool &bSysInstall, bool &bLightPack, CSimpleStringA &strNewVersion); static void HttpsLogCallBack(const char* logtxt); void judgeTaskClass();//临时判定升级任务类别 ErrorCodeEnum judgeRollbackTaskClass(CSimpleStringA verDirName, string& failReason, CSimpleStringA& strErrMsg);//临时判定回退任务类别 ErrorCodeEnum CreateNewDepVersion(CSimpleStringA NewSoftwareVersion, CSimpleStringA& strErrInfo);//升级时创建新适配器版本 ErrorCodeEnum CreateInstallDepVersion(CSimpleStringA NewSoftwareVersion, CSimpleStringA& strErrInfo);//安装时创建新适配器版本 ErrorCodeEnum ClearUpgradeFailDepVersion(CSimpleStringA NewSoftwareVersion);//清理升级新版本临时文件 ErrorCodeEnum UpgradeDepToNewVersion();//更新depactive文件 ErrorCodeEnum SwitchUpgradeDepNow();//切换适配器版本 ErrorCodeEnum RollBackDepVersionCheck(string& failReason, CSimpleStringA& strErrMsg);//回退版本检查 C:一般错误 X:终端找不到需要回退的版本文件夹 ErrorCodeEnum RollBackToHistoryDepVersion(CSimpleStringA historyDepVersion);//适配器回退到某个历史版本 //适配器安装函数 int ExecDepInstall(CSimpleStringA& strErrMsg);//适配器升级 0:失败 1:成功 int ExecDepRunCmd(CSimpleStringA& strErrMsg, CInstallStep* ins); bool ExecDepDeleteCmd(CSimpleStringA& strErrMsg, CInstallStep* ins); bool ExecDepCpoyCmd(CSimpleStringA& strErrMsg, CInstallStep* ins); bool GetDepRootTypePath(int rootType, CSimpleStringA& rootPath);//1:相对路径 2:当前版本相对路径 3:升级版本相对路径 4:升级包相对路径 CSimpleStringA getAlarmCurrVersion(); //升级时添加防火墙策略 ErrorCodeEnum SetNewVersionPathToFirewall(); bool isWork(); bool isAuthSucc(); bool isTerminalInstall(); void upgradeSuccStateBroadCast(); #ifdef RVC_OS_WIN #else int changeFileAtt(const char* path); #endif private: bool DirIsExist(const char* scanPath,const char* dirName); virtual void OnStateTrans(int iSrcState, int iDstState); virtual void OnSysVarEvent(const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName); virtual ErrorCodeEnum OnInit(); virtual ErrorCodeEnum OnExit(); enum{s1, s2, s3, s4, s5, s6, s7}; BEGIN_FSM_STATE(CUpgradeTaskFSM) FSM_STATE_ENTRY(s1, "Start",s1_on_entry,s1_on_exit,s1_on_event)//计算hash值 FSM_STATE_ENTRY(s2, "DealTask",s2_on_entry,s2_on_exit,s2_on_event)//处理上个任务,反馈任务结果,并根据任务状态跳转到其他状态 FSM_STATE_ENTRY(s3, "Poll",s3_on_entry,s3_on_exit,s3_on_event)//查询任务 FSM_STATE_ENTRY(s4, "Download", s4_on_entry, s4_on_exit, s4_on_event)//下载安装包 FSM_STATE_ENTRY(s5, "Install", s5_on_entry, s5_on_exit, s5_on_event)//安装升级包 FSM_STATE_ENTRY(s6, "Switch", s6_on_entry, s6_on_exit, s6_on_event)//进行版本切换 FSM_STATE_ENTRY(s7, "Disable", s7_on_entry, s7_on_exit, s7_on_event)//静止状态 END_FSM_STATE() BEGIN_FSM_RULE(CUpgradeTaskFSM,s1) FSM_RULE_ENTRY_ANY(s1, s2, Event_StartDealTask) FSM_RULE_ENTRY_ANY(s2, s3, Event_StartPoll) FSM_RULE_ENTRY(s2, s4, Event_EndQueryCurrTask, 4) FSM_RULE_ENTRY(s2, s5, Event_EndQueryCurrTask, 5) FSM_RULE_ENTRY(s2, s6, Event_EndQueryCurrTask, 6) FSM_RULE_ENTRY_ANY(s3, s4, Event_StartDownload) FSM_RULE_ENTRY_ANY(s3, s5, Event_StartInstall)//回退 FSM_RULE_ENTRY_ANY(s4, s5, Event_StartInstall) FSM_RULE_ENTRY_ANY(s4, s3, Event_StartPoll)//任务取消进入S3 FSM_RULE_ENTRY_ANY(s4, s2, Event_StartDealTask)//下载失败进入S2 FSM_RULE_ENTRY_ANY(s5, s6, Event_StartSwitch) FSM_RULE_ENTRY_ANY(s5, s2, Event_StartDealTask)//安装失败进入S2 FSM_RULE_ENTRY_ANY(s6, s2, Event_StartDealTask)//无需重启框架和系统切换成功进入S2 FSM_RULE_ENTRY_ANY(s6, s3, Event_StartPoll)//取消任务进入S3 FSM_RULE_ENTRY_ANY(s6, s7, Event_PreRestart)//重启服务 END_FSM_RULE() private: //完成 void s1_on_entry(); void s1_on_exit(); unsigned int s1_on_event(FSMEvent* event); //完成 void s2_on_entry(); void s2_on_exit(); unsigned int s2_on_event(FSMEvent* event); //完成 void s3_on_entry(); void s3_on_exit(); unsigned int s3_on_event(FSMEvent* event); //完成 void s4_on_entry(); void s4_on_exit(); unsigned int s4_on_event(FSMEvent* event); //完成 void s5_on_entry(); void s5_on_exit(); unsigned int s5_on_event(FSMEvent* event); //完成 void s6_on_entry(); void s6_on_exit(); unsigned int s6_on_event(FSMEvent* event); // void s7_on_entry(); void s7_on_exit(); unsigned int s7_on_event(FSMEvent* event); private: list m_DepWhitelist; //dep文件夹白名单 list m_DirBlacklist; //整体文件夹黑名单 list m_FileBlacklist; //整体文件黑名单 public: map m_fileSM3Map; // 版本文件hash值集合 CTaskInfo m_currentTask; //当前的任务缓存变量 CVersion m_currentVersion; //当前终端版本 CSimpleStringA m_currentDepVersion; //当前适配器版本 CenterUrl m_centerUrl;//访问总行的url地址集合 int m_newEachDownloadLen;//新的每次下载数据长度阈值(k) bool m_PrintHttpLog; //是否打印通讯日志 bool m_startFlag; //升级实体启动标志位,默认是不开, bool m_stopSetFirewall;//是否停止设置防火墙路径,默认是不停止 HashScanSet m_hashScanSet;//扫描文件hash设置 bool m_isSM3HashSucc;//hash是否计算成功 bool isSendHash;//hash是否发送 CSimpleStringA m_fileSM3ListHash;//SM3 64位hash CSimpleStringA m_fileSM3List;//版本文件hash集合字符串 DWORD m_beginSendSM3Time;//开始发送sm3hahs时间 int m_queryNewTaskCount;//查询新任务时无任务次数 int m_queryIsWorkCount; int m_downloadBreakOffCount; bool m_bDownloadIdle; //是否下载空闲 true: 不能下载,false: 可下载 bool m_bTaskCancel; //是否任务取消 true: 任务取消,false: 未取消 int m_iBlackFileCount; //黑名单文件数量 CSimpleStringA m_strPreTaskId; //预检查taskId int m_bNeedHash;//是否需要hash对比查询任务 bool m_bSwitchFlag;//是否启动后切换流程直接进入标志 bool m_bRollbackTask;//是否已经处于回退流程。 bool m_TempDepUpgradeFlag;//临时适配器升级安装的判定标志 true 适配器 false 非适配器 int m_queryNewTaskInterval;//查询任务时间间隔,默认是240s bool m_installStopCopyDep;//安装时是否停止拷贝应用dep公共文件夹 }; #endif //RVC_MOD_UPGRADETASK_FSM_H_