| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "module_wasm_app.h"
- #include "native_interface.h" /* for request_t type */
- #include "app_manager_host.h"
- #include "bh_platform.h"
- #include "bi-inc/attr_container.h"
- #include "coap_ext.h"
- #include "event.h"
- #include "watchdog.h"
- #include "runtime_lib.h"
- #if WASM_ENABLE_INTERP != 0
- #include "wasm.h"
- #endif
- #if WASM_ENABLE_AOT != 0
- #include "aot_export.h"
- #endif
- /* clang-format off */
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- /* Wasm bytecode file 4 version bytes */
- static uint8 wasm_bytecode_version[4] = {
- (uint8)0x01,
- (uint8)0x00,
- (uint8)0x00,
- (uint8)0x00
- };
- #endif
- #if WASM_ENABLE_AOT != 0
- /* Wasm aot file 4 version bytes */
- static uint8 wasm_aot_version[4] = {
- (uint8)0x02,
- (uint8)0x00,
- (uint8)0x00,
- (uint8)0x00
- };
- #endif
- /* clang-format on */
- static union {
- int a;
- char b;
- } __ue = { .a = 1 };
- #define is_little_endian() (__ue.b == 1)
- /* Wasm App Install Request Receiving Phase */
- typedef enum wasm_app_install_req_recv_phase_t {
- Phase_Req_Ver,
- Phase_Req_Action,
- Phase_Req_Fmt,
- Phase_Req_Mid,
- Phase_Req_Sender,
- Phase_Req_Url_Len,
- Phase_Req_Payload_Len, /* payload is wasm app binary */
- Phase_Req_Url,
- /* Magic phase */
- Phase_App_Magic,
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- /* Phases of wasm bytecode file */
- Phase_Wasm_Version,
- Phase_Wasm_Section_Type,
- Phase_Wasm_Section_Size,
- Phase_Wasm_Section_Content,
- #endif
- #if WASM_ENABLE_AOT != 0
- /* Phases of wasm AOT file */
- Phase_AOT_Version,
- Phase_AOT_Section_ID,
- Phase_AOT_Section_Size,
- Phase_AOT_Section_Content
- #endif
- } wasm_app_install_req_recv_phase_t;
- /* Message for insall wasm app */
- typedef struct install_wasm_app_msg_t {
- uint8 request_version;
- uint8 request_action;
- uint16 request_fmt;
- uint32 request_mid;
- uint32 request_sender;
- uint16 request_url_len;
- uint32 wasm_app_size; /* payload size is just wasm app binary size */
- char *request_url;
- wasm_app_file_t app_file;
- int app_file_magic;
- } install_wasm_app_msg_t;
- /* Wasm App Install Request Receive Context */
- typedef struct wasm_app_install_req_recv_ctx_t {
- wasm_app_install_req_recv_phase_t phase;
- int size_in_phase;
- install_wasm_app_msg_t message;
- int total_received_size;
- } wasm_app_install_req_recv_ctx_t;
- /* Current wasm app install request receive context */
- static wasm_app_install_req_recv_ctx_t recv_ctx;
- static bool
- wasm_app_module_init(void);
- static bool
- wasm_app_module_install(request_t *msg);
- static bool
- wasm_app_module_uninstall(request_t *msg);
- static void
- wasm_app_module_watchdog_kill(module_data *module_data);
- static bool
- wasm_app_module_handle_host_url(void *queue_msg);
- static module_data *
- wasm_app_module_get_module_data(void *inst);
- static bool
- wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size,
- int *received_size);
- static bool
- module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message);
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- static void
- destroy_all_wasm_sections(wasm_section_list_t sections);
- static void
- destroy_part_wasm_sections(wasm_section_list_t *p_sections,
- uint8 *section_types, int section_cnt);
- #endif
- #if WASM_ENABLE_AOT != 0
- static void
- destroy_all_aot_sections(aot_section_list_t sections);
- static void
- destroy_part_aot_sections(aot_section_list_t *p_sections, uint8 *section_types,
- int section_cnt);
- #endif
- #define Max_Msg_Callback 10
- int g_msg_type[Max_Msg_Callback] = { 0 };
- message_type_handler_t g_msg_callbacks[Max_Msg_Callback] = { 0 };
- #define Max_Cleanup_Callback 10
- static resource_cleanup_handler_t g_cleanup_callbacks[Max_Cleanup_Callback] = {
- 0
- };
- module_interface wasm_app_module_interface = {
- wasm_app_module_init,
- wasm_app_module_install,
- wasm_app_module_uninstall,
- wasm_app_module_watchdog_kill,
- wasm_app_module_handle_host_url,
- wasm_app_module_get_module_data,
- wasm_app_module_on_install_request_byte_arrive
- };
- #if WASM_ENABLE_INTERP == 0
- static unsigned
- align_uint(unsigned v, unsigned b)
- {
- unsigned m = b - 1;
- return (v + m) & ~m;
- }
- #endif
- static void
- exchange_uint32(uint8 *p_data)
- {
- uint8 value = *p_data;
- *p_data = *(p_data + 3);
- *(p_data + 3) = value;
- value = *(p_data + 1);
- *(p_data + 1) = *(p_data + 2);
- *(p_data + 2) = value;
- }
- static wasm_function_inst_t
- app_manager_lookup_function(const wasm_module_inst_t module_inst,
- const char *name, const char *signature)
- {
- wasm_function_inst_t func;
- func = wasm_runtime_lookup_function(module_inst, name, signature);
- if (!func && name[0] == '_')
- func = wasm_runtime_lookup_function(module_inst, name + 1, signature);
- return func;
- }
- static void
- app_instance_queue_callback(void *queue_msg, void *arg)
- {
- uint32 argv[2];
- wasm_function_inst_t func_onRequest, func_onTimer;
- wasm_module_inst_t inst = (wasm_module_inst_t)arg;
- module_data *m_data = app_manager_get_module_data(Module_WASM_App, inst);
- wasm_data *wasm_app_data;
- int message_type;
- bh_assert(m_data);
- wasm_app_data = (wasm_data *)m_data->internal_data;
- message_type = bh_message_type(queue_msg);
- if (message_type < BASE_EVENT_MAX) {
- switch (message_type) {
- case RESTFUL_REQUEST:
- {
- request_t *request = (request_t *)bh_message_payload(queue_msg);
- int size;
- char *buffer;
- int32 buffer_offset;
- app_manager_printf("App %s got request, url %s, action %d\n",
- m_data->module_name, request->url,
- request->action);
- func_onRequest = app_manager_lookup_function(
- inst, "_on_request", "(i32i32)");
- if (!func_onRequest) {
- app_manager_printf("Cannot find function onRequest\n");
- break;
- }
- buffer = pack_request(request, &size);
- if (buffer == NULL)
- break;
- buffer_offset =
- wasm_runtime_module_dup_data(inst, buffer, size);
- if (buffer_offset == 0) {
- const char *exception = wasm_runtime_get_exception(inst);
- if (exception) {
- app_manager_printf(
- "Got exception running wasm code: %s\n", exception);
- wasm_runtime_clear_exception(inst);
- }
- free_req_resp_packet(buffer);
- break;
- }
- free_req_resp_packet(buffer);
- argv[0] = (uint32)buffer_offset;
- argv[1] = (uint32)size;
- if (!wasm_runtime_call_wasm(wasm_app_data->exec_env,
- func_onRequest, 2, argv)) {
- const char *exception = wasm_runtime_get_exception(inst);
- bh_assert(exception);
- app_manager_printf("Got exception running wasm code: %s\n",
- exception);
- wasm_runtime_clear_exception(inst);
- wasm_runtime_module_free(inst, buffer_offset);
- break;
- }
- wasm_runtime_module_free(inst, buffer_offset);
- app_manager_printf("Wasm app process request success.\n");
- break;
- }
- case RESTFUL_RESPONSE:
- {
- wasm_function_inst_t func_onResponse;
- response_t *response =
- (response_t *)bh_message_payload(queue_msg);
- int size;
- char *buffer;
- int32 buffer_offset;
- app_manager_printf("App %s got response_t,status %d\n",
- m_data->module_name, response->status);
- func_onResponse = app_manager_lookup_function(
- inst, "_on_response", "(i32i32)");
- if (!func_onResponse) {
- app_manager_printf("Cannot find function on_response\n");
- break;
- }
- buffer = pack_response(response, &size);
- if (buffer == NULL)
- break;
- buffer_offset =
- wasm_runtime_module_dup_data(inst, buffer, size);
- if (buffer_offset == 0) {
- const char *exception = wasm_runtime_get_exception(inst);
- if (exception) {
- app_manager_printf(
- "Got exception running wasm code: %s\n", exception);
- wasm_runtime_clear_exception(inst);
- }
- free_req_resp_packet(buffer);
- break;
- }
- free_req_resp_packet(buffer);
- argv[0] = (uint32)buffer_offset;
- argv[1] = (uint32)size;
- if (!wasm_runtime_call_wasm(wasm_app_data->exec_env,
- func_onResponse, 2, argv)) {
- const char *exception = wasm_runtime_get_exception(inst);
- bh_assert(exception);
- app_manager_printf("Got exception running wasm code: %s\n",
- exception);
- wasm_runtime_clear_exception(inst);
- wasm_runtime_module_free(inst, buffer_offset);
- break;
- }
- wasm_runtime_module_free(inst, buffer_offset);
- app_manager_printf("Wasm app process response success.\n");
- break;
- }
- default:
- {
- for (int i = 0; i < Max_Msg_Callback; i++) {
- if (g_msg_type[i] == message_type) {
- g_msg_callbacks[i](m_data, queue_msg);
- return;
- }
- }
- app_manager_printf(
- "Invalid message type of WASM app queue message.\n");
- break;
- }
- }
- }
- else {
- switch (message_type) {
- case TIMER_EVENT_WASM:
- {
- unsigned int timer_id;
- if (bh_message_payload(queue_msg)) {
- /* Call Timer.callOnTimer() method */
- func_onTimer = app_manager_lookup_function(
- inst, "_on_timer_callback", "(i32)");
- if (!func_onTimer) {
- app_manager_printf(
- "Cannot find function _on_timer_callback\n");
- break;
- }
- timer_id =
- (unsigned int)(uintptr_t)bh_message_payload(queue_msg);
- argv[0] = timer_id;
- if (!wasm_runtime_call_wasm(wasm_app_data->exec_env,
- func_onTimer, 1, argv)) {
- const char *exception =
- wasm_runtime_get_exception(inst);
- bh_assert(exception);
- app_manager_printf(
- "Got exception running wasm code: %s\n", exception);
- wasm_runtime_clear_exception(inst);
- }
- }
- break;
- }
- default:
- {
- for (int i = 0; i < Max_Msg_Callback; i++) {
- if (g_msg_type[i] == message_type) {
- g_msg_callbacks[i](m_data, queue_msg);
- return;
- }
- }
- app_manager_printf(
- "Invalid message type of WASM app queue message.\n");
- break;
- }
- }
- }
- }
- #if WASM_ENABLE_LIBC_WASI != 0
- static bool
- wasm_app_prepare_wasi_dir(wasm_module_t module, const char *module_name,
- char *wasi_dir_buf, uint32 buf_size)
- {
- const char *wasi_root = wasm_get_wasi_root_dir();
- char *p = wasi_dir_buf;
- uint32 module_name_len = strlen(module_name);
- uint32 wasi_root_len = strlen(wasi_root);
- uint32 total_size;
- struct stat st = { 0 };
- bh_assert(wasi_root);
- /* wasi_dir: wasi_root/module_name */
- total_size = wasi_root_len + 1 + module_name_len + 1;
- if (total_size > buf_size)
- return false;
- memcpy(p, wasi_root, wasi_root_len);
- p += wasi_root_len;
- *p++ = '/';
- memcpy(p, module_name, module_name_len);
- p += module_name_len;
- *p++ = '\0';
- if (mkdir(wasi_dir_buf, 0777) != 0) {
- if (errno == EEXIST) {
- /* Failed due to dir already exist */
- if ((stat(wasi_dir_buf, &st) == 0) && (st.st_mode & S_IFDIR)) {
- return true;
- }
- }
- return false;
- }
- return true;
- }
- #endif
- /* WASM app thread main routine */
- static void *
- wasm_app_routine(void *arg)
- {
- wasm_function_inst_t func_onInit;
- wasm_function_inst_t func_onDestroy;
- module_data *m_data = (module_data *)arg;
- wasm_data *wasm_app_data = (wasm_data *)m_data->internal_data;
- wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
- /* Set m_data to the VM managed instance's custom data */
- wasm_runtime_set_custom_data(inst, m_data);
- app_manager_printf("WASM app '%s' started\n", m_data->module_name);
- #if WASM_ENABLE_LIBC_WASI != 0
- if (wasm_runtime_is_wasi_mode(inst)) {
- wasm_function_inst_t func_start;
- /* In wasi mode, we should call function named "_start"
- which initializes the wasi envrionment. The "_start" function
- will call "main" function */
- if ((func_start = wasm_runtime_lookup_wasi_start_function(inst))) {
- if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_start, 0,
- NULL)) {
- const char *exception = wasm_runtime_get_exception(inst);
- bh_assert(exception);
- app_manager_printf(
- "Got exception running wasi start function: %s\n",
- exception);
- wasm_runtime_clear_exception(inst);
- goto fail1;
- }
- }
- /* if no start function is found, we execute
- the _on_init function as normal */
- }
- #endif
- /* Call app's onInit() method */
- func_onInit = app_manager_lookup_function(inst, "_on_init", "()");
- if (!func_onInit) {
- app_manager_printf("Cannot find function on_init().\n");
- goto fail1;
- }
- if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onInit, 0,
- NULL)) {
- const char *exception = wasm_runtime_get_exception(inst);
- bh_assert(exception);
- app_manager_printf("Got exception running WASM code: %s\n", exception);
- wasm_runtime_clear_exception(inst);
- /* call on_destroy() in case some resources are opened in on_init()
- * and then exception thrown */
- goto fail2;
- }
- /* Enter queue loop run to receive and process applet queue message */
- bh_queue_enter_loop_run(m_data->queue, app_instance_queue_callback, inst);
- app_manager_printf("App instance main thread exit.\n");
- fail2:
- /* Call WASM app onDestroy() method if there is */
- func_onDestroy = app_manager_lookup_function(inst, "_on_destroy", "()");
- if (func_onDestroy) {
- if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onDestroy, 0,
- NULL)) {
- const char *exception = wasm_runtime_get_exception(inst);
- bh_assert(exception);
- app_manager_printf("Got exception running WASM code: %s\n",
- exception);
- wasm_runtime_clear_exception(inst);
- }
- }
- fail1:
- return NULL;
- }
- static void
- cleanup_app_resource(module_data *m_data)
- {
- int i;
- wasm_data *wasm_app_data = (wasm_data *)m_data->internal_data;
- bool is_bytecode = wasm_app_data->is_bytecode;
- am_cleanup_registeration(m_data->id);
- am_unregister_event(NULL, m_data->id);
- for (i = 0; i < Max_Cleanup_Callback; i++) {
- if (g_cleanup_callbacks[i] != NULL)
- g_cleanup_callbacks[i](m_data->id);
- else
- break;
- }
- wasm_runtime_deinstantiate(wasm_app_data->wasm_module_inst);
- /* Destroy remain sections (i.e. data segment section for bytecode file
- * or text section of aot file) from app file's section list. */
- if (is_bytecode) {
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- destroy_all_wasm_sections(
- (wasm_section_list_t)(wasm_app_data->sections));
- #else
- bh_assert(0);
- #endif
- }
- else {
- #if WASM_ENABLE_AOT != 0
- destroy_all_aot_sections((aot_section_list_t)(wasm_app_data->sections));
- #else
- bh_assert(0);
- #endif
- }
- if (wasm_app_data->wasm_module)
- wasm_runtime_unload(wasm_app_data->wasm_module);
- if (wasm_app_data->exec_env)
- wasm_runtime_destroy_exec_env(wasm_app_data->exec_env);
- /* Destroy watchdog timer */
- watchdog_timer_destroy(&m_data->wd_timer);
- /* Remove module data from module data list and free it */
- app_manager_del_module_data(m_data);
- }
- /************************************************************/
- /* Module specific functions implementation */
- /************************************************************/
- static bool
- wasm_app_module_init(void)
- {
- uint32 version;
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- version = WASM_CURRENT_VERSION;
- if (!is_little_endian())
- exchange_uint32((uint8 *)&version);
- bh_memcpy_s(wasm_bytecode_version, 4, &version, 4);
- #endif
- #if WASM_ENABLE_AOT != 0
- version = AOT_CURRENT_VERSION;
- if (!is_little_endian())
- exchange_uint32((uint8 *)&version);
- bh_memcpy_s(wasm_aot_version, 4, &version, 4);
- #endif
- return true;
- }
- #define APP_NAME_MAX_LEN 128
- #define MAX_INT_STR_LEN 11
- static bool
- wasm_app_module_install(request_t *msg)
- {
- unsigned int m_data_size, heap_size, stack_size;
- unsigned int timeout, timers, err_size;
- char *properties;
- int properties_offset;
- wasm_app_file_t *wasm_app_file;
- wasm_data *wasm_app_data;
- package_type_t package_type;
- module_data *m_data = NULL;
- wasm_module_t module = NULL;
- wasm_module_inst_t inst = NULL;
- wasm_exec_env_t exec_env = NULL;
- char m_name[APP_NAME_MAX_LEN] = { 0 };
- char timeout_str[MAX_INT_STR_LEN] = { 0 };
- char heap_size_str[MAX_INT_STR_LEN] = { 0 };
- char timers_str[MAX_INT_STR_LEN] = { 0 }, err[128], err_resp[256];
- #if WASM_ENABLE_LIBC_WASI != 0
- char wasi_dir_buf[PATH_MAX] = { 0 };
- const char *wasi_dir_list[] = { wasi_dir_buf };
- #endif
- err_size = sizeof(err);
- /* Check payload */
- if (!msg->payload || msg->payload_len == 0) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: invalid wasm file.");
- return false;
- }
- /* Judge the app type is AOTed or not */
- package_type = get_package_type((uint8 *)msg->payload, msg->payload_len);
- wasm_app_file = (wasm_app_file_t *)msg->payload;
- /* Check app name */
- properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
- bh_assert(properties_offset > 0);
- if (properties_offset <= 0) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: invalid app name.");
- goto fail;
- }
- properties = msg->url + properties_offset;
- find_key_value(properties, strlen(properties), "name", m_name,
- sizeof(m_name) - 1, '&');
- if (strlen(m_name) == 0) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: invalid app name.");
- goto fail;
- }
- if (app_manager_lookup_module_data(m_name)) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: app already installed.");
- goto fail;
- }
- /* Parse heap size */
- heap_size = APP_HEAP_SIZE_DEFAULT;
- find_key_value(properties, strlen(properties), "heap", heap_size_str,
- sizeof(heap_size_str) - 1, '&');
- if (strlen(heap_size_str) > 0) {
- heap_size = atoi(heap_size_str);
- if (heap_size < APP_HEAP_SIZE_MIN)
- heap_size = APP_HEAP_SIZE_MIN;
- else if (heap_size > APP_HEAP_SIZE_MAX)
- heap_size = APP_HEAP_SIZE_MAX;
- }
- /* Load WASM file and instantiate*/
- switch (package_type) {
- #if WASM_ENABLE_AOT != 0
- case Wasm_Module_AoT:
- {
- wasm_aot_file_t *aot_file;
- /* clang-format off */
- /* Sections to be released after loading */
- uint8 sections1[] = {
- AOT_SECTION_TYPE_TARGET_INFO,
- AOT_SECTION_TYPE_INIT_DATA,
- AOT_SECTION_TYPE_FUNCTION,
- AOT_SECTION_TYPE_EXPORT,
- AOT_SECTION_TYPE_RELOCATION,
- AOT_SECTION_TYPE_SIGANATURE,
- AOT_SECTION_TYPE_CUSTOM,
- };
- /* clang-format on */
- aot_file = &wasm_app_file->u.aot;
- /* Load AOT module from sections */
- module = wasm_runtime_load_from_sections(aot_file->sections, true,
- err, err_size);
- if (!module) {
- snprintf(err_resp, sizeof(err_resp),
- "Install WASM app failed: %s", err);
- SEND_ERR_RESPONSE(msg->mid, err_resp);
- goto fail;
- }
- /* Destroy useless sections from list after load */
- destroy_part_aot_sections(&aot_file->sections, sections1,
- sizeof(sections1) / sizeof(uint8));
- #if WASM_ENABLE_LIBC_WASI != 0
- if (!wasm_app_prepare_wasi_dir(module, m_name, wasi_dir_buf,
- sizeof(wasi_dir_buf))) {
- SEND_ERR_RESPONSE(
- msg->mid,
- "Install WASM app failed: prepare wasi env failed.");
- goto fail;
- }
- wasm_runtime_set_wasi_args(module, wasi_dir_list, 1, NULL, 0, NULL,
- 0, NULL, 0);
- #endif
- /* Instantiate the AOT module */
- inst =
- wasm_runtime_instantiate(module, 0, heap_size, err, err_size);
- if (!inst) {
- snprintf(err_resp, sizeof(err_resp),
- "Install WASM app failed: %s", err);
- SEND_ERR_RESPONSE(msg->mid, err);
- goto fail;
- }
- break;
- }
- #endif /* endof WASM_ENABLE_AOT != 0 */
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- case Wasm_Module_Bytecode:
- {
- wasm_bytecode_file_t *bytecode_file;
- /* Sections to be released after loading */
- uint8 sections1[] = {
- SECTION_TYPE_USER,
- SECTION_TYPE_TYPE,
- SECTION_TYPE_IMPORT,
- SECTION_TYPE_FUNC,
- SECTION_TYPE_TABLE,
- SECTION_TYPE_MEMORY,
- SECTION_TYPE_GLOBAL,
- SECTION_TYPE_EXPORT,
- SECTION_TYPE_START,
- SECTION_TYPE_ELEM,
- #if WASM_ENABLE_BULK_MEMORY != 0
- SECTION_TYPE_DATACOUNT
- #endif
- };
- /* Sections to be released after instantiating */
- uint8 sections2[] = { SECTION_TYPE_DATA };
- bytecode_file = &wasm_app_file->u.bytecode;
- /* Load wasm module from sections */
- module = wasm_runtime_load_from_sections(bytecode_file->sections,
- false, err, err_size);
- if (!module) {
- snprintf(err_resp, sizeof(err_resp),
- "Install WASM app failed: %s", err);
- SEND_ERR_RESPONSE(msg->mid, err_resp);
- goto fail;
- }
- /* Destroy useless sections from list after load */
- destroy_part_wasm_sections(&bytecode_file->sections, sections1,
- sizeof(sections1) / sizeof(uint8));
- #if WASM_ENABLE_LIBC_WASI != 0
- if (!wasm_app_prepare_wasi_dir(module, m_name, wasi_dir_buf,
- sizeof(wasi_dir_buf))) {
- SEND_ERR_RESPONSE(
- msg->mid,
- "Install WASM app failed: prepare wasi env failed.");
- goto fail;
- }
- wasm_runtime_set_wasi_args(module, wasi_dir_list, 1, NULL, 0, NULL,
- 0, NULL, 0);
- #endif
- /* Instantiate the wasm module */
- inst =
- wasm_runtime_instantiate(module, 0, heap_size, err, err_size);
- if (!inst) {
- snprintf(err_resp, sizeof(err_resp),
- "Install WASM app failed: %s", err);
- SEND_ERR_RESPONSE(msg->mid, err_resp);
- goto fail;
- }
- /* Destroy useless sections from list after instantiate */
- destroy_part_wasm_sections(&bytecode_file->sections, sections2,
- sizeof(sections2) / sizeof(uint8));
- break;
- }
- #endif /* endof WASM_ENALBE_INTERP != 0 || WASM_ENABLE_JIT != 0 */
- default:
- SEND_ERR_RESPONSE(
- msg->mid,
- "Install WASM app failed: invalid wasm package type.");
- goto fail;
- }
- /* Create module data including the wasm_app_data as its internal_data*/
- m_data_size = offsetof(module_data, module_name) + strlen(m_name) + 1;
- m_data_size = align_uint(m_data_size, 4);
- m_data = APP_MGR_MALLOC(m_data_size + sizeof(wasm_data));
- if (!m_data) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: allocate memory failed.");
- goto fail;
- }
- memset(m_data, 0, m_data_size + sizeof(wasm_data));
- m_data->module_type = Module_WASM_App;
- m_data->internal_data = (uint8 *)m_data + m_data_size;
- wasm_app_data = (wasm_data *)m_data->internal_data;
- wasm_app_data->wasm_module_inst = inst;
- wasm_app_data->wasm_module = module;
- wasm_app_data->m_data = m_data;
- if (package_type == Wasm_Module_Bytecode) {
- wasm_app_data->is_bytecode = true;
- wasm_app_data->sections = wasm_app_file->u.bytecode.sections;
- }
- else {
- wasm_app_data->is_bytecode = false;
- wasm_app_data->sections = wasm_app_file->u.aot.sections;
- }
- if (!(wasm_app_data->exec_env = exec_env =
- wasm_runtime_create_exec_env(inst, DEFAULT_WASM_STACK_SIZE))) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: create exec env failed.");
- goto fail;
- }
- /* Set module data - name and module type */
- bh_strcpy_s(m_data->module_name, strlen(m_name) + 1, m_name);
- /* Set module data - execution timeout */
- timeout = DEFAULT_WATCHDOG_INTERVAL;
- find_key_value(properties, strlen(properties), "wd", timeout_str,
- sizeof(timeout_str) - 1, '&');
- if (strlen(timeout_str) > 0)
- timeout = atoi(timeout_str);
- m_data->timeout = timeout;
- /* Set module data - create queue */
- m_data->queue = bh_queue_create();
- if (!m_data->queue) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: create app queue failed.");
- goto fail;
- }
- /* Set heap size */
- m_data->heap_size = heap_size;
- /* Set module data - timers number */
- timers = DEFAULT_TIMERS_PER_APP;
- find_key_value(properties, strlen(properties), "timers", timers_str,
- sizeof(timers_str) - 1, '&');
- if (strlen(timers_str) > 0) {
- timers = atoi(timers_str);
- if (timers > MAX_TIMERS_PER_APP)
- timers = MAX_TIMERS_PER_APP;
- }
- /* Attention: must add the module before start the thread! */
- app_manager_add_module_data(m_data);
- m_data->timer_ctx = create_wasm_timer_ctx(m_data->id, timers);
- if (!m_data->timer_ctx) {
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: create app timers failed.");
- goto fail;
- }
- /* Initialize watchdog timer */
- if (!watchdog_timer_init(m_data)) {
- SEND_ERR_RESPONSE(
- msg->mid,
- "Install WASM app failed: create app watchdog timer failed.");
- goto fail;
- }
- stack_size = APP_THREAD_STACK_SIZE_DEFAULT;
- #ifdef OS_ENABLE_HW_BOUND_CHECK
- stack_size += 4 * BH_KB;
- #endif
- /* Create WASM app thread. */
- if (os_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
- (void *)m_data, stack_size)
- != 0) {
- module_data_list_remove(m_data);
- SEND_ERR_RESPONSE(msg->mid,
- "Install WASM app failed: create app thread failed.");
- goto fail;
- }
- /* only when thread is created it is the flag of installation success */
- app_manager_post_applets_update_event();
- app_manager_printf("Install WASM app success!\n");
- send_error_response_to_host(msg->mid, CREATED_2_01, NULL); /* CREATED */
- return true;
- fail:
- if (m_data)
- release_module(m_data);
- if (inst)
- wasm_runtime_deinstantiate(inst);
- if (module)
- wasm_runtime_unload(module);
- if (exec_env)
- wasm_runtime_destroy_exec_env(exec_env);
- switch (package_type) {
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- case Wasm_Module_Bytecode:
- destroy_all_wasm_sections(wasm_app_file->u.bytecode.sections);
- break;
- #endif
- #if WASM_ENABLE_AOT != 0
- case Wasm_Module_AoT:
- destroy_all_aot_sections(wasm_app_file->u.aot.sections);
- break;
- #endif
- default:
- break;
- }
- return false;
- }
- /* For internal use: if defined to 1, the process will
- * exit when wasm app is uninstalled. Hence valgrind can
- * print memory leak report. */
- #ifndef VALGRIND_CHECK
- #define VALGRIND_CHECK 0
- #endif
- /* Uninstall WASM app */
- static bool
- wasm_app_module_uninstall(request_t *msg)
- {
- module_data *m_data;
- wasm_data *wasm_app_data;
- char m_name[APP_NAME_MAX_LEN] = { 0 };
- char *properties;
- int properties_offset;
- properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
- /* TODO: assert(properties_offset > 0) */
- if (properties_offset <= 0)
- return false;
- properties = msg->url + properties_offset;
- find_key_value(properties, strlen(properties), "name", m_name,
- sizeof(m_name) - 1, '&');
- if (strlen(m_name) == 0) {
- SEND_ERR_RESPONSE(msg->mid,
- "Uninstall WASM app failed: invalid app name.");
- return false;
- }
- m_data = app_manager_lookup_module_data(m_name);
- if (!m_data) {
- SEND_ERR_RESPONSE(msg->mid, "Uninstall WASM app failed: no app found.");
- return false;
- }
- if (m_data->module_type != Module_WASM_App) {
- SEND_ERR_RESPONSE(msg->mid,
- "Uninstall WASM app failed: invalid module type.");
- return false;
- }
- if (m_data->wd_timer.is_interrupting) {
- SEND_ERR_RESPONSE(
- msg->mid,
- "Uninstall WASM app failed: app is being interrupted by watchdog.");
- return false;
- }
- /* Exit app queue loop run */
- bh_queue_exit_loop_run(m_data->queue);
- /* Wait for wasm app thread to exit */
- wasm_app_data = (wasm_data *)m_data->internal_data;
- os_thread_join(wasm_app_data->thread_id, NULL);
- cleanup_app_resource(m_data);
- app_manager_post_applets_update_event();
- app_manager_printf("Uninstall WASM app successful!\n");
- #ifdef COLLECT_CODE_COVERAGE
- /* Exit app manager so as to collect code coverage data */
- if (!strcmp(m_name, "__exit_app_manager__")) {
- app_manager_printf("Exit app manager\n");
- bh_queue_exit_loop_run(get_app_manager_queue());
- }
- #endif
- #if VALGRIND_CHECK != 0
- bh_queue_exit_loop_run(get_app_manager_queue());
- #endif
- send_error_response_to_host(msg->mid, DELETED_2_02, NULL); /* DELETED */
- return true;
- }
- static bool
- wasm_app_module_handle_host_url(void *queue_msg)
- {
- /* TODO: implement in future */
- app_manager_printf("App handles host url address %d\n",
- (int)(uintptr_t)queue_msg);
- return false;
- }
- static module_data *
- wasm_app_module_get_module_data(void *inst)
- {
- wasm_module_inst_t module_inst = (wasm_module_inst_t)inst;
- return (module_data *)wasm_runtime_get_custom_data(module_inst);
- }
- static void
- wasm_app_module_watchdog_kill(module_data *m_data)
- {
- /* TODO: implement in future */
- app_manager_printf("Watchdog kills app: %s\n", m_data->module_name);
- return;
- }
- bool
- wasm_register_msg_callback(int message_type,
- message_type_handler_t message_handler)
- {
- int i;
- int freeslot = -1;
- for (i = 0; i < Max_Msg_Callback; i++) {
- /* replace handler for the same event registered */
- if (g_msg_type[i] == message_type)
- break;
- if (g_msg_callbacks[i] == NULL && freeslot == -1)
- freeslot = i;
- }
- if (i != Max_Msg_Callback)
- g_msg_callbacks[i] = message_handler;
- else if (freeslot != -1) {
- g_msg_callbacks[freeslot] = message_handler;
- g_msg_type[freeslot] = message_type;
- }
- else
- return false;
- return true;
- }
- bool
- wasm_register_cleanup_callback(resource_cleanup_handler_t handler)
- {
- int i;
- for (i = 0; i < Max_Cleanup_Callback; i++) {
- if (g_cleanup_callbacks[i] == NULL) {
- g_cleanup_callbacks[i] = handler;
- return true;
- }
- }
- return false;
- }
- #define RECV_INTEGER(value, next_phase) \
- do { \
- uint8 *p = (uint8 *)&value; \
- p[recv_ctx.size_in_phase++] = ch; \
- if (recv_ctx.size_in_phase == sizeof(value)) { \
- if (sizeof(value) == 4) \
- value = ntohl(value); \
- else if (sizeof(value) == 2) \
- value = ntohs(value); \
- recv_ctx.phase = next_phase; \
- recv_ctx.size_in_phase = 0; \
- } \
- } while (0)
- /* return:
- * 1: whole wasm app arrived
- * 0: one valid byte arrived
- * -1: fail to process the byte arrived, e.g. allocate memory fail
- */
- static bool
- wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size,
- int *received_size)
- {
- uint8 *p;
- int magic;
- package_type_t package_type = Package_Type_Unknown;
- if (recv_ctx.phase == Phase_Req_Ver) {
- recv_ctx.phase = Phase_Req_Ver;
- recv_ctx.size_in_phase = 0;
- recv_ctx.total_received_size = 0;
- }
- recv_ctx.total_received_size++;
- *received_size = recv_ctx.total_received_size;
- if (recv_ctx.phase == Phase_Req_Ver) {
- if (ch != 1 /* REQUES_PACKET_VER from restful_utils.c */)
- return false;
- recv_ctx.phase = Phase_Req_Action;
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Action) {
- recv_ctx.message.request_action = ch;
- recv_ctx.phase = Phase_Req_Fmt;
- recv_ctx.size_in_phase = 0;
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Fmt) {
- RECV_INTEGER(recv_ctx.message.request_fmt, Phase_Req_Mid);
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Mid) {
- RECV_INTEGER(recv_ctx.message.request_mid, Phase_Req_Sender);
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Sender) {
- RECV_INTEGER(recv_ctx.message.request_sender, Phase_Req_Url_Len);
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Url_Len) {
- p = (uint8 *)&recv_ctx.message.request_url_len;
- p[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase
- == sizeof(recv_ctx.message.request_url_len)) {
- recv_ctx.message.request_url_len =
- ntohs(recv_ctx.message.request_url_len);
- recv_ctx.message.request_url =
- APP_MGR_MALLOC(recv_ctx.message.request_url_len + 1);
- if (NULL == recv_ctx.message.request_url) {
- app_manager_printf("Allocate memory failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "allocate memory failed.");
- goto fail;
- }
- memset(recv_ctx.message.request_url, 0,
- recv_ctx.message.request_url_len + 1);
- recv_ctx.phase = Phase_Req_Payload_Len;
- recv_ctx.size_in_phase = 0;
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Payload_Len) {
- RECV_INTEGER(recv_ctx.message.wasm_app_size, Phase_Req_Url);
- return true;
- }
- else if (recv_ctx.phase == Phase_Req_Url) {
- recv_ctx.message.request_url[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase == recv_ctx.message.request_url_len) {
- recv_ctx.phase = Phase_App_Magic;
- recv_ctx.size_in_phase = 0;
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_App_Magic) {
- /* start to receive wasm app magic: bytecode or aot */
- p = (uint8 *)&recv_ctx.message.app_file_magic;
- p[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase == sizeof(recv_ctx.message.app_file_magic)) {
- magic = recv_ctx.message.app_file_magic;
- package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1);
- switch (package_type) {
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- case Wasm_Module_Bytecode:
- recv_ctx.message.app_file.u.bytecode.magic =
- recv_ctx.message.app_file_magic;
- recv_ctx.phase = Phase_Wasm_Version;
- recv_ctx.size_in_phase = 0;
- break;
- #endif
- #if WASM_ENABLE_AOT != 0
- case Wasm_Module_AoT:
- recv_ctx.message.app_file.u.aot.magic =
- recv_ctx.message.app_file_magic;
- recv_ctx.phase = Phase_AOT_Version;
- recv_ctx.size_in_phase = 0;
- break;
- #endif
- default:
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "invalid file format.");
- goto fail;
- }
- }
- return true;
- }
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- else if (recv_ctx.phase == Phase_Wasm_Version) {
- p = (uint8 *)&recv_ctx.message.app_file.u.bytecode.version;
- if (ch == wasm_bytecode_version[recv_ctx.size_in_phase])
- p[recv_ctx.size_in_phase++] = ch;
- else {
- app_manager_printf("Invalid WASM version!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: invalid WASM version.");
- goto fail;
- }
- if (recv_ctx.size_in_phase
- == sizeof(recv_ctx.message.app_file.u.bytecode.version)) {
- recv_ctx.phase = Phase_Wasm_Section_Type;
- recv_ctx.size_in_phase = 0;
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_Wasm_Section_Type) {
- uint8 section_type = ch;
- #if WASM_ENABLE_BULK_MEMORY == 0
- uint8 section_type_max = SECTION_TYPE_DATA;
- #else
- uint8 section_type_max = SECTION_TYPE_DATACOUNT;
- #endif
- if (section_type <= section_type_max) {
- wasm_section_t *new_section;
- if (!(new_section = (wasm_section_t *)APP_MGR_MALLOC(
- sizeof(wasm_section_t)))) {
- app_manager_printf("Allocate memory failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "allocate memory failed.");
- goto fail;
- }
- memset(new_section, 0, sizeof(wasm_section_t));
- new_section->section_type = section_type;
- new_section->next = NULL;
- /* add the section to tail of link list */
- if (NULL == recv_ctx.message.app_file.u.bytecode.sections) {
- recv_ctx.message.app_file.u.bytecode.sections = new_section;
- recv_ctx.message.app_file.u.bytecode.section_end = new_section;
- }
- else {
- recv_ctx.message.app_file.u.bytecode.section_end->next =
- new_section;
- recv_ctx.message.app_file.u.bytecode.section_end = new_section;
- }
- recv_ctx.phase = Phase_Wasm_Section_Size;
- recv_ctx.size_in_phase = 0;
- return true;
- }
- else {
- char error_buf[128];
- app_manager_printf("Invalid wasm section type: %d\n", section_type);
- snprintf(error_buf, sizeof(error_buf),
- "Install WASM app failed: invalid wasm section type %d",
- section_type);
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
- goto fail;
- }
- }
- else if (recv_ctx.phase == Phase_Wasm_Section_Size) {
- /* the last section is the current receiving one */
- wasm_section_t *section =
- recv_ctx.message.app_file.u.bytecode.section_end;
- uint32 byte;
- bh_assert(section);
- byte = ch;
- section->section_body_size |=
- ((byte & 0x7f) << recv_ctx.size_in_phase * 7);
- recv_ctx.size_in_phase++;
- /* check leab128 overflow for uint32 value */
- if (recv_ctx.size_in_phase
- > (sizeof(section->section_body_size) * 8 + 7 - 1) / 7) {
- app_manager_printf("LEB overflow when parsing section size\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "LEB overflow when parsing section size");
- goto fail;
- }
- if ((byte & 0x80) == 0) {
- /* leb128 encoded section size parsed done */
- if (!(section->section_body =
- APP_MGR_MALLOC(section->section_body_size))) {
- app_manager_printf("Allocate memory failed!\n");
- SEND_ERR_RESPONSE(
- recv_ctx.message.request_mid,
- "Install WASM app failed: allocate memory failed");
- goto fail;
- }
- recv_ctx.phase = Phase_Wasm_Section_Content;
- recv_ctx.size_in_phase = 0;
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_Wasm_Section_Content) {
- /* the last section is the current receiving one */
- wasm_section_t *section =
- recv_ctx.message.app_file.u.bytecode.section_end;
- bh_assert(section);
- section->section_body[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase == section->section_body_size) {
- if (recv_ctx.total_received_size == request_total_size) {
- /* whole wasm app received */
- if (module_wasm_app_handle_install_msg(&recv_ctx.message)) {
- APP_MGR_FREE(recv_ctx.message.request_url);
- recv_ctx.message.request_url = NULL;
- memset(&recv_ctx, 0, sizeof(recv_ctx));
- return true;
- }
- else {
- app_manager_printf("Handle install message failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "handle install message failed");
- /**
- * The sections were destroyed inside
- * module_wasm_app_handle_install_msg(),
- * no need to destroy again.
- */
- return false;
- }
- }
- else {
- recv_ctx.phase = Phase_Wasm_Section_Type;
- recv_ctx.size_in_phase = 0;
- return true;
- }
- }
- return true;
- }
- #endif /* end of WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 */
- #if WASM_ENABLE_AOT != 0
- else if (recv_ctx.phase == Phase_AOT_Version) {
- p = (uint8 *)&recv_ctx.message.app_file.u.aot.version;
- if (ch == wasm_aot_version[recv_ctx.size_in_phase])
- p[recv_ctx.size_in_phase++] = ch;
- else {
- app_manager_printf("Invalid AOT version!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: invalid AOT version");
- goto fail;
- }
- if (recv_ctx.size_in_phase
- == sizeof(recv_ctx.message.app_file.u.aot.version)) {
- recv_ctx.phase = Phase_AOT_Section_ID;
- recv_ctx.size_in_phase = 0;
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_AOT_Section_ID) {
- aot_section_t *cur_section;
- uint32 aot_file_cur_offset =
- recv_ctx.total_received_size - 1
- - 18 /* Request fixed part */ - recv_ctx.message.request_url_len;
- if (recv_ctx.size_in_phase == 0) {
- /* Skip paddings */
- if (aot_file_cur_offset % 4)
- return true;
- if (!(cur_section =
- (aot_section_t *)APP_MGR_MALLOC(sizeof(aot_section_t)))) {
- app_manager_printf("Allocate memory failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "allocate memory failed");
- goto fail;
- }
- memset(cur_section, 0, sizeof(aot_section_t));
- /* add the section to tail of link list */
- if (NULL == recv_ctx.message.app_file.u.aot.sections) {
- recv_ctx.message.app_file.u.aot.sections = cur_section;
- recv_ctx.message.app_file.u.aot.section_end = cur_section;
- }
- else {
- recv_ctx.message.app_file.u.aot.section_end->next = cur_section;
- recv_ctx.message.app_file.u.aot.section_end = cur_section;
- }
- }
- else {
- cur_section = recv_ctx.message.app_file.u.aot.section_end;
- bh_assert(cur_section);
- }
- p = (uint8 *)&cur_section->section_type;
- p[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase == sizeof(cur_section->section_type)) {
- /* Notes: integers are always little endian encoded in AOT file */
- if (!is_little_endian())
- exchange_uint32(p);
- if (cur_section->section_type < AOT_SECTION_TYPE_SIGANATURE
- || cur_section->section_type == AOT_SECTION_TYPE_CUSTOM) {
- recv_ctx.phase = Phase_AOT_Section_Size;
- recv_ctx.size_in_phase = 0;
- }
- else {
- char error_buf[128];
- app_manager_printf("Invalid AOT section id: %d\n",
- cur_section->section_type);
- snprintf(error_buf, sizeof(error_buf),
- "Install WASM app failed: invalid AOT section id %d",
- cur_section->section_type);
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
- goto fail;
- }
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_AOT_Section_Size) {
- /* the last section is the current receiving one */
- aot_section_t *section = recv_ctx.message.app_file.u.aot.section_end;
- bh_assert(section);
- p = (uint8 *)§ion->section_body_size;
- p[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase == sizeof(section->section_body_size)) {
- /* Notes: integers are always little endian encoded in AOT file */
- if (!is_little_endian())
- exchange_uint32(p);
- /* Allocate memory for section body */
- if (section->section_body_size > 0) {
- if (section->section_type == AOT_SECTION_TYPE_TEXT) {
- int map_prot =
- MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
- #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
- || defined(BUILD_TARGET_RISCV64_LP64D) \
- || defined(BUILD_TARGET_RISCV64_LP64)
- /* aot code and data in x86_64 must be in range 0 to 2G due
- to relocation for R_X86_64_32/32S/PC32 */
- int map_flags = MMAP_MAP_32BIT;
- #else
- int map_flags = MMAP_MAP_NONE;
- #endif
- uint64 total_size = (uint64)section->section_body_size
- + aot_get_plt_table_size();
- total_size = (total_size + 3) & ~((uint64)3);
- if (total_size >= UINT32_MAX
- || !(section->section_body =
- os_mmap(NULL, (uint32)total_size, map_prot,
- map_flags, os_get_invalid_handle()))) {
- app_manager_printf(
- "Allocate executable memory failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "allocate memory failed");
- goto fail;
- }
- #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
- /* address must be in the first 2 Gigabytes of
- the process address space */
- bh_assert((uintptr_t)section->section_body < INT32_MAX);
- #endif
- }
- else {
- if (!(section->section_body =
- APP_MGR_MALLOC(section->section_body_size))) {
- app_manager_printf("Allocate memory failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "allocate memory failed");
- goto fail;
- }
- }
- }
- recv_ctx.phase = Phase_AOT_Section_Content;
- recv_ctx.size_in_phase = 0;
- }
- return true;
- }
- else if (recv_ctx.phase == Phase_AOT_Section_Content) {
- /* the last section is the current receiving one */
- aot_section_t *section = recv_ctx.message.app_file.u.aot.section_end;
- bh_assert(section && section->section_body);
- section->section_body[recv_ctx.size_in_phase++] = ch;
- if (recv_ctx.size_in_phase == section->section_body_size) {
- if (section->section_type == AOT_SECTION_TYPE_TEXT) {
- uint32 total_size =
- section->section_body_size + aot_get_plt_table_size();
- total_size = (total_size + 3) & ~3;
- if (total_size > section->section_body_size) {
- memset(section->section_body + section->section_body_size,
- 0, total_size - section->section_body_size);
- section->section_body_size = total_size;
- }
- }
- if (recv_ctx.total_received_size == request_total_size) {
- /* whole aot file received */
- if (module_wasm_app_handle_install_msg(&recv_ctx.message)) {
- APP_MGR_FREE(recv_ctx.message.request_url);
- recv_ctx.message.request_url = NULL;
- memset(&recv_ctx, 0, sizeof(recv_ctx));
- return true;
- }
- else {
- app_manager_printf("Handle install message failed!\n");
- SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
- "Install WASM app failed: "
- "handle install message failed");
- /**
- * The sections were destroyed inside
- * module_wasm_app_handle_install_msg(),
- * no need to destroy again.
- */
- return false;
- }
- }
- else {
- recv_ctx.phase = Phase_AOT_Section_ID;
- recv_ctx.size_in_phase = 0;
- return true;
- }
- }
- return true;
- }
- #endif /* end of WASM_ENABLE_AOT != 0 */
- fail:
- /* Restore the package type */
- magic = recv_ctx.message.app_file_magic;
- package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1);
- switch (package_type) {
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- case Wasm_Module_Bytecode:
- destroy_all_wasm_sections(
- recv_ctx.message.app_file.u.bytecode.sections);
- break;
- #endif
- #if WASM_ENABLE_AOT != 0
- case Wasm_Module_AoT:
- destroy_all_aot_sections(recv_ctx.message.app_file.u.aot.sections);
- break;
- #endif
- default:
- break;
- }
- if (recv_ctx.message.request_url != NULL) {
- APP_MGR_FREE(recv_ctx.message.request_url);
- recv_ctx.message.request_url = NULL;
- }
- memset(&recv_ctx, 0, sizeof(recv_ctx));
- return false;
- }
- static bool
- module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message)
- {
- request_t *request = NULL;
- bh_message_t msg;
- request = (request_t *)APP_MGR_MALLOC(sizeof(request_t));
- if (request == NULL)
- return false;
- memset(request, 0, sizeof(*request));
- request->action = message->request_action;
- request->fmt = message->request_fmt;
- request->url = bh_strdup(message->request_url);
- request->sender = ID_HOST;
- request->mid = message->request_mid;
- request->payload_len = sizeof(message->app_file);
- request->payload = APP_MGR_MALLOC(request->payload_len);
- if (request->url == NULL || request->payload == NULL) {
- request_cleaner(request);
- return false;
- }
- /* Request payload is set to wasm_app_file_t struct,
- * but not whole app buffer */
- bh_memcpy_s(request->payload, request->payload_len, &message->app_file,
- request->payload_len);
- /* Since it's a wasm app install request, so directly post to app-mgr's
- * queue. The benefit is that section list can be freed when the msg
- * failed to post to app-mgr's queue. The defect is missing url check. */
- if (!(msg = bh_new_msg(RESTFUL_REQUEST, request, sizeof(*request),
- request_cleaner))) {
- request_cleaner(request);
- return false;
- }
- if (!bh_post_msg2(get_app_manager_queue(), msg))
- return false;
- return true;
- }
- #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
- static void
- destroy_all_wasm_sections(wasm_section_list_t sections)
- {
- wasm_section_t *cur = sections;
- while (cur) {
- wasm_section_t *next = cur->next;
- if (cur->section_body != NULL)
- APP_MGR_FREE(cur->section_body);
- APP_MGR_FREE(cur);
- cur = next;
- }
- }
- static void
- destroy_part_wasm_sections(wasm_section_list_t *p_sections,
- uint8 *section_types, int section_cnt)
- {
- int i;
- for (i = 0; i < section_cnt; i++) {
- uint8 section_type = section_types[i];
- wasm_section_t *cur = *p_sections, *prev = NULL;
- while (cur) {
- wasm_section_t *next = cur->next;
- if (cur->section_type == section_type) {
- if (prev)
- prev->next = next;
- else
- *p_sections = next;
- if (cur->section_body != NULL)
- APP_MGR_FREE(cur->section_body);
- APP_MGR_FREE(cur);
- break;
- }
- else {
- prev = cur;
- cur = next;
- }
- }
- }
- }
- #endif
- #if WASM_ENABLE_AOT != 0
- static void
- destroy_all_aot_sections(aot_section_list_t sections)
- {
- aot_section_t *cur = sections;
- while (cur) {
- aot_section_t *next = cur->next;
- if (cur->section_body != NULL) {
- if (cur->section_type == AOT_SECTION_TYPE_TEXT)
- os_munmap(cur->section_body, cur->section_body_size);
- else
- APP_MGR_FREE(cur->section_body);
- }
- APP_MGR_FREE(cur);
- cur = next;
- }
- }
- static void
- destroy_part_aot_sections(aot_section_list_t *p_sections, uint8 *section_types,
- int section_cnt)
- {
- int i;
- for (i = 0; i < section_cnt; i++) {
- uint8 section_type = section_types[i];
- aot_section_t *cur = *p_sections, *prev = NULL;
- while (cur) {
- aot_section_t *next = cur->next;
- if (cur->section_type == section_type) {
- if (prev)
- prev->next = next;
- else
- *p_sections = next;
- if (cur->section_body != NULL) {
- if (cur->section_type == AOT_SECTION_TYPE_TEXT)
- os_munmap(cur->section_body, cur->section_body_size);
- else
- APP_MGR_FREE(cur->section_body);
- }
- APP_MGR_FREE(cur);
- break;
- }
- else {
- prev = cur;
- cur = next;
- }
- }
- }
- }
- #endif
- #if WASM_ENABLE_LIBC_WASI != 0
- static char wasi_root_dir[PATH_MAX] = { '.' };
- bool
- wasm_set_wasi_root_dir(const char *root_dir)
- {
- char *path, resolved_path[PATH_MAX];
- if (!(path = realpath(root_dir, resolved_path)))
- return false;
- snprintf(wasi_root_dir, sizeof(wasi_root_dir), "%s", path);
- return true;
- }
- const char *
- wasm_get_wasi_root_dir()
- {
- return wasi_root_dir;
- }
- #endif
|