#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("!!!!!! a few of entities started up failed! please get more detail from dbg\\spshell !!!!!!"); sp_dbg_error("======================================================"); app_update_terminal_state(FrameworkState_Breakdown); Sleep(10000); app_t *app = get_app_instance(); sp_iom_post_quit(app->iom); } else { sp_dbg_info("all boot up entities has been started succ."); app_update_terminal_state(FrameworkState_Running); } return 0; } /*! launch limited startup module processes */ 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 sp_cfg_start_args_t* args) { 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, args, &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; 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; } sp_dbg_info("start bus daemon ok!"); 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/*multi-thread-switch*/, 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); /** for update terminal state event*/ rc = sp_var_client_create(g_app.svc, &g_app.var_client); if (rc != 0) { sp_dbg_error("var client create failed!"); return rc; } 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.on_destroy = NULL; 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 and start silverlight policy server ok!"); #endif //_WIN32 app_update_terminal_state(FrameworkState_Booting); 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() { int rc; #ifdef _DEBUG if (g_app.pConsole != NULL) { g_app.pConsole->StopListen(); //delete g_app.pConsole; g_app.pConsole = NULL; } #endif //_DEBUG /*kill all children process ?*/ rc = sp_mod_mgr_terminate_all_entity(sp_get_env()->mod_mgr, 0/*SP_SHELL_SVC_ID*/); if (0 != rc) { sp_dbg_error("terminate all entity failed! %d", rc); sp_shm_term(); winsock_term(); return 0; } sp_dbg_info("terminate all entity ok!"); #ifdef _WIN32 sp_dbg_info("stop silverlight policy server."); sp_sps_stop(g_app.sps); sp_dbg_info("destroy silverlight policy server."); sp_sps_destroy(g_app.sps); g_app.sps = NULL; #endif //_WIN32 sp_dbg_info("stop rpc server."); rc = sp_rpc_server_stop(g_app.rpc_server); if (rc != 0) { sp_dbg_error("stop rpc server failed! %d", rc); } else { sp_dbg_info("stop rpc server ok!"); } sp_dbg_info("destroy rpc server."); sp_rpc_server_destroy(g_app.rpc_server); g_app.rpc_server = NULL; sp_dbg_info("destroy bcm daemon."); sp_bcm_daemon_destroy(g_app.bcm_daemon); g_app.bcm_daemon = NULL; sp_dbg_info("destroy var daemon."); sp_var_daemon_destroy(g_app.var_daemon); g_app.var_daemon = NULL; sp_dbg_info("destroy var client"); sp_var_client_destroy(g_app.var_client); g_app.var_client = NULL; sp_dbg_info("destroy log daemon."); log_destroy(g_app.log); sp_dbg_info("term mod mgr."); sp_mod_mgr_term(sp_get_env()->mod_mgr); sp_dbg_info("stop svc."); rc = sp_svc_stop(g_app.svc); if (rc != 0) { sp_dbg_error("stop svc failed!"); } else { sp_dbg_info("stop svc ok!"); } sp_svc_destroy(g_app.svc); /*destroy iom and bus endpt*/ g_app.svc = NULL; g_app.iom = NULL; /*svc would destroy it.*/ //sp_dbg_info("destroy iom."); //sp_iom_destroy(g_app.iom); sp_dbg_info("stop bus daemon."); rc = bus_daemon_stop(g_app.bus_daemon); /*destroy ioqueue*/ if (rc != 0) { sp_dbg_error("stop bus daemon failed!"); } else { sp_dbg_info("stop bus daemon ok!"); } sp_dbg_info("destroy bus daemon."); rc = bus_daemon_destroy(g_app.bus_daemon); if (rc != 0) { sp_dbg_error("destroy bus daemon failed!"); } else { sp_dbg_info("destroy bus daemon ok!"); } g_app.bus_daemon = NULL; #ifdef _WIN32 if (g_app.bsc_gui != NULL) { sp_dbg_info("destroy gui."); sp_gui_destroy(g_app.bsc_gui); g_app.bsc_gui = NULL; } #endif sp_dbg_info("destroy env."); sp_env_destroy(sp_get_env()); sp_dbg_info("destroy share memory."); sp_shm_term(); winsock_term(); return 0; } int app_run() { int rc; rc = sp_iom_run(g_app.iom); return rc; } int app_update_terminal_state(int state) { int rc; char n[12] = {'\0'}; sp_env_t* env = sp_get_env(); sp_cfg_t* cfg = env->cfg; int old_state = cfg->shell_ini->shell_state; cfg->shell_ini->shell_state = state; _itoa(state, n, 10); rc = sp_var_client_set(g_app.var_client, VAR_RSERVERD_KEY_TERM_STATE, n, 0); return rc; } app_t *get_app_instance() { return &g_app; }