#pragma once #include "SpBase.h" #include "SpFSM.h" #include "SpSecureClient.h" #include "download.h" #include #include "Download_msg_g.h" using namespace Download; #pragma pack(1) // [StructName("LISTREQ")] struct ListReq { char TerminalNo[16]; }; //[StructName("LISTANS")] struct ListAns { int ResultCode; char ListXmlContent[0]; // no more than 32k }; //新国密文件列表接口20200210 lwt // [StructName("LISTNREQ")] struct ListNReq { char TerminalNo[16]; }; //[StructName("LISTNANS")] struct ListNAns { int ResultCode; char ListXmlContent[0]; // no more than 50k }; //[StructName("FILEREQ")] struct FileReq { //char FileName[64]; char FileName[256]; int BlockNo; }; //[StructName("FILEANS")] struct FileAns { int ResultCode; //char FileName[64]; char FileName[256]; int BlockNo; char FileContent[0]; // no more than 32k }; #pragma pack() enum DownloadCtlCode { Finish = 0, //完成 Begin = 1, //开始下载 Continua = 2, //文件已经存在,断点续传,按返回块开始传 ErrorBlock = 3, //上块错误,重新传 ReturnList = 4, //返回列表 }; #define USER_EVT_JMP_DISABLE EVT_USER+1 #define USER_EVT_JMP_ENABLE EVT_USER+2 #define USER_EVT_JMP_GETFILEINFO EVT_USER+3 #define USER_EVT_FILEINO_ANS EVT_USER+4 #define USER_EVT_FILE_ANS EVT_USER+5 #define USER_EVT_DISCONNECT EVT_USER+6 #define USER_EVT_JMP_SYNC EVT_USER+7 #define USER_EVT_SYNC_FINISHED EVT_USER+8 #define USER_EVT_NOTASK EVT_USER+9 #define USER_EVT_JMP_DISABLE_S0 EVT_USER+10 #define XML_US_ASCII_PREFIX "\r\n" struct ListAnsEvent : public FSMEvent { ListAnsEvent(BYTE *pBuf, int nLen) : FSMEvent(USER_EVT_FILEINO_ANS) { int size = nLen; int nprefix = strlen(XML_US_ASCII_PREFIX); int offset = 0; if (memcmp(pBuf + sizeof(ListAns), ", public IFSMStateHooker, public ISysVarListener { public: DownloadFSM(); virtual ~DownloadFSM(); 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 {s0,s1,s2,s3,s4,s5}; enum {SYNC_STATE = s5}; BEGIN_FSM_STATE(DownloadFSM) FSM_STATE_ENTRY(s0,"Disable",s0_on_entry,s0_on_exit,s0_on_event)//判断可视柜台是否离线状态,否则等待10s再进行判断,成功则跳出不可用状态 FSM_STATE_ENTRY(s1,"Enable",s1_on_entry,s1_on_exit,s1_on_event)//10秒内无连线状态则进入s2 FSM_STATE_ENTRY(s2, "Active",s2_on_entry,s2_on_exit,s2_on_event)//连接中台服务,不成功则等待30s后再连接 FSM_STATE_ENTRY(s3, "getFileInfo",s3_on_entry,s3_on_exit,s3_on_event) FSM_STATE_ENTRY(s4, "DownloadFile", s4_on_entry, s4_on_exit, s4_on_event) FSM_STATE_ENTRY(s5, "Synchronized", s5_on_entry, s5_on_exit, s5_on_event) END_FSM_STATE() BEGIN_FSM_RULE(DownloadFSM,s0) FSM_RULE_ENTRY_ANY(s0, s2, USER_EVT_JMP_ENABLE) //FSM_RULE_ENTRY_ANY(s0, s5, USER_EVT_JMP_SYNC) FSM_RULE_ENTRY_ANY(s1, s0, USER_EVT_JMP_DISABLE) FSM_RULE_ENTRY_ANY(s1, s2, EVT_TIMER) FSM_RULE_ENTRY_ANY(s2, s0, USER_EVT_JMP_DISABLE) FSM_RULE_ENTRY_ANY(s2, s1, USER_EVT_NOTASK)//无任务时跳回s1 FSM_RULE_ENTRY_ANY(s2, s3, USER_EVT_JMP_GETFILEINFO) FSM_RULE_ENTRY(s3, s1, USER_EVT_FILEINO_ANS, 0)//获取信息列表失败,则跳回s1 FSM_RULE_ENTRY(s3, s4, USER_EVT_FILEINO_ANS, 1)//需要下载 FSM_RULE_ENTRY(s3, s5, USER_EVT_FILEINO_ANS, 2)//无信息列表,经过滤后无新任务需要下载,则跳到s5,等待一段时间下载 FSM_RULE_ENTRY_ANY(s3, s1, USER_EVT_DISCONNECT)//通讯失败时跳回s1 FSM_RULE_ENTRY_ANY(s3, s1, USER_EVT_NOTASK)//任务列表无任务时跳回s1 FSM_RULE_ENTRY_ANY(s3, s0, USER_EVT_JMP_DISABLE) FSM_RULE_ENTRY_ANY(s4, s1, USER_EVT_DISCONNECT)//通讯失败时跳回s1 FSM_RULE_ENTRY_ANY(s4, s0, USER_EVT_JMP_DISABLE_S0)//用其他disable跳出 FSM_RULE_ENTRY_ANY(s4, s5, USER_EVT_JMP_SYNC) FSM_RULE_ENTRY_ANY(s5, s0, USER_EVT_SYNC_FINISHED) END_FSM_RULE() void s1_on_entry(); void s1_on_exit(); unsigned int s1_on_event(FSMEvent* event); void s0_on_entry(); void s0_on_exit(); unsigned int s0_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); ErrorCodeEnum LoadDownloadFileList();//加载运行时文件任务 bool checkFileStr(CSimpleStringA strFile,int count);//检查运行时文件是否正确 ErrorCodeEnum SaveDownloadFileList();//保存运行时文件任务 ErrorCodeEnum addDownLoadFileWork(CSimpleStringA fileName,DWORD expireTime);//添加下载任务 ErrorCodeEnum deleteDownLoadFileWork(CSimpleStringA fileName);//取消下载任务 ErrorCodeEnum deleteCurrentDownloadFile(CSimpleStringA fileName);//取消正在下载的任务 ErrorCodeEnum checkWorkExpireTime();//过滤检查下载任务时效性 ErrorCodeEnum returnDownloadFileResult(const char* filename,ErrorCodeEnum error,CSimpleStringA errorMsg);//广播下载文件结果 ErrorCodeEnum returnDownloadProgress(download_file_t* file,download_storage_t * currentStorage); bool isDownloadTask(const char * filename); private: ErrorCodeEnum LoadServerConfigFromCenterSetting(); void nextTask(); private: DownloadConnection *m_pConnection;//中台连接 download_storage_t *m_current; //正在下载的文件 array_header_t *m_arr_downlist; //这次连接需要下载的文件列表 char *m_last_filelist; // 缓存上次返回列表(废除) char m_base_path[MAX_PATH]; CSimpleStringA m_server1; int m_server1_port; CSimpleStringA m_server2; int m_server2_port; std::list *m_DFlist;//下载任务列表:多线程会改变里面的值 CRITICAL_SECTION m_cs;//临界区变量 std::list *m_currentFileTask;//当前正在下载的文件列表:只有单线程能改变里面的值 bool isStartUp; public: CSimpleStringA m_currentFileName;//正在下载的文件名 bool m_isDisable;//判断是否处于disable状态 }; class DownloadConnection : public SpSecureClient { public: DownloadConnection(CEntityBase *pEntity, DownloadFSM *pFSM) : SpSecureClient(pEntity), m_pFSM(pFSM) {} void SendListReq() { ListReq req = {0}; CSystemStaticInfo si; { m_pEntity->GetFunction()->GetSystemStaticInfo(si); } strcpy(&req.TerminalNo[0], si.strTerminalID); CSmartPointer pkt = CreateNewPackage("LISTREQ"); pkt->AddStruct("LISTREQ", false, false, (LPBYTE)&req, sizeof(ListReq)); SendPackage(pkt); } void SendListNReq() { ListNReq req = {0}; CSystemStaticInfo si; { m_pEntity->GetFunction()->GetSystemStaticInfo(si); } strcpy(&req.TerminalNo[0], si.strTerminalID); CSmartPointer pkt = CreateNewPackage("LISTNREQ"); pkt->AddStruct("LISTNREQ", false, false, (LPBYTE)&req, sizeof(ListNReq)); SendPackage(pkt); } void SendFileReq(const char *file, int block_id) { FileReq req = {0}; req.BlockNo = block_id; strcpy(req.FileName, file); //CSmartPointer pkt = CreateNewPackage("FILEREQ"); //pkt->AddStruct("FILEREQ", false, false, (LPBYTE)&req, sizeof(FileReq)); CSmartPointer pkt = CreateNewPackage("LFILEREQ"); pkt->AddStruct("LFILEREQ", false, false, (LPBYTE)&req, sizeof(FileReq)); SendPackage(pkt); } protected: virtual ~DownloadConnection() {} virtual void OnDisconnect() { m_pFSM->PostEventFIFO(new FSMEvent(USER_EVT_DISCONNECT)); } virtual void OnPkgAnswer(const CSmartPointer &pRecvPkg) { //以前有问题,增加errmsg错误判断, DWORD dwSysCode, dwUserCode; string strErrMsg; ErrorCodeEnum rc = Error_Succeed; if (pRecvPkg->GetErrMsg(dwSysCode, dwUserCode, strErrMsg)){ // 错误处理 rc = (ErrorCodeEnum)dwSysCode; LogError(Severity_Middle, (ErrorCodeEnum)dwSysCode, dwUserCode, strErrMsg.c_str()); string serviceCode = pRecvPkg->GetServiceCode(); Dbg("receive %s ans packet is error,errormsg is %s", serviceCode.c_str(),strErrMsg.c_str()); OnDisconnect(); }else{ // 正常处理 string serviceCode = pRecvPkg->GetServiceCode(); if (serviceCode == "LISTREQ") { int nLen = pRecvPkg->GetStructLen("LISTANS"); if (nLen > 0) { BYTE *pBuf = new BYTE[nLen]; memset(pBuf, 0, nLen); int nArrayNum = 0; if (pRecvPkg->GetStructData("LISTANS", pBuf, &nLen, &nArrayNum)) { FSMEvent *evt = new ListAnsEvent(pBuf, nLen); m_pFSM->PostEventFIFO(evt); } else { Dbg("create invalid fileInfo_Ans packet!"); OnDisconnect(); } delete[] pBuf; } } else if (serviceCode == "LISTNREQ") {//新国密列表文件 int nLen = pRecvPkg->GetStructLen("LISTNANS"); if (nLen > 0) { BYTE *pBuf = new BYTE[nLen]; memset(pBuf, 0, nLen); int nArrayNum = 0; if (pRecvPkg->GetStructData("LISTNANS", pBuf, &nLen, &nArrayNum)) { FSMEvent *evt = new ListNAnsEvent(pBuf, nLen); m_pFSM->PostEventFIFO(evt); } else { Dbg("create invalid fileNewInfo_Ans packet!"); OnDisconnect(); } delete[] pBuf; } } else if (serviceCode == "LFILEREQ") { int nLen = pRecvPkg->GetStructLen("LFILEANS"); if (nLen > 0) { BYTE *pBuf = new BYTE[nLen]; memset(pBuf, 0, nLen); int nArrayNum = 0; if (pRecvPkg->GetStructData("LFILEANS", pBuf, &nLen, &nArrayNum)) { FSMEvent *evt = new FileAnsEvent(pBuf, nLen); m_pFSM->PostEventFIFO(evt); } else { Dbg("create invalid file_Ans packet!"); OnDisconnect(); } delete[] pBuf; } } else { Dbg("unknown service code!"); OnDisconnect(); } } } private: DownloadFSM *m_pFSM; };