Import app manager, samples and test-tools
260
README.md
|
@ -1,17 +1,17 @@
|
|||
WebAssembly Micro Runtime
|
||||
=========================
|
||||
WebAssembly Micro Runtime (WAMR) is standalone WebAssembly (WASM) runtime designed for a small footprint. It includes:
|
||||
WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime designed for a small footprint. It includes:
|
||||
- A WebAssembly (WASM) VM core
|
||||
- The supporting APIs for the WASM applications (code is available but compilation depends on the app manager component)
|
||||
- A mechanism for dynamic management of the WASM application (Not available on Github yet. To be released soon)
|
||||
|
||||
Why should you use a WASM runtime out of your browser? There are a few points where this might be meaningful:
|
||||
1. WASM is already a LLVM official backend target. That means WASM can run any programming languages which can be compiled to LLVM IR. It is a huge advantage compared to language bound runtimes like JS or Lua.
|
||||
2. WASM is an open standard and it is fast becoming supported by the whole web ecosystem.
|
||||
3. WASM is designed to be very friendly for compiling to native binaries and gaining the native speed.
|
||||
4. It can potentially change the development practices. Imagine we can do both the WASM application development and validation in a browser, then just download the WASM binary code onto the target device.
|
||||
5. WASM can work without garbage collection. It is designed to support execution determinics for the time sensitive requirement.
|
||||
6. Maintain the safety goals WASM has of providing a sandboxed execution enviornment for untrusted code. In addition, because WASM is a compilation target, this implies a benefit of being able to target both an execution and security profile that is consistent across popular high-level programming languages.
|
||||
Why should you use a WASM runtime out of your browser? There are a few points where this might be meaningful:
|
||||
1. WASM is already an LLVM official backend target. That means WASM can run any programming languages which can be compiled to LLVM IR. It is a huge advantage compared to language bound runtimes like JS or Lua.
|
||||
2. WASM is an open standard and it is fast becoming supported by the whole web ecosystem.
|
||||
3. WASM is designed to be very friendly for compiling to native binaries and gaining the native speed.
|
||||
4. It can potentially change the development practices. Imagine we can do both the WASM application development and validation in a browser, then just download the WASM binary code onto the target device.
|
||||
5. WASM can work without garbage collection. It is designed to support execution determinics for the time sensitive requirement.
|
||||
6. Maintain the safety goals WASM has of providing a sandboxed execution environment for untrusted code. In addition, because WASM is a compilation target, this implies a benefit of being able to target both an execution and security profile that is consistent across popular high-level programming languages.
|
||||
|
||||
|
||||
|
||||
|
@ -24,7 +24,7 @@ Current Features of WAMR
|
|||
- Provides a mechanism for exporting native API's to WASM applications
|
||||
- Supports the programming of firmware apps in a large range of languages (C/C++/Java/Rust/Go/TypeScript etc.)
|
||||
- App sandbox execution environment on embedded OS
|
||||
- Purely asynchronized programming model
|
||||
- The purely asynchronized programming model
|
||||
- Menu configuration for easy platform integration
|
||||
- Supports micro-service and pub-sub event inter-app communication models
|
||||
- Easy to extend to support remote FW application management from host or cloud
|
||||
|
@ -35,7 +35,7 @@ The application manager component handles the packets that the platform receives
|
|||
|
||||
- The WebAssembly runtime provides the execution environment for WASM applications.
|
||||
|
||||
- The messaging layer can support the API for WASM applications to communicate to each other and also the host environment.
|
||||
- The messaging layer can support the API for WASM applications to communicate with each other and also the host environment.
|
||||
|
||||
- When ahead of time (AOT) compilation is enabled (TODO), the WASM application could be either WASM or a compiled native binary.
|
||||
|
||||
|
@ -88,12 +88,9 @@ git clone https://github.com/emscripten-core/emsdk.git
|
|||
emsdk install latest
|
||||
emsdk activate latest
|
||||
```
|
||||
|
||||
add ```./emsdk_env.sh``` into the path to ease future use, or source it everytime.
|
||||
add ```./emsdk_env.sh``` into the path to ease future use, or source it every time.
|
||||
The Emscripten website provides other installation methods beyond Linux.
|
||||
|
||||
(TODO) The user should copy the app-libs folder into project and include and build.
|
||||
|
||||
You can write a simple ```test.c``` as the first sample.
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
|
@ -101,23 +98,23 @@ You can write a simple ```test.c``` as the first sample.
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *buf;
|
||||
char *buf;
|
||||
|
||||
printf("Hello world!\n");
|
||||
printf("Hello world!\n");
|
||||
|
||||
buf = malloc(1024);
|
||||
if (!buf) {
|
||||
printf("malloc buf failed\n");
|
||||
return -1;
|
||||
}
|
||||
buf = malloc(1024);
|
||||
if (!buf) {
|
||||
printf("malloc buf failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("buf ptr: %p\n", buf);
|
||||
printf("buf ptr: %p\n", buf);
|
||||
|
||||
sprintf(buf, "%s", "1234\n");
|
||||
printf("buf: %s", buf);
|
||||
sprintf(buf, "%s", "1234\n");
|
||||
printf("buf: %s", buf);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Use the emcc command below to build the WASM C source code into the WASM binary.
|
||||
|
@ -147,31 +144,43 @@ ninja run
|
|||
|
||||
Embed WAMR into software production
|
||||
=====================================
|
||||
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. To use it in the embedded environment you should embed WAMR into your own software product. WASM provides a set of API's for embedded code to load the WASM module, instantiate the module and invoke a WASM function from a native call.
|
||||
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. To use it in the embedded environment you should embed WAMR into your own software product. WASM provides a set of APIs for embedded code to load the WASM module, instantiate the module and invoke a WASM function from a native call.
|
||||
|
||||
<img src="./doc/pics/embed.PNG" width="60%" height="60%">
|
||||
|
||||
|
||||
A typical WAMR API usage is shown below:
|
||||
A typical WAMR API usage is shown below (some return values checking are ignored):
|
||||
``` C
|
||||
static char global_heap_buf[512 * 1024];
|
||||
|
||||
char *buffer;
|
||||
wasm_module_t module;
|
||||
wasm_module_inst_t inst;
|
||||
wasm_function_inst_t func;
|
||||
wasm_exec_env_t env;
|
||||
uint32 argv[2];
|
||||
|
||||
bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf));
|
||||
wasm_runtime_init();
|
||||
|
||||
buffer = read_wasm_binary_to_buffer(…);
|
||||
module = wasm_runtime_load(buffer, size, err, err_size);
|
||||
inst = wasm_runtime_instantiate(module, 0, err, err_size);
|
||||
func = wasm_runtime_lookup_function(inst, "fib", "(i32i32");
|
||||
inst = wasm_runtime_instantiate(module, 0, 0, err, err_size);
|
||||
func = wasm_runtime_lookup_function(inst, "fib", "(i32)i32");
|
||||
env = wasm_runtime_create_exec_env(stack_size);
|
||||
|
||||
argv[0] = 8;
|
||||
if (!wasm_runtime_call_wasm(inst, env, func, 1, argv_buf) ) {
|
||||
wasm_runtime_clear_exception(inst);
|
||||
}
|
||||
wasm_runtime_clear_exception(inst);
|
||||
}
|
||||
/* the return value is stored in argv[0] */
|
||||
printf(“fib function return: %d\n”, argv[0]);
|
||||
|
||||
wasm_runtime_destory_exec_env(env);
|
||||
wasm_runtime_deinstantiate(inst);
|
||||
wasm_runtime_unload(module);
|
||||
wasm_runtime_destroy();
|
||||
bh_memory_destroy();
|
||||
```
|
||||
|
||||
|
||||
|
@ -188,7 +197,7 @@ Built-in application library
|
|||
Built-in API's include Libc APIs, Base library and Extension library reference.
|
||||
|
||||
**Libc APIs**<br/>
|
||||
This is a minimal set of Libc APIs for memory allocation, string manipulation and printing. The header file is located at ```lib/app-libs/libc/lib-base.h```. The current supported API set is listed here:
|
||||
This is a minimal set of Libc APIs for memory allocation, string manipulation and printing. The header file is located at ```lib/app-libs/libc/lib_base.h```. The current supported API set is listed here:
|
||||
``` C
|
||||
void *malloc(size_t size);
|
||||
void *calloc(size_t n, size_t size);
|
||||
|
@ -209,7 +218,7 @@ char *strncpy(char *dest, const char *src, unsigned long n);
|
|||
```
|
||||
|
||||
**Base library**<br/>
|
||||
Basic support for communication, timers, etc is available. You can refer to the header file ```lib/app-libs/base/wasm-app.h``` which contains the definitions for request and response API's, event pub/sub APIs and timer APIs. Please note that these API's require the native implementations.
|
||||
Basic support for communication, timers, etc is available. You can refer to the header file ```lib/app-libs/base/wasm_app.h``` which contains the definitions for request and response API's, event pub/sub APIs and timer APIs. Please note that these API's require the native implementations.
|
||||
The API set is listed below:
|
||||
``` C
|
||||
typedef void(*request_handler_f)(request_t *) ;
|
||||
|
@ -245,7 +254,7 @@ bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg);
|
|||
bool sensor_close(sensor_t sensor);
|
||||
```
|
||||
|
||||
The mechanism of exporting Native API to WASM application
|
||||
The mechanism of exporting native API to WASM application
|
||||
=======================================================
|
||||
|
||||
The basic working flow for WASM application calling into the native API is shown in the following diagram:
|
||||
|
@ -256,14 +265,14 @@ The basic working flow for WASM application calling into the native API is shown
|
|||
WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library.
|
||||
``` C
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
EXPORT_WASM_API(wasm_register_resource),
|
||||
EXPORT_WASM_API(wasm_response_send),
|
||||
EXPORT_WASM_API(wasm_post_request),
|
||||
EXPORT_WASM_API(wasm_sub_event),
|
||||
EXPORT_WASM_API(wasm_create_timer),
|
||||
EXPORT_WASM_API(wasm_timer_set_interval),
|
||||
EXPORT_WASM_API(wasm_timer_cancel),
|
||||
EXPORT_WASM_API(wasm_timer_restart)
|
||||
EXPORT_WASM_API(wasm_register_resource),
|
||||
EXPORT_WASM_API(wasm_response_send),
|
||||
EXPORT_WASM_API(wasm_post_request),
|
||||
EXPORT_WASM_API(wasm_sub_event),
|
||||
EXPORT_WASM_API(wasm_create_timer),
|
||||
EXPORT_WASM_API(wasm_timer_set_interval),
|
||||
EXPORT_WASM_API(wasm_timer_cancel),
|
||||
EXPORT_WASM_API(wasm_timer_restart)
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -286,15 +295,15 @@ WAMR implemented a framework for developers to export API's. Below is the proced
|
|||
Declare the API's for your WASM application source project to include.
|
||||
|
||||
**Step 2. Create a source file**<br/>
|
||||
Export the platform API's, for example in ``` products/linux/ext-lib-export.c ```
|
||||
Export the platform API's, for example in ``` products/linux/ext_lib_export.c ```
|
||||
``` C
|
||||
#include "lib-export.h"
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] =
|
||||
{
|
||||
};
|
||||
|
||||
#include "ext-lib-export.h"
|
||||
#include "ext_lib_export.h"
|
||||
```
|
||||
|
||||
**Step 3. Register new APIs**<br/>
|
||||
|
@ -305,15 +314,16 @@ The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function exp
|
|||
```
|
||||
|
||||
Below code example shows how to extend the library to support `customized()`:
|
||||
``` C
|
||||
//lib-export-impl.c
|
||||
|
||||
```
|
||||
//lib_export_impl.c
|
||||
void customized()
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
|
||||
// lib-export-dec.h
|
||||
// lib_export_dec.h
|
||||
#ifndef _LIB_EXPORT_DEC_H_
|
||||
#define _LIB_EXPORT_DEC_H_
|
||||
#ifdef __cplusplus
|
||||
|
@ -328,36 +338,162 @@ void customized();
|
|||
#endif
|
||||
|
||||
|
||||
// ext-lib-export.c
|
||||
#include "lib-export.h"
|
||||
#include "lib-export-dec.h"
|
||||
// ext_lib_export.c
|
||||
#include "lib_export.h"
|
||||
#include "lib_export_dec.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] =
|
||||
{
|
||||
EXPORT_WASM_API(customized)
|
||||
EXPORT_WASM_API(customized)
|
||||
};
|
||||
|
||||
#include "ext-lib-export.h"
|
||||
#include "ext_lib_export.h"
|
||||
```
|
||||
|
||||
Use extended library
|
||||
------------------------
|
||||
In the application source project, it will include the WAMR built-in APIs header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this:
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
#include "lib-export-dec.h" // provided by the platform vendor
|
||||
#include "lib_export_dec.h" // provided by the platform vendor
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int I;
|
||||
char *buf = “abcd”;
|
||||
customized(); // customized API provided by the platform vendor
|
||||
return i;
|
||||
int I;
|
||||
char *buf = “abcd”;
|
||||
customized(); // customized API provided by the platform vendor
|
||||
return i;
|
||||
}
|
||||
```
|
||||
|
||||
Future Goals
|
||||
========================
|
||||
The application manager and related code samples like inter-application communication, application life cycle management, 2D graphic demo and more ...
|
||||
|
||||
Communication programming models
|
||||
=========================
|
||||
WAMR supports two typical communication programming models, the microservice model and the pub/sub model.
|
||||
|
||||
|
||||
Microservice model
|
||||
-------------------------
|
||||
The microservice model is also known as request and response model. One WASM application acts as the server which provides a specific service. Other WASM applications or host/cloud applications request that service and get the response.
|
||||
<img src="./doc/pics/request.PNG" width="60%" height="60%">
|
||||
|
||||
Below is the reference implementation of the server application. It provides room temperature measurement service.
|
||||
|
||||
``` C
|
||||
void on_init()
|
||||
{
|
||||
/* register resource uri */
|
||||
init_resource_register();
|
||||
api_register_resource_handler("/room_temp", room_temp_handler);
|
||||
}
|
||||
|
||||
void on_destroy()
|
||||
{
|
||||
}
|
||||
|
||||
void room_temp_handler(request_t *request)
|
||||
{
|
||||
response_t response[1];
|
||||
attr_container_t *payload;
|
||||
payload = attr_container_create("room_temp payload");
|
||||
if (payload == NULL)
|
||||
return;
|
||||
|
||||
attr_container_set_string(&payload, "temp unit", "centigrade");
|
||||
attr_container_set_int(&payload, "value", 26);
|
||||
|
||||
make_response_for_request(request, response);
|
||||
set_response(response,
|
||||
CONTENT_2_05,
|
||||
FMT_ATTR_CONTAINER,
|
||||
payload,
|
||||
attr_container_get_serialize_length(payload));
|
||||
|
||||
api_response_send(response);
|
||||
attr_container_destroy(payload);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Pub/sub model
|
||||
-------------------------
|
||||
One WASM application acts as the event publisher. It publishes events to notify WASM applications or host/cloud applications which subscribe to the events.
|
||||
|
||||
<img src="./doc/pics/sub.PNG" width="60%" height="60%">
|
||||
|
||||
Below is the reference implementation of the pub application. It utilizes a timer to repeatedly publish an overheat alert event to the subscriber applications. Then the subscriber applications receive the events immediately.
|
||||
|
||||
``` C
|
||||
void on_init(
|
||||
{
|
||||
api_subscribe_event ("alert/overheat", overheat_handler);
|
||||
}
|
||||
|
||||
void on_destroy()
|
||||
{
|
||||
}
|
||||
|
||||
void overheat_handler(request_t *event
|
||||
{
|
||||
printf(“Event: %s\n", event->url);
|
||||
}
|
||||
|
||||
/* Timer callback */
|
||||
void timer_update(user_timer_t timer
|
||||
{
|
||||
attr_container_t *event;
|
||||
printf("Timer update %d\n", num++);
|
||||
|
||||
event = attr_container_create("event");
|
||||
attr_container_set_string(&event,
|
||||
"warning",
|
||||
"temperature is over high");
|
||||
|
||||
api_publish_event("alert/overheat",
|
||||
FMT_ATTR_CONTAINER,
|
||||
event,
|
||||
attr_container_get_serialize_length(event));
|
||||
|
||||
attr_container_destroy(event);
|
||||
}
|
||||
|
||||
void on_init()
|
||||
{
|
||||
user_timer_t timer;
|
||||
timer = api_timer_create(1000, true, true, timer_update);
|
||||
}
|
||||
```
|
||||
|
||||
Samples and demos
|
||||
=========================
|
||||
The simple sample
|
||||
--------
|
||||
Please refer to the ```samples/simple``` folder for samples of WASM application life cyle management and programming models.
|
||||
|
||||
2D graphic user interface with LittlevGL
|
||||
------------------------------------------------
|
||||
This sample demonstrates that a graphic user interface application in WebAssembly integrates the LittlevGL, an open-source embedded 2d graphic library. The sample source code is under ```samples/littlevgl```
|
||||
|
||||
In this sample, the LittlevGL source code is built into the WebAssembly code with the user application source files. The platform interfaces defined by LittlevGL is implemented in the runtime and exported to the application through the declarations from source "ext_lib_export.c" as below:
|
||||
|
||||
EXPORT_WASM_API(display_init),
|
||||
EXPORT_WASM_API(display_input_read),
|
||||
EXPORT_WASM_API(display_flush),
|
||||
EXPORT_WASM_API(display_fill),
|
||||
EXPORT_WASM_API(display_vdb_write),
|
||||
EXPORT_WASM_API(display_map),
|
||||
EXPORT_WASM_API(time_get_ms), };
|
||||
|
||||
The runtime component supports building target for Linux and Zephyr/STM Nucleo board respectively. The beauty of this sample is the WebAssembly application can have identical display and behavior when running from both runtime environments. That implies we can do majority of application validation from desktop environment then load it to the target device as long as two runtime distributions support the same set of application interface.
|
||||
|
||||
|
||||
Below pictures show the WASM application is running on an STM board with an LCD touch panel. When users click the blue button, the WASM application increases the counter, and the latest counter value is displayed on the top banner of the touch panel.
|
||||
<img src="./doc/pics/vgl.PNG" width="60%" height="60%">
|
||||
<img src="./doc/pics/vgl2.PNG" width="60%" height="60%">
|
||||
|
||||
The sample also provides the native Linux version of application without the runtime under folder "vgl-native-ui-app". It can help to check differences between the implementations in native and WebAssembly.
|
||||
<img src="./samples/littlevgl/UI.JPG">
|
||||
|
||||
|
||||
Submit issues and request
|
||||
=========================
|
||||
|
|
28
core/app-mgr/app-manager/CMakeLists.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include_directories (.
|
||||
include
|
||||
platform/include
|
||||
platform/${PLATFORM}
|
||||
../classlib/include
|
||||
utils/coap/er-coap
|
||||
utils/coap/extension
|
||||
../external/iwasm/include)
|
||||
|
||||
|
||||
file (GLOB_RECURSE source_all ../../app-manager/*.c)
|
||||
|
||||
add_library (appmgrlib ${source_all})
|
||||
|
406
core/app-mgr/app-manager/app_manager.c
Normal file
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "app_manager.h"
|
||||
#include "app_manager_host.h"
|
||||
#include "bh_queue.h"
|
||||
#include "bh_memory.h"
|
||||
#include "bh_thread.h"
|
||||
#include "attr_container.h"
|
||||
#include "event.h"
|
||||
#include "watchdog.h"
|
||||
#include "coap_ext.h"
|
||||
|
||||
/* Queue of app manager */
|
||||
static bh_queue *g_app_mgr_queue;
|
||||
|
||||
void*
|
||||
get_app_manager_queue()
|
||||
{
|
||||
return g_app_mgr_queue;
|
||||
}
|
||||
|
||||
void app_manager_post_applets_update_event()
|
||||
{
|
||||
module_data *m_data;
|
||||
attr_container_t *attr_cont;
|
||||
request_t msg;
|
||||
int num = 0, i = 0;
|
||||
char *url = "/applets";
|
||||
|
||||
if (!event_is_registered(url))
|
||||
return;
|
||||
|
||||
if (!(attr_cont = attr_container_create("All Applets"))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: allocate memory failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
|
||||
m_data = module_data_list;
|
||||
while (m_data) {
|
||||
num++;
|
||||
m_data = m_data->next;
|
||||
}
|
||||
|
||||
if (!(attr_container_set_int(&attr_cont, "num", num))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m_data = module_data_list;
|
||||
while (m_data) {
|
||||
char buf[32];
|
||||
i++;
|
||||
snprintf(buf, sizeof(buf), "%s%d", "applet", i);
|
||||
if (!(attr_container_set_string(&attr_cont, buf, m_data->module_name))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: set attr applet name key failed.");
|
||||
goto fail;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%d", "heap", i);
|
||||
if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
|
||||
app_manager_printf(
|
||||
"Post applets update event failed: set attr heap key failed.");
|
||||
goto fail;
|
||||
}
|
||||
m_data = m_data->next;
|
||||
}
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.url = url;
|
||||
msg.action = COAP_EVENT;
|
||||
msg.payload = (char*) attr_cont;
|
||||
send_request_to_host(&msg);
|
||||
|
||||
app_manager_printf("Post applets update event success!\n");
|
||||
attr_container_dump(attr_cont);
|
||||
|
||||
fail: vm_mutex_unlock(&module_data_list_lock);
|
||||
attr_container_destroy(attr_cont);
|
||||
}
|
||||
|
||||
static int get_applets_count()
|
||||
{
|
||||
module_data *m_data;
|
||||
int num = 0;
|
||||
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
|
||||
m_data = module_data_list;
|
||||
while (m_data) {
|
||||
num++;
|
||||
m_data = m_data->next;
|
||||
}
|
||||
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Query fw apps info if name = NULL, otherwise query specify app */
|
||||
static bool app_manager_query_applets(request_t *msg, const char *name)
|
||||
{
|
||||
module_data *m_data;
|
||||
attr_container_t *attr_cont;
|
||||
int num = 0, i = 0, len;
|
||||
bool ret = false, found = false;
|
||||
response_t response[1] = { 0 };
|
||||
|
||||
attr_cont = attr_container_create("Applets Info");
|
||||
if (!attr_cont) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: allocate memory failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
|
||||
m_data = module_data_list;
|
||||
while (m_data) {
|
||||
num++;
|
||||
m_data = m_data->next;
|
||||
}
|
||||
|
||||
if (name == NULL && !(attr_container_set_int(&attr_cont, "num", num))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
m_data = module_data_list;
|
||||
while (m_data) {
|
||||
char buf[32];
|
||||
|
||||
if (name == NULL) {
|
||||
i++;
|
||||
snprintf(buf, sizeof(buf), "%s%d", "applet", i);
|
||||
if (!(attr_container_set_string(&attr_cont, buf,
|
||||
m_data->module_name))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%d", "heap", i);
|
||||
if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applets failed: set attr container heap key failed.");
|
||||
goto fail;
|
||||
}
|
||||
} else if (!strcmp(name, m_data->module_name)) {
|
||||
found = true;
|
||||
if (!(attr_container_set_string(&attr_cont, "name",
|
||||
m_data->module_name))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applet failed: set attr container key failed.");
|
||||
goto fail;
|
||||
}
|
||||
if (!(attr_container_set_int(&attr_cont, "heap", m_data->heap_size))) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applet failed: set attr container heap key failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
m_data = m_data->next;
|
||||
}
|
||||
|
||||
if (name != NULL && !found) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Query Applet failed: the app is not found.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
len = attr_container_get_serialize_length(attr_cont);
|
||||
|
||||
make_response_for_request(msg, response);
|
||||
set_response(response, CONTENT_2_05,
|
||||
FMT_ATTR_CONTAINER, (char*) attr_cont, len);
|
||||
send_response_to_host(response);
|
||||
|
||||
ret = true;
|
||||
app_manager_printf("Query Applets success!\n");
|
||||
attr_container_dump(attr_cont);
|
||||
|
||||
fail: vm_mutex_unlock(&module_data_list_lock);
|
||||
attr_container_destroy(attr_cont);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void applet_mgt_reqeust_handler(request_t *request, void *unused)
|
||||
{
|
||||
bh_message_t msg;
|
||||
/* deep copy, but not use app self heap, but use global heap */
|
||||
request_t *req = clone_request(request);
|
||||
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
msg = bh_new_msg(RESTFUL_REQUEST, req, sizeof(*req), request_cleaner);
|
||||
if (!msg) {
|
||||
request_cleaner(req);
|
||||
return;
|
||||
}
|
||||
|
||||
bh_post_msg2(get_app_manager_queue(), msg);
|
||||
}
|
||||
|
||||
/* return -1 for error */
|
||||
static int get_module_type(char *kv_str)
|
||||
{
|
||||
int module_type = -1;
|
||||
char type_str[8] = { 0 };
|
||||
|
||||
find_key_value(kv_str, strlen(kv_str), "type", type_str,
|
||||
sizeof(type_str) - 1, '&');
|
||||
|
||||
if (strlen(type_str) == 0)
|
||||
module_type = Module_WASM_App;
|
||||
else if (strcmp(type_str, "jeff") == 0)
|
||||
module_type = Module_Jeff;
|
||||
else if (strcmp(type_str, "wasm") == 0)
|
||||
module_type = Module_WASM_App;
|
||||
else if (strcmp(type_str, "wasmlib") == 0)
|
||||
module_type = Module_WASM_Lib;
|
||||
|
||||
return module_type;
|
||||
}
|
||||
|
||||
#define APP_NAME_MAX_LEN 128
|
||||
|
||||
/* Queue callback of App Manager */
|
||||
|
||||
static void app_manager_queue_callback(void *message)
|
||||
{
|
||||
request_t *request = (request_t *) bh_message_payload((bh_message_t)message);
|
||||
int mid = request->mid, module_type, offset;
|
||||
|
||||
if ((offset = check_url_start(request->url, strlen(request->url), "/applet"))
|
||||
> 0) {
|
||||
module_type = get_module_type(request->url + offset);
|
||||
|
||||
if (module_type == -1) {
|
||||
SEND_ERR_RESPONSE(mid,
|
||||
"Applet Management failed: invalid module type.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Install Applet */
|
||||
if (request->action == COAP_PUT) {
|
||||
if (get_applets_count() >= MAX_APP_INSTALLATIONS) {
|
||||
SEND_ERR_RESPONSE(mid,
|
||||
"Install Applet failed: exceed max app installations.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!request->payload) {
|
||||
SEND_ERR_RESPONSE(mid,
|
||||
"Install Applet failed: invalid payload.");
|
||||
goto fail;
|
||||
}
|
||||
if (g_module_interfaces[module_type]
|
||||
&& g_module_interfaces[module_type]->module_install) {
|
||||
if (!g_module_interfaces[module_type]->module_install(request))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
/* Uninstall Applet */
|
||||
else if (request->action == COAP_DELETE) {
|
||||
module_type = get_module_type(request->url + offset);
|
||||
if (module_type == -1) {
|
||||
SEND_ERR_RESPONSE(mid,
|
||||
"Uninstall Applet failed: invalid module type.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (g_module_interfaces[module_type]
|
||||
&& g_module_interfaces[module_type]->module_uninstall) {
|
||||
if (!g_module_interfaces[module_type]->module_uninstall(
|
||||
request))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
/* Query Applets installed */
|
||||
else if (request->action == COAP_GET) {
|
||||
char name[APP_NAME_MAX_LEN] = { 0 };
|
||||
char *properties = request->url + offset;
|
||||
find_key_value(properties, strlen(properties), "name", name,
|
||||
sizeof(name) - 1, '&');
|
||||
if (strlen(name) > 0)
|
||||
app_manager_query_applets(request, name);
|
||||
else
|
||||
app_manager_query_applets(request, NULL);
|
||||
} else {
|
||||
SEND_ERR_RESPONSE(mid, "Invalid request of applet: invalid action");
|
||||
}
|
||||
}
|
||||
/* Event Register/Unregister */
|
||||
else if ((offset = check_url_start(request->url, strlen(request->url),
|
||||
"/event/")) > 0) {
|
||||
char url_buf[256] = { 0 };
|
||||
|
||||
strncpy(url_buf, request->url + offset, sizeof(url_buf) - 1);
|
||||
|
||||
if (!event_handle_event_request(request->action, url_buf, ID_HOST)) {
|
||||
SEND_ERR_RESPONSE(mid, "Handle event request failed.");
|
||||
goto fail;
|
||||
}
|
||||
send_error_response_to_host(mid, CONTENT_2_05, NULL); /* OK */
|
||||
} else {
|
||||
int i;
|
||||
for (i = 0; i < Module_Max; i++) {
|
||||
if (g_module_interfaces[i]
|
||||
&& g_module_interfaces[i]->module_handle_host_url) {
|
||||
if (g_module_interfaces[i]->module_handle_host_url(request))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fail:
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static void module_interfaces_init()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < Module_Max; i++) {
|
||||
if (g_module_interfaces[i] && g_module_interfaces[i]->module_init)
|
||||
g_module_interfaces[i]->module_init();
|
||||
}
|
||||
}
|
||||
|
||||
void app_manager_startup(host_interface *interface)
|
||||
{
|
||||
module_interfaces_init();
|
||||
|
||||
/* Create queue of App Manager */
|
||||
g_app_mgr_queue = bh_queue_create();
|
||||
if (!g_app_mgr_queue)
|
||||
return;
|
||||
|
||||
if (!module_data_list_init())
|
||||
goto fail1;
|
||||
|
||||
if (!watchdog_startup())
|
||||
goto fail2;
|
||||
|
||||
/* Initialize Host */
|
||||
app_manager_host_init(interface);
|
||||
|
||||
am_register_resource("/app/", targeted_app_request_handler, ID_APP_MGR);
|
||||
|
||||
/*/app/ and /event/ are both processed by applet_mgt_reqeust_handler*/
|
||||
am_register_resource("/applet", applet_mgt_reqeust_handler, ID_APP_MGR);
|
||||
am_register_resource("/event/", applet_mgt_reqeust_handler, ID_APP_MGR);
|
||||
|
||||
app_manager_printf("App Manager started.\n");
|
||||
|
||||
/* Enter loop run */
|
||||
bh_queue_enter_loop_run(g_app_mgr_queue, app_manager_queue_callback);
|
||||
|
||||
fail2: module_data_list_destroy();
|
||||
|
||||
fail1: bh_queue_destroy(g_app_mgr_queue);
|
||||
}
|
||||
|
||||
#include "module_config.h"
|
||||
|
||||
module_interface *g_module_interfaces[Module_Max] = {
|
||||
#if ENABLE_MODULE_JEFF != 0
|
||||
&jeff_module_interface,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
#if ENABLE_MODULE_WASM_APP != 0
|
||||
&wasm_app_module_interface,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
#if ENABLE_MODULE_WASM_LIB != 0
|
||||
&wasm_lib_module_interface
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
};
|
107
core/app-mgr/app-manager/app_manager.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_MANAGER_H
|
||||
#define APP_MANAGER_H
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "bh_common.h"
|
||||
#include "bh_queue.h"
|
||||
#include "korp_types.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "native_interface.h"
|
||||
#include "shared_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef __ZEPHYR__
|
||||
#define app_manager_printf printf
|
||||
#else
|
||||
#define app_manager_printf printk
|
||||
#endif
|
||||
|
||||
#define ID_HOST -3
|
||||
#define ID_APP_MGR -2
|
||||
#define ID_NONE (uint32)-1
|
||||
|
||||
#define SEND_ERR_RESPONSE(mid, err_msg) do { \
|
||||
app_manager_printf("%s\n", err_msg); \
|
||||
send_error_response_to_host(mid, INTERNAL_SERVER_ERROR_5_00, err_msg); \
|
||||
} while (0)
|
||||
|
||||
extern module_interface *g_module_interfaces[Module_Max];
|
||||
|
||||
/* Lock of the module data list */
|
||||
extern korp_mutex module_data_list_lock;
|
||||
|
||||
/* Module data list */
|
||||
extern module_data *module_data_list;
|
||||
|
||||
void
|
||||
app_manager_add_module_data(module_data *m_data);
|
||||
|
||||
void
|
||||
app_manager_del_module_data(module_data *m_data);
|
||||
|
||||
bool
|
||||
module_data_list_init();
|
||||
|
||||
void
|
||||
module_data_list_destroy();
|
||||
|
||||
bool
|
||||
app_manager_is_interrupting_module(uint32 module_type);
|
||||
|
||||
void release_module(module_data *m_data);
|
||||
|
||||
void
|
||||
module_data_list_remove(module_data *m_data);
|
||||
|
||||
void*
|
||||
app_manager_timer_create(void (*timer_callback)(void*),
|
||||
watchdog_timer *wd_timer);
|
||||
|
||||
void
|
||||
app_manager_timer_destroy(void *timer);
|
||||
|
||||
void
|
||||
app_manager_timer_start(void *timer, int timeout);
|
||||
|
||||
void
|
||||
app_manager_timer_stop(void *timer);
|
||||
|
||||
watchdog_timer*
|
||||
app_manager_get_wd_timer_from_timer_handle(void *timer);
|
||||
|
||||
int
|
||||
app_manager_signature_verify(const uint8_t *file, unsigned int file_len,
|
||||
const uint8_t *signature, unsigned int sig_size);
|
||||
|
||||
void targeted_app_request_handler(request_t *request, void *unused);
|
||||
|
||||
#if BEIHAI_ENABLE_TOOL_AGENT != 0
|
||||
void *
|
||||
app_manager_get_tool_agent_queue();
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
303
core/app-mgr/app-manager/app_manager_host.c
Normal file
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bh_common.h"
|
||||
#include "korp_types.h"
|
||||
#include "app_manager_host.h"
|
||||
#include "app_manager.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "coap_ext.h"
|
||||
#include "bh_memory.h"
|
||||
#include "bh_thread.h"
|
||||
|
||||
/* host communication interface */
|
||||
static host_interface host_commu;
|
||||
|
||||
/* IMRTLink Two leading bytes */
|
||||
static unsigned char leadings[] = { (unsigned char) 0x12, (unsigned char) 0x34 };
|
||||
|
||||
/* IMRTLink Receiving Phase */
|
||||
typedef enum recv_phase_t {
|
||||
Phase_Non_Start, Phase_Leading, Phase_Type, Phase_Size, Phase_Payload
|
||||
} recv_phase_t;
|
||||
|
||||
/* IMRTLink Receive Context */
|
||||
typedef struct recv_context_t {
|
||||
recv_phase_t phase;
|
||||
bh_link_msg_t message;
|
||||
int size_in_phase;
|
||||
} recv_context_t;
|
||||
|
||||
/* Current IMRTLink receive context */
|
||||
static recv_context_t recv_ctx;
|
||||
|
||||
/* Lock for device write */
|
||||
static korp_mutex host_lock;
|
||||
|
||||
static bool enable_log = false;
|
||||
|
||||
static bool is_little_endian()
|
||||
{
|
||||
long i = 0x01020304;
|
||||
unsigned char* c = (unsigned char*) &i;
|
||||
return (*c == 0x04) ? true : false;
|
||||
}
|
||||
|
||||
static void exchange32(uint8* pData)
|
||||
{
|
||||
uint8 value = *pData;
|
||||
*pData = *(pData + 3);
|
||||
*(pData + 3) = value;
|
||||
|
||||
value = *(pData + 1);
|
||||
*(pData + 1) = *(pData + 2);
|
||||
*(pData + 2) = value;
|
||||
}
|
||||
|
||||
/* return:
|
||||
* 1: complete message received
|
||||
* 0: incomplete message received
|
||||
*/
|
||||
static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
|
||||
{
|
||||
if (ctx->phase == Phase_Non_Start) {
|
||||
ctx->message.payload_size = 0;
|
||||
|
||||
if (ctx->message.payload) {
|
||||
bh_free(ctx->message.payload);
|
||||
ctx->message.payload = NULL;
|
||||
}
|
||||
|
||||
if (ch == leadings[0]) {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got leading 0\n");
|
||||
ctx->phase = Phase_Leading;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Leading) {
|
||||
if (ch == leadings[1]) {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got leading 1\n");
|
||||
ctx->phase = Phase_Type;
|
||||
} else
|
||||
ctx->phase = Phase_Non_Start;
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Type) {
|
||||
if (ctx->size_in_phase++ == 0) {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got type 0\n");
|
||||
ctx->message.message_type = ch;
|
||||
} else {
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got type 1\n");
|
||||
ctx->message.message_type |= (ch << 8);
|
||||
ctx->message.message_type = ntohs(ctx->message.message_type);
|
||||
ctx->phase = Phase_Size;
|
||||
ctx->size_in_phase = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Size) {
|
||||
unsigned char *p = (unsigned char *) &ctx->message.payload_size;
|
||||
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: got payload_size, byte %d\n",
|
||||
ctx->size_in_phase);
|
||||
p[ctx->size_in_phase++] = ch;
|
||||
|
||||
if (ctx->size_in_phase == sizeof(ctx->message.payload_size)) {
|
||||
#ifndef __ZEPHYR__
|
||||
ctx->message.payload_size = ntohl(ctx->message.payload_size);
|
||||
#else
|
||||
if (is_little_endian())
|
||||
exchange32((uint8*)&ctx->message.payload_size);
|
||||
#endif
|
||||
ctx->phase = Phase_Payload;
|
||||
|
||||
if (enable_log)
|
||||
app_manager_printf("##On byte arrive: payload_size: %d\n",
|
||||
ctx->message.payload_size);
|
||||
if (ctx->message.payload) {
|
||||
bh_free(ctx->message.payload);
|
||||
ctx->message.payload = NULL;
|
||||
}
|
||||
|
||||
/* message completion */
|
||||
if (ctx->message.payload_size == 0) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
if (enable_log)
|
||||
app_manager_printf(
|
||||
"##On byte arrive: receive end, payload_size is 0.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ctx->message.payload_size > 1024 * 1024) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->message.message_type != INSTALL_WASM_BYTECODE_APP) {
|
||||
ctx->message.payload = (char *) bh_malloc(
|
||||
ctx->message.payload_size);
|
||||
if (!ctx->message.payload) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->phase = Phase_Payload;
|
||||
ctx->size_in_phase = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if (ctx->phase == Phase_Payload) {
|
||||
if (ctx->message.message_type == INSTALL_WASM_BYTECODE_APP) {
|
||||
int received_size;
|
||||
module_on_install_request_byte_arrive_func module_on_install =
|
||||
g_module_interfaces[Module_WASM_App]->module_on_install;
|
||||
|
||||
ctx->size_in_phase++;
|
||||
|
||||
if (module_on_install != NULL) {
|
||||
if (module_on_install(ch, ctx->message.payload_size,
|
||||
&received_size)) {
|
||||
if (received_size == ctx->message.payload_size) {
|
||||
/* whole wasm app received */
|
||||
ctx->phase = Phase_Non_Start;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* receive or handle fail */
|
||||
ctx->phase = Phase_Non_Start;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ctx->message.payload[ctx->size_in_phase++] = ch;
|
||||
|
||||
if (ctx->size_in_phase == ctx->message.payload_size) {
|
||||
ctx->phase = Phase_Non_Start;
|
||||
if (enable_log)
|
||||
app_manager_printf(
|
||||
"##On byte arrive: receive end, payload_size is %d.\n",
|
||||
ctx->message.payload_size);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aee_host_msg_callback(void *msg, uint16_t msg_len)
|
||||
{
|
||||
unsigned char *p = msg, *p_end = p + msg_len;
|
||||
|
||||
/*app_manager_printf("App Manager receive %d bytes from Host\n", msg_len);*/
|
||||
|
||||
for (; p < p_end; p++) {
|
||||
int ret = on_imrt_link_byte_arrive(*p, &recv_ctx);
|
||||
|
||||
if (ret == 1) {
|
||||
if (recv_ctx.message.payload) {
|
||||
int msg_type = recv_ctx.message.message_type;
|
||||
|
||||
if (msg_type == REQUEST_PACKET) {
|
||||
request_t request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
if (!unpack_request(recv_ctx.message.payload,
|
||||
recv_ctx.message.payload_size, &request))
|
||||
continue;
|
||||
|
||||
request.sender = ID_HOST;
|
||||
|
||||
am_dispatch_request(&request);
|
||||
} else {
|
||||
printf("unexpected host msg type: %d\n", msg_type);
|
||||
}
|
||||
|
||||
bh_free(recv_ctx.message.payload);
|
||||
recv_ctx.message.payload = NULL;
|
||||
recv_ctx.message.payload_size = 0;
|
||||
}
|
||||
|
||||
memset(&recv_ctx, 0, sizeof(recv_ctx));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool app_manager_host_init(host_interface *interface)
|
||||
{
|
||||
vm_mutex_init(&host_lock);
|
||||
memset(&recv_ctx, 0, sizeof(recv_ctx));
|
||||
|
||||
host_commu.init = interface->init;
|
||||
host_commu.send = interface->send;
|
||||
host_commu.destroy = interface->destroy;
|
||||
|
||||
if (host_commu.init != NULL)
|
||||
return host_commu.init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
|
||||
{
|
||||
/* send an IMRT LINK message contains the buf as payload */
|
||||
if (host_commu.send != NULL) {
|
||||
int size_s = size, n;
|
||||
char header[16];
|
||||
|
||||
vm_mutex_lock(&host_lock);
|
||||
/* leading bytes */
|
||||
bh_memcpy_s(header, 2, leadings, 2);
|
||||
|
||||
/* message type */
|
||||
// todo: check if use network byte order!!!
|
||||
*((uint16*) (header + 2)) = htons(msg_type);
|
||||
|
||||
/* payload length */
|
||||
if (is_little_endian())
|
||||
exchange32((uint8*) &size_s);
|
||||
|
||||
bh_memcpy_s(header + 4, 4, &size_s, 4);
|
||||
n = host_commu.send(NULL, header, 8);
|
||||
if (n != 8) {
|
||||
vm_mutex_unlock(&host_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* payload */
|
||||
n = host_commu.send(NULL, buf, size);
|
||||
vm_mutex_unlock(&host_lock);
|
||||
|
||||
printf("sent %d bytes to host\n", n);
|
||||
return n;
|
||||
} else {
|
||||
printf("no send api provided\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
35
core/app-mgr/app-manager/app_manager_host.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _APP_MANAGER_HOST_H_
|
||||
#define _APP_MANAGER_HOST_H_
|
||||
|
||||
#include "wasm_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HOST_MODE_AON 1
|
||||
#define HOST_MODE_UART 2
|
||||
#define HOST_MODE_TEST 3
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
23
core/app-mgr/app-manager/app_mgr.cmake
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set (__APP_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories(${__APP_MGR_DIR})
|
||||
|
||||
|
||||
file (GLOB source_all ${__APP_MGR_DIR}/*.c ${__APP_MGR_DIR}/platform/${TARGET_PLATFORM}/*.c)
|
||||
|
||||
set (APP_MGR_SOURCE ${source_all})
|
||||
|
126
core/app-mgr/app-manager/ble_msg.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
#define BLUETOOTH_INTERFACE_ADVERTISMENT_DATA_LENGTH 31
|
||||
/* ble_device_info */
|
||||
typedef struct ble_device_info {
|
||||
|
||||
/* address type */
|
||||
uint8_t address_type;
|
||||
/* MAC of Device */
|
||||
uint8_t mac[6];
|
||||
/* security level */
|
||||
uint8_t security_level;
|
||||
/* signal strength */
|
||||
int8_t rssi;
|
||||
/* uuid_16_type */
|
||||
int8_t uuid_16_type;
|
||||
/* uuid_32_type */
|
||||
int8_t uuid_32_type;
|
||||
/* uuid_128_type */
|
||||
int8_t uuid_128_type;
|
||||
/* error code */
|
||||
uint8_t error_code;
|
||||
/* scan response length*/
|
||||
uint16_t adv_data_len;
|
||||
/* advertisement data */
|
||||
uint8_t *adv_data;
|
||||
/* scan response length*/
|
||||
uint16_t scan_response_len;
|
||||
/* scan response */
|
||||
uint8_t *scan_response;
|
||||
/* next device */
|
||||
struct ble_device_info *next;
|
||||
/* private data length */
|
||||
int private_data_length;
|
||||
/* private data */
|
||||
uint8_t *private_data;
|
||||
/* value handle*/
|
||||
uint16_t value_handle;
|
||||
/* ccc handle*/
|
||||
uint16_t ccc_handle;
|
||||
|
||||
}ble_device_info;
|
||||
|
||||
/* BLE message sub type */
|
||||
typedef enum BLE_SUB_EVENT_TYPE {
|
||||
BLE_SUB_EVENT_DISCOVERY,
|
||||
BLE_SUB_EVENT_CONNECTED,
|
||||
BLE_SUB_EVENT_DISCONNECTED,
|
||||
BLE_SUB_EVENT_NOTIFICATION,
|
||||
BLE_SUB_EVENT_INDICATION,
|
||||
BLE_SUB_EVENT_PASSKEYENTRY,
|
||||
BLE_SUB_EVENT_SECURITY_LEVEL_CHANGE
|
||||
}BLE_SUB_EVENT_TYPE;
|
||||
|
||||
/* Queue message, for BLE Event */
|
||||
typedef struct bh_queue_ble_sub_msg_t {
|
||||
/* message type, should be one of QUEUE_MSG_TYPE */
|
||||
BLE_SUB_EVENT_TYPE type;
|
||||
/* payload size */
|
||||
/*uint32_t payload_size;*/
|
||||
char payload[1];
|
||||
}bh_queue_ble_sub_msg_t;
|
||||
|
||||
static void
|
||||
app_instance_free_ble_msg(char *msg)
|
||||
{
|
||||
bh_queue_ble_sub_msg_t *ble_msg = (bh_queue_ble_sub_msg_t *)msg;
|
||||
ble_device_info *dev_info;
|
||||
|
||||
dev_info = (ble_device_info *) ble_msg->payload;
|
||||
|
||||
if (dev_info->scan_response != NULL)
|
||||
bh_free(dev_info->scan_response);
|
||||
|
||||
if (dev_info->private_data != NULL)
|
||||
bh_free(dev_info->private_data);
|
||||
|
||||
if (dev_info->adv_data != NULL)
|
||||
bh_free(dev_info->adv_data);
|
||||
|
||||
if (dev_info != NULL)
|
||||
bh_free(dev_info);
|
||||
}
|
||||
|
||||
static void
|
||||
app_instance_queue_free_callback(bh_message_t queue_msg)
|
||||
{
|
||||
|
||||
char * payload = (char *)bh_message_payload(queue_msg);
|
||||
if(payload == NULL)
|
||||
return;
|
||||
|
||||
switch (bh_message_type(queue_msg))
|
||||
{
|
||||
/*
|
||||
case SENSOR_EVENT: {
|
||||
bh_sensor_event_t *sensor_event = (bh_sensor_event_t *) payload;
|
||||
attr_container_t *event = sensor_event->event;
|
||||
attr_container_destroy(event);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case BLE_EVENT: {
|
||||
app_instance_free_ble_msg(payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
15
core/app-mgr/app-manager/coding_rule.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
Coding rules:
|
||||
|
||||
1. module implementation can include the export head files of associated runtime
|
||||
|
||||
2. app manager only call access the module implementation through the interface API
|
||||
|
||||
3. module implementation can call the app manager API from following files:
|
||||
- util.c
|
||||
- message.c
|
||||
|
||||
4. platform API: To define it
|
||||
|
||||
5. Any platform dependent implementation of app manager should be implemented in the
|
||||
platform specific source file, such as app_mgr_zephyr.c
|
||||
|
203
core/app-mgr/app-manager/event.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "event.h"
|
||||
|
||||
#include "app_manager.h"
|
||||
#include "bh_memory.h"
|
||||
#include "coap_ext.h"
|
||||
|
||||
typedef struct _subscribe {
|
||||
struct _subscribe * next;
|
||||
uint32 subscriber_id;
|
||||
} subscribe_t;
|
||||
|
||||
typedef struct _event {
|
||||
struct _event *next;
|
||||
int subscriber_size;
|
||||
subscribe_t * subscribers;
|
||||
char url[1]; /* event url */
|
||||
} event_reg_t;
|
||||
|
||||
event_reg_t *g_events = NULL;
|
||||
|
||||
static bool find_subscriber(event_reg_t * reg, uint32 id, bool remove_found)
|
||||
{
|
||||
subscribe_t* c = reg->subscribers;
|
||||
subscribe_t * prev = NULL;
|
||||
while (c) {
|
||||
subscribe_t * next = c->next;
|
||||
if (c->subscriber_id == id) {
|
||||
if (remove_found) {
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
reg->subscribers = next;
|
||||
|
||||
bh_free(c);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
prev = c;
|
||||
c = next;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool check_url(const char *url)
|
||||
{
|
||||
if (*url == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool am_register_event(const char *url, uint32_t reg_client)
|
||||
{
|
||||
event_reg_t *current = g_events;
|
||||
|
||||
app_manager_printf("am_register_event adding url:(%s)\n", url);
|
||||
|
||||
if (!check_url(url)) {
|
||||
app_manager_printf("am_register_event: invaild url:(%s)\n", url);
|
||||
return false;
|
||||
}
|
||||
while (current) {
|
||||
if (strcmp(url, current->url) == 0)
|
||||
break;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (current == NULL) {
|
||||
if (NULL
|
||||
== (current = (event_reg_t *) bh_malloc(
|
||||
offsetof(event_reg_t, url) + strlen(url) + 1))) {
|
||||
app_manager_printf("am_register_event: malloc fail\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(current, 0, sizeof(event_reg_t));
|
||||
bh_strcpy_s(current->url, strlen(url) + 1, url);
|
||||
current->next = g_events;
|
||||
g_events = current;
|
||||
}
|
||||
|
||||
if (find_subscriber(current, reg_client, false)) {
|
||||
return true;
|
||||
} else {
|
||||
subscribe_t * s = (subscribe_t*) bh_malloc(sizeof(subscribe_t));
|
||||
if (s == NULL)
|
||||
return false;
|
||||
|
||||
memset(s, 0, sizeof(subscribe_t));
|
||||
s->subscriber_id = reg_client;
|
||||
s->next = current->subscribers;
|
||||
current->subscribers = s;
|
||||
app_manager_printf("client: %d registered event (%s)\n", reg_client,
|
||||
url);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// @url: NULL means the client wants to unregister all its subscribed items
|
||||
bool am_unregister_event(const char *url, uint32_t reg_client)
|
||||
{
|
||||
event_reg_t *current = g_events, *pre = NULL;
|
||||
|
||||
while (current != NULL) {
|
||||
if (url == NULL || strcmp(current->url, url) == 0) {
|
||||
event_reg_t * next = current->next;
|
||||
if (find_subscriber(current, reg_client, true)) {
|
||||
app_manager_printf("client: %d deregistered event (%s)\n",
|
||||
reg_client, current->url);
|
||||
}
|
||||
|
||||
// remove the registration if no client subscribe it
|
||||
if (current->subscribers == NULL) {
|
||||
app_manager_printf("unregister for event deleted url:(%s)\n",
|
||||
current->url);
|
||||
if (pre)
|
||||
pre->next = next;
|
||||
else
|
||||
g_events = next;
|
||||
bh_free(current);
|
||||
current = next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pre = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool event_handle_event_request(uint8_t code, const char *event_url,
|
||||
uint32_t reg_client)
|
||||
{
|
||||
if (code == COAP_PUT) { /* register */
|
||||
return am_register_event(event_url, reg_client);
|
||||
} else if (code == COAP_DELETE) { /* unregister */
|
||||
return am_unregister_event(event_url, reg_client);
|
||||
} else {
|
||||
/* invalid request */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void am_publish_event(request_t * event)
|
||||
{
|
||||
bh_assert(event->action == COAP_EVENT);
|
||||
|
||||
event_reg_t *current = g_events;
|
||||
while (current) {
|
||||
if (0 == strcmp(event->url, current->url)) {
|
||||
subscribe_t* c = current->subscribers;
|
||||
while (c) {
|
||||
if (c->subscriber_id == ID_HOST) {
|
||||
send_request_to_host(event);
|
||||
} else {
|
||||
module_request_handler(event, (void *)c->subscriber_id);
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool event_is_registered(const char *event_url)
|
||||
{
|
||||
event_reg_t *current = g_events;
|
||||
|
||||
while (current != NULL) {
|
||||
if (strcmp(current->url, event_url) == 0) {
|
||||
return true;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
52
core/app-mgr/app-manager/event.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
|
||||
#include "bh_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Handle event request from host agent
|
||||
*
|
||||
* @param code the coap packet code
|
||||
* @param event_url the event url
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
event_handle_event_request(uint8_t code, const char *event_url,
|
||||
uint32_t register);
|
||||
|
||||
/**
|
||||
* Test whether the event is registered
|
||||
*
|
||||
* @param event_url the event url
|
||||
*
|
||||
* @return true for registered, false for not registered
|
||||
*/
|
||||
bool
|
||||
event_is_registered(const char *event_url);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_H_ */
|
98
core/app-mgr/app-manager/message.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "app_manager.h"
|
||||
#include "app_manager_host.h"
|
||||
#include "event.h"
|
||||
#include "attr_container.h"
|
||||
#include "bh_memory.h"
|
||||
#include "coap_ext.h"
|
||||
|
||||
#if 0
|
||||
bool send_coap_packet_to_host(coap_packet_t * packet)
|
||||
{
|
||||
int size;
|
||||
uint8_t *buf;
|
||||
|
||||
size = coap_serialize_message_tcp(&packet, &buf);
|
||||
if (!buf || size == 0)
|
||||
return false;
|
||||
|
||||
app_manager_host_send_msg(buf, size);
|
||||
bh_free(buf);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool send_request_to_host(request_t *msg)
|
||||
{
|
||||
if (COAP_EVENT == msg->action && !event_is_registered(msg->url)) {
|
||||
app_manager_printf("Event is not registered\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int size;
|
||||
char * packet = pack_request(msg, &size);
|
||||
if (packet == NULL)
|
||||
return false;
|
||||
|
||||
app_manager_host_send_msg(REQUEST_PACKET, packet, size);
|
||||
|
||||
free_req_resp_packet(packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_response_to_host(response_t *response)
|
||||
{
|
||||
int size;
|
||||
char * packet = pack_response(response, &size);
|
||||
if (packet == NULL)
|
||||
return false;
|
||||
|
||||
app_manager_host_send_msg(RESPONSE_PACKET, packet, size);
|
||||
|
||||
free_req_resp_packet(packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_error_response_to_host(int mid, int status, const char *msg)
|
||||
{
|
||||
int payload_len = 0;
|
||||
attr_container_t *payload = NULL;
|
||||
response_t response[1] = { 0 };
|
||||
|
||||
if (msg) {
|
||||
payload = attr_container_create("");
|
||||
if (payload) {
|
||||
attr_container_set_string(&payload, "error message", msg);
|
||||
payload_len = attr_container_get_serialize_length(payload);
|
||||
}
|
||||
}
|
||||
|
||||
set_response(response, status,
|
||||
FMT_ATTR_CONTAINER, (const char *)payload, payload_len);
|
||||
response->mid = mid;
|
||||
|
||||
send_response_to_host(response);
|
||||
|
||||
if (payload)
|
||||
attr_container_destroy(payload);
|
||||
return true;
|
||||
}
|
||||
|
34
core/app-mgr/app-manager/module_config.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MODULE_CONFIG_H_
|
||||
#define _MODULE_CONFIG_H_
|
||||
|
||||
#define ENABLE_MODULE_JEFF 0
|
||||
#define ENABLE_MODULE_WASM_APP 1
|
||||
#define ENABLE_MODULE_WASM_LIB 1
|
||||
|
||||
#ifdef ENABLE_MODULE_JEFF
|
||||
#include "module_jeff.h"
|
||||
#endif
|
||||
#ifdef ENABLE_MODULE_WASM_APP
|
||||
#include "module_wasm_app.h"
|
||||
#endif
|
||||
#ifdef ENABLE_MODULE_WASM_LIB
|
||||
#include "module_wasm_lib.h"
|
||||
#endif
|
||||
|
||||
#endif /* _MODULE_CONFIG_H_ */
|
1744
core/app-mgr/app-manager/module_jeff.c
Normal file
40
core/app-mgr/app-manager/module_jeff.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MODULE_JEFF_H_
|
||||
#define _MODULE_JEFF_H_
|
||||
|
||||
#include "app_manager.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern module_interface jeff_module_interface;
|
||||
|
||||
/* sensor event */
|
||||
typedef struct bh_sensor_event_t {
|
||||
/* Java sensor object */
|
||||
void *sensor;
|
||||
/* event of attribute container from context core */
|
||||
void *event;
|
||||
} bh_sensor_event_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MODULE_JEFF_H_ */
|
226
core/app-mgr/app-manager/module_utils.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "app_manager.h"
|
||||
#include "app_manager_host.h"
|
||||
#include "bh_queue.h"
|
||||
#include "bh_memory.h"
|
||||
#include "bh_thread.h"
|
||||
#include "attr_container.h"
|
||||
#include "event.h"
|
||||
#include "watchdog.h"
|
||||
#include "coap_ext.h"
|
||||
|
||||
/* Lock of the module data list */
|
||||
korp_mutex module_data_list_lock;
|
||||
|
||||
/* Module data list */
|
||||
module_data *module_data_list;
|
||||
|
||||
bool module_data_list_init()
|
||||
{
|
||||
module_data_list = NULL;
|
||||
return !vm_mutex_init(&module_data_list_lock) ? true : false;
|
||||
}
|
||||
|
||||
void module_data_list_destroy()
|
||||
{
|
||||
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
if (module_data_list) {
|
||||
while (module_data_list) {
|
||||
module_data *p = module_data_list->next;
|
||||
bh_free(module_data_list);
|
||||
module_data_list = p;
|
||||
}
|
||||
}
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
vm_mutex_destroy(&module_data_list_lock);
|
||||
}
|
||||
|
||||
static void module_data_list_add(module_data *m_data)
|
||||
{
|
||||
static uint32 module_id_max = 1;
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
// reserve some special ID
|
||||
// TODO: check the new id is not already occupied!
|
||||
if (module_id_max == 0xFFFFFFF0)
|
||||
module_id_max = 1;
|
||||
m_data->id = module_id_max++;
|
||||
if (!module_data_list) {
|
||||
module_data_list = m_data;
|
||||
} else {
|
||||
/* Set as head */
|
||||
m_data->next = module_data_list;
|
||||
module_data_list = m_data;
|
||||
}
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
}
|
||||
|
||||
void module_data_list_remove(module_data *m_data)
|
||||
{
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
if (module_data_list) {
|
||||
if (module_data_list == m_data)
|
||||
module_data_list = module_data_list->next;
|
||||
else {
|
||||
/* Search and remove it */
|
||||
module_data *p = module_data_list;
|
||||
|
||||
while (p && p->next != m_data)
|
||||
p = p->next;
|
||||
if (p && p->next == m_data)
|
||||
p->next = p->next->next;
|
||||
}
|
||||
}
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
}
|
||||
|
||||
module_data*
|
||||
module_data_list_lookup(const char *module_name)
|
||||
{
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
if (module_data_list) {
|
||||
module_data *p = module_data_list;
|
||||
|
||||
while (p) {
|
||||
/* Search by module name */
|
||||
if (!strcmp(module_name, p->module_name)) {
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
return p;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module_data*
|
||||
module_data_list_lookup_id(unsigned int module_id)
|
||||
{
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
if (module_data_list) {
|
||||
module_data *p = module_data_list;
|
||||
|
||||
while (p) {
|
||||
/* Search by module name */
|
||||
if (module_id == p->id) {
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
return p;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module_data *
|
||||
app_manager_get_module_data(uint32 module_type)
|
||||
{
|
||||
if (g_module_interfaces[module_type]
|
||||
&& g_module_interfaces[module_type]->module_get_module_data)
|
||||
return g_module_interfaces[module_type]->module_get_module_data();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
app_manager_get_module_queue(uint32 module_type)
|
||||
{
|
||||
return app_manager_get_module_data(module_type)->queue;
|
||||
}
|
||||
|
||||
const char*
|
||||
app_manager_get_module_name(uint32 module_type)
|
||||
{
|
||||
return app_manager_get_module_data(module_type)->module_name;
|
||||
}
|
||||
|
||||
unsigned int app_manager_get_module_id(uint32 module_type)
|
||||
{
|
||||
return app_manager_get_module_data(module_type)->id;
|
||||
}
|
||||
|
||||
void*
|
||||
app_manager_get_module_heap(uint32 module_type)
|
||||
{
|
||||
return app_manager_get_module_data(module_type)->heap;
|
||||
}
|
||||
|
||||
module_data*
|
||||
app_manager_lookup_module_data(const char *name)
|
||||
{
|
||||
return module_data_list_lookup(name);
|
||||
}
|
||||
|
||||
void app_manager_add_module_data(module_data *m_data)
|
||||
{
|
||||
module_data_list_add(m_data);
|
||||
}
|
||||
|
||||
void app_manager_del_module_data(module_data *m_data)
|
||||
{
|
||||
module_data_list_remove(m_data);
|
||||
|
||||
release_module(m_data);
|
||||
}
|
||||
|
||||
bool app_manager_is_interrupting_module(uint32 module_type)
|
||||
{
|
||||
return app_manager_get_module_data(module_type)->wd_timer.is_interrupting;
|
||||
}
|
||||
|
||||
extern void destory_module_timer_ctx(unsigned int module_id);
|
||||
|
||||
void release_module(module_data *m_data)
|
||||
{
|
||||
watchdog_timer_destroy(&m_data->wd_timer);
|
||||
|
||||
#ifdef HEAP_ENABLED /* TODO */
|
||||
if(m_data->heap) gc_destroy_for_instance(m_data->heap);
|
||||
#endif
|
||||
|
||||
if (m_data->queue)
|
||||
bh_queue_destroy(m_data->queue);
|
||||
|
||||
m_data->timer_ctx = NULL;
|
||||
|
||||
destory_module_timer_ctx(m_data->id);
|
||||
|
||||
bh_free(m_data);
|
||||
}
|
||||
|
||||
int check_modules_timer_expiry()
|
||||
{
|
||||
vm_mutex_lock(&module_data_list_lock);
|
||||
module_data *p = module_data_list;
|
||||
int ms_to_expiry = -1;
|
||||
|
||||
while (p) {
|
||||
|
||||
int next = get_expiry_ms(p->timer_ctx);
|
||||
if (next != -1) {
|
||||
if (ms_to_expiry == -1 || ms_to_expiry > next)
|
||||
ms_to_expiry = next;
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
vm_mutex_unlock(&module_data_list_lock);
|
||||
return ms_to_expiry;
|
||||
}
|
||||
|
992
core/app-mgr/app-manager/module_wasm_app.c
Normal file
|
@ -0,0 +1,992 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "module_wasm_app.h"
|
||||
|
||||
#include "native_interface.h" /* for request_t type */
|
||||
#include "app_manager_host.h"
|
||||
#include "bh_queue.h"
|
||||
#include "attr_container.h"
|
||||
#include "bh_thread.h"
|
||||
#include "bh_memory.h"
|
||||
#include "coap_ext.h"
|
||||
#include "event.h"
|
||||
#include "watchdog.h"
|
||||
#include "runtime_lib.h"
|
||||
|
||||
/* Wasm app 4 magic bytes */
|
||||
static unsigned char wasm_app_magics[] = { (unsigned char) 0x00,
|
||||
(unsigned char) 0x61, (unsigned char) 0x73, (unsigned char) 0x6d };
|
||||
|
||||
/* Wasm app 4 version bytes */
|
||||
static unsigned char wasm_app_version[] = { (unsigned char) 0x01,
|
||||
(unsigned char) 0x00, (unsigned char) 0x00, (unsigned char) 0x00 };
|
||||
|
||||
/* 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,
|
||||
Phase_Wasm_Magic,
|
||||
Phase_Wasm_Version,
|
||||
Phase_Wasm_Section_Type,
|
||||
Phase_Wasm_Section_Size,
|
||||
Phase_Wasm_Section_Content
|
||||
} wasm_app_install_req_recv_phase_t;
|
||||
|
||||
/* Message for insall wasm app */
|
||||
typedef struct install_wasm_app_msg_t {
|
||||
uint8_t request_version;
|
||||
uint8_t request_action;
|
||||
uint16_t request_fmt;
|
||||
uint32_t request_mid;
|
||||
uint32_t request_sender;
|
||||
uint16_t request_url_len;
|
||||
uint32_t wasm_app_size; /* payload size is just wasm app binary size */
|
||||
char *request_url;
|
||||
wasm_app_file_t wasm_app_binary;
|
||||
} 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 bytecode 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);
|
||||
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);
|
||||
static void destroy_wasm_sections_list(wasm_section_t *sections);
|
||||
static void destroy_wasm_section_from_list(wasm_section_t **sections, int type);
|
||||
|
||||
#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 };
|
||||
|
||||
static unsigned align_uint(unsigned v, unsigned b)
|
||||
{
|
||||
unsigned m = b - 1;
|
||||
return (v + m) & ~m;
|
||||
}
|
||||
|
||||
static void app_instance_queue_callback(void *queue_msg)
|
||||
{
|
||||
uint32 argv[2];
|
||||
wasm_function_inst_t func_onRequest, func_onTimer;
|
||||
|
||||
module_data *m_data = app_manager_get_module_data(Module_WASM_App);
|
||||
wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data;
|
||||
wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
|
||||
int message_type = bh_message_type(queue_msg);
|
||||
|
||||
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 = wasm_runtime_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) {
|
||||
app_manager_printf("Got exception running wasm code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
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(inst, NULL, func_onRequest, 2, argv)) {
|
||||
app_manager_printf("Got exception running wasm code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
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: {
|
||||
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);
|
||||
|
||||
wasm_function_inst_t func_onResponse = wasm_runtime_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) {
|
||||
app_manager_printf("Got exception running wasm code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
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(inst, NULL, func_onResponse, 2, argv)) {
|
||||
app_manager_printf("Got exception running wasm code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
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;
|
||||
}
|
||||
|
||||
case TIMER_EVENT_WASM: {
|
||||
if (bh_message_payload(queue_msg)) {
|
||||
/* Call Timer.callOnTimer() method */
|
||||
func_onTimer = wasm_runtime_lookup_function(inst,
|
||||
"_on_timer_callback", "(i32)");
|
||||
|
||||
if (!func_onTimer) {
|
||||
app_manager_printf("Cannot find function _on_timer_callback\n");
|
||||
break;
|
||||
}
|
||||
unsigned int timer_id = (unsigned int) bh_message_payload(
|
||||
queue_msg);
|
||||
argv[0] = timer_id;
|
||||
if (!wasm_runtime_call_wasm(inst, NULL, func_onTimer, 1, argv)) {
|
||||
app_manager_printf("Got exception running wasm code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
korp_tid thread = wasm_app_data->thread_id;
|
||||
|
||||
/* attach newly created thread to the VM managed instance */
|
||||
if (!wasm_runtime_attach_current_thread(inst, m_data)) {
|
||||
goto fail1;
|
||||
}
|
||||
app_manager_printf("WASM app '%s' started\n", m_data->module_name);
|
||||
|
||||
/* Call app's onInit() method */
|
||||
func_onInit = wasm_runtime_lookup_function(inst, "_on_init", "()");
|
||||
if (!func_onInit) {
|
||||
app_manager_printf("Cannot find function on_init().\n");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
if (!wasm_runtime_call_wasm(inst, NULL, func_onInit, 0, NULL)) {
|
||||
printf("Got exception running WASM code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
wasm_runtime_clear_exception(inst);
|
||||
/* call on_destroy() in case some resources are opened in on_init()
|
||||
* and then exception thrown */
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
/* Enter queue loop run to receive and process applet queue message */
|
||||
bh_queue_enter_loop_run(m_data->queue, app_instance_queue_callback);
|
||||
|
||||
app_manager_printf("App instance main thread exit.\n");
|
||||
|
||||
fail3:
|
||||
/* Call WASM app onDestroy() method if there is */
|
||||
func_onDestroy = wasm_runtime_lookup_function(inst, "_on_destroy", "()");
|
||||
if (func_onDestroy)
|
||||
wasm_runtime_call_wasm(inst, NULL, func_onDestroy, 0, NULL);
|
||||
|
||||
fail2: wasm_runtime_detach_current_thread(inst);
|
||||
|
||||
fail1:
|
||||
vm_thread_detach(thread);
|
||||
vm_thread_exit(NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cleanup_app_resource(module_data *m_data)
|
||||
{
|
||||
int i;
|
||||
wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data;
|
||||
|
||||
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) from list. */
|
||||
destroy_wasm_sections_list(wasm_app_data->sections);
|
||||
|
||||
if (wasm_app_data->wasm_module)
|
||||
wasm_runtime_unload(wasm_app_data->wasm_module);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Initialize WASM VM*/
|
||||
if (!wasm_runtime_init()) {
|
||||
app_manager_printf("WASM runtime environment initialization failed.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
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, wasm_app_aot_file_len, heap_size, timeout, timers,
|
||||
err_size;
|
||||
char *properties;
|
||||
int properties_offset, i;
|
||||
uint8 *wasm_app_aot_file;
|
||||
wasm_app_file_t *wasm_app_file;
|
||||
wasm_data *wasm_app_data;
|
||||
package_type_t package_type;
|
||||
module_data *m_data;
|
||||
wasm_module_t module = NULL;
|
||||
wasm_module_inst_t inst = NULL;
|
||||
char m_name[APP_NAME_MAX_LEN] = { 0 }, timeout_str[MAX_INT_STR_LEN] = { 0 },
|
||||
heap_size_str[MAX_INT_STR_LEN] = { 0 },
|
||||
timers_str[MAX_INT_STR_LEN] = { 0 }, err[256];
|
||||
/* Useless sections after load */
|
||||
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,
|
||||
/*SECTION_TYPE_CODE,*/
|
||||
/*SECTION_TYPE_DATA*/};
|
||||
/* Useless sections after instantiate */
|
||||
uint8 sections2[] = { SECTION_TYPE_DATA };
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check app name */
|
||||
properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
|
||||
bh_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,
|
||||
"Install WASM app failed: invalid app name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (app_manager_lookup_module_data(m_name)) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: app already installed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Judge the app type is AOTed or not */
|
||||
package_type = get_package_type((uint8 *) msg->payload, msg->payload_len);
|
||||
|
||||
/* Load WASM file and instantiate*/
|
||||
if (package_type == Wasm_Module_AoT) {
|
||||
wasm_app_aot_file = (uint8 *) msg->payload;
|
||||
wasm_app_aot_file_len = msg->payload_len;
|
||||
inst = wasm_runtime_load_aot(wasm_app_aot_file, wasm_app_aot_file_len,
|
||||
heap_size, err, err_size);
|
||||
if (!inst) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: load wasm aot binary failed.");
|
||||
return false;
|
||||
}
|
||||
} else if (package_type == Wasm_Module_Bytecode) {
|
||||
wasm_app_file = (wasm_app_file_t *) msg->payload;
|
||||
module = wasm_runtime_load_from_sections(wasm_app_file->sections, err,
|
||||
err_size);
|
||||
if (!module) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: load WASM file failed.");
|
||||
printf("error: %s\n", err);
|
||||
destroy_wasm_sections_list(wasm_app_file->sections);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Destroy useless sections from list after load */
|
||||
for (i = 0; i < sizeof(sections1); i++)
|
||||
destroy_wasm_section_from_list(&wasm_app_file->sections,
|
||||
sections1[i]);
|
||||
|
||||
inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size);
|
||||
if (!inst) {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: instantiate wasm runtime failed.");
|
||||
printf("error: %s\n", err);
|
||||
wasm_runtime_unload(module);
|
||||
destroy_wasm_sections_list(wasm_app_file->sections);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Destroy useless sections from list after instantiate */
|
||||
for (i = 0; i < sizeof(sections2); i++)
|
||||
destroy_wasm_section_from_list(&wasm_app_file->sections,
|
||||
sections2[i]);
|
||||
|
||||
} else {
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: invalid wasm package type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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 = bh_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;
|
||||
wasm_app_data->sections = wasm_app_file->sections;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* create a thread. This thread may not dedicate for this WASM app.
|
||||
WASM app instance needs to attach to one thread */
|
||||
if (vm_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
|
||||
(void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) {
|
||||
module_data_list_remove(m_data);
|
||||
SEND_ERR_RESPONSE(msg->mid,
|
||||
"Install WASM app failed: create app threadf 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);
|
||||
|
||||
wasm_runtime_deinstantiate(inst);
|
||||
|
||||
if (package_type == Wasm_Module_Bytecode)
|
||||
wasm_runtime_unload(module);
|
||||
|
||||
if (package_type == Wasm_Module_Bytecode)
|
||||
destroy_wasm_sections_list(wasm_app_file->sections);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
vm_thread_join(wasm_app_data->thread_id, NULL, -1);
|
||||
|
||||
cleanup_app_resource(m_data);
|
||||
|
||||
app_manager_post_applets_update_event();
|
||||
|
||||
app_manager_printf("Uninstall WASM app successful!\n");
|
||||
|
||||
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) queue_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
static module_data*
|
||||
wasm_app_module_get_module_data(void)
|
||||
{
|
||||
return wasm_runtime_get_current_thread_data();
|
||||
}
|
||||
|
||||
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{ \
|
||||
unsigned char *p = (unsigned char *)&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)
|
||||
{
|
||||
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) {
|
||||
unsigned char *p = (unsigned char *) &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 = bh_malloc(
|
||||
recv_ctx.message.request_url_len + 1);
|
||||
if (NULL == recv_ctx.message.request_url)
|
||||
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_Wasm_Magic;
|
||||
recv_ctx.size_in_phase = 0;
|
||||
}
|
||||
return true;
|
||||
} else if (recv_ctx.phase == Phase_Wasm_Magic) {
|
||||
/* start to receive wasm app binary */
|
||||
unsigned char *p =
|
||||
(unsigned char *) &recv_ctx.message.wasm_app_binary.magic;
|
||||
|
||||
if (ch == wasm_app_magics[recv_ctx.size_in_phase])
|
||||
p[recv_ctx.size_in_phase++] = ch;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
if (recv_ctx.size_in_phase
|
||||
== sizeof(recv_ctx.message.wasm_app_binary.magic)) {
|
||||
recv_ctx.phase = Phase_Wasm_Version;
|
||||
recv_ctx.size_in_phase = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (recv_ctx.phase == Phase_Wasm_Version) {
|
||||
unsigned char *p =
|
||||
(unsigned char *) &recv_ctx.message.wasm_app_binary.version;
|
||||
|
||||
if (ch == wasm_app_version[recv_ctx.size_in_phase])
|
||||
p[recv_ctx.size_in_phase++] = ch;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
if (recv_ctx.size_in_phase
|
||||
== sizeof(recv_ctx.message.wasm_app_binary.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) {
|
||||
wasm_section_t *new_section;
|
||||
|
||||
if (!(new_section = (wasm_section_t *) bh_malloc(sizeof(wasm_section_t))))
|
||||
goto fail;
|
||||
|
||||
memset(new_section, 0, sizeof(wasm_section_t));
|
||||
new_section->section_type = ch;
|
||||
new_section->next = NULL;
|
||||
|
||||
/* add the section to tail of link list */
|
||||
if (NULL == recv_ctx.message.wasm_app_binary.sections) {
|
||||
recv_ctx.message.wasm_app_binary.sections = new_section;
|
||||
recv_ctx.message.wasm_app_binary.section_end = new_section;
|
||||
} else {
|
||||
recv_ctx.message.wasm_app_binary.section_end->next = new_section;
|
||||
recv_ctx.message.wasm_app_binary.section_end = new_section;
|
||||
}
|
||||
|
||||
recv_ctx.phase = Phase_Wasm_Section_Size;
|
||||
recv_ctx.size_in_phase = 0;
|
||||
|
||||
return true;
|
||||
} else if (recv_ctx.phase == Phase_Wasm_Section_Size) {
|
||||
/* the last section is the current receiving one */
|
||||
wasm_section_t *section = recv_ctx.message.wasm_app_binary.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");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((byte & 0x80) == 0) {
|
||||
/* leb128 encoded section size parsed done */
|
||||
if (!(section->section_body = bh_malloc(section->section_body_size)))
|
||||
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.wasm_app_binary.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)) {
|
||||
bh_free(recv_ctx.message.request_url);
|
||||
recv_ctx.message.request_url = NULL;
|
||||
memset(&recv_ctx, 0, sizeof(recv_ctx));
|
||||
return true;
|
||||
} else
|
||||
goto fail;
|
||||
} else {
|
||||
recv_ctx.phase = Phase_Wasm_Section_Type;
|
||||
recv_ctx.size_in_phase = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fail: if (recv_ctx.message.wasm_app_binary.sections != NULL) {
|
||||
destroy_wasm_sections_list(recv_ctx.message.wasm_app_binary.sections);
|
||||
recv_ctx.message.wasm_app_binary.sections = NULL;
|
||||
}
|
||||
|
||||
if (recv_ctx.message.request_url != NULL) {
|
||||
bh_free(recv_ctx.message.request_url);
|
||||
recv_ctx.message.request_url = NULL;
|
||||
}
|
||||
|
||||
recv_ctx.phase = Phase_Req_Ver;
|
||||
recv_ctx.size_in_phase = 0;
|
||||
recv_ctx.total_received_size = 0;
|
||||
|
||||
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 *) bh_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->wasm_app_binary);
|
||||
request->payload = bh_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 */
|
||||
memcpy(request->payload, &message->wasm_app_binary, 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;
|
||||
}
|
||||
|
||||
static void destroy_wasm_sections_list(wasm_section_t *sections)
|
||||
{
|
||||
wasm_section_t *cur = sections;
|
||||
|
||||
/* App-manager-host and module_wasm won't access the
|
||||
* section list concurrently, so need lock to protect. */
|
||||
|
||||
while (cur) {
|
||||
wasm_section_t *next = cur->next;
|
||||
if (cur->section_body != NULL)
|
||||
bh_free(cur->section_body);
|
||||
bh_free(cur);
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void destroy_wasm_section_from_list(wasm_section_t **sections, int type)
|
||||
{
|
||||
wasm_section_t *cur, *prev = NULL;
|
||||
|
||||
/* App-manager-host and module_wasm won't access the
|
||||
* section list concurrently, so need lock to protect. */
|
||||
|
||||
cur = *sections;
|
||||
|
||||
while (cur) {
|
||||
wasm_section_t *next = cur->next;
|
||||
|
||||
if (type == cur->section_type) {
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
*sections = next;
|
||||
|
||||
if (cur->section_body != NULL)
|
||||
bh_free(cur->section_body);
|
||||
bh_free(cur);
|
||||
break;
|
||||
} else {
|
||||
prev = cur;
|
||||
}
|
||||
cur = next;
|
||||
}
|
||||
}
|
95
core/app-mgr/app-manager/module_wasm_app.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MODULE_WASM_APP_H_
|
||||
#define _MODULE_WASM_APP_H_
|
||||
|
||||
#include "bh_queue.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SECTION_TYPE_USER 0
|
||||
#define SECTION_TYPE_TYPE 1
|
||||
#define SECTION_TYPE_IMPORT 2
|
||||
#define SECTION_TYPE_FUNC 3
|
||||
#define SECTION_TYPE_TABLE 4
|
||||
#define SECTION_TYPE_MEMORY 5
|
||||
#define SECTION_TYPE_GLOBAL 6
|
||||
#define SECTION_TYPE_EXPORT 7
|
||||
#define SECTION_TYPE_START 8
|
||||
#define SECTION_TYPE_ELEM 9
|
||||
#define SECTION_TYPE_CODE 10
|
||||
#define SECTION_TYPE_DATA 11
|
||||
|
||||
enum {
|
||||
WASM_Msg_Start = BASE_EVENT_MAX, TIMER_EVENT_WASM, SENSOR_EVENT_WASM,
|
||||
|
||||
WASM_Msg_End = WASM_Msg_Start + 100
|
||||
};
|
||||
|
||||
typedef struct wasm_data {
|
||||
/* for easily access the containing wasm module */
|
||||
wasm_module_t wasm_module;
|
||||
wasm_module_inst_t wasm_module_inst;
|
||||
/* Permissions of the WASM app */
|
||||
char *perms;
|
||||
/*thread list mapped with this WASM module */
|
||||
korp_tid thread_id;
|
||||
/* for easily access the containing module data */
|
||||
module_data* m_data;
|
||||
/* section list of wasm bytecode */
|
||||
wasm_section_list_t sections;
|
||||
} wasm_data;
|
||||
|
||||
/* sensor event */
|
||||
typedef struct _sensor_event_data {
|
||||
uint32 sensor_id;
|
||||
|
||||
int data_fmt;
|
||||
/* event of attribute container from context core */
|
||||
void *data;
|
||||
} sensor_event_data_t;
|
||||
|
||||
/* WASM App File */
|
||||
typedef struct wasm_app_file {
|
||||
/* magics */
|
||||
int magic;
|
||||
/* current version */
|
||||
int version;
|
||||
/* WASM section list */
|
||||
wasm_section_list_t sections;
|
||||
/* Last WASM section in the list */
|
||||
wasm_section_t *section_end;
|
||||
} wasm_app_file_t;
|
||||
|
||||
extern module_interface wasm_app_module_interface;
|
||||
|
||||
typedef void (*message_type_handler_t)(module_data *m_data, bh_message_t msg);
|
||||
extern bool wasm_register_msg_callback(int msg_type,
|
||||
message_type_handler_t message_handler);
|
||||
|
||||
typedef void (*resource_cleanup_handler_t)(uint32 module_id);
|
||||
extern bool wasm_register_cleanup_callback(resource_cleanup_handler_t handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MODULE_WASM_APP_H_ */
|
59
core/app-mgr/app-manager/module_wasm_lib.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "module_wasm_lib.h"
|
||||
|
||||
static bool wasm_lib_module_init(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wasm_lib_module_install(request_t *msg)
|
||||
{
|
||||
(void) msg;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wasm_lib_module_uninstall(request_t *msg)
|
||||
{
|
||||
(void) msg;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void wasm_lib_module_watchdog_kill(module_data *m_data)
|
||||
{
|
||||
(void) m_data;
|
||||
}
|
||||
|
||||
static bool wasm_lib_module_handle_host_url(void *queue_msg)
|
||||
{
|
||||
(void) queue_msg;
|
||||
return false;
|
||||
}
|
||||
|
||||
static module_data*
|
||||
wasm_lib_module_get_module_data(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module_interface wasm_lib_module_interface = { wasm_lib_module_init,
|
||||
wasm_lib_module_install, wasm_lib_module_uninstall,
|
||||
wasm_lib_module_watchdog_kill, wasm_lib_module_handle_host_url,
|
||||
wasm_lib_module_get_module_data,
|
||||
NULL };
|
||||
|
32
core/app-mgr/app-manager/module_wasm_lib.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MODULE_WASM_LIB_H_
|
||||
#define _MODULE_WASM_LIB_H_
|
||||
|
||||
#include "app_manager.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern module_interface wasm_lib_module_interface;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MODULE_WASM_LIB_H_ */
|
54
core/app-mgr/app-manager/platform/linux/app_mgr_linux.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "app_manager.h"
|
||||
|
||||
void*
|
||||
app_manager_timer_create(void (*timer_callback)(void*),
|
||||
watchdog_timer *wd_timer)
|
||||
{
|
||||
/* TODO */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void app_manager_timer_destroy(void *timer)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void app_manager_timer_start(void *timer, int timeout)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void app_manager_timer_stop(void *timer)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
watchdog_timer *
|
||||
app_manager_get_wd_timer_from_timer_handle(void *timer)
|
||||
{
|
||||
/* TODO */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int app_manager_signature_verify(const uint8_t *file, unsigned int file_len,
|
||||
const uint8_t *signature, unsigned int sig_size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
72
core/app-mgr/app-manager/platform/zephyr/app_mgr_zephyr.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "app_manager.h"
|
||||
#include "bh_platform.h"
|
||||
#include "bh_memory.h"
|
||||
#include <autoconf.h>
|
||||
#include <zephyr.h>
|
||||
#include <kernel.h>
|
||||
#if 0
|
||||
#include <sigverify.h>
|
||||
#endif
|
||||
typedef struct k_timer_watchdog {
|
||||
struct k_timer timer;
|
||||
watchdog_timer *wd_timer;
|
||||
} k_timer_watchdog;
|
||||
|
||||
void*
|
||||
app_manager_timer_create(void (*timer_callback)(void*),
|
||||
watchdog_timer *wd_timer)
|
||||
{
|
||||
struct k_timer_watchdog *timer = bh_malloc(sizeof(struct k_timer_watchdog));
|
||||
|
||||
if (timer) {
|
||||
k_timer_init(&timer->timer, (void (*)(struct k_timer*)) timer_callback,
|
||||
NULL);
|
||||
timer->wd_timer = wd_timer;
|
||||
}
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
void app_manager_timer_destroy(void *timer)
|
||||
{
|
||||
bh_free(timer);
|
||||
}
|
||||
|
||||
void app_manager_timer_start(void *timer, int timeout)
|
||||
{
|
||||
k_timer_start(timer, timeout, 0);
|
||||
}
|
||||
|
||||
void app_manager_timer_stop(void *timer)
|
||||
{
|
||||
k_timer_stop(timer);
|
||||
}
|
||||
|
||||
watchdog_timer *
|
||||
app_manager_get_wd_timer_from_timer_handle(void *timer)
|
||||
{
|
||||
return ((k_timer_watchdog*) timer)->wd_timer;
|
||||
}
|
||||
#if 0
|
||||
int app_manager_signature_verify(const uint8_t *file, unsigned int file_len,
|
||||
const uint8_t *signature, unsigned int sig_size)
|
||||
{
|
||||
return signature_verify(file, file_len, signature, sig_size);
|
||||
}
|
||||
#endif
|
214
core/app-mgr/app-manager/resource_reg.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "native_interface.h"
|
||||
#include "shared_utils.h"
|
||||
#include "app_manager.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "attr_container.h"
|
||||
#include "coap_ext.h"
|
||||
|
||||
typedef struct _app_res_register {
|
||||
struct _app_res_register *next;
|
||||
char * url;
|
||||
void (*request_handler)(request_t *, void *);
|
||||
uint32 register_id;
|
||||
} app_res_register_t;
|
||||
|
||||
static app_res_register_t * g_resources = NULL;
|
||||
|
||||
void module_request_handler(request_t *request, void *user_data)
|
||||
{
|
||||
unsigned int mod_id = (unsigned int) user_data;
|
||||
bh_message_t msg;
|
||||
module_data *m_data;
|
||||
request_t *req;
|
||||
|
||||
/* Check module name */
|
||||
m_data = module_data_list_lookup_id(mod_id);
|
||||
if (!m_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_data->wd_timer.is_interrupting) {
|
||||
return;
|
||||
}
|
||||
|
||||
req = clone_request(request);
|
||||
if (!req) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set queue message and send to applet's queue */
|
||||
msg = bh_new_msg(RESTFUL_REQUEST, req, sizeof(*req), request_cleaner);
|
||||
if (!msg) {
|
||||
request_cleaner(req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bh_post_msg2(m_data->queue, msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
app_manager_printf("Send request to app %s success.\n",
|
||||
m_data->module_name);
|
||||
}
|
||||
|
||||
void targeted_app_request_handler(request_t *request, void *unused)
|
||||
{
|
||||
char applet_name[128] = { 0 };
|
||||
int offset;
|
||||
char *url = request->url;
|
||||
module_data *m_data;
|
||||
|
||||
offset = check_url_start(request->url, strlen(request->url), "/app/");
|
||||
|
||||
if (offset <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(applet_name, request->url + offset, sizeof(applet_name) - 1);
|
||||
char *p = strrchr(applet_name, '/');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
} else
|
||||
return;
|
||||
app_manager_printf("Send request to applet: %s\n", applet_name);
|
||||
|
||||
request->url = p + 1;
|
||||
|
||||
/* Check module name */
|
||||
m_data = module_data_list_lookup(applet_name);
|
||||
if (!m_data) {
|
||||
SEND_ERR_RESPONSE(request->mid,
|
||||
"Send request to applet failed: invalid applet name");
|
||||
goto end;
|
||||
}
|
||||
|
||||
module_request_handler(request, (void *)m_data->id);
|
||||
end: request->url = url;
|
||||
|
||||
}
|
||||
|
||||
void am_send_response(response_t *response)
|
||||
{
|
||||
module_data *m_data;
|
||||
|
||||
// if the receiver is not any of modules, just forward it to the host
|
||||
m_data = module_data_list_lookup_id(response->reciever);
|
||||
if (!m_data) {
|
||||
send_response_to_host(response);
|
||||
|
||||
} else {
|
||||
response_t * resp_for_send = clone_response(response);
|
||||
if (!resp_for_send) {
|
||||
return;
|
||||
}
|
||||
|
||||
bh_message_t msg = bh_new_msg(RESTFUL_RESPONSE, resp_for_send,
|
||||
sizeof(*resp_for_send), response_cleaner);
|
||||
if (!msg) {
|
||||
response_cleaner(resp_for_send);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bh_post_msg2(m_data->queue, msg)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * am_dispatch_request(request_t *request)
|
||||
{
|
||||
app_res_register_t *r = g_resources;
|
||||
|
||||
while (r) {
|
||||
if (check_url_start(request->url, strlen(request->url), r->url) > 0) {
|
||||
r->request_handler(request, (void *)r->register_id);
|
||||
return r;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool am_register_resource(const char *url,
|
||||
void (*request_handler)(request_t *, void *), uint32 register_id)
|
||||
{
|
||||
app_res_register_t * r = g_resources;
|
||||
int register_num = 0;
|
||||
|
||||
while (r) {
|
||||
if (strcmp(r->url, url) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r->register_id == register_id)
|
||||
register_num++;
|
||||
|
||||
r = r->next;
|
||||
}
|
||||
|
||||
if (strlen(url) > RESOUCE_EVENT_URL_LEN_MAX)
|
||||
return false;
|
||||
|
||||
if (register_num >= RESOURCE_REGISTRATION_NUM_MAX)
|
||||
return false;
|
||||
|
||||
r = (app_res_register_t *) bh_malloc(sizeof(app_res_register_t));
|
||||
if (r == NULL)
|
||||
return false;
|
||||
|
||||
memset(r, 0, sizeof(*r));
|
||||
r->url = bh_strdup(url);
|
||||
if (r->url == NULL) {
|
||||
bh_free(r);
|
||||
return false;
|
||||
}
|
||||
|
||||
r->request_handler = request_handler;
|
||||
r->next = g_resources;
|
||||
r->register_id = register_id;
|
||||
g_resources = r;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void am_cleanup_registeration(uint32 register_id)
|
||||
{
|
||||
app_res_register_t * r = g_resources;
|
||||
app_res_register_t * prev = NULL;
|
||||
|
||||
while (r) {
|
||||
app_res_register_t *next = r->next;
|
||||
|
||||
if (register_id == r->register_id) {
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
g_resources = next;
|
||||
|
||||
bh_free(r->url);
|
||||
bh_free(r);
|
||||
} else
|
||||
/* if r is freed, should not change prev. Only set prev to r
|
||||
when r isn't freed. */
|
||||
prev = r;
|
||||
|
||||
r = next;
|
||||
}
|
||||
}
|
140
core/app-mgr/app-manager/watchdog.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "watchdog.h"
|
||||
#include "bh_queue.h"
|
||||
#include "bh_thread.h"
|
||||
#include "bh_memory.h"
|
||||
#include "jeff_export.h"
|
||||
|
||||
#define WATCHDOG_THREAD_PRIORITY 5
|
||||
|
||||
/* Queue of watchdog */
|
||||
static bh_queue *watchdog_queue;
|
||||
|
||||
#ifdef WATCHDOG_ENABLED /* TODO */
|
||||
static void watchdog_timer_callback(void *timer)
|
||||
{
|
||||
watchdog_timer *wd_timer = app_manager_get_wd_timer_from_timer_handle(
|
||||
timer);
|
||||
|
||||
watchdog_timer_stop(wd_timer);
|
||||
|
||||
vm_mutex_lock(&wd_timer->lock);
|
||||
|
||||
if (!wd_timer->is_stopped) {
|
||||
|
||||
wd_timer->is_interrupting = true;
|
||||
|
||||
bh_post_msg(watchdog_queue, WD_TIMEOUT, wd_timer->module_data,
|
||||
sizeof(module_data));
|
||||
}
|
||||
|
||||
vm_mutex_unlock(&wd_timer->lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool watchdog_timer_init(module_data *m_data)
|
||||
{
|
||||
#ifdef WATCHDOG_ENABLED /* TODO */
|
||||
watchdog_timer *wd_timer = &m_data->wd_timer;
|
||||
|
||||
if (BH_SUCCESS != vm_mutex_init(&wd_timer->lock))
|
||||
return false;
|
||||
|
||||
if (!(wd_timer->timer_handle =
|
||||
app_manager_timer_create(watchdog_timer_callback, wd_timer))) {
|
||||
vm_mutex_destroy(&wd_timer->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
wd_timer->module_data = m_data;
|
||||
wd_timer->is_interrupting = false;
|
||||
wd_timer->is_stopped = false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void watchdog_timer_destroy(watchdog_timer *wd_timer)
|
||||
{
|
||||
#ifdef WATCHDOG_ENABLED /* TODO */
|
||||
app_manager_timer_destroy(wd_timer->timer_handle);
|
||||
vm_mutex_destroy(&wd_timer->lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void watchdog_timer_start(watchdog_timer *wd_timer)
|
||||
{
|
||||
vm_mutex_lock(&wd_timer->lock);
|
||||
|
||||
wd_timer->is_interrupting = false;
|
||||
wd_timer->is_stopped = false;
|
||||
app_manager_timer_start(wd_timer->timer_handle,
|
||||
wd_timer->module_data->timeout);
|
||||
|
||||
vm_mutex_unlock(&wd_timer->lock);
|
||||
}
|
||||
|
||||
void watchdog_timer_stop(watchdog_timer *wd_timer)
|
||||
{
|
||||
app_manager_timer_stop(wd_timer->timer_handle);
|
||||
}
|
||||
|
||||
#ifdef WATCHDOG_ENABLED /* TODO */
|
||||
static void watchdog_queue_callback(void *queue_msg)
|
||||
{
|
||||
if (bh_message_type(queue_msg) == WD_TIMEOUT) {
|
||||
module_data *m_data = (module_data *) bh_message_payload(queue_msg);
|
||||
if (g_module_interfaces[m_data->module_type]
|
||||
&& g_module_interfaces[m_data->module_type]->module_watchdog_kill) {
|
||||
g_module_interfaces[m_data->module_type]->module_watchdog_kill(
|
||||
m_data);
|
||||
app_manager_post_applets_update_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WATCHDOG_ENABLED /* TODO */
|
||||
static void*
|
||||
watchdog_thread_routine(void *arg)
|
||||
{
|
||||
/* Enter loop run */
|
||||
bh_queue_enter_loop_run(watchdog_queue, watchdog_queue_callback);
|
||||
|
||||
(void) arg;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool watchdog_startup()
|
||||
{
|
||||
if (!(watchdog_queue = bh_queue_create())) {
|
||||
app_manager_printf(
|
||||
"App Manager start failed: create watchdog queue failed.\n");
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
//todo: enable watchdog
|
||||
/* Start watchdog thread */
|
||||
if (!jeff_runtime_create_supervisor_thread_with_prio(watchdog_thread_routine, NULL,
|
||||
WATCHDOG_THREAD_PRIORITY)) {
|
||||
bh_queue_destroy(watchdog_queue);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
49
core/app-mgr/app-manager/watchdog.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _WATCHDOG_H_
|
||||
#define _WATCHDOG_H_
|
||||
|
||||
#include "app_manager.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
watchdog_timer_init(module_data *module_data);
|
||||
|
||||
void
|
||||
watchdog_timer_destroy(watchdog_timer *wd_timer);
|
||||
|
||||
void
|
||||
watchdog_timer_start(watchdog_timer *wd_timer);
|
||||
|
||||
void
|
||||
watchdog_timer_stop(watchdog_timer *wd_timer);
|
||||
|
||||
watchdog_timer*
|
||||
app_manager_get_watchdog_timer(void *timer);
|
||||
|
||||
bool
|
||||
watchdog_startup();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _WATCHDOG_H_ */
|
300
core/app-mgr/app-mgr-shared/app_manager_export.h
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _APP_MANAGER_EXPORT_H_
|
||||
#define _APP_MANAGER_EXPORT_H_
|
||||
|
||||
#include "native_interface.h"
|
||||
#include "shared_utils.h"
|
||||
#include "bh_queue.h"
|
||||
#include "host_link.h"
|
||||
#include "runtime_timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct attr_container_t;
|
||||
|
||||
/* Queue message type */
|
||||
typedef enum QUEUE_MSG_TYPE {
|
||||
COAP_PARSED = LINK_MSG_TYPE_MAX + 1,
|
||||
RESTFUL_REQUEST,
|
||||
RESTFUL_RESPONSE,
|
||||
TIMER_EVENT = 5,
|
||||
SENSOR_EVENT = 6,
|
||||
GPIO_INTERRUPT_EVENT = 7,
|
||||
BLE_EVENT = 8,
|
||||
JDWP_REQUEST = 9,
|
||||
WD_TIMEOUT = 10,
|
||||
BASE_EVENT_MAX = 100
|
||||
|
||||
} QUEUE_MSG_TYPE;
|
||||
|
||||
typedef enum {
|
||||
Module_Jeff, Module_WASM_App, Module_WASM_Lib, Module_Max
|
||||
} Module_Type;
|
||||
|
||||
struct module_data;
|
||||
|
||||
/* Watchdog timer of module */
|
||||
typedef struct watchdog_timer {
|
||||
/* Timer handle of the platform */
|
||||
void *timer_handle;
|
||||
/* Module of the watchdog timer */
|
||||
struct module_data *module_data;
|
||||
/* Lock of the watchdog timer */
|
||||
korp_mutex lock;
|
||||
/* Flag indicates module is being interrupted by watchdog */
|
||||
bool is_interrupting;
|
||||
/* Flag indicates watchdog timer is stopped */
|
||||
bool is_stopped;
|
||||
} watchdog_timer;
|
||||
|
||||
typedef struct module_data {
|
||||
struct module_data *next;
|
||||
|
||||
uint32 id;
|
||||
|
||||
/* Type of the module */
|
||||
Module_Type module_type;
|
||||
|
||||
/* Heap of the module */
|
||||
void *heap;
|
||||
|
||||
/* Heap size of the module */
|
||||
int heap_size;
|
||||
|
||||
/* Module execution timeout in millisecond */
|
||||
int timeout;
|
||||
|
||||
/* Queue of the module */
|
||||
bh_queue *queue;
|
||||
|
||||
/* Watchdog timer of the module*/
|
||||
struct watchdog_timer wd_timer;
|
||||
|
||||
timer_ctx_t timer_ctx;
|
||||
|
||||
/* max timers number app can create */
|
||||
int timers;
|
||||
|
||||
/* Internal data of the module */
|
||||
void *internal_data;
|
||||
|
||||
/* Module name */
|
||||
char module_name[1];
|
||||
} module_data;
|
||||
|
||||
/* Module function types */
|
||||
typedef bool (*module_init_func)(void);
|
||||
typedef bool (*module_install_func)(request_t *msg);
|
||||
typedef bool (*module_uninstall_func)(request_t *msg);
|
||||
typedef void (*module_watchdog_kill_func)(module_data *module_data);
|
||||
typedef bool (*module_handle_host_url_func)(void *queue_msg);
|
||||
typedef module_data *(*module_get_module_data_func)(void);
|
||||
|
||||
/**
|
||||
* @typedef module_on_install_request_byte_arrive_func
|
||||
*
|
||||
* @brief Define the signature of function to handle one byte of
|
||||
* module app install request for struct module_interface.
|
||||
*
|
||||
* @param ch the byte to be received and handled
|
||||
* @param total_size total size of the request
|
||||
* @param received_total_size currently received total size when the function return
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
typedef bool (*module_on_install_request_byte_arrive_func)(uint8 ch,
|
||||
int total_size, int *received_total_size);
|
||||
|
||||
/* Interfaces of each module */
|
||||
typedef struct module_interface {
|
||||
module_init_func module_init;
|
||||
module_install_func module_install;
|
||||
module_uninstall_func module_uninstall;
|
||||
module_watchdog_kill_func module_watchdog_kill;
|
||||
module_handle_host_url_func module_handle_host_url;
|
||||
module_get_module_data_func module_get_module_data;
|
||||
module_on_install_request_byte_arrive_func module_on_install;
|
||||
} module_interface;
|
||||
|
||||
/**
|
||||
* @typedef host_init_func
|
||||
* @brief Define the host initialize callback function signature for
|
||||
* struct host_interface.
|
||||
*
|
||||
* @return true if success, false if fail
|
||||
*/
|
||||
typedef bool (*host_init_func)(void);
|
||||
|
||||
/**
|
||||
* @typedef host_send_fun
|
||||
* @brief Define the host send callback function signature for
|
||||
* struct host_interface.
|
||||
*
|
||||
* @param buf data buffer to send.
|
||||
* @param size size of the data to send.
|
||||
*
|
||||
* @return size of the data sent in bytes
|
||||
*/
|
||||
typedef int (*host_send_fun)(void * ctx, const char *buf, int size);
|
||||
|
||||
/**
|
||||
* @typedef host_destroy_fun
|
||||
* @brief Define the host receive callback function signature for
|
||||
* struct host_interface.
|
||||
*
|
||||
*/
|
||||
typedef void (*host_destroy_fun)();
|
||||
|
||||
/* Interfaces of host communication */
|
||||
typedef struct host_interface {
|
||||
host_init_func init;
|
||||
host_send_fun send;
|
||||
host_destroy_fun destroy;
|
||||
} host_interface;
|
||||
|
||||
/**
|
||||
* Initialize communication with Host
|
||||
*
|
||||
* @param interface host communication interface
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
app_manager_host_init(host_interface *interface);
|
||||
|
||||
/**
|
||||
* Send message to Host
|
||||
*
|
||||
* @param buf buffer to send
|
||||
* @param size size of buffer
|
||||
*
|
||||
* @return size of buffer sent
|
||||
*/
|
||||
|
||||
/* Startup app manager */
|
||||
void
|
||||
app_manager_startup(host_interface *interface);
|
||||
|
||||
/* Get queue of current applet */
|
||||
void *
|
||||
app_manager_get_module_queue(uint32 module_type);
|
||||
|
||||
/* Get applet name of current applet */
|
||||
const char *
|
||||
app_manager_get_module_name(uint32 module_type);
|
||||
|
||||
/* Get heap of current applet */
|
||||
void *
|
||||
app_manager_get_module_heap(uint32 module_type);
|
||||
|
||||
void*
|
||||
get_app_manager_queue();
|
||||
|
||||
module_data*
|
||||
app_manager_get_module_data(uint32 module_type);
|
||||
|
||||
unsigned int
|
||||
app_manager_get_module_id(uint32 module_type);
|
||||
|
||||
module_data*
|
||||
app_manager_lookup_module_data(const char *name);
|
||||
|
||||
module_data*
|
||||
module_data_list_lookup(const char *module_name);
|
||||
|
||||
module_data*
|
||||
module_data_list_lookup_id(unsigned int module_id);
|
||||
|
||||
void
|
||||
app_manager_post_applets_update_event();
|
||||
|
||||
bool
|
||||
am_register_resource(const char *url,
|
||||
void (*request_handler)(request_t *, void *), uint32 register_id);
|
||||
|
||||
void am_cleanup_registeration(uint32 register_id);
|
||||
|
||||
bool
|
||||
am_register_event(const char *url, uint32_t reg_client);
|
||||
|
||||
bool
|
||||
am_unregister_event(const char *url, uint32_t reg_client);
|
||||
|
||||
void am_publish_event(request_t * event);
|
||||
|
||||
void * am_dispatch_request(request_t *request);
|
||||
|
||||
void am_send_response(response_t *response);
|
||||
|
||||
void module_request_handler(request_t *request, void *user_data);
|
||||
|
||||
/**
|
||||
* Send request message to host
|
||||
*
|
||||
* @param msg the request or event message.
|
||||
* It is event when msg->action==COAP_EVENT
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
send_request_to_host(request_t *msg);
|
||||
|
||||
/**
|
||||
* Send response message to host
|
||||
*
|
||||
* @param msg the response message
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
send_response_to_host(response_t *msg);
|
||||
|
||||
/**
|
||||
* Send response with mid and code to host
|
||||
*
|
||||
* @param mid the message id of response
|
||||
* @param code the code/status of response
|
||||
* @param msg the detailed message
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
bool
|
||||
send_error_response_to_host(int mid, int code, const char *msg);
|
||||
|
||||
/**
|
||||
* Check whether the applet has the permission
|
||||
*
|
||||
* @param perm the permission needed to check
|
||||
*
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size);
|
||||
|
||||
bool
|
||||
bh_applet_check_permission(const char *perm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
23
core/app-mgr/app-mgr-shared/app_mgr_shared.cmake
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set (APP_MGR_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories(${APP_MGR_SHARED_DIR})
|
||||
|
||||
|
||||
file (GLOB_RECURSE source_all ${APP_MGR_SHARED_DIR}/*.c)
|
||||
|
||||
set (APP_MGR_SHARED_SOURCE ${source_all})
|
||||
|
42
core/app-mgr/app-mgr-shared/host_link.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DEPS_APP_MGR_APP_MGR_SHARED_HOST_LINK_H_
|
||||
#define DEPS_APP_MGR_APP_MGR_SHARED_HOST_LINK_H_
|
||||
|
||||
typedef enum LINK_MSG_TYPE {
|
||||
COAP_TCP_RAW = 0,
|
||||
COAP_UDP_RAW = 1,
|
||||
REQUEST_PACKET,
|
||||
RESPONSE_PACKET,
|
||||
INSTALL_WASM_BYTECODE_APP,
|
||||
CBOR_GENERIC = 30,
|
||||
|
||||
LINK_MSG_TYPE_MAX = 50
|
||||
} LINK_MSG_TYPE;
|
||||
|
||||
/* Link message, or message between host and app manager */
|
||||
typedef struct bh_link_msg_t {
|
||||
/* 2 bytes leading */
|
||||
uint16_t leading_bytes;
|
||||
/* message type, must be COAP_TCP or COAP_UDP */
|
||||
uint16_t message_type;
|
||||
/* size of payload */
|
||||
uint32_t payload_size;
|
||||
char *payload;
|
||||
} bh_link_msg_t;
|
||||
|
||||
#endif /* DEPS_APP_MGR_APP_MGR_SHARED_HOST_LINK_H_ */
|
53
core/app-mgr/module.json
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"name": "aee",
|
||||
"version": "0.0.1",
|
||||
"description": "aee",
|
||||
"type": "source",
|
||||
"category": "middleware",
|
||||
"arch": "x86, arc, posix",
|
||||
"includes": [
|
||||
"Beihai/classlib/include",
|
||||
"Beihai/runtime/include",
|
||||
"Beihai/runtime/platform/include",
|
||||
"Beihai/runtime/platform/zephyr",
|
||||
"Beihai/runtime/utils/coap/er-coap",
|
||||
"Beihai/runtime/utils/coap/extension",
|
||||
"iwasm/runtime/include",
|
||||
"iwasm/runtime/platform/include",
|
||||
"iwasm/runtime/platform/zephyr",
|
||||
"iwasm/runtime/vmcore_wasm"
|
||||
],
|
||||
"sources": [
|
||||
"Beihai/classlib/native/internal/*.c",
|
||||
"Beihai/classlib/native/*.c",
|
||||
"Beihai/runtime/gc/*.c",
|
||||
"Beihai/runtime/platform/zephyr/*.c",
|
||||
"Beihai/runtime/utils/*.c",
|
||||
"Beihai/runtime/utils/coap/er-coap/*.c",
|
||||
"Beihai/runtime/utils/coap/extension/*.c",
|
||||
"Beihai/runtime/vmcore_jeff/*.c",
|
||||
"app-manager/app-manager.c",
|
||||
"app-manager/app-manager-host.c",
|
||||
"app-manager/app_mgr_zephyr.c",
|
||||
"app-manager/event.c",
|
||||
"app-manager/message.c",
|
||||
"app-manager/module_jeff.c",
|
||||
"app-manager/module_wasm_lib.c",
|
||||
"app-manager/module_wasm_app.c",
|
||||
"app-manager/watchdog.c",
|
||||
"Beihai/products/iMRT/*.c",
|
||||
"iwasm/runtime/utils/*.c",
|
||||
"iwasm/runtime/platform/zephyr/*.c",
|
||||
"iwasm/runtime/vmcore_wasm/*.c",
|
||||
"iwasm/lib/lib-export\.c",
|
||||
"iwasm/lib/aee/*.c",
|
||||
"iwasm/products/zephyr/sample/src/*.c"
|
||||
],
|
||||
"compile_definitions": [
|
||||
"NVALGRIND",
|
||||
"__JLF__",
|
||||
"__ZEPHYR__"
|
||||
],
|
||||
"target": "aee",
|
||||
"dependencies": []
|
||||
}
|
17
core/iwasm/app-samples/smart-light/build.sh
Executable file
|
@ -0,0 +1,17 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
emcc -g -O3 *.c -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
|
||||
-s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 -o test.wasm
|
||||
#./jeffdump -o ../test_wasm.h -n wasm_test_file test.wasm
|
67
core/iwasm/app-samples/smart-light/main.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//User LED
|
||||
#define LED_PORT "GPIOA"
|
||||
#define LED 5
|
||||
|
||||
//User KEY
|
||||
#define KEY_PORT "GPIOC"
|
||||
#define KEY 13
|
||||
|
||||
/** GPIO pin to be input. */
|
||||
#define GPIO_DIR_IN (0 << 0)
|
||||
|
||||
/** GPIO pin to be output. */
|
||||
#define GPIO_DIR_OUT (1 << 0)
|
||||
|
||||
void *device_get_binding(const char *);
|
||||
int gpio_pin_configure(void *, unsigned int, int);
|
||||
int gpio_pin_read(void *, unsigned int, unsigned int *);
|
||||
int gpio_pin_write(void *, unsigned int, unsigned int);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int gpio_value;
|
||||
unsigned char flag = 0;
|
||||
struct device *dev, *key_dev;
|
||||
|
||||
dev = device_get_binding(LED_PORT);
|
||||
/* Set LED pin as output */
|
||||
gpio_pin_configure(dev, LED, GPIO_DIR_OUT);
|
||||
|
||||
key_dev = device_get_binding(KEY_PORT);
|
||||
/* Set KEY pin as input */
|
||||
gpio_pin_configure(key_dev, KEY, GPIO_DIR_IN);
|
||||
|
||||
while (1) {
|
||||
gpio_pin_read(key_dev, KEY, &gpio_value);
|
||||
if (!gpio_value) {
|
||||
gpio_pin_write(dev, LED, 1);
|
||||
if (!flag) {
|
||||
printf("object detected\n");
|
||||
flag = 1;
|
||||
}
|
||||
} else {
|
||||
gpio_pin_write(dev, LED, 0);
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -71,7 +71,7 @@ uint16 htons(uint16 value)
|
|||
uint16 ret;
|
||||
if (is_little_endian()) {
|
||||
ret = value;
|
||||
swap16(&ret);
|
||||
swap16((uint8 *)&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
#include "request.h"
|
||||
#include "shared_utils.h"
|
||||
#include "wasm_app.h"
|
||||
|
@ -138,9 +138,9 @@ static bool register_url_handler(const char *url,
|
|||
|
||||
// tell app mgr to route this url to me
|
||||
if (reg_type == Reg_Request)
|
||||
wasm_register_resource(url);
|
||||
wasm_register_resource((int32)url);
|
||||
else
|
||||
wasm_sub_event(url);
|
||||
wasm_sub_event((int32)url);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ void api_send_request(request_t * request, response_handler_f response_handler,
|
|||
}
|
||||
}
|
||||
|
||||
wasm_post_request(buffer, size);
|
||||
wasm_post_request((int32)buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ void api_response_send(response_t *response)
|
|||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
wasm_response_send(buffer, size);
|
||||
wasm_response_send((int32)buffer, size);
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
|
||||
|
@ -339,11 +339,11 @@ bool api_publish_event(const char *url, int fmt, void *payload, int payload_len)
|
|||
{
|
||||
int size;
|
||||
request_t request[1];
|
||||
init_request(request, url, COAP_EVENT, fmt, payload, payload_len);
|
||||
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);
|
||||
wasm_post_request((int32)buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "native_interface.h"
|
||||
#include "shared_utils.h"
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
#include "request.h"
|
||||
#include "sensor.h"
|
||||
#include "timer_wasm_app.h"
|
||||
|
|
|
@ -31,7 +31,7 @@ sensor_t sensor_open(const char* name, int index,
|
|||
sensor_event_handler_f sensor_event_handler,
|
||||
void *user_data)
|
||||
{
|
||||
uint32 id = wasm_sensor_open(name, index);
|
||||
uint32 id = wasm_sensor_open((int32)name, index);
|
||||
if (id == -1)
|
||||
return NULL;
|
||||
|
||||
|
@ -66,7 +66,7 @@ bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg)
|
|||
char *buffer = (char *)cfg;
|
||||
int len = attr_container_get_serialize_length(cfg);
|
||||
|
||||
return wasm_sensor_config_with_attr_container(sensor->handle, buffer, len);
|
||||
return wasm_sensor_config_with_attr_container(sensor->handle, (int32)buffer, len);
|
||||
}
|
||||
|
||||
bool sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef _AEE_SENSOR_H_
|
||||
#define _AEE_SENSOR_H_
|
||||
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
|
||||
typedef union jvalue {
|
||||
bool z;
|
||||
|
@ -794,7 +794,7 @@ void attr_container_dump(const attr_container_t *attr_cont)
|
|||
break;
|
||||
case ATTR_TYPE_INT64:
|
||||
bh_memcpy_s(&value.j, sizeof(uint64_t), p, sizeof(uint64_t));
|
||||
attr_container_printf(", type: int64, value: 0x%llx\n", value.j);
|
||||
attr_container_printf(", type: int64, value: 0x%llx\n", (long long unsigned int)(value.j));
|
||||
p += 8;
|
||||
break;
|
||||
case ATTR_TYPE_BYTE:
|
|
@ -109,7 +109,10 @@ request_t * unpack_request(char * packet, int size, request_t * request)
|
|||
request->sender = ntohl(*((uint32*) (packet + 8)));
|
||||
request->payload_len = payload_len;
|
||||
request->url = REQUEST_PACKET_URL(packet);
|
||||
request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len;
|
||||
if (payload_len > 0)
|
||||
request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len;
|
||||
else
|
||||
request->payload = NULL;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
@ -150,7 +153,10 @@ response_t * unpack_response(char * packet, int size, response_t * response)
|
|||
response->mid = ntohl(*((uint32*) (packet + 4)));
|
||||
response->reciever = ntohl(*((uint32*) (packet + 8)));
|
||||
response->payload_len = payload_len;
|
||||
response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN;
|
||||
if (payload_len > 0)
|
||||
response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN;
|
||||
else
|
||||
response->payload = NULL;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -238,7 +244,7 @@ response_t * clone_response(response_t * response)
|
|||
response_t * set_response(response_t * response, int status, int fmt,
|
||||
const char *payload, int payload_len)
|
||||
{
|
||||
response->payload = payload;
|
||||
response->payload = (void *)payload;
|
||||
response->payload_len = payload_len;
|
||||
response->status = status;
|
||||
response->fmt = fmt;
|
||||
|
@ -384,11 +390,9 @@ char * find_key_value(char * buffer, int buffer_len, char * key, char * value,
|
|||
int value_len, char delimiter)
|
||||
{
|
||||
char * p = buffer;
|
||||
int i = 0;
|
||||
int remaining = buffer_len;
|
||||
int key_len = strlen(key);
|
||||
|
||||
char * item_start = p;
|
||||
while (*p != 0 && remaining > 0) {
|
||||
while (*p == ' ' || *p == delimiter) {
|
||||
p++;
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "lib-export.h"
|
||||
#include "lib_export.h"
|
||||
|
||||
#ifdef WASM_ENABLE_BASE_LIB
|
||||
#include "base-lib-export.h"
|
||||
#include "base_lib_export.h"
|
||||
#endif
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef _BASE_LIB_EXPORT_H_
|
||||
#define _BASE_LIB_EXPORT_H_
|
||||
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
#include "native_interface.h"
|
||||
|
||||
#endif /* end of _BASE_LIB_EXPORT_H_ */
|
|
@ -15,11 +15,11 @@
|
|||
*/
|
||||
|
||||
#include "native_interface.h"
|
||||
#include "app-manager-export.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "coap_ext.h"
|
||||
#include "wasm-export.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
extern void module_request_handler(request_t *request, uint32 register_id);
|
||||
extern void module_request_handler(request_t *request, void *user_data);
|
||||
|
||||
bool wasm_response_send(int32 buffer_offset, int size)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#include "runtime_timer.h"
|
||||
#include "app-manager-export.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "bh_list.h"
|
||||
#include "bh_thread.h"
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#include "runtime_sensor.h"
|
||||
#include "app-manager-export.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "bh_thread.h"
|
||||
#include "bh_time.h"
|
||||
|
@ -168,7 +168,7 @@ uint32 wasm_sensor_open(int32 name_offset, int instance)
|
|||
|
||||
memset(client, 0, sizeof(sensor_client_t));
|
||||
client->client_id = mod_id;
|
||||
client->client_callback = wasm_sensor_callback;
|
||||
client->client_callback = (void *)wasm_sensor_callback;
|
||||
client->interval = s->default_interval;
|
||||
client->next = s->clients;
|
||||
s->clients = client;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#define LIB_EXTENSION_RUNTIME_SENSOR_H_
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
struct _sys_sensor;
|
||||
typedef struct _sys_sensor* sensor_obj_t;
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
#include "bh_queue.h"
|
||||
#include "bh_thread.h"
|
||||
#include "runtime_sensor.h"
|
||||
#include "attr-container.h"
|
||||
#include "attr_container.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wasm-export.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -99,11 +99,10 @@ static attr_container_t * read_test_sensor(void * sensor)
|
|||
|
||||
static bool config_test_sensor(void * s, void * config)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void * thread_sensor_check(void * arg)
|
||||
static void thread_sensor_check(void * arg)
|
||||
{
|
||||
while (1) {
|
||||
int ms_to_expiry = check_sensor_timers();
|
||||
|
@ -120,6 +119,8 @@ static void cb_wakeup_thread()
|
|||
vm_cond_signal(&cond);
|
||||
}
|
||||
|
||||
void set_sensor_reshceduler(void (*callback)());
|
||||
|
||||
void init_sensor_framework()
|
||||
{
|
||||
// init the mutext and conditions
|
||||
|
@ -138,7 +139,7 @@ void init_sensor_framework()
|
|||
|
||||
wasm_register_cleanup_callback(sensor_cleanup_callback);
|
||||
|
||||
vm_thread_create(&tid, thread_sensor_check, NULL,
|
||||
vm_thread_create(&tid, (void *)thread_sensor_check, NULL,
|
||||
BH_APPLET_PRESERVED_STACK_SIZE);
|
||||
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "wasm-native.h"
|
||||
#include "wasm-export.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_export.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_platform_log.h"
|
||||
|
||||
|
@ -903,7 +903,9 @@ wasm_native_func_lookup(const char *module_name, const char *func_name)
|
|||
|
||||
while (func_def < func_def_end) {
|
||||
if (!strcmp(func_def->module_name, module_name)
|
||||
&& !strcmp(func_def->func_name, func_name))
|
||||
&& (!strcmp(func_def->func_name, func_name)
|
||||
|| (func_def->func_name[0] == '_'
|
||||
&& !strcmp(func_def->func_name + 1, func_name))))
|
||||
return (void*) (uintptr_t) func_def->func_ptr;
|
||||
func_def++;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ enable_language (ASM)
|
|||
|
||||
include (../../runtime/platform/${PLATFORM}/platform.cmake)
|
||||
include (../../runtime/utils/utils.cmake)
|
||||
include (../../runtime/vmcore_wasm/vmcore.cmake)
|
||||
include (../../runtime/vmcore-wasm/vmcore.cmake)
|
||||
include (../../lib/native/base/wasm_lib_base.cmake)
|
||||
include (../../lib/native/libc/wasm_libc.cmake)
|
||||
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)
|
||||
|
@ -68,12 +68,12 @@ add_library (vmlib
|
|||
${WASM_PLATFORM_LIB_SOURCE}
|
||||
${WASM_UTILS_LIB_SOURCE}
|
||||
${VMCORE_LIB_SOURCE}
|
||||
${WASM_LIB_BASE_DIR}/base-lib-export.c
|
||||
${WASM_LIB_BASE_DIR}/base_lib_export.c
|
||||
${WASM_LIBC_SOURCE}
|
||||
${PLATFORM_SHARED_SOURCE}
|
||||
${MEM_ALLOC_SHARED_SOURCE})
|
||||
|
||||
add_executable (iwasm main.c ext-lib-export.c)
|
||||
add_executable (iwasm main.c ext_lib_export.c)
|
||||
|
||||
install (TARGETS iwasm DESTINATION bin)
|
||||
|
||||
|
@ -83,7 +83,7 @@ add_library (libiwasm SHARED
|
|||
${WASM_PLATFORM_LIB_SOURCE}
|
||||
${WASM_UTILS_LIB_SOURCE}
|
||||
${VMCORE_LIB_SOURCE}
|
||||
${WASM_LIB_BASE_DIR}/base-lib-export.c
|
||||
${WASM_LIB_BASE_DIR}/base_lib_export.c
|
||||
${WASM_LIBC_SOURCE}
|
||||
${PLATFORM_SHARED_SOURCE}
|
||||
${MEM_ALLOC_SHARED_SOURCE})
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lib-export.h"
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext-lib-export.h"
|
||||
#include "ext_lib_export.h"
|
|
@ -24,7 +24,7 @@
|
|||
#include "wasm_platform.h"
|
||||
#include "wasm_platform_log.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm-export.h"
|
||||
#include "wasm_export.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "bh_memory.h"
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ set (SHARED_LIB_ROOT ${IWASM_ROOT}/../shared-lib)
|
|||
include_directories (${IWASM_ROOT}/runtime/include
|
||||
${IWASM_ROOT}/runtime/platform/include
|
||||
${IWASM_ROOT}/runtime/platform/zephyr
|
||||
${IWASM_ROOT}/runtime/vmcore_wasm
|
||||
${IWASM_ROOT}/runtime/vmcore-wasm
|
||||
${SHARED_LIB_ROOT}/include
|
||||
${SHARED_LIB_ROOT}/platform/include
|
||||
${SHARED_LIB_ROOT}/platform/zephyr)
|
||||
|
@ -37,14 +37,14 @@ set (IWASM_SRCS ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c
|
|||
${IWASM_ROOT}/runtime/utils/wasm_dlfcn.c
|
||||
${IWASM_ROOT}/runtime/platform/zephyr/wasm_math.c
|
||||
${IWASM_ROOT}/runtime/platform/zephyr/wasm_platform.c
|
||||
${IWASM_ROOT}/runtime/platform/zephyr/wasm-native.c
|
||||
${IWASM_ROOT}/runtime/vmcore_wasm/wasm-application.c
|
||||
${IWASM_ROOT}/runtime/vmcore_wasm/wasm-interp.c
|
||||
${IWASM_ROOT}/runtime/vmcore_wasm/wasm-loader.c
|
||||
${IWASM_ROOT}/runtime/vmcore_wasm/wasm-runtime.c
|
||||
${IWASM_ROOT}/runtime/vmcore_wasm/invokeNative_general.c
|
||||
${IWASM_ROOT}/runtime/platform/zephyr/wasm_native.c
|
||||
${IWASM_ROOT}/runtime/vmcore-wasm/wasm_application.c
|
||||
${IWASM_ROOT}/runtime/vmcore-wasm/wasm_interp.c
|
||||
${IWASM_ROOT}/runtime/vmcore-wasm/wasm_loader.c
|
||||
${IWASM_ROOT}/runtime/vmcore-wasm/wasm_runtime.c
|
||||
${IWASM_ROOT}/runtime/vmcore-wasm/invokeNative_general.c
|
||||
${IWASM_ROOT}/lib/native/libc/libc_wrapper.c
|
||||
${IWASM_ROOT}/lib/native/base/base-lib-export.c
|
||||
${IWASM_ROOT}/lib/native/base/base_lib_export.c
|
||||
${SHARED_LIB_ROOT}/platform/zephyr/bh_platform.c
|
||||
${SHARED_LIB_ROOT}/platform/zephyr/bh_assert.c
|
||||
${SHARED_LIB_ROOT}/platform/zephyr/bh_thread.c
|
||||
|
@ -54,4 +54,4 @@ set (IWASM_SRCS ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c
|
|||
${SHARED_LIB_ROOT}/mem-alloc/ems/ems_alloc.c
|
||||
${SHARED_LIB_ROOT}/mem-alloc/ems/ems_hmu.c)
|
||||
|
||||
target_sources(app PRIVATE ${IWASM_SRCS} src/main.c src/ext-lib-export.c)
|
||||
target_sources(app PRIVATE ${IWASM_SRCS} src/main.c src/ext_lib_export.c)
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lib-export.h"
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] = { };
|
||||
|
||||
#include "ext-lib-export.h"
|
||||
#include "ext_lib_export.h"
|
|
@ -21,7 +21,7 @@
|
|||
#include "wasm_platform.h"
|
||||
#include "wasm_platform_log.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm-export.h"
|
||||
#include "wasm_export.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "bh_memory.h"
|
||||
#include "test_wasm.h"
|
||||
|
|
75
core/iwasm/readme.txt
Normal file
|
@ -0,0 +1,75 @@
|
|||
|
||||
1. How to build iwasm in Linux
|
||||
|
||||
cd products/linux/
|
||||
mkdir build && cd build
|
||||
cmake .. && make
|
||||
|
||||
2. How to build iwasm in Zephyr system
|
||||
(1) clone zephyr source code
|
||||
|
||||
git clone https://github.com/zephyrproject-rtos/zephyr.git
|
||||
|
||||
(2) copy <iwasm_root_dir>/products/zephyr/simple directory to zephry/samples/
|
||||
|
||||
cd zephyr/samples/
|
||||
cp -a <iwasm_root_dir>/products/zephyr/simple simple
|
||||
cd simple
|
||||
|
||||
(3) create a link to <iwasm_root_dir> and rename it to iwasm
|
||||
|
||||
ln -s <iwasm_root_dir> iwasm
|
||||
|
||||
(4) create a link to <shared-lib_root_dir> and rename it to shared-lib
|
||||
|
||||
ln -s <shared-lib_root_dir> shared-lib
|
||||
|
||||
(5) build source code
|
||||
|
||||
mkdir build && cd build
|
||||
source ../../../zephyr-env.sh
|
||||
cmake -GNinja -DBOARD=qemu_x86 ..
|
||||
ninja
|
||||
|
||||
(6) run simple
|
||||
|
||||
ninja run
|
||||
|
||||
3. How to build iwasm in AliOS-Things platform
|
||||
(1) clone AliOS-Things source code
|
||||
|
||||
git clone https://github.com/alibaba/AliOS-Things.git
|
||||
|
||||
(2) copy <iwasm_root_dir>/products/alios-things directory to AliOS-Things/middleware,
|
||||
and rename it as iwasm
|
||||
|
||||
cp -a <iwasm_root_dir>/products/alios-things middleware/iwasm
|
||||
|
||||
(3) create a link to <iwasm_root_dir> in middleware/iwasm/ and rename it to iwasm
|
||||
|
||||
ln -s <iwasm_root_dir> middleware/iwasm/iwasm
|
||||
|
||||
(4) create a link to <shared-lib_root_dir> in middleware/iwasm/ and rename it to shared-lib
|
||||
|
||||
ln -s <shared-lib_root_dir> middle/iwasm/shared-lib
|
||||
|
||||
(5) modify sample source code of AliOS-Things to call iwasm_init() function
|
||||
|
||||
modify file app/example/helloworld/helloworld.c, in the beginning of
|
||||
function application_start(), add:
|
||||
|
||||
bool iwasm_init(void);
|
||||
iwasm_init();
|
||||
|
||||
modify file app/example/helloworld/helloworld.mk, change
|
||||
$(NAME)_COMPONENTS := yloop cli
|
||||
to
|
||||
$(NAME)_COMPONENTS := yloop cli iwasm
|
||||
|
||||
(6) build source code
|
||||
|
||||
aos make helloworld@linuxhost
|
||||
|
||||
(7) run source code
|
||||
./out/helloworld@linuxhost/binary/helloworld@linuxhost.elf
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef _EXT_LIB_EXPORT_H_
|
||||
#define _EXT_LIB_EXPORT_H_
|
||||
|
||||
#include "lib-export.h"
|
||||
#include "lib_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
|
@ -20,8 +20,8 @@
|
|||
* thread relative function.
|
||||
*/
|
||||
|
||||
#ifndef _WASM_THREAD_H
|
||||
#define _WASM_THREAD_H
|
||||
#ifndef _WA_THREAD_H
|
||||
#define _WA_THREAD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -59,5 +59,5 @@ ws_mutex_init(korp_mutex *mutex, bool is_recursive)
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of _WASM_THREAD_H */
|
||||
#endif /* end of _WA_THREAD_H */
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
#define _GNU_SOURCE /* for O_DIRECT */
|
||||
#endif
|
||||
|
||||
#include "wasm-native.h"
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "wasm_platform_log.h"
|
|
@ -39,64 +39,64 @@ typedef uint32_t u_int32_t;
|
|||
typedef uint64_t u_int64_t;
|
||||
|
||||
typedef union u32double_tag {
|
||||
int *pint;
|
||||
double *pdouble;
|
||||
int *pint;
|
||||
double *pdouble;
|
||||
} U32DOUBLE;
|
||||
|
||||
static inline int *
|
||||
pdouble2pint(double *pdouble)
|
||||
{
|
||||
U32DOUBLE u;
|
||||
u.pdouble = pdouble;
|
||||
return u.pint;
|
||||
U32DOUBLE u;
|
||||
u.pdouble = pdouble;
|
||||
return u.pint;
|
||||
}
|
||||
|
||||
typedef union
|
||||
{
|
||||
double value;
|
||||
struct
|
||||
{
|
||||
u_int32_t lsw;
|
||||
u_int32_t msw;
|
||||
} parts;
|
||||
struct
|
||||
{
|
||||
u_int64_t w;
|
||||
} xparts;
|
||||
double value;
|
||||
struct
|
||||
{
|
||||
u_int32_t lsw;
|
||||
u_int32_t msw;
|
||||
} parts;
|
||||
struct
|
||||
{
|
||||
u_int64_t w;
|
||||
} xparts;
|
||||
} ieee_double_shape_type_little;
|
||||
|
||||
typedef union
|
||||
{
|
||||
double value;
|
||||
struct
|
||||
{
|
||||
u_int32_t msw;
|
||||
u_int32_t lsw;
|
||||
} parts;
|
||||
struct
|
||||
{
|
||||
u_int64_t w;
|
||||
} xparts;
|
||||
double value;
|
||||
struct
|
||||
{
|
||||
u_int32_t msw;
|
||||
u_int32_t lsw;
|
||||
} parts;
|
||||
struct
|
||||
{
|
||||
u_int64_t w;
|
||||
} xparts;
|
||||
} ieee_double_shape_type_big;
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
struct {
|
||||
unsigned int manl :32;
|
||||
unsigned int manh :20;
|
||||
unsigned int exp :11;
|
||||
unsigned int sign :1;
|
||||
} bits;
|
||||
double d;
|
||||
struct {
|
||||
unsigned int manl :32;
|
||||
unsigned int manh :20;
|
||||
unsigned int exp :11;
|
||||
unsigned int sign :1;
|
||||
} bits;
|
||||
} IEEEd2bits_L;
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
struct {
|
||||
unsigned int sign :1;
|
||||
unsigned int exp :11;
|
||||
unsigned int manh :20;
|
||||
unsigned int manl :32;
|
||||
} bits;
|
||||
double d;
|
||||
struct {
|
||||
unsigned int sign :1;
|
||||
unsigned int exp :11;
|
||||
unsigned int manh :20;
|
||||
unsigned int manl :32;
|
||||
} bits;
|
||||
} IEEEd2bits_B;
|
||||
|
||||
#define __HIL(x) *(1+pdouble2pint(&x))
|
||||
|
@ -107,107 +107,107 @@ typedef union {
|
|||
/* Get two 32 bit ints from a double. */
|
||||
|
||||
#define EXTRACT_WORDS_L(ix0,ix1,d) \
|
||||
do { \
|
||||
ieee_double_shape_type_little ew_u; \
|
||||
ew_u.value = (d); \
|
||||
(ix0) = ew_u.parts.msw; \
|
||||
(ix1) = ew_u.parts.lsw; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_little ew_u; \
|
||||
ew_u.value = (d); \
|
||||
(ix0) = ew_u.parts.msw; \
|
||||
(ix1) = ew_u.parts.lsw; \
|
||||
} while (0)
|
||||
|
||||
/* Set a double from two 32 bit ints. */
|
||||
|
||||
#define INSERT_WORDS_L(d,ix0,ix1) \
|
||||
do { \
|
||||
ieee_double_shape_type_little iw_u; \
|
||||
iw_u.parts.msw = (ix0); \
|
||||
iw_u.parts.lsw = (ix1); \
|
||||
(d) = iw_u.value; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_little iw_u; \
|
||||
iw_u.parts.msw = (ix0); \
|
||||
iw_u.parts.lsw = (ix1); \
|
||||
(d) = iw_u.value; \
|
||||
} while (0)
|
||||
|
||||
/* Get two 32 bit ints from a double. */
|
||||
|
||||
#define EXTRACT_WORDS_B(ix0,ix1,d) \
|
||||
do { \
|
||||
ieee_double_shape_type_big ew_u; \
|
||||
ew_u.value = (d); \
|
||||
(ix0) = ew_u.parts.msw; \
|
||||
(ix1) = ew_u.parts.lsw; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_big ew_u; \
|
||||
ew_u.value = (d); \
|
||||
(ix0) = ew_u.parts.msw; \
|
||||
(ix1) = ew_u.parts.lsw; \
|
||||
} while (0)
|
||||
|
||||
/* Set a double from two 32 bit ints. */
|
||||
|
||||
#define INSERT_WORDS_B(d,ix0,ix1) \
|
||||
do { \
|
||||
ieee_double_shape_type_big iw_u; \
|
||||
iw_u.parts.msw = (ix0); \
|
||||
iw_u.parts.lsw = (ix1); \
|
||||
(d) = iw_u.value; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_big iw_u; \
|
||||
iw_u.parts.msw = (ix0); \
|
||||
iw_u.parts.lsw = (ix1); \
|
||||
(d) = iw_u.value; \
|
||||
} while (0)
|
||||
|
||||
/* Get the more significant 32 bit int from a double. */
|
||||
#define GET_HIGH_WORD_L(i,d) \
|
||||
do { \
|
||||
ieee_double_shape_type_little gh_u; \
|
||||
gh_u.value = (d); \
|
||||
(i) = gh_u.parts.msw; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_little gh_u; \
|
||||
gh_u.value = (d); \
|
||||
(i) = gh_u.parts.msw; \
|
||||
} while (0)
|
||||
|
||||
/* Get the more significant 32 bit int from a double. */
|
||||
#define GET_HIGH_WORD_B(i,d) \
|
||||
do { \
|
||||
ieee_double_shape_type_big gh_u; \
|
||||
gh_u.value = (d); \
|
||||
(i) = gh_u.parts.msw; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_big gh_u; \
|
||||
gh_u.value = (d); \
|
||||
(i) = gh_u.parts.msw; \
|
||||
} while (0)
|
||||
|
||||
/* Set the more significant 32 bits of a double from an int. */
|
||||
#define SET_HIGH_WORD_L(d,v) \
|
||||
do { \
|
||||
ieee_double_shape_type_little sh_u; \
|
||||
sh_u.value = (d); \
|
||||
sh_u.parts.msw = (v); \
|
||||
(d) = sh_u.value; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_little sh_u; \
|
||||
sh_u.value = (d); \
|
||||
sh_u.parts.msw = (v); \
|
||||
(d) = sh_u.value; \
|
||||
} while (0)
|
||||
|
||||
/* Set the more significant 32 bits of a double from an int. */
|
||||
#define SET_HIGH_WORD_B(d,v) \
|
||||
do { \
|
||||
ieee_double_shape_type_big sh_u; \
|
||||
sh_u.value = (d); \
|
||||
sh_u.parts.msw = (v); \
|
||||
(d) = sh_u.value; \
|
||||
} while (0)
|
||||
do { \
|
||||
ieee_double_shape_type_big sh_u; \
|
||||
sh_u.value = (d); \
|
||||
sh_u.parts.msw = (v); \
|
||||
(d) = sh_u.value; \
|
||||
} while (0)
|
||||
|
||||
/* Macro wrappers. */
|
||||
#define EXTRACT_WORDS(ix0,ix1,d) do { \
|
||||
if (is_little_endian) \
|
||||
EXTRACT_WORDS_L(ix0,ix1,d); \
|
||||
else \
|
||||
EXTRACT_WORDS_B(ix0,ix1,d); \
|
||||
if (is_little_endian) \
|
||||
EXTRACT_WORDS_L(ix0,ix1,d); \
|
||||
else \
|
||||
EXTRACT_WORDS_B(ix0,ix1,d); \
|
||||
} while (0)
|
||||
|
||||
#define INSERT_WORDS(d,ix0,ix1) do { \
|
||||
if (is_little_endian) \
|
||||
INSERT_WORDS_L(d,ix0,ix1); \
|
||||
else \
|
||||
INSERT_WORDS_B(d,ix0,ix1); \
|
||||
if (is_little_endian) \
|
||||
INSERT_WORDS_L(d,ix0,ix1); \
|
||||
else \
|
||||
INSERT_WORDS_B(d,ix0,ix1); \
|
||||
} while (0)
|
||||
|
||||
#define GET_HIGH_WORD(i,d) \
|
||||
do { \
|
||||
if (is_little_endian) \
|
||||
GET_HIGH_WORD_L(i,d); \
|
||||
else \
|
||||
GET_HIGH_WORD_B(i,d); \
|
||||
} while (0)
|
||||
do { \
|
||||
if (is_little_endian) \
|
||||
GET_HIGH_WORD_L(i,d); \
|
||||
else \
|
||||
GET_HIGH_WORD_B(i,d); \
|
||||
} while (0)
|
||||
|
||||
#define SET_HIGH_WORD(d,v) \
|
||||
do { \
|
||||
if (is_little_endian) \
|
||||
SET_HIGH_WORD_L(d,v); \
|
||||
else \
|
||||
SET_HIGH_WORD_B(d,v); \
|
||||
} while (0)
|
||||
do { \
|
||||
if (is_little_endian) \
|
||||
SET_HIGH_WORD_L(d,v); \
|
||||
else \
|
||||
SET_HIGH_WORD_B(d,v); \
|
||||
} while (0)
|
||||
|
||||
#define __HI(x) (is_little_endian ? __HIL(x) : __HIB(x))
|
||||
|
||||
|
@ -220,14 +220,14 @@ do { \
|
|||
#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
|
||||
#else
|
||||
#define STRICT_ASSIGN(type, lval, rval) do { \
|
||||
volatile type __lval; \
|
||||
\
|
||||
if (sizeof(type) >= sizeof(long double)) \
|
||||
(lval) = (rval); \
|
||||
else { \
|
||||
__lval = (rval); \
|
||||
(lval) = __lval; \
|
||||
} \
|
||||
volatile type __lval; \
|
||||
\
|
||||
if (sizeof(type) >= sizeof(long double)) \
|
||||
(lval) = (rval); \
|
||||
else { \
|
||||
__lval = (rval); \
|
||||
(lval) = __lval; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
@ -257,8 +257,8 @@ static const double
|
|||
static double
|
||||
#endif
|
||||
TWO52[2]={
|
||||
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
|
||||
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
|
||||
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
|
||||
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
|
||||
};
|
||||
|
||||
static double freebsd_sqrt(double x);
|
||||
|
@ -270,312 +270,312 @@ static int freebsd_isnan(double x);
|
|||
|
||||
static double freebsd_sqrt(double x) /* wrapper sqrt */
|
||||
{
|
||||
double z;
|
||||
int32_t sign = (int)0x80000000;
|
||||
int32_t ix0,s0,q,m,t,i;
|
||||
u_int32_t r,t1,s1,ix1,q1;
|
||||
double z;
|
||||
int32_t sign = (int)0x80000000;
|
||||
int32_t ix0,s0,q,m,t,i;
|
||||
u_int32_t r,t1,s1,ix1,q1;
|
||||
|
||||
EXTRACT_WORDS(ix0,ix1,x);
|
||||
EXTRACT_WORDS(ix0,ix1,x);
|
||||
|
||||
/* take care of Inf and NaN */
|
||||
if((ix0&0x7ff00000)==0x7ff00000) {
|
||||
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
|
||||
if((ix0&0x7ff00000)==0x7ff00000) {
|
||||
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
|
||||
sqrt(-inf)=sNaN */
|
||||
}
|
||||
}
|
||||
/* take care of zero */
|
||||
if(ix0<=0) {
|
||||
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
|
||||
else if(ix0<0)
|
||||
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
|
||||
}
|
||||
if(ix0<=0) {
|
||||
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
|
||||
else if(ix0<0)
|
||||
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
|
||||
}
|
||||
/* normalize x */
|
||||
m = (ix0>>20);
|
||||
if(m==0) { /* subnormal x */
|
||||
while(ix0==0) {
|
||||
m -= 21;
|
||||
ix0 |= (ix1>>11); ix1 <<= 21;
|
||||
}
|
||||
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
|
||||
m -= i-1;
|
||||
ix0 |= (ix1>>(32-i));
|
||||
ix1 <<= i;
|
||||
}
|
||||
m -= 1023; /* unbias exponent */
|
||||
ix0 = (ix0&0x000fffff)|0x00100000;
|
||||
if(m&1){ /* odd m, double x to make it even */
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
}
|
||||
m >>= 1; /* m = [m/2] */
|
||||
m = (ix0>>20);
|
||||
if(m==0) { /* subnormal x */
|
||||
while(ix0==0) {
|
||||
m -= 21;
|
||||
ix0 |= (ix1>>11); ix1 <<= 21;
|
||||
}
|
||||
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
|
||||
m -= i-1;
|
||||
ix0 |= (ix1>>(32-i));
|
||||
ix1 <<= i;
|
||||
}
|
||||
m -= 1023; /* unbias exponent */
|
||||
ix0 = (ix0&0x000fffff)|0x00100000;
|
||||
if(m&1){ /* odd m, double x to make it even */
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
}
|
||||
m >>= 1; /* m = [m/2] */
|
||||
|
||||
/* generate sqrt(x) bit by bit */
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
|
||||
r = 0x00200000; /* r = moving bit from right to left */
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
|
||||
r = 0x00200000; /* r = moving bit from right to left */
|
||||
|
||||
while(r!=0) {
|
||||
t = s0+r;
|
||||
if(t<=ix0) {
|
||||
s0 = t+r;
|
||||
ix0 -= t;
|
||||
q += r;
|
||||
}
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
r>>=1;
|
||||
}
|
||||
while(r!=0) {
|
||||
t = s0+r;
|
||||
if(t<=ix0) {
|
||||
s0 = t+r;
|
||||
ix0 -= t;
|
||||
q += r;
|
||||
}
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
r>>=1;
|
||||
}
|
||||
|
||||
r = sign;
|
||||
while(r!=0) {
|
||||
t1 = s1+r;
|
||||
t = s0;
|
||||
if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
|
||||
s1 = t1+r;
|
||||
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
|
||||
ix0 -= t;
|
||||
if (ix1 < t1) ix0 -= 1;
|
||||
ix1 -= t1;
|
||||
q1 += r;
|
||||
}
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
r>>=1;
|
||||
}
|
||||
r = sign;
|
||||
while(r!=0) {
|
||||
t1 = s1+r;
|
||||
t = s0;
|
||||
if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
|
||||
s1 = t1+r;
|
||||
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
|
||||
ix0 -= t;
|
||||
if (ix1 < t1) ix0 -= 1;
|
||||
ix1 -= t1;
|
||||
q1 += r;
|
||||
}
|
||||
ix0 += ix0 + ((ix1&sign)>>31);
|
||||
ix1 += ix1;
|
||||
r>>=1;
|
||||
}
|
||||
|
||||
/* use floating add to find out rounding direction */
|
||||
if((ix0|ix1)!=0) {
|
||||
z = one-tiny; /* trigger inexact flag */
|
||||
if (z>=one) {
|
||||
z = one+tiny;
|
||||
if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
|
||||
else if (z>one) {
|
||||
if (q1==(u_int32_t)0xfffffffe) q+=1;
|
||||
q1+=2;
|
||||
} else
|
||||
q1 += (q1&1);
|
||||
}
|
||||
}
|
||||
ix0 = (q>>1)+0x3fe00000;
|
||||
ix1 = q1>>1;
|
||||
if ((q&1)==1) ix1 |= sign;
|
||||
ix0 += (m <<20);
|
||||
if((ix0|ix1)!=0) {
|
||||
z = one-tiny; /* trigger inexact flag */
|
||||
if (z>=one) {
|
||||
z = one+tiny;
|
||||
if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
|
||||
else if (z>one) {
|
||||
if (q1==(u_int32_t)0xfffffffe) q+=1;
|
||||
q1+=2;
|
||||
} else
|
||||
q1 += (q1&1);
|
||||
}
|
||||
}
|
||||
ix0 = (q>>1)+0x3fe00000;
|
||||
ix1 = q1>>1;
|
||||
if ((q&1)==1) ix1 |= sign;
|
||||
ix0 += (m <<20);
|
||||
|
||||
INSERT_WORDS(z,ix0,ix1);
|
||||
INSERT_WORDS(z,ix0,ix1);
|
||||
|
||||
return z;
|
||||
return z;
|
||||
}
|
||||
|
||||
static double freebsd_floor(double x)
|
||||
{
|
||||
int32_t i0,i1,j0;
|
||||
u_int32_t i,j;
|
||||
int32_t i0,i1,j0;
|
||||
u_int32_t i,j;
|
||||
|
||||
EXTRACT_WORDS(i0,i1,x);
|
||||
EXTRACT_WORDS(i0,i1,x);
|
||||
|
||||
j0 = ((i0>>20)&0x7ff)-0x3ff;
|
||||
if(j0<20) {
|
||||
if(j0<0) { /* raise inexact if x != 0 */
|
||||
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
|
||||
if(i0>=0) {i0=i1=0;}
|
||||
else if(((i0&0x7fffffff)|i1)!=0)
|
||||
{ i0=0xbff00000;i1=0;}
|
||||
}
|
||||
} else {
|
||||
i = (0x000fffff)>>j0;
|
||||
if(((i0&i)|i1)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0<0) i0 += (0x00100000)>>j0;
|
||||
i0 &= (~i); i1=0;
|
||||
}
|
||||
}
|
||||
} else if (j0>51) {
|
||||
if(j0==0x400) return x+x; /* inf or NaN */
|
||||
else return x; /* x is integral */
|
||||
} else {
|
||||
i = ((u_int32_t)(0xffffffff))>>(j0-20);
|
||||
if((i1&i)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0<0) {
|
||||
if(j0==20) i0+=1;
|
||||
else {
|
||||
j = i1+(1<<(52-j0));
|
||||
if(j<i1) i0 +=1 ; /* got a carry */
|
||||
i1=j;
|
||||
}
|
||||
}
|
||||
i1 &= (~i);
|
||||
}
|
||||
}
|
||||
j0 = ((i0>>20)&0x7ff)-0x3ff;
|
||||
if(j0<20) {
|
||||
if(j0<0) { /* raise inexact if x != 0 */
|
||||
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
|
||||
if(i0>=0) {i0=i1=0;}
|
||||
else if(((i0&0x7fffffff)|i1)!=0)
|
||||
{ i0=0xbff00000;i1=0;}
|
||||
}
|
||||
} else {
|
||||
i = (0x000fffff)>>j0;
|
||||
if(((i0&i)|i1)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0<0) i0 += (0x00100000)>>j0;
|
||||
i0 &= (~i); i1=0;
|
||||
}
|
||||
}
|
||||
} else if (j0>51) {
|
||||
if(j0==0x400) return x+x; /* inf or NaN */
|
||||
else return x; /* x is integral */
|
||||
} else {
|
||||
i = ((u_int32_t)(0xffffffff))>>(j0-20);
|
||||
if((i1&i)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0<0) {
|
||||
if(j0==20) i0+=1;
|
||||
else {
|
||||
j = i1+(1<<(52-j0));
|
||||
if(j<i1) i0 +=1 ; /* got a carry */
|
||||
i1=j;
|
||||
}
|
||||
}
|
||||
i1 &= (~i);
|
||||
}
|
||||
}
|
||||
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
|
||||
static double freebsd_ceil(double x)
|
||||
{
|
||||
int32_t i0,i1,j0;
|
||||
u_int32_t i,j;
|
||||
EXTRACT_WORDS(i0,i1,x);
|
||||
j0 = ((i0>>20)&0x7ff)-0x3ff;
|
||||
if(j0<20) {
|
||||
if(j0<0) { /* raise inexact if x != 0 */
|
||||
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
|
||||
if(i0<0) {i0=0x80000000;i1=0;}
|
||||
else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
|
||||
}
|
||||
} else {
|
||||
i = (0x000fffff)>>j0;
|
||||
if(((i0&i)|i1)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0>0) i0 += (0x00100000)>>j0;
|
||||
i0 &= (~i); i1=0;
|
||||
}
|
||||
}
|
||||
} else if (j0>51) {
|
||||
if(j0==0x400) return x+x; /* inf or NaN */
|
||||
else return x; /* x is integral */
|
||||
} else {
|
||||
i = ((u_int32_t)(0xffffffff))>>(j0-20);
|
||||
if((i1&i)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0>0) {
|
||||
if(j0==20) i0+=1;
|
||||
else {
|
||||
j = i1 + (1<<(52-j0));
|
||||
if(j<i1) i0+=1; /* got a carry */
|
||||
i1 = j;
|
||||
}
|
||||
}
|
||||
i1 &= (~i);
|
||||
}
|
||||
}
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
return x;
|
||||
int32_t i0,i1,j0;
|
||||
u_int32_t i,j;
|
||||
EXTRACT_WORDS(i0,i1,x);
|
||||
j0 = ((i0>>20)&0x7ff)-0x3ff;
|
||||
if(j0<20) {
|
||||
if(j0<0) { /* raise inexact if x != 0 */
|
||||
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
|
||||
if(i0<0) {i0=0x80000000;i1=0;}
|
||||
else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
|
||||
}
|
||||
} else {
|
||||
i = (0x000fffff)>>j0;
|
||||
if(((i0&i)|i1)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0>0) i0 += (0x00100000)>>j0;
|
||||
i0 &= (~i); i1=0;
|
||||
}
|
||||
}
|
||||
} else if (j0>51) {
|
||||
if(j0==0x400) return x+x; /* inf or NaN */
|
||||
else return x; /* x is integral */
|
||||
} else {
|
||||
i = ((u_int32_t)(0xffffffff))>>(j0-20);
|
||||
if((i1&i)==0) return x; /* x is integral */
|
||||
if(huge+x>0.0) { /* raise inexact flag */
|
||||
if(i0>0) {
|
||||
if(j0==20) i0+=1;
|
||||
else {
|
||||
j = i1 + (1<<(52-j0));
|
||||
if(j<i1) i0+=1; /* got a carry */
|
||||
i1 = j;
|
||||
}
|
||||
}
|
||||
i1 &= (~i);
|
||||
}
|
||||
}
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
return x;
|
||||
}
|
||||
|
||||
static double freebsd_rint(double x)
|
||||
{
|
||||
int32_t i0,j0,sx;
|
||||
u_int32_t i,i1;
|
||||
double w,t;
|
||||
EXTRACT_WORDS(i0,i1,x);
|
||||
sx = (i0>>31)&1;
|
||||
j0 = ((i0>>20)&0x7ff)-0x3ff;
|
||||
if(j0<20) {
|
||||
if(j0<0) {
|
||||
if(((i0&0x7fffffff)|i1)==0) return x;
|
||||
i1 |= (i0&0x0fffff);
|
||||
i0 &= 0xfffe0000;
|
||||
i0 |= ((i1|-i1)>>12)&0x80000;
|
||||
SET_HIGH_WORD(x,i0);
|
||||
STRICT_ASSIGN(double,w,TWO52[sx]+x);
|
||||
t = w-TWO52[sx];
|
||||
GET_HIGH_WORD(i0,t);
|
||||
SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
|
||||
return t;
|
||||
} else {
|
||||
i = (0x000fffff)>>j0;
|
||||
if(((i0&i)|i1)==0) return x; /* x is integral */
|
||||
i>>=1;
|
||||
if(((i0&i)|i1)!=0) {
|
||||
/*
|
||||
* Some bit is set after the 0.5 bit. To avoid the
|
||||
* possibility of errors from double rounding in
|
||||
* w = TWO52[sx]+x, adjust the 0.25 bit to a lower
|
||||
* guard bit. We do this for all j0<=51. The
|
||||
* adjustment is trickiest for j0==18 and j0==19
|
||||
* since then it spans the word boundary.
|
||||
*/
|
||||
if(j0==19) i1 = 0x40000000; else
|
||||
if(j0==18) i1 = 0x80000000; else
|
||||
i0 = (i0&(~i))|((0x20000)>>j0);
|
||||
}
|
||||
}
|
||||
} else if (j0>51) {
|
||||
if(j0==0x400) return x+x; /* inf or NaN */
|
||||
else return x; /* x is integral */
|
||||
} else {
|
||||
i = ((u_int32_t)(0xffffffff))>>(j0-20);
|
||||
if((i1&i)==0) return x; /* x is integral */
|
||||
i>>=1;
|
||||
if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
|
||||
}
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
STRICT_ASSIGN(double,w,TWO52[sx]+x);
|
||||
return w-TWO52[sx];
|
||||
int32_t i0,j0,sx;
|
||||
u_int32_t i,i1;
|
||||
double w,t;
|
||||
EXTRACT_WORDS(i0,i1,x);
|
||||
sx = (i0>>31)&1;
|
||||
j0 = ((i0>>20)&0x7ff)-0x3ff;
|
||||
if(j0<20) {
|
||||
if(j0<0) {
|
||||
if(((i0&0x7fffffff)|i1)==0) return x;
|
||||
i1 |= (i0&0x0fffff);
|
||||
i0 &= 0xfffe0000;
|
||||
i0 |= ((i1|-i1)>>12)&0x80000;
|
||||
SET_HIGH_WORD(x,i0);
|
||||
STRICT_ASSIGN(double,w,TWO52[sx]+x);
|
||||
t = w-TWO52[sx];
|
||||
GET_HIGH_WORD(i0,t);
|
||||
SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
|
||||
return t;
|
||||
} else {
|
||||
i = (0x000fffff)>>j0;
|
||||
if(((i0&i)|i1)==0) return x; /* x is integral */
|
||||
i>>=1;
|
||||
if(((i0&i)|i1)!=0) {
|
||||
/*
|
||||
* Some bit is set after the 0.5 bit. To avoid the
|
||||
* possibility of errors from double rounding in
|
||||
* w = TWO52[sx]+x, adjust the 0.25 bit to a lower
|
||||
* guard bit. We do this for all j0<=51. The
|
||||
* adjustment is trickiest for j0==18 and j0==19
|
||||
* since then it spans the word boundary.
|
||||
*/
|
||||
if(j0==19) i1 = 0x40000000; else
|
||||
if(j0==18) i1 = 0x80000000; else
|
||||
i0 = (i0&(~i))|((0x20000)>>j0);
|
||||
}
|
||||
}
|
||||
} else if (j0>51) {
|
||||
if(j0==0x400) return x+x; /* inf or NaN */
|
||||
else return x; /* x is integral */
|
||||
} else {
|
||||
i = ((u_int32_t)(0xffffffff))>>(j0-20);
|
||||
if((i1&i)==0) return x; /* x is integral */
|
||||
i>>=1;
|
||||
if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
|
||||
}
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
STRICT_ASSIGN(double,w,TWO52[sx]+x);
|
||||
return w-TWO52[sx];
|
||||
}
|
||||
|
||||
static int freebsd_isnan(double d)
|
||||
{
|
||||
if (is_little_endian) {
|
||||
IEEEd2bits_L u;
|
||||
u.d = d;
|
||||
return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
|
||||
}
|
||||
else {
|
||||
IEEEd2bits_B u;
|
||||
u.d = d;
|
||||
return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
|
||||
}
|
||||
if (is_little_endian) {
|
||||
IEEEd2bits_L u;
|
||||
u.d = d;
|
||||
return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
|
||||
}
|
||||
else {
|
||||
IEEEd2bits_B u;
|
||||
u.d = d;
|
||||
return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
|
||||
}
|
||||
}
|
||||
|
||||
static double freebsd_fabs(double x)
|
||||
{
|
||||
u_int32_t high;
|
||||
GET_HIGH_WORD(high,x);
|
||||
SET_HIGH_WORD(x,high&0x7fffffff);
|
||||
return x;
|
||||
u_int32_t high;
|
||||
GET_HIGH_WORD(high,x);
|
||||
SET_HIGH_WORD(x,high&0x7fffffff);
|
||||
return x;
|
||||
}
|
||||
|
||||
double sqrt(double x)
|
||||
{
|
||||
return freebsd_sqrt(x);
|
||||
return freebsd_sqrt(x);
|
||||
}
|
||||
|
||||
double floor(double x)
|
||||
{
|
||||
return freebsd_floor(x);
|
||||
return freebsd_floor(x);
|
||||
}
|
||||
|
||||
double ceil(double x)
|
||||
{
|
||||
return freebsd_ceil(x);
|
||||
return freebsd_ceil(x);
|
||||
}
|
||||
|
||||
double fmin(double x, double y)
|
||||
{
|
||||
return x < y ? x : y;
|
||||
return x < y ? x : y;
|
||||
}
|
||||
|
||||
double fmax(double x, double y)
|
||||
{
|
||||
return x > y ? x : y;
|
||||
return x > y ? x : y;
|
||||
}
|
||||
|
||||
double rint(double x)
|
||||
{
|
||||
return freebsd_rint(x);
|
||||
return freebsd_rint(x);
|
||||
}
|
||||
|
||||
double fabs(double x)
|
||||
{
|
||||
return freebsd_fabs(x);
|
||||
return freebsd_fabs(x);
|
||||
}
|
||||
|
||||
int isnan(double x)
|
||||
{
|
||||
return freebsd_isnan(x);
|
||||
return freebsd_isnan(x);
|
||||
}
|
||||
|
||||
double trunc(double x)
|
||||
{
|
||||
return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x);
|
||||
return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x);
|
||||
}
|
||||
|
||||
int signbit(double x)
|
||||
{
|
||||
return ((__HI(x) & 0x80000000) >> 31);
|
||||
return ((__HI(x) & 0x80000000) >> 31);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "wasm-native.h"
|
||||
#include "wasm_native.h"
|
||||
|
||||
|
||||
void*
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm_runtime.h"
|
||||
|
||||
void invokeNative(uint32 argv[], uint32 argc, void (*native_code)())
|
||||
{
|
|
@ -18,9 +18,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "wasm.h"
|
||||
#include "wasm-interp.h"
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm-thread.h"
|
||||
#include "wasm_interp.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm_assert.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
|
@ -14,11 +14,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "wasm-interp.h"
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm-thread.h"
|
||||
#include "wasm-opcode.h"
|
||||
#include "wasm-loader.h"
|
||||
#include "wasm_interp.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm_opcode.h"
|
||||
#include "wasm_loader.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
||||
|
|
@ -14,11 +14,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "wasm-loader.h"
|
||||
#include "wasm_loader.h"
|
||||
#include "wasm.h"
|
||||
#include "wasm-native.h"
|
||||
#include "wasm-opcode.h"
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_opcode.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
||||
|
||||
|
@ -373,7 +373,10 @@ resolve_sym(const char *module_name, const char *field_name)
|
|||
return NULL;
|
||||
|
||||
if (field_name[0] == '_'
|
||||
&& (sym = wasm_dlsym(NULL, field_name + 1)))
|
||||
&& (sym = wasm_dlsym(NULL, field_name + 1)))
|
||||
return sym;
|
||||
|
||||
if ((sym = wasm_dlsym(NULL, field_name)))
|
||||
return sym;
|
||||
|
||||
return NULL;
|
|
@ -14,11 +14,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm-thread.h"
|
||||
#include "wasm-loader.h"
|
||||
#include "wasm-native.h"
|
||||
#include "wasm-interp.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm_loader.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_interp.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_platform_log.h"
|
||||
#include "wasm_memory.h"
|
|
@ -18,7 +18,7 @@
|
|||
#define _WASM_RUNTIME_H
|
||||
|
||||
#include "wasm.h"
|
||||
#include "wasm-thread.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wasm_hashmap.h"
|
||||
|
||||
#ifdef __cplusplus
|
|
@ -18,7 +18,7 @@
|
|||
#define _WASM_RUNTIME_THREAD_H
|
||||
|
||||
#include "wasm_assert.h"
|
||||
#include "wasm_thread.h"
|
||||
#include "wa_thread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
38
core/shared-lib/coap/LICENSE
Normal file
|
@ -0,0 +1,38 @@
|
|||
Contiki is licensed under the 3-clause BSD license. This license gives
|
||||
everyone the right to use and distribute the code, either in binary or
|
||||
source code format, as long as the copyright license is retained in
|
||||
the source code.
|
||||
|
||||
The copyright for different parts of the code is held by different
|
||||
people and organizations, but the code is licensed under the same type
|
||||
of license. The license text is:
|
||||
|
||||
* Copyright (c) (Year), (Name of copyright holder)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
19
core/shared-lib/coap/Makefile
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
COAP_ROOT=${ZEPHYR_BASE}/subsys/aee/Beihai/runtime/utils/coap
|
||||
subdir-ccflags-y += -I${COAP_ROOT}/er-coap -I${COAP_ROOT}/extension
|
||||
|
||||
obj-y += er-coap/
|
||||
obj-y += extension/
|
15
core/shared-lib/coap/er-coap/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
obj-y += er-coap.o
|
75
core/shared-lib/coap/er-coap/er-coap-conf.h
Executable file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Collection of default configuration values.
|
||||
* \author
|
||||
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#ifndef ER_COAP_CONF_H_
|
||||
#define ER_COAP_CONF_H_
|
||||
|
||||
/* Features that can be disabled to achieve smaller memory footprint */
|
||||
#define COAP_LINK_FORMAT_FILTERING 0
|
||||
#define COAP_PROXY_OPTION_PROCESSING 0
|
||||
|
||||
/* Listening port for the CoAP REST Engine */
|
||||
#ifndef COAP_SERVER_PORT
|
||||
#define COAP_SERVER_PORT COAP_DEFAULT_PORT
|
||||
#endif
|
||||
|
||||
/* The number of concurrent messages that can be stored for retransmission in the transaction layer. */
|
||||
#ifndef COAP_MAX_OPEN_TRANSACTIONS
|
||||
#define COAP_MAX_OPEN_TRANSACTIONS 4
|
||||
#endif /* COAP_MAX_OPEN_TRANSACTIONS */
|
||||
|
||||
/* Maximum number of failed request attempts before action */
|
||||
#ifndef COAP_MAX_ATTEMPTS
|
||||
#define COAP_MAX_ATTEMPTS 4
|
||||
#endif /* COAP_MAX_ATTEMPTS */
|
||||
|
||||
/* Conservative size limit, as not all options have to be set at the same time. Check when Proxy-Uri option is used */
|
||||
#ifndef COAP_MAX_HEADER_SIZE /* Hdr CoF If-Match Obs Blo strings */
|
||||
#define COAP_MAX_HEADER_SIZE 512
|
||||
//(4 + COAP_TOKEN_LEN + 3 + 1 + COAP_ETAG_LEN + 4 + 4 + 30) /* 65 */
|
||||
#endif /* COAP_MAX_HEADER_SIZE */
|
||||
|
||||
/* Number of observer slots (each takes abot xxx bytes) */
|
||||
#ifndef COAP_MAX_OBSERVERS
|
||||
#define COAP_MAX_OBSERVERS COAP_MAX_OPEN_TRANSACTIONS - 1
|
||||
#endif /* COAP_MAX_OBSERVERS */
|
||||
|
||||
/* Interval in notifies in which NON notifies are changed to CON notifies to check client. */
|
||||
#define COAP_OBSERVE_REFRESH_INTERVAL 20
|
||||
|
||||
#endif /* ER_COAP_CONF_H_ */
|
161
core/shared-lib/coap/er-coap/er-coap-constants.h
Executable file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Collection of constants specified in the CoAP standard.
|
||||
* \author
|
||||
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#ifndef ER_COAP_CONSTANTS_H_
|
||||
#define ER_COAP_CONSTANTS_H_
|
||||
|
||||
#define COAP_DEFAULT_PORT 5683
|
||||
|
||||
#define COAP_DEFAULT_MAX_AGE 60
|
||||
#define COAP_RESPONSE_TIMEOUT 3
|
||||
#define COAP_RESPONSE_RANDOM_FACTOR 1.5
|
||||
#define COAP_MAX_RETRANSMIT 4
|
||||
|
||||
#define COAP_HEADER_LEN 4 /* | version:0x03 type:0x0C tkl:0xF0 | code | mid:0x00FF | mid:0xFF00 | */
|
||||
#define COAP_TOKEN_LEN 8 /* The maximum number of bytes for the Token */
|
||||
#define COAP_ETAG_LEN 8 /* The maximum number of bytes for the ETag */
|
||||
|
||||
#define COAP_HEADER_VERSION_MASK 0xC0
|
||||
#define COAP_HEADER_VERSION_POSITION 6
|
||||
#define COAP_HEADER_TYPE_MASK 0x30
|
||||
#define COAP_HEADER_TYPE_POSITION 4
|
||||
#define COAP_HEADER_TOKEN_LEN_MASK 0x0F
|
||||
#define COAP_HEADER_TOKEN_LEN_POSITION 0
|
||||
|
||||
#define COAP_HEADER_OPTION_DELTA_MASK 0xF0
|
||||
#define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F
|
||||
|
||||
/* CoAP message types */
|
||||
typedef enum {
|
||||
COAP_TYPE_CON, /* confirmables */
|
||||
COAP_TYPE_NON, /* non-confirmables */
|
||||
COAP_TYPE_ACK, /* acknowledgements */
|
||||
COAP_TYPE_RST /* reset */
|
||||
} coap_message_type_t;
|
||||
|
||||
/* CoAP request method codes */
|
||||
typedef enum {
|
||||
COAP_GET = 1, COAP_POST, COAP_PUT, COAP_DELETE
|
||||
} coap_method_t;
|
||||
|
||||
/* CoAP response codes */
|
||||
typedef enum {
|
||||
NO_ERROR = 0,
|
||||
|
||||
CREATED_2_01 = 65, /* CREATED */
|
||||
DELETED_2_02 = 66, /* DELETED */
|
||||
VALID_2_03 = 67, /* NOT_MODIFIED */
|
||||
CHANGED_2_04 = 68, /* CHANGED */
|
||||
CONTENT_2_05 = 69, /* OK */
|
||||
CONTINUE_2_31 = 95, /* CONTINUE */
|
||||
|
||||
BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */
|
||||
UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */
|
||||
BAD_OPTION_4_02 = 130, /* BAD_OPTION */
|
||||
FORBIDDEN_4_03 = 131, /* FORBIDDEN */
|
||||
NOT_FOUND_4_04 = 132, /* NOT_FOUND */
|
||||
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
|
||||
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
|
||||
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
|
||||
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
|
||||
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */
|
||||
|
||||
INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */
|
||||
NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */
|
||||
BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */
|
||||
SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */
|
||||
GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */
|
||||
PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */
|
||||
|
||||
/* Erbium errors */
|
||||
MEMORY_ALLOCATION_ERROR = 192, PACKET_SERIALIZATION_ERROR,
|
||||
|
||||
/* Erbium hooks */
|
||||
MANUAL_RESPONSE, PING_RESPONSE
|
||||
} coap_status_t;
|
||||
|
||||
/* CoAP header option numbers */
|
||||
typedef enum {
|
||||
COAP_OPTION_IF_MATCH = 1, /* 0-8 B */
|
||||
COAP_OPTION_URI_HOST = 3, /* 1-255 B */
|
||||
COAP_OPTION_ETAG = 4, /* 1-8 B */
|
||||
COAP_OPTION_IF_NONE_MATCH = 5, /* 0 B */
|
||||
COAP_OPTION_OBSERVE = 6, /* 0-3 B */
|
||||
COAP_OPTION_URI_PORT = 7, /* 0-2 B */
|
||||
COAP_OPTION_LOCATION_PATH = 8, /* 0-255 B */
|
||||
COAP_OPTION_URI_PATH = 11, /* 0-255 B */
|
||||
COAP_OPTION_CONTENT_FORMAT = 12, /* 0-2 B */
|
||||
COAP_OPTION_MAX_AGE = 14, /* 0-4 B */
|
||||
COAP_OPTION_URI_QUERY = 15, /* 0-255 B */
|
||||
COAP_OPTION_ACCEPT = 17, /* 0-2 B */
|
||||
COAP_OPTION_LOCATION_QUERY = 20, /* 0-255 B */
|
||||
COAP_OPTION_BLOCK2 = 23, /* 1-3 B */
|
||||
COAP_OPTION_BLOCK1 = 27, /* 1-3 B */
|
||||
COAP_OPTION_SIZE2 = 28, /* 0-4 B */
|
||||
COAP_OPTION_PROXY_URI = 35, /* 1-1034 B */
|
||||
COAP_OPTION_PROXY_SCHEME = 39, /* 1-255 B */
|
||||
COAP_OPTION_SIZE1 = 60, /* 0-4 B */
|
||||
} coap_option_t;
|
||||
|
||||
/* CoAP Content-Formats */
|
||||
typedef enum {
|
||||
TEXT_PLAIN = 0,
|
||||
TEXT_XML = 1,
|
||||
TEXT_CSV = 2,
|
||||
TEXT_HTML = 3,
|
||||
IMAGE_GIF = 21,
|
||||
IMAGE_JPEG = 22,
|
||||
IMAGE_PNG = 23,
|
||||
IMAGE_TIFF = 24,
|
||||
AUDIO_RAW = 25,
|
||||
VIDEO_RAW = 26,
|
||||
APPLICATION_LINK_FORMAT = 40,
|
||||
APPLICATION_XML = 41,
|
||||
APPLICATION_OCTET_STREAM = 42,
|
||||
APPLICATION_RDF_XML = 43,
|
||||
APPLICATION_SOAP_XML = 44,
|
||||
APPLICATION_ATOM_XML = 45,
|
||||
APPLICATION_XMPP_XML = 46,
|
||||
APPLICATION_EXI = 47,
|
||||
APPLICATION_FASTINFOSET = 48,
|
||||
APPLICATION_SOAP_FASTINFOSET = 49,
|
||||
APPLICATION_JSON = 50,
|
||||
APPLICATION_X_OBIX_BINARY = 51
|
||||
} coap_content_format_t;
|
||||
|
||||
#endif /* ER_COAP_CONSTANTS_H_ */
|
1131
core/shared-lib/coap/er-coap/er-coap.c
Executable file
370
core/shared-lib/coap/er-coap/er-coap.h
Executable file
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* An implementation of the Constrained Application Protocol (RFC).
|
||||
* \author
|
||||
* Matthias Kovatsch <kovatsch@inf.ethz.ch>
|
||||
*/
|
||||
|
||||
#ifndef ER_COAP_H_
|
||||
#define ER_COAP_H_
|
||||
|
||||
#include "../extension/coap_platforms.h"
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include <stdint.h>
|
||||
//#include "contiki-net.h"
|
||||
#include "er-coap-constants.h"
|
||||
#include "er-coap-conf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* sanity check for configured values */
|
||||
#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + REST_MAX_CHUNK_SIZE)
|
||||
/*#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN)
|
||||
#error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE"
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* ------ section added by the coap request --------- */
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
//typedef int (*restful_response_handler)(void *response,void *data);
|
||||
#define RX_TIMEOUT (-1)
|
||||
typedef int (*Tx_Data)(void * coap_ctx, const uip_ipaddr_t *dst_addr, void *buf, int len);
|
||||
typedef int (*Rx_Data) (void * coap_ctx, void *buf, int len, int timeout);
|
||||
typedef int (*Request_Handler) (void * coap_ctx, void *);
|
||||
|
||||
typedef int (*CoAP_Res_Handler) (void * request, void * response, char **out_payload, int * payload_len);
|
||||
|
||||
typedef struct _coap_resource_handler
|
||||
{
|
||||
struct _coap_resource_handler * next;
|
||||
char * url;
|
||||
CoAP_Res_Handler get_handler;
|
||||
CoAP_Res_Handler put_handler;
|
||||
CoAP_Res_Handler post_handler;
|
||||
CoAP_Res_Handler other_handler; // create | delete
|
||||
}coap_resource_handler_t;
|
||||
|
||||
|
||||
|
||||
typedef struct res_block_state
|
||||
{
|
||||
struct res_block_state * next;
|
||||
char * url;
|
||||
void * buffer;
|
||||
int buffer_size;
|
||||
uint32_t block_num;
|
||||
uint16_t block_size;
|
||||
uint16_t content_fmt;
|
||||
uint32_t last_access;
|
||||
uint8_t is_get;
|
||||
} res_block_state_t;
|
||||
|
||||
|
||||
typedef struct peer_block_state
|
||||
{
|
||||
struct peer_block_state * next;
|
||||
struct net_addr_coap peer_addr;
|
||||
res_block_state_t * list;
|
||||
}peer_block_state_t;
|
||||
|
||||
|
||||
typedef struct coap_context {
|
||||
uint8_t * buf;
|
||||
uint32_t buf_len; // the data length
|
||||
uint32_t buf_size; // the malloced buffer size
|
||||
|
||||
struct net_addr_coap my_addr;
|
||||
|
||||
// the address associated with current buffer
|
||||
struct net_addr_coap src_addr;
|
||||
|
||||
uint8_t status;
|
||||
uint8_t is_used;
|
||||
uint8_t response_on_not_found;
|
||||
uint16_t default_retrans_cnt;
|
||||
uint32_t default_retrans_ms;
|
||||
|
||||
Tx_Data tx_data;
|
||||
Rx_Data rx_data;
|
||||
|
||||
int socket;
|
||||
char * user_data;
|
||||
|
||||
peer_block_state_t * blockwise_list;
|
||||
coap_resource_handler_t * resource_handlers;
|
||||
|
||||
void * transactions;
|
||||
void * transaction_lock;
|
||||
uint32_t last_checktime;
|
||||
|
||||
void * request_handler;
|
||||
|
||||
#ifdef WITH_DTLS
|
||||
struct dtls_context_t *dtls_context;
|
||||
dtls_handler_t dtls_handler;
|
||||
struct process *process;
|
||||
#endif /* WITH_DTLS */
|
||||
|
||||
} coap_context_t;
|
||||
|
||||
int add_resource_handler(coap_context_t * coap_ctx, coap_resource_handler_t * handler);
|
||||
|
||||
|
||||
// coap_context_t * coap_context_new(uip_ipaddr_t *my_addr, uint16_t my_port); //CANNOTBUILD
|
||||
void coap_context_close(coap_context_t *coap_ctx);
|
||||
void coap_ctx_send(coap_context_t *coap_ctx, uint8_t *data,
|
||||
uint16_t length);
|
||||
|
||||
/* ---------------- end of section ------------------ */
|
||||
|
||||
|
||||
/* use Erbium CoAP for the REST Engine. Must come before include of rest-engine.h. */
|
||||
//#define REST coap_rest_implementation
|
||||
//#include "rest-engine.h"
|
||||
|
||||
/* REST_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */
|
||||
#ifndef COAP_MAX_BLOCK_SIZE
|
||||
#define COAP_MAX_BLOCK_SIZE (REST_MAX_CHUNK_SIZE < 32 ? 16 : \
|
||||
(REST_MAX_CHUNK_SIZE < 64 ? 32 : \
|
||||
(REST_MAX_CHUNK_SIZE < 128 ? 64 : \
|
||||
(REST_MAX_CHUNK_SIZE < 256 ? 128 : \
|
||||
(REST_MAX_CHUNK_SIZE < 512 ? 256 : \
|
||||
(REST_MAX_CHUNK_SIZE < 1024 ? 512 : \
|
||||
(REST_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048)))))))
|
||||
#endif /* COAP_MAX_BLOCK_SIZE */
|
||||
|
||||
/* direct access into the buffer */
|
||||
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
#ifdef NETSTACK_CONF_WITH_IPV6
|
||||
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
|
||||
#else
|
||||
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
|
||||
#endif
|
||||
|
||||
/* bitmap for set options */
|
||||
enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 };
|
||||
|
||||
#define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE))
|
||||
#define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE)))
|
||||
|
||||
/* parsed message struct */
|
||||
typedef struct {
|
||||
uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */
|
||||
|
||||
uint8_t version;
|
||||
coap_message_type_t type;
|
||||
uint8_t code;
|
||||
uint16_t mid;
|
||||
|
||||
uint8_t token_len;
|
||||
uint8_t token[COAP_TOKEN_LEN];
|
||||
|
||||
uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */
|
||||
|
||||
coap_content_format_t content_format; /* parse options once and store; allows setting options in random order */
|
||||
uint32_t max_age;
|
||||
uint8_t etag_len;
|
||||
uint8_t etag[COAP_ETAG_LEN];
|
||||
size_t proxy_uri_len;
|
||||
const char *proxy_uri;
|
||||
size_t proxy_scheme_len;
|
||||
const char *proxy_scheme;
|
||||
size_t uri_host_len;
|
||||
const char *uri_host;
|
||||
size_t location_path_len;
|
||||
const char *location_path;
|
||||
uint16_t uri_port;
|
||||
size_t location_query_len;
|
||||
const char *location_query;
|
||||
size_t uri_path_len;
|
||||
const char *uri_path;
|
||||
int32_t observe;
|
||||
coap_content_format_t accept;
|
||||
uint8_t if_match_len;
|
||||
uint8_t if_match[COAP_ETAG_LEN];
|
||||
uint32_t block2_num;
|
||||
uint8_t block2_more;
|
||||
uint32_t block2_size;
|
||||
uint32_t block2_offset;
|
||||
uint32_t block1_num;
|
||||
uint8_t block1_more;
|
||||
uint32_t block1_size;
|
||||
uint32_t block1_offset;
|
||||
uint32_t size2;
|
||||
uint32_t size1;
|
||||
size_t uri_query_len;
|
||||
const char *uri_query;
|
||||
uint8_t if_none_match;
|
||||
|
||||
uint32_t payload_len;
|
||||
uint8_t *payload;
|
||||
} coap_packet_t;
|
||||
|
||||
/* option format serialization */
|
||||
#define COAP_SERIALIZE_INT_OPTION(number, field, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) { \
|
||||
PRINTF(text " [%u]\n", coap_pkt->field); \
|
||||
option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \
|
||||
current_number = number; \
|
||||
}
|
||||
#define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) { \
|
||||
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->field##_len, \
|
||||
coap_pkt->field[0], \
|
||||
coap_pkt->field[1], \
|
||||
coap_pkt->field[2], \
|
||||
coap_pkt->field[3], \
|
||||
coap_pkt->field[4], \
|
||||
coap_pkt->field[5], \
|
||||
coap_pkt->field[6], \
|
||||
coap_pkt->field[7] \
|
||||
); /* FIXME always prints 8 bytes */ \
|
||||
option += coap_serialize_array_option(number, current_number, option, coap_pkt->field, coap_pkt->field##_len, '\0'); \
|
||||
current_number = number; \
|
||||
}
|
||||
#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) { \
|
||||
PRINTF(text " [%.*s]\n", coap_pkt->field##_len, coap_pkt->field); \
|
||||
option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \
|
||||
current_number = number; \
|
||||
}
|
||||
#define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \
|
||||
if(IS_OPTION(coap_pkt, number)) \
|
||||
{ \
|
||||
PRINTF(text " [%lu%s (%u B/blk)]\n", coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
|
||||
uint32_t block = coap_pkt->field##_num << 4; \
|
||||
if(coap_pkt->field##_more) { block |= 0x8; } \
|
||||
block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \
|
||||
PRINTF(text " encoded: 0x%lX\n", block); \
|
||||
option += coap_serialize_int_option(number, current_number, option, block); \
|
||||
current_number = number; \
|
||||
}
|
||||
|
||||
/* to store error code and human-readable payload */
|
||||
extern coap_status_t erbium_status_code;
|
||||
extern char *coap_error_message;
|
||||
|
||||
void coap_init_connection(uint16_t port);
|
||||
uint16_t coap_get_mid(void);
|
||||
|
||||
void coap_init_message(void *packet, coap_message_type_t type, uint8_t code,
|
||||
uint16_t mid);
|
||||
size_t coap_serialize_message(void *packet, uint8_t *buffer);
|
||||
void coap_send_message(coap_context_t*, uip_ipaddr_t *addr, uint16_t port, uint8_t *data,
|
||||
uint16_t length);
|
||||
coap_status_t coap_parse_message(void *request, uint8_t *data,
|
||||
uint16_t data_len);
|
||||
|
||||
int coap_get_query_variable(void *packet, const char *name,
|
||||
const char **output);
|
||||
int coap_get_post_variable(void *packet, const char *name,
|
||||
const char **output);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
int coap_set_status_code(void *packet, unsigned int code);
|
||||
|
||||
int coap_set_token(void *packet, const uint8_t *token, size_t token_len);
|
||||
|
||||
int coap_get_header_content_format(void *packet, unsigned int *format);
|
||||
int coap_set_header_content_format(void *packet, unsigned int format);
|
||||
|
||||
int coap_get_header_accept(void *packet, unsigned int *accept);
|
||||
int coap_set_header_accept(void *packet, unsigned int accept);
|
||||
|
||||
int coap_get_header_max_age(void *packet, uint32_t *age);
|
||||
int coap_set_header_max_age(void *packet, uint32_t age);
|
||||
|
||||
int coap_get_header_etag(void *packet, const uint8_t **etag);
|
||||
int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len);
|
||||
|
||||
int coap_get_header_if_match(void *packet, const uint8_t **etag);
|
||||
int coap_set_header_if_match(void *packet, const uint8_t *etag,
|
||||
size_t etag_len);
|
||||
|
||||
int coap_get_header_if_none_match(void *packet);
|
||||
int coap_set_header_if_none_match(void *packet);
|
||||
|
||||
int coap_get_header_proxy_uri(void *packet, const char **uri); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_proxy_uri(void *packet, const char *uri);
|
||||
|
||||
int coap_get_header_proxy_scheme(void *packet, const char **scheme); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_proxy_scheme(void *packet, const char *scheme);
|
||||
|
||||
int coap_get_header_uri_host(void *packet, const char **host); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_uri_host(void *packet, const char *host);
|
||||
|
||||
int coap_get_header_uri_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_uri_path(void *packet, const char *path);
|
||||
|
||||
int coap_get_header_uri_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_uri_query(void *packet, const char *query);
|
||||
|
||||
int coap_get_header_location_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_location_path(void *packet, const char *path); /* also splits optional query into Location-Query option. */
|
||||
|
||||
int coap_get_header_location_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */
|
||||
int coap_set_header_location_query(void *packet, const char *query);
|
||||
|
||||
int coap_get_header_observe(void *packet, uint32_t *observe);
|
||||
int coap_set_header_observe(void *packet, uint32_t observe);
|
||||
|
||||
int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more,
|
||||
uint32_t *size, uint32_t *offset);
|
||||
int coap_set_header_block2(void *packet, uint32_t num, uint8_t more,
|
||||
uint32_t size);
|
||||
|
||||
int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more,
|
||||
uint16_t *size, uint32_t *offset);
|
||||
int coap_set_header_block1(void *packet, uint32_t num, uint8_t more,
|
||||
uint16_t size);
|
||||
|
||||
int coap_get_header_size2(void *packet, uint32_t *size);
|
||||
int coap_set_header_size2(void *packet, uint32_t size);
|
||||
|
||||
int coap_get_header_size1(void *packet, uint32_t *size);
|
||||
int coap_set_header_size1(void *packet, uint32_t size);
|
||||
|
||||
int coap_get_payload(void *packet, const uint8_t **payload);
|
||||
int coap_set_payload(void *packet, const void *payload, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ER_COAP_H_ */
|
15
core/shared-lib/coap/extension/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
obj-y += coap_over_tcp.o
|
105
core/shared-lib/coap/extension/coap_conversion.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "coap_ext.h"
|
||||
|
||||
char * coap_get_full_url_alloc(coap_packet_t * request)
|
||||
{
|
||||
const char *url = NULL;
|
||||
const char * query = NULL;
|
||||
int url_len = coap_get_header_uri_path(request, &url);
|
||||
int query_len = coap_get_header_uri_query(request, &query);
|
||||
|
||||
if (url_len == 0)
|
||||
return NULL;
|
||||
|
||||
char * url_alloc = (char*) bh_malloc(url_len + 1 + query_len + 1);
|
||||
memcpy(url_alloc, url, url_len);
|
||||
url_alloc[url_len] = 0;
|
||||
|
||||
// make the url looks like /abc?e=f
|
||||
if (query_len != 0) {
|
||||
strcat(url_alloc, "&");
|
||||
memcpy(url_alloc + strlen(url_alloc), query, query_len);
|
||||
url_alloc[url_len + 1 + query_len] = 0;
|
||||
}
|
||||
|
||||
return url_alloc;
|
||||
}
|
||||
|
||||
void convert_request_to_coap_packet(request_t * req, coap_packet_t * packet)
|
||||
{
|
||||
coap_init_message(packet, COAP_TYPE_NON, req->action, req->mid);
|
||||
coap_set_token(packet, (uint8_t *) &req->mid, sizeof(req->mid));
|
||||
coap_set_header_content_format(packet, req->fmt);
|
||||
|
||||
coap_set_header_uri_path(packet, req->url);
|
||||
|
||||
coap_set_payload(packet, req->payload, req->payload_len);
|
||||
|
||||
packet->mid = req->mid;
|
||||
}
|
||||
|
||||
void convert_response_to_coap_packet(response_t * response,
|
||||
coap_packet_t * packet)
|
||||
{
|
||||
coap_init_message(packet, COAP_TYPE_NON, response->status, response->mid);
|
||||
coap_set_token(packet, (uint8_t *) &response->mid, sizeof(response->mid));
|
||||
coap_set_header_content_format(packet, response->fmt);
|
||||
coap_set_payload(packet, response->payload, response->payload_len);
|
||||
|
||||
packet->mid = response->mid;
|
||||
}
|
||||
|
||||
// return: the length of url.
|
||||
// note: the url is probably not end with 0 due to coap packing design.
|
||||
int convert_coap_packet_to_request(coap_packet_t *packet, request_t *request)
|
||||
{
|
||||
const char *url = NULL;
|
||||
int url_len = coap_get_header_uri_path(packet, &url);
|
||||
|
||||
memset(request, 0, sizeof(*request));
|
||||
|
||||
request->action = packet->code;
|
||||
request->fmt = packet->content_format;
|
||||
if (packet->token_len == 4) {
|
||||
request->mid = *((unsigned long *) packet->token);
|
||||
} else {
|
||||
request->mid = packet->mid;
|
||||
}
|
||||
request->payload = packet->payload;
|
||||
request->payload_len = packet->payload_len;
|
||||
request->url = (char *)url;
|
||||
return url_len;
|
||||
}
|
||||
|
||||
void convert_coap_packet_to_response(coap_packet_t *packet,
|
||||
response_t *response)
|
||||
{
|
||||
memset(response, 0, sizeof(*response));
|
||||
|
||||
response->status = packet->code;
|
||||
response->fmt = packet->content_format;
|
||||
if (packet->token_len == 4) {
|
||||
response->mid = *((unsigned long *) packet->token);
|
||||
} else {
|
||||
response->mid = packet->mid;
|
||||
}
|
||||
|
||||
response->payload = packet->payload;
|
||||
response->payload_len = packet->payload_len;
|
||||
return;
|
||||
}
|
57
core/shared-lib/coap/extension/coap_ext.h
Executable file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COAP_EXTENSION_COAP_EXT_H_
|
||||
#define COAP_EXTENSION_COAP_EXT_H_
|
||||
|
||||
#include "er-coap.h"
|
||||
#include "shared_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define COAP_EVENT (COAP_DELETE + 2)
|
||||
|
||||
char * coap_get_full_url_alloc(coap_packet_t * request);
|
||||
|
||||
coap_status_t coap_parse_message_tcp(void *packet, uint8_t *data,
|
||||
uint32_t data_len);
|
||||
|
||||
int coap_serialize_message_tcp(void *packet, uint8_t ** buffer_out);
|
||||
int coap_set_payload_tcp(void *packet, const void *payload, size_t length);
|
||||
uint8_t coap_is_request(coap_packet_t * coap_message);
|
||||
|
||||
uint16_t coap_find_mid(uint8_t *buffer);
|
||||
uint8_t coap_find_code(uint8_t *buffer);
|
||||
void coap_change_mid(uint8_t *buffer, uint16_t id);
|
||||
|
||||
int add_resource_handler(coap_context_t * coap_ctx,
|
||||
coap_resource_handler_t * handler);
|
||||
uint32_t check_blockwise_timeout_ms(coap_context_t * coap_ctx, int timeout_sec);
|
||||
|
||||
int convert_coap_packet_to_request(coap_packet_t *packet, request_t *request);
|
||||
void convert_coap_packet_to_response(coap_packet_t *packet,
|
||||
response_t *response);
|
||||
|
||||
void convert_response_to_coap_packet(response_t * response,
|
||||
coap_packet_t * packet);
|
||||
void convert_request_to_coap_packet(request_t * req, coap_packet_t * packet);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* COAP_EXTENSION_COAP_EXT_H_ */
|
481
core/shared-lib/coap/extension/coap_over_tcp.c
Executable file
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "bh_common.h"
|
||||
#include "er-coap.h"
|
||||
#include "coap_ext.h"
|
||||
#include "er-coap-constants.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
|
||||
#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#define PRINT6ADDR(addr)
|
||||
#define PRINTLLADDR(addr)
|
||||
#endif
|
||||
|
||||
extern size_t
|
||||
coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
||||
uint8_t *buffer, uint8_t *array, size_t length, char split_char);
|
||||
extern size_t
|
||||
coap_serialize_int_option(unsigned int number, unsigned int current_number,
|
||||
uint8_t *buffer, uint32_t value);
|
||||
extern uint16_t coap_log_2(uint16_t value);
|
||||
extern uint32_t coap_parse_int_option(uint8_t *bytes, size_t length);
|
||||
extern void
|
||||
coap_merge_multi_option(char **dst, size_t *dst_len, uint8_t *option,
|
||||
size_t option_len, char separator);
|
||||
|
||||
/*
|
||||
*
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Len=15 | TKL | Extended Length (32 bits)
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| | Code | Token (if any, TKL bytes) ...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Options (if any) ...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|1 1 1 1 1 1 1 1| Payload (if any) ...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
*/
|
||||
|
||||
int coap_set_payload_tcp(void *packet, const void *payload, size_t length)
|
||||
{
|
||||
coap_packet_t * const coap_pkt = (coap_packet_t *) packet;
|
||||
|
||||
coap_pkt->payload = (uint8_t *) payload;
|
||||
coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length);
|
||||
|
||||
return coap_pkt->payload_len;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static size_t coap_calc_ext_len_field(int len)
|
||||
{
|
||||
if(len < 13)
|
||||
return 0;
|
||||
else if(len <= (0xFF+13))
|
||||
return 1;
|
||||
else if(len <= (0xFFFF+269))
|
||||
return 2;
|
||||
else if(len < (0xFFFFFFFF+65805))
|
||||
return 4;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t coap_max_options_offset(void *packet)
|
||||
{
|
||||
coap_packet_t * const coap_pkt = (coap_packet_t *) packet;
|
||||
return 6 + coap_pkt->token_len;
|
||||
}
|
||||
|
||||
int coap_serialize_message_tcp(void *packet, uint8_t ** buffer_out)
|
||||
{
|
||||
coap_packet_t * const coap_pkt = (coap_packet_t *) packet;
|
||||
uint8_t buffer[128];
|
||||
|
||||
uint8_t *option = buffer;
|
||||
unsigned int current_number = 0;
|
||||
|
||||
if (coap_pkt->uri_path_len > 100) {
|
||||
*buffer_out = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Serialize options */
|
||||
current_number = 0;
|
||||
if (0 == coap_pkt->token_len) {
|
||||
bh_memcpy_s(coap_pkt->token, COAP_TOKEN_LEN, &coap_pkt->mid,
|
||||
sizeof(coap_pkt->mid));
|
||||
coap_pkt->token_len = sizeof(coap_pkt->mid);
|
||||
}PRINTF("-Serializing options at %p-\n", option);
|
||||
|
||||
/* The options must be serialized in the order of their number */
|
||||
COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_HOST, uri_host, '\0',
|
||||
"Uri-Host");
|
||||
COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_ETAG, etag, "ETag");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_IF_NONE_MATCH,
|
||||
content_format - coap_pkt-> content_format /* hack to get a zero field */,
|
||||
"If-None-Match");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_OBSERVE, observe, "Observe");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_URI_PORT, uri_port, "Uri-Port");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_PATH, location_path, '/',
|
||||
"Location-Path");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, 0, //'/',
|
||||
"Uri-Path");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
|
||||
"Content-Format");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_QUERY, uri_query, '&',
|
||||
"Uri-Query");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_ACCEPT, accept, "Accept");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_QUERY, location_query,
|
||||
'&', "Location-Query");
|
||||
COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK2, block2, "Block2");
|
||||
COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK1, block1, "Block1");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE2, size2, "Size2");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_URI, proxy_uri, '\0',
|
||||
"Proxy-Uri");
|
||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_SCHEME, proxy_scheme, '\0',
|
||||
"Proxy-Scheme");
|
||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1");
|
||||
|
||||
/* Pack payload */
|
||||
if (coap_pkt->payload_len) {
|
||||
*option = 0xFF;
|
||||
++option;
|
||||
}
|
||||
uint32_t option_len = option - &buffer[0];
|
||||
|
||||
uint8_t * p = (uint8_t *) os_malloc(
|
||||
coap_max_options_offset(packet) + option_len
|
||||
+ coap_pkt->payload_len);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
*buffer_out = p;
|
||||
|
||||
uint8_t first_4bits;
|
||||
|
||||
*p = (coap_pkt->token_len & 0xF);
|
||||
uint32_t len = option_len + coap_pkt->payload_len;
|
||||
|
||||
if (len < 13) {
|
||||
first_4bits = len;
|
||||
*p++ |= first_4bits << 4;
|
||||
} else if (len <= (0xFF + 13)) {
|
||||
first_4bits = 13;
|
||||
*p++ |= first_4bits << 4;
|
||||
*p++ = len - 13;
|
||||
} else if (len <= (0xFFFF + 269)) {
|
||||
first_4bits = 14;
|
||||
*p++ |= first_4bits << 4;
|
||||
len -= 269;
|
||||
*p = (uint8_t)(len >> 8);
|
||||
p++;
|
||||
*p = (uint8_t)(len & 0xFF);
|
||||
p++;
|
||||
} else {
|
||||
first_4bits = 15;
|
||||
*p++ |= first_4bits << 4;
|
||||
|
||||
len -= 65805;
|
||||
*p++ = (uint8_t)(len >> 24);
|
||||
*p++ = (uint8_t)(len >> 16);
|
||||
*p++ = (uint8_t)(len >> 8);
|
||||
*p++ = (uint8_t)(len & 0xFF);
|
||||
}
|
||||
|
||||
*p = coap_pkt->code;
|
||||
p++;
|
||||
|
||||
if (coap_pkt->token_len)
|
||||
bh_memcpy_s(p, coap_pkt->token_len, coap_pkt->token,
|
||||
coap_pkt->token_len);
|
||||
p += coap_pkt->token_len;
|
||||
|
||||
bh_memcpy_s(p, option_len, buffer, option_len);
|
||||
p += option_len;
|
||||
|
||||
bh_memcpy_s(p, coap_pkt->payload_len, coap_pkt->payload,
|
||||
coap_pkt->payload_len);
|
||||
p += coap_pkt->payload_len;
|
||||
|
||||
return (p - *buffer_out); /* packet length */
|
||||
}
|
||||
|
||||
coap_status_t coap_parse_message_tcp(void *packet, uint8_t *data,
|
||||
uint32_t data_len)
|
||||
{
|
||||
coap_packet_t * const coap_pkt = (coap_packet_t *) packet;
|
||||
|
||||
/* initialize packet */
|
||||
memset(coap_pkt, 0, sizeof(coap_packet_t));
|
||||
|
||||
/* pointer to packet bytes */
|
||||
coap_pkt->buffer = data;
|
||||
|
||||
/* parse header fields */
|
||||
coap_pkt->version = 1;
|
||||
coap_pkt->type = COAP_TYPE_NON;
|
||||
coap_pkt->token_len = MIN(COAP_TOKEN_LEN, data[0] & 0xF);
|
||||
coap_pkt->mid = 0;
|
||||
|
||||
uint8_t *p = data;
|
||||
uint8_t first_4bits = data[0] >> 4;
|
||||
|
||||
uint32_t options_payload_size;
|
||||
uint8_t ext_len_field = 0;
|
||||
if (first_4bits < 13) {
|
||||
options_payload_size = first_4bits;
|
||||
p++;
|
||||
} else if (first_4bits == 13) {
|
||||
ext_len_field = 1;
|
||||
options_payload_size = data[1] + 13;
|
||||
p += 2;
|
||||
} else if (first_4bits == 14) {
|
||||
ext_len_field = 2;
|
||||
options_payload_size = (uint16_t)(data[1] << 8) + data[2] + 269;
|
||||
p += 3;
|
||||
} else if (first_4bits == 15) {
|
||||
ext_len_field = 4;
|
||||
options_payload_size = (data[1] << 24) + (data[2] << 16)
|
||||
+ (data[3] << 8) + data[4] + 65805;
|
||||
p += 5;
|
||||
}
|
||||
|
||||
// check the data size is smaller than the size indicated by the packet
|
||||
if (ext_len_field + coap_pkt->token_len + 2 + options_payload_size
|
||||
> data_len)
|
||||
return BAD_REQUEST_4_00;
|
||||
|
||||
coap_pkt->code = *p++;
|
||||
if (coap_pkt->token_len)
|
||||
bh_memcpy_s(coap_pkt->token, COAP_TOKEN_LEN, p, coap_pkt->token_len);
|
||||
|
||||
if (coap_pkt->token_len >= 2) {
|
||||
union {
|
||||
uint16_t *mid;
|
||||
uint8_t *token;
|
||||
} mid_token_union;
|
||||
|
||||
mid_token_union.token = coap_pkt->token;
|
||||
coap_pkt->mid = *(mid_token_union.mid);
|
||||
}
|
||||
|
||||
p += coap_pkt->token_len;
|
||||
|
||||
uint8_t *current_option = p;
|
||||
uint8_t * option_start = p;
|
||||
|
||||
/* parse options */
|
||||
memset(coap_pkt->options, 0, sizeof(coap_pkt->options));
|
||||
|
||||
unsigned int option_number = 0;
|
||||
unsigned int option_delta = 0;
|
||||
size_t option_length = 0;
|
||||
|
||||
while (current_option < data + data_len) {
|
||||
/* payload marker 0xFF, currently only checking for 0xF* because rest is reserved */
|
||||
if ((current_option[0] & 0xF0) == 0xF0) {
|
||||
coap_pkt->payload = ++current_option;
|
||||
coap_pkt->payload_len = options_payload_size
|
||||
- (coap_pkt->payload - option_start);
|
||||
//coap_pkt->payload_len = data_len - (coap_pkt->payload - data);
|
||||
break;
|
||||
}
|
||||
|
||||
option_delta = current_option[0] >> 4;
|
||||
option_length = current_option[0] & 0x0F;
|
||||
++current_option;
|
||||
|
||||
/* avoids code duplication without function overhead */
|
||||
unsigned int *x = &option_delta;
|
||||
|
||||
do {
|
||||
if (*x == 13) {
|
||||
*x += current_option[0];
|
||||
++current_option;
|
||||
} else if (*x == 14) {
|
||||
*x += 255;
|
||||
*x += current_option[0] << 8;
|
||||
++current_option;
|
||||
*x += current_option[0];
|
||||
++current_option;
|
||||
}
|
||||
} while (x != (unsigned int*) &option_length && (x =
|
||||
(unsigned int*) &option_length));
|
||||
option_length = *x;
|
||||
option_number += option_delta;
|
||||
|
||||
PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta,
|
||||
option_length);
|
||||
|
||||
SET_OPTION(coap_pkt, option_number);
|
||||
|
||||
switch (option_number) {
|
||||
|
||||
case COAP_OPTION_CONTENT_FORMAT:
|
||||
coap_pkt->content_format = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Content-Format [%u]\n", coap_pkt->content_format);
|
||||
break;
|
||||
case COAP_OPTION_MAX_AGE:
|
||||
coap_pkt->max_age = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Max-Age [%lu]\n", coap_pkt->max_age);
|
||||
break;
|
||||
case COAP_OPTION_ETAG:
|
||||
coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
|
||||
bh_memcpy_s(coap_pkt->etag, COAP_ETAG_LEN, current_option,
|
||||
coap_pkt->etag_len);
|
||||
PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
|
||||
coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1],
|
||||
coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4],
|
||||
coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7]
|
||||
); /*FIXME always prints 8 bytes */
|
||||
break;
|
||||
case COAP_OPTION_ACCEPT:
|
||||
coap_pkt->accept = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Accept [%u]\n", coap_pkt->accept);
|
||||
break;
|
||||
case COAP_OPTION_IF_MATCH:
|
||||
/* TODO support multiple ETags */
|
||||
coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length);
|
||||
bh_memcpy_s(coap_pkt->if_match, COAP_ETAG_LEN, current_option,
|
||||
coap_pkt->if_match_len);
|
||||
PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
|
||||
coap_pkt->if_match_len, coap_pkt->if_match[0],
|
||||
coap_pkt->if_match[1], coap_pkt->if_match[2],
|
||||
coap_pkt->if_match[3], coap_pkt->if_match[4],
|
||||
coap_pkt->if_match[5], coap_pkt->if_match[6],
|
||||
coap_pkt->if_match[7]
|
||||
); /* FIXME always prints 8 bytes */
|
||||
break;
|
||||
case COAP_OPTION_IF_NONE_MATCH:
|
||||
coap_pkt->if_none_match = 1;
|
||||
PRINTF("If-None-Match\n");
|
||||
break;
|
||||
|
||||
case COAP_OPTION_PROXY_URI:
|
||||
#if COAP_PROXY_OPTION_PROCESSING
|
||||
coap_pkt->proxy_uri = (char *)current_option;
|
||||
coap_pkt->proxy_uri_len = option_length;
|
||||
#endif
|
||||
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len,
|
||||
coap_pkt->proxy_uri);
|
||||
coap_error_message = "This is a constrained server (Contiki)";
|
||||
return PROXYING_NOT_SUPPORTED_5_05;
|
||||
break;
|
||||
case COAP_OPTION_PROXY_SCHEME:
|
||||
#if COAP_PROXY_OPTION_PROCESSING
|
||||
coap_pkt->proxy_scheme = (char *)current_option;
|
||||
coap_pkt->proxy_scheme_len = option_length;
|
||||
#endif
|
||||
PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n",
|
||||
coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
|
||||
coap_error_message = "This is a constrained server (Contiki)";
|
||||
return PROXYING_NOT_SUPPORTED_5_05;
|
||||
break;
|
||||
|
||||
case COAP_OPTION_URI_HOST:
|
||||
coap_pkt->uri_host = (char *) current_option;
|
||||
coap_pkt->uri_host_len = option_length;
|
||||
PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host);
|
||||
break;
|
||||
case COAP_OPTION_URI_PORT:
|
||||
coap_pkt->uri_port = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port);
|
||||
break;
|
||||
case COAP_OPTION_URI_PATH:
|
||||
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
||||
coap_merge_multi_option((char **) &(coap_pkt->uri_path),
|
||||
&(coap_pkt->uri_path_len), current_option, option_length,
|
||||
'/');
|
||||
PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path);
|
||||
break;
|
||||
case COAP_OPTION_URI_QUERY:
|
||||
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
||||
coap_merge_multi_option((char **) &(coap_pkt->uri_query),
|
||||
&(coap_pkt->uri_query_len), current_option, option_length,
|
||||
'&');
|
||||
PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len,
|
||||
coap_pkt->uri_query);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_LOCATION_PATH:
|
||||
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
||||
coap_merge_multi_option((char **) &(coap_pkt->location_path),
|
||||
&(coap_pkt->location_path_len), current_option,
|
||||
option_length, '/');
|
||||
PRINTF("Location-Path [%.*s]\n", coap_pkt->location_path_len,
|
||||
coap_pkt->location_path);
|
||||
break;
|
||||
case COAP_OPTION_LOCATION_QUERY:
|
||||
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
||||
coap_merge_multi_option((char **) &(coap_pkt->location_query),
|
||||
&(coap_pkt->location_query_len), current_option,
|
||||
option_length, '&');
|
||||
PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len,
|
||||
coap_pkt->location_query);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_OBSERVE:
|
||||
coap_pkt->observe = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Observe [%lu]\n", coap_pkt->observe);
|
||||
break;
|
||||
case COAP_OPTION_BLOCK2:
|
||||
coap_pkt->block2_num = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
coap_pkt->block2_more = (coap_pkt->block2_num & 0x08) >> 3;
|
||||
coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07);
|
||||
coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
|
||||
<< (coap_pkt->block2_num & 0x07);
|
||||
coap_pkt->block2_num >>= 4;
|
||||
PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num,
|
||||
coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
|
||||
break;
|
||||
case COAP_OPTION_BLOCK1:
|
||||
coap_pkt->block1_num = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
coap_pkt->block1_more = (coap_pkt->block1_num & 0x08) >> 3;
|
||||
coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07);
|
||||
coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
|
||||
<< (coap_pkt->block1_num & 0x07);
|
||||
coap_pkt->block1_num >>= 4;
|
||||
PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num,
|
||||
coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
|
||||
break;
|
||||
case COAP_OPTION_SIZE2:
|
||||
coap_pkt->size2 = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Size2 [%lu]\n", coap_pkt->size2);
|
||||
break;
|
||||
case COAP_OPTION_SIZE1:
|
||||
coap_pkt->size1 = coap_parse_int_option(current_option,
|
||||
option_length);
|
||||
PRINTF("Size1 [%lu]\n", coap_pkt->size1);
|
||||
break;
|
||||
default:
|
||||
PRINTF("unknown (%u)\n", option_number);
|
||||
/* check if critical (odd) */
|
||||
if (option_number & 1) {
|
||||
coap_error_message = "Unsupported critical option";
|
||||
return BAD_OPTION_4_02;
|
||||
}
|
||||
}
|
||||
|
||||
current_option += option_length;
|
||||
} /* for */
|
||||
PRINTF("-Done parsing-------\n");
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
89
core/shared-lib/coap/extension/coap_platforms.h
Executable file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COAP_PLATFORMS_H_
|
||||
#define COAP_PLATFORMS_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "bh_platform.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
/*#include "list_coap.h"*/
|
||||
#include <stdbool.h>
|
||||
|
||||
#define COAP_TRANS_LOCK(ctx) coap_lock(ctx->transaction_lock)
|
||||
#define COAP_TRANS_UNLOCK(ctx ) coap_unlock(ctx->transaction_lock)
|
||||
|
||||
/* REST_MAX_CHUNK_SIZE is the max size of payload.
|
||||
* The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer.
|
||||
* Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks.
|
||||
*/
|
||||
#ifndef REST_MAX_CHUNK_SIZE
|
||||
#define REST_MAX_CHUNK_SIZE (1024*1024)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
#define CLOCK_SECOND 1000
|
||||
|
||||
typedef enum {
|
||||
A_Raw, A_Sock_Addr, A_IP_Addr, A_Custom
|
||||
} Net_Addr_Type;
|
||||
|
||||
#define NET_ADDR_RAW_SIZE 32
|
||||
|
||||
typedef struct net_addr_coap {
|
||||
Net_Addr_Type addr_type;
|
||||
union {
|
||||
char raw[NET_ADDR_RAW_SIZE];
|
||||
struct sockaddr_in sock_addr;
|
||||
} u;
|
||||
uint16_t port;
|
||||
uint16_t addr_len;
|
||||
} net_addr_t;
|
||||
|
||||
#define uip_ipaddr_t struct net_addr_coap
|
||||
|
||||
#define memb_free(x, y) free(x)
|
||||
|
||||
void set_addr_ip(uip_ipaddr_t *, char * ip, int port);
|
||||
uip_ipaddr_t * new_net_addr(Net_Addr_Type type);
|
||||
void copy_net_addr(uip_ipaddr_t * dest, uip_ipaddr_t * src);
|
||||
bool compare_net_addr(uip_ipaddr_t * dest, uip_ipaddr_t * src);
|
||||
|
||||
uint32_t get_elpased_ms(uint32_t * last_system_clock);
|
||||
uint32_t get_platform_time();
|
||||
uint32_t get_platform_time_sec();
|
||||
|
||||
void coap_sleep_ms(uint32_t ms);
|
||||
void coap_lock(void *);
|
||||
void coap_unlock(void *);
|
||||
void * coap_create_lock();
|
||||
void coap_free_lock(void *);
|
||||
|
||||
void *xalloc(uint32_t size);
|
||||
|
||||
#define os_malloc bh_malloc
|
||||
#define os_free bh_free
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* COAP_PLATFORMS_H_ */
|
23
core/shared-lib/coap/lib_coap.cmake
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set (LIB_COAP_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories(${LIB_COAP_DIR}/er-coap)
|
||||
include_directories(${LIB_COAP_DIR}/extension)
|
||||
|
||||
file (GLOB_RECURSE source_all ${LIB_COAP_DIR}/*.c)
|
||||
|
||||
set (LIB_COAP_SOURCE ${source_all})
|
||||
|
236
core/shared-lib/include/bni.h
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* @file bni.h
|
||||
* @date Mon Jul 2 16:54:58 2012
|
||||
*
|
||||
* @brief Beihai native interface.
|
||||
*/
|
||||
|
||||
#ifndef BNI_H
|
||||
#define BNI_H
|
||||
|
||||
#include "bh_types.h"
|
||||
|
||||
/* Primitive types */
|
||||
typedef uint8 jboolean;
|
||||
typedef int8 jbyte;
|
||||
typedef uint16 jchar;
|
||||
typedef int16 jshort;
|
||||
typedef int32 jint;
|
||||
typedef int64 jlong;
|
||||
typedef float jfloat;
|
||||
typedef double jdouble;
|
||||
typedef jint jsize;
|
||||
|
||||
/* Predefined Java class types. */
|
||||
struct _jobject;
|
||||
typedef struct _jobject *jobject;
|
||||
struct _jclass;
|
||||
typedef struct _jclass *jclass;
|
||||
struct _jstring;
|
||||
typedef struct _jstring *jstring;
|
||||
|
||||
/* Values of jboolean: */
|
||||
#define BNI_FALSE 0
|
||||
#define BNI_TRUE 1
|
||||
|
||||
/**
|
||||
* Return the length of the array object.
|
||||
*
|
||||
* @param array Java array object
|
||||
*
|
||||
* @return the length of the Java array
|
||||
*/
|
||||
#define bni_array_length(array) ((jsize)((uint32)(array)->__length >> 2))
|
||||
|
||||
/**
|
||||
* Return the address of the first element of array object.
|
||||
*
|
||||
* @param array Java array object
|
||||
*
|
||||
* @return the address of the first element of array object
|
||||
*/
|
||||
#define bni_array_elem(array) ((array)->__elem)
|
||||
|
||||
/**
|
||||
* Find the Java class with given class name.
|
||||
*
|
||||
* @param name Java class name
|
||||
*
|
||||
* @return class object of the Java class if found, NULL otherwise
|
||||
*
|
||||
* @throws OutOfMemoryError if VM runs out of memory.
|
||||
*/
|
||||
jclass
|
||||
bni_find_class(const char *name);
|
||||
|
||||
/**
|
||||
* Throw an exception of given class with message.
|
||||
*
|
||||
* @param clazz class object of a subclass of java.lang.Throwable
|
||||
* @param msg message for the exception or NULL if no message
|
||||
*
|
||||
* @return 0 if succeeds, nonzero otherwise
|
||||
*/
|
||||
jint
|
||||
bni_throw_new(jclass clazz, const char *msg);
|
||||
|
||||
/**
|
||||
* Throw a NullPointerException.
|
||||
*
|
||||
* @throws NullPointerException
|
||||
*/
|
||||
void
|
||||
bni_throw_npe(void);
|
||||
|
||||
/**
|
||||
* Throw an ArrayIndexOutOfBoundsException
|
||||
*
|
||||
* @param index the index used to access the array
|
||||
*
|
||||
* @throws ArrayIndexOutOfBoundsException
|
||||
*/
|
||||
void
|
||||
bni_throw_aioobe(int index);
|
||||
|
||||
/**
|
||||
* Determine whether an exception is being thrown.
|
||||
*
|
||||
* @return exception object if exception is thrown, NULL otherwise
|
||||
*/
|
||||
jobject
|
||||
bni_exception_occurred(void);
|
||||
|
||||
/**
|
||||
* Print the current exception to error-reporting channel.
|
||||
*/
|
||||
void
|
||||
bni_exception_describe(void);
|
||||
|
||||
/**
|
||||
* Clear the currently thrown exception.
|
||||
*/
|
||||
void
|
||||
bni_exception_clear(void);
|
||||
|
||||
/**
|
||||
* Return the Unicode character number of a string.
|
||||
*
|
||||
* @param str Java string object
|
||||
*
|
||||
* @return the Unicode character number of the string
|
||||
*/
|
||||
jsize
|
||||
bni_string_length(jstring str);
|
||||
|
||||
/**
|
||||
* Return the length in bytes of the modified UTF-8 representation of
|
||||
* a string.
|
||||
*
|
||||
* @param str Java string object
|
||||
* @param start start offset in the string
|
||||
* @param len number of Unicode characters
|
||||
*
|
||||
* @return the UTF-8 length of the string
|
||||
*
|
||||
* @throws StringIndexOutOfBoundsException on index overflow.
|
||||
*/
|
||||
jsize
|
||||
bni_string_utf_length(jstring str, jsize start, jsize len);
|
||||
|
||||
/**
|
||||
* Copies len number of Unicode characters beginning at offset start
|
||||
* to the given buffer buf.
|
||||
*
|
||||
* @param str Java string object
|
||||
* @param start start offset in the string
|
||||
* @param len number of Unicode characters to copy
|
||||
* @param buf buffer for storing the result
|
||||
*/
|
||||
void
|
||||
bni_string_region(jstring str, jsize start, jsize len, jchar *buf);
|
||||
|
||||
/**
|
||||
* Translates len number of Unicode characters beginning at offset
|
||||
* start into modified UTF-8 encoding and place the result in the
|
||||
* given buffer buf.
|
||||
*
|
||||
* @param str Java string object
|
||||
* @param start start offset in the string
|
||||
* @param len number of Unicode characters to copy
|
||||
* @param buf buffer for storing the result
|
||||
*
|
||||
* @throws StringIndexOutOfBoundsException on index overflow.
|
||||
*/
|
||||
void
|
||||
bni_string_utf_region(jstring str, jsize start, jsize len, char *buf);
|
||||
|
||||
/**
|
||||
* Translate Unicode characters into modified UTF-8 encoding and return
|
||||
* the result.
|
||||
*
|
||||
* @param str Java string object
|
||||
*
|
||||
* @return the UTF-8 encoding string if succeeds, NULL otherwise
|
||||
*/
|
||||
char *
|
||||
bni_string_get_utf_chars(jstring str);
|
||||
|
||||
/**
|
||||
* Get the given Java object's class index.
|
||||
*
|
||||
* @param obj Java object
|
||||
*
|
||||
* @return -1 if obj is an array, class index of the object otherwise
|
||||
*/
|
||||
jint
|
||||
bni_object_class_index(jobject obj);
|
||||
|
||||
/**
|
||||
* Allocate memory from the current instance's private heap.
|
||||
*
|
||||
* @param size bytes to allocate
|
||||
*
|
||||
* @return pointer to the allocated memory
|
||||
*
|
||||
* @throws OutOfMemoryError if VM runs out of memory.
|
||||
*/
|
||||
void*
|
||||
bni_malloc(unsigned size);
|
||||
|
||||
/**
|
||||
* Allocate memory from the current instance's private heap and clear
|
||||
* to zero.
|
||||
*
|
||||
* @param size bytes to allocate
|
||||
*
|
||||
* @return pointer to the allocated memory
|
||||
*
|
||||
* @throws OutOfMemoryError if VM runs out of memory.
|
||||
*/
|
||||
void*
|
||||
bni_calloc(unsigned size);
|
||||
|
||||
/**
|
||||
* Free the memory allocated from the current instance's private heap.
|
||||
*
|
||||
* @param ptr pointer to the memory in current instance's private heap
|
||||
*/
|
||||
void
|
||||
bni_free(void *ptr);
|
||||
|
||||
#endif
|
615
core/shared-lib/include/jeff_export.h
Executable file
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* @file jeff-export.h
|
||||
* @date Wed Aug 3 18:17:30 2011
|
||||
*
|
||||
* @brief Exported interface for operating or executing JEFF files.
|
||||
* All interface names start with "jeff_", which is the namespace name
|
||||
* of this module.
|
||||
*/
|
||||
|
||||
#ifndef JEFF_EXPORT_H
|
||||
#define JEFF_EXPORT_H
|
||||
|
||||
#include "bni.h"
|
||||
#include "korp_types.h"
|
||||
|
||||
/********************************************************************
|
||||
* Exported internal types
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* JEFF file handle type
|
||||
*/
|
||||
struct JeffFileHeaderLinked;
|
||||
typedef struct JeffFileHeaderLinked *jeff_file_t;
|
||||
|
||||
/**
|
||||
* JEFF class type
|
||||
*/
|
||||
struct JeffClassHeaderLinked;
|
||||
typedef struct JeffClassHeaderLinked *jeff_class_t;
|
||||
|
||||
/**
|
||||
* VM instance handle type
|
||||
*/
|
||||
struct JeffInstanceLocalRoot;
|
||||
typedef struct JeffInstanceLocalRoot *jeff_instance_t;
|
||||
|
||||
/**
|
||||
* Record of one native method's definition.
|
||||
*/
|
||||
struct JeffNativeMethodDef {
|
||||
/* Mangled name of the native method. NULL for initialization
|
||||
functions. */
|
||||
const char *mangled_name;
|
||||
|
||||
/* Points to the native C function. */
|
||||
void (*func_ptr)(uint32 *);
|
||||
|
||||
/* Return size type of the native function. */
|
||||
uint32 return_size_type;
|
||||
};
|
||||
|
||||
/********************************************************************
|
||||
* Interface for operating global environment of the JEFF VM
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Load the core library from the given file buffer and initialize the
|
||||
* runtime environment (global objects etc.) of the VM. The thread
|
||||
* calls this function becomes the supervisor thread, which belongs to
|
||||
* a unique supervisor instance. Currently, if this init failed,
|
||||
* partially initialized states of the VM runtime environment won't be
|
||||
* cleaned up, so the VM must be shutdown and restarted. method_defs
|
||||
* points to an array of native method definition records.
|
||||
* Initialization functions must be in the front of the array and
|
||||
* following native method definitions must be sorted by their mangled
|
||||
* names.
|
||||
*
|
||||
* @param file the JEFF file of the core library
|
||||
* @param file_size the size of the JEFF file of the core library
|
||||
* @param method_defs native method definition records
|
||||
* @param method_defs_num number of native method records
|
||||
* @param heap the heap for the current (supervisor) instance
|
||||
*
|
||||
* @return true if succeeds, otherwise the error cannot be recovered
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_init(jeff_file_t file, unsigned file_size,
|
||||
struct JeffNativeMethodDef *method_defs, unsigned method_defs_num,
|
||||
void *heap);
|
||||
|
||||
/**
|
||||
* Load a JEFF file into the VM from the given file buffer. It can be
|
||||
* called from any VM thread.
|
||||
*
|
||||
* @param file the JEFF file to be loaded
|
||||
* @param size the size of the JEFF file
|
||||
* @param is_library whether the JEFF file is a library
|
||||
* @param allow_to_load a function that returns true if classes in the
|
||||
* given package is allowed to be loaded. The NULL function pointer
|
||||
* allows all packages.
|
||||
* @param allow_to_link a function that returns true if classes in the
|
||||
* given package is allowed to be linked to. The NULL function
|
||||
* pointer allows all packages.
|
||||
*
|
||||
* @return true if succeeds, otherwise detailed error information is
|
||||
* passed to vmci_diagnostic_print. The caller can catch it by
|
||||
* implementing that function.
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_load(jeff_file_t file, unsigned size, bool is_library,
|
||||
bool (*allow_to_load)(const uint8 *pname, unsigned len),
|
||||
bool (*allow_to_link)(const uint8 *pname, unsigned plen,
|
||||
const uint8 *cname, unsigned clen));
|
||||
|
||||
/**
|
||||
* Unload a JEFF file from the VM. All resources related to the JEFF
|
||||
* file except the JEFF file itself are released. It can be called
|
||||
* from any VM thread.
|
||||
*
|
||||
* @param file the JEFF file to be unloaded
|
||||
*
|
||||
* @return true if succeeds, otherwise detailed error information is
|
||||
* passed to vmci_diagnostic_print. The caller can catch it by
|
||||
* implementing that function.
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_unload(jeff_file_t file);
|
||||
|
||||
/**
|
||||
* Return the JEFF file with the given file uid.
|
||||
*
|
||||
* @param fuid the unique id of a loaded JEFF file
|
||||
*
|
||||
* @return the JEFF file is exists, otherwise NULL
|
||||
*/
|
||||
jeff_file_t
|
||||
jeff_runtime_fuid_to_file(unsigned fuid);
|
||||
|
||||
/**
|
||||
* Return the file uid of the given JEFF file.
|
||||
*
|
||||
* @param file a loaded JEFF file
|
||||
*
|
||||
* @return the unique id of the given JEFF file
|
||||
*/
|
||||
unsigned
|
||||
jeff_runtime_file_to_fuid(jeff_file_t file);
|
||||
|
||||
/**
|
||||
* Create a supervisor thread belonging to the supervisor instance.
|
||||
* Threads that may interact with VM core must be either the main
|
||||
* thread of supervisor instance (which calls jeff_runtime_init) or
|
||||
* created by this function so that VM core required data structures
|
||||
* can be set up correctly.
|
||||
*
|
||||
* @param start_routine the start routine of the new thread
|
||||
* @param arg argument to the start routine
|
||||
*
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_create_supervisor_thread(void* (*start_routine)(void *),
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Create a supervisor thread belonging to the supervisor instance.
|
||||
* Threads that may interact with VM core must be either the main
|
||||
* thread of supervisor instance (which calls jeff_runtime_init) or
|
||||
* created by this function so that VM core required data structures
|
||||
* can be set up correctly.
|
||||
*
|
||||
* @param start_routine the start routine of the new thread
|
||||
* @param arg argument to the start routine
|
||||
* @param prio thread priority
|
||||
*
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_create_supervisor_thread_with_prio(void* (*start_routine)(void *),
|
||||
void *arg, int prio);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for operating instance local environment
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Create a VM instance with the given JEFF file as its main file,
|
||||
* (i.e. the file containing the main class of the VM instance). This
|
||||
* function can be called from any VM thread, but it must be isolated
|
||||
* from JEFF file's unloading operation so that the main file won't be
|
||||
* unloaded before it's locked by the new instance. All instance
|
||||
* local memory except stacks of threads are allocated from the given
|
||||
* heap. If succeeds, it increases reference count of the main_file
|
||||
* and returns the handle of the new VM instance. The new instance's
|
||||
* main thread will run the start_routine with argument arg. If the
|
||||
* cleanup_routine is not NULL, it will be called after start_routine
|
||||
* returns and just before the main thread exits. It will also be
|
||||
* called after the instance is destroied. It is guaranteed to be
|
||||
* called exactly once no matter how the instance terminates.
|
||||
*
|
||||
* @param main_file the main JEFF file of the new instance
|
||||
* @param heap the private heap of the new instance
|
||||
* @param stack_depth the maximal nesting levels of Java methods of
|
||||
* the new instance. It must be <= 16 * 1024. Otherwise the instance
|
||||
* creation will fail.
|
||||
* @param start_routine start routine of the main thread. Don't
|
||||
* destroy the heap or inform other thread to do this at the end of
|
||||
* this routine since after it returns, VM core will call destroy
|
||||
* functions on objects allocated in this heap (e.g. locks and
|
||||
* condition variables). Do the destroying or informing of destroying
|
||||
* in the cleanup_routine.
|
||||
* @param arg the instance argument that will be passed to the start
|
||||
* routine. It can be get or set by jeff_runtime_get_instance_arg and
|
||||
* jeff_runtime_set_instance arg from threads of the instance. The
|
||||
* caller can use it to store instance local data.
|
||||
* @param cleanup_routine the optional cleanup routine for the
|
||||
* instance, which may be NULL. It may be executed in the end of the
|
||||
* main thread of the created instance by this function if this
|
||||
* instance exits normally, or it may be executed in a thread of other
|
||||
* instance in case this instance is being killed by that instance.
|
||||
* In both cases, this routine regards it is executed in a thread of
|
||||
* this instance (the instance created by this function) because
|
||||
* jeff_runtime_get_instance_arg will always return the argument of
|
||||
* this instance.
|
||||
*
|
||||
* @return the VM instance handle if succeeds, NULL otherwise
|
||||
*/
|
||||
jeff_instance_t
|
||||
jeff_runtime_create_instance(jeff_file_t main_file, void *heap,
|
||||
unsigned stack_depth, void* (*start_routine)(void *), void *arg,
|
||||
void (*cleanup_routine)(void));
|
||||
|
||||
/**
|
||||
* Destroy the given VM instance and decrease the reference count of
|
||||
* its main file and all explicitly used JEFF files. It can be called
|
||||
* from any VM thread. If there are alive threads of the instance,
|
||||
* they will be terminated mandatorily and then the cleanup routine is
|
||||
* called if it's not NULL.
|
||||
*
|
||||
* @param handle the handle of the instance to be destroyed
|
||||
*/
|
||||
void
|
||||
jeff_runtime_destroy_instance(jeff_instance_t handle);
|
||||
|
||||
/**
|
||||
* Retrieve the current instance's argument.
|
||||
*
|
||||
* @return the current instance's argument
|
||||
*/
|
||||
void*
|
||||
jeff_runtime_get_instance_arg(void);
|
||||
|
||||
/**
|
||||
* Set the current instance's argument.
|
||||
*
|
||||
* @return the new argument for the current instance
|
||||
*/
|
||||
void
|
||||
jeff_runtime_set_instance_arg(void *arg);
|
||||
|
||||
/**
|
||||
* Retrieve the current instance's heap.
|
||||
*
|
||||
* @return the current instance's heap
|
||||
*/
|
||||
void*
|
||||
jeff_runtime_get_instance_heap(void);
|
||||
|
||||
/**
|
||||
* Suspend all threads of the given VM instance. This function can
|
||||
* only be called from thread that is not of the given VM instance.
|
||||
*
|
||||
* @param handle the handle of the instance to be suspended
|
||||
*/
|
||||
void
|
||||
jeff_runtime_suspend_instance(jeff_instance_t handle);
|
||||
|
||||
/**
|
||||
* Resume all threads of the given VM instance. This function can
|
||||
* only be called from thread that is not of the given VM instance.
|
||||
*
|
||||
* @param handle the handle of the instance to be resumed
|
||||
*/
|
||||
void
|
||||
jeff_runtime_resume_instance(jeff_instance_t handle);
|
||||
|
||||
/**
|
||||
* Interrupt all threads of the given VM instance. This function can
|
||||
* only be called from thread that is not of the given VM instance.
|
||||
*
|
||||
* @param handle the handle of the instance to be interrupted
|
||||
* @param by_force whether the interruption is by force
|
||||
*/
|
||||
void
|
||||
jeff_runtime_interrupt_instance(jeff_instance_t handle, bool by_force);
|
||||
|
||||
/**
|
||||
* Wait for the given VM instance to terminate.
|
||||
*
|
||||
* @param ilr the VM instance to be waited for
|
||||
* @param mills wait millseconds to return
|
||||
*/
|
||||
void
|
||||
jeff_runtime_wait_for_instance(jeff_instance_t ilr, int mills);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for operating thread local environment
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Return true if there is an uncaught exception (thrown during
|
||||
* running an application or applet command).
|
||||
*
|
||||
* @return true if there is an uncaught exception
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_check_uncaught_exception(void);
|
||||
|
||||
/**
|
||||
* Print qualified name of the uncaught exception (and stack trace if
|
||||
* enabled) by calling vmci_diagnostic_print.
|
||||
*/
|
||||
void
|
||||
jeff_runtime_print_uncaught_exception(void);
|
||||
|
||||
/**
|
||||
* Clear the uncaught exception.
|
||||
*/
|
||||
void
|
||||
jeff_runtime_reset_uncaught_exception(void);
|
||||
|
||||
/**
|
||||
* Change current thread to a safe state (VMWAIT). After calling this
|
||||
* and before calling jeff_runtime_exit_safe_state, all operations
|
||||
* must be safe, i.e. no GC or system level resource operations are
|
||||
* allowed because in a safe state, the VM instance is assumed to be
|
||||
* able to perform GC, JDWP or termination at any time. Usually, this
|
||||
* function is called just before the native code is going to wait for
|
||||
* something and the exiting safe state function is called just after
|
||||
* the waiting returns.
|
||||
*/
|
||||
void
|
||||
jeff_runtime_enter_safe_state(void);
|
||||
|
||||
/**
|
||||
* Change current thread to an unsafe state (RUNNING) so that unsafe
|
||||
* operations can also be done.
|
||||
*/
|
||||
void
|
||||
jeff_runtime_exit_safe_state(void);
|
||||
|
||||
/**
|
||||
* Set thread local error code for the current thread.
|
||||
*
|
||||
* @param code the error code to be set
|
||||
*/
|
||||
void
|
||||
jeff_runtime_set_error(unsigned code);
|
||||
|
||||
/**
|
||||
* Get the last error code of current thread.
|
||||
*
|
||||
* @return the last error code of current thread
|
||||
*/
|
||||
unsigned
|
||||
jeff_runtime_get_error(void);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for GC support
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Traverse all objects of the given heap that are global or locate in
|
||||
* threads' frames and return them by calling vmci_gc_rootset_elem.
|
||||
* This function will suspend all threads except the current one of
|
||||
* the VM instance owning the given heap before traversing. It
|
||||
* traverses either all or none of the rootset objects, and returns
|
||||
* true and false respectively. If it returns false, the GC process
|
||||
* shouldn't proceed and is not necessary to unmark anything because
|
||||
* no objects are marked. The function jeff_runtime_gc_finished must
|
||||
* be called if and only if this function returns true so as to resume
|
||||
* threads that are suspended during GC process.
|
||||
*
|
||||
* @param heap the heap for which rootset objects are looked up
|
||||
*
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_runtime_traverse_gc_rootset(void *heap);
|
||||
|
||||
/**
|
||||
* Get the reference offset table of the given object. If the
|
||||
* returned value R >= 0, *ret points to the reference offset table of
|
||||
* the object and R is the number of offsets in the table. Otherwise,
|
||||
* if the returned value R < 0, all reference fields of the object
|
||||
* must be in a continuous region (usually the object is an array),
|
||||
* then *ret is the offset to the first field in the region and R is
|
||||
* the number of such fields in the region.
|
||||
*
|
||||
* @param obj pointer to the Java object
|
||||
* @param ret points to a pointer for storing the reference offset
|
||||
* table if return value >= 0, or for storing the offset to the first
|
||||
* object reference in the Java object if return value < 0
|
||||
*
|
||||
* @return number of offsets in the reference_offset table if >= 0, or
|
||||
* number of object references in the object if < 0
|
||||
*/
|
||||
int
|
||||
jeff_object_get_reference_offsets(const jobject obj, uint16 **ret);
|
||||
|
||||
/**
|
||||
* Inform the containing VM instance that GC has finished and all
|
||||
* suspended threads can be resumed. This function must be called if
|
||||
* and only if jeff_runtime_traverse_gc_rootset returns true.
|
||||
*/
|
||||
void
|
||||
jeff_runtime_gc_finished(void);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for tooling support
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* This function is used to suspend the main thread of VM instance so
|
||||
* that debugger can have chance to connect to the VM instance, set
|
||||
* breakpoints and do any other debug settings. It must be called
|
||||
* from the main thread of VM instance at the point just after VM
|
||||
* instance initialization finishes and just before application code
|
||||
* is to be executed.
|
||||
*/
|
||||
void
|
||||
jeff_tool_suspend_self(void);
|
||||
|
||||
/**
|
||||
* Start up tool agent thread for the given VM instance. It can be
|
||||
* called from any VM thread.
|
||||
*
|
||||
* @param handle the VM instance for which tool agent is started up
|
||||
* @param queue queue of the tool agent
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_tool_start_agent(jeff_instance_t handle, void *queue);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for toolkit support
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Return the JEFF class pointer of the given class name.
|
||||
*
|
||||
* @param class_name the qualified class name
|
||||
*
|
||||
* @return the JEFF class pointer
|
||||
*/
|
||||
jeff_class_t
|
||||
jeff_tool_get_jeff_class(const char *class_name);
|
||||
|
||||
/**
|
||||
* Get the mangled class name of the given class.
|
||||
*
|
||||
* @param clz the JEFF class
|
||||
* @param buf buffer for returning the mangled name
|
||||
* @param buf_size size of the buffer
|
||||
*
|
||||
* @return actual size of the mangled class name including the
|
||||
* terminating null byte
|
||||
*/
|
||||
unsigned
|
||||
jeff_tool_get_mangled_class_name(jeff_class_t clz, char *buf,
|
||||
unsigned buf_size);
|
||||
|
||||
/**
|
||||
* Get class index of given class in its containing JEFF file.
|
||||
*
|
||||
* @param clz the JEFF class
|
||||
*
|
||||
* @return class index in the containing JEFF file
|
||||
*/
|
||||
int
|
||||
jeff_tool_get_class_index(jeff_class_t clz);
|
||||
|
||||
/**
|
||||
* Callback handler prototype for traversing fields of class.
|
||||
*
|
||||
* @param arg argument passed to the handler from caller
|
||||
* @param access_flag access flag of the method
|
||||
* @param name the field name
|
||||
* @param descriptor mangled field type descriptor
|
||||
* @param offset the offset of the field in the class
|
||||
* @param size size of the field
|
||||
*/
|
||||
typedef void
|
||||
(*JeffToolFieldHandler)(void *arg, unsigned access_flag, const char *name,
|
||||
const char *descriptor, unsigned offset, unsigned size);
|
||||
|
||||
/**
|
||||
* Traverse all fields of the given class, including those inherited
|
||||
* from super classes. The fields are traversed in the same order as
|
||||
* the field layout of the class.
|
||||
*
|
||||
* @param arg argument to be passed to the handler
|
||||
* @param clz the JEFF class
|
||||
* @param instance instance fields or static fielts
|
||||
* @param handler the callback handler for each field
|
||||
*/
|
||||
void
|
||||
jeff_tool_foreach_field(void *arg, jeff_class_t clz, bool instance,
|
||||
JeffToolFieldHandler handler);
|
||||
|
||||
/**
|
||||
* Callback handler prototype for traversing methods of class.
|
||||
*
|
||||
* @param arg argument passed to the handler from caller
|
||||
* @param access_flag access flag of the method
|
||||
* @param name mangled name of the method
|
||||
* @param descriptor mangled method arguments descriptor
|
||||
* @param retune_type mangled descriptor of method's return type
|
||||
*/
|
||||
typedef void
|
||||
(*JeffToolMethodHandler)(void *arg, unsigned access_flag, const char *name,
|
||||
const char *descriptor, const char *return_type);
|
||||
|
||||
/**
|
||||
* Traverse all methods of the given class.
|
||||
*
|
||||
* @param arg argument to be passed to the handler
|
||||
* @param clz the JEFF class
|
||||
* @param handler the callback handler for each method
|
||||
*/
|
||||
void
|
||||
jeff_tool_foreach_method(void *arg, jeff_class_t clz,
|
||||
JeffToolMethodHandler handler);
|
||||
|
||||
/**
|
||||
* Callback handler prototype for traversing classes of main file.
|
||||
*
|
||||
* @param arg argument passed to the handler from caller
|
||||
* @param clz pointer to one class in the main file
|
||||
*/
|
||||
typedef void
|
||||
(*JeffToolClassHandler)(void *arg, jeff_class_t clz);
|
||||
|
||||
/**
|
||||
* Traverse all classes of the main file.
|
||||
*
|
||||
* @param arg argument to be passed to the handler
|
||||
* @param handler the callback handler for each class
|
||||
*/
|
||||
void
|
||||
jeff_tool_foreach_class(void *arg, JeffToolClassHandler handler);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for executing applications
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Initialize global environment for executing Java applications.
|
||||
*
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_application_env_init(void);
|
||||
|
||||
/**
|
||||
* Find the unique class containing a public static "main
|
||||
* ([Ljava.lang.String;)V" method from the main JEFF file of the
|
||||
* current instance and execute that method.
|
||||
*
|
||||
* @param argc the number of arguments
|
||||
* @param argv the arguments array
|
||||
*
|
||||
* @return true if the main method is called, false otherwise (e.g. an
|
||||
* exception occurs when preparing the arguments Java string array)
|
||||
*/
|
||||
bool
|
||||
jeff_application_execute(int argc, char *argv[]);
|
||||
|
||||
/********************************************************************
|
||||
* Interface for executing applets
|
||||
********************************************************************/
|
||||
|
||||
/**
|
||||
* Initialize global environment for executing applets.
|
||||
*
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_applet_env_init(void);
|
||||
|
||||
/**
|
||||
* Start to run from com.intel.runtime.core.RuntimeContext.main with a
|
||||
* default message queue size and a default service class object. If
|
||||
* the main JEFF file of the current VM instance contains exactly one
|
||||
* class that is derived from com.intel.util.IntelApplet, then use it
|
||||
* as the default service class.
|
||||
*
|
||||
* @param queue_size the default main message queue size
|
||||
* @param default_service_class qualified class name of the default
|
||||
* service class (entry point class), which must be in the main JEFF
|
||||
* file. If NULL, find the default main class with rules described
|
||||
* above.
|
||||
*
|
||||
* @return true if succeeds, false otherwise
|
||||
*/
|
||||
bool
|
||||
jeff_applet_start(int queue_size, const char *default_service_class);
|
||||
|
||||
#endif
|
|
@ -152,7 +152,7 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size)
|
|||
bh_assert(
|
||||
hmu && (gc_uint8*) hmu >= heap->base_addr
|
||||
&& (gc_uint8*) hmu < heap->base_addr + heap->current_size);
|
||||
bh_assert(((gc_uint32)(uintptr_t)hmu_to_obj(hmu) & 7) == 0);
|
||||
bh_assert(((gc_uint32) hmu_to_obj(hmu) & 7) == 0);
|
||||
bh_assert(
|
||||
size > 0
|
||||
&& ((gc_uint8*) hmu) + size
|
||||
|
@ -242,7 +242,7 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size)
|
|||
|
||||
p = node->next;
|
||||
node->next = p->next;
|
||||
bh_assert(((gc_int32)(intptr_t)hmu_to_obj(p) & 7) == 0);
|
||||
bh_assert(((gc_int32) hmu_to_obj(p) & 7) == 0);
|
||||
|
||||
if ((gc_size_t) node_idx
|
||||
!= init_node_idx&& ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { /* with bigger size*/
|
||||
|
|
|
@ -75,7 +75,7 @@ static void *vm_thread_wrapper(void *arg)
|
|||
{
|
||||
thread_wrapper_arg * targ = arg;
|
||||
LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ);
|
||||
targ->stack = (void *) ((uintptr_t)(&arg) & ~0xfff);
|
||||
targ->stack = (void *) ((unsigned int) (&arg) & ~0xfff);
|
||||
_vm_tls_put(1, targ);
|
||||
targ->start(targ->arg);
|
||||
bh_free(targ);
|
||||
|
|
|
@ -417,7 +417,6 @@ int check_app_timers(timer_ctx_t ctx)
|
|||
vm_mutex_lock(&ctx->mutex);
|
||||
|
||||
app_timer_t * t = ctx->g_app_timers;
|
||||
app_timer_t * prev = NULL;
|
||||
app_timer_t * expired = NULL;
|
||||
|
||||
uint64 now = bh_get_tick_ms();
|
||||
|
@ -443,8 +442,6 @@ int check_app_timers(timer_ctx_t ctx)
|
|||
|
||||
void cleanup_app_timers(timer_ctx_t ctx)
|
||||
{
|
||||
app_timer_t *t;
|
||||
|
||||
vm_mutex_lock(&ctx->mutex);
|
||||
|
||||
release_timer_list(&ctx->g_app_timers);
|
||||
|
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 66 KiB |
BIN
doc/pics/vgl.PNG
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
doc/pics/vgl2.PNG
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
doc/pics/vgl_linux.PNG
Normal file
After Width: | Height: | Size: 25 KiB |