#include "precompile.h" #include "app.h" #include "log.h" #include "svc.h" #include "def.h" #include "bus.h" #include "memutil.h" #include "fileutil.h" #include "sockutil.h" #include "sp_svc.h" #include "sp_dbg_export.h" #include "sp_var.h" #include "sp_def.h" #include "sp_env.h" #include "sp_pst.h" #include "sp_shm.h" #include "sp_rpc.h" #include "sp_bcm.h" #include "SimpleString.h" #include "SpBase.h" #ifdef _WIN32 #include "SpShellConsole.h" #endif //_WIN32 #include struct app_t g_app; static int get_child_range() { char tmp[32]; #ifdef _WIN32 return _spawnl(_P_WAIT, ".\\bin\\sphost.exe", "sphost.exe", _itoa(sp_shm_get_range(0xffffffff), tmp, 10), NULL); #else return _spawnl(_P_WAIT, "./bin/sphost", "sphost", _itoa(sp_shm_get_range(0xffffffff), tmp, 10), NULL); #endif //_WIN32 } static void on_info(sp_rpc_server_t *server, int epid, int svc_id, int call_type, iobuffer_t **info_pkt, void *user_data) { BEGIN_INFO_MAP() HANDLE_INFO(SHELL_CMD_INFO_BLUESCREEN_DISPLAY, on_bluesceen_display) HANDLE_INFO(SHELL_CMD_INFO_FATAL_ERROR_DISPLAY, on_fatal_error_display) HANDLE_INFO(SHELL_CMD_INFO_STARTUP_INFO_DISPLAY, on_startup_info_display) HANDLE_INFO(SHELL_CMD_INFO_BLUESCREEN_UNDISPLAY, on_bluesceen_undisplay) HANDLE_INFO(SHELL_CMD_INFO_MACHINE_REBOOT, on_machine_reboot) HANDLE_INFO(SHELL_CMD_INFO_ENTITY_QUIT, on_entity_quit) HANDLE_INFO(SHELL_CMD_INFO_OUTPUT_CONSOLE_ON, on_output_console_on) HANDLE_INFO(SHELL_CMD_INFO_OUTPUT_CONSOLE_OFF, on_output_console_off) END_INFO_MAP() } static void on_req(sp_rpc_server_t *server, int epid, int svc_id, int rpc_id, int call_type, iobuffer_t **req_pkt, void *user_data) { BEGIG_REQ_MAP() HANDLE_REQ(SHELL_CMD_REQ_ENTITY_START, on_entity_start) HANDLE_REQ(SHELL_CMD_REQ_ENTITY_STOP, on_entity_stop) HANDLE_REQ(SHELL_CMD_REQ_ENTITY_PAUSE, on_entity_pause) HANDLE_REQ(SHELL_CMD_REQ_ENTITY_CONTINUE, on_entity_continue) HANDLE_REQ(SHELL_CMD_REQ_ENTITY_TEST, on_entity_test) HANDLE_REQ(SHELL_CMD_REQ_ENTITY_TERMINATE, on_entity_termination) HANDLE_REQ(SHELL_CMD_REQ_GET_BCAST_RECEIVER, on_get_bcast_receiver) END_REQ_MAP() } static unsigned int __stdcall __startlist_proc(void *param) { sp_env_t *env = sp_get_env(); sp_cfg_t *cfg = env->cfg; int i; bool bAllSuc = true; for (i = 0; i < cfg->shell_ini->arr_startlist->nelts; ++i) { sp_cfg_shell_entity_t *cfg_ent = ARRAY_IDX(cfg->shell_ini->arr_startlist, i, sp_cfg_shell_entity_t*); int rc = sp_mod_mgr_start_entity(env->mod_mgr, cfg_ent->idx, cfg_ent->cmdline, SP_SHELL_SVC_ID); if (rc != 0) { sp_dbg_warn("start entity %s failed!", cfg_ent->name); bAllSuc = false; } else { sp_dbg_info("start entity %s ok!", cfg_ent->name); Sleep(100); } } if (!bAllSuc) { sp_dbg_error("======================================================"); sp_dbg_error("!!!!!! 部分实体启动失败,请检查dbg\\spshell日志排除故障 !!!!!!"); sp_dbg_error("======================================================"); Sleep(10000); app_t *app = get_app_instance(); sp_iom_post_quit(app->iom); } return 0; } static int kickoff_startlist() { HANDLE hTempThread; hTempThread = (HANDLE)_beginthreadex(NULL, 0, &__startlist_proc, NULL, 0, NULL); if (hTempThread) { CloseHandle(hTempThread); return 0; } else { sp_dbg_warn("create startlist_proc thread failed!"); } return Error_Resource; } #include "sp_runTask.h" int RenameLightPacks(const char *pszAdPath) { int nRet = 0; auto pLogList = fileutil_get_sub_files2_a(pszAdPath, 50); for (int i = 0; i < pLogList->nelts; ++i) { CSimpleStringA strFilePath = ARRAY_IDX(pLogList, i, char*); if (strFilePath.IsEndWith(".new")) { auto strNewFile = strFilePath.SubString(0, strFilePath.GetLength() -4); if (MoveFileExA(strFilePath, strNewFile, MOVEFILE_REPLACE_EXISTING )) sp_dbg_info("rename [%s] to [%s] succeed", (const char*)strFilePath, (const char*)strNewFile); else { nRet = Error_Unexpect; sp_dbg_error("rename [%s] to [%s] fail: 0x%X", (const char*)strFilePath, (const char*)strNewFile, GetLastError()); } } } toolkit_array_free2(pLogList); return nRet; } static CSimpleStringA GetInstallStateStr(InstallStateEnum eState) { const struct { const char *str; InstallStateEnum val; } tbl[] = { { "Active", Install_Active }, { "Pending", Install_Pending }, { "SetToStart", Install_SetToStart }, { "FailRun", Install_FailRun }, { "RollBack", Install_RollBack }, { "Upgraded", Install_Upgraded }, { "Cancelled", Install_Cancelled }, { "WaitConfirm", Install_WaitConfirm }, { "Installed", Install_Installed }, }; for (int i = 0; i < sizeof(tbl) / sizeof(tbl[0]); ++i) { if (tbl[i].val == eState) return tbl[i].str; } return CSimpleStringA::Format("invalid state: %d", (int)eState); } int app_init() { const char *urls[1]; sp_env_t *env; void *hint_addr; int range; int rc; sp_rpc_server_callback callback; memset(&g_app, 0, sizeof(g_app)); if (winsock_init() != 0) { sp_dbg_error("winsock init failed!"); return -1; } range= get_child_range(); hint_addr = sp_shm_init(range, TRUE); if (!hint_addr) { sp_dbg_error("init shm failed!"); return Error_Resource; } sp_dbg_info("init shm ok, addr = 0x%08x", hint_addr); rc = sp_env_create(hint_addr, range, &env); if (rc != 0) { sp_dbg_error("create env failed!"); return rc; } sp_dbg_info("create env ok!"); #ifdef _WIN32 bool isEqual = !strcmp(env->cfg->root_ini->machine_type, "RVC.IL"); sp_gui_setShow(isEqual ? 0 : 1); rc = sp_gui_create(&g_app.bsc_gui); if (rc != 0) { sp_dbg_error("app shell gui init failed!"); return rc; } if (isEqual) { sp_dbg_info("machine_type is RVC.IL, undisplay the logGui"); sp_gui_undisplay(g_app.bsc_gui); } else { sp_dbg_info("machine_type is %s, display the logGui", env->cfg->root_ini->machine_type); sp_gui_display(g_app.bsc_gui); //显示在任务栏 } sp_dbg_set_output_gui(g_app.bsc_gui); sp_dbg_info("app shell gui init ok!"); env->gui = g_app.bsc_gui; #endif //_WIN32 // log current version info sp_cfg_install_ini_t *install_ini = env->cfg->install_ini; CVersion curVersion = CVersion(install_ini->install_version.major, install_ini->install_version.minor, install_ini->install_version.revision, install_ini->install_version.build); auto version_info = sp_cfg_find_previous_version_info(env->cfg, &install_ini->install_version); CVersion preVersion; if (version_info) preVersion = CVersion(version_info->version.major, version_info->version.minor, version_info->version.revision, version_info->version.build); version_info = sp_cfg_find_version_info(env->cfg, &install_ini->install_version); if (version_info) { CSmallDateTime tmSwithOverDate = version_info->switch_time; CSimpleStringA strInstallPack = version_info->install_pack; CSimpleStringA strInstallState = GetInstallStateStr((InstallStateEnum)version_info->install_state); sp_dbg_info("current version:[%s], previous version:[%s], pack:[%s], state:[%s], swith time:[%s]", (const char*)curVersion.ToString(), (const char*)preVersion.ToString(), (const char*)strInstallPack, (const char*)strInstallState, (const char*)tmSwithOverDate.ToTimeString()); } else sp_dbg_error("get version info fail, current version: [%s]", (const char*)curVersion.ToString()); sp_cfg_root_ini_t *root_ini = env->cfg->root_ini; int i; sp_cfg_path_t *pos; ARRAY_FOR_EACH_ENTRY(pos, i, root_ini->arr_path, sp_cfg_path_t*) { if (!ExistsDirA(pos->path)) { BOOL bRet = CreateDirRecursiveA(pos->path); if (bRet) { sp_dbg_info("create %s ok!", pos->path); } else { sp_dbg_error("create %s failed!", pos->path); return Error_Resource; } } } sp_pst_recover(env->dir->obj_path); #ifdef _WIN32 sp_runtask_killprocess(); #endif //_WIN32 urls[0] = env->url; #if 1 rc = bus_daemon_create(array_size(urls), urls, 2, &g_app.bus_daemon); if (rc != 0) { sp_dbg_error("create bus deamon failed!"); return rc; } rc = bus_daemon_start(g_app.bus_daemon); if (rc != 0) { sp_dbg_error("start bus daemon failed!"); return rc; } #endif rc = sp_iom_create(env->url, SP_SHELL_MOD_ID, &g_app.iom); if (rc != 0) { sp_dbg_error("create iom failed!"); return rc; } sp_dbg_info("create iom ok!"); rc = sp_svc_create(g_app.iom, 1, SP_SHELL_SVC_ID, 0, &g_app.svc); //threadpool if (rc != 0) { sp_dbg_error("create svc failed!"); return rc; } sp_dbg_info("create svc ok!"); rc = sp_svc_start(g_app.svc); //threadpool 任务池 if (rc != 0) { sp_dbg_error("start svc failed!"); return rc; } sp_dbg_info("start svc ok!"); sp_mod_mgr_bind_shell_svc(env->mod_mgr, g_app.svc); sp_dbg_info("bind svc ok!"); rc = sp_mod_mgr_init(env->mod_mgr); if (rc != 0) { sp_dbg_error("init mod mgr failed!"); return rc; } sp_dbg_info("init mod mgr ok!"); rc = log_create(g_app.svc, &g_app.log); if (rc != 0) { sp_dbg_error("log daemon create failed!"); return rc; } sp_dbg_info("log daemon create ok!"); // 检查轻量更新包是否有.new文件 RenameLightPacks(env->cfg->root_ini->ref_addata_path); rc = sp_var_daemon_create(g_app.svc, &g_app.var_daemon); // add workitem daemon_on_pkt and daemon_on_sys if (rc != 0) { sp_dbg_error("var daemon create failed!"); return rc; } sp_dbg_info("var daemon create ok!"); rc = sp_bcm_daemon_create(g_app.svc, &g_app.bcm_daemon); if (rc != 0) { sp_dbg_error("bcm daemon create failed!"); return rc; } sp_dbg_info("bcm daemon create ok!"); sp_mod_mgr_bind_bcm_daemon(env->mod_mgr, g_app.bcm_daemon); callback.on_info = &on_info; callback.on_req = &on_req; callback.user_data = NULL; rc = sp_rpc_server_create(g_app.svc, &callback, &g_app.rpc_server); if (rc != 0) { sp_dbg_error("app shell rpc server init failed!"); return rc; } rc = sp_rpc_server_start(g_app.rpc_server); if (rc != 0) { sp_dbg_error("app shell rpc server start failed!"); return rc; } #ifdef _WIN32 rc = sp_sps_create(&g_app.sps); if (rc != 0) { sp_dbg_error("create silverlight policy server failed!"); return rc; } rc = sp_sps_start(g_app.sps); if (rc != 0) { sp_dbg_error("start silverlight policy server failed!"); return rc; } sp_dbg_info("create silverlight policy server ok!"); #endif //_WIN32 //launch limited startup module processes rc = kickoff_startlist(); if (rc != 0) { sp_dbg_error("kickoff startlist thread proc failed!"); } sp_dbg_info("kickoff startlist thread proc ok!"); #ifdef _DEBUG // start console service int nConsolePort = env->cfg->shell_ini->nConsolePort; if (nConsolePort >0) { g_app.pConsole = new CSpShellConsole(); if (!g_app.pConsole->StartListen(nConsolePort)) { sp_dbg_error("start spshell console service at port %d fail, %s", nConsolePort, g_app.pConsole->GetLastErrorMsg()); return Error_Unexpect; } sp_dbg_info("start spshell console service at port %d ok!", nConsolePort); } #endif #ifdef _WIN32 sp_runtask_startprocess(); #endif //_WIN32 // close spshell dbg info // sp_dbg_set_output_gui(NULL); return 0; } int app_term() { #ifdef _WIN32 if (g_app.pConsole != NULL) { g_app.pConsole->StopListen(); g_app.pConsole = NULL; } #endif //_WIN32 log_destroy(g_app.log); sp_dbg_term(); winsock_term(); return 0; } int app_run() { int rc; rc = sp_iom_run(g_app.iom); return rc; } app_t *get_app_instance() { return &g_app; }