#include "precompile.h" #include "sp_cfg.h" #include "sp_def.h" //#include "sp_sal.h" #include "sp_dir.h" #include "sp_env.h" #include "sp_var.h" #include "iniutil.h" #include "strutil.h" #include "memutil.h" #include "shm_mem.h" #include "fileutil.h" #include "SpBase.h" #include "CodeSignVerify.h" #include #include #include #include #include #include #include #include #include #include #include "dbgutil.h" #include "sp_httpDefine.h" #include "sp_logwithlink.h" #include "RestfulFunc.h" #if defined(_MSC_VER) #include "AutoLock.h" #include #include #include #include "RVCEventCode.h" #include #include #include #include #include #define UPDATE_ROOT_BY_HTTP #else #include "JsonConvertHelper.hpp" #endif //_MSC_VER #include "sp_checkEntity.h" #include #if defined(_MSC_VER) std::map g_specialRunInfoArr; class sp_cfg_share { private: LARGE_TIME m_shellFirstStart; public: static sp_cfg_share* getInstance(); void sp_cfg_setShellFirstStartTime(LARGE_TIME t_shellFirstStart) { m_shellFirstStart = t_shellFirstStart; }; LARGE_TIME sp_cfg_getShellFirstStartTime() { return m_shellFirstStart; }; }; sp_cfg_share* sp_cfg_share::getInstance() { static sp_cfg_share* Instance = NULL; if (NULL == Instance) Instance = new sp_cfg_share(); return Instance; } void sp_cfg_setShellFirstStartTime(LARGE_TIME t_shellFirstStart) { sp_cfg_share::getInstance()->sp_cfg_setShellFirstStartTime(t_shellFirstStart); }; LARGE_TIME sp_cfg_getShellFirstStartTime() { return sp_cfg_share::getInstance()->sp_cfg_getShellFirstStartTime(); }; auto fileExist = [](const char* path) ->bool { fstream f2; f2.open(path); if (!f2) { f2.close(); return false; } else { f2.close(); return true; } }; #else ///*TODO(80374374@3/14/2023): */ #endif //_MSC_VER ErrorCodeEnum init_shell_byHttp(sp_dir_t* dir, sp_cfg_shell_ini_t* shell, sp_cfg_root_ini_t* root, const sp_cfg_start_args_t* args, const char* shellVarIni, std::map> shellConfig); int sp_tryReadFromCacheConfig(int cfgType, const char* section, const char* key, char* dst, int max_len); int sp_tryRefreshLogLevelFromCacheConfig(); void shell_getHttpToken(std::string& channelId, std::string& token, std::string& terminalNo, std::string& reserve1) { sp_env_t* env = sp_get_env(); if (NULL != env && NULL != env->cfg && NULL != env->cfg->shell_ini && env->cfg->shell_ini->channelId != NULL && env->cfg->shell_ini->token != NULL) { channelId = env->cfg->shell_ini->channelId; token = env->cfg->shell_ini->token; terminalNo = env->cfg->root_ini->terminal_no; } else if(NULL == env) DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("shell_getHttpToken can not get token!env == NULL"); else if(NULL == env->cfg) DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("shell_getHttpToken can not get token!env->cfg == NULL"); else if(NULL == env->cfg->shell_ini) DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("shell_getHttpToken can not get token!env->cfg->shell_ini == NULL"); else if(NULL == env->cfg->shell_ini->channelId) DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("shell_getHttpToken can not get token!env->cfg->shell_ini->channelId == NULL"); else if(NULL == env->cfg->shell_ini->token) DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("shell_getHttpToken can not get token!env->cfg->shell_ini->token == NULL"); } #define MAX_ENTITY_LEN 33 #ifdef _WIN32 #define MOD_LIB_SUFFIX ".dll" #else #define MOD_LIB_SUFFIX ".so" #endif //_WIN32 #define T_MALLOC_T(type, shm) \ shm ? (type*)shm_malloc(sizeof(type)) : (type*)malloc(sizeof(type)) #define T_MALLOC(size, shm) \ shm ? shm_malloc(size) : malloc(size) #define T_FREE(p, shm) \ shm ? shm_free(p) : free(p) #define T_STRDUP(s, shm) \ shm ? shm_strdup(s) : _strdup(s) #define T_ARRAY_MAKE(n, size, shm) \ shm ? shm_array_make(n, size) : array_make(n, size) std::vector g_arrKill; std::vector g_arrStart; std::vector getKillArr() { if(g_arrKill.size() > 0) return g_arrKill; std::vector ret; const int maxKillNum = 10; const int MAX_LEN = 256; for (size_t i = 1; i < maxKillNum; i++) { char tmp[MAX_LEN] = ""; if (Error_Succeed == sp_tryReadFromCacheConfig(ConfigTypeEnum::Config_Shell, "killProcess", std::to_string(i).c_str(), tmp, MAX_LEN)) ret.push_back(tmp); else break; } return ret; } std::vector getStartArr() { if(g_arrStart.size() > 0) return g_arrStart; std::vector ret; const int maxStartNum = 10; const int MAX_LEN = 256; for (size_t i = 1; i < maxStartNum; i++) { char tmp[MAX_LEN] = ""; if (Error_Succeed == sp_tryReadFromCacheConfig(ConfigTypeEnum::Config_Shell, "RunScript", std::to_string(i).c_str(), tmp, MAX_LEN)) ret.push_back(tmp); else break; } return ret; } static int verify_entity_name(const char *name) { const char *p = name; int len = 0; while (*p) { if (!isalnum(*p)) { return FALSE; } len++; if (len > MAX_ENTITY_LEN) return FALSE; p++; } return TRUE; } static int parse_install_state(const char *str) { const struct { int ch; int val; } tbl[] = { {'A', Install_Active}, {'I', Install_Pending}, {'S', Install_SetToStart}, {'F', Install_FailRun}, {'R', Install_RollBack}, {'U', Install_Upgraded}, {'C',Install_Cancelled}, {'W',Install_WaitConfirm}, {'D', Install_Installed}, }; int i; for (i = 0; i < array_size(tbl); ++i) { if (tbl[i].ch == str[0]) { return tbl[i].val; } } return -1; // error } int read_ini_install_state(const char *file, const char *section, const char *key) { char *p = inifile_read_str(file, section, key, ""); int ret = parse_install_state(p); FREE(p); return ret; } static __inline int file_write(FILE *fp, const void *buf, int n) { size_t t = fwrite(buf, n, 1, fp); return t == n ? 0 : Error_IO; } static __inline int file_read(FILE *fp, void *buf, int n) { size_t t = fread(buf, n, 1, fp); return t == n ? 0 : Error_IO; } static void destroy_entity(sp_cfg_shell_entity_t *entity) { if (entity) { if (entity->name) shm_free(entity->name); if (entity->argv) shm_free((void*)entity->argv); if (entity->cmdline) shm_free(entity->cmdline); shm_free(entity); } } static void destroy_module(sp_cfg_shell_module_t* mod) { if (mod) { if (mod->name) shm_free(mod->name); if (mod->author) shm_free(mod->author); if (mod->company) shm_free(mod->company); shm_free(mod); } } static void destroy_sysevent(sp_cfg_shell_sysevent_t *sysevent) { if (sysevent) { if (sysevent->name) shm_free(sysevent->name); if (sysevent->arr_owner_entity) shm_array_free(sysevent->arr_owner_entity); shm_free(sysevent); } } /*find path from root.ini which loaded at begin*/ static sp_cfg_path_t *find_path(sp_cfg_t *cfg, const char *path_prefix) { int i; for (i = 0; cfg->root_ini->arr_path != NULL && i < cfg->root_ini->arr_path->nelts; ++i) { sp_cfg_path_t *tpath = ARRAY_IDX(cfg->root_ini->arr_path, i, sp_cfg_path_t*); if (strcmp(tpath->name, path_prefix) == 0) { return tpath; } } return NULL; } static sp_cfg_shell_module_t* find_module(sp_cfg_shell_ini_t *shell, const char *mod_name) { int i; sp_cfg_shell_module_t* mod; const int len = (strstr(mod_name, "lib") == mod_name) ? 3 : 0; //linux .so name ARRAY_FOR_EACH_ENTRY(mod, i, shell->arr_module, sp_cfg_shell_module_t*) { if (_stricmp(mod->name, mod_name + len) == 0) return mod; } return NULL; } static sp_cfg_shell_entity_t *find_entity(sp_cfg_shell_ini_t *shell, const char *entity_name) { int i; sp_cfg_shell_entity_t *entity; ARRAY_FOR_EACH_ENTRY(entity, i, shell->arr_entity, sp_cfg_shell_entity_t*) { if (_stricmp(entity->name, entity_name) == 0) return entity; } return NULL; } static int read_ini_version(const char *file, const char *section, const char *key, int *major, int *minor, int *revision, int *build) { int n; int ret = -1; char *str = inifile_read_str(file, section, key, ""); if (str) { const int len = strlen(str); FREE(str); if (len == 0) { if (major) *major = 0; if (minor) *minor = 0; if (revision) *revision = 0; if (build) *build = 0; return 0; } } if (build) { n = inifile_format_read(file, section, key, "%d.%d.%d.%d", major, minor, revision, build); if (n == 4) ret = 0; } else if (revision) { n = inifile_format_read(file, section, key, "%d.%d.%d", major, minor, revision); if (n == 3) ret = 0; } else { n = inifile_format_read(file, section, key, "%d.%d", major, minor); if (n == 2) ret = 0; } return ret; } static int read_ini_str(const char *file, const char *section, const char *key, char **pstr, int shm) { int rc = Error_Param; char* str = inifile_read_str(file, section, key, ""); if (str) { if (shm) { *pstr = shm_strdup(str); rc = 0; FREE(str); } else { *pstr = str; rc = 0; } } return rc; } static int read_ini_date(const char *file, const char *section, const char *key, int *year, int *month, int *day, int *hour, int *minute, int *second, int shm) { int ret; if (second) *second = 0; ret = inifile_format_read(file, section, key, "%d-%d-%d %d:%d", year, month, day, hour, minute); return ret == 5 ? 0 : Error_Param; } static int read_ini_position(const char *file, const char *section, const char *key, float *x, float *y, int shm) { int ret; ret = inifile_format_read(file, section, key, "%f,%f", x, y); return ret == 2 ? 0 : Error_Param; } static int read_ini_path(const char *file, const char *section, const char *key, char **path, int shm) { int rc = read_ini_str(file, section, key, path, shm); if (rc == 0) { char *s = *path; int slen = strlen(s); if (s[slen - 1] == SPLIT_SLASH) s[slen - 1] = 0; } return rc; } static int read_terminal(const char *file, sp_cfg_root_ini_t *root, int shm) { int rc = 0; rc = read_ini_str(file, "Terminal", "TerminalNo", &root->terminal_no, shm); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read TerminalNo failed!"); return rc; } else if (strlen(root->terminal_no) == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read TerminalNo empty!"); return Error_NotConfig; } rc = read_ini_str(file, "Terminal", "MachineType", &root->machine_type, shm); if (rc != 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read MachineType failed!"); else if (strlen(root->machine_type) == 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read MachineType empty!"); rc = read_ini_str(file, "Terminal", "MachineModel", &root->machine_model, shm); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read MachineModel failed!"); } rc = read_ini_str(file, "Terminal", "SN", &root->machine_sn, shm); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read SN failed!"); } rc = read_ini_str(file, "Terminal", "Manufacturer", &root->manufacturer, shm); if (rc != 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read Manufacturer failed!"); else if (strlen(root->manufacturer) == 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read Manufacturer empty!"); rc = read_ini_version(file, "Terminal", "MachineVersion", &root->machine_version.major, &root->machine_version.minor, NULL, NULL); rc = read_ini_str(file, "Terminal", "Site", &root->site, shm); root->screen = inifile_read_int(file, "Terminal", "Screen", -1); if (root->screen == -1) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read Screen failed!"); rc = read_ini_position(file, "Terminal", "EnrolGPS", &root->enroll_gps_x, &root->enroll_gps_y, shm); if (rc != 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read EnrolGPS failed!"); rc = read_ini_str(file, "Terminal", "EnrolAddr", &root->enroll_address, shm); if (rc != 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read EnrolAddr failed!"); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read_terminal success, TerminalNo:%s, MachineType:%s, MachineModel:%s, MachineVersion:%d.%d, site:%s, screen:%d", root->terminal_no, root->machine_type == NULL ? "" : root->machine_type , root->machine_model == NULL ? "" : root->machine_model , root->machine_version.major, root->machine_version.minor , root->site == NULL ? "" : root->site, root->screen); return rc; } int safeStringToInt(const std::string& str) { if (str.empty()) { // 返回默认值,或者抛出自定义异常,或者进行其他错误处理 return 0; // 返回默认值 0 } else { try { return std::stoi(str); } catch (const std::invalid_argument& e) { // 返回默认值,或者抛出自定义异常,或者进行其他错误处理 return 0; // 返回默认值 0 } } } bool update_rootCfg(sp_cfg_root_ini_t* root, std::map >& root_cfg) { if (root_cfg.find(CONFIG_TERMINALINFO_HEAD) == root_cfg.end()) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_TERMINALINFO_HEAD); return false; } auto terminalinfo_root = root_cfg[CONFIG_TERMINALINFO_HEAD]; if (terminalinfo_root.find(CONFIG_NODE_MACHINETYPE) != terminalinfo_root.end()) { shm_free(root->machine_type); root->machine_type = shm_strdup(terminalinfo_root[CONFIG_NODE_MACHINETYPE].c_str()); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_MACHINETYPE); if (terminalinfo_root.find(CONFIG_NODE_MACHINEVERSION) != terminalinfo_root.end()) sscanf(terminalinfo_root[CONFIG_NODE_MACHINETYPE].c_str(), "%d.%d", &root->machine_version.major, &root->machine_version.minor); else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_MACHINEVERSION); if (terminalinfo_root.find(CONFIG_NODE_SITES) != terminalinfo_root.end()) { shm_free(root->site); root->site = shm_strdup(terminalinfo_root[CONFIG_NODE_SITES].c_str()); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_SITES); if (terminalinfo_root.find(CONFIG_NODE_SCREEN) != terminalinfo_root.end()) root->screen = safeStringToInt(terminalinfo_root[CONFIG_NODE_SCREEN]); else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_SCREEN); if (terminalinfo_root.find(CONFIG_NODE_ENROLADDR) != terminalinfo_root.end()) { shm_free(root->enroll_address); root->enroll_address = shm_strdup(terminalinfo_root[CONFIG_NODE_ENROLADDR].c_str()); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_ENROLADDR); if (terminalinfo_root.find(CONFIG_NODE_MANUFACTURER) != terminalinfo_root.end()) { shm_free(root->manufacturer); root->manufacturer = shm_strdup(terminalinfo_root[CONFIG_NODE_MANUFACTURER].c_str()); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_MANUFACTURER); if (terminalinfo_root.find(CONFIG_NODE_MACHINEMODEL) != terminalinfo_root.end()) { shm_free(root->machine_model); root->machine_model = shm_strdup(terminalinfo_root[CONFIG_NODE_MACHINEMODEL].c_str()); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("can not find node:%s", CONFIG_NODE_MACHINEMODEL); return true; } SPBASE_API int sp_cfg_getVer(char *ver) { static CSimpleStringA s_terminalVer; if (s_terminalVer.GetLength() == 0)//only init s_terminalVer one time { CSimpleStringA strActiveFile = CSimpleStringA::Format("%s" SPLIT_SLASH_STR "active.txt", sp_get_env()->dir->root_ver_path); std::ifstream iFile(strActiveFile.GetData()); if (!iFile.is_open()) { LogError(Severity_Low, Error_Unexpect, 0, "open active.txt fail"); return Error_Unexpect; } std::ostringstream buffer; buffer << iFile.rdbuf(); std::string myString = buffer.str(); // 去除空格 myString.erase(std::remove(myString.begin(), myString.end(), ' '), myString.end()); // 去除换行符 myString.erase(std::remove(myString.begin(), myString.end(), '\r'), myString.end()); myString.erase(std::remove(myString.begin(), myString.end(), '\n'), myString.end()); s_terminalVer = myString.c_str(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("read active.txt, version[%s]", s_terminalVer.GetData()); } #ifdef RVC_OS_LINUX sprintf(ver, "%s", s_terminalVer.GetData()); #else sprintf_s(ver, SP_MAX_VER_LEN, "%s", s_terminalVer.GetData()); #endif return Error_Succeed; } SPBASE_API int sp_cfg_getDepVer(char* ver) { auto cfg = sp_get_env()->cfg; auto dir = sp_get_env()->dir; int rc = Error_Succeed; if (cfg == NULL || dir == NULL) return Error_Null; char path[MAX_PATH] = ""; rc = sp_dir_get_path(dir, SP_DIR_DEPVER_TXT, NULL, path, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("get depver.txt path failed!"); return rc; } char version[SP_MAX_VER_LEN]; int result; if ((result = sp_dir_inner_get_content(path, version)) == 0) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("read dep version text, version[%s]", version); sprintf(ver, "%s", version); } return result; } void get_upload_info(unsigned long* t_upload_TerminalSys_Suc, unsigned long* t_upload_TerminalUser_Suc, unsigned long* t_upload_BussinessSys_Suc, unsigned long* t_upload_BussinessUser_Suc, unsigned long* t_upload_beidou_Suc, unsigned long* t_upload_TerminalSys_Err, unsigned long* t_upload_TerminalUser_Err, unsigned long* t_upload_BussinessSys_Err, unsigned long* t_upload_BussinessUser_Err, unsigned long* t_upload_beidou_Err) { log_producer_config_get_upload_info(t_upload_TerminalSys_Suc, t_upload_TerminalUser_Suc, t_upload_BussinessSys_Suc, t_upload_BussinessUser_Suc, t_upload_beidou_Suc, t_upload_TerminalSys_Err, t_upload_TerminalUser_Err, t_upload_BussinessSys_Err, t_upload_BussinessUser_Err, t_upload_beidou_Err); } void get_upload_info2(unsigned long* t_discard_full, unsigned long* t_discard_RTI1002, unsigned long* curLogNum) { log_producer_config_get_upload_info2(t_discard_full, t_discard_RTI1002, curLogNum); } int sp_TryUpdateToken(char *oldToken, char *newToken) { auto cfg = sp_get_env()->cfg; if (cfg == NULL || cfg->shell_ini == NULL || cfg->root_ini == NULL) return Error_Null; std::string terminalNoInRoot = (cfg->root_ini->terminal_no == NULL) ? "" : cfg->root_ini->terminal_no; std::string channelId = (cfg->shell_ini->channelId == NULL) ? "" : cfg->shell_ini->channelId; std::string tokenScret = (cfg->shell_ini->tokenSecret == NULL) ? "" : cfg->shell_ini->tokenSecret; std::string commonUrl = (cfg->shell_ini->CommonLaunchUrl == NULL) ? "" : cfg->shell_ini->CommonLaunchUrl; char terminalVer[SP_MAX_VER_LEN] = ""; sp_cfg_getVer(terminalVer); if (cfg->shell_ini->token != NULL) strcpy(oldToken, cfg->shell_ini->token); if (commonUrl.length() == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setAPI("TryUpdateToken").setLogCode("QLR0402Z10A00001")("can not get CommonLaunchUrl from shell"); return ErrorCodeEnum::Error_NotConfig; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_USER)("TryUpdateToken by %s, %s", terminalNoInRoot.c_str(), terminalVer); auto tokenRet = refreshToken(terminalNoInRoot, terminalVer, channelId, tokenScret, commonUrl); if (tokenRet.first) { if (cfg->shell_ini->token != NULL) shm_free(cfg->shell_ini->token); cfg->shell_ini->token = shm_strdup(tokenRet.second.c_str()); strcpy(newToken, cfg->shell_ini->token); return ErrorCodeEnum::Error_Succeed; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("TryUpdateToken").setLogCode("QLR0402Z10A00003")("total getToken failed, commonUrl:%s", commonUrl.c_str()); return ErrorCodeEnum::Error_Failed; } } bool checkRootIniParam(sp_cfg_root_ini_t* root) { if (root == NULL) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("checkRootIniParam root == NULL"); return false; } else if (root->machine_type == NULL) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__) ("create cfg object failed!, some cfg in rootCfg not exist, machine_type:%d", root->machine_type != NULL); return false; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("checkRootIniParam terminal_no:%s, machine_type:%s, manufacturer:%s, machine_model:%s" , (root->terminal_no == NULL ? "" : root->terminal_no), (root->machine_type == NULL ? "" : root->machine_type) , (root->manufacturer == NULL ? "" : root->manufacturer), (root->machine_model == NULL ? "" : root->machine_model)); return true; } int sp_tryReadFromCacheConfig(int cfgType, const char* section, const char* key, char* dst, int max_len) { char tmp[MAX_PATH]; GetModuleFileNameA(NULL, tmp, MAX_PATH); *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; switch (cfgType) { case ConfigTypeEnum::Config_Run: sprintf(tmp, "%s" SPLIT_SLASH_STR "runinfo" SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "rootCfg", tmp); break; case ConfigTypeEnum::Config_Shell: sprintf(tmp, "%s" SPLIT_SLASH_STR "runinfo" SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "ShellCfg", tmp); break; case ConfigTypeEnum::Config_Cache: sprintf(tmp, "%s" SPLIT_SLASH_STR "runinfo" SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "CenterCfg", tmp); break; default: return ErrorCodeEnum::Error_NotConfig; } if (!ExistsFile(tmp)) return ErrorCodeEnum::Error_NotConfig; std::string cfgInfo = TerminalCfgRet::readStrFromFile(tmp); std::map> tmp_Config; ConvertStrToDeviceConfigMap(cfgInfo, tmp_Config); if (tmp_Config.find(section) == tmp_Config.end()) return ErrorCodeEnum::Error_NoTarget; auto curSection = tmp_Config[section]; if (curSection.find(key) == curSection.end()) return ErrorCodeEnum::Error_NoDefine; else { #ifdef RVC_OS_LINUX sprintf(dst, "%s", curSection[key].c_str()); #else sprintf_s(dst, max_len, "%s", curSection[key].c_str()); #endif return Error_Succeed; } } int sp_tryRefreshLogLevelFromCacheConfig() { char tmp[MAX_PATH]; GetModuleFileNameA(NULL, tmp, MAX_PATH); *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; sprintf(tmp, "%s" SPLIT_SLASH_STR "runinfo" SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "CenterCfg", tmp); if (!ExistsFile(tmp)) return ErrorCodeEnum::Error_NotConfig; std::string cfgInfo = TerminalCfgRet::readStrFromFile(tmp); std::map> tmp_Config; ConvertStrToDeviceConfigMap(cfgInfo, tmp_Config); load_debugLevelInMem(tmp_Config); return 0; } int sp_tryReadFromCenterSetting(const char* section, const char* key, char *dst, int max_len) { char tmp[MAX_PATH]; GetModuleFileNameA(NULL, tmp, MAX_PATH); *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; sprintf(tmp, "%s" SPLIT_SLASH_STR "runinfo" SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "CenterCfg", tmp); if (!ExistsFile(tmp)) return ErrorCodeEnum::Error_NotConfig; std::string centerCfg = TerminalCfgRet::readStrFromFile(tmp); std::map> tmp_centerConfig; ConvertStrToDeviceConfigMap(centerCfg, tmp_centerConfig); if (tmp_centerConfig.find(section) == tmp_centerConfig.end()) return ErrorCodeEnum::Error_NoTarget; auto curSection = tmp_centerConfig[section]; if (curSection.find(key) == curSection.end()) return ErrorCodeEnum::Error_NoDefine; else { #ifdef RVC_OS_LINUX sprintf(dst, "%s", curSection[key].c_str()); #else sprintf_s(dst, max_len, "%s", curSection[key].c_str()); #endif return Error_Succeed; } } SPBASE_API int sp_ModifyMemCfg(const char* configType, const char* module, const char* name, const char* value) { auto cfg = sp_get_env()->cfg; char **dstConfig = NULL; if (0 == CSimpleString(configType).Compare("centersetting", true)) dstConfig = &(cfg->root_ini->center_config); else if (0 == CSimpleString(configType).Compare("root", true)) dstConfig = &(cfg->root_ini->root_config); else if (0 == CSimpleString(configType).Compare("shell", true)) dstConfig = &(cfg->root_ini->shell_config); else return ErrorCodeEnum::Error_Param; std::map> tmp_config; ConvertStrToDeviceConfigMap(*dstConfig == NULL ? "" : *dstConfig, tmp_config); if (tmp_config.find(module) == tmp_config.end()) { //not exist module, insert std::map std::map tmp_param; tmp_param[name] = value; tmp_config.insert(std::make_pair(module, tmp_param)); } else tmp_config[module][name] = value; std::string modifyConfig = TerminalCfgRet::ConvertMapMapConfigToStr(tmp_config); shm_free(*dstConfig); *dstConfig = shm_strdup(modifyConfig.c_str()); return ErrorCodeEnum::Error_Succeed; } int sp_TryUpdate_vtm_err_msg() { auto cfg = sp_get_env()->cfg; auto dir = sp_get_env()->dir; if (cfg == NULL || dir == NULL) return Error_Null; CSimpleStringA strShellVarIni = CSimpleStringA::Format("%s", (const char*)dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("shellVar.ini"); CSimpleStringA strVtmErrMsgCfgPath = CSimpleStringA::Format("%s", (const char*)dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append(VTMERRMSG_FILENAME); std::string terminalNoInRoot = cfg->root_ini->terminal_no == NULL ? "" : cfg->root_ini->terminal_no; CSimpleStringA CenterConfigTotal = cfg->shell_ini->CenterConfigTotal; auto vtmErrMsgList = GetVTMErrMsgCfgFromUrl(CenterConfigTotal, terminalNoInRoot.c_str()); if (!vtmErrMsgList.first)//falat, get err msg list from file { std::string versionNo = inifile_read_str(strShellVarIni.GetData(), CONFIG_HEAD, VTMERRMSG_VERSION, ""); std::string errMsgStr = TerminalCfgRet::readStrFromFile(strVtmErrMsgCfgPath.GetData()); if (versionNo.length() > 0 && errMsgStr.length() > 0) { cfg->root_ini->vtm_err_msg_version = shm_strdup(versionNo.c_str()); cfg->root_ini->vtm_err_msg_config = shm_strdup(errMsgStr.c_str()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read vtm_err_msg from shellvar.ini"); return ErrorCodeEnum::Error_Succeed; } else { cfg->root_ini->vtm_err_msg_version = shm_strdup(""); cfg->root_ini->vtm_err_msg_config = shm_strdup(""); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("set vtm_err_msg and vtm_err_msg_version to null"); return ErrorCodeEnum::Error_Null; } } //get err msg list success, write mem and write file auto writeRet = vtmErrMsgList.second.saveVTMErrToFile(strVtmErrMsgCfgPath.GetData()); if (!writeRet.first) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("saveVTMErrToFile failed, %s", writeRet.second.c_str()); return ErrorCodeEnum::Error_IO; } cfg->root_ini->vtm_err_msg_version = shm_strdup(vtmErrMsgList.second.version_no.c_str()); cfg->root_ini->vtm_err_msg_config = shm_strdup(writeRet.second.c_str()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read vtm_err_msg from http server"); return ErrorCodeEnum::Error_Succeed; } int sp_TryUpdateCfg() { auto cfg = sp_get_env()->cfg; auto dir = sp_get_env()->dir; int rc = Error_Succeed; if (cfg == NULL || dir == NULL || cfg->shell_ini == NULL || cfg->root_ini == NULL) return Error_Null; std::string terminalNoInRoot = cfg->root_ini->terminal_no == NULL ? "" : cfg->root_ini->terminal_no; CSimpleStringA CenterConfigTotal = cfg->shell_ini->CenterConfigTotal; char shellvar_path[MAX_PATH] = ""; rc = sp_dir_get_path(dir, SP_DIR_SHELLVAR_INI, NULL, shellvar_path, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get shellvar.ini path failed!"); return rc; } //do get config do { clock_t t_begin = clock();//微服务访问计时 //read old config list std::string old_centerVer, old_centerConfig, old_rootVer, old_rootConfig, old_shellVer, old_shellConfig; CSimpleStringA strShellVarIni = CSimpleStringA::Format("%s", (const char*)dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("shellVar.ini"); CSimpleStringA strRootCfgPath = CSimpleStringA::Format("%s", (const char*)dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("rootCfg"); CSimpleStringA strCenterCfgPath = CSimpleStringA::Format("%s", (const char*)dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("CenterCfg"); CSimpleStringA strShellCfgPath = CSimpleStringA::Format("%s", (const char*)dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("ShellCfg"); old_rootVer = inifile_read_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_ROOT_VERSION, ""); old_centerVer = inifile_read_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_CENTER_VERSION, ""); old_shellVer = inifile_read_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_SHELL_INI_VERSION, ""); old_rootConfig = TerminalCfgRet::readStrFromFile(strRootCfgPath.GetData()); old_centerConfig = TerminalCfgRet::readStrFromFile(strCenterCfgPath.GetData()); old_shellConfig = TerminalCfgRet::readStrFromFile(strShellCfgPath.GetData()); if (CenterConfigTotal.GetLength() == 0) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read rootCfg from root.ini"); break; } //从微服务获取集中配置和root配置 std::map> tmp_centerConfig, tmp_rootConfig, tmp_shellConfig; std::map logLevelArr; ConvertStrToDeviceConfigMap(old_centerConfig, tmp_centerConfig); ConvertStrToDeviceConfigMap(old_rootConfig, tmp_rootConfig); ConvertStrToDeviceConfigMap(old_shellConfig, tmp_shellConfig); auto runInfoRet = GetTerminalCfgFromUrl(CenterConfigTotal, terminalNoInRoot, "", "", "", tmp_centerConfig, tmp_rootConfig, tmp_shellConfig); if (!runInfoRet.first)//只有解析出错时才会进入该入口,比如获取配置失败;收到的值中无关键节点;不会因root、center、shell中缺少某一配置而返回错误 { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("GetTerminalCfgFromUrl err, env:%s, url:%s", cfg->shell_ini->env, cfg->shell_ini->CenterConfigTotal); //从微服务获取配置失败,使用当前shellVar中配置 if (tmp_centerConfig.size() > 0) { cfg->root_ini->center_version = shm_strdup(old_centerVer.c_str()); cfg->root_ini->center_config = shm_strdup(old_centerConfig.c_str()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read center_config from shellvar.ini"); load_debugLevelInMem(tmp_centerConfig); } if (tmp_rootConfig.size() > 0) { cfg->root_ini->root_version = shm_strdup(old_rootVer.c_str()); cfg->root_ini->root_config = shm_strdup(old_rootConfig.c_str()); update_rootCfg(cfg->root_ini, tmp_rootConfig); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read root_config from shellvar.ini"); checkRootIniParam(cfg->root_ini); } if (tmp_shellConfig.size() > 0) { cfg->root_ini->shell_version = shm_strdup(old_shellVer.c_str()); cfg->root_ini->shell_config = shm_strdup(old_shellConfig.c_str()); rc = init_shell_byHttp(dir, cfg->shell_ini, cfg->root_ini, cfg->args, shellvar_path, tmp_shellConfig); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read shell_config from shellvar.ini"); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "load shell.ini failed!"); return rc; } } else DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read shell_config err, no config exist"); break; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("GetTerminalCfgFromUrl success, cost:%d", (clock() - t_begin) * 1000 / CLOCKS_PER_SEC); //判断UseRootCfg,是否缓存或者清空配置 auto cur_centerConfig = runInfoRet.second.center_config; auto cur_rootConfig = runInfoRet.second.root_config; auto cur_shellConfig = runInfoRet.second.shell_config; bool t_UseRootCfg = cur_centerConfig.find("Common") != cur_centerConfig.end() && cur_centerConfig["Common"].find("UseRootCfg") != cur_centerConfig["Common"].end() && cur_centerConfig["Common"]["UseRootCfg"] == "1";/*判断UseRootCfg == 1*/ bool t_rootUpdate = runInfoRet.second.root_update; if (t_UseRootCfg && t_rootUpdate)//认为返回的root配置无问题 { //save file inifile_write_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_ROOT_VERSION, runInfoRet.second.root_version.c_str()); TerminalCfgRet::saveMapMapToFile(strRootCfgPath.GetData(), cur_rootConfig); //save mem, 使用从server获取的配置 cfg->root_ini->root_version = shm_strdup(runInfoRet.second.root_version.c_str()); cfg->root_ini->root_config = shm_strdup(TerminalCfgRet::ConvertMapMapConfigToStr(cur_rootConfig).c_str()); update_rootCfg(cfg->root_ini, cur_rootConfig); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read root_config from http server"); } else if (t_UseRootCfg && tmp_rootConfig.size() > 0)//认为返回的root配置有问题 { cfg->root_ini->root_version = shm_strdup(old_rootVer.c_str()); cfg->root_ini->root_config = shm_strdup(old_rootConfig.c_str()); update_rootCfg(cfg->root_ini, tmp_rootConfig); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read root_config from shellvar.ini"); } else { //clear file inifile_write_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_ROOT_VERSION, ""); std::map> null_config; TerminalCfgRet::saveMapMapToFile(strRootCfgPath.GetData(), null_config); //clear mem cfg->root_ini->root_config = shm_strdup(""); cfg->root_ini->root_version = shm_strdup(""); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("UseRootCfg maybe err, root_update:%d, clear all rootCfg, use default root.ini", runInfoRet.second.root_update); } checkRootIniParam(cfg->root_ini); //判断UseCenterCfg,是否缓存或者清空配置 bool t_CheckCenterCfg = cur_centerConfig.find("Common") != cur_centerConfig.end() && cur_centerConfig["Common"].find("UseCenterCfg") != cur_centerConfig["Common"].end(); if (t_CheckCenterCfg && cur_centerConfig["Common"]["UseCenterCfg"] == "1") { //save file inifile_write_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_CENTER_VERSION, runInfoRet.second.center_version.c_str()); TerminalCfgRet::saveMapMapToFile(strCenterCfgPath.GetData(), cur_centerConfig); load_debugLevelInMem(cur_centerConfig); //save mem cfg->root_ini->center_version = shm_strdup(runInfoRet.second.center_version.c_str()); cfg->root_ini->center_config = shm_strdup(TerminalCfgRet::ConvertMapMapConfigToStr(cur_centerConfig).c_str()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read center_config from http server"); } else { //clear file inifile_write_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_CENTER_VERSION, ""); std::map> null_config; TerminalCfgRet::saveMapMapToFile(strCenterCfgPath.GetData(), null_config); //clear mem cfg->root_ini->center_config = shm_strdup(""); cfg->root_ini->center_version = shm_strdup(""); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("UseCenterCfg not 1, clear all CenterCfg, use default centersetting.ini"); } //shell的读取 if (cur_shellConfig.size() > 0) { rc = init_shell_byHttp(dir, cfg->shell_ini, cfg->root_ini, cfg->args, shellvar_path, cur_shellConfig); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "load shell.ini failed!"); return rc; } cfg->root_ini->shell_version = shm_strdup(runInfoRet.second.shell_version.c_str()); cfg->root_ini->shell_config = shm_strdup(TerminalCfgRet::ConvertMapMapConfigToStr(cur_shellConfig).c_str()); //save file inifile_write_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_SHELL_INI_VERSION, runInfoRet.second.shell_version.c_str()); TerminalCfgRet::saveMapMapToFile(strShellCfgPath.GetData(), runInfoRet.second.shell_config); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read shell_config from htpp server"); } else if (tmp_shellConfig.size() > 0) { cfg->root_ini->shell_version = shm_strdup(old_shellVer.c_str()); cfg->root_ini->shell_config = shm_strdup(old_shellConfig.c_str()); rc = init_shell_byHttp(dir, cfg->shell_ini, cfg->root_ini, cfg->args, shellvar_path, tmp_shellConfig); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read shell_config from shellvar.ini"); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "load shell.ini failed!"); return rc; } } else DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read shell_config err, no config exist"); t_begin = clock();//微服务访问计时 auto uploadVerRet = UploadTerminalVersionFromUrl(CenterConfigTotal, terminalNoInRoot, cfg->root_ini->center_version != NULL ? cfg->root_ini->center_version : "", cfg->root_ini->root_version != NULL ? cfg->root_ini->root_version : "", cfg->root_ini->shell_version != NULL ? cfg->root_ini->shell_version : ""); if (!uploadVerRet) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("UploadTerminalVersionFromUrl err, env:%s, url:%s", cfg->shell_ini->env, cfg->shell_ini->CenterConfigTotal); break; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("UploadTerminalVersionFromUrl success, cost:%d", (clock() - t_begin) * 1000 / CLOCKS_PER_SEC); } while (false); if (!checkRootIniParam(cfg->root_ini)) return ErrorCodeEnum::Error_NotExist; if (0 != (rc = load_mod_mgr(sp_get_env()->mod_mgr, sp_get_env()->cfg))) return rc; return Error_Succeed; } int sp_TryUpdateCenterCfg(int* isUpdate, int* isReset, char* version) { sp_env_t* env = sp_get_env(); std::string terminalNoInRoot = env->cfg->root_ini->terminal_no == NULL ? "" : env->cfg->root_ini->terminal_no; std::string old_centerVer, old_centerConfig, old_rootVer, old_rootConfig, old_shellConfig, old_shellVer; CSimpleStringA strShellVarIni = CSimpleStringA::Format("%s", (const char*)env->dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("shellVar.ini"); CSimpleStringA strRootCfgPath = CSimpleStringA::Format("%s", (const char*)env->dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("rootCfg"); CSimpleStringA strCenterCfgPath = CSimpleStringA::Format("%s", (const char*)env->dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("CenterCfg"); CSimpleStringA strShellCfgPath = CSimpleStringA::Format("%s", (const char*)env->dir->root_runinfo_path) .Append(SPLIT_SLASH_STR).Append("runcfg").Append(SPLIT_SLASH_STR).Append("ShellCfg"); old_rootVer = env->cfg->root_ini->root_version == NULL ? "" : env->cfg->root_ini->root_version; old_centerVer = env->cfg->root_ini->center_version == NULL ? "" : env->cfg->root_ini->center_version; old_rootConfig = env->cfg->root_ini->root_config == NULL ? "" : env->cfg->root_ini->root_config; old_centerConfig = env->cfg->root_ini->center_config == NULL ? "" : env->cfg->root_ini->center_config; old_shellConfig = env->cfg->root_ini->shell_config == NULL ? "" : env->cfg->root_ini->shell_config; old_shellVer = env->cfg->root_ini->shell_version == NULL ? "" : env->cfg->root_ini->shell_version; CSimpleStringA CenterConfigTotal = env->cfg->shell_ini->CenterConfigTotal; if (CenterConfigTotal.GetLength() == 0) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read rootCfg from root.ini"); return Error_Break; } //从微服务获取集中配置和root配置 std::map> tmp_centerConfig, tmp_rootConfig, tmp_shellConfig; ConvertStrToDeviceConfigMap(old_centerConfig, tmp_centerConfig); ConvertStrToDeviceConfigMap(old_rootConfig, tmp_rootConfig); ConvertStrToDeviceConfigMap(old_shellConfig, tmp_shellConfig); auto runInfoRet = GetTerminalCfgFromUrl(CenterConfigTotal, terminalNoInRoot, old_centerVer, old_rootVer, old_shellVer, tmp_centerConfig, tmp_rootConfig, tmp_shellConfig); if (!runInfoRet.first) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("GetTerminalCfgFromUrl err, env:%s, url:%s", env->cfg->shell_ini->env, env->cfg->shell_ini->CenterConfigTotal); return Error_NetBroken; } //是否update和是否reset if (runInfoRet.second.center_update) { if (env->cfg->root_ini->center_version != NULL) shm_free(env->cfg->root_ini->center_version); if (env->cfg->root_ini->center_config != NULL) shm_free(env->cfg->root_ini->center_config); //save file inifile_write_str(strShellVarIni.GetData(), CONFIG_HEAD, TOTALCONFIG_CENTER_VERSION, runInfoRet.second.center_version.c_str()); TerminalCfgRet::saveMapMapToFile(strCenterCfgPath.GetData(), runInfoRet.second.center_config); env->cfg->root_ini->center_version = shm_strdup(runInfoRet.second.center_version.c_str()); env->cfg->root_ini->center_config = shm_strdup(TerminalCfgRet::ConvertMapMapConfigToStr(runInfoRet.second.center_config).c_str()); *isUpdate = true; } *isReset = runInfoRet.second.center_reset; if (version != NULL) strcpy(version, runInfoRet.second.center_version.c_str()); std::string cur_rootVer = env->cfg->root_ini->root_version == NULL ? "" : env->cfg->root_ini->root_version; std::string cur_centerVer = env->cfg->root_ini->center_version == NULL ? "" : env->cfg->root_ini->center_version; std::string cur_shellVer = env->cfg->root_ini->shell_version == NULL ? "" : env->cfg->root_ini->shell_version; if (cur_centerVer.length() > 0 && cur_centerVer != old_centerVer) UploadTerminalVersionFromUrl(CenterConfigTotal, terminalNoInRoot, cur_centerVer, cur_rootVer, cur_shellVer); return ErrorCodeEnum::Error_Succeed; } static int read_path(sp_dir_t* dir, const char* file, sp_cfg_root_ini_t* root, int shm) { int rc = 0; root->arr_path = T_ARRAY_MAKE(32, sizeof(sp_cfg_path_t*), shm); if (root->ref_sysroot_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "Run", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_sysroot_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("SysRoot"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_addata_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "adData", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_addata_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("ADData"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_syslog_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "SysLog", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_syslog_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("SysLog"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_intlog_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "InterLog", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_intlog_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("InterLog"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_uploadvideo_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "UploadVideo", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_uploadvideo_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("UploadVideo"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_uploadphoto_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "UploadPhoto", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_uploadphoto_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("UploadPhoto"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_localvideo_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "Video", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_localvideo_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("LocalVideo"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_downloads_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "Downloads", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_downloads_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("Downloads"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_upgraded_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "Upgraded", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_upgraded_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("Upgraded"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_tmp_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "Temp", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_tmp_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("Temp"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } if (root->ref_centersetting_path == NULL) { CSimpleString tmp = CSimpleString::Format("%s" SPLIT_SLASH_STR "CenterSetting", dir->rvc_path); char* shm_path = shm_strdup(tmp); root->ref_centersetting_path = shm_path; sp_cfg_path_t* path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = shm_strdup("CenterSetting"); path->path = shm_path; SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; if (!ExistsDirA(shm_path)) CreateDirRecursiveA(shm_path); } return rc; } static sp_cfg_pack_info_t *read_pack_info(const char *file, const char *pack, int shm) { sp_cfg_pack_info_t *pack_info = T_MALLOC_T(sp_cfg_pack_info_t, shm); memset(pack_info, 0, sizeof(sp_cfg_pack_info_t)); pack_info->name = T_STRDUP(pack, shm); pack_info->install_time = inifile_read_int(file, pack, "InstalledDate", 0); pack_info->state = read_ini_install_state(file, pack, "PackState"); return pack_info; } static array_header_t *parse_packs(const char *file, const char *str, int shm) { array_header_t *arr = T_ARRAY_MAKE(-1, sizeof(sp_cfg_pack_info_t*), shm); char *packs = _strdup(str); if (packs) { char *token; const char *seps = " \t,"; token = strtok(packs, seps); while (token != NULL) { sp_cfg_pack_info_t *pack_info = read_pack_info(file, token, shm); if (pack_info) { if (shm) { SHM_ARRAY_PUSH(arr, sp_cfg_pack_info_t*) = pack_info; } else { ARRAY_PUSH(arr, sp_cfg_pack_info_t*) = pack_info; } } token = strtok(NULL, seps); } free(packs); } return arr; } static int load_root_ini(sp_dir_t *dir, sp_cfg_root_ini_t *root, const char *file, int shm) { int rc; rc = read_path(dir, file, root, shm); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read [Path] section failed!"); } if (!ExistsFileA(file)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("[root.ini] file not exists!"); //启动一个http server,用于接收终端号 return Error_NotExist; } rc = read_terminal(file, root, shm); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read [Terminal] section failed!"); return rc; } return rc; } static int unload_root_ini(sp_cfg_root_ini_t *root, int shm) { int i; if (shm) { shm_free(root->terminal_no); shm_free(root->machine_type); for (i = 0; i < root->arr_path->nelts; ++i) { sp_cfg_path_t *path = ARRAY_IDX(root->arr_path, i, sp_cfg_path_t*); shm_free(path->name); shm_free(path->path); shm_free(path); } shm_array_free(root->arr_path); } else { free(root->terminal_no); free(root->machine_type); for (i = 0; i < root->arr_path->nelts; ++i) { sp_cfg_path_t *path = ARRAY_IDX(root->arr_path, i, sp_cfg_path_t*); free(path->name); free(path->path); free(path); } array_free(root->arr_path); } memset(root, 0, sizeof(sp_cfg_root_ini_t)); return 0; } #if defined(_MSC_VER) void load_specialRunInfoInCentersetting(const char* fileName) { array_header_t* arr_section = inifile_read_section_all(fileName); g_specialRunInfoArr.clear(); if (!arr_section) return; for (int i = 0; i < arr_section->nelts; ++i) { char* sec = ARRAY_IDX(arr_section, i, char*); array_header_t* arr_key = inifile_read_section_key_all(fileName, sec); if (!arr_key) continue; for (int j = 0; j < arr_key->nelts; ++j) { char* key = ARRAY_IDX(arr_key, j, char*); if (_stricmp(key, "specialRunInfo") == 0) { std::string secName = sec; std::transform(secName.begin(), secName.end(), secName.begin(), ::tolower); std::string tmpStr = inifile_read_str(fileName, sec, "specialRunInfo", ""); if (tmpStr.length() > 0) g_specialRunInfoArr[secName] = tmpStr; } } } } #endif //_MSC_VER static inline int shell_ini__load_debug_level(const char* shell_ini_path, const char* entity_name) { int level = inifile_read_int(shell_ini_path, "Debug", entity_name, 0); /*to see: DebugLevelEnum*/ if (level > 2 || level < 0) level = 0; return level; } /*add intrinsic spshell module*/ static inline void init_shell_module(sp_cfg_shell_ini_t* shell, const CVersionInfo* shell_ver, int mem_trace, int debug_level) { sp_cfg_shell_entity_t* ent = NULL; sp_cfg_shell_module_t* mod = NULL; mod = (sp_cfg_shell_module_t*)shm_malloc(sizeof(sp_cfg_shell_module_t)); TOOLKIT_ASSERT(mod != NULL); memset(mod, 0, sizeof(sp_cfg_shell_module_t)); sp_version_copy(&mod->version, &shell->software_version); mod->author = shm_strdup(shell_ver->strAuthorName); mod->company = shm_strdup(shell_ver->strCompanyName); mod->name = shm_strdup(SPSHELL_NAME); mod->mem_trace = mem_trace; mod->idx = shell->arr_module->nelts; //the first mod id is spshell /*increment netls at the same time*/ SHM_ARRAY_PUSH(shell->arr_module, sp_cfg_shell_module_t*) = mod; ent = (sp_cfg_shell_entity_t*)shm_malloc(sizeof(sp_cfg_shell_entity_t)); memset(ent, 0, sizeof(sp_cfg_shell_entity_t)); ent->mod = mod; ent->name = shm_strdup(SPSHELL_NAME); ent->idx = shell->arr_entity->nelts; ent->privilege = 1; sp_version_init(&ent->version); ent->debug_level = debug_level; ent->m_startTimes++; #if defined(RVC_OS_WIN) ZeroMemory(&ent->m_EntityStartTime, sizeof(LARGE_TIME)); ZeroMemory(&ent->m_EntityStartEndTime, sizeof(LARGE_TIME)); ZeroMemory(&ent->m_EntityInitEndTime, sizeof(LARGE_TIME)); SYSTEMTIME t_cur; GetLocalTime(&t_cur); SystemTimeToFileTime(&t_cur, &ent->m_EntityStartTime.filetimePart);//spshell, idx 0, 初始化启动时间 sp_cfg_setShellFirstStartTime(ent->m_EntityStartTime); ent->m_EntityInitEndTime.longPart = sp_cfg_getShellFirstStartTime().longPart + clock() * 10000; //FILETIME精度为100纳秒 #else ZeroMemory(&ent->m_EntityStartTime, sizeof(SYSTEMTIME)); ZeroMemory(&ent->m_EntityStartEndTime, sizeof(SYSTEMTIME)); ZeroMemory(&ent->m_EntityInitEndTime, sizeof(SYSTEMTIME)); GetLocalTime(&ent->m_EntityStartTime); //spshell, idx 0, 初始化启动时间 const ULONGLONG curTickCount = GetTickCount64(); memcpy(&ent->m_EntityInitEndTime, &curTickCount, sizeof(ULONGLONG)); #endif //RVC_OS_WIN SHM_ARRAY_PUSH(shell->arr_entity, sp_cfg_shell_entity_t*) = ent; } static inline void shell_ini__get_mod_version(sp_cfg_shell_module_t* mod, const char* mod_path) { #ifdef _WIN32 CCodeSignVerify ver; CVersionInfo verInfo; if (!ver.GetVersionInfo(mod_path, verInfo)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read file %s version info fail, %s", mod_path, (const char*)ver.GetErrorMsg()); mod->author = shm_strdup(verInfo.strAuthorName); mod->company = shm_strdup(verInfo.strCompanyName); mod->version.major = verInfo.FileVersion.GetMajor(); mod->version.minor = verInfo.FileVersion.GetMajor(); mod->version.revision = verInfo.FileVersion.GetRevision(); mod->version.build = verInfo.FileVersion.GetBuild(); #endif } static inline int shell_ini__veritify_core_file_legality(sp_dir_t* dir, sp_cfg_shell_ini_t* shell) { #ifdef _WIN32 // SpBase.dll、SpShell.exe、SpHost.exe代码签名校验 char sal_tmp[MAX_PATH] = { 0 }; const char* sal_files[] = { "SpBase.dll", "SpHost.exe", "SpShell.exe" }; int i; CCodeSignVerify ver; for (i = 0; i < sizeof(sal_files) / sizeof(sal_files[0]); i++) { sprintf(sal_tmp, "%s" SPLIT_SLASH_STR "%s", dir->bin_path, sal_files[i]); CSignInfo signInfo; if (!ver.VerifySignature(sal_tmp, signInfo)) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("file %s sign verify fail, %s", sal_files[i], (const char*)ver.GetErrorMsg()); return Error_FailVerify; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("file %s sign verify pass, signer: %s, sign time: %s, cert hash: %s", sal_files[i], (const char*)signInfo.strSignCertSubject, (const char*)signInfo.dtSignTime.ToTimeString(), (const char*)signInfo.strSignCertHash); if (shell->spbase_sign_cert_hash == NULL) { shell->spbase_sign_cert_hash = shm_strdup(signInfo.strSignCertHash); } else if (stricmp(shell->spbase_sign_cert_hash, signInfo.strSignCertHash) != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("sign cert hash not equal, last : [%s], current: [%s]", shell->spbase_sign_cert_hash, (const char*)signInfo.strSignCertHash); return Error_FailVerify; } } #endif return 0; } static inline int shell_ini__vertify_mod_legality(sp_cfg_shell_ini_t* shell, const char* lib_file_path, const char* mod_name) { int rc = 0; #ifdef _WIN32 CCodeSignVerify ver; CSignInfo signInfo; if (!ver.VerifySignature(lib_file_path, signInfo)) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("file %s sign verify fail, %s", mod_name, (const char*)ver.GetErrorMsg()); rc = Error_FailVerify; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("file %s sign verify pass, signer: %s, sign time: %s, cert hash: %s", mod_name, (const char*)signInfo.strSignCertSubject, (const char*)signInfo.dtSignTime.ToTimeString(), (const char*)signInfo.strSignCertHash); if (stricmp(shell->spbase_sign_cert_hash, signInfo.strSignCertHash) != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("entity %s sign cert hash [%s] not equal to spbase sign cert hash [%s]", mod_name, (const char*)signInfo.strSignCertHash, shell->spbase_sign_cert_hash); rc = Error_FailVerify; } #endif return rc; } static int shell_ini__load_entities_list(sp_dir_t* dir, sp_cfg_shell_ini_t* shell, sp_cfg_root_ini_t* root, bool vertify_or_not, std::map &entityArr, std::map &memTraceArr, std::map &debugLevelArr, std::vector &exist_entity) { int rc = 0; do { for (auto cur_it = entityArr.begin(); cur_it != entityArr.end(); cur_it++) { char tmp[MAX_PATH]; int ret; if (exist_entity.end() != std::find(exist_entity.begin(), exist_entity.end(), cur_it->first)) continue; sp_cfg_shell_entity_t* entity = (sp_cfg_shell_entity_t*)shm_malloc(sizeof(sp_cfg_shell_entity_t)); memset(entity, 0, sizeof(sp_cfg_shell_entity_t)); entity->name = shm_strdup(cur_it->first.c_str()); if (!verify_entity_name(entity->name)) { rc = Error_Unexpect; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("verify entity %s name failed!", entity->name); break; } ZeroMemory(&entity->m_EntityStartTime, sizeof(SYSTEMTIME)); ZeroMemory(&entity->m_EntityInitEndTime, sizeof(SYSTEMTIME)); ZeroMemory(&entity->m_EntityStartEndTime, sizeof(SYSTEMTIME));//初始化实体启动时间 #if defined(_MSC_VER) entity->m_EntityStartTime.longPart = entity->m_EntityInitEndTime.longPart = entity->m_EntityStartEndTime.longPart = sp_cfg_getShellFirstStartTime().longPart; #endif //_MSC_VER entity->debug_level = debugLevelArr.find(entity->name) == debugLevelArr.end() ? 0 : debugLevelArr[cur_it->first]; entity->log_record_level = getEntityLogLevel(entity->name); entity->runType = 1;//1,Debug;2,Release //judge if run in release or debug std::string tmpEntityName = entity->name, entityInfo = ""; std::transform(tmpEntityName.begin(), tmpEntityName.end(), tmpEntityName.begin(), ::tolower); #if defined(_MSC_VER) if (g_specialRunInfoArr.find(tmpEntityName) != g_specialRunInfoArr.end()) entityInfo = g_specialRunInfoArr[tmpEntityName]; else entityInfo = cur_it->second; #else entityInfo = cur_it->second; #endif int pos1 = entityInfo.find("Debug"), pos2 = entityInfo.find("Release"); if (pos1 > 0 || pos2 > 0) { char runInfo[MAX_PATH] = ""; ret = sscanf(entityInfo.c_str(), "%d,%[^,],%x, %s", &entity->privilege, tmp, &entity->devel_id, runInfo); if (CSimpleStringA(runInfo).Compare("Release") == 0) entity->runType = 2; ret = 3; } else ret = sscanf(entityInfo.c_str(), "%d,%[^,],%x", &entity->privilege, tmp, &entity->devel_id); if (ret == 3) { sp_cfg_shell_module_t* mod; if (str_has_suffix(tmp, MOD_LIB_SUFFIX)) { const int len = strlen(tmp); tmp[len - strlen(MOD_LIB_SUFFIX)] = 0; } mod = find_module(shell, tmp); if (!mod) { char mod_lib_path[MAX_PATH]; const int len = (strstr(tmp, "lib") == tmp) ? 3 : 0; mod = (sp_cfg_shell_module_t*)shm_malloc(sizeof(sp_cfg_shell_module_t)); memset(mod, 0, sizeof(sp_cfg_shell_module_t)); mod->name = shm_strdup(tmp + len); CSimpleString dstMod; #if defined(_MSC_VER) dstMod = CSimpleString::Format("%s.dll", tmp); #else dstMod = CSimpleString::Format("lib%s.so", tmp); #endif //_MSC_VER sprintf(mod_lib_path, "%s" SPLIT_SLASH_STR "%s", dir->mod_path, dstMod.GetData()); mod->debugFileExist = EntityResource::getSaveFile(); if (vertify_or_not) { rc = shell_ini__vertify_mod_legality(shell, mod_lib_path, mod->name); } if (rc == 0) { shell_ini__get_mod_version(mod, mod_lib_path); #if defined(_MSC_VER) mod->runType = entity->runType; #endif //_MSC_VER mod->mem_trace = memTraceArr.find(entity->name) == memTraceArr.end() ? 0 : memTraceArr[cur_it->first]; mod->idx = shell->arr_module->nelts; //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("mod idx, %s : %d", entity->name, mod->idx); SHM_ARRAY_PUSH(shell->arr_module, sp_cfg_shell_module_t*) = mod; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("sal verify file %s failed!", mod_lib_path); destroy_module(mod); destroy_entity(entity); break; } } entity->mod = mod; entity->idx = shell->arr_entity->nelts; //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("entity idx, %s : %d", entity->name, entity->idx); SHM_ARRAY_PUSH(shell->arr_entity, sp_cfg_shell_entity_t*) = entity; //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("entity: %s, id: %d", entity->name, entity->idx); } else { std::string entityInfo = cur_it->second; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read entity line failed! bad format!, EntityName:%s, info:%s", entity->name, entityInfo.c_str()); rc = Error_Param; destroy_entity(entity); break; } } if (rc != 0) break; } while (false); return rc; } static int shell_ini__init_sysevent(sp_cfg_shell_ini_t* shell) { int rc = 0; if (NULL == shell->arr_sysevent) { shell->arr_sysevent = shm_array_make(0, sizeof(sp_cfg_shell_sysevent_t*)); rc = 1; } else if (shell->arr_sysevent->nelts == 0) { rc = 1; } if (rc == 1) { //单独添加一个框架级别的系统变量 sp_cfg_shell_sysevent_t* sysevent = T_MALLOC_T(sp_cfg_shell_sysevent_t, 1); memset(sysevent, 0, sizeof(sp_cfg_shell_sysevent_t)); sysevent->name = T_STRDUP(VAR_RSERVERD_KEY_TERM_STATE, 1); sysevent->init_value[0] = '0', sysevent->init_value[1] = '\0'; sysevent->arr_owner_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*)); sp_cfg_shell_entity_t* owner_entity = find_entity(shell, SPSHELL_NAME); if (owner_entity) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("add framework level sys val: %s", VAR_RSERVERD_KEY_TERM_STATE); SHM_ARRAY_PUSH(sysevent->arr_owner_entity, sp_cfg_shell_entity_t*) = owner_entity; sysevent->idx = shell->arr_sysevent->nelts; SHM_ARRAY_PUSH(shell->arr_sysevent, sp_cfg_shell_sysevent_t*) = sysevent; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("cannot find specified entity for sys val: %s", VAR_RSERVERD_KEY_TERM_STATE); destroy_sysevent(sysevent); } } return rc; } static int shell_ini__load_sysevent(sp_cfg_shell_ini_t* shell, const char* shell_var_path, std::map &sysEventArr) { int rc = 0; shell_ini__init_sysevent(shell); for (auto it = sysEventArr.begin(); it != sysEventArr.end(); it++) { char tmp[1024], tmp2[1024]; char initVar[SP_CFG_MAX_SYSEVT_BUF]; sp_cfg_shell_sysevent_t* sysevent = (sp_cfg_shell_sysevent_t*)shm_malloc(sizeof(sp_cfg_shell_sysevent_t)); memset(sysevent, 0, sizeof(sp_cfg_shell_sysevent_t)); sysevent->name = shm_strdup(it->first.c_str()); sysevent->arr_owner_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*)); int ret = sscanf(it->second.c_str(), "%[^,], \"%[^\"]", tmp, sysevent->init_value); auto varRet = inifile_format_read(shell_var_path, "SysEvent", sysevent->name, "%[^,], \"%[^\"]", tmp2, initVar); if (varRet == 2) { /** 缺陷修复,以shell.ini的实体内容为准 Gifur@2023426]*/ /**TODO(Gifur): BUG: 如果在已有的系统变量上添加已有的实体,会因运行时存在文件而导致添加失败 [5/23/2020 Gifur] */ //memcpy(tmp, tmp2, sizeof(tmp)); memcpy(sysevent->init_value, initVar, sizeof(sysevent->init_value)); //如果在shellvar.ini中也能找到该数据,则替换该数值 //情况1:shell.ini添加一个长期有效变量,则在write时在shellvar.ini中生成一个相应的副本。下次读取时从shellvar.ini中读取 //情况2:shell.ini中删除一个长期有效变量,shellvar.ini中并不会相应删除.优先从shell.ini中读取相应变量 } // 为安全起见,准入实体状态强制设为初始状态I if (stricmp(sysevent->name, "EntryPermit") == 0) strcpy(sysevent->init_value, "I"); if (ret > 0) { const char* seps = ";\t "; char* tok = strtok(tmp, seps); while (tok) { sp_cfg_shell_entity_t* owner_entity = find_entity(shell, tok); if (owner_entity) { SHM_ARRAY_PUSH(sysevent->arr_owner_entity, sp_cfg_shell_entity_t*) = owner_entity; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("cannot find entity %s", tok); rc = Error_NotExist; destroy_sysevent(sysevent); break; } tok = strtok(NULL, seps); } if (rc != 0) break; sysevent->idx = shell->arr_sysevent->nelts; SHM_ARRAY_PUSH(shell->arr_sysevent, sp_cfg_shell_sysevent_t*) = sysevent; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read SysEvent failed! bad format!"); rc = Error_Param; destroy_sysevent(sysevent); break; } } return rc; } static int load_entity_list_byHttp(sp_cfg_shell_ini_t* shell, array_header_t** arr, int test_mode, std::map &startupArr) { int rc = Error_Succeed; char section_name[128] = {SHELL_STARTUP_HEAD}; if (test_mode) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("test mode: override startup list"); strcpy(section_name, "Test"); } TOOLKIT_ASSERT(arr); TOOLKIT_ASSERT(*arr == NULL); *arr = shm_array_make(startupArr.size(), sizeof(char*)); TOOLKIT_ASSERT(*arr); for (auto it = startupArr.begin(); it != startupArr.end(); it++) { std::string startupEntity = it->second; sp_cfg_shell_entity_t* ent = find_entity(shell, startupEntity.c_str()); char* s = _strdup(startupEntity.c_str()); char* cmdline = strchr(s, ' '); if (s) { if (strlen(s)) { int numargs, numchars; char** argv = NULL; char* p; sp_cfg_shell_entity_t* ent; char* cmdline = strchr(s, ' '); if (cmdline) { *cmdline = 0; cmdline++; str_parse_cmdline(cmdline, NULL, NULL, &numargs, &numchars); p = (char*)shm_malloc(numargs * sizeof(char*) + numchars); argv = (char**)p; str_parse_cmdline(cmdline, (char**)p, p + numargs * sizeof(char*), &numargs, &numchars); } ent = find_entity(shell, s); if (ent) { if (cmdline) { //TODO: detect only use entity::cmdline, never seem use of argc and argv [Gifur@2020426] ent->argc = numargs; ent->argv = argv; if (numargs) { ent->cmdline = shm_strdup(cmdline); } } SHM_ARRAY_PUSH(*arr, sp_cfg_shell_entity_t*) = ent; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Startup failed! find startup list [%s] defined entity [%s] fail!", it->first.c_str(), s); rc = Error_Param; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Startup failed! startup list [%s] define invalid!", it->first.c_str()); rc = Error_Param; } FREE(s); } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Startup failed! startup list [%s] define invalid!", it->first.c_str()); rc = Error_Param; } FREE(s); if (rc != 0) break; } return rc; } static int shell_ini__load_entity_list(sp_cfg_shell_ini_t* shell, array_header_t** arr, const char* shell_ini_path, int test_mode) { int i; int rc = 0; char section_name[128] = { "Startup" }; if (test_mode) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("test mode: override startup list"); strcpy(section_name, "Test"); } TOOLKIT_ASSERT(arr); TOOLKIT_ASSERT(*arr == NULL); i = inifile_read_int(shell_ini_path, section_name, "Number", 0); if (i >= 0) { int n = i; *arr = shm_array_make(i, sizeof(char*)); TOOLKIT_ASSERT(*arr); for (i = 1; i <= n; ++i) { char key[512]; char* s; _itoa(i, key, 10); s = inifile_read_str(shell_ini_path, section_name, key, ""); if (s) { if (strlen(s)) { int numargs, numchars; char** argv = NULL; char* p; sp_cfg_shell_entity_t* ent; char* cmdline = strchr(s, ' '); if (cmdline) { *cmdline = 0; cmdline++; str_parse_cmdline(cmdline, NULL, NULL, &numargs, &numchars); p = (char*)shm_malloc(numargs * sizeof(char*) + numchars); argv = (char**)p; str_parse_cmdline(cmdline, (char**)p, p + numargs * sizeof(char*), &numargs, &numchars); } ent = find_entity(shell, s); if (ent) { if (cmdline) { //TODO: detect only use entity::cmdline, never seem use of argc and argv [Gifur@2020426] ent->argc = numargs; ent->argv = argv; if (numargs) { ent->cmdline = shm_strdup(cmdline); } } SHM_ARRAY_PUSH(*arr, sp_cfg_shell_entity_t*) = ent; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Startup failed! find startup list [%s] defined entity [%s] fail!", key, s); rc = Error_Param; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Startup failed! startup list [%s] define invalid!", key); rc = Error_Param; } FREE(s); } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Startup failed! startup list [%s] define invalid!", key); rc = Error_Param; } if (rc != 0) break; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read %s failed! startup number invalid!", section_name); rc = Error_Param; } return rc; } static inline int shell_ini__load_software_version(sp_cfg_shell_ini_t* shell, const char* shell_ini_path, const char* shell_runinfo_file) { int rc = 0; shell->software_version.build = 0; if (NULL != shell_runinfo_file) rc = read_ini_version(shell_runinfo_file, "Main", "SoftwareVersion", &shell->software_version.major, &shell->software_version.minor, &shell->software_version.revision, NULL); if (rc != 0) rc = read_ini_version(shell_ini_path, "Main", "SoftwareVersion", &shell->software_version.major, &shell->software_version.minor, &shell->software_version.revision, NULL); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read Main::SoftwareVersion failed!"); } return rc; } void init_shellVer(sp_dir_t* dir, CVersionInfo &shellVerInfo) { #ifdef _WIN32 CCodeSignVerify signVerify; char spshell_path[MAX_PATH] = { 0 }; sprintf(spshell_path, "%s" SPLIT_SLASH_STR "%s", dir->bin_path, "SpShell.exe"); if (!signVerify.GetVersionInfo(spshell_path, shellVerInfo)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read file %s version info fail, %s", spshell_path, (const char*)signVerify.GetErrorMsg()); } #endif //_WIN32 } template std::map clearUnExistConfig(std::map& src) { std::map dst; for (auto it = src.begin(); it != src.end(); it++) { if (it->first[0] == ';') continue; else dst.insert(std::make_pair(it->first, it->second)); } return dst; } int init_defaultShellCfg(sp_dir_t* dir, sp_cfg_t* cfg) { char shellvar_path[MAX_PATH] = ""; auto rc = sp_dir_get_path(dir, SP_DIR_SHELLVAR_INI, NULL, shellvar_path, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get shellvar.ini path failed!"); return rc; } std::map> default_shellConfig; std::map mainSection; mainSection.insert(std::make_pair("SoftwareVersion", "1.1.0")); default_shellConfig.insert(std::make_pair("Main", mainSection)); std::map entitySection; entitySection.insert(std::make_pair("VtmLoader", "1,mod_VtmLoader,0x10F")); entitySection.insert(std::make_pair("Chromium", "1,mod_chromium,0x402")); entitySection.insert(std::make_pair("GUIConsole", "1,mod_GUIConsole,0x508")); default_shellConfig.insert(std::make_pair("Entity", entitySection)); std::map startupSection; long long index = 1; //should not change those orders startupSection.insert(std::make_pair(std::to_string(index++), "GUIConsole")); startupSection.insert(std::make_pair(std::to_string(index++), "Chromium")); startupSection.insert(std::make_pair(std::to_string(index++), "VtmLoader")); default_shellConfig.insert(std::make_pair("Startup", startupSection)); return init_shell_byHttp(dir, cfg->shell_ini, cfg->root_ini, cfg->args, shellvar_path, default_shellConfig); } ErrorCodeEnum init_shell_byHttp(sp_dir_t* dir, sp_cfg_shell_ini_t* shell, sp_cfg_root_ini_t* root, const sp_cfg_start_args_t* args, const char* shellVarIni, std::map> shellConfig) { int rc = -1; if(shellConfig.find(SHELL_MAIN_HEAD) != shellConfig.end() && shellConfig[SHELL_MAIN_HEAD].find(SHELL_MAIN_SOFTWAREVERSION) != shellConfig[SHELL_MAIN_HEAD].end()) sscanf(shellConfig[SHELL_MAIN_HEAD][SHELL_MAIN_SOFTWAREVERSION].c_str(), "%d.%d.%d", &shell->software_version.major, &shell->software_version.minor, &shell->software_version.revision); else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find %s::%s", SHELL_MAIN_HEAD, SHELL_MAIN_SOFTWAREVERSION); return Error_NotConfig; } if (shellConfig.find(SHELL_ENTITY_HEAD) == shellConfig.end()) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find %s", SHELL_ENTITY_HEAD); return Error_NotConfig; } if (args->sign_verifity && (rc = shell_ini__veritify_core_file_legality(dir, shell)) != 0) return Error_NotConfig; CVersionInfo shellVerInfo; init_shellVer(dir, shellVerInfo); //init spshell module std::vector exist_entity, exist_module; if(NULL == shell->arr_entity) shell->arr_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*)); else { sp_cfg_shell_entity_t* entity; int i; ARRAY_FOR_EACH_ENTRY(entity, i, shell->arr_entity, sp_cfg_shell_entity_t*) { exist_entity.push_back(entity->name); } } if(NULL == shell->arr_module) shell->arr_module = shm_array_make(0, sizeof(sp_cfg_shell_module_t*)); else { sp_cfg_shell_module_t* entity; int i; ARRAY_FOR_EACH_ENTRY(entity, i, shell->arr_module, sp_cfg_shell_module_t*) { exist_module.push_back(entity->name); } } //init entity arr,去除以;开头的实体 std::map entityArr = clearUnExistConfig(shellConfig[SHELL_ENTITY_HEAD]); #ifdef _WIN32 CSimpleStringA sectionNameWithType = CSimpleStringA::Format("%s_%s", SHELL_ENTITY_HEAD, root->machine_type); #else CSimpleStringA sectionNameWithType = CSimpleStringA::Format("%s_%s", "UOSEntity", root->machine_type); #endif if (shellConfig.find(sectionNameWithType.GetData()) != shellConfig.end()) //有带机型的实体 { std::map entityTypeArr = clearUnExistConfig(shellConfig[sectionNameWithType.GetData()]); for (auto it = entityTypeArr.begin(); it != entityTypeArr.end(); it++) entityArr.insert(std::make_pair(it->first, it->second)); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find section:%s", sectionNameWithType.GetData()); std::map memTraceArr, debugLevelArr; for (auto it = entityArr.begin(); it != entityArr.end(); it++) { int mem_trace = 0, debug_level = 0; if (shellConfig.find(SHELL_MEMTRACE_HEAD) != shellConfig.end() && shellConfig[SHELL_MEMTRACE_HEAD].find(it->first) != shellConfig[SHELL_MEMTRACE_HEAD].end()) mem_trace = std::atoi(shellConfig[SHELL_MEMTRACE_HEAD][it->first].c_str()); else mem_trace = 0; if (shellConfig.find(SHELL_DEBUG_HEAD) != shellConfig.end() && shellConfig[SHELL_DEBUG_HEAD].find(it->first) != shellConfig[SHELL_DEBUG_HEAD].end()) debug_level = std::atoi(shellConfig[SHELL_DEBUG_HEAD][it->first].c_str()); else debug_level = 0; memTraceArr.insert(std::make_pair(it->first, mem_trace)); debugLevelArr.insert(std::make_pair(it->first, debug_level)); } memTraceArr = clearUnExistConfig(memTraceArr); debugLevelArr = clearUnExistConfig(debugLevelArr); int mem_trace = 0, debug_level = 0; if (exist_entity.end() == std::find(exist_entity.begin(), exist_entity.end(), "Spshell")) { if (shellConfig.find(SHELL_MEMTRACE_HEAD) != shellConfig.end() && shellConfig[SHELL_MEMTRACE_HEAD].find(SPSHELL_NAME) != shellConfig[SHELL_MEMTRACE_HEAD].end()) mem_trace = std::atoi(shellConfig[SHELL_MEMTRACE_HEAD][SPSHELL_NAME].c_str()); if (shellConfig.find(SHELL_DEBUG_HEAD) != shellConfig.end() && shellConfig[SHELL_DEBUG_HEAD].find(SPSHELL_NAME) != shellConfig[SHELL_DEBUG_HEAD].end()) debug_level = std::atoi(shellConfig[SHELL_DEBUG_HEAD][SPSHELL_NAME].c_str()); init_shell_module(shell, &shellVerInfo, mem_trace, debug_level); } if((rc = shell_ini__load_entities_list(dir, shell, root, args->sign_verifity, entityArr, memTraceArr, debugLevelArr, exist_entity))) return Error_NotConfig; //load sysEventArr if (shellConfig.find(SHELL_SYSEVENT_HEAD) == shellConfig.end()) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find %s", SHELL_SYSEVENT_HEAD); shell->arr_sysevent = shm_array_make(0, sizeof(sp_cfg_shell_sysevent_t*));//避免错误,也需要建立一个相关sysevnet存储 } else { std::map sysEventArr = shellConfig[SHELL_SYSEVENT_HEAD]; if ((rc = shell_ini__load_sysevent(shell, shellVarIni, sysEventArr)) != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("load sysevent from shellvar.ini fail"); return Error_NotConfig; } } //init entity debug mode if (args->debug_mode && shell->arr_entity) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("override entities' debug level!"); for (int i = 0; i < shell->arr_entity->nelts; ++i) { sp_cfg_shell_entity_t* entity = ARRAY_IDX(shell->arr_entity, i, sp_cfg_shell_entity_t*); entity->debug_level = 2; /*Debug_High*/ } } //init startup entity if (shellConfig.find(SHELL_STARTUP_HEAD) == shellConfig.end()) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find %s", SHELL_STARTUP_HEAD); else if (shell->arr_startlist == NULL) { std::map startupArr = shellConfig[SHELL_STARTUP_HEAD]; if (args->start_entities != NULL) { char* value; char* name; char* context = NULL; array_header_t* t = NULL; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("override start entity list!"); value = _strdup(args->start_entities); if (!value) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("_strdup start_entities failed!"); return Error_NotConfig; } if(NULL ==shell->arr_startlist) shell->arr_startlist = shm_array_make(1, sizeof(char*)); name = strtok_s(value, ";", &context); while (name != NULL) { sp_cfg_shell_entity_t* ent = find_entity(shell, name); if (ent) SHM_ARRAY_PUSH(shell->arr_startlist, sp_cfg_shell_entity_t*) = ent; else { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("cannot find entity name %s defined at cmdline!", name); rc = Error_Param; } name = strtok_s(NULL, ";", &context); } free(value); if (rc != 0) return Error_NotConfig; } else if ((rc = load_entity_list_byHttp(shell, &shell->arr_startlist, 0, startupArr)) != 0) return Error_NotConfig; if (is_own_test_mode(args->test_mode)) { array_header_t* arr = NULL; if ((rc = load_entity_list_byHttp(shell, &arr, 1, startupArr)) != 0) return Error_NotConfig; if (arr && arr->nelts > 0) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("append additional test entity: %d", arr->nelts); shm_array_cat(shell->arr_startlist, arr); } shm_array_free(arr); } } shell->shell_debug_level = args->debug_mode ? 2 : debug_level; shell->log_record_level = getEntityLogLevel(SPSHELL_NAME); if (args->telnet_port == 0) shell->nConsolePort = shellConfig[SHELL_MAIN_HEAD].find(SHELL_MAIN_CONSOLEPORT) != shellConfig[SHELL_MAIN_HEAD].end() ? atoi(shellConfig[SHELL_MAIN_HEAD][SHELL_MAIN_CONSOLEPORT].c_str()) : 0; else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("override telnet console port: %d", args->telnet_port); shell->nConsolePort = args->telnet_port; } //init kill arr if (shellConfig.find(SHELL_KILLPROCESS_HEAD) == shellConfig.end()) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find %s", SHELL_KILLPROCESS_HEAD); else { std::map killArr = shellConfig[SHELL_KILLPROCESS_HEAD]; g_arrKill.clear(); for (auto it = killArr.begin(); it != killArr.end(); it++) g_arrKill.push_back(it->second); } //init start arr if (shellConfig.find(SHELL_RUNSCRIPT_HEAD) == shellConfig.end()) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("shellConfig can not find %s", SHELL_RUNSCRIPT_HEAD); else { std::map startArr = shellConfig[SHELL_RUNSCRIPT_HEAD]; g_arrStart.clear(); for (auto it = startArr.begin(); it != startArr.end(); it++) g_arrStart.push_back(it->second); } return Error_Succeed; } static int shell_ini__load_mod_entity(sp_dir_t* dir, sp_cfg_shell_ini_t* shell, const char* shell_ini_path, sp_cfg_root_ini_t* root, const sp_cfg_start_args_t* args, const CVersionInfo* ver) { shell->arr_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*)); // BugFix: replace char* with sp_cfg_shell_module_t* [Gifur@2020422] shell->arr_module = shm_array_make(0, sizeof(sp_cfg_shell_module_t*)); std::map entityArr, entityInfoArr; std::map memTraceArr, debugLevelArr; //init Entity char sectionName[MAX_PATH] = "Entity"; array_header_t* arr = inifile_read_section_key_all(shell_ini_path, sectionName); CSimpleStringA sectionNameWithType = CSimpleStringA::Format("%s_%s", sectionName, root->machine_type); array_header_t* arr2 = inifile_read_section_key_all(shell_ini_path, sectionNameWithType); for (int i = 0; i < arr->nelts; ++i) entityArr.insert(std::make_pair(ARRAY_IDX(arr, i, char*), sectionName)); for (int i = 0; i < arr2->nelts; ++i) entityArr.insert(std::make_pair(ARRAY_IDX(arr2, i, char*), sectionNameWithType)); if (arr) toolkit_array_free2(arr); if (arr2) toolkit_array_free2(arr2); for (auto it = entityArr.begin(); it != entityArr.end(); it++) entityInfoArr.insert(std::make_pair(it->first, inifile_read_str(shell_ini_path, it->second.c_str(), it->first.c_str(), ""))); //init memTraceArr for (auto it = entityArr.begin(); it != entityArr.end(); it++) memTraceArr.insert(std::make_pair(it->second, inifile_read_int(shell_ini_path, "MemTrace", it->second.c_str(), 0))); //init debugLevel for (auto it = entityArr.begin(); it != entityArr.end(); it++) debugLevelArr.insert(std::make_pair(it->second, shell_ini__load_debug_level(shell_ini_path, it->second.c_str()))); //init shell module memTraceArr.insert(std::make_pair(SPSHELL_NAME, inifile_read_int(shell_ini_path, "MemTrace", SPSHELL_NAME, 0))); debugLevelArr.insert(std::make_pair(SPSHELL_NAME, shell_ini__load_debug_level(shell_ini_path, SPSHELL_NAME))); init_shell_module(shell, ver, memTraceArr[SPSHELL_NAME], debugLevelArr[SPSHELL_NAME]); std::vector null_arr; return shell_ini__load_entities_list(dir, shell, root, args->sign_verifity, entityInfoArr, memTraceArr, debugLevelArr, null_arr); } static int unload_shell_ini(sp_cfg_shell_ini_t *shell) { int i; if (shell->arr_entity) { for (i = 0; i< shell->arr_entity->nelts; ++i) { sp_cfg_shell_entity_t *entity = ARRAY_IDX(shell->arr_entity, i, sp_cfg_shell_entity_t*); destroy_entity(entity); } shm_array_free(shell->arr_entity); } if (shell->arr_module) { for (i = 0; i < shell->arr_module->nelts; ++i) { sp_cfg_shell_module_t *mod = ARRAY_IDX(shell->arr_module, i, sp_cfg_shell_module_t*); destroy_module(mod); } shm_array_free(shell->arr_module); } if (shell->arr_sysevent) { for (i = 0; i < shell->arr_sysevent->nelts; ++i) { sp_cfg_shell_sysevent_t *sysevent = ARRAY_IDX(shell->arr_sysevent, i, sp_cfg_shell_sysevent_t*); destroy_sysevent(sysevent); } shm_array_free(shell->arr_sysevent); } if (shell->arr_startlist) { shm_array_free(shell->arr_startlist); } return 0; } static int load_install_ini(sp_dir_t *dir, sp_cfg_install_ini_t *inst, const char *file, int shm) { int rc = 0; array_header_t *arr_section = NULL; int nLastStartTime =0; sp_version_t active_version = { 0 }; rc = read_ini_version(file, "Main", "InstallVersion", &inst->install_version.major, &inst->install_version.minor, &inst->install_version.revision, &inst->install_version.build); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read ini file failed, %s Main::InstallVersion failed!", file); return rc; } // 校验版本目录名与软件版本是否一致 sscanf(strrchr(dir->base_path, SPLIT_SLASH) + 1, "%d.%d.%d.%d", &active_version.major, &active_version.minor, &active_version.revision, &active_version.build); if (sp_version_cmp(&active_version, &inst->install_version) != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("version dir %d.%d.%d.%d not equals install version %d.%d.%d.%d", active_version.major, active_version.minor, active_version.revision, active_version.build, inst->install_version.major, inst->install_version.minor, inst->install_version.revision, inst->install_version.build); return Error_NotMeetCondition; } inst->install_time = inifile_read_int(file, "Main", "CreateDate", 0); if (inst->install_time == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read ini file failed, %s Main::CreateDate failed", file); return -1; } rc = read_ini_version(file, "Main", "LatterInstallVersion", &inst->latter_install_version.major, &inst->latter_install_version.minor, &inst->latter_install_version.revision, &inst->latter_install_version.build); if (rc != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read ini file failed, %s Main::LatterInstallVersion failed!", file); return rc; } rc = read_ini_str(file, "Main", "LightPack", &inst->light_packs, shm); if (rc != 0 || inst->light_packs == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read ini file failed, %s Main::LightPack", file); return rc; } inst->arr_light_pack = parse_packs(file, inst->light_packs, shm); nLastStartTime = inifile_read_int(file, "Main", "CurrentTime", 0); inst->current_startup_time = y2k_time_now(); { char tmp[32]; sprintf(tmp, "0x%08X", inst->current_startup_time); inifile_write_str(file, "Main", "CurrentTime", tmp); } inst->today_run_count = inifile_read_int(file, "Main", "TodayRunCount", 0); if (inst->today_run_count >=0) { if (y2k_time_is_today(nLastStartTime)) inst->today_run_count++; else inst->today_run_count = 1; inifile_write_int(file, "Main", "TodayRunCount", inst->today_run_count); } inst->total_run_count = inifile_read_int(file, "Main", "TotalRunCount", 0); if (inst->total_run_count >=0) { inst->total_run_count++; inifile_write_int(file, "Main", "TotalRunCount", inst->total_run_count); } // read all history version arr_section = inifile_read_section_all(file); if (arr_section) { int i; inst->arr_version = T_ARRAY_MAKE(0, sizeof(sp_cfg_version_info_t*), shm); for (i = 0; i < arr_section->nelts; ++i) { char *sec = ARRAY_IDX(arr_section, i, char*); if (_stricmp(sec, "Main") != 0) { if (isdigit(sec[0]) && ('.' == sec[1] || '.' == sec[2])) // { // skip light pack sp_cfg_version_info_t *ver_info = T_MALLOC_T(sp_cfg_version_info_t, shm); memset(ver_info, 0, sizeof(sp_cfg_version_info_t)); sscanf(sec, "%d.%d.%d.%d", &ver_info->version.major, &ver_info->version.minor, &ver_info->version.revision, &ver_info->version.build); rc = read_ini_version(file, sec, "PreviousInstallVersion", &ver_info->previous_version.major, &ver_info->previous_version.minor, &ver_info->previous_version.revision, &ver_info->previous_version.build); if (rc != 0) break; rc = read_ini_str(file, sec, "InstallPack", &ver_info->install_pack, shm); if (rc != 0) break; // 轻量安装包没有安装历史 //ver_info->arr_pack = parse_packs(file, ver_info->packs, shm); ver_info->switch_time = inifile_read_int(file, sec, "SwitchOverDate", 0); ver_info->install_state = read_ini_install_state(file, sec, "InstallState"); if (ver_info->install_state == -1) break; if (shm) { SHM_ARRAY_PUSH(inst->arr_version, sp_cfg_version_info_t*) = ver_info; } else { ARRAY_PUSH(inst->arr_version, sp_cfg_version_info_t*) = ver_info; } } } } toolkit_array_free2(arr_section); } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read ini file failed, %s, section all failed", file); return -1; } ////////////////////////////// return rc; } static void unload_install_ini(sp_cfg_install_ini_t *inst, int shm) { //... } /**直接从当前运行路径中拆分版本号*/ static int generate_install_memory(sp_dir_t* dir, sp_cfg_install_ini_t* inst) { if (dir == NULL || inst == NULL) return -1; sscanf(strrchr(dir->base_path, SPLIT_SLASH) + 1, "%d.%d.%d.%d", &inst->install_version.major, &inst->install_version.minor, &inst->install_version.revision, &inst->install_version.build); y2k_time_t now = y2k_time_now(); inst->install_time = now; inst->latter_install_version.major = inst->latter_install_version.minor = inst->latter_install_version.revision = inst->latter_install_version.build = 0; inst->light_packs = shm_strdup(""); inst->latter_install_pack = shm_strdup(""); inst->total_run_count = inst->today_run_count = 0; inst->current_startup_time = now; inst->arr_version = T_ARRAY_MAKE(0, sizeof(sp_cfg_version_info_t*), 1); sp_cfg_version_info_t* ver_info = T_MALLOC_T(sp_cfg_version_info_t, 1); memset(ver_info, 0, sizeof(sp_cfg_version_info_t)); ver_info->version.major = inst->install_version.major; ver_info->version.minor = inst->install_version.minor; ver_info->version.revision = inst->install_version.revision; ver_info->version.build = inst->install_version.build; ver_info->previous_version.major = ver_info->previous_version.minor = ver_info->previous_version.build = ver_info->previous_version.revision = 0; ver_info->switch_time = now; ver_info->install_state = Install_Active; ver_info->install_pack = shm_strdup(""); SHM_ARRAY_PUSH(inst->arr_version, sp_cfg_version_info_t*) = ver_info; inst->arr_light_pack = T_ARRAY_MAKE(0, sizeof(sp_cfg_version_info_t*), 1); return 0; } int sp_cfg_create(sp_dir_t* dir, const sp_cfg_start_args_t* args, sp_cfg_t** p_cfg) { sp_cfg_t *cfg; int rc = Error_Unexpect; char tmp[MAX_PATH], shell_var_path[MAX_PATH], env_path[MAX_PATH]; char* shellvarPath = NULL; cfg = (sp_cfg_t *)shm_malloc(sizeof(sp_cfg_t)); memset(cfg, 0, sizeof(sp_cfg_t)); cfg->root_ini = (sp_cfg_root_ini_t *)shm_malloc(sizeof(sp_cfg_root_ini_t)); memset(cfg->root_ini, 0, sizeof(sp_cfg_root_ini_t)); cfg->shell_ini = (sp_cfg_shell_ini_t *)shm_malloc(sizeof(sp_cfg_shell_ini_t)); memset(cfg->shell_ini, 0, sizeof(sp_cfg_shell_ini_t)); cfg->install_ini = (sp_cfg_install_ini_t*)shm_malloc(sizeof(sp_cfg_install_ini_t)); memset(cfg->install_ini, 0, sizeof(sp_cfg_install_ini_t)); cfg->run_info = (sp_cfg_run_info_t*)shm_malloc(sizeof(sp_cfg_run_info_t)); memset(cfg->run_info, 0, sizeof(sp_cfg_run_info_t)); { cfg->args = (sp_cfg_start_args_t*)shm_malloc(sizeof(sp_cfg_start_args_t)); memset(cfg->args, 0, sizeof(sp_cfg_start_args_t)); cfg->args->start_entities = shm_strdup(args->start_entities); cfg->args->test_mode = args->test_mode; #ifndef DEVOPS_ON_PRD //非生产情况下,才支持测试模式 cfg->args->auto_test = args->auto_test; #endif cfg->args->debug_mode = args->debug_mode; cfg->args->guardian_mode = args->guardian_mode; cfg->args->sign_verifity = args->sign_verifity; cfg->args->ipc_type = args->ipc_type; cfg->args->telnet_port = args->telnet_port; cfg->args->root = args->root; cfg->args->program = shm_strdup(args->program); cfg->args->arguments = shm_strdup(args->arguments); } cfg->run_info->startup_time = y2k_time_now(); rc = sp_dir_get_path_new(dir, SP_DIR_ROOT_INI, NULL, tmp, MAX_PATH, detect_env_test_mode(cfg->args->test_mode)); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get root ini path failed!"); return rc; } rc = load_root_ini(dir, cfg->root_ini, tmp, 1); if (rc != 0) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "load root.ini failed!"); cfg->root_ini_path = shm_strdup(tmp); rc = sp_dir_get_path(dir, SP_DIR_SHELL_INI, NULL, tmp, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get shell.ini path failed!"); return rc; } rc = sp_dir_get_path(dir, SP_DIR_SHELLVAR_INI, NULL, shell_var_path, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get shellvar.ini path failed!"); return rc; } rc = sp_dir_get_path(dir, SP_DIR_ENV_INI, NULL, env_path, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get env.ini path failed!"); return rc; } std::fstream shellVarFile; shellVarFile.open(shell_var_path, std::ios::in); if (!shellVarFile) { /*cannot found shellVar.ini, then create one.*/ std::ofstream file(shell_var_path, std::fstream::out); } shellvarPath = shell_var_path; /*override*/ cfg->args->sign_verifity = 0; if (cfg->args->sign_verifity) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("verify code sign required."); } SetTokenCallBack(shell_getHttpToken); SetRestfulTokenCallBack(shell_getHttpToken); if (Error_Succeed != (rc = init_defaultShellCfg(dir, cfg))) return rc; cfg->shell_ini_path = shm_strdup(tmp); cfg->shellvar_ini_path = shm_strdup(shell_var_path); rc = sp_dir_get_path(dir, SP_DIR_INSTALL_INI, NULL, tmp, MAX_PATH); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "get install.ini path failed!");; return rc; } cfg->install_ini_path = shm_strdup(tmp); if (ExistsFileA(tmp)) { rc = load_install_ini(dir, cfg->install_ini, tmp, 1); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "load install.ini failed!"); return rc; } } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("get install info from memory"); rc = generate_install_memory(dir, cfg->install_ini); if (rc != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object failed!, %s", "generate install.ini failed!"); return rc; } } spinlock_init(&cfg->lock); *p_cfg = cfg; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create cfg object ok! %p, lock = %d", cfg, cfg->lock); rc = 0; return rc; } void sp_cfg_destroy(sp_cfg_t *cfg) { unload_root_ini(cfg->root_ini, 1); unload_shell_ini(cfg->shell_ini); unload_install_ini(cfg->install_ini, 1); shm_free(cfg->root_ini); shm_free(cfg->root_ini_path); shm_free(cfg->shell_ini); shm_free(cfg->shell_ini_path); shm_free(cfg->install_ini); shm_free(cfg->args->start_entities); shm_free(cfg->args->program); shm_free(cfg->args->arguments); shm_free(cfg->args); shm_free(cfg); } void sp_cfg_lock(sp_cfg_t *cfg) { spinlock_enter(&cfg->lock, 0); } void sp_cfg_unlock(sp_cfg_t *cfg) { spinlock_leave(&cfg->lock); } sp_cfg_shell_entity_t *sp_cfg_get_entity_by_name(sp_cfg_t *cfg, const char *name) { return find_entity(cfg->shell_ini, name); } sp_cfg_shell_entity_t *sp_cfg_get_entity_by_idx(sp_cfg_t *cfg, int idx) { if (idx >= 0 && idx < cfg->shell_ini->arr_entity->nelts) { return ARRAY_IDX(cfg->shell_ini->arr_entity, idx, sp_cfg_shell_entity_t*); } else { return NULL; } } sp_cfg_shell_entity_t *sp_cfg_get_entity_shell(sp_cfg_t *cfg) { return ARRAY_IDX(cfg->shell_ini->arr_entity, 0, sp_cfg_shell_entity_t*); } sp_cfg_shell_module_t *sp_cfg_get_module_by_name(sp_cfg_t *cfg, const char *name) { return find_module(cfg->shell_ini, name); } sp_cfg_shell_module_t *sp_cfg_get_module_by_idx(sp_cfg_t *cfg, int idx) { if (idx >= 0 && idx < cfg->shell_ini->arr_module->nelts) { return ARRAY_IDX(cfg->shell_ini->arr_module, idx, sp_cfg_shell_module_t*); } else { return NULL; } } sp_cfg_shell_module_t *sp_cfg_get_module_shell(sp_cfg_t *cfg) { return ARRAY_IDX(cfg->shell_ini->arr_module, 0, sp_cfg_shell_module_t*); } sp_cfg_shell_sysevent_t*sp_cfg_get_sysevent(sp_cfg_t *cfg, const char *name) { array_header_t *arr_sysevent = cfg->shell_ini->arr_sysevent; int i; for (i = 0; i < arr_sysevent->nelts; ++i) { sp_cfg_shell_sysevent_t *tmp = ARRAY_IDX(arr_sysevent, i, sp_cfg_shell_sysevent_t *); if (_stricmp(tmp->name, name) == 0) return tmp; } return NULL; } char *sp_cfg_get_path(sp_cfg_t *cfg, const char *path_prefix) { sp_cfg_path_t *path = find_path(cfg, path_prefix); if (path) { return path->path; } return NULL; } int sp_cfg_refresh_debug_level(sp_cfg_t *cfg, sp_cfg_shell_entity_t *cfg_ent) { //TODO: shell.ini cannot be written!! char tmp[32]; _itoa(cfg_ent->debug_level, tmp, 10); return WritePrivateProfileStringA("Debug", cfg_ent->name, tmp, cfg->shell_ini_path) ? 0 : Error_IO; } int sp_cfg_refresh_ent_version(sp_cfg_shell_entity_t* cfg_ent, const char* new_version) { if (new_version == NULL || strlen(new_version) == 0) return Error_Param; if (sp_version_is_valid(&cfg_ent->version) || (!sp_version_is_valid(&cfg_ent->version) && strstr(new_version, "0.0.0") == new_version) ) { return 0; } char* tok = NULL; long major = 0; long minor = 0; long patch = 0; int count = 0; char kernel[32] = {0}; const char* seps = ".-"; strcpy(kernel, new_version); tok = strtok(kernel, seps); while (tok) { switch (count) { case 0: major = strtol(tok, NULL, 0); break; case 1: minor = strtol(tok, NULL, 0); break; case 2: patch = strtol(tok, NULL, 0); break; } tok = strtok(NULL, seps); count++; } sp_version_fulfill(&cfg_ent->version, major, minor, patch, 0); return 0; fail: return Error_Unexpect; } int sp_cfg_util_read_root_ini_version(sp_cfg_root_ini_t *ini, int major, int minor, int revision, int build) { char tmp[MAX_PATH]; sp_env_t *env = sp_get_env(); sp_dir_get_path_version(env->dir, major, minor, revision, build, SP_DIR_ROOT_INI, NULL, tmp, MAX_PATH, detect_env_test_mode(env->cfg->args->test_mode)); return load_root_ini(env->dir, ini, tmp, 0); } int sp_cfg_util_free_root_ini(sp_cfg_root_ini_t *ini) { unload_root_ini(ini, 0); return 0; } int sp_cfg_get_devel_id(sp_cfg_t *cfg, int idx) { sp_env_t *env = sp_get_env(); sp_cfg_shell_entity_t *cfg_ent = sp_cfg_get_entity_by_idx(env->cfg, idx); return cfg_ent->devel_id; } sp_cfg_version_info_t* sp_cfg_find_previous_version_info(sp_cfg_t *cfg, const sp_version_t *version) { sp_cfg_version_info_t* ver_info = sp_cfg_find_version_info(cfg, version); if (ver_info) { sp_version_t *previous_version = &ver_info->previous_version; return sp_cfg_find_version_info(cfg, previous_version); } return NULL; } sp_cfg_version_info_t* sp_cfg_find_version_info(sp_cfg_t *cfg, const sp_version_t *version) { int i; for (i = 0; i < cfg->install_ini->arr_version->nelts; ++i) { sp_cfg_version_info_t *ver_info = ARRAY_IDX(cfg->install_ini->arr_version, i, sp_cfg_version_info_t*); if (sp_version_equal(&ver_info->version, version)) return ver_info; } return NULL; } int sp_cfg_is_pack_installed(sp_cfg_t *cfg, const char*pack) { // 先查找轻量表历史 int i; for(i =0; iinstall_ini->arr_light_pack->nelts; i++) { sp_cfg_pack_info_t *pack_info = ARRAY_IDX(cfg->install_ini->arr_light_pack, i, sp_cfg_pack_info_t *); if (stricmp(pack_info->name, pack) == 0) return 0; } // 再查找版本安装包 for (i = 0; i < cfg->install_ini->arr_version->nelts; ++i) { sp_cfg_version_info_t *ver_info = ARRAY_IDX(cfg->install_ini->arr_version, i, sp_cfg_version_info_t*); if (stricmp(ver_info->install_pack, pack) ==0) return 0; } return 1; }