#include "stdafx.h" #include "DeviceControlFSM.h" #include "GetDevInfoHelper.h" #include "EventCode.h" #include "fileutil.h" #include "toolkit.h" #include "osutil.h" #include "CommEntityUtil.hpp" #if defined(RVC_OS_WIN) static const char DEFAULT_ADAPTER_LIBRARY_NAME[] = "DeviceControl.cmbsz.1.1.dll"; #else static const char DEFAULT_ADAPTER_LIBRARY_NAME[] = "libDeviceControl.cmbsz.1.1.so"; #endif //RVC_OS_WIN namespace { /* PAD, Desk2S1.0: false * Stand2S, CardStore, Desk2S.2.0, Desk2S.2.1, Desk1S.1.0: true */ bool IsNeedOpenUsb(CEntityBase* pCallerEntity) { bool result = false; ErrorCodeEnum errCode = Error_Unexpect; CSystemStaticInfo sysDevInfo; errCode = pCallerEntity->GetFunction()->GetSystemStaticInfo(sysDevInfo); CSimpleStringA strMachineType; strMachineType = sysDevInfo.strMachineType; WORD majorVersion = sysDevInfo.MachineVersion.GetMajor(); WORD minorVersion = sysDevInfo.MachineVersion.GetMinor(); CSimpleStringA machineVersion = CSimpleStringA::Format("%d.%d", majorVersion, minorVersion); Dbg("MachineType:%s, machineVersion:%s", strMachineType.GetData(), machineVersion.GetData()); if (!strMachineType.Compare("RVC.PAD", true) || (!strMachineType.Compare("RVC.Desk2S", true) && !machineVersion.Compare("1.0"))) { result = false; } else if (!strMachineType.Compare("RVC.Stand2S", true) || !strMachineType.Compare("RVC.CardStore", true) || (!strMachineType.Compare("RVC.Desk2S", true) && !machineVersion.Compare("2.0")) || (!strMachineType.Compare("RVC.Desk2S", true) && !machineVersion.Compare("2.1")) || (!strMachineType.Compare("RVC.Desk1S", true) && !machineVersion.Compare("1.0"))) { result = true; } else { //TODO:: if add new machine type result = true; } return result; } } ErrorCodeEnum CDeviceControlFSM::OnInit() { LOG_FUNCTION(); ErrorCodeEnum eErr; GET_DEV_ENTITY_BASE_POINTER()->InitializeVendorLogSwitch(); CSmartPointer spConfig; CSystemStaticInfo sysInfo; CSmartPointer spEntityFunction = GetEntityBase()->GetFunction(); eErr = spEntityFunction->GetSystemStaticInfo(sysInfo); if (eErr != Error_Succeed) { Dbg("Get System Static info failed: %s.", SpStrError(eErr)); return eErr; } spEntityFunction->OpenConfig(Config_Root, spConfig); m_csMachineType = sysInfo.strMachineType; Dbg("machine type:%s", (LPCTSTR)m_csMachineType); CSimpleStringA dllName, tmpDevSN(""); const bool IsNotPadType = (m_csMachineType.IsNullOrEmpty() || m_csMachineType.Compare("RVC.PAD", true) != 0 || m_bFWB); if(IsNotPadType) { CSimpleStringA csDepPath(""); eErr = spEntityFunction->GetPath("Dep", csDepPath); if (eErr == Error_Succeed) { Dbg("not RVC.PAD or is FWB(%d),to use default dll.", m_bFWB); dllName = csDepPath + SPLIT_SLASH_STR; dllName += DEFAULT_ADAPTER_LIBRARY_NAME; } } else { auto pEntity = GET_DEV_ENTITY_BASE_POINTER(); eErr = pEntity->ExtractVendorLibFullPath(dllName); if (eErr != Error_Succeed) { Dbg("ExtractVendorLibFullPath(%s) failed.", (LPCTSTR)dllName); return Error_DevLoadFileFailed; } Dbg("%s", (LPCTSTR)dllName); } eErr = m_hDevHelper.LoadUp(dllName); if (eErr != Error_Succeed) { Dbg("LoadUp failed.%s", SpStrError(eErr)); return Error_DevLoadFileFailed; } else { Dbg("load vendor dll and pointer suc."); } InitializeTokenLib(); if (!IsNotPadType)//RVC.PAD to read root.ini { int baudRate, port; spConfig->ReadConfigValueInt("Device.DeviceControl", "Baudrate", baudRate); spConfig->ReadConfigValueInt("Device.DeviceControl", "Port", port); eErr = m_hDevHelper->DevOpen(port, baudRate); if (eErr != Error_Succeed) { LOG_DEVCONTROL_ERROR_MSG_MACRO(eErr, DevOpen); return Error_DevConnFailed; } else { Dbg("Open device succ."); } eErr = m_hDevHelper->PortControl(USB_PORT_ENABLE); if (eErr != Error_Succeed) { LOG_DEVCONTROL_ERROR_MSG_MACRO(eErr, PortControl); } } return Error_Succeed; } ErrorCodeEnum CDeviceControlFSM::InitializeTokenLib() { #if defined(RVC_OS_WIN) CSmartPointer spEntityFunction = GetEntityBase()->GetFunction(); CSimpleStringA csDepPath(""); ErrorCodeEnum eErr = spEntityFunction->GetPath("Dep", csDepPath); if (eErr == Error_Succeed) { CSimpleStringA csAQUkeyDll, csBackslash("\\"); csAQUkeyDll = csDepPath + csBackslash + "token.dll"; m_hTokenDll = LoadLibraryA(csAQUkeyDll); if (m_hTokenDll == NULL) { Dbg("Load aq dll failed.%d", GetLastError()); return Error_DevLoadFileFailed; } else { if ((AQGetUKeyID = (lpGetUKeyID)GetProcAddress(m_hTokenDll, "GetUKeyID")) == NULL) { Dbg("Get GetUKeyID failed."); return Error_DevLoadFileFailed; } if ((AQInitToken = (lpInitToken)GetProcAddress(m_hTokenDll, "InitToken")) == NULL) { Dbg("Get InitToken failed."); return Error_DevLoadFileFailed; } Dbg("Load aq suc."); } } return eErr; #else return Error_NotSupport; #endif //RVC_OS_WIN } void CDeviceControlFSM::DoRestartSogouServicesJob() { LOG_FUNCTION(); CSmartPointer spConfig; ErrorCodeEnum err = GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spConfig); CSimpleStringA str(true); err = spConfig->ReadConfigValue("Browser", "SogouRestart", str); if (str.Compare("true", true) == 0) { spConfig->WriteConfigValue("Browser", "SogouRestart", NULL); RestartSogouServices(); } } ErrorCodeEnum CDeviceControlFSM::RestartSogouServices() { LOG_FUNCTION(); ErrorCodeEnum result(Error_Succeed); CSimpleStringA shellScriptPath; GetEntityBase()->GetFunction()->GetPath("Base", shellScriptPath); shellScriptPath += SPLIT_SLASH_STR; shellScriptPath += "res" SPLIT_SLASH_STR "RunScript" SPLIT_SLASH_STR; std::string startup_service(shellScriptPath.GetData()); startup_service += "startup_sogouservice.sh"; std::string shutdown_service(shellScriptPath.GetData()); shutdown_service += "shutdown_sogouservice.sh"; std::string shutdown_service_without_monitor(shellScriptPath.GetData()); shutdown_service_without_monitor += "shutdown_sogouservice_without_monitor.sh"; const BOOL s1 = ExistsFileA(startup_service.c_str()); const BOOL s2 = ExistsFileA(shutdown_service.c_str()); const BOOL s3 = ExistsFileA(shutdown_service_without_monitor.c_str()); if (s3) { Dbg("to shutdown sogou service except monitor..."); char* relate_processes[3] = { "sogouImeWebSrv", "sogouImeService", "sogoumonitor.sh" }; int count = 4; alive_process_info old_processes[4]; memset(old_processes, 0, sizeof(old_processes)); osutil_detect_unique_app(relate_processes, array_size(relate_processes), &count, old_processes); int sogouImeWebSrv_PID(0), sogouImeServicePID(0); bool monitor_exist(false), other_exists(false); /** 因为接口暂时获取不了命令行的内容,只能暂时将此接口置为成功 [Gifur@2022110]*/ monitor_exist = true; for (int i = 0; i < count; ++i) { if (strcmp(old_processes[i].name, relate_processes[2]) == 0) { monitor_exist = true; } else { other_exists = true; } if (strcmp(old_processes[i].name, relate_processes[0]) == 0) { sogouImeWebSrv_PID = old_processes[i].pid; } else if (strcmp(old_processes[i].name, relate_processes[1]) == 0) { sogouImeServicePID = old_processes[i].pid; } } if (!monitor_exist) { return Error_InvalidState; } else if(!other_exists){ return Error_NotExist; } else { std::string succStr, errStr; std::string runStr("bash "); runStr += shutdown_service_without_monitor; if (!SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { LogWarn(Severity_Middle, Error_Unexpect, LOG_DEVICECONTROL_SOGOU_SCRIPTS_EXECUTE_FAILED, CSimpleStringA::Format("%s: %s, %s", shutdown_service_without_monitor.c_str(), succStr.c_str(), errStr.c_str())); return Error_Unexpect; } else { Dbg("execute {%s} suc: %s", shutdown_service_without_monitor.c_str(), succStr.c_str()); /**等待服务进程退出 */ Sleep(300); /** Sogou的监护服务每隔5s会检测搜狗服务是否存在,否则会重启,为什么不自己重启,因为搜狗服务得跑在普通用户权限下 [Gifur@20211230]*/ const DWORD defaultInterval = 3000; const int maxtIntervalTimes(3); int intervalTimes(0); char* relate_processes2[2] = { "sogouImeWebSrv", "sogouImeService" }; bool succ_flag(false); int sogouImeWebSrv_newPID(0), sogouImeService_newPID(0); int count2 = 3; alive_process_info new_processes[3]; memset(new_processes, 0, sizeof(new_processes)); osutil_detect_unique_app(relate_processes2, array_size(relate_processes2), &count2, new_processes); do { if (count2 == 2/*normal process count*/) { int exit_flag(0); for (int i = 0; i < count2; ++i) { if (strcmp(new_processes[i].name, relate_processes2[0]) == 0 && sogouImeWebSrv_PID != new_processes[i].pid) { sogouImeWebSrv_newPID = new_processes[i].pid; exit_flag += 1; } else if (strcmp(new_processes[i].name, relate_processes2[1]) == 0 && sogouImeServicePID != new_processes[i].pid) { exit_flag += 1; sogouImeService_newPID = new_processes[i].pid; } } if (exit_flag == 2) { succ_flag = true; break; } } if (++intervalTimes >= maxtIntervalTimes) { break; } Sleep(defaultInterval); count2 = 3; memset(new_processes, 0, sizeof(new_processes)); osutil_detect_unique_app(relate_processes2, array_size(relate_processes2), &count2, new_processes); } while (true); if (succ_flag) { LogWarn(Severity_Middle, Error_Debug, LOG_DEVICECONTROL_SOGOU_SCRIPTS_EXECUTE_SUCC, CSimpleStringA::Format("auto restart sogou services succ: WebSrv pid: %u, Service pid: %u", sogouImeWebSrv_newPID, sogouImeService_newPID)); result = Error_Succeed; } else { LogWarn(Severity_Middle, Error_TimeOut, LOG_DEVICECONTROL_SOGOU_SCRIPTS_EXECUTE_TIMEOUT, "wait sogou auto restart timeout"); result = Error_TimeOut; } } } } else if (s1 && s2) { do { std::string succStr, errStr; std::string runStr("bash "); runStr += shutdown_service; if (!SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { LogWarn(Severity_Middle, Error_Unexpect, LOG_DEVICECONTROL_SOGOU_SCRIPTS_EXECUTE_FAILED, CSimpleStringA::Format("%s: %s, %s", shutdown_service.c_str(), succStr.c_str(), errStr.c_str())); return Error_Unexpect; } else { Dbg("execute {%s} suc: %s", shutdown_service.c_str(), succStr.c_str()); } } while (false); Sleep(3000); do { char app[MAX_PATH] = { '\0' }; tk_process_t* process = NULL; tk_process_option_t option; option.exit_cb = NULL; option.file = NULL; option.flags = 0; sprintf(app, "bash %s", startup_service.c_str()); option.params = app; const int res = process_spawn(&option, &process); if (0 == res) { FREE(process); Dbg("execute {%s} suc", startup_service.c_str()); } else { LogWarn(Severity_Middle, Error_Unexpect, LOG_DEVICECONTROL_SOGOU_SCRIPTS_EXECUTE_FAILED, CSimpleStringA::Format("%s: %d", startup_service.c_str(), res)); return Error_Unexpect; } } while (false); LogWarn(Severity_Middle, Error_Unexpect, LOG_DEVICECONTROL_SOGOU_SCRIPTS_EXECUTE_SUCC, "sogou restart succ."); } else { LogWarn(Severity_Middle, Error_NotExist, LOG_DEVICECONTROL_SOGOU_SCRIPTS_NOT_EXISTS, CSimpleStringA::Format("%s=%d, %s=%d", startup_service.c_str(), s1, shutdown_service.c_str(), s2)); result = Error_NotExist; } return result; } ErrorCodeEnum CDeviceControlFSM::OnExit() { return Error_Succeed; } unsigned int CDeviceControlFSM::s0_on_event(FSMEvent* pEvt) { Dbg("s0 event %d,%d", pEvt->iEvt, pEvt->param1); switch (pEvt->iEvt) { case USER_EVT_USB: { USBEvent* ue = dynamic_cast(pEvt); OpenTask* task = new OpenTask(this); task->ctx = ue->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_QUERY_USB: { QueryUSBEvent* ue = dynamic_cast(pEvt); QueryUSBTask* task = new QueryUSBTask(this); task->ctx = ue->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_GET_UKEYID: { GetUkeyIDEvent* ue = dynamic_cast(pEvt); GetUkeyIDTask* task = new GetUkeyIDTask(this); task->ctx = ue->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); #if defined(RVC_OS_WIN) m_bWorkingOp = true; WorkingOpTask* pOp = new WorkingOpTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(pOp); #endif //RVC_OS_WIN return 0; } case USER_EVT_INIT_TOKEN: { InitTokenEvent* ue = dynamic_cast(pEvt); InitTokenTask* task = new InitTokenTask(this); task->ctx = ue->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); #if defined(RVC_OS_WIN) m_bWorkingOp = true; WorkingOpTask* pOp = new WorkingOpTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(pOp); #endif //RVC_OS_WIN return 0; } default: break; } return 0; } unsigned int CDeviceControlFSM::s1_on_event(FSMEvent* pEvt) { Dbg("s1 %d,%d", pEvt->iEvt, pEvt->param1); switch (pEvt->iEvt) { case USER_EVT_USB_FINISHED: pEvt->SetHandled(); return pEvt->param1; case USER_EVT_QUERY_USB_FINISHED: pEvt->SetHandled(); return pEvt->param1; default: break; } return 0; } unsigned int CDeviceControlFSM::s3_on_event(FSMEvent* pEvt) { Dbg("s3 %d,%d", pEvt->iEvt, pEvt->param1); switch (pEvt->iEvt) { case USER_EVT_GET_UKEYID_FINISHED: pEvt->SetHandled(); return pEvt->param1; default: break; } return 0; } unsigned int CDeviceControlFSM::s4_on_event(FSMEvent* pEvt) { Dbg("s4 %d,%d", pEvt->iEvt, pEvt->param1); switch (pEvt->iEvt) { case USER_EVT_INIT_TOKEN_FINISHED: pEvt->SetHandled(); return pEvt->param1; default: break; } return 0; } int CDeviceControlFSM::UsbControl(SpReqAnsContext::Pointer ctx) { Dbg("open %d", ctx->Req.open); if (IsNeedOpenUsb(m_pEntity)) { ControlType eType; if (ctx->Req.open) { eType = USB_PORT_ENABLE; LogEvent(Severity_Middle, LOG_EVT_USB_CONTROL_ON, "usb on");//control by gpio LogEvent(Severity_Middle, LOG_EVT_USB_LIGHT_ON, "usb on");//control by gpio } else { eType = USB_PORT_DISABLE; LogEvent(Severity_Middle, LOG_EVT_USB_CONTROL_OFF, "usb off");//control by gpio LogEvent(Severity_Middle, LOG_EVT_USB_LIGHT_OFF, "usb off");//control by gpio } } else { Dbg("no need open/close usb, this machine's usb is always open."); } ctx->Answer(Error_Succeed); return 0; } int CDeviceControlFSM::GetUkeyIDx(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); if (ctx == NULL) { Dbg("ctx is null."); return 1; } #if defined(RVC_OS_WIN) char pID[512]; ZeroMemory(pID, 512); int tmp = 512; int ret = AQGetUKeyID(pID, tmp); m_bWorkingOp = false; if (ret == 0) { ctx->Ans.UkeyID = pID; ctx->Ans.UkeyIDLen = strlen(pID); Dbg("oiltest ukey id [%d][%s][%d]", tmp, (LPCTSTR)ctx->Ans.UkeyID, ctx->Ans.UkeyIDLen); ctx->Ans.reserved1 = 999; ctx->Answer(Error_Succeed); return 0; } else { Dbg("GetUKey failed.%d,%d", ret, GetLastError()); ctx->Ans.reserved1 = ret; ctx->Answer(Error_Succeed); return 1; } #else ctx->Answer(Error_NotSupport); return 1; #endif //RVC_OS_WIN } int CDeviceControlFSM::InitTokenx(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); if (ctx == NULL) { Dbg("ctx is null."); return 1; } #if defined(RVC_OS_WIN) int tokensnlen, pkcs10len, msglen; tokensnlen = 32; pkcs10len = 2048; msglen = 128; char tokenSn[32], pkcs10[2048], msg[128]; ZeroMemory(tokenSn, tokensnlen); ZeroMemory(pkcs10, pkcs10len); ZeroMemory(msg, msglen); int ret = AQInitToken(const_cast(ctx->Req.CertType.GetData()) , ctx->Ans.TokenType, const_cast(ctx->Req.OldSuperPwd.GetData()) , const_cast(ctx->Req.UserName.GetData()) , const_cast(ctx->Req.UserIDType.GetData()) , const_cast(ctx->Req.UserIDNo.GetData()) , tokenSn , tokensnlen, pkcs10, pkcs10len, msg, msglen); m_bWorkingOp = false; if (ret == 0) { Dbg("[%d][%s][%d][%s][%d]", tokensnlen, tokenSn, msglen, msg, pkcs10len); char xx1[768], xx2[768]; ZeroMemory(xx1, 768); ZeroMemory(xx2, 768); if (pkcs10len > 600) { strncpy(xx1, pkcs10, 600); strncpy(xx2, pkcs10 + 600, pkcs10len - 600 + 1); } else strncpy(xx1, pkcs10, pkcs10len); Dbg("[%s]", xx1); Dbg("[%s]", xx2); ctx->Ans.TokenSn = tokenSn; ctx->Ans.PKCS10 = pkcs10; ctx->Ans.Msg = msg; ctx->Ans.TokenSnLen = tokensnlen; ctx->Ans.PKCS10Len = pkcs10len; ctx->Ans.MsgLen = msglen; ctx->Ans.reserved1 = 999; ctx->Answer(Error_Succeed); return 0; } else { Dbg("InitToken failed.%d,%d", ret, GetLastError()); ctx->Ans.reserved1 = ret; ctx->Answer(Error_Succeed); return 1; } #else ctx->Answer(Error_NotSupport); return 1; #endif //RVC_OS_WIN } int CDeviceControlFSM::QueryUSB(SpReqAnsContext::Pointer ctx) { ErrorCodeEnum eErr = Error_Unexpect; GpioService_ClientBase* pGpio = new GpioService_ClientBase(this->GetEntityBase()); if (pGpio != NULL) { eErr = pGpio->Connect(); if (eErr != Error_Succeed) { Dbg("connect to gpio failed."); pGpio->SafeDelete(); pGpio = NULL; ctx->Answer(eErr); return 0; } GpioService_QueryCurrSet_Req req; GpioService_QueryCurrSet_Ans ans; eErr = pGpio->QueryCurrSet(req, ans, 10000); if (eErr == Error_Succeed) { ctx->Ans.flag = ((ans.output & 0x2) == 0x2); Dbg("%d,%d", ans.output, ctx->Ans.flag); ctx->Answer(Error_Succeed); } else { Dbg("Query usb failed: %s", SpStrError(eErr)); ctx->Answer(eErr); } pGpio->GetFunction()->CloseSession(); } return 0; } /** 5s per times and quit after 100 times*/ void CDeviceControlFSM::WorkingOp() { int count = 0; while (m_bWorkingOp) { //relate with eventconvert LogEvent(Severity_Low, LOG_EVT_USB_CONTROL_OP, "ukey op."); Sleep(5000); count++; if (count > 100) { m_bWorkingOp = false; break; } } }