#ifndef __HEARTBEAT_FSM_H #define __HEARTBEAT_FSM_H #pragma once #ifdef RVC_OS_WIN #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include #include #else //oiltestlinux #endif //RVC_OS_WIN //#pragma comment(lib, "Loadperf.lib") #include "SpFSM.h" #include "HeartBeat_def_g.h" #include "HeartBeat_msg_g.h" using namespace HeartBeat; #include "SpSecureClient.h" #include "EventCode.h" #include "CardIssuer_client_g.h" //using namespace CardIssuer; #include "PinPad_client_g.h" //using namespace PinPad; #include "CardReadAdapter_client_g.h" //using namespace CardReadAdapter; #include "IDCertificate_client_g.h" //using namespace IDCertificate; #include "ScannerSet_client_g.h" using namespace ScannerSet; typedef DWORD (__stdcall *LpRestorePerfRegistryFromFile)(LPCWSTR szFileName, LPCWSTR szLangId); #pragma pack(1) // [StructName("FNTSTAT")] struct HandReq { char TerminalNo[16]; uint32_t ip; char WarningLevel; char RunState; char CustomerHandle; char CallState; char LocalMaintain; char RemoteMaintain; char TermStage; char PreTermStage; char NetState; char PreNetState; }; // [StructName("xxx")] struct HandErrListReq { int warnLevel; char reserved1;//用来存放交易控制标志 char reserved2; char reserved3; char reserved4; char errList[512]; }; //[StructName("HANDANS")] struct HandAns { uint32_t EventCode; char param1[16]; //int count; }; struct CardActiveReq { uint32_t type; uint32_t slot; uint32_t reserved1; uint32_t reserved2; char Account[32]; char FromTerminalNo[16]; char TerminalNo[16]; uint32_t EvtCode; uint32_t ErrCode; uint32_t findCard; uint32_t cardPos; char Param1[16]; char Param2[1024]; char Reserved3[128]; char Reserved4[128]; }; struct CrossCallReq { uint32_t CallType;//跨机调用类型,同def文件的method id,实体内唯一 bool bTwoWay;//true :two way call; false: one way call char FromTerminalNo[16]; char ToTerminalNo[16]; uint32_t nEntityID; uint32_t Appendix1; uint32_t Appendix2; //返回包时用于标注错误 uint32_t ErrorCode; //oilyang@20190118 uint32_t blobSN;//拆包时用于标注序号 //本来以为StrParamX足够大,用这个值来划分blob,结果一个blob就塞满了 //故numOfBlobInParamX用于标注拆包数量(结构个数) uint32_t numOfBlobInParamX; uint32_t lensOfBlobInParamX[16];//多个blob塞到StrParamX用于标注每一个的长度 char StrParam1[128]; char StrParam2[1024]; char StrParamX[0];//用于传递图片信息 }; #pragma pack() enum EvtType { USER_EVT_TEST = EVT_USER+1, USER_EVT_QUIT, USER_EVT_START, USER_EVT_STARTFINISHED, USER_EVT_HANDSHAKEFINISHED, USER_EVT_INSTRUCTION, USER_EVT_LOST, USER_EVT_STOP, USER_EVT_REJECT, USER_EVT_EXIT, USER_EVT_CARD_ACTIVE, USER_EVT_CARD_ACTIVE_FINISHED, USER_EVT_CROSS_TERM_CALL, USER_EVT_CROSS_TERM_CALL_FINISHED, USER_EVT_LOCAL_CROSS_TERM_CALL_FINISHED, USER_EVT_ILCallToRVC, USER_EVT_CallResultToIL, }; struct TerminalInfo { char TerminalNo[16]; uint32_t ip; char WarningLevel; char RunState; char CustomerHandle; char CallState; char LocalMaintain; char RemoteMaintain; char TermStage; char PreTermStage; char NetState; char PreNetState; }; // Terminal Performance Information Struct[Josephus in 9:09:47 2016/4/23] struct TermianlCounter { DWORD serverIP; uint16_t totalMem; //MB uint16_t freeMem; //MB uint16_t procNum; uint16_t threadNum; DWORD handleNum; DWORD freeDisk; //MB char osStartTime[22]; uint16_t cpuLoad; }; enum InstructionType { INC_UNKNOWN = 0, INC_GLOBAL_SETTING_SYNC, INC_COMM_RECONNECT, INC_START_REMOTE_CONTROL, INC_UPDATE_CHECK, INC_RECOVER_SERVICE, INC_PAUSE_SERVICE, INC_AREA_SERVICE_SWITCH, INC_VERSION_ROLLBACK, INC_BRIDGE, INC_VEDIO_CONNECTING, INC_TRADE_MANAGER_NORMAL, INC_TRADE_MANAGER_ON, INC_TRADE_MANAGER_OFF, INC_DEVICE_LOCK_ON, INC_DEVICE_UNLOCK, INC_DEVICE_KICK_OFF, }; class CHeartBeatEntity; class CHeartBeatFSM; class InstructionEvent : public FSMEvent { public: InstructionEvent() : FSMEvent(USER_EVT_INSTRUCTION){} virtual ~InstructionEvent(){} SpReqAnsContext::Pointer ctx; protected: private: }; class CardActiveEvent : public FSMEvent { public: CardActiveEvent() : FSMEvent(USER_EVT_CARD_ACTIVE){} virtual ~CardActiveEvent(){} SpReqAnsContext::Pointer ctx; protected: private: }; class CrossTermCallEvent : public FSMEvent { public: CrossTermCallEvent() : FSMEvent(USER_EVT_CROSS_TERM_CALL) {} virtual ~CrossTermCallEvent() {} SpReqAnsContext::Pointer ctx; protected: private: }; class ILCallToRVCEvent : public FSMEvent { public: ILCallToRVCEvent() : FSMEvent(USER_EVT_ILCallToRVC) {} virtual ~ILCallToRVCEvent() {} SpOnewayCallContext::Pointer ctx; }; class CallResultToILEvent : public FSMEvent { public: CallResultToILEvent() : FSMEvent(USER_EVT_CallResultToIL) {} virtual ~CallResultToILEvent() {} SpOnewayCallContext::Pointer ctx; }; class HeartBeatConnection; class CHeartBeatFSM : public FSMImpl { public: enum {s0,s1,s2,s3,s4,s5}; BEGIN_FSM_STATE(CHeartBeatFSM) FSM_STATE_ENTRY(s0,"Init",s0_on_entry,s0_on_exit,s0_on_event) FSM_STATE_ENTRY(s1,"Starting",s1_on_entry,s1_on_exit,s1_on_event) FSM_STATE_ENTRY(s2,"Connected",s2_on_entry,s2_on_exit,s2_on_event) FSM_STATE_ENTRY(s3,"Lost",s3_on_entry,s3_on_exit,s3_on_event) FSM_STATE_ENTRY(s4,"Reject",s4_on_entry,s4_on_exit,s4_on_event) FSM_STATE_ENTRY(s5,"Failed",s5_on_entry,s5_on_exit,s5_on_event) END_FSM_STATE() BEGIN_FSM_RULE(CHeartBeatFSM,s0) FSM_RULE_ENTRY(s0,s1,USER_EVT_START,0) FSM_RULE_ENTRY(s1,s2,USER_EVT_STARTFINISHED,0) FSM_RULE_ENTRY(s1,s0,USER_EVT_STARTFINISHED,1) FSM_RULE_ENTRY(s2,s0,USER_EVT_STOP,0) FSM_RULE_ENTRY(s2,s0,USER_EVT_START,0) FSM_RULE_ENTRY(s4,s0,USER_EVT_STOP,0) END_FSM_RULE() CHeartBeatFSM():m_initTimes(0),m_bUseBackup(false),m_testResult(Error_Succeed), m_warnLevel(0), m_entErrorList(""), m_nLodCtrFlag(0), m_pHandShakeConn(NULL) , m_tradeState(99),m_bJBMachine(false), m_pCRAClient(NULL), m_pIDClient(NULL) , m_pPinPadClient(NULL) , m_localDeviceNo(""), m_ILDeviceNo(""), m_tmpMultiBlob(""), m_terminalStage(""){} ~CHeartBeatFSM(){} virtual ErrorCodeEnum OnInit(); virtual ErrorCodeEnum OnExit(); void s0_on_entry(); void s0_on_exit(); unsigned int s0_on_event(FSMEvent* pEvt); void s1_on_entry(); void s1_on_exit(); unsigned int s1_on_event(FSMEvent* pEvt); void s2_on_entry(); void s2_on_exit(); unsigned int s2_on_event(FSMEvent* pEvt); void s3_on_entry(); void s3_on_exit(); unsigned int s3_on_event(FSMEvent* pEvt); void s4_on_entry(); void s4_on_exit(); unsigned int s4_on_event(FSMEvent* pEvt); void s5_on_entry(); void s5_on_exit(); unsigned int s5_on_event(FSMEvent* pEvt); DWORD m_dwServIP; int Starting(); int DoHandShake(); void SetConnNULL(){} ErrorCodeEnum SetErrorList(int warmLevel,CSimpleStringA strList); void SelfTest(EntityTestEnum eTestType,CSmartPointer pTransactionContext); int GetWarnLevel(){return m_warnLevel;} void SetTradeManagerState(int tState){ m_tradeState = tState; } void SetTerminalStageState(CSimpleStringA stage) { m_terminalStage = stage; } CSimpleStringA GetTerminalStageState() { return m_terminalStage; } int GetTradeManagerState(){ return m_tradeState; } CSimpleString GetEntityErrorList(){return m_entErrorList;} // Terminal Performance Counter component [Josephus in 9:17:13 2016/4/23] ErrorCodeEnum GetPerformCounter(TermianlCounter& counter); const CSimpleStringA GetRealIP() { return m_csServerIP; } const char* GetRunDiskPath() { return (LPCTSTR)m_csRunDiskName; } void SetLodCtrStatus(int val) { m_nLodCtrFlag = val; } int CardActive(SpReqAnsContext::Pointer ctx); void LocalPreOnline(int slot, CSimpleStringA fromTermNo, CSimpleStringA termNo, CSimpleStringA account, CSimpleStringA data); void ReceivePreOnlineBack(unsigned long errCode,CSimpleStringA data, unsigned long findCard, unsigned long cardPos); int CrossTermCall(SpReqAnsContext::Pointer ctx); int ProcessCrossCallToHBService(int callType, SpReqAnsContext::Pointer ctx); int SendToHeartBeatService(HeartBeatService_CrossTermCall_Req &req, HeartBeatService_CrossTermCall_Ans &ans); void DoLocalProcessCrossCallTask(CrossCallReq *reqInfo, const int nBufSize); int LocalProcessCrossCall(CrossCallReq* reqInfo, const int nBufSize); void ILCallToRVC(SpOnewayCallContext::Pointer ctx); void CallResultToIL(SpOnewayCallContext::Pointer ctx); void ProcessPreOnline(CardActiveReq* req); void ProcessCardActive(CardActiveReq* req); protected: void DoInstruction(SpReqAnsContext::Pointer ctx); private: int m_tmpTestFlag; SOCKET m_ConnSocket; CSimpleStringA m_servStr,m_servIP,m_servStrB,m_servIPB,m_entErrorList,m_localDeviceNo,m_ILDeviceNo,m_tmpMultiBlob, m_terminalStage; int m_port,m_portB,m_initTimes,m_warnLevel,m_tradeState; unsigned long m_ulServIP; HeartBeatConnection* m_pHandShakeConn; bool m_bUseBackup; ErrorCodeEnum m_testResult; CSimpleStringA m_csServerIP, m_csRunDiskName; int m_nLodCtrFlag; bool m_bJBMachine; CardReadAdapter::CardReadAdapterService_ClientBase *m_pCRAClient; IDCertificate::IDCertService_ClientBase *m_pIDClient; PinPad::PinPadService_ClientBase *m_pPinPadClient; }; struct StartTask : public ITaskSp { CHeartBeatFSM* fsm; StartTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_STARTFINISHED); e->param1 = fsm->Starting(); fsm->PostEventFIFO(e); } }; struct HandShakeTask : public ITaskSp { CHeartBeatFSM* fsm; HandShakeTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_HANDSHAKEFINISHED); e->param1 = fsm->DoHandShake(); fsm->PostEventFIFO(e); } }; struct LodctrTask : public ITaskSp { CHeartBeatFSM* fsm; LodctrTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { HMODULE hDll = LoadLibrary("loadperf.dll"); if(hDll == NULL) { Dbg("Load loadperf.dll failed %d", GetLastError()); return; } LpRestorePerfRegistryFromFile restoreFunc = (LpRestorePerfRegistryFromFile)GetProcAddress( hDll, "RestorePerfRegistryFromFileW"); if(restoreFunc == NULL) { Dbg("GetProcAddress of RestorePerfRegistryFromFileW failed %d", GetLastError()); return; } DWORD dwRet = restoreFunc(NULL, NULL); Dbg("restoreFunc returned 0x%08x", dwRet); if(dwRet == 0) { fsm->SetLodCtrStatus(1); } else { fsm->SetLodCtrStatus(2); } return; } }; struct CardActiveTask : public ITaskSp { CHeartBeatFSM* fsm; SpReqAnsContext::Pointer ctx; CardActiveTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_CARD_ACTIVE_FINISHED); e->param1 = fsm->CardActive(ctx); fsm->PostEventFIFO(e); } }; struct CrossTermCallTask : public ITaskSp { CHeartBeatFSM* fsm; SpReqAnsContext::Pointer ctx; CrossTermCallTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_CROSS_TERM_CALL_FINISHED); e->param1 = fsm->CrossTermCall(ctx); fsm->PostEventFIFO(e); } }; struct ILCallToRVCTask : public ITaskSp { CHeartBeatFSM* fsm; SpOnewayCallContext::Pointer ctx; ILCallToRVCTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { fsm->ILCallToRVC(ctx); } }; struct CallResultToILTask : public ITaskSp { CHeartBeatFSM* fsm; SpOnewayCallContext::Pointer ctx; CallResultToILTask(CHeartBeatFSM* f) : fsm(f) {} void Process() { fsm->CallResultToIL(ctx); } }; struct LocalProcessCrossCallTask : public ITaskSp { CHeartBeatFSM* fsm; CrossCallReq *xreqInfo; int xnBufSize; SpReqAnsContext::Pointer ctx; LocalProcessCrossCallTask(CHeartBeatFSM* f, CrossCallReq *reqInfo, const int nBufSize) : fsm(f),xnBufSize(nBufSize) { BYTE *pBuf = new BYTE[nBufSize + 1]; ZeroMemory(pBuf, nBufSize + 1); memcpy(pBuf, reqInfo, nBufSize); xreqInfo = (CrossCallReq*)pBuf; Dbg("id:%x",xreqInfo->nEntityID); } ~LocalProcessCrossCallTask() { if (xreqInfo) { delete[] (BYTE*)xreqInfo; } } void Process() { FSMEvent *e = new FSMEvent(USER_EVT_LOCAL_CROSS_TERM_CALL_FINISHED); e->param1 = fsm->LocalProcessCrossCall(xreqInfo,xnBufSize); fsm->PostEventFIFO(e); } }; struct ProcessPreOnlineTask : public ITaskSp { CHeartBeatFSM* fsm; CardActiveReq* cardActiveReq; ProcessPreOnlineTask(CHeartBeatFSM* f, CardActiveReq* req) : fsm(f),cardActiveReq(NULL) { if (req != NULL) { cardActiveReq = (CardActiveReq*)malloc(sizeof(struct CardActiveReq)); if(cardActiveReq != NULL) memcpy(cardActiveReq, req, sizeof(struct CardActiveReq)); } } ~ProcessPreOnlineTask() { if (cardActiveReq != nullptr) { free((void*)cardActiveReq); cardActiveReq = nullptr; } } void Process() { fsm->ProcessPreOnline(cardActiveReq); } }; class HeartBeatConnection : public SpSecureClient { public: HeartBeatConnection(CEntityBase *pEntity, CHeartBeatFSM *pFSM) : SpSecureClient(pEntity), m_pFSM(pFSM), m_TerminalNo("") { CSystemStaticInfo sysSInfo; m_pEntity->GetFunction()->GetSystemStaticInfo(sysSInfo); m_TerminalNo = sysSInfo.strTerminalID; } virtual ~HeartBeatConnection() {} void SendHandShake(); //type:0,send preonline; 1,result of preonline void SendCardActive(const int type, const int slot,unsigned long errCode, const char *termNo, const char *account, const int accSize , const char *data, const int dataSize,int findCard,int cardPos); void SendCrossCallToService(HeartBeatService_CrossTermCall_Req &req, HeartBeatService_CrossTermCall_Ans &ans); void SendILCallToService(CSimpleStringA csContent,int err,bool bFromIL, CSimpleStringA fromDevNo, CSimpleStringA toDevNo); void PkgRcvProcHandAndInstruc(const CSmartPointer &pRecvPkg); void PkgRcvProcCardActive(const CSmartPointer &pRecvPkg); void PkgRcvProcCrossCall(const CSmartPointer &pRecvPkg); protected: virtual void OnDisconnect() { m_pFSM->SetConnNULL(); this->Close(); } virtual void OnPkgAnswer(const CSmartPointer &pRecvPkg); //virtual void OnReceivePackage(CSmartPointer &pRecvPkg) //{ // //oiltest //} private: CSimpleStringA m_TerminalNo; CHeartBeatFSM *m_pFSM; }; #endif //__HEARTBEAT_FSM_H