mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-07 07:25:12 +00:00
![wenyongh](/assets/img/avatar_default.png)
* Implement memory profiler, optimize memory usage, modify code indent * Implement memory.grow and limit heap space base offset to 1G; modify iwasm build type to Release and 64 bit by default * Add a new extension library: connection * Fix bug of reading magic number and version in big endian platform * Re-org platform APIs: move most platform APIs from iwasm to shared-lib * Enhance wasm loader to fix some security issues * Fix issue about illegal load of EXC_RETURN into PC on stm32 board * Updates that let a restricted version of the interpreter run in SGX * Enable native/app address validation and conversion for wasm app * Remove wasm_application_exectue_* APIs from wasm_export.h which makes confused * Refine binary size and fix several minor issues Optimize interpreter LOAD/STORE opcodes to decrease the binary size Fix issues when using iwasm library: _bh_log undefined, bh_memory.h not found Remove unused _stdin/_stdout/_stderr global variables resolve in libc wrapper Add macros of global heap size, stack size, heap size for Zephyr main.c Clear compile warning of wasm_application.c * Add more strict security checks for libc wrapper API's * Use one libc wrapper copy for sgx and other platforms; remove bh_printf macro for other platform header files * Enhance security of libc strcpy/sprintf wrapper function * Fix issue of call native for x86_64/arm/mips, add module inst parameter for native wrapper functions * Remove get_module_inst() and fix issue of call native * Refine wgl lib: remove module_inst parameter from widget functions; move function index check to runtime instantiate * Refine interpreter call native process, refine memory boudary check * Fix issues of invokeNative function of arm/mips/general version * Add a switch to build simple sample without gui support * Add BUILD_TARGET setting in makefile to replace cpu compiler flags in source code * Re-org shared lib header files, remove unused info; fix compile issues of vxworks * Add build target general * Remove unused files * Update license header * test push * Restore file * Sync up with internal/feature * Sync up with internal/feature * Rename build_wamr_app to build_wasm_app * Fix small issues of README * Enhance malformed wasm file checking Fix issue of print hex int and implement utf8 string check Fix wasi file read/write right issue Fix minor issue of build wasm app doc * Sync up with internal/feature * Sync up with internal/feature: fix interpreter arm issue, fix read leb issue * Sync up with internal/feature * Fix bug of config.h and rename wasi config.h to ssp_config.h * Sync up with internal/feature * Import wamr aot * update document * update document * Update document, disable WASI in 32bit * update document * remove files * update document * Update document * update document * update document * update samples * Sync up with internal repo
350 lines
8.5 KiB
C
350 lines
8.5 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
#include "bi-inc/attr_container.h"
|
|
#include "wa-inc/request.h"
|
|
#include "wa-inc/timer_wasm_app.h"
|
|
#include "bi-inc/shared_utils.h"
|
|
#include "wasm_app.h"
|
|
#include "req_resp_api.h"
|
|
#include "timer_api.h"
|
|
|
|
#define TRANSACTION_TIMEOUT_MS 5000
|
|
|
|
typedef enum {
|
|
Reg_Event, Reg_Request
|
|
} reg_type_t;
|
|
|
|
typedef struct _res_register {
|
|
struct _res_register *next;
|
|
const char * url;
|
|
reg_type_t reg_type;
|
|
void (*request_handler)(request_t *);
|
|
} res_register_t;
|
|
|
|
typedef struct transaction {
|
|
struct transaction *next;
|
|
int mid;
|
|
unsigned int time; /* start time */
|
|
response_handler_f handler;
|
|
void *user_data;
|
|
} transaction_t;
|
|
|
|
static res_register_t * g_resources = NULL;
|
|
|
|
static transaction_t *g_transactions = NULL;
|
|
|
|
static user_timer_t g_trans_timer = NULL;
|
|
|
|
static transaction_t *transaction_find(int mid)
|
|
{
|
|
transaction_t *t = g_transactions;
|
|
|
|
while (t) {
|
|
if (t->mid == mid)
|
|
return t;
|
|
t = t->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* new transaction is added to the tail of the list, so the list
|
|
* is sorted by expiry time naturally.
|
|
*/
|
|
static void transaction_add(transaction_t *trans)
|
|
{
|
|
transaction_t *t;
|
|
|
|
if (g_transactions == NULL) {
|
|
g_transactions = trans;
|
|
return;
|
|
}
|
|
|
|
t = g_transactions;
|
|
while (t) {
|
|
if (t->next == NULL) {
|
|
t->next = trans;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void transaction_remove(transaction_t *trans)
|
|
{
|
|
transaction_t *prev = NULL, *current = g_transactions;
|
|
|
|
while (current) {
|
|
if (current == trans) {
|
|
if (prev == NULL) {
|
|
g_transactions = current->next;
|
|
free(current);
|
|
return;
|
|
}
|
|
prev->next = current->next;
|
|
free(current);
|
|
return;
|
|
}
|
|
prev = current;
|
|
current = current->next;
|
|
}
|
|
}
|
|
|
|
static bool is_event_type(request_t * req)
|
|
{
|
|
return req->action == COAP_EVENT;
|
|
}
|
|
|
|
static bool register_url_handler(const char *url,
|
|
request_handler_f request_handler, reg_type_t reg_type)
|
|
{
|
|
res_register_t * r = g_resources;
|
|
|
|
while (r) {
|
|
if (reg_type == r->reg_type && strcmp(r->url, url) == 0) {
|
|
r->request_handler = request_handler;
|
|
return true;
|
|
}
|
|
r = r->next;
|
|
}
|
|
|
|
r = (res_register_t *) malloc(sizeof(res_register_t));
|
|
if (r == NULL)
|
|
return false;
|
|
|
|
memset(r, 0, sizeof(*r));
|
|
|
|
r->url = strdup(url);
|
|
if (!r->url) {
|
|
free(r);
|
|
return false;
|
|
}
|
|
|
|
r->request_handler = request_handler;
|
|
r->reg_type = reg_type;
|
|
r->next = g_resources;
|
|
g_resources = r;
|
|
|
|
// tell app mgr to route this url to me
|
|
if (reg_type == Reg_Request)
|
|
wasm_register_resource(url);
|
|
else
|
|
wasm_sub_event(url);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool api_register_resource_handler(const char *url,
|
|
request_handler_f request_handler)
|
|
{
|
|
return register_url_handler(url, request_handler, Reg_Request);
|
|
}
|
|
|
|
static void transaction_timeout_handler(user_timer_t timer)
|
|
{
|
|
transaction_t *cur, *expired = NULL;
|
|
unsigned int elpased_ms, now = wasm_get_sys_tick_ms();
|
|
|
|
/*
|
|
* Since he transaction list is sorted by expiry time naturally,
|
|
* we can easily get all expired transactions.
|
|
* */
|
|
cur = g_transactions;
|
|
while (cur) {
|
|
if (now < cur->time)
|
|
elpased_ms = now + (0xFFFFFFFF - cur->time) + 1;
|
|
else
|
|
elpased_ms = now - cur->time;
|
|
|
|
if (elpased_ms >= TRANSACTION_TIMEOUT_MS) {
|
|
g_transactions = cur->next;
|
|
cur->next = expired;
|
|
expired = cur;
|
|
cur = g_transactions;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* call each transaction's handler with response set to NULL */
|
|
cur = expired;
|
|
while (cur) {
|
|
transaction_t *tmp = cur;
|
|
cur->handler(NULL, cur->user_data);
|
|
cur = cur->next;
|
|
free(tmp);
|
|
}
|
|
|
|
/*
|
|
* If the transaction list is not empty, restart the timer according
|
|
* to the first transaction. Otherwise, stop the timer.
|
|
*/
|
|
if (g_transactions != NULL) {
|
|
unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
|
|
if (now < g_transactions->time) {
|
|
elpased_ms = now + (0xFFFFFFFF - g_transactions->time) + 1;
|
|
} else {
|
|
elpased_ms = now - g_transactions->time;
|
|
}
|
|
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
|
|
api_timer_restart(g_trans_timer, ms_to_expiry);
|
|
} else {
|
|
api_timer_cancel(g_trans_timer);
|
|
g_trans_timer = NULL;
|
|
}
|
|
}
|
|
|
|
void api_send_request(request_t * request, response_handler_f response_handler,
|
|
void * user_data)
|
|
{
|
|
int size;
|
|
char *buffer;
|
|
transaction_t *trans;
|
|
|
|
if ((trans = (transaction_t *) malloc(sizeof(transaction_t))) == NULL) {
|
|
printf(
|
|
"send request: allocate memory for request transaction failed!\n");
|
|
return;
|
|
}
|
|
|
|
memset(trans, 0, sizeof(transaction_t));
|
|
trans->handler = response_handler;
|
|
trans->mid = request->mid;
|
|
trans->time = wasm_get_sys_tick_ms();
|
|
trans->user_data = user_data;
|
|
|
|
if ((buffer = pack_request(request, &size)) == NULL) {
|
|
printf("send request: pack request failed!\n");
|
|
free(trans);
|
|
return;
|
|
}
|
|
|
|
transaction_add(trans);
|
|
|
|
/* if the trans is the 1st one, start the timer */
|
|
if (trans == g_transactions) {
|
|
/* assert(g_trans_timer == NULL); */
|
|
if (g_trans_timer == NULL) {
|
|
g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS,
|
|
false,
|
|
true, transaction_timeout_handler);
|
|
}
|
|
}
|
|
|
|
wasm_post_request(buffer, size);
|
|
|
|
free_req_resp_packet(buffer);
|
|
}
|
|
|
|
/*
|
|
*
|
|
* APIs for the native layers to callback for request/response arrived to this app
|
|
*
|
|
*/
|
|
|
|
void on_response(char * buffer, int size)
|
|
{
|
|
response_t response[1];
|
|
transaction_t *trans;
|
|
|
|
if (NULL == unpack_response(buffer, size, response)) {
|
|
printf("unpack response failed\n");
|
|
return;
|
|
}
|
|
|
|
if ((trans = transaction_find(response->mid)) == NULL) {
|
|
printf("cannot find the transaction\n");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* When the 1st transaction get response:
|
|
* 1. If the 2nd trans exist, restart the timer according to its expiry time;
|
|
* 2. Otherwise, stop the timer since there is no more transactions;
|
|
*/
|
|
if (trans == g_transactions) {
|
|
if (trans->next != NULL) {
|
|
unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
|
|
if (now < trans->next->time) {
|
|
elpased_ms = now + (0xFFFFFFFF - trans->next->time) + 1;
|
|
} else {
|
|
elpased_ms = now - trans->next->time;
|
|
}
|
|
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
|
|
api_timer_restart(g_trans_timer, ms_to_expiry);
|
|
} else {
|
|
api_timer_cancel(g_trans_timer);
|
|
g_trans_timer = NULL;
|
|
}
|
|
}
|
|
|
|
trans->handler(response, trans->user_data);
|
|
transaction_remove(trans);
|
|
}
|
|
|
|
void on_request(char *buffer, int size)
|
|
{
|
|
request_t request[1];
|
|
bool is_event;
|
|
res_register_t *r = g_resources;
|
|
|
|
if (NULL == unpack_request(buffer, size, request)) {
|
|
printf("unpack request failed\n");
|
|
return;
|
|
}
|
|
|
|
is_event = is_event_type(request);
|
|
|
|
while (r) {
|
|
if ((is_event && r->reg_type == Reg_Event)
|
|
|| (!is_event && r->reg_type == Reg_Request)) {
|
|
if (check_url_start(request->url, strlen(request->url), r->url)
|
|
> 0) {
|
|
r->request_handler(request);
|
|
return;
|
|
}
|
|
}
|
|
|
|
r = r->next;
|
|
}
|
|
|
|
printf("on_request: exit. no service handler\n");
|
|
}
|
|
|
|
void api_response_send(response_t *response)
|
|
{
|
|
int size;
|
|
char * buffer = pack_response(response, &size);
|
|
if (buffer == NULL)
|
|
return;
|
|
|
|
wasm_response_send(buffer, size);
|
|
free_req_resp_packet(buffer);
|
|
}
|
|
|
|
/// event api
|
|
|
|
bool api_publish_event(const char *url, int fmt, void *payload, int payload_len)
|
|
{
|
|
int size;
|
|
request_t request[1];
|
|
init_request(request, (char *)url, COAP_EVENT, fmt, payload, payload_len);
|
|
char * buffer = pack_request(request, &size);
|
|
if (buffer == NULL)
|
|
return false;
|
|
wasm_post_request(buffer, size);
|
|
|
|
free_req_resp_packet(buffer);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool api_subscribe_event(const char * url, request_handler_f handler)
|
|
{
|
|
return register_url_handler(url, handler, Reg_Event);
|
|
}
|
|
|