Merge pull request #4 from intel/master

sync upstream
This commit is contained in:
Weining 2019-05-17 17:27:15 +08:00 committed by GitHub
commit 5918d19758
164 changed files with 21803 additions and 1064 deletions

357
README.md
View File

@ -1,60 +1,63 @@
WebAssembly Micro Runtime
=========================
WebAssembly Micro Runtime (WAMR) is standalone WebAssembly (WASM) runtime with small footprint. It includes a few components:
- WebAssembly VM core
- WASM application programming API (code available, but compilation is depending on the app manager component)
- Dynamic WASM application management (Not available in github yet. It will be released soon)
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 we use a WASM runtime out of browser? There are a few points which might be meaningful:
1. WASM is already the LLVM official backend target. That means WASM can run any programming languages which can be compiled to LLVM IR. It is a huge advantage comparing to those language bound runtimes like JS, Lua.
2. WASM is an open standard and the growing trend is so fast as it is supported by the whole web ecosystem
3. WASM is designed to be very friendly for compiling to native binary and gaining the native speed.
4. Potentially change the development practices. Imaging we can do both the WASM application development and validation in a browser, then just download the wasm binary code into the target device.
5. WASM can work without garbage collection. It can be designed to support execution determinics for the time sensitive requirement.
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.
Features
Current Features of WAMR
=========================
- WASM interpreter (AOT is planned)
- Provide built-in Libc subset, support "side_module=1" EMCC compilation option
- Provide APIs for embedding runtime into production software
- Provide mechanism for exporting native APIs to WASM applications
- Support programming firmware apps in multi languages (C/C++/Java/Rust/Go/TypeScript etc.)
- Provides support for a subset of Lib.
- Supports "side_module=1" EMCC compilation option
- Provides API's for embedding runtime into production software
- 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
- Pure asynchronized programming model
- The purely asynchronized programming model
- Menu configuration for easy platform integration
- Support micro service and pub-sub event inter-app communication models
- Supports micro-service and pub-sub event inter-app communication models
- Easy to extend to support remote FW application management from host or cloud
Architecture
=========================
The application manager component handles the packets that the platform recieved from external through any communication buses such as socket, serial port, PSI. A packet type can be either request, response or event. It will service the request with URI "/applet" and call the runtime glue layer interfaces for installing/uninstalling the application. For other URIs, it will filter the resource registeration table and router the request to internal queue of responsible application.
The application manager component handles the packets that the platform receives from external sources through any communication buses such as a socket, serial port or PSI. A packet type can be either a request, response or an event. The app manager will serve the requests with URI "/applet" and call the runtime glue layer interfaces for installing/uninstalling the application. For other URI's, it will filter the resource registration table and route the request to the internal queue of the responsible application.
The WebAssembly runtime is the execution environment for WASM applications.
- The WebAssembly runtime provides the execution environment for WASM applications.
The messaging layer can suppor the API for WASM applications 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 compilation is enabled, the WASM application can be either bytecode or compiled native binary.
- When ahead of time (AOT) compilation is enabled (TODO), the WASM application could be either WASM or a compiled native binary.
<img src="./doc/pics/architecture.PNG" width="80%" height="80%">
Build WAMR Core
=========================
Please follow below instructions to build WAMR core on different platforms.
Please follow the instructions below to build the WAMR core on different platforms.
Linux
-------------------------
Firstly please install library dependencies of lib gcc.
Use below installation commands for Ubuntu Linux:
First of all please install library dependencies of lib gcc.
Use installation commands below for Ubuntu Linux:
``` Bash
sudo apt install lib32gcc-5-dev
sudo apt-get install g++-multilib
```
After installing dependencies, build the source code:
``` Bash
cd products/linux/
cd core/iwasm/products/linux/
mkdir build
cd build
cmake ..
@ -62,7 +65,7 @@ make
```
Zephyr
-------------------------
You need download Zephyr source code first and embeded WAMR into it.
You need to download the Zephyr source code first and embedded WAMR into it.
``` Bash
git clone https://github.com/zephyrproject-rtos/zephyr.git
cd zephyr/samples/
@ -78,45 +81,43 @@ ninja
Build WASM app
=========================
A popular method to build out WASM binary is to use ```emcc```.
Assuming you are using Linux. Please install emcc from Emscripten EMSDK following below steps:
A popular method to build a WASM binary is to use ```emcc```.
Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below:
```
git clone https://github.com/emscripten-core/emsdk.git
emsdk install latest
emsdk activate latest
```
add ```./emsdk_env.sh``` into path to ease future use, or source it everytime.
Emscripten website provides other installtion method beyond Linux.
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: user should copy the app-libs folder into project and include and build.
You can write a simple ```test.c```as the first sample.
You can write a simple ```test.c``` as the first sample.
``` C
#include <stdio.h>
#include <stdlib.h>
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 below emcc commmand to build the WASM C source code into WASM binary.
Use the emcc command below to build the WASM C source code into the WASM binary.
``` Bash
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
@ -125,67 +126,78 @@ You will get ```test.wasm``` which is the WASM app binary.
Run WASM app
========================
Assume you are using Linux, the command to run the test.wasm is
Assume you are using Linux, the command to run the test.wasm is:
``` Bash
cd iwasm/products/linux/bin
./iwasm test.wasm
```
You will get output:
You will get the following output:
```
Hello world!
buf ptr: 0x000101ac
buf: 1234
```
If you would like to run test app on Zephyr, we have embedded test sample into its OS image. You need to execute
If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute:
```
ninja run
```
Embed WAMR into software production
=====================================
WAMR can be built into a standalone executable which takes WASM application file name as input, and then execute it. To use it in the embedded environment, you should embed WAMR into your own software product. WASM provides a set of APIs for embedders code to load WASM module, instansiate module and invoke WASM function from 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 APIs usage is as 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();
```
WASM application library
WASM application library
========================
In general, there are 3 kinds of APIs for programming the WASM application:
- Built-in APIs: WAMR has already provided a minimal API set for developers.
- 3rd party APIs: Programmer can download include any 3rd party C source code, and added into their own WASM app source tree.
- Platform native APIs: The board vendors define these APIs during their making board firmware. They are provided WASM application to invoke like built-in and 3rd party APIs. In this way board vendors extend APIs which can make programmers develop more complicated WASM apps.
In general, there are 3 classes of API's important for the WASM application:
- Built-in API's: WAMR provides a minimal API set for developers.
- 3rd party API's: Programmer can download and include any 3rd party C source code and add it into their own WASM app source tree.
- Platform native API's: WAMR provides a mechanism to export a native API to the WASM application.
Built-in application library
---------------
Built-in APIs include Libc APIs, Base library, Extension library reference.
Built-in API's include Libc APIs, Base library and Extension library reference.
**Libc APIs**<br/>
It is the minimal Libc APIs like memory allocation and string copy etc.
The header files is ```lib/app-libs/libc/lib-base.h```. The API set is listed as below:
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);
@ -206,8 +218,8 @@ char *strncpy(char *dest, const char *src, unsigned long n);
```
**Base library**<br/>
The basic support like communication, timers etc is already available. The header files is ```lib/app-libs/base/wasm-app.h```, it includes request and response APIs, event pub/sub APIs and timer APIs. Please be noted that they may not work if you have no corresponding framework to work with them.
The API set is listed as below:
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 *) ;
typedef void(*response_handler_f)(response_t *, void *) ;
@ -232,7 +244,7 @@ void api_timer_restart(user_timer_t timer, int interval);
```
**Library extension reference**<br/>
Currently we provide the sensor APIs as one library extension sample. The header file ```lib/app-libs/extension/sensor/sensor.h```, the API set is listed as below:
Currently we provide the sensor API's as one library extension sample. In the header file ```lib/app-libs/extension/sensor/sensor.h```, the API set is defined as below:
``` C
sensor_t sensor_open(const char* name, int index,
void(*on_sensor_event)(sensor_t, attr_container_t *, void *),
@ -242,75 +254,76 @@ 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 described as following diagram.
The basic working flow for WASM application calling into the native API is shown in the following diagram:
<img src="./doc/pics/extend_library.PNG" width="60%" height="60%">
WAMR provides the macro `EXPORT_WASM_API` to enable users to export native API to WASM application. WAMR implemented a base API for timer and messaging by using `EXPORT_WASM_API`. They can be reference point of extending your own library.
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)
};
```
![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **Security attention:** The WebAssembly application is supposed to access its own memory space, the integrator should carefully design the native function to ensure the memory safe. The native API to be exporte to WASM application must follow the rules:
![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must:
- Only use 32 bits number for parameters
- Dont passing data structure pointer (do data serialization instead)
- Do the pointer address conversion in native API
- Dont passing function pointer as callback
- Should not pass data to the structure pointer (do data serialization instead)
- Should do the pointer address conversion in the native API
- Should not pass function pointer as callback
Below is a sample of library extension. All invoke across WASM world and native world must be serialized and de-serialized, and native world must do boundary check for every incoming address from WASM world.
Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world.
<img src="./doc/pics/safe.PNG" width="100%" height="100%">
Exporting native API steps
==========================
WAMR implemented a framework for developers to export APIs. The procedure to expose the platform APIs in three steps:
WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform APIs in three steps:
**Step 1. Create a header file**<br/>
Declare the APIs for WASM application source project to include.
Declare the API's for your WASM application source project to include.
**Step 2. Create a source file**<br/>
Export the platform APIs, 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/>
Use macro EXPORT_WASM_API and EXPORT_WASM_API2 to add exported APIs into the array of ```extended_native_symbol_defs```.
Use the macro `EXPORT_WASM_API` and `EXPORT_WASM_API2` to add exported API's into the array of ```extended_native_symbol_defs```.
The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function export:
``` c
#define EXPORT_WASM_API(symbol) {#symbol, symbol}
```
Below code example shows how to extend the library to support `customeized()`:
``` C
//lib-export-impl.c
Below code example shows how to extend the library to support `customized()`:
```
//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
@ -325,39 +338,163 @@ 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 includes the WAMR built-in APIs header file and platform extension header files.
Assume the board vendor extend the library which added a API called customized(). The WASM application would be like this:
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 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 platform vendor
return i;
int I;
char *buf = “abcd”;
customized(); // customized API provided by the platform vendor
return i;
}
```
Comming soon...
========================
We are preparing the open source for application manager and related cool samples like inter-application communication, application life cycle management, 2D graphic demo and more. You will get updated soon.
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
=========================
[Click here to submit. Your feedback is always welcome!](https://github.com/intel/wasm-micro-runtime/issues/new)

View 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})

View 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
};

View 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

View 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;
}

View 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

View 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})

View 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

View 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

View 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;
}

View 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_ */

View 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;
}

View 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_ */

File diff suppressed because it is too large Load Diff

View 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_ */

View 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;
}

View 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;
}
}

View 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_ */

View 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 };

View 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_ */

View 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;
}

View 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

View 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;
}
}

View 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;
}

View 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_ */

View 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

View 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})

View 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
View 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": []
}

View 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

View 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;
}

View File

@ -71,7 +71,7 @@ uint16 htons(uint16 value)
uint16 ret;
if (is_little_endian()) {
ret = value;
swap16(&ret);
swap16((uint8 *)&ret);
return ret;
}

View File

@ -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);

View File

@ -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"

View File

@ -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)

View File

@ -17,7 +17,7 @@
#ifndef _AEE_SENSOR_H_
#define _AEE_SENSOR_H_
#include "attr-container.h"
#include "attr_container.h"
#ifdef __cplusplus
extern "C" {

View File

@ -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:

View File

@ -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++;

View File

@ -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[] = {

View File

@ -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_ */

View File

@ -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)
{

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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,14 @@ 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)
target_link_libraries (iwasm vmlib -lm -ldl -lpthread)
@ -81,11 +83,13 @@ 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})
install (TARGETS libiwasm DESTINATION lib)
set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm)
target_link_libraries (libiwasm -lm -ldl -lpthread)

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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
View 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

View File

@ -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" {

View File

@ -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 */

View File

@ -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"
@ -109,31 +109,44 @@ __syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
return syscall(54, arg1, arg2, wsz);
}
case 145: /* readv */
case 146: /* writev */
{
/* Implement syscall 54 and syscall 146 to support printf()
for non SIDE_MODULE=1 mode */
uint32 iovcnt = arg3, i;
struct iovec *vec_begin, *vec;
struct iovec_app {
int32 iov_base_offset;
uint32 iov_len;
} *vec;
int32 vec_offset = arg2, str_offset;
uint32 iov_count = arg3, i;
int32 count = 0;
char *iov_base, *str;
if (!validate_app_addr(arg2, sizeof(struct iovec)))
if (!validate_app_addr(vec_offset, sizeof(struct iovec_app)))
return 0;
vec_begin = vec = (struct iovec*)addr_app_to_native(arg2);
for (i = 0; i < iovcnt; i++, vec++) {
vec = (struct iovec_app *)addr_app_to_native(vec_offset);
for (i = 0; i < iov_count; i++, vec++) {
if (vec->iov_len > 0) {
if (!validate_app_addr((int32)vec->iov_base, 1))
if (!validate_app_addr(vec->iov_base_offset, 1))
return 0;
vec->iov_base = addr_app_to_native((int32)vec->iov_base);
iov_base = (char*)addr_app_to_native(vec->iov_base_offset);
if (!(str_offset = module_malloc(vec->iov_len + 1)))
return 0;
str = addr_app_to_native(str_offset);
memcpy(str, iov_base, vec->iov_len);
str[vec->iov_len] = '\0';
count += wasm_printf("%s", str);
module_free(str_offset);
}
}
if (arg0 == 145)
return syscall(145, arg1, vec_begin, arg3);
else
return syscall(146, arg1, vec_begin, arg3);
return count;
}
case 145: /* readv */
case 3: /* read*/
case 5: /* open */
case 221: /* fcntl */

View File

@ -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);
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "wasm-native.h"
#include "wasm_native.h"
void*

View File

@ -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)())
{

View File

@ -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"

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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" {

View 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.

View 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/

View 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

View 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_ */

View 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_ */

File diff suppressed because it is too large Load Diff

View 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_ */

View 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

View 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;
}

View 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_ */

View 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;
}

View 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_ */

View 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})

View 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

View 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

View File

@ -44,7 +44,7 @@ int gci_check_platform()
CHECK(1, sizeof(gc_int8));
CHECK(1, sizeof(gc_uint8));
CHECK(4, sizeof(gc_size_t));
CHECK(4, sizeof(void *));
/*CHECK(4, sizeof(void *));*/
return GC_SUCCESS;
}

View File

@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 66 KiB

BIN
doc/pics/vgl.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
doc/pics/vgl2.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
doc/pics/vgl_linux.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Some files were not shown because too many files have changed in this diff Show More