Merge branch main into dev/gc_refactor

This commit is contained in:
Wenyong Huang 2024-04-12 11:49:36 +08:00
commit 0dd952121c
574 changed files with 10058 additions and 42917 deletions

5
.github/ISSUE_TEMPLATE/blank_issue.md vendored Normal file
View File

@ -0,0 +1,5 @@
---
name: Blank Issue
about: Create a blank issue.
title: ''
---

28
.github/ISSUE_TEMPLATE/improvement.md vendored Normal file
View File

@ -0,0 +1,28 @@
---
name: Improvement
about: A feature request or code improvement.
title: ''
labels: ''
assignees: ''
---
Thanks for filing a feature request! Please fill out the TODOs below.
#### Feature
TODO: Brief description of the feature/improvement you'd like to see in WAMR
#### Benefit
TODO: What is the value of adding this in WAMR? What problems does it solve?
#### Implementation
TODO: Do you have an implementation plan, and/or ideas for data structures or
algorithms to use?
#### Alternatives
TODO: What are the alternative implementation approaches or alternative ways to
solve the problem that this feature would solve? How do these alternatives
compare to this proposal?

36
.github/ISSUE_TEMPLATE/report_bug.md vendored Normal file
View File

@ -0,0 +1,36 @@
---
name: WAMR bug or defect report
about: Report a bug or defect in WAMR
title: ''
---
Thanks for filing a bug or defect report! Please fill out the TODOs below.
### Subject of the issue
Describe the bug or defect here.
### Test case
Upload the related wasm file, wast file or the source files if you can.
### Your environment
* Host OS
* WAMR version, platform, cpu architecture, running mode, etc.
### Steps to reproduce
Tell us how to reproduce this bug or defect.
### Expected behavior
Tell us what should happen
### Actual behavior
Tell us what happens instead
### Extra Info
Anything else you'd like to add?

35
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,35 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "docker"
directory: "/.devcontainer"
schedule:
interval: "weekly"
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/build-scripts"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/language-bindings/python/wasm-c-api"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/language-bindings/python/wamr-api"
schedule:
interval: "weekly"

View File

@ -42,9 +42,12 @@ def fetch_version_from_code():
def fetch_latest_git_tag():
list_tag_cmd = (
'git tag --list WAMR-*.*.* --sort=committerdate --format="%(refname:short)"'
)
"""
Get the most recent tag from the HEAD,
if it's main branch, it should be the latest release tag.
if it's release/x.x.x branch, it should be the latest release tag of the branch.
"""
list_tag_cmd = "git describe --tags --abbrev=0 HEAD"
p = subprocess.run(shlex.split(list_tag_cmd), capture_output=True, check=True)
all_tags = p.stdout.decode().strip()

View File

@ -33,10 +33,16 @@ jobs:
- name: checkout
uses: actions/checkout@v4
- name: install dependencies
- name: install dependencies for non macos-14
if: inputs.os != 'macos-14'
run: /usr/bin/env python3 -m pip install -r requirements.txt
working-directory: build-scripts
- name: install dependencies for macos-14
if: inputs.os == 'macos-14'
run: /usr/bin/env python3 -m pip install -r requirements.txt --break-system-packages
working-directory: build-scripts
- name: retrive the last commit ID
id: get_last_commit
run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py --llvm-ver)" >> $GITHUB_OUTPUT

View File

@ -82,9 +82,7 @@ jobs:
- name: install utils macos
if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos')
run: |
brew remove swig
brew install swig@4.1 cmake ninja libedit
brew link --overwrite swig@4.1
brew install swig cmake ninja libedit
sudo rm -rf /Library/Developer/CommandLineTools
- name: install utils ubuntu

View File

@ -30,6 +30,10 @@ on:
description: download WASI_SDK from this URL
type: string
required: true
wamr_app_framework_url:
description: download WAMR app framework to get wamr_sdk
type: string
required: true
jobs:
build:
@ -37,6 +41,14 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: download wamr-app-framework
run: |
git clone ${{ inputs.wamr_app_framework_url }}
cd wamr-app-framework
git submodule init
git submodule update
working-directory: wamr-sdk
- name: download and install wasi-sdk
run: |
cd /opt
@ -46,16 +58,24 @@ jobs:
sudo rm ${basename}
sudo mv wasi-sdk-* wasi-sdk
- name: download dependencies
run: |
cd ./wamr-app-framework/deps
./download.sh
working-directory: wamr-sdk
- name: generate wamr-sdk release
run: |
cd ./wamr-app-framework/wamr-sdk
./build_sdk.sh -n wamr-sdk -x $(pwd)/${{ inputs.config_file }}
working-directory: wamr-sdk
- name: compress the binary
run: |
cd wamr-app-framework/wamr-sdk/out
tar czf wamr-sdk-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz wamr-sdk
zip -r wamr-sdk-${{ inputs.ver_num }}-${{ inputs.runner }}.zip wamr-sdk
working-directory: wamr-sdk/out
working-directory: wamr-sdk
- name: upload release tar.gz
uses: actions/upload-release-asset@v1
@ -63,7 +83,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ inputs.upload_url }}
asset_path: wamr-sdk/out/wamr-sdk-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz
asset_path: wamr-sdk/wamr-app-framework/wamr-sdk/out/wamr-sdk-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz
asset_name: wamr-sdk-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}.tar.gz
asset_content_type: application/x-gzip
@ -73,6 +93,11 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ inputs.upload_url }}
asset_path: wamr-sdk/out/wamr-sdk-${{ inputs.ver_num }}-${{ inputs.runner }}.zip
asset_path: wamr-sdk/wamr-app-framework/wamr-sdk/out/wamr-sdk-${{ inputs.ver_num }}-${{ inputs.runner }}.zip
asset_name: wamr-sdk-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}.zip
asset_content_type: application/zip
- name: delete wamr-app-framework
run: |
rm -rf wamr-app-framework
working-directory: wamr-sdk

View File

@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4
- name: Use Node.js 16.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 16.x

114
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,114 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
name: "CodeQL"
on:
#pull_request:
# types:
# - opened
# branches: '*'
#push:
# branches: [ "main" ]
# midnight UTC
schedule:
- cron: '0 0 * * *'
# allow to be triggered manually
workflow_dispatch:
jobs:
analyze:
if: github.repository == 'bytecodealliance/wasm-micro-runtime'
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-20.04' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: recursive
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
queries: security-and-quality
# Command-line programs to run using the OS shell.
# See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
- run: |
./.github/workflows/codeql_buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
upload: false
id: step1
# Filter out rules with low severity or high false positve rate
# Also filter out warnings in third-party code
- name: Filter out unwanted errors and warnings
uses: advanced-security/filter-sarif@v1
with:
patterns: |
-**:cpp/path-injection
-**:cpp/world-writable-file-creation
-**:cpp/poorly-documented-function
-**:cpp/potentially-dangerous-function
-**:cpp/use-of-goto
-**:cpp/integer-multiplication-cast-to-long
-**:cpp/comparison-with-wider-type
-**:cpp/leap-year/*
-**:cpp/ambiguously-signed-bit-field
-**:cpp/suspicious-pointer-scaling
-**:cpp/suspicious-pointer-scaling-void
-**:cpp/unsigned-comparison-zero
-**/cmake*/Modules/**
input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
- name: Upload CodeQL results to code scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.step1.outputs.sarif-output }}
category: "/language:${{matrix.language}}"
- name: Upload CodeQL results as an artifact
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: codeql-results
path: ${{ steps.step1.outputs.sarif-output }}
retention-days: 10
- name: Fail if an error is found
run: |
./.github/workflows/codeql_fail_on_error.py \
${{ steps.step1.outputs.sarif-output }}/cpp.sarif

277
.github/workflows/codeql_buildscript.sh vendored Executable file
View File

@ -0,0 +1,277 @@
#!/usr/bin/env bash
sudo apt update
sudo apt install -y build-essential cmake g++-multilib libgcc-11-dev lib32gcc-11-dev ccache ninja-build ccache
WAMR_DIR=${PWD}
# TODO: use pre-built llvm binary to build wamrc to
# avoid static code analysing for llvm
: '
# build wamrc
cd ${WAMR_DIR}/wamr-compiler
./build_llvm.sh
rm -fr build && mkdir build && cd build
cmake ..
make -j
if [[ $? != 0 ]]; then
echo "Failed to build wamrc!"
exit 1;
fi
'
# build iwasm with default features enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -fr build && mkdir build && cd build
cmake ..
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with default features enabled!"
exit 1;
fi
# build iwasm with default features enabled on x86_32
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -fr build && mkdir build && cd build
cmake .. -DWAMR_BUILD_TARGET=X86_32
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with default features enabled on x86_32!"
exit 1;
fi
# build iwasm with classic interpreter enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_INTERP=0
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with classic interpreter enabled!"
exit 1;
fi
# build iwasm with extra features enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -fr build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug \
-DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1 \
-DWAMR_BUILD_MULTI_MODULE=1 -DWAMR_BUILD_SIMD=1 \
-DWAMR_BUILD_TAIL_CALL=1 -DWAMR_BUILD_REF_TYPES=1 \
-DWAMR_BUILD_CUSTOM_NAME_SECTION=1 -DWAMR_BUILD_MEMORY_PROFILING=1 \
-DWAMR_BUILD_PERF_PROFILING=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \
-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build wamrc iwasm with extra features enabled!"
exit 1;
fi
# build iwasm with global heap pool enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -fr build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug \
-DWAMR_BUILD_ALLOC_WITH_USER_DATA=1 \
-DWAMR_DISABLE_STACK_HW_BOUND_CHECK=1 \
-DWAMR_BUILD_GLOBAL_HEAP_POOL=1 \
-DWAMR_BUILD_GLOBAL_HEAP_SIZE=131072
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with global heap pool enabled!"
exit 1;
fi
# build iwasm with wasi-threads enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -fr build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LIB_WASI_THREADS=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with wasi-threads enabled!"
exit 1;
fi
# build iwasm with GC enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_GC=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with GC enabled!"
exit 1;
fi
# build iwasm with exception handling enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_EXCE_HANDLING=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with exception handling enabled!"
exit 1;
fi
# build iwasm with memory64 enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MEMORY64=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with memory64 enabled!"
exit 1;
fi
# build iwasm with hardware boundary check disabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_DISABLE_HW_BOUND_CHECK=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with hardware boundary check disabled!"
exit 1;
fi
# build iwasm with quick AOT entry disabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_QUICK_AOT_ENTRY=0
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with quick AOT entry disabled!"
exit 1;
fi
# build iwasm with wakeup of blocking operations disabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_DISABLE_WAKEUP_BLOCKING_OP=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with wakeup of blocking operations disabled!"
exit 1;
fi
# build iwasm with module instance context disabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MODULE_INST_CONTEXT=0 \
-DWAMR_BUILD_LIBC_BUILTIN=0 -DWAMR_BUILD_LIBC_WASI=0
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with module instance context disabled!"
exit 1;
fi
# build iwasm with libc-uvwasi enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -fr build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LIBC_UVWASI=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with libc-uvwasi enabled!"
exit 1;
fi
# build iwasm with fast jit lazy mode enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with fast jit lazy mode enabled!"
exit 1;
fi
# build iwasm with fast jit eager mode enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_FAST_JIT_DUMP=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with fast jit eager mode enabled!"
exit 1;
fi
# TODO: use pre-built llvm binary to build llvm-jit and multi-tier-jit
: '
# build iwasm with llvm jit lazy mode enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_JIT=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build llvm jit lazy mode enabled!"
exit 1;
fi
# build iwasm with llvm jit eager mode enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0
make -j
if [[ $? != 0 ]]; then
echo "Failed to build llvm jit eager mode enabled!"
exit 1;
fi
# build iwasm with multi-tier jit enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \
-DWAMR_BUILD_FAST_JIT_DUMP=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with multi-tier jit enabled!"
exit 1;
fi
'
# build iwasm with wasm mini-loader enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MINI_LOADER=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build with wasm mini-loader enabled!"
exit 1;
fi
# build iwasm with source debugging enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_DEBUG_AOT=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with source debugging enabled!"
exit 1;
fi
# build iwasm with AOT static PGO enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_STATIC_PGO=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with AOT static PGO enabled!"
exit 1;
fi
# build iwasm with configurable bounds checks enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_CONFIGUABLE_BOUNDS_CHECKS=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with configurable bounds checks enabled!"
exit 1;
fi
# build iwasm with linux perf support enabled
cd ${WAMR_DIR}/product-mini/platforms/linux/
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_LINUX_PERF=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with linux perf support enabled!"
exit 1;
fi

34
.github/workflows/codeql_fail_on_error.py vendored Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env python3
import json
import sys
# Return whether SARIF file contains error-level results
def codeql_sarif_contain_error(filename):
with open(filename, 'r') as f:
s = json.load(f)
for run in s.get('runs', []):
rules_metadata = run['tool']['driver']['rules']
if not rules_metadata:
rules_metadata = run['tool']['extensions'][0]['rules']
for res in run.get('results', []):
if 'ruleIndex' in res:
rule_index = res['ruleIndex']
elif 'rule' in res and 'index' in res['rule']:
rule_index = res['rule']['index']
else:
continue
try:
rule_level = rules_metadata[rule_index]['defaultConfiguration']['level']
except IndexError as e:
print(e, rule_index, len(rules_metadata))
else:
if rule_level == 'error':
return True
return False
if __name__ == "__main__":
if codeql_sarif_contain_error(sys.argv[1]):
sys.exit(1)

View File

@ -20,7 +20,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
- "test-tools/wamr-ide/**"
# will be triggered on push events
push:
@ -38,7 +37,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
- "test-tools/wamr-ide/**"
# allow to be triggered manually
workflow_dispatch:
@ -67,6 +65,7 @@ env:
WASI_TEST_OPTIONS: "-s wasi_certification -w"
WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -S -b -P"
GC_TEST_OPTIONS: "-s spec -G -b -P"
MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
jobs:
build_llvm_libraries_on_ubuntu_2204:
@ -146,6 +145,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
]
os: [ubuntu-22.04]
platform: [android, linux]
@ -204,11 +204,32 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32)
# Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform
- make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
platform: android
- make_options_run_mode: $AOT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
platform: android
# LLVM JIT pre-built binary wasn't compiled by Android NDK
# and isn't available for android
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
platform: android
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
platform: android
include:
- os: ubuntu-22.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
@ -234,13 +255,23 @@ jobs:
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build iwasm
- name: Build iwasm for linux
if: matrix.platform == 'linux'
run: |
mkdir build && cd build
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
cmake --build . --config Release --parallel 4
working-directory: product-mini/platforms/${{ matrix.platform }}
- name: Build iwasm for android
if: matrix.platform == 'android'
run: |
mkdir build && cd build
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} \
-DWAMR_BUILD_TARGET=X86_64
cmake --build . --config Release --parallel 4
working-directory: product-mini/platforms/${{ matrix.platform }}
- name: Build and run unit tests
run: |
mkdir build-unittests && cd build-unittests
@ -358,14 +389,14 @@ jobs:
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
sudo ln -sf wasi-sdk-20.0 wasi-sdk
- name: download and install wabt
run: |
cd /opt
sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.31 wabt
sudo ln -sf wabt-1.0.31 wabt
- name: Get LLVM libraries
id: retrieve_llvm_libs
uses: actions/cache@v4
@ -430,13 +461,6 @@ jobs:
cmake --build . --config Debug --parallel 4
./hello
- name: Build Sample [simple]
run: |
./build.sh -p host-interp
python3 ./sample_test_run.py $(pwd)/out
exit $?
working-directory: ./samples/simple
- name: Build Sample [wasi-threads]
run: |
cd samples/wasi-threads
@ -457,6 +481,16 @@ jobs:
./build.sh
./run.sh
- name: Build Sample [debug-tools]
run: |
cd samples/debug-tools
mkdir build && cd build
cmake ..
cmake --build . --config Debug --parallel 4
./iwasm wasm-apps/trap.wasm | grep "#" > call_stack.txt
./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt
bash -x ../symbolicate.sh
test:
needs:
[
@ -486,6 +520,7 @@ jobs:
$THREADS_TEST_OPTIONS,
$WASI_TEST_OPTIONS,
$GC_TEST_OPTIONS,
$MEMORY64_TEST_OPTIONS,
]
wasi_sdk_release:
[
@ -524,19 +559,30 @@ jobs:
test_option: $GC_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $GC_TEST_OPTIONS
# aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Memory64
- running_mode: "aot"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "fast-interp"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "fast-jit"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "jit"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $MEMORY64_TEST_OPTIONS
steps:
- name: checkout
uses: actions/checkout@v4
- name: Set-up OCaml
uses: ocaml/setup-ocaml@v2
if: matrix.test_option == '$GC_TEST_OPTIONS'
if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
with:
ocaml-compiler: 4.13
- name: Set-up Ocamlbuild
if: matrix.test_option == '$GC_TEST_OPTIONS'
run: opam install ocamlbuild dune
if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
run: opam install ocamlbuild dune menhir
- name: download and install wasi-sdk
if: matrix.test_option == '$WASI_TEST_OPTIONS'
@ -555,7 +601,6 @@ jobs:
make -j AR=/opt/wasi-sdk/bin/llvm-ar NM=/opt/wasi-sdk/bin/llvm-nm CC=/opt/wasi-sdk/bin/clang THREAD_MODEL=posix
echo "SYSROOT_PATH=$PWD/sysroot" >> $GITHUB_ENV
- name: set env variable(if llvm are used)
if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
run: echo "USE_LLVM=true" >> $GITHUB_ENV
@ -601,13 +646,13 @@ jobs:
- name: run tests
timeout-minutes: 30
if: matrix.test_option != '$GC_TEST_OPTIONS'
if: matrix.test_option != '$GC_TEST_OPTIONS' && matrix.test_option != '$MEMORY64_TEST_OPTIONS'
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites
- name: run gc tests
- name: run gc or memory64 tests
timeout-minutes: 20
if: matrix.test_option == '$GC_TEST_OPTIONS'
if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
run: |
eval $(opam env)
./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
@ -659,6 +704,12 @@ jobs:
npm install
working-directory: test-tools/wamr-ide/VSCode-Extension
- name: code style check
run: |
npm install --save-dev prettier
npm run prettier-format-check
working-directory: test-tools/wamr-ide/VSCode-Extension
- name: build iwasm with source debugging feature
run: |
mkdir build

View File

@ -20,7 +20,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# will be triggered on push events
push:
branches:
@ -37,7 +36,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# allow to be triggered manually
workflow_dispatch:
@ -244,7 +242,7 @@ jobs:
run: |
cmake -S . -B build ${{ matrix.make_options }}
cmake --build build --config Release --parallel 4
ctest --test-dir build
ctest --test-dir build --output-on-failure
working-directory: samples/wasm-c-api
build_samples_others:
@ -275,14 +273,14 @@ jobs:
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
sudo ln -sf wasi-sdk-20.0 wasi-sdk
- name: download and install wabt
run: |
cd /opt
sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.31 wabt
sudo ln -sf wabt-1.0.31 wabt
- name: Build Sample [basic]
run: |
@ -371,3 +369,13 @@ jobs:
cd samples/terminate
./build.sh
./run.sh
- name: Build Sample [debug-tools]
run: |
cd samples/debug-tools
mkdir build && cd build
cmake ..
cmake --build . --config Debug --parallel 4
./iwasm wasm-apps/trap.wasm | grep "#" > call_stack.txt
./iwasm wasm-apps/trap.aot | grep "#" > call_stack_aot.txt
bash -x ../symbolicate.sh

View File

@ -19,7 +19,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# will be triggered on push events
push:
branches:
@ -35,7 +34,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# allow to be triggered manually
workflow_dispatch:

View File

@ -20,7 +20,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# will be triggered on push events
push:
branches:
@ -37,7 +36,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# allow to be triggered manually
workflow_dispatch:

View File

@ -19,7 +19,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# will be triggered on push events
push:
branches:
@ -35,7 +34,6 @@ on:
- "!samples/workload/**"
- "tests/wamr-test-suites/**"
- "wamr-compiler/**"
- "wamr-sdk/**"
# allow to be triggered manually
workflow_dispatch:

View File

@ -32,8 +32,22 @@ jobs:
- name: prepare
id: preparation
run: |
# show latest 3 versions
git tag --list WAMR-*.*.* --sort=committerdate --format="%(refname:short)" | tail -n 3
# show latest 3 versions on the branch that create release
# Set the initial commit to the head of the branch
commit="HEAD"
#
# Loop to get the three most recent tags
for i in {1..3}
do
# Get the most recent tag reachable from the current commit
tag=$(git describe --tags --abbrev=0 $commit)
# Print the tag
echo "$tag"
# Move to the commit before the found tag to find the next tag in the next iteration
commit=$(git rev-list -n 1 $tag^)
done
# compare latest git tag and semantic version definition
result=$(python3 ./.github/scripts/fetch_and_compare_version.py)
echo "script result is ${result}"

View File

@ -130,6 +130,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
]
os: [ubuntu-20.04]
platform: [android, linux]
@ -188,11 +189,32 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32)
# Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform
- make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
platform: android
- make_options_run_mode: $AOT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
platform: android
# LLVM JIT pre-built binary wasn't compiled by Android NDK
# and isn't available for android
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
platform: android
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
platform: android
include:
- os: ubuntu-20.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
@ -219,13 +241,23 @@ jobs:
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build iwasm
- name: Build iwasm for linux
if: matrix.platform == 'linux'
run: |
mkdir build && cd build
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
cmake --build . --config Release --parallel 4
working-directory: product-mini/platforms/${{ matrix.platform }}
- name: Build iwasm for android
if: matrix.platform == 'android'
run: |
mkdir build && cd build
cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }} \
-DWAMR_BUILD_TARGET=X86_64
cmake --build . --config Release --parallel 4
working-directory: product-mini/platforms/${{ matrix.platform }}
build_iwasm_linux_gcc4_8:
runs-on: ubuntu-latest
container:
@ -255,6 +287,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
]
exclude:
# uncompatiable feature and platform
@ -283,6 +316,11 @@ jobs:
# MINI_LOADER only on INTERP mode
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 only on CLASSIC INTERP mode
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
steps:
- name: checkout
uses: actions/checkout@v3
@ -421,13 +459,13 @@ jobs:
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
sudo ln -sf wasi-sdk-20.0 wasi-sdk
- name: download and install wabt
run: |
cd /opt
sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.31 wabt
sudo ln -sf wabt-1.0.31 wabt
- name: Get LLVM libraries
id: retrieve_llvm_libs
@ -489,12 +527,6 @@ jobs:
cmake ..
cmake --build . --config Release --parallel 4
./hello
- name: Build Sample [simple]
run: |
./build.sh -p host-interp
python3 ./sample_test_run.py $(pwd)/out
exit $?
working-directory: ./samples/simple
- name: Build Sample [wasi-threads]
run: |
@ -632,7 +664,9 @@ jobs:
run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV
- name: set additional tsan options
run: echo "TSAN_OPTIONS=suppressions=$PWD/tsan_suppressions.txt" >> $GITHUB_ENV
run: |
echo "TSAN_OPTIONS=suppressions=$PWD/tsan_suppressions.txt" >> $GITHUB_ENV
sudo sysctl vm.mmap_rnd_bits=28
working-directory: tests/wamr-test-suites
#only download llvm libraries in jit and aot mode

View File

@ -147,6 +147,7 @@ jobs:
upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver}}
wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
wamr_app_framework_url: https://github.com/bytecodealliance/wamr-app-framework.git
release_wamr_sdk_on_ubuntu_2204:
needs: [create_tag, create_release]
@ -157,6 +158,7 @@ jobs:
upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver}}
wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
wamr_app_framework_url: https://github.com/bytecodealliance/wamr-app-framework.git
release_wamr_sdk_on_macos:
needs: [create_tag, create_release]
@ -167,6 +169,7 @@ jobs:
upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver}}
wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz
wamr_app_framework_url: https://github.com/bytecodealliance/wamr-app-framework.git
#
# vscode extension cross-platform

4
.gitignore vendored
View File

@ -14,13 +14,9 @@
core/deps/**
core/shared/mem-alloc/tlsf
core/app-framework/wgl
core/iwasm/libraries/lib-wasi-threads/test/*.wasm
core/iwasm/libraries/lib-socket/test/*.wasm
wamr-sdk/out/
wamr-sdk/runtime/build_runtime_sdk/
test-tools/host-tool/bin/
product-mini/app-samples/hello-world/test.wasm
product-mini/platforms/linux-sgx/enclave-sample/App/
product-mini/platforms/linux-sgx/enclave-sample/Enclave/

View File

@ -2,10 +2,10 @@ WebAssembly Micro Runtime Attributions
======================================
WAMR project reused some components from other open source project:
- **cJson**: used in the host_tool for remotely managing wasm applications
- **cJson**: in the repository [wamr-app-framework](https://github.com/bytecodealliance/wamr-app-framework/), used in the host_tool for remotely managing wasm applications
- **contiki-ng**: for the coap protocol implementation
- **freebsd libm**: used in core/shared/platform/alios/bh_math.c
- **LVGL**: for the gui samples and wrapped the wasm graphic layer
- **LVGL**: in the repository [wamr-app-framework](https://github.com/bytecodealliance/wamr-app-framework/), for the gui samples and wrapped the wasm graphic layer
- **llvm**: for the AOT/JIT compilation
- **wasm-c-api**: to implement the C-APIs of wasm. using headers and sameples
- **wasmtime**: for the wasi libc implementation
@ -42,7 +42,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
### cJson
[LICENSE](./test-tools/host-tool/external/cJSON/LICENSE)
[LICENSE](https://github.com/bytecodealliance/wamr-app-framework/blob/main/test-tools/host-tool/external/cJSON/LICENSE)
### contiki-ng
@ -54,13 +54,13 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
### LVGL
[LICENSE](./samples/littlevgl/LICENCE.txt)
[LICENSE](https://github.com/bytecodealliance/wamr-app-framework/blob/main/samples/littlevgl/LICENCE.txt)
[LICENSE](./core/app-framework/wgl/app/wa-inc/lvgl/LICENCE.txt)
[LICENSE](https://github.com/bytecodealliance/wamr-app-framework/blob/main/app-framework/wgl/app/wa-inc/lvgl/LICENCE.txt)
### llvm
[LICENSE](./core/deps/llvm/llvm/LICENCE.txt)
[LICENSE](./LICENCE.txt)
### wasm-c-api
@ -76,11 +76,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
### zephyr
[LICENSE](./samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE)
### wac
[LICENSE](./tests/wamr-test-suites/spec-test-script/LICENSE)
[LICENSE](https://github.com/bytecodealliance/wamr-app-framework/blob/main/samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE)
### libuv

View File

@ -3,6 +3,11 @@
cmake_minimum_required (VERSION 3.0)
if(ESP_PLATFORM)
include (${COMPONENT_DIR}/build-scripts/esp-idf/wamr/CMakeLists.txt)
return()
endif()
project (iwasm)
set (CMAKE_VERBOSE_MAKEFILE OFF)
@ -151,7 +156,7 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1)
endif ()
if (MINGW)
target_link_libraries (iwasm_shared -lWs2_32)
target_link_libraries (iwasm_shared INTERFACE -lWs2_32 -lwsock32)
endif ()
install (TARGETS iwasm_shared LIBRARY DESTINATION lib)

View File

@ -27,7 +27,7 @@ We Use Github Flow, So All Code Changes Happen Through Pull Requests. Pull reque
Coding Style
===============================
Please use [K&R](https://en.wikipedia.org/wiki/Indentation_style#K.26R) coding style, such as 4 spaces for indentation rather than tabs etc.
We suggest use Eclipse like IDE or stable coding format tools to make your code compliant to K&R format.
We suggest using VS Code like IDE or stable coding format tools, like clang-format, to make your code compliant to the customized format(in .clang-format).
Report bugs
===================

View File

@ -14,8 +14,8 @@ WebAssembly Micro Runtime (WAMR) is a lightweight standalone WebAssembly (Wasm)
- [**iwasm**](./product-mini/): The executable binary built with WAMR VMcore supports WASI and command line interface.
- [**wamrc**](./wamr-compiler/): The AOT compiler to compile Wasm file into AOT file
- Useful components and tools for building real solutions with WAMR vmcore:
- [App-framework](./core/app-framework/README.md): A framework for supporting APIs for the Wasm applications
- [App-manager](./core/app-mgr/README.md): a framework for dynamical loading the Wasm module remotely
- [App-framework](https://github.com/bytecodealliance/wamr-app-framework/blob/main/app-framework/README.md): A framework for supporting APIs for the Wasm applications
- [App-manager](https://github.com/bytecodealliance/wamr-app-framework/blob/main/app-mgr/README.md): a framework for dynamical loading the Wasm module remotely
- [WAMR-IDE](./test-tools/wamr-ide): An experimental VSCode extension for developping WebAssembly applications with C/C++
@ -35,15 +35,14 @@ WebAssembly Micro Runtime (WAMR) is a lightweight standalone WebAssembly (Wasm)
- [XIP (Execution In Place) support](./doc/xip.md), ref to [document](./doc/xip.md)
- [Berkeley/Posix Socket support](./doc/socket_api.md), ref to [document](./doc/socket_api.md) and [sample](./samples/socket-api)
- [Multi-tier JIT](./product-mini#linux) and [Running mode control](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-running-modes/)
- Language bindings: [Go](./language-bindings/go/README.md), [Python](./language-bindings/python/README.md)
- Language bindings: [Go](./language-bindings/go/README.md), [Python](./language-bindings/python/README.md), [Rust](./language-bindings/rust/README.md)
### Wasm post-MVP features
- [wasm-c-api](https://github.com/WebAssembly/wasm-c-api), ref to [document](doc/wasm_c_api.md) and [sample](samples/wasm-c-api)
- [128-bit SIMD](https://github.com/WebAssembly/simd), ref to [samples/workload](samples/workload)
- [Reference Types](https://github.com/WebAssembly/reference-types), ref to [document](doc/ref_types.md) and [sample](samples/ref-types)
- [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions)
- [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops), [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations)
- [Multi-value](https://github.com/WebAssembly/multi-value), [Tail-call](https://github.com/WebAssembly/tail-call), [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory)
- [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations), [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory), [Memory64](https://github.com/WebAssembly/memory64)
- [Tail-call](https://github.com/WebAssembly/tail-call), [Garbage Collection](https://github.com/WebAssembly/gc), [Exception Handling](https://github.com/WebAssembly/exception-handling)
### Supported architectures and platforms
The WAMR VMcore supports the following architectures:
@ -68,6 +67,7 @@ The following platforms are supported, click each link below for how to build iw
- [Port WAMR to a new platform](./doc/port_wamr.md)
- [VS Code development container](./doc/devcontainer.md)
- [Samples](./samples) and [Benchmarks](./tests/benchmarks)
- [End-user APIs documentation](https://bytecodealliance.github.io/wamr.dev/apis/)

View File

@ -1 +0,0 @@
/node_modules

View File

@ -1,124 +0,0 @@
# AssemblyScript_on_WAMR
This project is based on [Wasm Micro Runtime](https://github.com/bytecodealliance/wasm-micro-runtime) (WAMR) and [AssemblyScript](https://github.com/AssemblyScript/assemblyscript). It implements some of the `wamr app framework` in *assemblyscript*, which allows you to write some applications in *assemblyscript* and dynamically installed on *WAMR Runtime*
## Building
To build the samples in this repo, you need `npm` on your system
``` bash
sudo apt install npm
```
Then install all the dependencies under the repo's root dir
``` bash
cd $repo_root
npm install
```
Use the command to build all samples:
``` bash
npm run build:all
```
or you can build every sample individually:
``` bash
npm run build:timer
npm run build:publisher
npm run build:subscriber
# ...
```
You will get the compiled wasm file under `build` folder
Please refer to [package.json](./package.json) for more commands.
## Run
These applications require WAMR's application framework, you need to build WAMR first.
``` bash
cd ${WAMR_ROOT}/samples/simple
./build.sh
```
You will get two executable files under `out` folder:
`simple`: The wamr runtime with application framework
`host_tool`: The tool used to dynamically install/uninstall applications
1. Start the runtime:
``` bash
./simple -s
```
2. Install the compiled wasm file using `host_tool`:
``` bash
./host_tool -i app_name -f your_compiled_wasm_file.wasm
```
You can also use the WAMR's AoT compiler `wamrc` to compile the wasm bytecode into native code before you run them. Please refer to this [guide](../README.md#build-wamrc-aot-compiler) to build and install `WAMR AoT compiler`.
After installing `wamrc`, you can compile the wasm file using command:
``` bash
wamrc -o file_name.aot file_name.wasm
```
and you can install the AoT file to the runtime:
``` bash
./host_tool -i app_name -f your_compiled_aot_file.aot
```
## Development
You can develop your own application based on the `wamr_app_lib` APIs.
### Console APIs
``` typescript
function log(a: string): void;
function log_number(a: number): void;
```
### Timer APIs
``` typescript
function setTimeout(cb: () => void, timeout: i32): user_timer;
function setInterval(cb: () => void, timeout: i32): user_timer;
function timer_cancel(timer: user_timer): void;
function timer_restart(timer: user_timer, interval: number): void;
function now(): i32;
// export to runtime
function on_timer_callback(on_timer_id: i32): void;
```
### Request APIs
``` typescript
// register handler
function register_resource_handler(url: string,
request_handle: request_handler_f): void;
// request
function post(url: string, payload: ArrayBuffer, payload_len: number,
tag: string, cb: (resp: wamr_response) => void): void;
function get(url: string, tag: string,
cb: (resp: wamr_response) => void): void;
function put(url: string, payload: ArrayBuffer, payload_len: number, tag: string,
cb: (resp: wamr_response) => void): void;
function del(url: string, tag: string,
cb: (resp: wamr_response) => void): void;
// response
function make_response_for_request(req: wamr_request): wamr_response;
function api_response_send(resp: wamr_response): void;
// event
function publish_event(url: string, fmt: number,
payload: ArrayBuffer, payload_len: number): void;
function subscribe_event(url: string, cb: request_handler_f): void;
// export to runtime
function on_request(buffer_offset: i32, size: i32): void;
function on_response(buffer_offset : i32, size: i32): void;
```
You should export the `on_timer_callback`, `on_request` and `on_response` in your application entry file, refer to the samples for example.
To build your application, you can use `asc`:
``` bash
asc app.ts -b build/app.wasm -t build/app.wat --sourceMap --validate --optimize
```
or you can add a command into [package.json](./package.json):
``` json
"build:app": "asc app.ts -b build/app.wasm -t build/app.wat --sourceMap --validate --optimize",
```

View File

@ -1,30 +0,0 @@
{
"name": "assembly_script",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"assemblyscript": {
"version": "0.17.4",
"resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.17.4.tgz",
"integrity": "sha1-1GEduJpClDNa1H7DxmYaJqRCh3E=",
"dev": true,
"requires": {
"binaryen": "98.0.0-nightly.20201109",
"long": "^4.0.0"
}
},
"binaryen": {
"version": "98.0.0-nightly.20201109",
"resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-98.0.0-nightly.20201109.tgz",
"integrity": "sha1-USv2yhXGe/dAIURzSkg25jmTqgU=",
"dev": true
},
"long": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flong%2Fdownload%2Flong-4.0.0.tgz",
"integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=",
"dev": true
}
}
}

View File

@ -1,20 +0,0 @@
{
"name": "assembly_script",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --optimize --exportRuntime --use abort=",
"build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --optimize --exportRuntime --use abort=",
"build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --optimize --exportRuntime --use abort=",
"build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --optimize --exportRuntime --use abort=",
"build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --optimize --exportRuntime --use abort=",
"build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher"
},
"author": "",
"license": "ISC",
"devDependencies": {
"assemblyscript": "^0.18.15"
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
// The entry file of your WebAssembly module.
import * as console from "../wamr_app_lib/console"
import * as timer from "../wamr_app_lib/timer"
import * as request from "../wamr_app_lib/request"
function publish_overheat_event(): void {
var payload = String.UTF8.encode("warning: temperature is over high");
request.publish_event("alert/overheat", 0, payload, payload.byteLength);
}
export function on_init() : void {
timer.setInterval(publish_overheat_event, 2000);
}
export function on_destroy() : void {
}
/* Function below are requred by wamr runtime, don't remove or modify them */
export function _on_timer_callback(on_timer_id: i32): void {
timer.on_timer_callback(on_timer_id);
}
export function _on_request(buffer_offset: i32, size: i32): void {
request.on_request(buffer_offset, size);
}
export function _on_response(buffer_offset : i32, size: i32): void {
request.on_response(buffer_offset, size);
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
// The entry file of your WebAssembly module.
import * as console from "../wamr_app_lib/console"
import * as timer from "../wamr_app_lib/timer"
import * as request from "../wamr_app_lib/request"
export function on_init() : void {
request.subscribe_event("alert/overheat", (req) => {
console.log("### user over heat event handler called:");
console.log("");
console.log(" " + String.UTF8.decode(req.payload) + "\n");
})
}
export function on_destroy() : void {
}
/* Function below are requred by wamr runtime, don't remove or modify them */
export function _on_timer_callback(on_timer_id: i32): void {
timer.on_timer_callback(on_timer_id);
}
export function _on_request(buffer_offset: i32, size: i32): void {
request.on_request(buffer_offset, size);
}
export function _on_response(buffer_offset : i32, size: i32): void {
request.on_response(buffer_offset, size);
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
// The entry file of your WebAssembly module.
import * as console from "../wamr_app_lib/console"
import * as timer from "../wamr_app_lib/timer"
import * as request from "../wamr_app_lib/request"
export function on_init() : void {
request.register_resource_handler("/test", (req) => {
console.log("### Req: /test " + String.UTF8.decode(req.payload));
console.log(" request payload:");
console.log(" " + String.UTF8.decode(req.payload) + "\n");
var resp = request.make_response_for_request(req);
resp.set_payload(String.UTF8.encode("Ok"), 2);
request.api_response_send(resp);
});
}
export function on_destroy() : void {
}
/* Function below are requred by wamr runtime, don't remove or modify them */
export function _on_timer_callback(on_timer_id: i32): void {
timer.on_timer_callback(on_timer_id);
}
export function _on_request(buffer_offset: i32, size: i32): void {
request.on_request(buffer_offset, size);
}
export function _on_response(buffer_offset : i32, size: i32): void {
request.on_response(buffer_offset, size);
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
// The entry file of your WebAssembly module.
import * as console from "../wamr_app_lib/console"
import * as timer from "../wamr_app_lib/timer"
import * as request from "../wamr_app_lib/request"
export function on_init() : void {
var payload = String.UTF8.encode("test message");
request.post("/test", payload, payload.byteLength, "", (resp) => {
if (resp != null) {
console.log("Post Success");
if (resp.payload != null) {
console.log(" response payload:")
console.log(" " + String.UTF8.decode(resp.payload!) + "\n");
}
}
else
console.log("Post Timeout");
});
}
export function on_destroy() : void {
}
/* Function below are requred by wamr runtime, don't remove or modify them */
export function _on_timer_callback(on_timer_id: i32): void {
timer.on_timer_callback(on_timer_id);
}
export function _on_request(buffer_offset: i32, size: i32): void {
request.on_request(buffer_offset, size);
}
export function _on_response(buffer_offset : i32, size: i32): void {
request.on_response(buffer_offset, size);
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
// The entry file of your WebAssembly module.
import * as console from '../wamr_app_lib/console'
import * as timer from '../wamr_app_lib/timer'
/* clousure is not implemented yet, we need to declare global variables
so that they can be accessed inside a callback function */
var cnt = 0;
var my_timer: timer.user_timer;
export function on_init(): void {
/* The callback function will be called every 2 second,
and will stop after 10 calls */
my_timer = timer.setInterval(() => {
cnt ++;
console.log((cnt * 2).toString() + " seconds passed");
if (cnt >= 10) {
timer.timer_cancel(my_timer);
console.log("Stop Timer");
}
}, 2000);
}
export function on_destroy(): void {
}
/* Function below are requred by wamr runtime, don't remove or modify them */
export function _on_timer_callback(on_timer_id: i32): void {
timer.on_timer_callback(on_timer_id);
}

View File

@ -1,6 +0,0 @@
{
"extends": "../node_modules/assemblyscript/std/assembly.json",
"include": [
"./**/*.ts"
]
}

View File

@ -1,15 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
@external("env", "puts")
declare function printf(a: ArrayBuffer): i32;
export function log(a: string): void {
printf(String.UTF8.encode(a, true));
}
export function log_number(a: number): void {
printf(String.UTF8.encode(a.toString()));
}

View File

@ -1,495 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
import * as console from './console'
import * as timer from './timer'
@external("env", "wasm_response_send")
declare function wasm_response_send(buffer: ArrayBuffer, size: i32): bool;
@external("env", "wasm_register_resource")
declare function wasm_register_resource(url: ArrayBuffer): void;
@external("env", "wasm_post_request")
declare function wasm_post_request(buffer: ArrayBuffer, size: i32): void;
@external("env", "wasm_sub_event")
declare function wasm_sub_event(url: ArrayBuffer): void;
var COAP_GET = 1;
var COAP_POST = 2;
var COAP_PUT = 3;
var COAP_DELETE = 4;
var COAP_EVENT = COAP_DELETE + 2;
/* CoAP response codes */
export enum CoAP_Status {
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
};
var g_mid: i32 = 0;
class wamr_request {
mid: i32 = 0;
url: string = "";
action: i32 = 0;
fmt: i32 = 0;
payload: ArrayBuffer;
payload_len: i32 = 0;
sender: i32 = 0;
constructor(mid: i32, url: string, action: i32, fmt: i32,
payload: ArrayBuffer, payload_len: number) {
this.mid = mid;
this.url = url;
this.action = action;
this.fmt = fmt;
this.payload = payload;
this.payload_len = i32(payload_len);
}
}
class wamr_response {
mid: i32 = 0;
status: i32 = 0;
fmt: i32 = 0;
payload: ArrayBuffer | null;
payload_len: i32 = 0;
receiver: i32 = 0;
constructor(mid: i32, status: i32, fmt: i32,
payload: ArrayBuffer | null, payload_len: i32) {
this.mid = mid;
this.status = status;
this.fmt = fmt;
this.payload = payload;
this.payload_len = payload_len;
}
set_status(status: number): void {
this.status = i32(status);
}
set_payload(payload: ArrayBuffer, payload_len: number): void {
this.payload = payload;
this.payload_len = i32(payload_len);
}
}
class wamr_resource {
url: string;
type: number;
cb: request_handler_f;
constructor(url: string, type: number, cb: request_handler_f) {
this.url = url;
this.type = type;
this.cb = cb;
}
}
function is_expire(trans: wamr_transaction, index: i32, array: Array<wamr_transaction>): bool {
var now = timer.now();
var elapsed_ms = (now < trans.time) ?
(now + (0xFFFFFFFF - trans.time) + 1) : (now - trans.time);
return elapsed_ms >= TRANSACTION_TIMEOUT_MS;
}
function not_expire(trans: wamr_transaction, index: i32, array: Array<wamr_transaction>): bool {
var now = timer.now();
var elapsed_ms = (now < trans.time) ?
(now + (0xFFFFFFFF - trans.time) + 1) : (now - trans.time);
return elapsed_ms < TRANSACTION_TIMEOUT_MS;
}
function transaction_timeout_handler(): void {
var now = timer.now();
var expired = transaction_list.filter(is_expire);
transaction_list = transaction_list.filter(not_expire);
expired.forEach(item => {
item.cb(null);
transaction_remove(item);
})
if (transaction_list.length > 0) {
var elpased_ms: number, ms_to_expiry: number;
now = timer.now();
if (now < transaction_list[0].time) {
elpased_ms = now + (0xFFFFFFFF - transaction_list[0].time) + 1;
} else {
elpased_ms = now - transaction_list[0].time;
}
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
timer.timer_restart(g_trans_timer, ms_to_expiry);
} else {
timer.timer_cancel(g_trans_timer);
}
}
function transaction_find(mid: number): wamr_transaction | null {
for (let i = 0; i < transaction_list.length; i++) {
if (transaction_list[i].mid == mid)
return transaction_list[i];
}
return null;
}
function transaction_add(trans: wamr_transaction): void {
transaction_list.push(trans);
if (transaction_list.length == 1) {
g_trans_timer = timer.setTimeout(
transaction_timeout_handler,
TRANSACTION_TIMEOUT_MS
);
}
}
function transaction_remove(trans: wamr_transaction): void {
var index = transaction_list.indexOf(trans);
transaction_list.splice(index, 1);
}
var transaction_list = new Array<wamr_transaction>();
class wamr_transaction {
mid: number;
time: number;
cb: (resp: wamr_response | null) => void;
constructor(mid: number, time: number, cb: (resp: wamr_response) => void) {
this.mid = mid;
this.time = time;
this.cb = cb;
}
}
var REQUEST_PACKET_FIX_PART_LEN = 18;
var RESPONSE_PACKET_FIX_PART_LEN = 16;
var TRANSACTION_TIMEOUT_MS = 5000;
var g_trans_timer: timer.user_timer;
var Reg_Event = 0;
var Reg_Request = 1;
function pack_request(req: wamr_request): DataView {
var url_len = req.url.length + 1;
var len = REQUEST_PACKET_FIX_PART_LEN + url_len + req.payload_len
var buf = new ArrayBuffer(len);
var dataview = new DataView(buf, 0, len);
dataview.setUint8(0, 1);
dataview.setUint8(1, u8(req.action));
dataview.setUint16(2, u16(req.fmt));
dataview.setUint32(4, req.mid);
dataview.setUint32(8, req.sender);
dataview.setUint16(12, u16(url_len))
dataview.setUint32(14, req.payload_len);
var i = 0;
for (i = 0; i < url_len - 1; i++) {
dataview.setUint8(i + 18, u8(req.url.codePointAt(i)));
}
dataview.setUint8(i + 18, 0);
var payload_view = new DataView(req.payload);
for (i = 0; i < req.payload_len; i++) {
dataview.setUint8(i + 18 + url_len, u8(payload_view.getUint8(i)));
}
return dataview;
}
function unpack_request(packet: ArrayBuffer, size: i32): wamr_request {
var dataview = new DataView(packet, 0, size);
if (dataview.getUint8(0) != 1)
throw new Error("packet version mismatch");
if (size < REQUEST_PACKET_FIX_PART_LEN)
throw new Error("packet size error");
var url_len = dataview.getUint16(12);
var payload_len = dataview.getUint32(14);
if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len))
throw new Error("packet size error");
var action = dataview.getUint8(1);
var fmt = dataview.getUint16(2);
var mid = dataview.getUint32(4);
var sender = dataview.getUint32(8);
var url = packet.slice(REQUEST_PACKET_FIX_PART_LEN, REQUEST_PACKET_FIX_PART_LEN + url_len - 1);
var payload = packet.slice(REQUEST_PACKET_FIX_PART_LEN + url_len, REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len);
var req = new wamr_request(mid, String.UTF8.decode(url), action, fmt, payload, payload_len);
req.sender = sender;
return req;
}
function pack_response(resp: wamr_response): DataView {
var len = RESPONSE_PACKET_FIX_PART_LEN + resp.payload_len
var buf = new ArrayBuffer(len);
var dataview = new DataView(buf, 0, len);
dataview.setUint8(0, 1);
dataview.setUint8(1, u8(resp.status));
dataview.setUint16(2, u16(resp.fmt));
dataview.setUint32(4, resp.mid);
dataview.setUint32(8, resp.receiver);
dataview.setUint32(12, resp.payload_len)
if (resp.payload != null) {
var payload_view = new DataView(resp.payload!);
for (let i = 0; i < resp.payload_len; i++) {
dataview.setUint8(i + 16, payload_view.getUint8(i));
}
}
return dataview;
}
function unpack_response(packet: ArrayBuffer, size: i32): wamr_response {
var dataview = new DataView(packet, 0, size);
if (dataview.getUint8(0) != 1)
throw new Error("packet version mismatch");
if (size < RESPONSE_PACKET_FIX_PART_LEN)
throw new Error("packet size error");
var payload_len = dataview.getUint32(12);
if (size != RESPONSE_PACKET_FIX_PART_LEN + payload_len)
throw new Error("packet size error");
var status = dataview.getUint8(1);
var fmt = dataview.getUint16(2);
var mid = dataview.getUint32(4);
var receiver = dataview.getUint32(8);
var payload = packet.slice(RESPONSE_PACKET_FIX_PART_LEN);
var resp = new wamr_response(mid, status, fmt, payload, payload_len);
resp.receiver = receiver;
return resp;
}
function do_request(req: wamr_request, cb: (resp: wamr_response) => void): void {
var trans = new wamr_transaction(req.mid, timer.now(), cb);
var msg = pack_request(req);
transaction_add(trans);
wasm_post_request(msg.buffer, msg.byteLength);
}
function do_response(resp: wamr_response): void {
var msg = pack_response(resp);
wasm_response_send(msg.buffer, msg.byteLength);
}
var resource_list = new Array<wamr_resource>();
type request_handler_f = (req: wamr_request) => void;
function registe_url_handler(url: string, cb: request_handler_f, type: number): void {
for (let i = 0; i < resource_list.length; i++) {
if (resource_list[i].type == type && resource_list[i].url == url) {
resource_list[i].cb = cb;
return;
}
}
var res = new wamr_resource(url, type, cb);
resource_list.push(res);
if (type == Reg_Request)
wasm_register_resource(String.UTF8.encode(url));
else
wasm_sub_event(String.UTF8.encode(url));
}
function is_event_type(req: wamr_request): bool {
return req.action == COAP_EVENT;
}
function check_url_start(url: string, leading_str: string): bool {
return url.split('/')[0] == leading_str.split('/')[0];
}
/* User APIs below */
export function post(url: string, payload: ArrayBuffer, payload_len: number, tag: string,
cb: (resp: wamr_response) => void): void {
var req = new wamr_request(g_mid++, url, COAP_POST, 0, payload, payload_len);
do_request(req, cb);
}
export function get(url: string, tag: string,
cb: (resp: wamr_response) => void): void {
var req = new wamr_request(g_mid++, url, COAP_GET, 0, new ArrayBuffer(0), 0);
do_request(req, cb);
}
export function put(url: string, payload: ArrayBuffer, payload_len: number, tag: string,
cb: (resp: wamr_response) => void): void {
var req = new wamr_request(g_mid++, url, COAP_PUT, 0, payload, payload_len);
do_request(req, cb);
}
export function del(url: string, tag: string,
cb: (resp: wamr_response) => void): void {
var req = new wamr_request(g_mid++, url, COAP_DELETE, 0, new ArrayBuffer(0), 0);
do_request(req, cb);
}
export function make_response_for_request(req: wamr_request): wamr_response {
var resp = new wamr_response(req.mid, CoAP_Status.CONTENT_2_05, 0, null, 0);
resp.receiver = req.sender;
return resp;
}
export function api_response_send(resp: wamr_response): void {
do_response(resp);
}
export function register_resource_handler(url: string,
request_handle: request_handler_f): void {
registe_url_handler(url, request_handle, Reg_Request);
}
export function publish_event(url: string, fmt: number,
payload: ArrayBuffer, payload_len: number): void {
var req = new wamr_request(g_mid++, url, COAP_EVENT, i32(fmt), payload, payload_len);
var msg = pack_request(req);
wasm_post_request(msg.buffer, msg.byteLength);
}
export function subscribe_event(url: string, cb: request_handler_f): void {
registe_url_handler(url, cb, Reg_Event);
}
/* These two APIs are required by wamr runtime,
use a wrapper to export them in the entry file
e.g:
import * as request from '.wamr_app_lib/request'
// Your code here ...
export function _on_request(buffer_offset: i32, size: i32): void {
on_request(buffer_offset, size);
}
export function _on_response(buffer_offset: i32, size: i32): void {
on_response(buffer_offset, size);
}
*/
export function on_request(buffer_offset: i32, size: i32): void {
var buffer = new ArrayBuffer(size);
var dataview = new DataView(buffer);
for (let i = 0; i < size; i++) {
dataview.setUint8(i, load<i8>(buffer_offset + i, 0, 1));
}
var req = unpack_request(buffer, size);
var is_event = is_event_type(req);
for (let i = 0; i < resource_list.length; i++) {
if ((is_event && resource_list[i].type == Reg_Event)
|| (!is_event && resource_list[i].type == Reg_Request)) {
if (check_url_start(req.url, resource_list[i].url)) {
resource_list[i].cb(req);
return;
}
}
}
console.log("on_request: exit. no service handler.");
}
export function on_response(buffer_offset: i32, size: i32): void {
var buffer = new ArrayBuffer(size);
var dataview = new DataView(buffer);
for (let i = 0; i < size; i++) {
dataview.setUint8(i, load<i8>(buffer_offset + i, 0, 1));
}
var resp = unpack_response(buffer, size);
var trans = transaction_find(resp.mid);
if (trans != null) {
if (transaction_list.indexOf(trans) == 0) {
if (transaction_list.length >= 2) {
var elpased_ms: number, ms_to_expiry: number;
var now = timer.now();
if (now < transaction_list[1].time) {
elpased_ms = now + (0xFFFFFFFF - transaction_list[1].time) + 1;
} else {
elpased_ms = now - transaction_list[1].time;
}
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
timer.timer_restart(g_trans_timer, ms_to_expiry);
} else {
timer.timer_cancel(g_trans_timer);
}
}
trans.cb(resp);
}
}

View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
@external("env", "wasm_create_timer")
declare function wasm_create_timer(a: i32, b: bool, c: bool): i32;
@external("env", "wasm_timer_cancel")
declare function wasm_timer_cancel(a: i32): void;
@external("env", "wasm_timer_restart")
declare function wasm_timer_restart(a: i32, b: i32): void;
@external("env", "wasm_get_sys_tick_ms")
declare function wasm_get_sys_tick_ms(): i32;
export var timer_list = new Array<user_timer>();
export class user_timer {
timer_id: i32 = 0;
timeout: i32;
period: bool = false;
cb: () => void;
constructor(cb: () => void, timeout: i32, period: bool) {
this.cb = cb;
this.timeout = timeout;
this.period = period
this.timer_id = timer_create(this.timeout, this.period, true);
}
}
export function timer_create(a: i32, b: bool, c: bool): i32 {
return wasm_create_timer(a, b, c);
}
export function setTimeout(cb: () => void, timeout: i32): user_timer {
var timer = new user_timer(cb, timeout, false);
timer_list.push(timer);
return timer;
}
export function setInterval(cb: () => void, timeout: i32): user_timer {
var timer = new user_timer(cb, timeout, true);
timer_list.push(timer);
return timer;
}
export function timer_cancel(timer: user_timer): void {
wasm_timer_cancel(timer.timer_id);
var i = 0;
for (i = 0; i < timer_list.length; i++) {
if (timer_list[i].timer_id == timer.timer_id)
break;
}
timer_list.splice(i, 1);
}
export function timer_restart(timer: user_timer, interval: number): void {
wasm_timer_restart(timer.timer_id, i32(interval));
}
export function now(): i32 {
return wasm_get_sys_tick_ms();
}
// This export function need to be copied to the top application file
//
export function on_timer_callback(on_timer_id: i32): void {
for (let i = 0; i < timer_list.length; i++) {
if (timer_list[i].timer_id == on_timer_id) {
timer_list[i].cb();
}
}
}

View File

@ -1,6 +0,0 @@
{
"extends": "../node_modules/assemblyscript/std/assembly.json",
"include": [
"./**/*.ts"
]
}

View File

@ -13,8 +13,6 @@ objs = []
WAMR_ROOT_DIR = os.path.join(cwd, "..")
SHARED_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'shared')
IWASM_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'iwasm')
APP_MGR_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-mgr')
APP_FRAMEWORK_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-framework')
DEPS_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'deps')
if GetDepend(['WAMR_BUILD_INTERP']):
@ -28,12 +26,6 @@ if GetDepend(['WAMR_BUILD_AOT']):
script_path = os.path.join(IWASM_DIR, 'compilation', 'SConscript')
objs += SConscript(script_path)
if GetDepend(['WAMR_BUILD_APP_FRAMEWORK']):
objs += SConscript(os.path.join(APP_FRAMEWORK_DIR, 'SConscript'))
objs += SConscript(os.path.join(SHARED_DIR, 'coap', 'SConscript'))
objs += SConscript(os.path.join(APP_MGR_DIR, 'app-manager', 'SConscript'))
objs += SConscript(os.path.join(APP_MGR_DIR, 'app-mgr-shared', 'SConscript'))
if GetDepend(['WAMR_BUILD_LIBC_BUILTIN']):
objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-builtin', 'SConscript'))

View File

@ -248,6 +248,15 @@ if (WAMR_BUILD_SHARED_MEMORY EQUAL 1)
else ()
add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0)
endif ()
if (WAMR_BUILD_MEMORY64 EQUAL 1)
# if native is 32-bit or cross-compiled to 32-bit
if (NOT WAMR_BUILD_TARGET MATCHES ".*64.*")
message (FATAL_ERROR "-- Memory64 is only available on the 64-bit platform/target")
endif()
add_definitions (-DWASM_ENABLE_MEMORY64=1)
set (WAMR_DISABLE_HW_BOUND_CHECK 1)
message (" Memory64 memory enabled")
endif ()
if (WAMR_BUILD_THREAD_MGR EQUAL 1)
message (" Thread manager enabled")
endif ()
@ -430,6 +439,10 @@ if (WAMR_BUILD_WASI_NN EQUAL 1)
if (DEFINED WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH)
add_definitions (-DWASM_WASI_NN_EXTERNAL_DELEGATE_PATH="${WAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH}")
endif ()
if (WAMR_BUILD_WASI_EPHEMERAL_NN EQUAL 1)
message (" WASI-NN: WASI-Ephemeral-NN enabled")
add_definitions (-DWASM_ENABLE_WASI_EPHEMERAL_NN=1)
endif()
endif ()
if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1)
add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1)
@ -525,3 +538,19 @@ else ()
# Disable quick aot/jit entries for interp and fast-jit
add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=0)
endif ()
if (WAMR_BUILD_AOT EQUAL 1)
if (NOT DEFINED WAMR_BUILD_AOT_INTRINSICS)
# Enable aot intrinsics by default
set (WAMR_BUILD_AOT_INTRINSICS 1)
endif ()
if (WAMR_BUILD_AOT_INTRINSICS EQUAL 1)
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=1)
message (" AOT intrinsics enabled")
else ()
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0)
message (" AOT intrinsics disabled")
endif ()
else ()
# Disable aot intrinsics for interp, fast-jit and llvm-jit
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0)
endif ()

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# Set WAMR's build options
if("${IDF_TARGET}" STREQUAL "esp32c3")
if("${IDF_TARGET}" STREQUAL "esp32c3" OR "${IDF_TARGET}" STREQUAL "esp32c6")
set(WAMR_BUILD_TARGET "RISCV32")
else()
set(WAMR_BUILD_TARGET "XTENSA")

View File

@ -10,12 +10,6 @@ endif ()
if (NOT DEFINED IWASM_DIR)
set (IWASM_DIR ${WAMR_ROOT_DIR}/core/iwasm)
endif ()
if (NOT DEFINED APP_MGR_DIR)
set (APP_MGR_DIR ${WAMR_ROOT_DIR}/core/app-mgr)
endif ()
if (NOT DEFINED APP_FRAMEWORK_DIR)
set (APP_FRAMEWORK_DIR ${WAMR_ROOT_DIR}/core/app-framework)
endif ()
if (NOT DEFINED DEPS_DIR)
set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
endif ()
@ -88,13 +82,6 @@ if (WAMR_BUILD_GC EQUAL 1)
set (WAMR_BUILD_REF_TYPES 1)
endif ()
if (WAMR_BUILD_APP_FRAMEWORK EQUAL 1)
include (${APP_FRAMEWORK_DIR}/app_framework.cmake)
include (${SHARED_DIR}/coap/lib_coap.cmake)
include (${APP_MGR_DIR}/app-manager/app_mgr.cmake)
include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake)
endif ()
if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
endif ()
@ -200,9 +187,6 @@ set (source_all
${IWASM_COMPL_SOURCE}
${IWASM_FAST_JIT_SOURCE}
${IWASM_GC_SOURCE}
${WASM_APP_LIB_SOURCE_ALL}
${NATIVE_INTERFACE_SOURCE}
${APP_MGR_SOURCE}
${LIB_WASI_THREADS_SOURCE}
${LIB_PTHREAD_SOURCE}
${THREAD_MGR_SOURCE}

View File

@ -21,7 +21,6 @@ EXCLUDE_PATHS = [
"**/.git/*",
"**/.github/*",
"**/.vscode/*",
"**/assembly-script/*",
"**/build/*",
"**/build-scripts/*",
"**/ci/*",
@ -30,9 +29,7 @@ EXCLUDE_PATHS = [
"**/samples/wasm-c-api/src/*.*",
"**/samples/workload/*",
"**/test-tools/wasi-sdk/*",
"**/test-tools/IoT-APP-Store-Demo/*",
"**/tests/wamr-test-suites/workspace/*",
"**/wamr-sdk/*",
]
C_SUFFIXES = [".c", ".cpp", ".h"]

View File

@ -1,120 +0,0 @@
# Application framework
By using the WAMR VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some effort.
The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, that are based on the event driven programming model. Here are the supporting API sets by the [WAMR application framework library](../doc/wamr_api.md) :
- Timer, Inter-app communication (request/response and pub/sub), Sensor, Connectivity and data transmission, 2D graphic UI
Browse the folder [core/app-framework](./app-framework) for how to extend the application framework.
## Directory structure
This folder "app-native-shared" is for the source files shared by both WASM APP and native runtime
- The c files in this directory are compiled into both the WASM APP and runtime.
- The header files for distributing to SDK are placed in the "bi-inc" folder.
This folder "template" contains a pre-defined directory structure for a framework component. The developers can copy the template folder to create new components to the application framework.
Every other subfolder is framework component. Each component contains two library parts: **app and native**.
- The "base" component provide timer API and inter-app communication support. It must be enabled if other components are selected.
- Under the "app" folder of a component, the subfolder "wa_inc" holds all header files that should be included by the WASM applications
## Application framework basic model
The app framework is built on top of two fundamental operations:
- [Native calls into WASM function](../../doc/embed_wamr.md)
- [WASM app calls into native API](../../doc/export_native_api.md)
Asynchronized programming model is supported for WASM applications
- Every WASM app has its own sandbox and thread
- Queue and messaging
<img src="../../doc/pics/app_framework.PNG" style="zoom:67%;" />
## Customized building of app framework
A component can be compilation configurable to the runtime. The wamr SDK tool "build_sdk.sh" supports menu config to select app components for building a customized runtime.
A number of CMAKE variables are defined to control build of framework and components. You can create a cmake file for defining these variables and include it in the CMakeList.txt for your software, or pass it in "-x" argument when run the [build_sdk.sh](../../wamr-sdk/build_sdk.sh) for building the runtime SDK.
```cmake
set (WAMR_BUILD_APP_FRAMEWORK 1)
set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE)
```
Variables:
- **WAMR_BUILD_APP_FRAMEWORK**: enable the application framework
- **WAMR_BUILD_APP_LIST**: the selected components to be built into the final runtime
The configuration file can be generated through the wamr-sdk menu config:
```bash
cd wamr-sdk
./build_sdk -n [profile] -i
```
## Create new components
Generally you should follow following steps to create a new component:
- Copy the “template” for creating a new folder
- Implement the app part
- If your component exports native function to WASM, ensure your created a header file under app for declaring the function prototype.
- If you component provides header files for the WASM applications to include, ensure it is placed under subfolder "wa_inc".
- Implement the native part
- If your native function is exported to WASM, you need to create an inl file for the registration. It can be any file name, assuming the file name is "my_component.inl" here:
```c
//use right signature for your functions
EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_1, "(i*~)i"),
EXPORT_WASM_API_WITH_SIG(wasm_my_component_api_2, "(i)i"),
```
- Ensure "wasm_lib.cmake" is provided as it will be included by the WAMR SDK building script
- Add a definition in "wasm_lib.cmake" for your component, e.g.
```cmake
add_definitions (-DAPP_FRAMEWORK_MY_COMPONENT)
```
- Modify the file [app_ext_lib_export.c](./app_ext_lib_export.c) to register native APIs exported for the new introduced component. Skip it if not exporting native functions.
```
#include "lib_export.h"
...
#ifdef APP_FRAMEWORK_MY_COMPONENT // this definition is created in wasm_lib.cmake
#include "my_component_native_api.h"
#endif
static NativeSymbol extended_native_symbol_defs[] = {
...
#ifdef APP_FRAMEWORK_MY_COMPONENT
#include "my_component.inl"
#endif
};
```
## Sensor component working flow
![](../../doc/pics/sensor_callflow.PNG)

View File

@ -1,11 +0,0 @@
Notes:
=======
This folder is for the source files shared by both WASM APP and native runtime
- The c files in this directory are compiled into both the WASM APP and runtime.
- The header files for distributing to SDK are placed in the "bi-inc" folder.

View File

@ -1,986 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bi-inc/attr_container.h"
typedef union jvalue {
bool z;
int8_t i8;
uint8_t u8;
int16_t i16;
uint16_t u16;
int32_t i32;
uint32_t u32;
int64_t i64;
uint64_t u64;
float f;
double d;
} jvalue;
static inline int16_t
get_int16(const char *buf)
{
int16_t ret;
bh_memcpy_s(&ret, sizeof(int16_t), buf, sizeof(int16_t));
return ret;
}
static inline uint16_t
get_uint16(const char *buf)
{
uint16_t ret;
bh_memcpy_s(&ret, sizeof(uint16_t), buf, sizeof(uint16_t));
return ret;
}
static inline int32_t
get_int32(const char *buf)
{
int32_t ret;
bh_memcpy_s(&ret, sizeof(int32_t), buf, sizeof(int32_t));
return ret;
}
static inline uint32_t
get_uint32(const char *buf)
{
uint32_t ret;
bh_memcpy_s(&ret, sizeof(uint32_t), buf, sizeof(uint32_t));
return ret;
}
static inline int64_t
get_int64(const char *buf)
{
int64_t ret;
bh_memcpy_s(&ret, sizeof(int64_t), buf, sizeof(int64_t));
return ret;
}
static inline uint64_t
get_uint64(const char *buf)
{
uint64_t ret;
bh_memcpy_s(&ret, sizeof(uint64_t), buf, sizeof(uint64_t));
return ret;
}
static inline void
set_int16(char *buf, int16_t v)
{
bh_memcpy_s(buf, sizeof(int16_t), &v, sizeof(int16_t));
}
static inline void
set_uint16(char *buf, uint16_t v)
{
bh_memcpy_s(buf, sizeof(uint16_t), &v, sizeof(uint16_t));
}
static inline void
set_int32(char *buf, int32_t v)
{
bh_memcpy_s(buf, sizeof(int32_t), &v, sizeof(int32_t));
}
static inline void
set_uint32(char *buf, uint32_t v)
{
bh_memcpy_s(buf, sizeof(uint32_t), &v, sizeof(uint32_t));
}
static inline void
set_int64(char *buf, int64_t v)
{
bh_memcpy_s(buf, sizeof(int64_t), &v, sizeof(int64_t));
}
static inline void
set_uint64(char *buf, uint64_t v)
{
bh_memcpy_s(buf, sizeof(uint64_t), &v, sizeof(uint64_t));
}
char *
attr_container_get_attr_begin(const attr_container_t *attr_cont,
uint32_t *p_total_length, uint16_t *p_attr_num)
{
char *p = (char *)attr_cont->buf;
uint16_t str_len, attr_num;
uint32_t total_length;
/* skip total length */
total_length = get_uint32(p);
p += sizeof(uint32_t);
if (!total_length)
return NULL;
/* tag length */
str_len = get_uint16(p);
p += sizeof(uint16_t);
if (!str_len)
return NULL;
/* tag content */
p += str_len;
if ((uint32_t)(p - attr_cont->buf) >= total_length)
return NULL;
/* attribute num */
attr_num = get_uint16(p);
p += sizeof(uint16_t);
if ((uint32_t)(p - attr_cont->buf) >= total_length)
return NULL;
if (p_total_length)
*p_total_length = total_length;
if (p_attr_num)
*p_attr_num = attr_num;
/* first attribute */
return p;
}
static char *
attr_container_get_attr_next(const char *curr_attr)
{
char *p = (char *)curr_attr;
uint8_t type;
/* key length and key */
p += sizeof(uint16_t) + get_uint16(p);
type = *p++;
/* Byte type to Boolean type */
if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) {
p += 1 << (type & 3);
return p;
}
/* String type */
else if (type == ATTR_TYPE_STRING) {
p += sizeof(uint16_t) + get_uint16(p);
return p;
}
/* ByteArray type */
else if (type == ATTR_TYPE_BYTEARRAY) {
p += sizeof(uint32_t) + get_uint32(p);
return p;
}
return NULL;
}
static const char *
attr_container_find_attr(const attr_container_t *attr_cont, const char *key)
{
uint32_t total_length;
uint16_t str_len, attr_num, i;
const char *p = attr_cont->buf;
if (!key)
return NULL;
if (!(p = attr_container_get_attr_begin(attr_cont, &total_length,
&attr_num)))
return NULL;
for (i = 0; i < attr_num; i++) {
/* key length */
if (!(str_len = get_uint16(p)))
return NULL;
if (str_len == strlen(key) + 1
&& memcmp(p + sizeof(uint16_t), key, str_len) == 0) {
if ((uint32_t)(p + sizeof(uint16_t) + str_len - attr_cont->buf)
>= total_length)
return NULL;
return p;
}
if (!(p = attr_container_get_attr_next(p)))
return NULL;
}
return NULL;
}
char *
attr_container_get_attr_end(const attr_container_t *attr_cont)
{
uint32_t total_length;
uint16_t attr_num, i;
char *p;
if (!(p = attr_container_get_attr_begin(attr_cont, &total_length,
&attr_num)))
return NULL;
for (i = 0; i < attr_num; i++)
if (!(p = attr_container_get_attr_next(p)))
return NULL;
return p;
}
static char *
attr_container_get_msg_end(attr_container_t *attr_cont)
{
char *p = attr_cont->buf;
return p + get_uint32(p);
}
uint16_t
attr_container_get_attr_num(const attr_container_t *attr_cont)
{
uint16_t str_len;
/* skip total length */
const char *p = attr_cont->buf + sizeof(uint32_t);
str_len = get_uint16(p);
/* skip tag length and tag */
p += sizeof(uint16_t) + str_len;
/* attribute num */
return get_uint16(p);
}
static void
attr_container_inc_attr_num(attr_container_t *attr_cont)
{
uint16_t str_len, attr_num;
/* skip total length */
char *p = attr_cont->buf + sizeof(uint32_t);
str_len = get_uint16(p);
/* skip tag length and tag */
p += sizeof(uint16_t) + str_len;
/* attribute num */
attr_num = get_uint16(p) + 1;
set_uint16(p, attr_num);
}
attr_container_t *
attr_container_create(const char *tag)
{
attr_container_t *attr_cont;
int length, tag_length;
char *p;
tag_length = tag ? strlen(tag) + 1 : 1;
length = offsetof(attr_container_t, buf) +
/* total length + tag length + tag + reserved 100 bytes */
sizeof(uint32_t) + sizeof(uint16_t) + tag_length + 100;
if (!(attr_cont = attr_container_malloc(length))) {
attr_container_printf(
"Create attr_container failed: allocate memory failed.\r\n");
return NULL;
}
memset(attr_cont, 0, length);
p = attr_cont->buf;
/* total length */
set_uint32(p, length - offsetof(attr_container_t, buf));
p += 4;
/* tag length, tag */
set_uint16(p, tag_length);
p += 2;
if (tag)
bh_memcpy_s(p, tag_length, tag, tag_length);
return attr_cont;
}
void
attr_container_destroy(const attr_container_t *attr_cont)
{
if (attr_cont)
attr_container_free((char *)attr_cont);
}
static bool
check_set_attr(attr_container_t **p_attr_cont, const char *key)
{
uint32_t flags;
if (!p_attr_cont || !*p_attr_cont || !key || strlen(key) == 0) {
attr_container_printf(
"Set attribute failed: invalid input arguments.\r\n");
return false;
}
flags = get_uint32((char *)*p_attr_cont);
if (flags & ATTR_CONT_READONLY_SHIFT) {
attr_container_printf(
"Set attribute failed: attribute container is readonly.\r\n");
return false;
}
return true;
}
bool
attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
int type, const void *value, int value_length)
{
attr_container_t *attr_cont, *attr_cont1;
uint16_t str_len;
uint32_t total_length, attr_len;
char *p, *p1, *attr_end, *msg_end, *attr_buf;
if (!check_set_attr(p_attr_cont, key)) {
return false;
}
attr_cont = *p_attr_cont;
p = attr_cont->buf;
total_length = get_uint32(p);
if (!(attr_end = attr_container_get_attr_end(attr_cont))) {
attr_container_printf("Set attr failed: get attr end failed.\r\n");
return false;
}
msg_end = attr_container_get_msg_end(attr_cont);
/* key len + key + '\0' + type */
attr_len = sizeof(uint16_t) + strlen(key) + 1 + 1;
if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN)
attr_len += 1 << (type & 3);
else if (type == ATTR_TYPE_STRING)
attr_len += sizeof(uint16_t) + value_length;
else if (type == ATTR_TYPE_BYTEARRAY)
attr_len += sizeof(uint32_t) + value_length;
if (!(p = attr_buf = attr_container_malloc(attr_len))) {
attr_container_printf("Set attr failed: allocate memory failed.\r\n");
return false;
}
/* Set the attr buf */
str_len = (uint16_t)(strlen(key) + 1);
set_uint16(p, str_len);
p += sizeof(uint16_t);
bh_memcpy_s(p, str_len, key, str_len);
p += str_len;
*p++ = type;
if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN)
bh_memcpy_s(p, 1 << (type & 3), value, 1 << (type & 3));
else if (type == ATTR_TYPE_STRING) {
set_uint16(p, value_length);
p += sizeof(uint16_t);
bh_memcpy_s(p, value_length, value, value_length);
}
else if (type == ATTR_TYPE_BYTEARRAY) {
set_uint32(p, value_length);
p += sizeof(uint32_t);
bh_memcpy_s(p, value_length, value, value_length);
}
if ((p = (char *)attr_container_find_attr(attr_cont, key))) {
/* key found */
p1 = attr_container_get_attr_next(p);
if (p1 - p == attr_len) {
bh_memcpy_s(p, attr_len, attr_buf, attr_len);
attr_container_free(attr_buf);
return true;
}
if ((uint32_t)(p1 - p + msg_end - attr_end) >= attr_len) {
memmove(p, p1, attr_end - p1);
bh_memcpy_s(p + (attr_end - p1), attr_len, attr_buf, attr_len);
attr_container_free(attr_buf);
return true;
}
total_length += attr_len + 100;
if (!(attr_cont1 = attr_container_malloc(offsetof(attr_container_t, buf)
+ total_length))) {
attr_container_printf(
"Set attr failed: allocate memory failed.\r\n");
attr_container_free(attr_buf);
return false;
}
bh_memcpy_s(attr_cont1, p - (char *)attr_cont, attr_cont,
p - (char *)attr_cont);
bh_memcpy_s((char *)attr_cont1 + (unsigned)(p - (char *)attr_cont),
attr_end - p1, p1, attr_end - p1);
bh_memcpy_s((char *)attr_cont1 + (unsigned)(p - (char *)attr_cont)
+ (unsigned)(attr_end - p1),
attr_len, attr_buf, attr_len);
p = attr_cont1->buf;
set_uint32(p, total_length);
*p_attr_cont = attr_cont1;
/* Free original buffer */
attr_container_free(attr_cont);
attr_container_free(attr_buf);
return true;
}
else {
/* key not found */
if ((uint32_t)(msg_end - attr_end) >= attr_len) {
bh_memcpy_s(attr_end, msg_end - attr_end, attr_buf, attr_len);
attr_container_inc_attr_num(attr_cont);
attr_container_free(attr_buf);
return true;
}
total_length += attr_len + 100;
if (!(attr_cont1 = attr_container_malloc(offsetof(attr_container_t, buf)
+ total_length))) {
attr_container_printf(
"Set attr failed: allocate memory failed.\r\n");
attr_container_free(attr_buf);
return false;
}
bh_memcpy_s(attr_cont1, attr_end - (char *)attr_cont, attr_cont,
attr_end - (char *)attr_cont);
bh_memcpy_s((char *)attr_cont1
+ (unsigned)(attr_end - (char *)attr_cont),
attr_len, attr_buf, attr_len);
attr_container_inc_attr_num(attr_cont1);
p = attr_cont1->buf;
set_uint32(p, total_length);
*p_attr_cont = attr_cont1;
/* Free original buffer */
attr_container_free(attr_cont);
attr_container_free(attr_buf);
return true;
}
return false;
}
bool
attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
short value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_SHORT, &value,
2);
}
bool
attr_container_set_int16(attr_container_t **p_attr_cont, const char *key,
int16_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT16, &value,
2);
}
bool
attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
int value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT, &value, 4);
}
bool
attr_container_set_int32(attr_container_t **p_attr_cont, const char *key,
int32_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT32, &value,
4);
}
bool
attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key,
uint32_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT32, &value,
4);
}
bool
attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
int64_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT64, &value,
8);
}
bool
attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key,
uint64_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT64, &value,
8);
}
bool
attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
int8_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTE, &value, 1);
}
bool
attr_container_set_int8(attr_container_t **p_attr_cont, const char *key,
int8_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT8, &value, 1);
}
bool
attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key,
uint8_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT8, &value,
1);
}
bool
attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
uint16_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT16, &value,
2);
}
bool
attr_container_set_float(attr_container_t **p_attr_cont, const char *key,
float value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_FLOAT, &value,
4);
}
bool
attr_container_set_double(attr_container_t **p_attr_cont, const char *key,
double value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_DOUBLE, &value,
8);
}
bool
attr_container_set_bool(attr_container_t **p_attr_cont, const char *key,
bool value)
{
int8_t value1 = value ? 1 : 0;
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BOOLEAN, &value1,
1);
}
bool
attr_container_set_string(attr_container_t **p_attr_cont, const char *key,
const char *value)
{
if (!value) {
attr_container_printf("Set attr failed: invald input arguments.\r\n");
return false;
}
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_STRING, value,
strlen(value) + 1);
}
bool
attr_container_set_bytearray(attr_container_t **p_attr_cont, const char *key,
const int8_t *value, unsigned length)
{
if (!value) {
attr_container_printf("Set attr failed: invald input arguments.\r\n");
return false;
}
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTEARRAY, value,
length);
}
static const char *
attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
{
const char *attr_addr;
if (!attr_cont || !key) {
attr_container_printf(
"Get attribute failed: invalid input arguments.\r\n");
return NULL;
}
if (!(attr_addr = attr_container_find_attr(attr_cont, key))) {
attr_container_printf("Get attribute failed: lookup key failed.\r\n");
return NULL;
}
/* key len + key + '\0' */
return attr_addr + 2 + strlen(key) + 1;
}
#define TEMPLATE_ATTR_BUF_TO_VALUE(attr, key, var_name) \
do { \
jvalue val; \
const char *addr = attr_container_get_attr(attr, key); \
uint8_t type; \
if (!addr) \
return 0; \
val.i64 = 0; \
type = *(uint8_t *)addr++; \
switch (type) { \
case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ \
case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ \
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ \
case ATTR_TYPE_INT64: \
case ATTR_TYPE_UINT8: \
case ATTR_TYPE_UINT16: \
case ATTR_TYPE_UINT32: \
case ATTR_TYPE_UINT64: \
case ATTR_TYPE_FLOAT: \
case ATTR_TYPE_DOUBLE: \
case ATTR_TYPE_BOOLEAN: \
bh_memcpy_s(&val, sizeof(val.var_name), addr, \
1 << (type & 3)); \
break; \
case ATTR_TYPE_STRING: \
{ \
unsigned len = get_uint16(addr); \
addr += 2; \
if (len > sizeof(val.var_name)) \
len = sizeof(val.var_name); \
bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
break; \
} \
case ATTR_TYPE_BYTEARRAY: \
{ \
unsigned len = get_uint32(addr); \
addr += 4; \
if (len > sizeof(val.var_name)) \
len = sizeof(val.var_name); \
bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
break; \
} \
default: \
bh_assert(0); \
break; \
} \
return val.var_name; \
} while (0)
short
attr_container_get_as_short(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i16);
}
int16_t
attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key)
{
return (int16_t)attr_container_get_as_short(attr_cont, key);
}
int
attr_container_get_as_int(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i32);
}
int32_t
attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key)
{
return (int32_t)attr_container_get_as_int(attr_cont, key);
}
uint32_t
attr_container_get_as_uint32(const attr_container_t *attr_cont, const char *key)
{
return (uint32_t)attr_container_get_as_int(attr_cont, key);
}
int64_t
attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i64);
}
uint64_t
attr_container_get_as_uint64(const attr_container_t *attr_cont, const char *key)
{
return (uint64_t)attr_container_get_as_int64(attr_cont, key);
}
int8_t
attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i8);
}
int8_t
attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key)
{
return attr_container_get_as_byte(attr_cont, key);
}
uint8_t
attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key)
{
return (uint8_t)attr_container_get_as_byte(attr_cont, key);
}
uint16_t
attr_container_get_as_uint16(const attr_container_t *attr_cont, const char *key)
{
return (uint16_t)attr_container_get_as_short(attr_cont, key);
}
float
attr_container_get_as_float(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, f);
}
double
attr_container_get_as_double(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, d);
}
bool
attr_container_get_as_bool(const attr_container_t *attr_cont, const char *key)
{
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, z);
}
const int8_t *
attr_container_get_as_bytearray(const attr_container_t *attr_cont,
const char *key, unsigned *array_length)
{
const char *addr = attr_container_get_attr(attr_cont, key);
uint8_t type;
uint32_t length;
if (!addr)
return NULL;
if (!array_length) {
attr_container_printf("Get attribute failed: invalid input arguments.");
return NULL;
}
type = *(uint8_t *)addr++;
switch (type) {
case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
case ATTR_TYPE_INT64:
case ATTR_TYPE_UINT8:
case ATTR_TYPE_UINT16:
case ATTR_TYPE_UINT32:
case ATTR_TYPE_UINT64:
case ATTR_TYPE_FLOAT:
case ATTR_TYPE_DOUBLE:
case ATTR_TYPE_BOOLEAN:
length = 1 << (type & 3);
break;
case ATTR_TYPE_STRING:
length = get_uint16(addr);
addr += 2;
break;
case ATTR_TYPE_BYTEARRAY:
length = get_uint32(addr);
addr += 4;
break;
default:
return NULL;
}
*array_length = length;
return (const int8_t *)addr;
}
char *
attr_container_get_as_string(const attr_container_t *attr_cont, const char *key)
{
unsigned array_length;
return (char *)attr_container_get_as_bytearray(attr_cont, key,
&array_length);
}
const char *
attr_container_get_tag(const attr_container_t *attr_cont)
{
return attr_cont ? attr_cont->buf + sizeof(uint32_t) + sizeof(uint16_t)
: NULL;
}
bool
attr_container_contain_key(const attr_container_t *attr_cont, const char *key)
{
if (!attr_cont || !key || !strlen(key)) {
attr_container_printf(
"Check contain key failed: invalid input arguments.\r\n");
return false;
}
return attr_container_find_attr(attr_cont, key) ? true : false;
}
unsigned int
attr_container_get_serialize_length(const attr_container_t *attr_cont)
{
const char *p;
if (!attr_cont) {
attr_container_printf("Get container serialize length failed: invalid "
"input arguments.\r\n");
return 0;
}
p = attr_cont->buf;
return sizeof(uint16_t) + get_uint32(p);
}
bool
attr_container_serialize(char *buf, const attr_container_t *attr_cont)
{
const char *p;
uint16_t flags;
uint32_t length;
if (!buf || !attr_cont) {
attr_container_printf(
"Container serialize failed: invalid input arguments.\r\n");
return false;
}
p = attr_cont->buf;
length = sizeof(uint16_t) + get_uint32(p);
bh_memcpy_s(buf, length, attr_cont, length);
/* Set readonly */
flags = get_uint16((const char *)attr_cont);
set_uint16(buf, flags | (1 << ATTR_CONT_READONLY_SHIFT));
return true;
}
bool
attr_container_is_constant(const attr_container_t *attr_cont)
{
uint16_t flags;
if (!attr_cont) {
attr_container_printf(
"Container check const: invalid input arguments.\r\n");
return false;
}
flags = get_uint16((const char *)attr_cont);
return (flags & (1 << ATTR_CONT_READONLY_SHIFT)) ? true : false;
}
void
attr_container_dump(const attr_container_t *attr_cont)
{
uint32_t total_length;
uint16_t attr_num, i, type;
const char *p, *tag, *key;
jvalue value;
if (!attr_cont)
return;
tag = attr_container_get_tag(attr_cont);
if (!tag)
return;
attr_container_printf("Attribute container dump:\n");
attr_container_printf("Tag: %s\n", tag);
p = attr_container_get_attr_begin(attr_cont, &total_length, &attr_num);
if (!p)
return;
attr_container_printf("Attribute list:\n");
for (i = 0; i < attr_num; i++) {
key = p + 2;
/* Skip key len and key */
p += 2 + get_uint16(p);
type = *p++;
attr_container_printf(" key: %s", key);
switch (type) {
case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
bh_memcpy_s(&value.i8, 1, p, 1);
attr_container_printf(", type: byte, value: 0x%x\n",
value.i8 & 0xFF);
p++;
break;
case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
bh_memcpy_s(&value.i16, sizeof(int16_t), p, sizeof(int16_t));
attr_container_printf(", type: short, value: 0x%x\n",
value.i16 & 0xFFFF);
p += 2;
break;
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
bh_memcpy_s(&value.i32, sizeof(int32_t), p, sizeof(int32_t));
attr_container_printf(", type: int, value: 0x%x\n", value.i32);
p += 4;
break;
case ATTR_TYPE_INT64:
bh_memcpy_s(&value.i64, sizeof(int64_t), p, sizeof(int64_t));
attr_container_printf(", type: int64, value: 0x%llx\n",
(long long unsigned int)(value.i64));
p += 8;
break;
case ATTR_TYPE_UINT8:
bh_memcpy_s(&value.u8, 1, p, 1);
attr_container_printf(", type: uint8, value: 0x%x\n", value.u8);
p++;
break;
case ATTR_TYPE_UINT16:
bh_memcpy_s(&value.u16, sizeof(uint16_t), p, sizeof(uint16_t));
attr_container_printf(", type: uint16, value: 0x%x\n",
value.u16);
p += 2;
break;
case ATTR_TYPE_UINT32:
bh_memcpy_s(&value.u32, sizeof(uint32_t), p, sizeof(uint32_t));
attr_container_printf(", type: uint32, value: 0x%x\n",
value.u32);
p += 4;
break;
case ATTR_TYPE_UINT64:
bh_memcpy_s(&value.u64, sizeof(uint64_t), p, sizeof(uint64_t));
attr_container_printf(", type: int64, value: 0x%llx\n",
(long long unsigned int)(value.u64));
p += 8;
break;
case ATTR_TYPE_FLOAT:
bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float));
attr_container_printf(", type: float, value: %f\n", value.f);
p += 4;
break;
case ATTR_TYPE_DOUBLE:
bh_memcpy_s(&value.d, sizeof(double), p, sizeof(double));
attr_container_printf(", type: double, value: %f\n", value.d);
p += 8;
break;
case ATTR_TYPE_BOOLEAN:
bh_memcpy_s(&value.z, 1, p, 1);
attr_container_printf(", type: bool, value: 0x%x\n", value.z);
p++;
break;
case ATTR_TYPE_STRING:
attr_container_printf(", type: string, value: %s\n",
p + sizeof(uint16_t));
p += sizeof(uint16_t) + get_uint16(p);
break;
case ATTR_TYPE_BYTEARRAY:
attr_container_printf(", type: byte array, length: %d\n",
get_uint32(p));
p += sizeof(uint32_t) + get_uint32(p);
break;
default:
bh_assert(0);
break;
}
}
attr_container_printf("\n");
}

View File

@ -1,596 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _ATTR_CONTAINER_H_
#define _ATTR_CONTAINER_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Attribute type */
enum {
ATTR_TYPE_BEGIN = 0,
ATTR_TYPE_BYTE = ATTR_TYPE_BEGIN,
ATTR_TYPE_INT8 = ATTR_TYPE_BYTE,
ATTR_TYPE_SHORT,
ATTR_TYPE_INT16 = ATTR_TYPE_SHORT,
ATTR_TYPE_INT,
ATTR_TYPE_INT32 = ATTR_TYPE_INT,
ATTR_TYPE_INT64,
ATTR_TYPE_UINT8,
ATTR_TYPE_UINT16,
ATTR_TYPE_UINT32,
ATTR_TYPE_UINT64,
/**
* Why ATTR_TYPE_FLOAT = 10?
* We determine the number of bytes that should be copied through 1<<(type &
* 3). ATTR_TYPE_BYTE = 0, so the number of bytes is 1 << 0 = 1.
* ATTR_TYPE_UINT64 = 7, so the number of bytes is 1 << 3 = 8.
* Since the float type takes up 4 bytes, ATTR_TYPE_FLOAT should be 10.
* Calculation: (1 << (10&3)) = (1 << 2) = 4
*/
ATTR_TYPE_FLOAT = 10,
ATTR_TYPE_DOUBLE,
ATTR_TYPE_BOOLEAN,
ATTR_TYPE_STRING,
ATTR_TYPE_BYTEARRAY,
ATTR_TYPE_END = ATTR_TYPE_BYTEARRAY
};
#define ATTR_CONT_READONLY_SHIFT 2
typedef struct attr_container {
/* container flag:
* bit0, bit1 denote the implemenation algorithm, 00: buffer, 01: link list
* bit2 denotes the readonly flag: 1 is readonly and attr cannot be set
*/
char flags[2];
/**
* Buffer format
* for buffer implementation:
* buf length (4 bytes)
* tag length (2 bytes)
* tag
* attr num (2bytes)
* attr[0..n-1]:
* attr key length (2 bytes)
* attr type (1byte)
* attr value (length depends on attr type)
*/
char buf[1];
} attr_container_t;
/**
* Create attribute container
*
* @param tag tag of current attribute container
*
* @return the created attribute container, NULL if failed
*/
attr_container_t *
attr_container_create(const char *tag);
/**
* Destroy attribute container
*
* @param attr_cont the attribute container to destroy
*/
void
attr_container_destroy(const attr_container_t *attr_cont);
/**
* Set short attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
short value);
/**
* Set int16 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int16(attr_container_t **p_attr_cont, const char *key,
int16_t value);
/**
* Set int attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
int value);
/**
* Set int32 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int32(attr_container_t **p_attr_cont, const char *key,
int32_t value);
/**
* Set uint32 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key,
uint32_t value);
/**
* Set int64 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
int64_t value);
/**
* Set uint64 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key,
uint64_t value);
/**
* Set byte attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
int8_t value);
/**
* Set int8 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int8(attr_container_t **p_attr_cont, const char *key,
int8_t value);
/**
* Set uint8 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key,
uint8_t value);
/**
* Set uint16 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
uint16_t value);
/**
* Set float attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_float(attr_container_t **p_attr_cont, const char *key,
float value);
/**
* Set double attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_double(attr_container_t **p_attr_cont, const char *key,
double value);
/**
* Set bool attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_bool(attr_container_t **p_attr_cont, const char *key,
bool value);
/**
* Set string attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_string(attr_container_t **p_attr_cont, const char *key,
const char *value);
/**
* Set bytearray attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the bytearray buffer
* @param length the bytearray length
*
* @return true if success, false otherwise
*/
bool
attr_container_set_bytearray(attr_container_t **p_attr_cont, const char *key,
const int8_t *value, unsigned length);
/**
* Get tag of current attribute container
*
* @param attr_cont the attribute container
*
* @return tag of current attribute container
*/
const char *
attr_container_get_tag(const attr_container_t *attr_cont);
/**
* Get attribute number of current attribute container
*
* @param attr_cont the attribute container
*
* @return attribute number of current attribute container
*/
uint16_t
attr_container_get_attr_num(const attr_container_t *attr_cont);
/**
* Whether the attribute container contains an attribute key.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return true if key is contained in message, false otherwise
*/
bool
attr_container_contain_key(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as short value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the short value of the attribute, 0 if key isn't found
*/
short
attr_container_get_as_short(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int16 value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the short value of the attribute, 0 if key isn't found
*/
int16_t
attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the int value of the attribute, 0 if key isn't found
*/
int
attr_container_get_as_int(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int32 value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the int value of the attribute, 0 if key isn't found
*/
int32_t
attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint32 value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the unsigned int value of the attribute, 0 if key isn't found
*/
uint32_t
attr_container_get_as_uint32(const attr_container_t *attr_cont,
const char *key);
/**
* Get attribute from attribute container and return it as int64 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the long value of the attribute, 0 if key isn't found
*/
int64_t
attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint64 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the unsigned long value of the attribute, 0 if key isn't found
*/
uint64_t
attr_container_get_as_uint64(const attr_container_t *attr_cont,
const char *key);
/**
* Get attribute from attribute container and return it as byte value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the byte value of the attribute, 0 if key isn't found
*/
int8_t
attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int8 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the byte value of the attribute, 0 if key isn't found
*/
int8_t
attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint8 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the uint8 value of the attribute, 0 if key isn't found
*/
uint8_t
attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint16 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the char value of the attribute, 0 if key isn't found
*/
uint16_t
attr_container_get_as_uint16(const attr_container_t *attr_cont,
const char *key);
/**
* Get attribute from attribute container and return it as float value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the float value of the attribute, 0 if key isn't found
*/
float
attr_container_get_as_float(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as double value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the double value of the attribute, 0 if key isn't found
*/
double
attr_container_get_as_double(const attr_container_t *attr_cont,
const char *key);
/**
* Get attribute from attribute container and return it as bool value,
* return false if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the bool value of the attribute, 0 if key isn't found
*/
bool
attr_container_get_as_bool(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as string value,
* return NULL if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the string value of the attribute, NULL if key isn't found
*/
char *
attr_container_get_as_string(const attr_container_t *attr_cont,
const char *key);
/**
* Get attribute from attribute container and return it as bytearray value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the bytearray value of the attribute, NULL if key isn't found
*/
const int8_t *
attr_container_get_as_bytearray(const attr_container_t *attr_cont,
const char *key, unsigned *array_length);
/**
* Get the buffer size of attribute container
*
* @param attr_cont the attribute container
*
* @return the buffer size of attribute container
*/
unsigned
attr_container_get_serialize_length(const attr_container_t *attr_cont);
/**
* Serialize attribute container to a buffer
*
* @param buf the buffer to receive the serialized data
* @param attr_cont the attribute container to be serialized
*
* @return true if success, false otherwise
*/
bool
attr_container_serialize(char *buf, const attr_container_t *attr_cont);
/**
* Whether the attribute container is const, or set attribute isn't supported
*
* @param attr_cont the attribute container
*
* @return true if const, false otherwise
*/
bool
attr_container_is_constant(const attr_container_t *attr_cont);
void
attr_container_dump(const attr_container_t *attr_cont);
#ifndef attr_container_malloc
#define attr_container_malloc WA_MALLOC
#endif
#ifndef attr_container_free
#define attr_container_free WA_FREE
#endif
#ifndef attr_container_printf
#define attr_container_printf printf
#endif
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* end of _ATTR_CONTAINER_H_ */

View File

@ -1,155 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _SHARED_UTILS_H_
#define _SHARED_UTILS_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FMT_ATTR_CONTAINER 99
#define FMT_APP_RAW_BINARY 98
/* the request structure */
typedef struct request {
// message id
uint32 mid;
// url of the request
char *url;
// action of the request, can be PUT/GET/POST/DELETE
int action;
// payload format, currently only support attr_container_t type
int fmt;
// payload of the request, currently only support attr_container_t type
void *payload;
// length in bytes of the payload
int payload_len;
// sender of the request
unsigned long sender;
} request_t;
/* the response structure */
typedef struct response {
// message id
uint32 mid;
// status of the response
int status;
// payload format
int fmt;
// payload of the response,
void *payload;
// length in bytes of the payload
int payload_len;
// receiver of the response
unsigned long reciever;
} response_t;
int
check_url_start(const char *url, int url_len, const char *leading_str);
bool
match_url(char *pattern, char *matched);
char *
find_key_value(char *buffer, int buffer_len, char *key, char *value,
int value_len, char delimiter);
request_t *
clone_request(request_t *request);
void
request_cleaner(request_t *request);
response_t *
clone_response(response_t *response);
void
response_cleaner(response_t *response);
/**
* @brief Set fields of response.
*
* @param response pointer of the response to be set
* @param status status of response
* @param fmt format of the response payload
* @param payload payload of the response
* @param payload_len length in bytes of the response payload
*
* @return pointer to the response
*
* @warning the response pointer MUST NOT be NULL
*/
response_t *
set_response(response_t *response, int status, int fmt, const char *payload,
int payload_len);
/**
* @brief Make a response for a request.
*
* @param request pointer of the request
* @param response pointer of the response to be made
*
* @return pointer to the response
*
* @warning the request and response pointers MUST NOT be NULL
*/
response_t *
make_response_for_request(request_t *request, response_t *response);
/**
* @brief Initialize a request.
*
* @param request pointer of the request to be initialized
* @param url url of the request
* @param action action of the request
* @param fmt format of the request payload
* @param payload payload of the request
* @param payload_len length in bytes of the request payload
*
* @return pointer to the request
*
* @warning the request pointer MUST NOT be NULL
*/
request_t *
init_request(request_t *request, char *url, int action, int fmt, void *payload,
int payload_len);
char *
pack_request(request_t *request, int *size);
request_t *
unpack_request(char *packet, int size, request_t *request);
char *
pack_response(response_t *response, int *size);
response_t *
unpack_response(char *packet, int size, response_t *response);
void
free_req_resp_packet(char *packet);
char *
wa_strdup(const char *str);
#ifdef __cplusplus
}
#endif
#endif /* end of _SHARED_UTILS_H_ */

View File

@ -1,101 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H
#define WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
/* Object native function IDs */
enum {
OBJ_FUNC_ID_DEL,
OBJ_FUNC_ID_DEL_ASYNC,
OBJ_FUNC_ID_CLEAN,
OBJ_FUNC_ID_SET_EVT_CB,
OBJ_FUNC_ID_ALIGN,
/* Number of functions */
_OBJ_FUNC_ID_NUM,
};
/* Button native function IDs */
enum {
BTN_FUNC_ID_CREATE,
BTN_FUNC_ID_SET_TOGGLE,
BTN_FUNC_ID_SET_STATE,
BTN_FUNC_ID_TOGGLE,
BTN_FUNC_ID_SET_INK_IN_TIME,
BTN_FUNC_ID_SET_INK_WAIT_TIME,
BTN_FUNC_ID_SET_INK_OUT_TIME,
BTN_FUNC_ID_GET_STATE,
BTN_FUNC_ID_GET_TOGGLE,
BTN_FUNC_ID_GET_INK_IN_TIME,
BTN_FUNC_ID_GET_INK_WAIT_TIME,
BTN_FUNC_ID_GET_INK_OUT_TIME,
/* Number of functions */
_BTN_FUNC_ID_NUM,
};
/* Check box native function IDs */
enum {
CB_FUNC_ID_CREATE,
CB_FUNC_ID_SET_TEXT,
CB_FUNC_ID_SET_STATIC_TEXT,
CB_FUNC_ID_GET_TEXT,
CB_FUNC_ID_GET_TEXT_LENGTH,
/* Number of functions */
_CB_FUNC_ID_NUM,
};
/* List native function IDs */
enum {
LIST_FUNC_ID_CREATE,
LIST_FUNC_ID_ADD_BTN,
/* Number of functions */
_LIST_FUNC_ID_NUM,
};
/* Label native function IDs */
enum {
LABEL_FUNC_ID_CREATE,
LABEL_FUNC_ID_SET_TEXT,
LABEL_FUNC_ID_SET_ARRAY_TEXT,
LABEL_FUNC_ID_SET_STATIC_TEXT,
LABEL_FUNC_ID_SET_LONG_MODE,
LABEL_FUNC_ID_SET_ALIGN,
LABEL_FUNC_ID_SET_RECOLOR,
LABEL_FUNC_ID_SET_BODY_DRAW,
LABEL_FUNC_ID_SET_ANIM_SPEED,
LABEL_FUNC_ID_SET_TEXT_SEL_START,
LABEL_FUNC_ID_SET_TEXT_SEL_END,
LABEL_FUNC_ID_GET_TEXT,
LABEL_FUNC_ID_GET_TEXT_LENGTH,
LABEL_FUNC_ID_GET_LONG_MODE,
LABEL_FUNC_ID_GET_ALIGN,
LABEL_FUNC_ID_GET_RECOLOR,
LABEL_FUNC_ID_GET_BODY_DRAW,
LABEL_FUNC_ID_GET_ANIM_SPEED,
LABEL_FUNC_ID_GET_LETTER_POS,
LABEL_FUNC_ID_GET_TEXT_SEL_START,
LABEL_FUNC_ID_GET_TEXT_SEL_END,
LABEL_FUNC_ID_INS_TEXT,
LABEL_FUNC_ID_CUT_TEXT,
/* Number of functions */
_LABEL_FUNC_ID_NUM,
};
#ifdef __cplusplus
}
#endif
#endif /* WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H */

View File

@ -1,15 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (NATIVE_INTERFACE_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${NATIVE_INTERFACE_DIR})
file (GLOB_RECURSE source_all ${NATIVE_INTERFACE_DIR}/*.c)
set (NATIVE_INTERFACE_SOURCE ${source_all})
set (WASM_APP_BI_INC_DIR "${NATIVE_INTERFACE_DIR}/bi-inc")
LIST (APPEND RUNTIME_LIB_HEADER_LIST "${NATIVE_INTERFACE_DIR}/native_interface.h")

View File

@ -1,13 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _NATIVE_INTERFACE_H_
#define _NATIVE_INTERFACE_H_
/* Note: the bh_plaform.h is the only head file separately
implemented by both [app] and [native] worlds */
#include "bh_platform.h"
#endif /* end of _NATIVE_INTERFACE_H */

View File

@ -1,493 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "bi-inc/shared_utils.h"
/* Serialization of request and response message
*
* Choices:
* We considered a few options:
* 1. coap
* 2. flatbuffer
* 3. cbor
* 4. attr-containers of our own
* 5. customized serialization for request/response
*
* Now we choose the #5 mainly because we need to quickly get the URL for
* dispatching and sometimes we want to change the URL in the original packet.
* the request format: fixed part: version: (1 byte), code (1 byte), fmt(2
* byte), mid (4 bytes), sender_id(4 bytes), url_len(2 bytes),
* payload_len(4bytes) dynamic part: url (bytes in url_len), payload
*
* response format:
* fixed part: (1 byte), code (1 byte), fmt(2 byte), mid (4 bytes), sender_id(4
* bytes), payload_len(4bytes) dynamic part: payload
*/
#define REQUES_PACKET_VER 1
#define REQUEST_PACKET_FIX_PART_LEN 18
#define REQUEST_PACKET_URL_OFFSET REQUEST_PACKET_FIX_PART_LEN
#define REQUEST_PACKET_URL_LEN \
*((uint16 *)((char *)buffer + 12)) /* to ensure little endian */
#define REQUEST_PACKET_PAYLOAD_LEN \
*((uint32 *)((char *)buffer + 14)) /* to ensure little endian */
#define REQUEST_PACKET_URL(buffer) ((char *)buffer + REQUEST_PACKET_URL_OFFSET)
#define REQUEST_PACKET_PAYLOAD(buffer) \
((char *)buffer + REQUEST_PACKET_URL_OFFSET \
+ REQUEST_PACKET_URL_LEN(buffer))
#define RESPONSE_PACKET_FIX_PART_LEN 16
char *
pack_request(request_t *request, int *size)
{
int url_len = strlen(request->url) + 1;
int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len;
uint16 u16;
uint32 u32;
char *packet;
if ((packet = (char *)WA_MALLOC(len)) == NULL)
return NULL;
/* TODO: ensure little endian for words and dwords */
*packet = REQUES_PACKET_VER;
*((uint8 *)(packet + 1)) = request->action;
u16 = htons(request->fmt);
memcpy(packet + 2, &u16, 2);
u32 = htonl(request->mid);
memcpy(packet + 4, &u32, 4);
u32 = htonl(request->sender);
memcpy(packet + 8, &u32, 4);
u16 = htons(url_len);
memcpy(packet + 12, &u16, 2);
u32 = htonl(request->payload_len);
memcpy(packet + 14, &u32, 4);
strcpy(packet + REQUEST_PACKET_URL_OFFSET, request->url);
memcpy(packet + REQUEST_PACKET_URL_OFFSET + url_len, request->payload,
request->payload_len);
*size = len;
return packet;
}
void
free_req_resp_packet(char *packet)
{
WA_FREE(packet);
}
request_t *
unpack_request(char *packet, int size, request_t *request)
{
uint16 url_len, u16;
uint32 payload_len, u32;
if (*packet != REQUES_PACKET_VER) {
return NULL;
}
if (size < REQUEST_PACKET_FIX_PART_LEN) {
return NULL;
}
memcpy(&u16, packet + 12, 2);
url_len = ntohs(u16);
memcpy(&u32, packet + 14, 4);
payload_len = ntohl(u32);
if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
return NULL;
}
if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) {
return NULL;
}
request->action = *((uint8 *)(packet + 1));
memcpy(&u16, packet + 2, 2);
request->fmt = ntohs(u16);
memcpy(&u32, packet + 4, 4);
request->mid = ntohl(u32);
memcpy(&u32, packet + 8, 4);
request->sender = ntohl(u32);
request->payload_len = payload_len;
request->url = REQUEST_PACKET_URL(packet);
if (payload_len > 0)
request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len;
else
request->payload = NULL;
return request;
}
char *
pack_response(response_t *response, int *size)
{
int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len;
uint16 u16;
uint32 u32;
char *packet;
if ((packet = (char *)WA_MALLOC(len)) == NULL)
return NULL;
/* TODO: ensure little endian for words and dwords */
*packet = REQUES_PACKET_VER;
*((uint8 *)(packet + 1)) = response->status;
u16 = htons(response->fmt);
memcpy(packet + 2, &u16, 2);
u32 = htonl(response->mid);
memcpy(packet + 4, &u32, 4);
u32 = htonl(response->reciever);
memcpy(packet + 8, &u32, 4);
u32 = htonl(response->payload_len);
memcpy(packet + 12, &u32, 4);
memcpy(packet + RESPONSE_PACKET_FIX_PART_LEN, response->payload,
response->payload_len);
*size = len;
return packet;
}
response_t *
unpack_response(char *packet, int size, response_t *response)
{
uint16 u16;
uint32 payload_len, u32;
if (*packet != REQUES_PACKET_VER)
return NULL;
if (size < RESPONSE_PACKET_FIX_PART_LEN)
return NULL;
memcpy(&u32, packet + 12, 4);
payload_len = ntohl(u32);
if (size != (RESPONSE_PACKET_FIX_PART_LEN + payload_len))
return NULL;
response->status = *((uint8 *)(packet + 1));
memcpy(&u16, packet + 2, 2);
response->fmt = ntohs(u16);
memcpy(&u32, packet + 4, 4);
response->mid = ntohl(u32);
memcpy(&u32, packet + 8, 4);
response->reciever = ntohl(u32);
response->payload_len = payload_len;
if (payload_len > 0)
response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN;
else
response->payload = NULL;
return response;
}
request_t *
clone_request(request_t *request)
{
/* deep clone */
request_t *req = (request_t *)WA_MALLOC(sizeof(request_t));
if (req == NULL)
return NULL;
memset(req, 0, sizeof(*req));
req->action = request->action;
req->fmt = request->fmt;
req->url = wa_strdup(request->url);
req->sender = request->sender;
req->mid = request->mid;
if (req->url == NULL)
goto fail;
req->payload_len = request->payload_len;
if (request->payload_len) {
req->payload = (char *)WA_MALLOC(request->payload_len);
if (!req->payload)
goto fail;
memcpy(req->payload, request->payload, request->payload_len);
}
else {
/* when payload_len is 0, the payload may be used for
carrying some handle or integer */
req->payload = request->payload;
}
return req;
fail:
request_cleaner(req);
return NULL;
}
void
request_cleaner(request_t *request)
{
if (request->url != NULL)
WA_FREE(request->url);
if (request->payload != NULL && request->payload_len > 0)
WA_FREE(request->payload);
WA_FREE(request);
}
void
response_cleaner(response_t *response)
{
if (response->payload != NULL && response->payload_len > 0)
WA_FREE(response->payload);
WA_FREE(response);
}
response_t *
clone_response(response_t *response)
{
response_t *clone = (response_t *)WA_MALLOC(sizeof(response_t));
if (clone == NULL)
return NULL;
memset(clone, 0, sizeof(*clone));
clone->fmt = response->fmt;
clone->mid = response->mid;
clone->status = response->status;
clone->reciever = response->reciever;
clone->payload_len = response->payload_len;
if (clone->payload_len) {
clone->payload = (char *)WA_MALLOC(response->payload_len);
if (!clone->payload)
goto fail;
memcpy(clone->payload, response->payload, response->payload_len);
}
else {
/* when payload_len is 0, the payload may be used for
carrying some handle or integer */
clone->payload = response->payload;
}
return clone;
fail:
response_cleaner(clone);
return NULL;
}
response_t *
set_response(response_t *response, int status, int fmt, const char *payload,
int payload_len)
{
response->payload = (void *)payload;
response->payload_len = payload_len;
response->status = status;
response->fmt = fmt;
return response;
}
response_t *
make_response_for_request(request_t *request, response_t *response)
{
response->mid = request->mid;
response->reciever = request->sender;
return response;
}
static unsigned int mid = 0;
request_t *
init_request(request_t *request, char *url, int action, int fmt, void *payload,
int payload_len)
{
request->url = url;
request->action = action;
request->fmt = fmt;
request->payload = payload;
request->payload_len = payload_len;
request->mid = ++mid;
return request;
}
/*
check if the "url" is starting with "leading_str"
return: 0 - not match; >0 - the offset of matched url, include any "/" at the
end notes:
1. it ensures the leading_str "/abc" can pass "/abc/cde" and "/abc/, but fail
"/ab" and "/abcd". leading_str "/abc/" can pass "/abc"
2. it omit the '/' at the first char
3. it ensure the leading_str "/abc" can pass "/abc?cde
*/
int
check_url_start(const char *url, int url_len, const char *leading_str)
{
int offset = 0;
if (*leading_str == '/')
leading_str++;
if (url_len > 0 && *url == '/') {
url_len--;
url++;
offset++;
}
int len = strlen(leading_str);
if (len == 0)
return 0;
/* ensure leading_str not end with "/" */
if (leading_str[len - 1] == '/') {
len--;
if (len == 0)
return 0;
}
/* equal length */
if (url_len == len) {
if (memcmp(url, leading_str, url_len) == 0) {
return (offset + len);
}
else {
return 0;
}
}
if (url_len < len)
return 0;
else if (memcmp(url, leading_str, len) != 0)
return 0;
else if (url[len] != '/' && url[len] != '?')
return 0;
else
return (offset + len + 1);
}
// * @pattern:
// * sample 1: /abcd, match /abcd only
// * sample 2: /abcd/ match match "/abcd" and "/abcd/*"
// * sample 3: /abcd*, match any url started with "/abcd"
// * sample 4: /abcd/*, exclude "/abcd"
bool
match_url(char *pattern, char *matched)
{
if (*pattern == '/')
pattern++;
if (*matched == '/')
matched++;
int matched_len = strlen(matched);
if (matched_len == 0)
return false;
if (matched[matched_len - 1] == '/') {
matched_len--;
if (matched_len == 0)
return false;
}
int len = strlen(pattern);
if (len == 0)
return false;
if (pattern[len - 1] == '/') {
len--;
if (strncmp(pattern, matched, len) != 0)
return false;
if (len == matched_len)
return true;
if (matched_len > len && matched[len] == '/')
return true;
return false;
}
else if (pattern[len - 1] == '*') {
if (pattern[len - 2] == '/') {
if (strncmp(pattern, matched, len - 1) == 0)
return true;
else
return false;
}
else {
return (strncmp(pattern, matched, len - 1) == 0);
}
}
else {
return (strcmp(pattern, matched) == 0);
}
}
/*
* get the value of the key from following format buffer:
* key1=value1;key2=value2;key3=value3
*/
char *
find_key_value(char *buffer, int buffer_len, char *key, char *value,
int value_len, char delimiter)
{
char *p = buffer;
int remaining = buffer_len;
int key_len = strlen(key);
while (*p != 0 && remaining > 0) {
while (*p == ' ' || *p == delimiter) {
p++;
remaining--;
}
if (remaining <= key_len)
return NULL;
/* find the key */
if (0 == strncmp(p, key, key_len) && p[key_len] == '=') {
p += (key_len + 1);
remaining -= (key_len + 1);
char *v = value;
memset(value, 0, value_len);
value_len--; /* ensure last char is 0 */
while (*p != delimiter && remaining > 0 && value_len > 0) {
*v++ = *p++;
remaining--;
value_len--;
}
return value;
}
/* goto next key */
while (*p != delimiter && remaining > 0) {
p++;
remaining--;
}
}
return NULL;
}

View File

@ -1,38 +0,0 @@
#include "lib_export.h"
#ifdef APP_FRAMEWORK_SENSOR
#include "sensor_native_api.h"
#endif
#ifdef APP_FRAMEWORK_CONNECTION
#include "connection_native_api.h"
#endif
#ifdef APP_FRAMEWORK_WGL
#include "gui_native_api.h"
#endif
/* More header file here */
static NativeSymbol extended_native_symbol_defs[] = {
#ifdef APP_FRAMEWORK_SENSOR
#include "runtime_sensor.inl"
#endif
#ifdef APP_FRAMEWORK_CONNECTION
#include "connection.inl"
#endif
#ifdef APP_FRAMEWORK_WGL
#include "wamr_gui.inl"
#endif
/* More inl file here */
};
int
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis)
{
*p_ext_lib_apis = extended_native_symbol_defs;
return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol);
}

View File

@ -1,93 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
add_definitions (-DWASM_ENABLE_APP_FRAMEWORK=1)
set (APP_FRAMEWORK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR})
if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE )
LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${CMAKE_CURRENT_LIST_DIR}/app_ext_lib_export.c)
endif()
# app-native-shared and base are required
include (${APP_FRAMEWORK_ROOT_DIR}/app-native-shared/native_interface.cmake)
LIST (APPEND WASM_APP_SOURCE_ALL ${NATIVE_INTERFACE_SOURCE})
MACRO(SUBDIRLIST result curdir)
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
SET(dirlist "")
FOREACH(child ${children})
IF(IS_DIRECTORY ${curdir}/${child})
LIST(APPEND dirlist ${child})
ENDIF()
ENDFOREACH()
SET(${result} ${dirlist})
ENDMACRO()
function (add_module_native arg)
message ("Add native module ${ARGV0}")
include (${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native/wasm_lib.cmake)
file (GLOB header
${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native/*.h
${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native/*.inl
)
LIST (APPEND WASM_APP_LIBS_DIR ${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native)
set (WASM_APP_LIBS_DIR ${WASM_APP_LIBS_DIR} PARENT_SCOPE)
LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
set (RUNTIME_LIB_HEADER_LIST ${RUNTIME_LIB_HEADER_LIST} PARENT_SCOPE)
LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_CURRENT_SOURCE})
set (WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_SOURCE_ALL} PARENT_SCOPE)
endfunction ()
function (add_module_app arg)
message ("Add app module ${ARGV0}")
include (${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/app/wasm_app.cmake)
LIST (APPEND WASM_APP_WA_INC_DIR_LIST "${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/app/wa-inc")
set (WASM_APP_WA_INC_DIR_LIST ${WASM_APP_WA_INC_DIR_LIST} PARENT_SCOPE)
LIST (APPEND WASM_APP_NAME ${ARGV0})
set (WASM_APP_NAME ${WASM_APP_NAME} PARENT_SCOPE)
LIST (APPEND WASM_APP_SOURCE_ALL ${WASM_APP_CURRENT_SOURCE})
set (WASM_APP_SOURCE_ALL ${WASM_APP_SOURCE_ALL} PARENT_SCOPE)
endfunction ()
if ("${WAMR_BUILD_APP_LIST}" STREQUAL "WAMR_APP_BUILD_ALL")
# add all modules under this folder
SUBDIRLIST(SUBDIRS ${APP_FRAMEWORK_ROOT_DIR})
FOREACH(subdir ${SUBDIRS})
if ("${subdir}" STREQUAL "app-native-shared")
continue()
endif ()
if ("${subdir}" STREQUAL "template")
continue()
endif ()
if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE )
add_module_native (${subdir})
else ()
add_module_app (${subdir})
endif ()
ENDFOREACH()
else ()
# add each module in the list
FOREACH (dir IN LISTS WAMR_BUILD_APP_LIST)
string(REPLACE "WAMR_APP_BUILD_" "" dir ${dir})
string(TOLOWER ${dir} dir)
if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE )
add_module_native (${dir})
else ()
add_module_app (${dir})
endif ()
ENDFOREACH (dir)
endif()

View File

@ -1,89 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
*
*
*/
static bool
is_little_endian()
{
long i = 0x01020304;
unsigned char *c = (unsigned char *)&i;
return (*c == 0x04) ? true : false;
}
static void
swap32(uint8 *pData)
{
uint8 value = *pData;
*pData = *(pData + 3);
*(pData + 3) = value;
value = *(pData + 1);
*(pData + 1) = *(pData + 2);
*(pData + 2) = value;
}
static void
swap16(uint8 *pData)
{
uint8 value = *pData;
*(pData) = *(pData + 1);
*(pData + 1) = value;
}
uint32
htonl(uint32 value)
{
uint32 ret;
if (is_little_endian()) {
ret = value;
swap32((uint8 *)&ret);
return ret;
}
return value;
}
uint32
ntohl(uint32 value)
{
return htonl(value);
}
uint16
htons(uint16 value)
{
uint16 ret;
if (is_little_endian()) {
ret = value;
swap16((uint8 *)&ret);
return ret;
}
return value;
}
uint16
ntohs(uint16 value)
{
return htons(value);
}
char *
wa_strdup(const char *s)
{
char *s1 = NULL;
if (s && (s1 = WA_MALLOC(strlen(s) + 1)))
memcpy(s1, s, strlen(s) + 1);
return s1;
}

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_
#define DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_
#include <stdbool.h>
typedef unsigned char uint8;
typedef char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
#ifndef NULL
#define NULL ((void *)0)
#endif
#ifndef __cplusplus
#define true 1
#define false 0
#define inline __inline
#endif
// all wasm-app<->native shared source files should use WA_MALLOC/WA_FREE.
// they will be mapped to different implementations in each side
#ifndef WA_MALLOC
#define WA_MALLOC malloc
#endif
#ifndef WA_FREE
#define WA_FREE free
#endif
uint32
htonl(uint32 value);
uint32
ntohl(uint32 value);
uint16
htons(uint16 value);
uint16
ntohs(uint16 value);
// We are not worried for the WASM world since the sandbox will catch it.
#define bh_memcpy_s(dst, dst_len, src, src_len) memcpy(dst, src, src_len)
#ifdef NDEBUG
#define bh_assert(v) (void)0
#else
#define bh_assert(v) \
do { \
if (!(v)) { \
int _count; \
printf("ASSERTION FAILED: %s, at %s, line %d", #v, __FILE__, \
__LINE__); \
_count = printf("\n"); \
printf("%d\n", _count / (_count - 1)); \
} \
} while (0)
#endif
#endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */

View File

@ -1,31 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _REQ_RESP_API_H_
#define _REQ_RESP_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
bool
wasm_response_send(const char *buf, int size);
void
wasm_register_resource(const char *url);
void
wasm_post_request(const char *buf, int size);
void
wasm_sub_event(const char *url);
#ifdef __cplusplus
}
#endif
#endif /* end of _REQ_RESP_API_H_ */

View File

@ -1,365 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bi-inc/attr_container.h"
#include "wa-inc/request.h"
#include "wa-inc/timer_wasm_app.h"
#include "bi-inc/shared_utils.h"
#include "wasm_app.h"
#include "req_resp_api.h"
#include "timer_api.h"
#define TRANSACTION_TIMEOUT_MS 5000
typedef enum { Reg_Event, Reg_Request } reg_type_t;
typedef struct _res_register {
struct _res_register *next;
const char *url;
reg_type_t reg_type;
void (*request_handler)(request_t *);
} res_register_t;
typedef struct transaction {
struct transaction *next;
int mid;
unsigned int time; /* start time */
response_handler_f handler;
void *user_data;
} transaction_t;
static res_register_t *g_resources = NULL;
static transaction_t *g_transactions = NULL;
static user_timer_t g_trans_timer = NULL;
static transaction_t *
transaction_find(int mid)
{
transaction_t *t = g_transactions;
while (t) {
if (t->mid == mid)
return t;
t = t->next;
}
return NULL;
}
/*
* new transaction is added to the tail of the list, so the list
* is sorted by expiry time naturally.
*/
static void
transaction_add(transaction_t *trans)
{
transaction_t *t;
if (g_transactions == NULL) {
g_transactions = trans;
return;
}
t = g_transactions;
while (t) {
if (t->next == NULL) {
t->next = trans;
return;
}
}
}
static void
transaction_remove(transaction_t *trans)
{
transaction_t *prev = NULL, *current = g_transactions;
while (current) {
if (current == trans) {
if (prev == NULL) {
g_transactions = current->next;
free(current);
return;
}
prev->next = current->next;
free(current);
return;
}
prev = current;
current = current->next;
}
}
static bool
is_event_type(request_t *req)
{
return req->action == COAP_EVENT;
}
static bool
register_url_handler(const char *url, request_handler_f request_handler,
reg_type_t reg_type)
{
res_register_t *r = g_resources;
while (r) {
if (reg_type == r->reg_type && strcmp(r->url, url) == 0) {
r->request_handler = request_handler;
return true;
}
r = r->next;
}
r = (res_register_t *)malloc(sizeof(res_register_t));
if (r == NULL)
return false;
memset(r, 0, sizeof(*r));
r->url = strdup(url);
if (!r->url) {
free(r);
return false;
}
r->request_handler = request_handler;
r->reg_type = reg_type;
r->next = g_resources;
g_resources = r;
// tell app mgr to route this url to me
if (reg_type == Reg_Request)
wasm_register_resource(url);
else
wasm_sub_event(url);
return true;
}
bool
api_register_resource_handler(const char *url,
request_handler_f request_handler)
{
return register_url_handler(url, request_handler, Reg_Request);
}
static void
transaction_timeout_handler(user_timer_t timer)
{
transaction_t *cur, *expired = NULL;
unsigned int elpased_ms, now = wasm_get_sys_tick_ms();
/*
* Since he transaction list is sorted by expiry time naturally,
* we can easily get all expired transactions.
* */
cur = g_transactions;
while (cur) {
if (now < cur->time)
elpased_ms = now + (0xFFFFFFFF - cur->time) + 1;
else
elpased_ms = now - cur->time;
if (elpased_ms >= TRANSACTION_TIMEOUT_MS) {
g_transactions = cur->next;
cur->next = expired;
expired = cur;
cur = g_transactions;
}
else {
break;
}
}
/* call each transaction's handler with response set to NULL */
cur = expired;
while (cur) {
transaction_t *tmp = cur;
cur->handler(NULL, cur->user_data);
cur = cur->next;
free(tmp);
}
/*
* If the transaction list is not empty, restart the timer according
* to the first transaction. Otherwise, stop the timer.
*/
if (g_transactions != NULL) {
unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
if (now < g_transactions->time) {
elpased_ms = now + (0xFFFFFFFF - g_transactions->time) + 1;
}
else {
elpased_ms = now - g_transactions->time;
}
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
api_timer_restart(g_trans_timer, ms_to_expiry);
}
else {
api_timer_cancel(g_trans_timer);
g_trans_timer = NULL;
}
}
void
api_send_request(request_t *request, response_handler_f response_handler,
void *user_data)
{
int size;
char *buffer;
transaction_t *trans;
if ((trans = (transaction_t *)malloc(sizeof(transaction_t))) == NULL) {
printf(
"send request: allocate memory for request transaction failed!\n");
return;
}
memset(trans, 0, sizeof(transaction_t));
trans->handler = response_handler;
trans->mid = request->mid;
trans->time = wasm_get_sys_tick_ms();
trans->user_data = user_data;
if ((buffer = pack_request(request, &size)) == NULL) {
printf("send request: pack request failed!\n");
free(trans);
return;
}
transaction_add(trans);
/* if the trans is the 1st one, start the timer */
if (trans == g_transactions) {
/* assert(g_trans_timer == NULL); */
if (g_trans_timer == NULL) {
g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS, false,
true, transaction_timeout_handler);
}
}
wasm_post_request(buffer, size);
free_req_resp_packet(buffer);
}
/*
*
* APIs for the native layers to callback for request/response arrived to this
* app
*
*/
void
on_response(char *buffer, int size)
{
response_t response[1];
transaction_t *trans;
if (NULL == unpack_response(buffer, size, response)) {
printf("unpack response failed\n");
return;
}
if ((trans = transaction_find(response->mid)) == NULL) {
printf("cannot find the transaction\n");
return;
}
/*
* When the 1st transaction get response:
* 1. If the 2nd trans exist, restart the timer according to its expiry
* time;
* 2. Otherwise, stop the timer since there is no more transactions;
*/
if (trans == g_transactions) {
if (trans->next != NULL) {
unsigned int elpased_ms, ms_to_expiry, now = wasm_get_sys_tick_ms();
if (now < trans->next->time) {
elpased_ms = now + (0xFFFFFFFF - trans->next->time) + 1;
}
else {
elpased_ms = now - trans->next->time;
}
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
api_timer_restart(g_trans_timer, ms_to_expiry);
}
else {
api_timer_cancel(g_trans_timer);
g_trans_timer = NULL;
}
}
trans->handler(response, trans->user_data);
transaction_remove(trans);
}
void
on_request(char *buffer, int size)
{
request_t request[1];
bool is_event;
res_register_t *r = g_resources;
if (NULL == unpack_request(buffer, size, request)) {
printf("unpack request failed\n");
return;
}
is_event = is_event_type(request);
while (r) {
if ((is_event && r->reg_type == Reg_Event)
|| (!is_event && r->reg_type == Reg_Request)) {
if (check_url_start(request->url, strlen(request->url), r->url)
> 0) {
r->request_handler(request);
return;
}
}
r = r->next;
}
printf("on_request: exit. no service handler\n");
}
void
api_response_send(response_t *response)
{
int size;
char *buffer = pack_response(response, &size);
if (buffer == NULL)
return;
wasm_response_send(buffer, size);
free_req_resp_packet(buffer);
}
/// event api
bool
api_publish_event(const char *url, int fmt, void *payload, int payload_len)
{
int size;
request_t request[1];
init_request(request, (char *)url, COAP_EVENT, fmt, payload, payload_len);
char *buffer = pack_request(request, &size);
if (buffer == NULL)
return false;
wasm_post_request(buffer, size);
free_req_resp_packet(buffer);
return true;
}
bool
api_subscribe_event(const char *url, request_handler_f handler)
{
return register_url_handler(url, handler, Reg_Event);
}

View File

@ -1,100 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdlib.h>
#include <string.h>
#include "wa-inc/timer_wasm_app.h"
#include "timer_api.h"
#if 1
#include <stdio.h>
#else
#define printf (...)
#endif
struct user_timer {
struct user_timer *next;
int timer_id;
void (*user_timer_callback)(user_timer_t);
};
struct user_timer *g_timers = NULL;
user_timer_t
api_timer_create(int interval, bool is_period, bool auto_start,
on_user_timer_update_f on_timer_update)
{
int timer_id = wasm_create_timer(interval, is_period, auto_start);
// TODO
struct user_timer *timer =
(struct user_timer *)malloc(sizeof(struct user_timer));
if (timer == NULL) {
// TODO: remove the timer_id
printf("### api_timer_create malloc faild!!! \n");
return NULL;
}
memset(timer, 0, sizeof(*timer));
timer->timer_id = timer_id;
timer->user_timer_callback = on_timer_update;
if (g_timers == NULL)
g_timers = timer;
else {
timer->next = g_timers;
g_timers = timer;
}
return timer;
}
void
api_timer_cancel(user_timer_t timer)
{
user_timer_t t = g_timers, prev = NULL;
wasm_timer_cancel(timer->timer_id);
while (t) {
if (t == timer) {
if (prev == NULL) {
g_timers = t->next;
free(t);
}
else {
prev->next = t->next;
free(t);
}
return;
}
else {
prev = t;
t = t->next;
}
}
}
void
api_timer_restart(user_timer_t timer, int interval)
{
wasm_timer_restart(timer->timer_id, interval);
}
void
on_timer_callback(int timer_id)
{
struct user_timer *t = g_timers;
while (t) {
if (t->timer_id == timer_id) {
t->user_timer_callback(t);
break;
}
t = t->next;
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _TIMER_API_H_
#define _TIMER_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int timer_id_t;
timer_id_t
wasm_create_timer(int interval, bool is_period, bool auto_start);
void
wasm_timer_destroy(timer_id_t timer_id);
void
wasm_timer_cancel(timer_id_t timer_id);
void
wasm_timer_restart(timer_id_t timer_id, int interval);
uint32
wasm_get_sys_tick_ms(void);
#ifdef __cplusplus
}
#endif
#endif /* end of _TIMER_API_H_ */

View File

@ -1,171 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _AEE_REQUEST_H_
#define _AEE_REQUEST_H_
#include "bi-inc/shared_utils.h"
#ifdef __cplusplus
extern "C" {
#endif
/* CoAP request method codes */
typedef enum {
COAP_GET = 1,
COAP_POST,
COAP_PUT,
COAP_DELETE,
COAP_EVENT = (COAP_DELETE + 2)
} 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;
/**
* @typedef request_handler_f
*
* @brief Define the signature of callback function for API
* api_register_resource_handler() to handle request or for API
* api_subscribe_event() to handle event.
*
* @param request pointer of the request to be handled
*
* @see api_register_resource_handler
* @see api_subscribe_event
*/
typedef void (*request_handler_f)(request_t *request);
/**
* @typedef response_handler_f
*
* @brief Define the signature of callback function for API
* api_send_request() to handle response of a request.
*
* @param response pointer of the response to be handled
* @param user_data user data associated with the request which is set when
* calling api_send_request().
*
* @see api_send_request
*/
typedef void (*response_handler_f)(response_t *response, void *user_data);
/*
*****************
* Request APIs
*****************
*/
/**
* @brief Register resource.
*
* @param url url of the resource
* @param handler callback function to handle the request to the resource
*
* @return true if success, false otherwise
*/
bool
api_register_resource_handler(const char *url, request_handler_f handler);
/**
* @brief Send request asynchronously.
*
* @param request pointer of the request to be sent
* @param response_handler callback function to handle the response
* @param user_data user data
*/
void
api_send_request(request_t *request, response_handler_f response_handler,
void *user_data);
/**
* @brief Send response.
*
* @param response pointer of the response to be sent
*
* @par
* @code
* void res1_handler(request_t *request)
* {
* response_t response[1];
* make_response_for_request(request, response);
* set_response(response, DELETED_2_02, 0, NULL, 0);
* api_response_send(response);
* }
* @endcode
*/
void
api_response_send(response_t *response);
/*
*****************
* Event APIs
*****************
*/
/**
* @brief Publish an event.
*
* @param url url of the event
* @param fmt format of the event payload
* @param payload payload of the event
* @param payload_len length in bytes of the event payload
*
* @return true if success, false otherwise
*/
bool
api_publish_event(const char *url, int fmt, void *payload, int payload_len);
/**
* @brief Subscribe an event.
*
* @param url url of the event
* @param handler callback function to handle the event.
*
* @return true if success, false otherwise
*/
bool
api_subscribe_event(const char *url, request_handler_f handler);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _AEE_TIMER_H_
#define _AEE_TIMER_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/* board producer define user_timer */
struct user_timer;
typedef struct user_timer *user_timer_t;
/**
* @typedef on_user_timer_update_f
*
* @brief Define the signature of callback function for API api_timer_create().
*
* @param timer the timer
*
* @see api_timer_create
*/
typedef void (*on_user_timer_update_f)(user_timer_t timer);
/*
*****************
* Timer APIs
*****************
*/
/**
* @brief Create timer.
*
* @param interval timer interval
* @param is_period whether the timer is periodic
* @param auto_start whether start the timer immediately after created
* @param on_timer_update callback function called when timer expired
*
* @return the timer created if success, NULL otherwise
*/
user_timer_t
api_timer_create(int interval, bool is_period, bool auto_start,
on_user_timer_update_f on_timer_update);
/**
* @brief Cancel timer.
*
* @param timer the timer to cancel
*/
void
api_timer_cancel(user_timer_t timer);
/**
* @brief Restart timer.
*
* @param timer the timer to cancel
* @param interval the timer interval
*/
void
api_timer_restart(user_timer_t timer, int interval);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,13 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_APP_BASE_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_APP_BASE_DIR})
add_definitions (-DWASM_ENABLE_BASE_LIB)
file (GLOB_RECURSE source_all ${WASM_APP_BASE_DIR}/*.c)
set (WASM_APP_CURRENT_SOURCE ${source_all})
set (WASM_APP_BASE_DIR ${WASM_APP_BASE_DIR} PARENT_SCOPE)

View File

@ -1,20 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _LIB_AEE_H_
#define _LIB_AEE_H_
#include "bi-inc/shared_utils.h"
#include "bi-inc/attr_container.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* end of _LIB_AEE_H_ */

View File

@ -1,14 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
EXPORT_WASM_API_WITH_SIG(wasm_register_resource, "($)"),
EXPORT_WASM_API_WITH_SIG(wasm_response_send, "(*~)i"),
EXPORT_WASM_API_WITH_SIG(wasm_post_request, "(*~)"),
EXPORT_WASM_API_WITH_SIG(wasm_sub_event, "($)"),
EXPORT_WASM_API_WITH_SIG(wasm_create_timer, "(iii)i"),
EXPORT_WASM_API_WITH_SIG(wasm_timer_destroy, "(i)"),
EXPORT_WASM_API_WITH_SIG(wasm_timer_cancel, "(i)"),
EXPORT_WASM_API_WITH_SIG(wasm_timer_restart, "(ii)"),
EXPORT_WASM_API_WITH_SIG(wasm_get_sys_tick_ms, "()i"),

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lib_export.h"
#include "req_resp_native_api.h"
#include "timer_native_api.h"
static NativeSymbol extended_native_symbol_defs[] = {
/* TODO: use macro EXPORT_WASM_API() or EXPORT_WASM_API2() to
add functions to register. */
#include "base_lib.inl"
};
uint32
get_base_lib_export_apis(NativeSymbol **p_base_lib_apis)
{
*p_base_lib_apis = extended_native_symbol_defs;
return sizeof(extended_native_symbol_defs) / sizeof(NativeSymbol);
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _REQ_RESP_API_H_
#define _REQ_RESP_API_H_
#include "bh_platform.h"
#include "wasm_export.h"
#ifdef __cplusplus
extern "C" {
#endif
bool
wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size);
void
wasm_register_resource(wasm_exec_env_t exec_env, char *url);
void
wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size);
void
wasm_sub_event(wasm_exec_env_t exec_env, char *url);
#ifdef __cplusplus
}
#endif
#endif /* end of _REQ_RESP_API_H_ */

View File

@ -1,84 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "app_manager_export.h"
#include "coap_ext.h"
#include "wasm_export.h"
#include "bh_assert.h"
extern void
module_request_handler(request_t *request, void *user_data);
bool
wasm_response_send(wasm_exec_env_t exec_env, char *buffer, int size)
{
if (buffer != NULL) {
response_t response[1];
if (NULL == unpack_response(buffer, size, response))
return false;
am_send_response(response);
return true;
}
return false;
}
void
wasm_register_resource(wasm_exec_env_t exec_env, char *url)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (url != NULL) {
unsigned int mod_id =
app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(mod_id != ID_NONE);
am_register_resource(url, module_request_handler, mod_id);
}
}
void
wasm_post_request(wasm_exec_env_t exec_env, char *buffer, int size)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (buffer != NULL) {
request_t req[1];
if (!unpack_request(buffer, size, req))
return;
// TODO: add permission check, ensure app can't do harm
// set sender to help dispatch the response to the sender ap
unsigned int mod_id =
app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(mod_id != ID_NONE);
req->sender = mod_id;
if (req->action == COAP_EVENT) {
am_publish_event(req);
return;
}
am_dispatch_request(req);
}
}
void
wasm_sub_event(wasm_exec_env_t exec_env, char *url)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (url != NULL) {
unsigned int mod_id =
app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(mod_id != ID_NONE);
am_register_event(url, mod_id);
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef LIB_BASE_RUNTIME_LIB_H_
#define LIB_BASE_RUNTIME_LIB_H_
#include "runtime_timer.h"
bool
init_wasm_timer();
void
exit_wasm_timer();
timer_ctx_t
get_wasm_timer_ctx();
timer_ctx_t
create_wasm_timer_ctx(unsigned int module_id, int prealloc_num);
void
destroy_module_timer_ctx(unsigned int module_id);
#endif /* LIB_BASE_RUNTIME_LIB_H_ */

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _TIMER_API_H_
#define _TIMER_API_H_
#include "bh_platform.h"
#include "wasm_export.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int timer_id_t;
/*
* timer interfaces
*/
typedef unsigned int timer_id_t;
timer_id_t
wasm_create_timer(wasm_exec_env_t exec_env, int interval, bool is_period,
bool auto_start);
void
wasm_timer_destroy(wasm_exec_env_t exec_env, timer_id_t timer_id);
void
wasm_timer_cancel(wasm_exec_env_t exec_env, timer_id_t timer_id);
void
wasm_timer_restart(wasm_exec_env_t exec_env, timer_id_t timer_id, int interval);
uint32
wasm_get_sys_tick_ms(wasm_exec_env_t exec_env);
#ifdef __cplusplus
}
#endif
#endif /* end of _TIMER_API_H_ */

View File

@ -1,220 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "app_manager_export.h"
#include "../app-manager/module_wasm_app.h"
#include "timer_native_api.h"
typedef struct {
bh_list_link l;
timer_ctx_t timer_ctx;
} timer_ctx_node_t;
static bool timer_thread_run = true;
static bh_list g_timer_ctx_list;
static korp_cond g_timer_ctx_list_cond;
static korp_mutex g_timer_ctx_list_mutex;
void
wasm_timer_callback(timer_id_t id, unsigned int mod_id)
{
module_data *module = module_data_list_lookup_id(mod_id);
if (module == NULL)
return;
// !!! the length parameter must be 0, so the receiver will
// not free the payload pointer.
bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *)(uintptr_t)id, 0);
}
/**
* why we create a separate link for module timer contexts
* rather than traverse the module list?
* It helps to reduce the lock frequency for the module list.
* Also when we lock the module list and then call the callback for
* timer expire, the callback is request the list lock again for lookup
* the module from module id. It is for avoiding that situation.
*/
void *
thread_modulers_timer_check(void *arg)
{
uint32 ms_to_expiry;
uint64 us_to_wait;
while (timer_thread_run) {
ms_to_expiry = (uint32)-1;
os_mutex_lock(&g_timer_ctx_list_mutex);
timer_ctx_node_t *elem =
(timer_ctx_node_t *)bh_list_first_elem(&g_timer_ctx_list);
while (elem) {
uint32 next = check_app_timers(elem->timer_ctx);
if (next != (uint32)-1) {
if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
ms_to_expiry = next;
}
elem = (timer_ctx_node_t *)bh_list_elem_next(elem);
}
os_mutex_unlock(&g_timer_ctx_list_mutex);
if (ms_to_expiry == (uint32)-1)
us_to_wait = BHT_WAIT_FOREVER;
else
us_to_wait = (uint64)ms_to_expiry * 1000;
os_mutex_lock(&g_timer_ctx_list_mutex);
os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
us_to_wait);
os_mutex_unlock(&g_timer_ctx_list_mutex);
}
return NULL;
}
void
wakeup_modules_timer_thread(timer_ctx_t ctx)
{
os_mutex_lock(&g_timer_ctx_list_mutex);
os_cond_signal(&g_timer_ctx_list_cond);
os_mutex_unlock(&g_timer_ctx_list_mutex);
}
bool
init_wasm_timer()
{
korp_tid tm_tid;
bh_list_init(&g_timer_ctx_list);
if (os_cond_init(&g_timer_ctx_list_cond) != 0) {
return false;
}
/* temp solution for: thread_modulers_timer_check thread
would recursive lock the mutex */
if (os_recursive_mutex_init(&g_timer_ctx_list_mutex) != 0) {
goto fail1;
}
if (0
!= os_thread_create(&tm_tid, thread_modulers_timer_check, NULL,
BH_APPLET_PRESERVED_STACK_SIZE)) {
goto fail2;
}
return true;
fail2:
os_mutex_destroy(&g_timer_ctx_list_mutex);
fail1:
os_cond_destroy(&g_timer_ctx_list_cond);
return false;
}
void
exit_wasm_timer()
{
timer_thread_run = false;
}
timer_ctx_t
create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
{
timer_ctx_t ctx =
create_timer_ctx(wasm_timer_callback, wakeup_modules_timer_thread,
prealloc_num, module_id);
if (ctx == NULL)
return NULL;
timer_ctx_node_t *node =
(timer_ctx_node_t *)wasm_runtime_malloc(sizeof(timer_ctx_node_t));
if (node == NULL) {
destroy_timer_ctx(ctx);
return NULL;
}
memset(node, 0, sizeof(*node));
node->timer_ctx = ctx;
os_mutex_lock(&g_timer_ctx_list_mutex);
bh_list_insert(&g_timer_ctx_list, node);
os_mutex_unlock(&g_timer_ctx_list_mutex);
return ctx;
}
void
destroy_module_timer_ctx(unsigned int module_id)
{
timer_ctx_node_t *elem;
os_mutex_lock(&g_timer_ctx_list_mutex);
elem = (timer_ctx_node_t *)bh_list_first_elem(&g_timer_ctx_list);
while (elem) {
if (timer_ctx_get_owner(elem->timer_ctx) == module_id) {
bh_list_remove(&g_timer_ctx_list, elem);
destroy_timer_ctx(elem->timer_ctx);
wasm_runtime_free(elem);
break;
}
elem = (timer_ctx_node_t *)bh_list_elem_next(elem);
}
os_mutex_unlock(&g_timer_ctx_list_mutex);
}
timer_ctx_t
get_wasm_timer_ctx(wasm_module_inst_t module_inst)
{
module_data *m = app_manager_get_module_data(Module_WASM_App, module_inst);
if (m == NULL)
return NULL;
return m->timer_ctx;
}
timer_id_t
wasm_create_timer(wasm_exec_env_t exec_env, int interval, bool is_period,
bool auto_start)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
bh_assert(timer_ctx);
return sys_create_timer(timer_ctx, interval, is_period, auto_start);
}
void
wasm_timer_destroy(wasm_exec_env_t exec_env, timer_id_t timer_id)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
bh_assert(timer_ctx);
sys_timer_destroy(timer_ctx, timer_id);
}
void
wasm_timer_cancel(wasm_exec_env_t exec_env, timer_id_t timer_id)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
bh_assert(timer_ctx);
sys_timer_cancel(timer_ctx, timer_id);
}
void
wasm_timer_restart(wasm_exec_env_t exec_env, timer_id_t timer_id, int interval)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
bh_assert(timer_ctx);
sys_timer_restart(timer_ctx, timer_id, interval);
}
uint32
wasm_get_sys_tick_ms(wasm_exec_env_t exec_env)
{
return (uint32)bh_get_tick_ms();
}

View File

@ -1,13 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_LIB_BASE_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions (-DWASM_ENABLE_BASE_LIB)
include_directories(${WASM_LIB_BASE_DIR})
file (GLOB_RECURSE source_all ${WASM_LIB_BASE_DIR}/*.c)
set (WASM_APP_LIB_CURRENT_SOURCE ${source_all})

View File

@ -1,118 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wa-inc/connection.h"
#include "connection_api.h"
/* Raw connection structure */
typedef struct _connection {
/* Next connection */
struct _connection *next;
/* Handle of the connection */
uint32 handle;
/* Callback function called when event on this connection occurs */
on_connection_event_f on_event;
/* User data */
void *user_data;
} connection_t;
/* Raw connections list */
static connection_t *g_conns = NULL;
connection_t *
api_open_connection(const char *name, attr_container_t *args,
on_connection_event_f on_event, void *user_data)
{
connection_t *conn;
char *args_buffer = (char *)args;
uint32 handle, args_len = attr_container_get_serialize_length(args);
handle = wasm_open_connection(name, args_buffer, args_len);
if (handle == -1)
return NULL;
conn = (connection_t *)malloc(sizeof(*conn));
if (conn == NULL) {
wasm_close_connection(handle);
return NULL;
}
memset(conn, 0, sizeof(*conn));
conn->handle = handle;
conn->on_event = on_event;
conn->user_data = user_data;
if (g_conns != NULL) {
conn->next = g_conns;
g_conns = conn;
}
else {
g_conns = conn;
}
return conn;
}
void
api_close_connection(connection_t *c)
{
connection_t *conn = g_conns, *prev = NULL;
while (conn) {
if (conn == c) {
wasm_close_connection(c->handle);
if (prev != NULL)
prev->next = conn->next;
else
g_conns = conn->next;
free(conn);
return;
}
else {
prev = conn;
conn = conn->next;
}
}
}
int
api_send_on_connection(connection_t *conn, const char *data, uint32 len)
{
return wasm_send_on_connection(conn->handle, data, len);
}
bool
api_config_connection(connection_t *conn, attr_container_t *cfg)
{
char *cfg_buffer = (char *)cfg;
uint32 cfg_len = attr_container_get_serialize_length(cfg);
return wasm_config_connection(conn->handle, cfg_buffer, cfg_len);
}
void
on_connection_data(uint32 handle, char *buffer, uint32 len)
{
connection_t *conn = g_conns;
while (conn != NULL) {
if (conn->handle == handle) {
if (len == 0) {
conn->on_event(conn, CONN_EVENT_TYPE_DISCONNECT, NULL, 0,
conn->user_data);
}
else {
conn->on_event(conn, CONN_EVENT_TYPE_DATA, buffer, len,
conn->user_data);
}
return;
}
conn = conn->next;
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef CONNECTION_API_H_
#define CONNECTION_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
uint32
wasm_open_connection(const char *name, char *args_buf, uint32 args_buf_len);
void
wasm_close_connection(uint32 handle);
int
wasm_send_on_connection(uint32 handle, const char *data, uint32 data_len);
bool
wasm_config_connection(uint32 handle, const char *cfg_buf, uint32 cfg_buf_len);
#ifdef __cplusplus
}
#endif
#endif /* end of CONNECTION_API_H_ */

View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _CONNECTION_H_
#define _CONNECTION_H_
#include "bi-inc/attr_container.h"
#ifdef __cplusplus
extern "C" {
#endif
struct _connection;
typedef struct _connection connection_t;
/* Connection event type */
typedef enum {
/* Data is received */
CONN_EVENT_TYPE_DATA = 1,
/* Connection is disconnected */
CONN_EVENT_TYPE_DISCONNECT
} conn_event_type_t;
/*
* @typedef on_connection_event_f
*
* @param conn the connection that the event belongs to
* @param type event type
* @param data the data received for CONN_EVENT_TYPE_DATA event
* @param len length of the data in byte
* @param user_data user data
*/
typedef void (*on_connection_event_f)(connection_t *conn,
conn_event_type_t type, const char *data,
uint32 len, void *user_data);
/*
*****************
* Connection API's
*****************
*/
/*
* @brief Open a connection.
*
* @param name name of the connection, "TCP", "UDP" or "UART"
* @param args connection arguments, such as: ip:127.0.0.1, port:8888
* @param on_event callback function called when event occurs
* @param user_data user data
*
* @return the connection or NULL means fail
*/
connection_t *
api_open_connection(const char *name, attr_container_t *args,
on_connection_event_f on_event, void *user_data);
/*
* @brief Close a connection.
*
* @param conn connection
*/
void
api_close_connection(connection_t *conn);
/*
* Send data to the connection in non-blocking manner which returns immediately
*
* @param conn the connection
* @param data data buffer to be sent
* @param len length of the data in byte
*
* @return actual length sent, or -1 if fail(maybe underlying buffer is full)
*/
int
api_send_on_connection(connection_t *conn, const char *data, uint32 len);
/*
* @brief Configure connection.
*
* @param conn the connection
* @param cfg configurations
*
* @return true if success, false otherwise
*/
bool
api_config_connection(connection_t *conn, attr_container_t *cfg);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,11 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_APP_CONN_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_APP_CONN_DIR})
file (GLOB source_all ${WASM_APP_CONN_DIR}/*.c)
set (WASM_APP_CURRENT_SOURCE ${source_all})

View File

@ -1,9 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
EXPORT_WASM_API_WITH_SIG(wasm_open_connection, "($*~)i"),
EXPORT_WASM_API_WITH_SIG(wasm_close_connection, "(i)"),
EXPORT_WASM_API_WITH_SIG(wasm_send_on_connection, "(i*~)i"),
EXPORT_WASM_API_WITH_SIG(wasm_config_connection, "(i*~)i"),

View File

@ -1,75 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef CONNECTION_LIB_H_
#define CONNECTION_LIB_H_
#include "bi-inc/attr_container.h"
#include "wasm_export.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* This file defines connection library which should be implemented by
* different platforms
*/
/*
* @brief Open a connection.
*
* @param name name of the connection, "TCP", "UDP" or "UART"
* @param args connection arguments, such as: ip:127.0.0.1, port:8888
*
* @return 0~0xFFFFFFFE means id of the connection, otherwise(-1) means fail
*/
typedef uint32 (*connection_open_f)(wasm_module_inst_t module_inst,
const char *name, attr_container_t *args);
/*
* @brief Close a connection.
*
* @param handle of the connection
*/
typedef void (*connection_close_f)(uint32 handle);
/*
* @brief Send data to the connection in non-blocking manner.
*
* @param handle of the connection
* @param data data buffer to be sent
* @param len length of the data in byte
*
* @return actual length sent, -1 if fail
*/
typedef int (*connection_send_f)(uint32 handle, const char *data, int len);
/*
* @brief Configure connection.
*
* @param handle of the connection
* @param cfg configurations
*
* @return true if success, false otherwise
*/
typedef bool (*connection_config_f)(uint32 handle, attr_container_t *cfg);
/* Raw connection interface for platform to implement */
typedef struct _connection_interface {
connection_open_f _open;
connection_close_f _close;
connection_send_f _send;
connection_config_f _config;
} connection_interface_t;
/* Platform must define this interface */
extern connection_interface_t connection_impl;
#ifdef __cplusplus
}
#endif
#endif /* CONNECTION_LIB_H_ */

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef CONNECTION_API_H_
#define CONNECTION_API_H_
#include "bh_platform.h"
#include "wasm_export.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* connection interfaces
*/
uint32
wasm_open_connection(wasm_exec_env_t exec_env, char *name, char *args_buf,
uint32 len);
void
wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle);
int
wasm_send_on_connection(wasm_exec_env_t exec_env, uint32 handle, char *data,
uint32 len);
bool
wasm_config_connection(wasm_exec_env_t exec_env, uint32 handle, char *cfg_buf,
uint32 len);
#ifdef __cplusplus
}
#endif
#endif /* end of CONNECTION_API_H_ */

View File

@ -1,61 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "connection_lib.h"
#include "wasm_export.h"
#include "native_interface.h"
#include "connection_native_api.h"
/* Note:
*
* This file is the consumer of connection lib which is implemented by different
* platforms
*/
uint32
wasm_open_connection(wasm_exec_env_t exec_env, char *name, char *args_buf,
uint32 len)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
attr_container_t *args;
args = (attr_container_t *)args_buf;
if (connection_impl._open != NULL)
return connection_impl._open(module_inst, name, args);
return -1;
}
void
wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle)
{
if (connection_impl._close != NULL)
connection_impl._close(handle);
}
int
wasm_send_on_connection(wasm_exec_env_t exec_env, uint32 handle, char *data,
uint32 len)
{
if (connection_impl._send != NULL)
return connection_impl._send(handle, data, len);
return -1;
}
bool
wasm_config_connection(wasm_exec_env_t exec_env, uint32 handle, char *cfg_buf,
uint32 len)
{
attr_container_t *cfg;
cfg = (attr_container_t *)cfg_buf;
if (connection_impl._config != NULL)
return connection_impl._config(handle, cfg);
return false;
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "conn_tcp.h"
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
int
tcp_open(char *address, uint16 port)
{
int sock, ret;
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(address);
servaddr.sin_port = htons(port);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == -1)
return -1;
ret = connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (ret == -1) {
close(sock);
return -1;
}
/* Put the socket in non-blocking mode */
if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) {
close(sock);
return -1;
}
return sock;
}
int
tcp_send(int sock, const char *data, int size)
{
return send(sock, data, size, 0);
}
int
tcp_recv(int sock, char *buffer, int buf_size)
{
return recv(sock, buffer, buf_size, 0);
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef CONN_LINUX_TCP_H_
#define CONN_LINUX_TCP_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
int
tcp_open(char *address, uint16 port);
int
tcp_send(int sock, const char *data, int size);
int
tcp_recv(int sock, char *buffer, int buf_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,103 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "conn_uart.h"
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
static int
parse_baudrate(int baud)
{
switch (baud) {
case 9600:
return B9600;
case 19200:
return B19200;
case 38400:
return B38400;
case 57600:
return B57600;
case 115200:
return B115200;
case 230400:
return B230400;
case 460800:
return B460800;
case 500000:
return B500000;
case 576000:
return B576000;
case 921600:
return B921600;
case 1000000:
return B1000000;
case 1152000:
return B1152000;
case 1500000:
return B1500000;
case 2000000:
return B2000000;
case 2500000:
return B2500000;
case 3000000:
return B3000000;
case 3500000:
return B3500000;
case 4000000:
return B4000000;
default:
return -1;
}
}
int
uart_open(char *device, int baudrate)
{
int uart_fd;
struct termios uart_term;
uart_fd = open(device, O_RDWR | O_NOCTTY);
if (uart_fd < 0)
return -1;
memset(&uart_term, 0, sizeof(uart_term));
uart_term.c_cflag = parse_baudrate(baudrate) | CS8 | CLOCAL | CREAD;
uart_term.c_iflag = IGNPAR;
uart_term.c_oflag = 0;
/* set noncanonical mode */
uart_term.c_lflag = 0;
uart_term.c_cc[VTIME] = 30;
uart_term.c_cc[VMIN] = 1;
tcflush(uart_fd, TCIFLUSH);
if (tcsetattr(uart_fd, TCSANOW, &uart_term) != 0) {
close(uart_fd);
return -1;
}
/* Put the fd in non-blocking mode */
if (fcntl(uart_fd, F_SETFL, fcntl(uart_fd, F_GETFL) | O_NONBLOCK) < 0) {
close(uart_fd);
return -1;
}
return uart_fd;
}
int
uart_send(int fd, const char *data, int size)
{
return write(fd, data, size);
}
int
uart_recv(int fd, char *buffer, int buf_size)
{
return read(fd, buffer, buf_size);
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef CONN_LINUX_UART_H_
#define CONN_LINUX_UART_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
int
uart_open(char *device, int baudrate);
int
uart_send(int fd, const char *data, int size);
int
uart_recv(int fd, char *buffer, int buf_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "conn_udp.h"
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
int
udp_open(uint16 port)
{
int sock, ret;
struct sockaddr_in addr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
return -1;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) {
close(sock);
return -1;
}
/* Put the socket in non-blocking mode */
if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) {
close(sock);
return -1;
}
return sock;
}
int
udp_send(int sock, struct sockaddr *dest, const char *data, int size)
{
return sendto(sock, data, size, MSG_CONFIRM, dest, sizeof(*dest));
}
int
udp_recv(int sock, char *buffer, int buf_size)
{
struct sockaddr_in remaddr;
socklen_t addrlen = sizeof(remaddr);
return recvfrom(sock, buffer, buf_size, 0, (struct sockaddr *)&remaddr,
&addrlen);
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef CONN_LINUX_UDP_H_
#define CONN_LINUX_UDP_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
int
udp_open(uint16 port);
int
udp_send(int sock, struct sockaddr *dest, const char *data, int size);
int
udp_recv(int sock, char *buffer, int buf_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,609 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/*
* Note:
* This file implements the linux version connection library which is
* defined in connection_lib.h.
* It also provides a reference implementation of connections manager.
*/
#include "connection_lib.h"
#include "bh_platform.h"
#include "app_manager_export.h"
#include "module_wasm_app.h"
#include "conn_tcp.h"
#include "conn_udp.h"
#include "conn_uart.h"
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define MAX_EVENTS 10
#define IO_BUF_SIZE 256
static bool polling_thread_run = true;
/* Connection type */
typedef enum conn_type {
CONN_TYPE_TCP,
CONN_TYPE_UDP,
CONN_TYPE_UART,
CONN_TYPE_UNKNOWN
} conn_type_t;
/* Sys connection */
typedef struct sys_connection {
/* Next connection */
struct sys_connection *next;
/* Type */
conn_type_t type;
/* Handle to interact with wasm app */
uint32 handle;
/* Underlying connection ID, may be socket fd */
int fd;
/* Module id that the connection belongs to */
uint32 module_id;
/* Argument, such as dest addr for udp */
void *arg;
} sys_connection_t;
/* Epoll instance */
static int epollfd;
/* Connections list */
static sys_connection_t *g_connections = NULL;
/* Max handle */
static uint32 g_handle_max = 0;
/* Lock to protect g_connections and g_handle_max */
static korp_mutex g_lock;
/* Epoll events */
static struct epoll_event epoll_events[MAX_EVENTS];
/* Buffer to receive data */
static char io_buf[IO_BUF_SIZE];
static uint32
_conn_open(wasm_module_inst_t module_inst, const char *name,
attr_container_t *args);
static void
_conn_close(uint32 handle);
static int
_conn_send(uint32 handle, const char *data, int len);
static bool
_conn_config(uint32 handle, attr_container_t *cfg);
/* clang-format off */
/*
* Platform implementation of connection library
*/
connection_interface_t connection_impl = {
._open = _conn_open,
._close = _conn_close,
._send = _conn_send,
._config = _conn_config
};
/* clang-format on */
static void
add_connection(sys_connection_t *conn)
{
os_mutex_lock(&g_lock);
g_handle_max++;
if (g_handle_max == -1)
g_handle_max++;
conn->handle = g_handle_max;
if (g_connections) {
conn->next = g_connections;
g_connections = conn;
}
else {
g_connections = conn;
}
os_mutex_unlock(&g_lock);
}
#define FREE_CONNECTION(conn) \
do { \
if (conn->arg) \
wasm_runtime_free(conn->arg); \
wasm_runtime_free(conn); \
} while (0)
static int
get_app_conns_num(uint32 module_id)
{
sys_connection_t *conn;
int num = 0;
os_mutex_lock(&g_lock);
conn = g_connections;
while (conn) {
if (conn->module_id == module_id)
num++;
conn = conn->next;
}
os_mutex_unlock(&g_lock);
return num;
}
static sys_connection_t *
find_connection(uint32 handle, bool remove_found)
{
sys_connection_t *conn, *prev = NULL;
os_mutex_lock(&g_lock);
conn = g_connections;
while (conn) {
if (conn->handle == handle) {
if (remove_found) {
if (prev != NULL) {
prev->next = conn->next;
}
else {
g_connections = conn->next;
}
}
os_mutex_unlock(&g_lock);
return conn;
}
else {
prev = conn;
conn = conn->next;
}
}
os_mutex_unlock(&g_lock);
return NULL;
}
static void
cleanup_connections(uint32 module_id)
{
sys_connection_t *conn, *prev = NULL;
os_mutex_lock(&g_lock);
conn = g_connections;
while (conn) {
if (conn->module_id == module_id) {
epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL);
close(conn->fd);
if (prev != NULL) {
prev->next = conn->next;
FREE_CONNECTION(conn);
conn = prev->next;
}
else {
g_connections = conn->next;
FREE_CONNECTION(conn);
conn = g_connections;
}
}
else {
prev = conn;
conn = conn->next;
}
}
os_mutex_unlock(&g_lock);
}
static conn_type_t
get_conn_type(const char *name)
{
if (strcmp(name, "TCP") == 0)
return CONN_TYPE_TCP;
if (strcmp(name, "UDP") == 0)
return CONN_TYPE_UDP;
if (strcmp(name, "UART") == 0)
return CONN_TYPE_UART;
return CONN_TYPE_UNKNOWN;
}
/* --- connection lib function --- */
static uint32
_conn_open(wasm_module_inst_t module_inst, const char *name,
attr_container_t *args)
{
int fd;
sys_connection_t *conn;
struct epoll_event ev;
uint32 module_id = app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(module_id != ID_NONE);
if (get_app_conns_num(module_id) >= MAX_CONNECTION_PER_APP)
return -1;
conn = (sys_connection_t *)wasm_runtime_malloc(sizeof(*conn));
if (conn == NULL)
return -1;
memset(conn, 0, sizeof(*conn));
conn->module_id = module_id;
conn->type = get_conn_type(name);
/* Generate a handle and add to list */
add_connection(conn);
if (conn->type == CONN_TYPE_TCP) {
char *address;
uint16 port;
/* Check and parse connection parameters */
if (!attr_container_contain_key(args, "address")
|| !attr_container_contain_key(args, "port"))
goto fail;
address = attr_container_get_as_string(args, "address");
port = attr_container_get_as_uint16(args, "port");
/* Connect to TCP server */
if (!address || (fd = tcp_open(address, port)) == -1)
goto fail;
}
else if (conn->type == CONN_TYPE_UDP) {
uint16 port;
/* Check and parse connection parameters */
if (!attr_container_contain_key(args, "bind port"))
goto fail;
port = attr_container_get_as_uint16(args, "bind port");
/* Bind port */
if ((fd = udp_open(port)) == -1)
goto fail;
}
else if (conn->type == CONN_TYPE_UART) {
char *device;
int baud;
/* Check and parse connection parameters */
if (!attr_container_contain_key(args, "device")
|| !attr_container_contain_key(args, "baudrate"))
goto fail;
device = attr_container_get_as_string(args, "device");
baud = attr_container_get_as_int(args, "baudrate");
/* Open device */
if (!device || (fd = uart_open(device, baud)) == -1)
goto fail;
}
else {
goto fail;
}
conn->fd = fd;
/* Set current connection as event data */
ev.events = EPOLLIN;
ev.data.ptr = conn;
/* Monitor incoming data */
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
close(fd);
goto fail;
}
return conn->handle;
fail:
find_connection(conn->handle, true);
wasm_runtime_free(conn);
return -1;
}
/* --- connection lib function --- */
static void
_conn_close(uint32 handle)
{
sys_connection_t *conn = find_connection(handle, true);
if (conn != NULL) {
epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL);
close(conn->fd);
FREE_CONNECTION(conn);
}
}
/* --- connection lib function --- */
static int
_conn_send(uint32 handle, const char *data, int len)
{
sys_connection_t *conn = find_connection(handle, false);
if (conn == NULL)
return -1;
if (conn->type == CONN_TYPE_TCP)
return tcp_send(conn->fd, data, len);
if (conn->type == CONN_TYPE_UDP) {
struct sockaddr *addr = (struct sockaddr *)conn->arg;
return udp_send(conn->fd, addr, data, len);
}
if (conn->type == CONN_TYPE_UART)
return uart_send(conn->fd, data, len);
return -1;
}
/* --- connection lib function --- */
static bool
_conn_config(uint32 handle, attr_container_t *cfg)
{
sys_connection_t *conn = find_connection(handle, false);
if (conn == NULL)
return false;
if (conn->type == CONN_TYPE_UDP) {
char *address;
uint16_t port;
struct sockaddr_in *addr;
/* Parse remote address/port */
if (!attr_container_contain_key(cfg, "address")
|| !attr_container_contain_key(cfg, "port"))
return false;
if (!(address = attr_container_get_as_string(cfg, "address")))
return false;
port = attr_container_get_as_uint16(cfg, "port");
if (conn->arg == NULL) {
addr = (struct sockaddr_in *)wasm_runtime_malloc(sizeof(*addr));
if (addr == NULL)
return false;
memset(addr, 0, sizeof(*addr));
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(address);
addr->sin_port = htons(port);
/* Set remote address as connection arg */
conn->arg = addr;
}
else {
addr = (struct sockaddr_in *)conn->arg;
addr->sin_addr.s_addr = inet_addr(address);
addr->sin_port = htons(port);
}
return true;
}
return false;
}
/* --- connection manager reference implementation ---*/
typedef struct connection_event {
uint32 handle;
char *data;
uint32 len;
} connection_event_t;
static void
connection_event_cleaner(connection_event_t *conn_event)
{
if (conn_event->data != NULL)
wasm_runtime_free(conn_event->data);
wasm_runtime_free(conn_event);
}
static void
post_msg_to_module(sys_connection_t *conn, char *data, uint32 len)
{
module_data *module = module_data_list_lookup_id(conn->module_id);
char *data_copy = NULL;
connection_event_t *conn_data_event;
bh_message_t msg;
if (module == NULL)
return;
conn_data_event =
(connection_event_t *)wasm_runtime_malloc(sizeof(*conn_data_event));
if (conn_data_event == NULL)
return;
if (len > 0) {
data_copy = (char *)wasm_runtime_malloc(len);
if (data_copy == NULL) {
wasm_runtime_free(conn_data_event);
return;
}
bh_memcpy_s(data_copy, len, data, len);
}
memset(conn_data_event, 0, sizeof(*conn_data_event));
conn_data_event->handle = conn->handle;
conn_data_event->data = data_copy;
conn_data_event->len = len;
msg = bh_new_msg(CONNECTION_EVENT_WASM, conn_data_event,
sizeof(*conn_data_event), connection_event_cleaner);
if (!msg) {
connection_event_cleaner(conn_data_event);
return;
}
bh_post_msg2(module->queue, msg);
}
static void *
polling_thread_routine(void *arg)
{
while (polling_thread_run) {
int i, n;
n = epoll_wait(epollfd, epoll_events, MAX_EVENTS, -1);
if (n == -1 && errno != EINTR)
continue;
for (i = 0; i < n; i++) {
sys_connection_t *conn =
(sys_connection_t *)epoll_events[i].data.ptr;
if (conn->type == CONN_TYPE_TCP) {
int count = tcp_recv(conn->fd, io_buf, IO_BUF_SIZE);
if (count <= 0) {
/* Connection is closed by peer */
post_msg_to_module(conn, NULL, 0);
_conn_close(conn->handle);
}
else {
/* Data is received */
post_msg_to_module(conn, io_buf, count);
}
}
else if (conn->type == CONN_TYPE_UDP) {
int count = udp_recv(conn->fd, io_buf, IO_BUF_SIZE);
if (count > 0)
post_msg_to_module(conn, io_buf, count);
}
else if (conn->type == CONN_TYPE_UART) {
int count = uart_recv(conn->fd, io_buf, IO_BUF_SIZE);
if (count > 0)
post_msg_to_module(conn, io_buf, count);
}
}
}
return NULL;
}
void
app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg)
{
uint32 argv[3];
wasm_function_inst_t func_on_conn_data;
bh_assert(CONNECTION_EVENT_WASM == bh_message_type(msg));
wasm_data *wasm_app_data = (wasm_data *)m_data->internal_data;
wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
connection_event_t *conn_event =
(connection_event_t *)bh_message_payload(msg);
int32 data_offset;
if (conn_event == NULL)
return;
func_on_conn_data = wasm_runtime_lookup_function(
inst, "_on_connection_data", "(i32i32i32)");
if (!func_on_conn_data)
func_on_conn_data = wasm_runtime_lookup_function(
inst, "on_connection_data", "(i32i32i32)");
if (!func_on_conn_data) {
printf("Cannot find function on_connection_data\n");
return;
}
/* 0 len means connection closed */
if (conn_event->len == 0) {
argv[0] = conn_event->handle;
argv[1] = 0;
argv[2] = 0;
if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_on_conn_data,
3, argv)) {
const char *exception = wasm_runtime_get_exception(inst);
bh_assert(exception);
printf(":Got exception running wasm code: %s\n", exception);
wasm_runtime_clear_exception(inst);
return;
}
}
else {
data_offset = wasm_runtime_module_dup_data(inst, conn_event->data,
conn_event->len);
if (data_offset == 0) {
const char *exception = wasm_runtime_get_exception(inst);
if (exception) {
printf("Got exception running wasm code: %s\n", exception);
wasm_runtime_clear_exception(inst);
}
return;
}
argv[0] = conn_event->handle;
argv[1] = (uint32)data_offset;
argv[2] = conn_event->len;
if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_on_conn_data,
3, argv)) {
const char *exception = wasm_runtime_get_exception(inst);
bh_assert(exception);
printf(":Got exception running wasm code: %s\n", exception);
wasm_runtime_clear_exception(inst);
wasm_runtime_module_free(inst, data_offset);
return;
}
wasm_runtime_module_free(inst, data_offset);
}
}
bool
init_connection_framework()
{
korp_tid tid;
epollfd = epoll_create(MAX_EVENTS);
if (epollfd == -1)
return false;
if (os_mutex_init(&g_lock) != 0) {
close(epollfd);
return false;
}
if (!wasm_register_cleanup_callback(cleanup_connections)) {
goto fail;
}
if (!wasm_register_msg_callback(CONNECTION_EVENT_WASM,
app_mgr_connection_event_callback)) {
goto fail;
}
if (os_thread_create(&tid, polling_thread_routine, NULL,
BH_APPLET_PRESERVED_STACK_SIZE)
!= 0) {
goto fail;
}
return true;
fail:
os_mutex_destroy(&g_lock);
close(epollfd);
return false;
}
void
exit_connection_framework()
{
polling_thread_run = false;
}

View File

@ -1,13 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_LIB_CONN_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_LIB_CONN_MGR_DIR})
file (GLOB_RECURSE source_all ${WASM_LIB_CONN_MGR_DIR}/*.c)
set (WASM_LIB_CONN_MGR_SOURCE ${source_all})

View File

@ -1,18 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_LIB_CONN_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_LIB_CONN_DIR})
add_definitions (-DAPP_FRAMEWORK_CONNECTION)
include (${CMAKE_CURRENT_LIST_DIR}/${WAMR_BUILD_PLATFORM}/connection_mgr.cmake)
file (GLOB source_all
${WASM_LIB_CONN_MGR_SOURCE}
${WASM_LIB_CONN_DIR}/*.c
)
set (WASM_APP_LIB_CURRENT_SOURCE ${source_all})

View File

@ -1,25 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/*
* Note:
* This file implements the linux version connection library which is
* defined in connection_lib.h.
* It also provides a reference impl of connections manager.
*/
#include "connection_lib.h"
/* clang-format off */
/*
* Platform implementation of connection library
*/
connection_interface_t connection_impl = {
._open = NULL,
._close = NULL,
._send = NULL,
._config = NULL
};
/* clang-format on */

View File

@ -1,13 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_LIB_CONN_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_LIB_CONN_MGR_DIR})
file (GLOB_RECURSE source_all ${WASM_LIB_CONN_MGR_DIR}/*.c)
set (WASM_LIB_CONN_MGR_SOURCE ${source_all})

View File

@ -1,122 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wa-inc/sensor.h"
#include "sensor_api.h"
typedef struct _sensor {
struct _sensor *next;
char *name;
uint32 handle;
void (*sensor_callback)(sensor_t, attr_container_t *, void *);
void *user_data;
} sensor;
static sensor_t g_sensors = NULL;
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);
if (id == -1)
return NULL;
// create local node for holding the user callback
sensor_t sensor = (sensor_t)malloc(sizeof(struct _sensor));
if (sensor == NULL)
return NULL;
memset(sensor, 0, sizeof(struct _sensor));
sensor->handle = id;
sensor->name = strdup(name);
sensor->user_data = user_data;
sensor->sensor_callback = sensor_event_handler;
if (!sensor->name) {
free(sensor);
return NULL;
}
if (g_sensors == NULL) {
g_sensors = sensor;
}
else {
sensor->next = g_sensors;
g_sensors = sensor;
}
return sensor;
}
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);
}
bool
sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay)
{
bool ret = wasm_sensor_config(sensor->handle, interval, bit_cfg, delay);
return ret;
}
bool
sensor_close(sensor_t sensor)
{
wasm_sensor_close(sensor->handle);
// remove local node
sensor_t s = g_sensors;
sensor_t prev = NULL;
while (s) {
if (s == sensor) {
if (prev == NULL) {
g_sensors = s->next;
}
else {
prev->next = s->next;
}
free(s->name);
free(s);
return true;
}
else {
prev = s;
s = s->next;
}
}
return false;
}
/*
*
* API for native layer to callback for sensor events
*
*/
void
on_sensor_event(uint32 sensor_id, char *buffer, int len)
{
attr_container_t *sensor_data = (attr_container_t *)buffer;
// lookup the sensor and call the handlers
sensor_t s = g_sensors;
sensor_t prev = NULL;
while (s) {
if (s->handle == sensor_id) {
s->sensor_callback(s, sensor_data, s->user_data);
break;
}
s = s->next;
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _SENSOR_API_H_
#define _SENSOR_API_H_
#include "bh_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
uint32
wasm_sensor_open(const char *name, int instance);
bool
wasm_sensor_config(uint32 sensor, uint32 interval, int bit_cfg, uint32 delay);
bool
wasm_sensor_config_with_attr_container(uint32 sensor, char *buffer, uint32 len);
bool
wasm_sensor_close(uint32 sensor);
#ifdef __cplusplus
}
#endif
#endif /* end of _SENSOR_API_H_ */

View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _AEE_SENSOR_H_
#define _AEE_SENSOR_H_
#include "bi-inc/attr_container.h"
#ifdef __cplusplus
extern "C" {
#endif
/* board producer define sensor */
struct _sensor;
typedef struct _sensor *sensor_t;
/**
* @typedef sensor_event_handler_f
*
* @brief Define the signature of callback function for API
* sensor_open() to handle sensor event.
*
* @param sensor the sensor which the event belong to
* @param sensor_event the sensor event
* @param user_data user data associated with the sensor which is set when
* calling sensor_open().
*
* @see sensor_open
*/
typedef void (*sensor_event_handler_f)(sensor_t sensor,
attr_container_t *sensor_event,
void *user_data);
/*
*****************
* Sensor APIs
*****************
*/
/**
* @brief Open sensor.
*
* @param name sensor name
* @param index sensor index
* @param handler callback function to handle the sensor event
* @param user_data user data
*
* @return the sensor opened if success, NULL otherwise
*/
sensor_t
sensor_open(const char *name, int index, sensor_event_handler_f handler,
void *user_data);
/**
* @brief Configure sensor with interval/bit_cfg/delay values.
*
* @param sensor the sensor to be configured
* @param interval sensor event interval
* @param bit_cfg sensor bit config
* @param delay sensor delay
*
* @return true if success, false otherwise
*/
bool
sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay);
/**
* @brief Configure sensor with attr_container_t object.
*
* @param sensor the sensor to be configured
* @param cfg the configuration
*
* @return true if success, false otherwise
*/
bool
sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg);
/**
* @brief Close sensor.
*
* @param sensor the sensor to be closed
*
* @return true if success, false otherwise
*/
bool
sensor_close(sensor_t sensor);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,11 +0,0 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (WASM_APP_SENSOR_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_APP_SENSOR_DIR})
file (GLOB_RECURSE source_all ${WASM_APP_SENSOR_DIR}/*.c)
set (WASM_APP_CURRENT_SOURCE ${source_all})

View File

@ -1,434 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "runtime_sensor.h"
#include "app_manager_export.h"
#include "module_wasm_app.h"
#include "bh_platform.h"
static sys_sensor_t *g_sys_sensors = NULL;
static uint32 g_sensor_id_max = 0;
static sensor_client_t *
find_sensor_client(sys_sensor_t *sensor, unsigned int client_id,
bool remove_if_found);
void (*rechedule_sensor_callback)() = NULL;
/*
* API for the applications to call - don't call it from the runtime
*
*/
static void
sensor_event_cleaner(sensor_event_data_t *sensor_event)
{
if (sensor_event->data != NULL) {
if (sensor_event->data_fmt == FMT_ATTR_CONTAINER)
attr_container_destroy(sensor_event->data);
else
wasm_runtime_free(sensor_event->data);
}
wasm_runtime_free(sensor_event);
}
static void
wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data)
{
attr_container_t *sensor_data = (attr_container_t *)user_data;
attr_container_t *sensor_data_clone;
int sensor_data_len;
sensor_event_data_t *sensor_event;
bh_message_t msg;
sensor_client_t *c = (sensor_client_t *)client;
module_data *module = module_data_list_lookup_id(c->client_id);
if (module == NULL)
return;
if (sensor_data == NULL)
return;
sensor_data_len = attr_container_get_serialize_length(sensor_data);
sensor_data_clone =
(attr_container_t *)wasm_runtime_malloc(sensor_data_len);
if (sensor_data_clone == NULL)
return;
/* multiple sensor clients may use/free the sensor data, so make a copy */
bh_memcpy_s(sensor_data_clone, sensor_data_len, sensor_data,
sensor_data_len);
sensor_event =
(sensor_event_data_t *)wasm_runtime_malloc(sizeof(*sensor_event));
if (sensor_event == NULL) {
wasm_runtime_free(sensor_data_clone);
return;
}
memset(sensor_event, 0, sizeof(*sensor_event));
sensor_event->sensor_id = sensor_id;
sensor_event->data = sensor_data_clone;
sensor_event->data_fmt = FMT_ATTR_CONTAINER;
msg = bh_new_msg(SENSOR_EVENT_WASM, sensor_event, sizeof(*sensor_event),
sensor_event_cleaner);
if (!msg) {
sensor_event_cleaner(sensor_event);
return;
}
bh_post_msg2(module->queue, msg);
}
bool
wasm_sensor_config(wasm_exec_env_t exec_env, uint32 sensor, uint32 interval,
int bit_cfg, uint32 delay)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
attr_container_t *attr_cont;
sensor_client_t *c;
sensor_obj_t s = find_sys_sensor_id(sensor);
if (s == NULL)
return false;
unsigned int mod_id =
app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(mod_id != ID_NONE);
os_mutex_lock(&s->lock);
c = find_sensor_client(s, mod_id, false);
if (c == NULL) {
os_mutex_unlock(&s->lock);
return false;
}
c->interval = interval;
c->bit_cfg = bit_cfg;
c->delay = delay;
os_mutex_unlock(&s->lock);
if (s->config != NULL) {
attr_cont = attr_container_create("config sensor");
attr_container_set_int(&attr_cont, "interval", (int)interval);
attr_container_set_int(&attr_cont, "bit_cfg", bit_cfg);
attr_container_set_int(&attr_cont, "delay", (int)delay);
s->config(s, attr_cont);
attr_container_destroy(attr_cont);
}
refresh_read_interval(s);
reschedule_sensor_read();
return true;
}
uint32
wasm_sensor_open(wasm_exec_env_t exec_env, char *name, int instance)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
if (name != NULL) {
sensor_client_t *c;
sys_sensor_t *s = find_sys_sensor(name, instance);
if (s == NULL)
return (uint32)-1;
unsigned int mod_id =
app_manager_get_module_id(Module_WASM_App, module_inst);
bh_assert(mod_id != ID_NONE);
os_mutex_lock(&s->lock);
c = find_sensor_client(s, mod_id, false);
if (c) {
// the app already opened this sensor
os_mutex_unlock(&s->lock);
return (uint32)-1;
}
sensor_client_t *client =
(sensor_client_t *)wasm_runtime_malloc(sizeof(sensor_client_t));
if (client == NULL) {
os_mutex_unlock(&s->lock);
return (uint32)-1;
}
memset(client, 0, sizeof(sensor_client_t));
client->client_id = mod_id;
client->client_callback = (void *)wasm_sensor_callback;
client->interval = s->default_interval;
client->next = s->clients;
s->clients = client;
os_mutex_unlock(&s->lock);
refresh_read_interval(s);
reschedule_sensor_read();
return s->sensor_id;
}
return (uint32)-1;
}
bool
wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, uint32 sensor,
char *buffer, int len)
{
if (buffer != NULL) {
attr_container_t *cfg = (attr_container_t *)buffer;
sensor_obj_t s = find_sys_sensor_id(sensor);
if (s == NULL)
return false;
if (s->config == NULL)
return false;
return s->config(s, cfg);
}
return false;
}
bool
wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
unsigned int mod_id =
app_manager_get_module_id(Module_WASM_App, module_inst);
unsigned int client_id = mod_id;
sensor_obj_t s = find_sys_sensor_id(sensor);
sensor_client_t *c;
bh_assert(mod_id != ID_NONE);
if (s == NULL)
return false;
os_mutex_lock(&s->lock);
if ((c = find_sensor_client(s, client_id, true)) != NULL)
wasm_runtime_free(c);
os_mutex_unlock(&s->lock);
refresh_read_interval(s);
reschedule_sensor_read();
return true;
}
/*
*
* sensor framework API - don't expose to the applications
*
*/
void
set_sensor_reshceduler(void (*callback)())
{
rechedule_sensor_callback = callback;
}
// used for other threads to wakeup the sensor read thread
void
reschedule_sensor_read()
{
if (rechedule_sensor_callback)
rechedule_sensor_callback();
}
void
refresh_read_interval(sensor_obj_t sensor)
{
sensor_client_t *c;
uint32 interval = sensor->default_interval;
os_mutex_lock(&sensor->lock);
c = sensor->clients;
if (c)
interval = c->interval;
while (c) {
if (c->interval < interval)
interval = c->interval;
c = c->next;
}
os_mutex_unlock(&sensor->lock);
sensor->read_interval = interval;
}
sensor_obj_t
add_sys_sensor(char *name, char *description, int instance,
uint32 default_interval, void *read_func, void *config_func)
{
sys_sensor_t *s = (sys_sensor_t *)wasm_runtime_malloc(sizeof(sys_sensor_t));
if (s == NULL)
return NULL;
memset(s, 0, sizeof(*s));
s->name = bh_strdup(name);
s->sensor_instance = instance;
s->default_interval = default_interval;
if (!s->name) {
wasm_runtime_free(s);
return NULL;
}
if (description) {
s->description = bh_strdup(description);
if (!s->description) {
wasm_runtime_free(s->name);
wasm_runtime_free(s);
return NULL;
}
}
g_sensor_id_max++;
if (g_sensor_id_max == UINT32_MAX)
g_sensor_id_max++;
s->sensor_id = g_sensor_id_max;
s->read = read_func;
s->config = config_func;
if (g_sys_sensors == NULL) {
g_sys_sensors = s;
}
else {
s->next = g_sys_sensors;
g_sys_sensors = s;
}
if (os_mutex_init(&s->lock) != 0) {
if (s->description) {
wasm_runtime_free(s->description);
}
wasm_runtime_free(s->name);
wasm_runtime_free(s);
}
return s;
}
sensor_obj_t
find_sys_sensor(const char *name, int instance)
{
sys_sensor_t *s = g_sys_sensors;
while (s) {
if (strcmp(s->name, name) == 0 && s->sensor_instance == instance)
return s;
s = s->next;
}
return NULL;
}
sensor_obj_t
find_sys_sensor_id(uint32 sensor_id)
{
sys_sensor_t *s = g_sys_sensors;
while (s) {
if (s->sensor_id == sensor_id)
return s;
s = s->next;
}
return NULL;
}
sensor_client_t *
find_sensor_client(sys_sensor_t *sensor, unsigned int client_id,
bool remove_if_found)
{
sensor_client_t *prev = NULL, *c = sensor->clients;
while (c) {
sensor_client_t *next = c->next;
if (c->client_id == client_id) {
if (remove_if_found) {
if (prev)
prev->next = next;
else
sensor->clients = next;
}
return c;
}
else {
prev = c;
c = c->next;
}
}
return NULL;
}
// return the milliseconds to next check
uint32
check_sensor_timers()
{
uint32 ms_to_next_check = UINT32_MAX;
uint32 now = (uint32)bh_get_tick_ms();
sys_sensor_t *s = g_sys_sensors;
while (s) {
uint32 last_read = s->last_read;
uint32 elpased_ms = bh_get_elpased_ms(&last_read);
if (s->read_interval <= 0 || s->clients == NULL) {
s = s->next;
continue;
}
if (elpased_ms >= s->read_interval) {
attr_container_t *data = s->read(s);
if (data) {
sensor_client_t *client = s->clients;
while (client) {
client->client_callback(client, s->sensor_id, data);
client = client->next;
}
attr_container_destroy(data);
}
s->last_read = now;
if (s->read_interval < ms_to_next_check)
ms_to_next_check = s->read_interval;
}
else {
uint32 remaining = s->read_interval - elpased_ms;
if (remaining < ms_to_next_check)
ms_to_next_check = remaining;
}
s = s->next;
}
return ms_to_next_check;
}
void
sensor_cleanup_callback(uint32 module_id)
{
sys_sensor_t *s = g_sys_sensors;
while (s) {
sensor_client_t *c;
os_mutex_lock(&s->lock);
if ((c = find_sensor_client(s, module_id, true)) != NULL) {
wasm_runtime_free(c);
}
os_mutex_unlock(&s->lock);
s = s->next;
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef LIB_EXTENSION_RUNTIME_SENSOR_H_
#define LIB_EXTENSION_RUNTIME_SENSOR_H_
#include "bh_platform.h"
#include "bi-inc/attr_container.h"
#include "wasm_export.h"
#include "sensor_native_api.h"
struct _sys_sensor;
typedef struct _sys_sensor *sensor_obj_t;
typedef struct _sensor_client {
struct _sensor_client *next;
unsigned int client_id; // the app id
uint32 interval;
int bit_cfg;
uint32 delay;
void (*client_callback)(void *client, uint32, attr_container_t *);
} sensor_client_t;
typedef struct _sys_sensor {
struct _sys_sensor *next;
char *name;
int sensor_instance;
char *description;
uint32 sensor_id;
sensor_client_t *clients;
/* app, sensor mgr and app mgr may access the clients at the same time,
so need a lock to protect the clients */
korp_mutex lock;
uint32 last_read;
uint32 read_interval;
uint32 default_interval;
/* TODO: may support other type return value, such as 'cbor' */
attr_container_t *(*read)(void *);
bool (*config)(void *, void *);
} sys_sensor_t;
sensor_obj_t
add_sys_sensor(char *name, char *description, int instance,
uint32 default_interval, void *read_func, void *config_func);
sensor_obj_t
find_sys_sensor(const char *name, int instance);
sensor_obj_t
find_sys_sensor_id(uint32 sensor_id);
void
refresh_read_interval(sensor_obj_t sensor);
void
sensor_cleanup_callback(uint32 module_id);
uint32
check_sensor_timers();
void
reschedule_sensor_read();
bool
init_sensor_framework();
void
start_sensor_framework();
void
exit_sensor_framework();
#endif /* LIB_EXTENSION_RUNTIME_SENSOR_H_ */

View File

@ -1,9 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
EXPORT_WASM_API_WITH_SIG(wasm_sensor_open, "($i)i"),
EXPORT_WASM_API_WITH_SIG(wasm_sensor_config, "(iiii)i"),
EXPORT_WASM_API_WITH_SIG(wasm_sensor_config_with_attr_container, "(i*~)i"),
EXPORT_WASM_API_WITH_SIG(wasm_sensor_close, "(i)i"),

View File

@ -1,148 +0,0 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_platform.h"
#include "runtime_sensor.h"
#include "bi-inc/attr_container.h"
#include "module_wasm_app.h"
#include "wasm_export.h"
/*
*
* One reference implementation for sensor manager
*
*
*/
static korp_cond cond;
static korp_mutex mutex;
static bool sensor_check_thread_run = true;
void
app_mgr_sensor_event_callback(module_data *m_data, bh_message_t msg)
{
uint32 argv[3];
wasm_function_inst_t func_onSensorEvent;
bh_assert(SENSOR_EVENT_WASM == bh_message_type(msg));
wasm_data *wasm_app_data = (wasm_data *)m_data->internal_data;
wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
sensor_event_data_t *payload =
(sensor_event_data_t *)bh_message_payload(msg);
if (payload == NULL)
return;
func_onSensorEvent =
wasm_runtime_lookup_function(inst, "_on_sensor_event", "(i32i32i32)");
if (!func_onSensorEvent)
func_onSensorEvent = wasm_runtime_lookup_function(
inst, "on_sensor_event", "(i32i32i32)");
if (!func_onSensorEvent) {
printf("Cannot find function on_sensor_event\n");
}
else {
int32 sensor_data_offset;
uint32 sensor_data_len;
if (payload->data_fmt == FMT_ATTR_CONTAINER) {
sensor_data_len =
attr_container_get_serialize_length(payload->data);
}
else {
printf("Unsupported sensor data format: %d\n", payload->data_fmt);
return;
}
sensor_data_offset =
wasm_runtime_module_dup_data(inst, payload->data, sensor_data_len);
if (sensor_data_offset == 0) {
const char *exception = wasm_runtime_get_exception(inst);
if (exception) {
printf("Got exception running wasm code: %s\n", exception);
wasm_runtime_clear_exception(inst);
}
return;
}
argv[0] = payload->sensor_id;
argv[1] = (uint32)sensor_data_offset;
argv[2] = sensor_data_len;
if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onSensorEvent,
3, argv)) {
const char *exception = wasm_runtime_get_exception(inst);
bh_assert(exception);
printf(":Got exception running wasm code: %s\n", exception);
wasm_runtime_clear_exception(inst);
wasm_runtime_module_free(inst, sensor_data_offset);
return;
}
wasm_runtime_module_free(inst, sensor_data_offset);
}
}
static void
thread_sensor_check(void *arg)
{
while (sensor_check_thread_run) {
uint32 ms_to_expiry = check_sensor_timers();
if (ms_to_expiry == UINT32_MAX)
ms_to_expiry = 5000;
os_mutex_lock(&mutex);
os_cond_reltimedwait(&cond, &mutex, ms_to_expiry * 1000);
os_mutex_unlock(&mutex);
}
}
static void
cb_wakeup_thread()
{
os_cond_signal(&cond);
}
void
set_sensor_reshceduler(void (*callback)());
bool
init_sensor_framework()
{
/* init the mutext and conditions */
if (os_cond_init(&cond) != 0) {
return false;
}
if (os_mutex_init(&mutex) != 0) {
os_cond_destroy(&cond);
return false;
}
set_sensor_reshceduler(cb_wakeup_thread);
wasm_register_msg_callback(SENSOR_EVENT_WASM,
app_mgr_sensor_event_callback);
wasm_register_cleanup_callback(sensor_cleanup_callback);
return true;
}
void
start_sensor_framework()
{
korp_tid tid;
os_thread_create(&tid, (void *)thread_sensor_check, NULL,
BH_APPLET_PRESERVED_STACK_SIZE);
}
void
exit_sensor_framework()
{
sensor_check_thread_run = false;
reschedule_sensor_read();
// todo: wait the sensor thread termination
}

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