diff --git a/.devcontainer/raspi/Dockerfile b/.devcontainer/raspi/Dockerfile
index dca356ad..0ebc3fd1 100644
--- a/.devcontainer/raspi/Dockerfile
+++ b/.devcontainer/raspi/Dockerfile
@@ -23,6 +23,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
git \
gpg \
make \
+ patchelf \
pycodestyle \
python3-pip \
python3-bashate \
@@ -90,6 +91,8 @@ RUN echo "deb https://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VERS
&& update-alternatives --install /usr/bin/ld.lld ld.lld /usr/bin/ld.lld-${LLVM_VERSION} 50 \
&& update-alternatives --install /usr/bin/wasm-ld wasm-ld /usr/bin/wasm-ld-${LLVM_VERSION} 50
+RUN pip3 install auditwheel==6.3.0 --break-system-packages
+
ENV WASI_PREFIX=/usr/bin/
ARG WASI_SDK_VERSION=24
ENV WASI_SYSROOT=/opt/wasi-sysroot-${WASI_SDK_VERSION}.0
diff --git a/.devcontainer/ubuntu/Dockerfile b/.devcontainer/ubuntu/Dockerfile
index bb6bfb31..d9dfb797 100644
--- a/.devcontainer/ubuntu/Dockerfile
+++ b/.devcontainer/ubuntu/Dockerfile
@@ -24,6 +24,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
git \
gpg \
make \
+ patchelf \
pycodestyle \
python3-pip \
python3-bashate \
@@ -60,7 +61,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 50
# Remove this once stdeb is fully released for ubuntu:24.04 (python3.12)
-RUN pip3 install git+https://github.com/astraw/stdeb.git --break-system-packages
+RUN pip3 install \
+ auditwheel==6.3.0 \
+ git+https://github.com/astraw/stdeb.git \
+ --break-system-packages
RUN echo "deb https://apt.llvm.org/noble/ llvm-toolchain-noble-${LLVM_VERSION} main" > /etc/apt/sources.list.d/apt.llvm.org.list && \
curl -sL https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \
diff --git a/.github/workflows/build-sdk.yml b/.github/workflows/build-sdk.yml
index 8970c6b2..35445a58 100644
--- a/.github/workflows/build-sdk.yml
+++ b/.github/workflows/build-sdk.yml
@@ -29,7 +29,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ github.token }}
options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }}
- timeout-minutes: 8 # the worst case is 3 minutes
+ timeout-minutes: ${{ startsWith(matrix.runner, 'buildjet') && 20 || 8 }} # the worst case is 3 minutes but buildjet sometimes is slower downloading the docker image
strategy:
fail-fast: false
matrix:
@@ -92,7 +92,7 @@ jobs:
- name: Build Python package
working-directory: src/python-evp-app-sdk
- run: python3 -m build
+ run: make
- name: SDK Debian package
working-directory: src/python-evp-app-sdk
@@ -101,7 +101,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: python-sdk-${{ matrix.name }}-${{ matrix.platform }}-${{ github.run_id }}
- path: src/python-evp-app-sdk/dist/*
+ path: lib/python/*
- uses: actions/upload-artifact@v4
with:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0f876b6c..c66fc4f6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -29,7 +29,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ github.token }}
options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }}
- timeout-minutes: 8 # the worst case is 3 minutes
+ timeout-minutes: ${{ startsWith(matrix.runner, 'buildjet') && 20 || 8 }} # the worst case is 3 minutes but buildjet sometimes is slower downloading the docker image
strategy:
fail-fast: false
matrix:
@@ -50,7 +50,8 @@ jobs:
ref: ${{ inputs.ref }}
- name: Build
- run: bear -- make -j$((`nproc` * 2)) CFLAGS="-g -Werror"
+ run: bear -- make -j$((`nproc` * 2)) CFLAGS="-g -Werror" \
+ LDFLAGS="-Wl,--export-dynamic"
- name: Generate SBOM
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index eb4ff94f..96b26ee4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,14 +13,26 @@ jobs:
release-artifacts:
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v4
+ - name: Get release version name
+ id: version
+ run: |
+ name=$(echo "${{ github.ref_name }}" | awk -F/ '{print $NF}')
+ echo "name=$name" >> $GITHUB_OUTPUT
- name: Get last successful run id
id: run-id
env:
GH_TOKEN: ${{ github.token }}
run: |
- last_run_id=$(gh run list -w main.yml -c ${{ github.sha }} -b main -s completed --json databaseId -L 1 | jq -r .[].databaseId)
+ last_run_id=$(
+ gh run list \
+ --repo ${{ github.repository }} \
+ -w main.yml \
+ -c ${{ github.sha }} \
+ -b main \
+ -s completed \
+ --json databaseId -L 1 | jq -r .[].databaseId
+ )
test -z $last_run_id && echo "cannot find last successful run_id" && exit 1 || echo "last_run_id=$last_run_id" && echo "last_run_id=$last_run_id" >> $GITHUB_OUTPUT
- name: Download Python SDK (RaspiOS bookworm ARM64)
@@ -113,6 +125,17 @@ jobs:
path: dist-ubuntu-noble-amd64
github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }}
+ - name: Download SBOM
+ uses: actions/download-artifact@v4
+ env:
+ LAST_RUN_ID: ${{ steps.run-id.outputs.last_run_id }}
+ with:
+ pattern: sbom-agent-*${{ env.LAST_RUN_ID }}
+ merge-multiple: false
+ run-id: ${{ env.LAST_RUN_ID }}
+ path: sbom
+ github-token: ${{ github.event.repository.private && secrets.MIDOJENKINS_ARTIFACT_READ_EVP_AGENT_OSS || github.token }}
+
- name: Rename deb artifacts
run: |
set -x
@@ -124,15 +147,13 @@ jobs:
mv $deb $(echo $deb | sed -E 's/(.*)_([^_]*).deb/\1-raspios-bookworm_\2.deb/');
done
- - name: Rename whl artifacts
+ - name: Create a zip for sbom
run: |
set -x
- for whl in dist-ubuntu-noble-*/*.whl; do
- mv $whl $(echo $whl | sed -E 's/(.*)-([^-]*).whl/\1-ubuntu_noble-\2.whl/');
- done
-
- for whl in dist-raspios-bookworm-*/*.whl; do
- mv $whl $(echo $whl | sed -E 's/(.*)-([^-]*).whl/\1-raspios_bookworm-\2.whl/');
+ cd sbom
+ for dir in sbom-agent*; do
+ sbom_name="${dir%-*}"
+ zip -r ${sbom_name}-${{ steps.version.outputs.name }}.zip $dir;
done
- name: List files in dist-ubuntu-noble-amd64
@@ -151,3 +172,4 @@ jobs:
files: |
dist-*/*.deb
dist-*/*.whl
+ sbom/*.zip
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 65720cb4..8f81847d 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -29,7 +29,7 @@ jobs:
username: ${{ github.actor }}
password: ${{ github.token }}
options: ${{ startsWith(matrix.runner, 'buildjet') && '--user 1000:1001' || '--user 1001:127' }}
- timeout-minutes: 30
+ timeout-minutes: ${{ startsWith(matrix.runner, 'buildjet') && 20 || 8 }} # the worst case is 3 minutes but buildjet sometimes is slower downloading the docker image
strategy:
fail-fast: false
matrix:
@@ -67,7 +67,7 @@ jobs:
make -j$((`nproc` * 2))\
KBUILD_DEFCONFIG=configs/unit-test-all-hubs-wasm.config\
test_modules/tests
-
+
- name: Run tests
env:
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
diff --git a/.gitignore b/.gitignore
index fa7fcb4b..304318bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,7 @@ test/lorem-ipsum
.venv/
*.core
/dist
+/src/python-evp-app-sdk/dist-stamp
/src/sdkenc/stamp
/src/sdkenc/*.h
/include/sdkenc/*.h
diff --git a/.gitmodules b/.gitmodules
index f14d4c33..158ac3ca 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -16,7 +16,7 @@
url = https://github.com/apache/nuttx-apps
[submodule "src/wasm-micro-runtime"]
path = src/wasm-micro-runtime
- url = https://github.com/bytecodealliance/wasm-micro-runtime
+ url = https://github.com/midokura/wasm-micro-runtime.git
[submodule "test/libweb"]
path = test/libweb
url = https://github.com/midokura/libweb.git
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..519cb2ca
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,138 @@
+
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement
+[our contact form](https://support.aitrios.sony-semicon.com/hc/en-us/requests/new).
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..4b071e50
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,64 @@
+
+
+# Contributing Guidelines
+
+We gratefully accept contributions from the community. Please take a moment to review this document and our [Code of Conduct](CODE_OF_CONDUCT.md) in order to make the contribution process efficient and pleasant for everyone involved.
+
+## Bug Reports
+
+If you think you have found a bug, first make sure that you are testing against the latest version, in case your issue has already been fixed. Search our issues list on GitHub to see if a similar or related problem has already been reported.
+
+When creating a new issue, or updating an existing one, please provide as much contextual information as you can. What environment, device and OS do you use? What is your build configuration? With what version of dependencies and with which compiler and toolchain did you build?
+
+In addition it will be very helpful if you can provide a unit test, system test, or step by step instructions to reproduce the bug. It makes it much easier to find the problem and fix it.
+
+## Feature Requests
+
+If you find yourself wishing for a feature that doesn't exist, you are probably not alone. There are bound to be others with similar needs. Open an issue on our issues list on GitHub, detailing:
+- The feature you would like to see
+- Why it is important
+- How it should work
+- How you will use it
+
+## Security Vulnerabilities
+
+> [!WARNING]
+> Do not use public issues to report security vulnerabilities: contact us directly instead.
+
+If you think that you have identified a security vulnerability in Edge Virtualization Platform(EVP), please send us your report with as much context as possible via [our contact form](https://support.aitrios.sony-semicon.com/hc/en-us/requests/new).
+
+## Contributing Code, Tests, and Documentation
+
+Send us your pull requests! For those just getting started, GitHub has a [how to](https://help.github.com/articles/using-pull-requests/).
+
+In order to maintain proper traceability of contributions, we require that you agree to the four clauses of the [Developer's Certificate of Origin](https://developercertificate.org/). Particularly, commits should be signed off by their respective authors. This repository enforces this by means of the [DCO GitHub app](https://github.com/apps/dco).
+
+### Submit a Pull Request (PR)
+
+- Check for open issues or PRs related to your change.
+- Before writing any code, consider creating a new issue for any major change and enhancement that you wish to make. It may be that somebody is already working on it, or that there are particular complexities that you should know about.
+- Fork the repository on GitHub to start making your changes. As a general rule, you should use the "main" branch as a basis.
+- Include unit tests when you contribute new features, as they help to prove that your code works correctly and guard against future breaking changes.
+- Bug fixes also generally require unit tests, because the presence of bugs usually indicates insufficient test coverage.
+- Keep API compatibility in mind when you change code in core functionality. Any non-backward-compatible public API changes, i.e. breaking changes to header files in the `edge-virtualization-platform/src/` folder, will require a major version increment.
+- Include a license header at the top of all new files.
+- Please avoid including unrelated commits and changes in your PR branch.
+- Before submitting a PR, test locally. Run formatting checks and unit tests on your development machine. See [the build instructions](docs/README.md) for details.
+- Send a PR and work with us until it is merged. Contributions may need some modifications, so a few rounds of review and fixing may be necessary.
+- For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it takes to review and merge.
+- Include as much context as possible: What problem does your PR solve, how does it solve it, and why is it important?
+
+Our team members will review your PR, and once it is approved and passes continuous integration checks it will be ready to merge.
+
+Bear in mind that when you contribute a new feature, the maintenance burden is transferred to the edge-virtualization-platform team. This means that the benefit of the contribution must be compared against the cost of maintaining the feature.
+
+> [!WARNING]
+> By submitting a PR, you agree to license your work under the same license as that used by the project.
+
+## License and Copyright
+
+Contributors accept that their contributions are made under the Apache-2.0 license. All new files should include the Apache-2.0 standard license header where possible. See the [LICENSE](LICENSE) file for the full text of this license.
diff --git a/Makefile b/Makefile
index 64310bc4..a2ffabba 100644
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,8 @@ deps.mk: .config
dist: all
$(SCRIPTDIR)/mk-agent-deb.sh -V $(VERSION) -a $(ARCH)
- $(SCRIPTDIR)/mk-sdk-deb.sh -V $(SDK_VERSION) -a $(ARCH)
+ $(SCRIPTDIR)/mk-app-sdk-deb.sh -V $(SDK_VERSION) -a $(ARCH)
+ $(SCRIPTDIR)/mk-agent-sdk-deb.sh -V $(SDK_VERSION) -a $(ARCH)
clean:
cd test && $(MAKE) clean
diff --git a/PrivacyPolicy.md b/PrivacyPolicy.md
new file mode 100644
index 00000000..d7b6f9ba
--- /dev/null
+++ b/PrivacyPolicy.md
@@ -0,0 +1,520 @@
+
+
+Last Updated and Effective: 30th May, 2025
+
+**Privacy Policy on SSS Open-Source Projects**
+
+This privacy policy (**"Privacy Policy"**) describes our policies and
+procedures about the collection, use, disclosure and sharing, or other
+processing of your personal information when you participate in or use
+our open-source software development project (each, a **"Project"**)
+sites (e.g., github.com, collectively, the **"Sites"**). This Privacy
+Policy applies to activities by Sony Semiconductor Solutions Corporation
+(collectively **"SSS"**, **"we"** or **"us"**).
+
+For purposes of data protection legislation, we are the controller of
+your personal information.
+
+In this Privacy Policy, "personal information" includes references to
+"personal data" as defined under applicable laws.
+
+**Personal Information That SSS Collects**
+
+We collect personal information directly from individuals through the
+Sites. You do not have to provide us your personal information.
+ However, if you choose not to disclose certain information, you will
+not be able to participate in certain aspects of our Projects.
+
+***Your Contributions to Open-Source Projects***.
+
+*Attribution, Provenance and Integrity*. When you contribute source
+code, documentation or other content to one of our Projects (whether on
+your own behalf or through contributions made as part of your employment
+services to your employer), we collect and store the information and
+content that you contribute. This includes the contents of those
+contributions, as well as information required to confirm the provenance
+of intellectual property contained in those contributions, and personal
+information that you make publicly available in the record of the
+contribution pursuant to sign-offs under the Developer Certificate of
+Origin (). Some Projects require
+additional agreements or information pursuant to their intellectual
+property policies; in such cases we collect and store information
+related to your acceptance of those agreements. We may also collect
+information relating to your participation in technical, governance or
+other Project-related meetings.
+
+*Other Project-related Content.* The content you provide in relation to
+Projects also includes materials that you make publicly available in
+connection with Project development, collaboration and communication,
+such as on mailing lists, blogs, Project wiki pages and issue trackers,
+and related services.
+
+**Purposes and Legal Basis for Our Using of Your Personal Information**
+
+**Purposes and Legitimate Interests**
+
+SSS uses the personal information we collect for our legitimate business
+interests, which include the following purposes:
+
+- *Operating our Open-Source Projects*. To enable communication
+ between and among open source developers in the community; to
+ facilitate and document Project governance and technical
+ decision-making; to maintain, and make publicly available on a
+ perpetual basis, records regarding intellectual property provenance
+ and license compliance for Project contributions. See the
+ "Attribution, Provenance and Integrity" section above for more
+ information.
+
+- *Compliance*. To comply with legal obligations and requests. For
+ example, to comply with laws that compel us to disclose information
+ to public authorities, courts, law enforcement or regulators,
+ maintain records for a certain period, or maintain records
+ demonstrating enforcement and sublicensing of our trademarks and
+ those of our Projects.
+
+- *Business and Legal Operations*. As part of our general business and
+ legal operations (e.g., accounting, record keeping, and for other
+ business administration purposes), and as necessary to establish,
+ exercise and defend (actual and potential) legal claims.
+
+- *Prevent Misuse*. Where we believe necessary to investigate, prevent
+ or take action regarding illegal activities, suspected fraud,
+ situations involving potential threats to the safety of any person
+ or violations of the relevant Terms or this Privacy Policy.
+
+**Purposes and Legal Basis**
+
+| **Purposes of Processing (see above)** | **Legal Basis of Processing (EU Users)** |
+|-----------------------------------------|---------------------------------------------|
+| Operating our Open Source Projects | • Our Legitimate Business Interests
• Where Necessary to Enter into or Perform a Contract with You (upon your request, or as necessary to enable your participation in the Projects or to make the Services available)
• Compliance with Law
• As Necessary to Establish, Exercise and Defend Legal Claims |
+| Compliance | • Our Legitimate Business Interests
• Compliance with Law
• As Necessary to Establish, Exercise and Defend Legal Claims |
+| Business and Legal Operations | • Our Legitimate Business Interests
• Compliance with Law
• As Necessary to Establish, Exercise and Defend Legal Claims |
+| Prevent Misuse | • Our Legitimate Business Interests
• Compliance with Law
• As Necessary to Establish, Exercise and Defend Legal Claims |
+
+**Sharing of Personal Information**
+
+We disclose personal information as set forth below (excluding those
+mentioned in the *"Publicly Available information"* section below), and
+where individuals have otherwise consented:
+
+- *Publicly Available Information, including Your Contributions to
+ Open-Source Projects.* User names, other user ids, email addresses
+ and other attribution and affiliation information related to the
+ information and contributions that a user posts in conjunction with
+ or subject to an Open Source license are publicly available in the
+ relevant Project source code repositories. Your contributions to
+ Open-Source Projects, and certain of your other Content such as
+ comments and messages posted to public forums, are available to
+ other participants and users of our Projects and may be viewed
+ publicly. In some cases you may be able to provide Project or
+ contribution-related information directly to third-party sites and
+ services; these third parties are independent data controllers and
+ their use of your personal information is subject to their own
+ policies. For the avoidance of doubt, the above information is not
+ shared by us, but is made available to the public by yourself.
+
+- *Legally Required.* We may disclose your information if we are
+ required to do so by law (including to law enforcement in the U.S.
+ and other jurisdictions).
+
+- *Protection of Rights.* We may disclose information where we believe
+ it necessary to respond to claims asserted against us or, comply
+ with legal process (e.g., subpoenas or warrants), enforce or
+ administer our agreements and terms, for fraud prevention, risk
+ assessment, investigation, and protect the rights, property or
+ safety of SSS, its Users, participants in its events or Projects, or
+ others.
+
+**Data Security**
+
+We have implemented commercially reasonable precautions designed to
+protect the information we collect from loss, misuse, and unauthorized
+access, disclosure, alteration, and destruction. Please be aware that
+despite our best efforts, no data security measures can guarantee 100%
+security.
+
+You hereby agree to take steps to protect against unauthorized access to
+your passwords, phone, and computer by, among other things, signing off
+after using a shared computer, choosing robust passwords that nobody
+else knows or can easily guess, not using a password for more than one
+site or service, and keeping your log-ins and passwords private. We are
+not responsible for any lost, stolen, or compromised passwords or for
+any activity on your account via unauthorized password activity. You
+hereby agree to promptly notify us if you become aware that any
+information provided by or submitted to our Sites or through our
+Services is lost, stolen, or used without permission. at [Contact
+Us](https://www.sony-semicon.com/en/contact/index.html).
+
+**Retention of Your Personal Information**
+
+We generally keep personal information only for as long as required to
+fulfill the purposes for which it was collected. However, in some
+circumstances, we may retain personal information for other periods of
+time, for instance where we are required to do so in accordance with
+legal, tax and accounting requirements, or if required to do so by a
+legal process, legal authority, or other governmental entity having
+authority to make the request, for so long as required. In specific
+circumstances, we may also retain your personal information for longer
+periods of time corresponding to a statute of limitation, so that we
+have an accurate record of your dealings with us in the event of any
+complaints or challenges.
+
+**International Transfers**
+
+If you are located within the European Economic Area, the United Kingdom
+or Switzerland, you should note that your personal information will be
+transferred to countries outside these jurisdictions, including the
+United States. As of July 10, 2023, the U.S. is deemed by the European
+Union to provide adequate data protection for EU residents under the
+[EU-U.S. Data Privacy
+Framework](https://commission.europa.eu/document/fa09cbad-dd7d-4684-ae60-be03fcb0fddf_en).
+ Additionally, we have put in place European Commission approved
+Standard Contractual Clauses to provide for adequate safeguards to
+protect personal information transferred outside these jurisdictions,
+including between SSS entities. In addition, if personal information is
+transferred to third party service providers located outside these
+jurisdictions, we will take steps to ensure that your personal
+information receives the same level of protection as if it remained
+within these jurisdictions, including by entering into data transfer
+agreements, using the European Commission approved Standard Contractual
+Clauses or other safeguards as approved by the European Commission. You
+have a right to obtain details of the mechanism under which your
+personal information is transferred outside of the EU, and may do so by
+contacting us at [Contact
+Us](https://www.sony-semicon.com/en/contact/index.html).
+
+**Children's Privacy**
+
+Except as specifically indicated within a Site, we do not knowingly
+collect or solicit personal information from anyone under the applicable
+threshold age for children, or knowingly allow such persons to register.
+If we become aware that we have collected personal information from a
+child under the relevant age without parental consent, we take steps to
+delete that information. Where we specifically indicate that we collect
+personal information from children under such threshold age, we will
+obtain the parent or guardian's consent and provide adequate notice.
+
+**Links to Third Party Sites and Services**
+
+The Sites may contain links to third party sites or online services.
+Please refer to the privacy policies of the relevant third party
+websites or services to find out more about how they process and handle
+personal information.
+
+**Your Rights**
+
+***Data Subject Rights**.* Individuals in the European Economic Area and
+other jurisdictions have certain data protection rights under applicable
+law:
+
+- to obtain a copy of your personal information together with
+ information about how and on what legal basis that personal
+ information is processed;
+
+- to rectify inaccurate personal information (including to have
+ incomplete personal information completed);
+
+- to erase your personal information (in limited circumstances, such
+ as where it is no longer necessary in relation to the purposes for
+ which it was collected or processed);
+
+- to restrict processing of your personal information under certain
+ circumstances;
+
+- to export certain personal information in machine-readable format to
+ a third party (or to you) when we justify our processing on the
+ basis of your consent or the performance of a contract with you and
+ the processing is carried out by automated means;
+
+- to withdraw your consent to our processing of your personal
+ information (where that processing is based on your consent, without
+ affecting the lawfulness of processing based on consent before its
+ withdrawal);
+
+- to obtain, or see a copy of the appropriate safeguards under which
+ your personal information is transferred to a third country or
+ international organization; and
+
+- to object to our use and processing of your personal information
+ that is conducted on the basis of our legitimate interest. You also
+ have the right to object at any time to any processing of your
+ personal information for direct marketing purposes, including
+ profiling for marketing purposes.
+
+***Lodging a Complaint**.* You also have the right to lodge a complaint
+with your local supervisory authority for data protection, or privacy
+regulator. A list of data protection supervisory authorities is
+available [here](http://ec.europa.eu/newsroom/article29/item-detail.cfm?item_id=612080).
+
+***Submitting a Request**.* *To exercise the above rights or contact us
+with questions or complaints regarding our treatment of your personal
+information, contact us at: [Contact
+Us](https://www.sony-semicon.com/en/contact/index.html). Please note
+that we may request proof of identity, and we reserve the right to
+charge a fee where permitted by law, especially if your request is
+manifestly unfounded or excessive. We will respond to your request
+within the applicable timeframes set out by applicable law.
+
+**Supplemental Jurisdictional Privacy Notices**
+
+**Notice to California Residents**
+
+This California Privacy Notice supplements our Privacy Policy sets forth
+the disclosures and rights for California Consumers regarding their
+personal information, as required by the CCPA. Terms (including defined
+capitalized terms) used in this California Privacy Notice have the same
+meanings given in the CCPA, unless otherwise defined.
+
+California Consumer Rights. Subject to certain exceptions,
+as a California consumer, you may have the following rights regarding
+your CA Personal Information:
+
+- **Right to Know.** Request information regarding what Personal
+ Information we collect, use, disclose, and sell, including the
+ right to request that we provide you with the categories and /or
+ specific pieces of Personal Information we have collected about
+ you;
+
+- **Right to Delete.** Request deletion of the Personal Information we
+ collect about you;
+
+- **Right to Correct.** Request correction of inaccurate Personal
+ Information that we maintain about you;
+
+- **\"Do Not Sell or Share My Personal Information.\"** Request to
+ opt-out of the "sale" of your Personal Information or the
+ "sharing" of your Personal Information to a third party for
+ cross-contextual behavioral advertising (i.e., targeted
+ advertising). As we do not knowingly collect Personal Information
+ of residents younger than the age of 16, we also do not knowingly
+ sell or share their Personal Information for cross-contextual
+ behavioral advertising.
+
+- **\"Limit the Use and Disclosure of Sensitive Personal Information.\"**
+ A business must provide the Right to Limit the
+ Use and Disclosure of Sensitive Personal Information only when
+ Sensitive Personal Information is collected or processed for the
+ purpose of inferring characteristics about a consumer or does not
+ fall under certain statutory exceptions. Our use of any Sensitive
+ Personal Information falls within an exception, so we do not offer
+ this right at this time.
+
+**Agents.** If you are an authorized representative
+submitting a request on a consumer's behalf, please complete the
+applicable request per the instructions below. We will follow up to
+request a signed, written permission signed by the individual who is the
+subject of the request authorizing you to make the request on their
+behalf. The written permission must state your full legal name, the full
+legal name of the individual who is the subject of the request, and a
+clear description of the permission granted. Alternatively, you may
+submit a copy of a power of attorney under applicable state law. In
+either case, please also indicate in your email the nature of your
+request. The consumer's identity, in addition to your own, will need to
+be independently verified in order for us to be able to fulfill your
+request. We may also ask the consumer to directly confirm with us that
+they provided you permission to submit the request. Please keep in mind
+that if we do not receive adequate proof that you are authorized to act
+on the consumer's behalf, we may deny the request.
+
+**Verifying Requests.** In your request, you must provide
+enough information to allow us to verify you are the person about whom
+we collected Personal Information, or their authorized representative.
+You must also describe your request with enough detail so that we can
+understand, evaluate and respond to it. We will only use the information
+you provide in a request to verify your identity.
+
+When you exercise your Right to Know, Right to Delete, and/or Right to
+Correct, we may ask that you provide us with additional information in
+order to verify your identity and fulfill your request. If we are unable
+to verify your identity, we will not be able to process the request.
+
+**Exercising Your Rights.**
+
+**Right to Know; Right to Delete; Right to Correct**
+
+> If you are a California Consumer and would like to exercise your Right
+> to Know, Right to Delete, and/or Right to Correct, please submit your
+> request using [this
+> link](https://www.sony-semicon.com/en/contact/index.html) or you may
+> call us toll-free at 1-833-681-9900.
+
+**Do Not Sell or Share for Cross Context Behavioral Advertising**
+
+**Right to Opt-Out of Sale/Sharing**
+
+We do not Sell or Share personal information for cross-contextual
+behavioral advertising, so we do not offer this right at this
+time.
+
+**Data Retention.** We generally keep personal information
+only for as long as required to fulfill the purposes for which it was
+collected. However, in some circumstances, we may retain personal
+information for other periods of time, for instance where we are
+required to do so in accordance with legal, tax and accounting
+requirements, or if required to do so by a legal process, legal
+authority, or other governmental entity having authority to make the
+request, for so long as required. In specific circumstances, we may
+also retain your personal information for longer periods of time
+corresponding to a statute of limitation, so that we have an accurate
+record of your dealings with us in the event of any complaints or
+challenges.
+
+**Data Reporting**
+
+Click [here](https://electronics.sony.com/DSR-metrics) to
+access our data reporting metrics for the previous calendar year.
+
+**Right to Non-Discrimination for the Exercise of a Consumer's Privacy
+Rights**
+
+California Consumers have the right to not receive discriminatory
+treatment for exercising CCPA rights. We will not discriminate against
+you for exercising your CCPA rights.
+
+**Notice of Financial Incentive**
+
+Under California regulations, if we offer certain loyalty or similar
+program(s) directly or reasonably related to the collection, retention
+or deletion of your Personal Information, such program may be considered
+a "financial incentive". In such case, we will be required to make
+additional disclosures to you, which we will provide when you agree to
+participate.
+
+**Personal Information We Collect & Purposes for Collection**
+
+The Personal Information we collect about you will depend upon how you
+interact with us. Accordingly, we may not collect all of the below
+information about you. In addition to the below, we may collect and/or
+use additional types of information and will do so after providing
+notice to you and obtaining your consent to the extent such notice and
+consent is required by applicable law.
+
+We may have used Personal Information for the business or commercial
+purposes described in Table 1:
+
+| Categories of Personal Information Collected | Business or Commercial Purposes for Collection of Personal Information | Categories of Sources from Which Personal Information Was Collected | Categories of Third Parties to Whom We May Disclose Personal Information for a Business Purpose | Categories of Third Parties to Whom this Type of Personal Information is Sold or Shared for Cross Context Behavioral Advertising |
+|---|---|---|---|---|
+| Identifiers
This category includes information such as name, phone number, mailing address, email, DOB, and online or device identifiers such as Device IDs and IP address. | We may use this type of information to:
Provide requested services; process transactions; respond to your inquiries; provide you updates on your account, your products and our websites, products and services; prevent fraud and for internal business, legal and compliance purposes | Websites and/ or data subject | Subsidiaries and affiliates off SSS and Legal Authorities (as required by law) | We do not sell or share this type of information for cross-context behavioral advertising |
+
+**Additional Notice to California Residents:**
+
+If you are a California resident, under the California "Shine the Light"
+law, you have the right to receive: (a) information identifying any
+third party companies to which we may have disclosed, within the past
+year, personal information pertaining to you and your family for that
+company\'s direct marketing purposes; and (b) a description of the
+categories of personal information disclosed. To obtain such
+information, please email your request to
+[privacy\@am.sony.com](mailto:privacy@am.sony.com), and
+include your name, email address, mailing address or zip code, and a
+reference to "Your California Privacy Rights." We are not responsible
+for requests that are not labeled or sent properly, or do not have
+complete information.
+
+**Notice to Quebec (Canada) Residents** This notice sets
+forth disclosures and rights for consumers residing in Québec regarding
+their personal information, as required by the Québec's Data Privacy Law
+25.
+
+**Location Tracking:** We may use technologies which collect information
+about your general location, such as the country in which you are
+located; however, we do not track your location without your consent.
+
+**Consumer Rights:**
+
+Subject to certain exceptions, you may have the following rights
+regarding your personal information:
+
+- **Right to Access and Request Information On Data Processing**
+ Request information about our data
+ processing activities, namely what personal information was
+ collected from you and how we process it. You may ask us to
+ clarify the categories of persons that have access to your
+ personal information and the applicable retention period for that
+ information.
+
+- **Right to Rectify.** Request rectification of
+ inaccurate personal information we maintain about you.
+
+- **Rights Regarding the Use of Automated Decision-making.**
+ You have the right to request that
+ we tell you if we use your personal information to render a
+ decision based exclusively on automated processing of such
+ information and additional information about such processing.
+ However, Sony does not use personal information to render any
+ decisions based exclusively on an automated processing of such
+ information.
+
+- **Right to Withdraw Consent.** Request to withdraw
+ your consent to our collection, use, and disclosure of personal
+ information at any time. If you withdraw your consent, we may not
+ be able to provide certain products or services to you. We will
+ advise you if this is the case at the time you withdraw your
+ consent.
+
+**Exercising your rights:** If you are a Quebec resident and wish to
+exercise your right(s), please: submit your request here: [**SOCAN
+Privacy Request Webform**](https://sony-privacyportal.my.onetrust.com/webform/ae4501a4-318f-4210-bddc-9a8bc984c5a6/0c8ea26c-76a5-4bcd-9ef5-3597f99e021a); or you may call us at: 1-888-494-7669.
+
+For requests to access, in order to have us provide specific pieces of
+information, we will require a signed declaration under penalty of
+perjury that you are the consumer whose personal information is the
+subject of the request.
+
+Our Privacy Officer is in charge of the protection of personal
+information.
+
+**Contact information for Sony of Canada Privacy Officer.**
+
+Sony of Canada ULC,
+
+Attn: Privacy Officer, Law Department
+
+2235 Sheppard Avenue East, Suite 800 Toronto, ON M2J 5B5
+
+Telephone: 1-888-494-7669 (toll free within Canada)
+
+Email: [**privacy\@am.sony.com**](mailto:privacy@am.sony.com)
+
+You may submit a complaint to the Commision d'accès à l'information du
+Québec (CAI) by visiting:
+[**https://www.cai.gouv.qc.ca/a-propos/nous-joindre/**](https://www.cai.gouv.qc.ca/a-propos/nous-joindre/).
+
+**Contact Us**
+
+If you have any questions about our practices or this Privacy Policy,
+please contact us at: [Contact Us](https://www.sony-semicon.com/en/contact/index.html):
+
+Sony Semiconductor Solutions Corporation, 4-14-1 Asahi-cho, Atsugi-shi,
+Kanagawa, 243-0014 Japan.
+
+For residents of the United States or Canada, please contact us at:
+privacy\@am.sony.com
+
+For residents of the EEA or Switzerland, please contact us at:
+privacyoffice.SEU\@sony.com
+
+Our representative in the EEA and Switzerland is Sony Europe BV, a Dutch
+company, whose business address is Taurusavenue 16, 2132LS Hoofddorp,
+the Netherlands.
+
+For residents of the UK, please contact us at:
+privacyoffice.SEU\@sony.com.
+
+Our representative in the UK is Sony Europe BV, a Dutch company, whose
+UK branch has its business address in The Privacy Office, The Heights,
+Brooklands, Weybridge, Surrey KT13 0XW, The United Kingdom.
+
+**Changes to the Privacy Policy**
+
+This Policy is current as of the effective date set forth above. If we
+change our privacy policies and procedures, we will post those changes
+on this page and/or continue to provide access to a copy of the prior
+version. If we make any changes to this Privacy Policy that materially
+change how we treat your personal information, we will endeavor to
+provide you with reasonable notice of such changes, such as via
+prominent notice on our Sites.
diff --git a/configs/nuttx.config b/configs/nuttx.config
index d9822616..96075fd9 100644
--- a/configs/nuttx.config
+++ b/configs/nuttx.config
@@ -1453,7 +1453,7 @@ CONFIG_FSUTILS_PASSWD_KEY4=0x9abcdef0
# CONFIG_INTERPRETERS_MINIBASIC is not set
# CONFIG_INTERPRETERS_QUICKJS is not set
CONFIG_INTERPRETERS_WAMR=y
-CONFIG_INTERPRETERS_WAMR_VERSION="WAMR-2.1.2"
+CONFIG_INTERPRETERS_WAMR_VERSION="WAMR-2.2.0"
# CONFIG_INTERPRETERS_IWASM_TASK is not set
CONFIG_INTERPRETERS_WAMR_AOT=y
CONFIG_INTERPRETERS_WAMR_FAST=y
diff --git a/docs/about/release_process.rst b/docs/about/release_process.rst
index 1c8501ce..365ecc97 100644
--- a/docs/about/release_process.rst
+++ b/docs/about/release_process.rst
@@ -28,7 +28,7 @@ of the different relevant artifacts:
When creating and publishing a GitHub release UI,
targetting the ``main`` branch.
-The tag ``releases/v``
+The tag ``v``
with the same value from ``scripts/rules.mk`` must be created.
The field version is the value defined in ``rules.mk``
where ``version`` must follow `semantic versioning`_.
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index f6dff637..efe8a02f 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -60,7 +60,7 @@ EVP Agent requires the following tools:
It also requires the following libraries:
- * `WAMR`_ 2.1.2
+ * `WAMR`_ 2.2.0
* `MbedTLS`_ 3.6.2
* `Flatcc`_ 0.6.1
@@ -89,7 +89,7 @@ To build the AoT and XiP modules, WAMRC is required.
This requires:
* `WASI-SDK`_ 24
- * `WAMRC`_ 2.1.2
+ * `WAMRC`_ 2.2.0
Package installation
********************
diff --git a/include/evp/agent.h b/include/evp/agent.h
index 482cd95c..1e7b94bd 100644
--- a/include/evp/agent.h
+++ b/include/evp/agent.h
@@ -200,6 +200,7 @@ enum evp_agent_status evp_agent_get_status(struct evp_agent_context *ctxt);
int evp_agent_loop(struct evp_agent_context *ctxt);
int evp_agent_stop(struct evp_agent_context *ctxt);
void evp_agent_free(struct evp_agent_context *ctxt);
+void evp_agent_wakeup(const char *name);
/**
* Set the platform methods
diff --git a/include/evp/agent_config.h b/include/evp/agent_config.h
new file mode 100644
index 00000000..11535ebb
--- /dev/null
+++ b/include/evp/agent_config.h
@@ -0,0 +1,59 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Sony Semiconductor Solutions Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef EVP_CONFIG_H
+#define EVP_CONFIG_H
+
+#include
+
+#include
+
+enum config_key {
+ EVP_CONFIG_TLS_CA_CERT,
+ EVP_CONFIG_MQTT_HOST,
+ EVP_CONFIG_MQTT_PORT,
+ EVP_CONFIG_MQTT_TLS_CA_CERT,
+ EVP_CONFIG_MQTT_TLS_CLIENT_CERT,
+ EVP_CONFIG_MQTT_TLS_CLIENT_KEY,
+ EVP_CONFIG_MQTT_MFS_QOS,
+ EVP_CONFIG_HTTPS_CA_CERT,
+ EVP_CONFIG_MQTT_PROXY_HOST,
+ EVP_CONFIG_MQTT_PROXY_PORT,
+ EVP_CONFIG_MQTT_PROXY_USERNAME,
+ EVP_CONFIG_MQTT_PROXY_PASSWORD,
+ EVP_CONFIG_HTTP_PROXY_HOST,
+ EVP_CONFIG_HTTP_PROXY_PORT,
+ EVP_CONFIG_HTTP_PROXY_USERNAME,
+ EVP_CONFIG_HTTP_PROXY_PASSWORD,
+ EVP_CONFIG_REGISTRY_AUTH,
+ EVP_CONFIG_REPORT_STATUS_INTERVAL_MIN_SEC,
+ EVP_CONFIG_REPORT_STATUS_INTERVAL_MAX_SEC,
+ EVP_CONFIG_CONFIGURATION_ID,
+ EVP_CONFIG_TRANSPORT_QUEUE_LIMIT,
+#if defined(CONFIG_EVP_MODULE_IMPL_DOCKER)
+ EVP_CONFIG_DOCKER_TLS_CA_CERT,
+ EVP_CONFIG_DOCKER_TLS_CLIENT_CERT,
+ EVP_CONFIG_DOCKER_TLS_CLIENT_KEY,
+#endif /* defined(CONFIG_EVP_MODULE_IMPL_DOCKER) */
+ EVP_CONFIG_PK_FILE,
+ EVP_CONFIG_IOT_PLATFORM,
+ EVP_CONFIG_RAWCONTAINERSPEC_SIGNVERIF_PUBKEY,
+};
+
+struct config {
+ enum config_key key;
+ void *value;
+ size_t size;
+ void (*free)(void *);
+};
+
+/* Functions that call the backend-specific implementations */
+int load_config_impl(struct config *, void **, size_t *);
+void unload_config_impl(struct config *, void *, size_t);
+struct config *get_config_impl(enum config_key);
+bool config_is_pk_file(enum config_key key);
+
+#endif /* EVP_CONFIG_H */
diff --git a/include/internal/config_impl.h b/include/internal/config_impl.h
index d3c23125..3769082a 100644
--- a/include/internal/config_impl.h
+++ b/include/internal/config_impl.h
@@ -9,21 +9,10 @@
*/
#include
-#include "evp_config.h"
+#include
-struct config {
- enum config_key key;
- void *value;
- size_t size;
- void (*free)(void *);
-};
+#include "evp_config.h"
bool is_config_optional(enum config_key);
int config_load_pk_file(const char *, void **, size_t *);
void config_unload_pk_file(void *, size_t);
-
-/* Functions that call the backend-specific implementations */
-int load_config_impl(struct config *, void **, size_t *);
-void unload_config_impl(struct config *, void *, size_t);
-struct config *get_config_impl(enum config_key);
-bool config_is_pk_file(enum config_key key);
diff --git a/include/internal/evp_config.h b/include/internal/evp_config.h
index e742d099..6e3b8575 100644
--- a/include/internal/evp_config.h
+++ b/include/internal/evp_config.h
@@ -12,43 +12,13 @@
#include
#include
+#include
+
#define MIN_REPORT_INTERVAL_SEC 3
#define MAX_REPORT_INTERVAL_SEC 180
#define DEFAULT_MQTT_MFS_QOS 1
#define DEFAULT_TRANSPORT_QUEUE_LIMIT CONFIG_EVP_MQTT_SEND_BUFF_SIZE
-enum config_key {
- EVP_CONFIG_TLS_CA_CERT,
- EVP_CONFIG_MQTT_HOST,
- EVP_CONFIG_MQTT_PORT,
- EVP_CONFIG_MQTT_TLS_CA_CERT,
- EVP_CONFIG_MQTT_TLS_CLIENT_CERT,
- EVP_CONFIG_MQTT_TLS_CLIENT_KEY,
- EVP_CONFIG_MQTT_MFS_QOS,
- EVP_CONFIG_HTTPS_CA_CERT,
- EVP_CONFIG_MQTT_PROXY_HOST,
- EVP_CONFIG_MQTT_PROXY_PORT,
- EVP_CONFIG_MQTT_PROXY_USERNAME,
- EVP_CONFIG_MQTT_PROXY_PASSWORD,
- EVP_CONFIG_HTTP_PROXY_HOST,
- EVP_CONFIG_HTTP_PROXY_PORT,
- EVP_CONFIG_HTTP_PROXY_USERNAME,
- EVP_CONFIG_HTTP_PROXY_PASSWORD,
- EVP_CONFIG_REGISTRY_AUTH,
- EVP_CONFIG_REPORT_STATUS_INTERVAL_MIN_SEC,
- EVP_CONFIG_REPORT_STATUS_INTERVAL_MAX_SEC,
- EVP_CONFIG_CONFIGURATION_ID,
- EVP_CONFIG_TRANSPORT_QUEUE_LIMIT,
-#if defined(CONFIG_EVP_MODULE_IMPL_DOCKER)
- EVP_CONFIG_DOCKER_TLS_CA_CERT,
- EVP_CONFIG_DOCKER_TLS_CLIENT_CERT,
- EVP_CONFIG_DOCKER_TLS_CLIENT_KEY,
-#endif /* defined(CONFIG_EVP_MODULE_IMPL_DOCKER) */
- EVP_CONFIG_PK_FILE,
- EVP_CONFIG_IOT_PLATFORM,
- EVP_CONFIG_RAWCONTAINERSPEC_SIGNVERIF_PUBKEY,
-};
-
struct config;
struct config *get_config(enum config_key);
diff --git a/scripts/cmake-wasm-micro-runtime.sh b/scripts/cmake-wasm-micro-runtime.sh
index 578d7a04..ca082a4d 100755
--- a/scripts/cmake-wasm-micro-runtime.sh
+++ b/scripts/cmake-wasm-micro-runtime.sh
@@ -44,14 +44,18 @@ xtensa)
;;
esac
+WAMR_CFLAGS="\
+-DAPP_THREAD_STACK_SIZE_DEFAULT=131072 \
+-DAPP_THREAD_STACK_SIZE_MIN=131072 \
+"
cmake \
-DCMAKE_INSTALL_PREFIX="$prefix" \
-DCMAKE_C_COMPILER=${CC:-cc} \
-DCMAKE_CXX_COMPILER=${CXX:-c++} \
- -DCMAKE_C_FLAGS="${CFLAGS}" \
+ -DCMAKE_C_FLAGS="${WAMR_CFLAGS} ${CFLAGS}" \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DWAMR_BUILD_TARGET=${arch:-X86_64} \
- -DWAMR_BUILD_SHARED=0 \
+ -DWAMR_BUILD_SHARED=1 \
-DWAMR_BUILD_INTERP=1 \
-DWAMR_BUILD_FAST_INTERP=1 \
-DWAMR_BUILD_JIT=0 \
diff --git a/scripts/mk-agent-deb.sh b/scripts/mk-agent-deb.sh
index 216ad666..327d7287 100755
--- a/scripts/mk-agent-deb.sh
+++ b/scripts/mk-agent-deb.sh
@@ -106,6 +106,7 @@ License: BSD-3-Clause
EOF
mkdir -p dist/usr/bin
+mkdir -p dist/usr/lib
mkdir -p dist/var/lib/evp_agent
mkdir -p dist/lib/systemd/system
@@ -129,5 +130,6 @@ WantedBy=multi-user.target
EOF
cp bin/evp_agent dist/usr/bin/evp_agent
+cp lib/libiwasm.so dist/usr/lib/libiwasm.so
dpkg-deb --build dist evp-agent-${version}_$arch.deb
diff --git a/scripts/mk-agent-sdk-deb.sh b/scripts/mk-agent-sdk-deb.sh
new file mode 100755
index 00000000..f25d6ec7
--- /dev/null
+++ b/scripts/mk-agent-sdk-deb.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+
+set -e
+
+arch=amd64
+version=0.0.0
+
+usage()
+{
+ echo "usage: mk-agent-sdk-deb [-a arch] [-V version]" >&2
+ exit 1
+}
+
+while test $# -gt 0; do
+ case "$1" in
+ -a)
+ arch=${2?`usage`}
+ shift 2
+ ;;
+ -V)
+ version=${2?`usage`}
+ shift 2
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+
+rm -rf dist
+trap "rm -rf dist $$.tmp" EXIT HUP INT TERM
+
+case $arch in
+aarch64)
+ debarch=arm64
+ ;;
+x86_64)
+ debarch=amd64
+ ;;
+esac
+
+# create deb package
+mkdir -p dist/DEBIAN
+
+cat > dist/DEBIAN/control <
+Depends: libc6 (>= 2.35)
+Recommends: evp-agent
+Vcs-Browser: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform
+Vcs-Git: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform
+Description: Software Development Kit for EVP Agent
+ This package provides the required interfaces and libraries
+ to embed an EVP Agent within a user-built application
+EOF
+
+cat > dist/DEBIAN/copyright <
+
+Files: *
+Copyright: 2024 Sony Semiconductor Solutions Corporation
+License: Apache-2.0
+
+Files: src/flatcc
+Copyright: 2015 Mikkel F. Jørgensen, dvide.com
+License: Apache-2.0
+
+Files: include/internal/queue.h
+Copyright: (c) 1991, 1993 The Regents of the University of California.
+License: BSD-3-Clause
+EOF
+
+mkdir -p dist/usr/lib/$arch-linux-gnu
+mkdir -p dist/usr/include/evp
+
+cp lib/libevp-agent.a dist/usr/lib/$arch-linux-gnu/
+cp lib/libevp-utils.a dist/usr/lib/$arch-linux-gnu/
+cp \
+ include/evp/agent.h\
+ include/evp/agent_config.h\
+ include/evp/sdk_base.h\
+ include/evp/sdk_blob_azure.h\
+ include/evp/sdk_blob_evp.h\
+ include/evp/sdk_blob.h\
+ include/evp/sdk_blob_http_ext.h\
+ include/evp/sdk_blob_http.h\
+ include/evp/sdk.h\
+ include/evp/sdk_sys.h\
+ include/evp/sdk_types.h\
+ dist/usr/include/evp/
+
+dpkg-deb --build dist libevp-agent-sdk-dev-${version}_$debarch.deb
diff --git a/scripts/mk-app-sdk-deb.sh b/scripts/mk-app-sdk-deb.sh
new file mode 100755
index 00000000..2ae469f6
--- /dev/null
+++ b/scripts/mk-app-sdk-deb.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+
+set -e
+
+arch=amd64
+version=0.0.0
+
+usage()
+{
+ echo "usage: mk-app-sdk-deb [-a arch] [-V version]" >&2
+ exit 1
+}
+
+while test $# -gt 0; do
+ case "$1" in
+ -a)
+ arch=${2?`usage`}
+ shift 2
+ ;;
+ -V)
+ version=${2?`usage`}
+ shift 2
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+
+rm -rf dist
+trap "rm -rf dist $$.tmp" EXIT HUP INT TERM
+
+case $arch in
+aarch64)
+ debarch=arm64
+ ;;
+x86_64)
+ debarch=amd64
+ ;;
+esac
+
+# create deb package
+mkdir -p dist/DEBIAN
+
+cat > dist/DEBIAN/control <
+Depends: libc6 (>= 2.35)
+Recommends: evp-agent
+Vcs-Browser: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform
+Vcs-Git: https://github.com/SonySemiconductorSolutions/edge-virtualization-platform
+Description: Software Development Kit for EVP applications
+ This package provides the required interfaces and libraries
+ to build EVP applications.
+EOF
+
+cat > dist/DEBIAN/copyright <
+
+Files: *
+Copyright: 2024 Sony Semiconductor Solutions Corporation
+License: Apache-2.0
+
+Files: src/flatcc
+Copyright: 2015 Mikkel F. Jørgensen, dvide.com
+License: Apache-2.0
+
+Files: include/internal/queue.h
+Copyright: (c) 1991, 1993 The Regents of the University of California.
+License: BSD-3-Clause
+EOF
+
+mkdir -p dist/usr/lib/$arch-linux-gnu
+mkdir -p dist/usr/include/evp
+
+cp lib/libevp-app-sdk.a dist/usr/lib/$arch-linux-gnu/
+cp \
+ include/evp/sdk_base.h\
+ include/evp/sdk_blob_azure.h\
+ include/evp/sdk_blob_evp.h\
+ include/evp/sdk_blob.h\
+ include/evp/sdk_blob_http_ext.h\
+ include/evp/sdk_blob_http.h\
+ include/evp/sdk.h\
+ include/evp/sdk_sys.h\
+ include/evp/sdk_types.h\
+ dist/usr/include/evp/
+
+dpkg-deb --build dist libevp-app-sdk-dev-${version}_$debarch.deb
diff --git a/scripts/rules.mk b/scripts/rules.mk
index 3b44ac59..827f5516 100644
--- a/scripts/rules.mk
+++ b/scripts/rules.mk
@@ -7,7 +7,7 @@
all:
# Macros related to the version of the agent
-VERSION = 1.45.0
+VERSION = 1.48.0
SDK_VERSION = 1.0.0
# Default value for configuration macros
diff --git a/src/evp_agent/config_env.c b/src/evp_agent/config_env.c
index 77a38d9b..264b8b22 100644
--- a/src/evp_agent/config_env.c
+++ b/src/evp_agent/config_env.c
@@ -14,6 +14,8 @@
#include
#include
+#include
+
#include
#include
#include
diff --git a/src/libevp-agent/agent_event.c b/src/libevp-agent/agent_event.c
index 741781a3..9314f543 100644
--- a/src/libevp-agent/agent_event.c
+++ b/src/libevp-agent/agent_event.c
@@ -13,6 +13,7 @@
/* clang-format off */
static const char(*const list[]) = {
"agent/status",
+ "agent/conn_status",
"blob/result",
"deployment/reconcileStatus",
"mqtt/sync/err",
diff --git a/src/libevp-agent/blob_type_evp_rpc.c b/src/libevp-agent/blob_type_evp_rpc.c
index 4994d0b7..f3ad3013 100644
--- a/src/libevp-agent/blob_type_evp_rpc.c
+++ b/src/libevp-agent/blob_type_evp_rpc.c
@@ -158,12 +158,10 @@ blob_type_evp_load(const struct evp_agent_context *agent,
}
if (!entry_obj) {
- xlog_info("No cache hit for instanceName=%s",
- wk->module_instance_name);
- xlog_debug("No cache hit for "
- "instanceName=%s, remoteName=%s, storageName=%s",
- wk->module_instance_name, wk->remote_name,
- wk->storage_name);
+ xlog_info("No cache hit for "
+ "instanceName=%s, remoteName=%s, storageName=%s",
+ wk->module_instance_name, wk->remote_name,
+ wk->storage_name);
goto end;
}
diff --git a/src/libevp-agent/docker.c b/src/libevp-agent/docker.c
index 07ca8bfe..815c9224 100644
--- a/src/libevp-agent/docker.c
+++ b/src/libevp-agent/docker.c
@@ -121,7 +121,7 @@ static int
docker_stream_fn(unsigned http_status, char **bufp, int offset, int datend,
int *buflen, void *vp)
{
- const void *p = (*bufp) + offset;
+ const char *p = (*bufp) + offset;
size_t n = datend - offset;
struct docker_stream_state *state = vp;
diff --git a/src/libevp-agent/evp_agent.c b/src/libevp-agent/evp_agent.c
index b1642279..0c64d9c1 100644
--- a/src/libevp-agent/evp_agent.c
+++ b/src/libevp-agent/evp_agent.c
@@ -298,6 +298,9 @@ evp_agent_loop(struct evp_agent_context *ctxt)
xlog_info("agent connected to hub");
evp_agent_notification_publish(
ctxt, "agent/status", "connected");
+ evp_agent_notification_publish(
+ ctxt, "agent/conn_status",
+ "connected");
}
} else {
@@ -306,6 +309,9 @@ evp_agent_loop(struct evp_agent_context *ctxt)
xlog_info("agent disconnected from hub");
evp_agent_notification_publish(
ctxt, "agent/status", "disconnected");
+ evp_agent_notification_publish(
+ ctxt, "agent/conn_status",
+ "connecting");
}
}
evp_agent_unlock();
@@ -335,6 +341,10 @@ evp_agent_loop(struct evp_agent_context *ctxt)
case EVP_AGENT_STATUS_DISCONNECTING:
if (connections_get_count() == 0) {
ctxt->status = EVP_AGENT_STATUS_DISCONNECTED;
+ ret |= evp_agent_notification_publish(
+ ctxt, "agent/status", "disconnected");
+ ret |= evp_agent_notification_publish(
+ ctxt, "agent/conn_status", "disconnected");
}
break;
default:
@@ -444,6 +454,12 @@ evp_agent_free(struct evp_agent_context *ctxt)
free(ctxt);
}
+void
+evp_agent_wakeup(const char *name)
+{
+ main_loop_wakeup(name);
+}
+
int
evp_agent_connect(struct evp_agent_context *ctxt)
{
@@ -482,14 +498,20 @@ evp_agent_disconnect(struct evp_agent_context *ctxt)
int rv = transport_disconnect(ctxt->transport_ctxt);
// Disconnect network connections
connections_set_status(false);
+ const char *conn_status;
if (connections_get_count() == 0) {
ctxt->status = EVP_AGENT_STATUS_DISCONNECTED;
+ conn_status = "disconnected";
} else {
ctxt->status = EVP_AGENT_STATUS_DISCONNECTING;
+ conn_status = "disconnecting";
}
main_loop_wakeup(__func__);
evp_agent_unlock();
- evp_agent_notification_publish(ctxt, "agent/status", "disconnected");
+ rv |= evp_agent_notification_publish(ctxt, "agent/status",
+ "disconnected");
+ rv |= evp_agent_notification_publish(ctxt, "agent/conn_status",
+ conn_status);
return rv;
}
diff --git a/src/libevp-agent/hash.c b/src/libevp-agent/hash.c
index 9f090d3e..93691c96 100644
--- a/src/libevp-agent/hash.c
+++ b/src/libevp-agent/hash.c
@@ -22,6 +22,7 @@ check_hash(struct module *module, const unsigned char *ref, size_t ref_len,
char **result)
{
int ret;
+ unsigned char *calc = NULL;
mbedtls_md_type_t type = MBEDTLS_MD_SHA256;
const mbedtls_md_info_t *info = mbedtls_md_info_from_type(type);
@@ -32,11 +33,12 @@ check_hash(struct module *module, const unsigned char *ref, size_t ref_len,
const char *md_name = mbedtls_md_get_name(info);
const size_t byte_size = mbedtls_md_get_size(info);
if (ref_len != byte_size) {
- return EINVAL;
+ *result = xstrdup("Module hash mismatch");
+ ret = 0;
+ goto finish;
}
- unsigned char *calc = malloc(byte_size);
- if (!calc) {
+ if (!(calc = malloc(byte_size))) {
return ENOMEM;
}
@@ -70,9 +72,9 @@ check_hash(struct module *module, const unsigned char *ref, size_t ref_len,
goto finish;
}
char *r = bin_array_to_hexchar(ref, byte_size, ref_string,
- sizeof(ref_string));
+ byte_size * 2 + 1);
char *c = bin_array_to_hexchar(calc, byte_size, calc_string,
- sizeof(calc_string));
+ byte_size * 2 + 1);
if (!r || !c) {
xlog_error("bin_array_to_hexchar failed:%s%s",
diff --git a/src/libevp-agent/hub/tb/tb.c b/src/libevp-agent/hub/tb/tb.c
index eb859bbc..efc87806 100644
--- a/src/libevp-agent/hub/tb/tb.c
+++ b/src/libevp-agent/hub/tb/tb.c
@@ -436,13 +436,8 @@ get_done_evp1(EVP_RPC_ID id, void *cb_data, void *payload, uint32_t delay,
// TODO: Replace assert (programming error)
assert(error == 0);
- // Don't print deployment data in INFO level
- // Since it could contain user data
- xlog_debug("get_done (in %" PRIu32 " ms): id=%ju, payload=%s", delay,
- (uintmax_t)id, (const char *)payload);
-
- xlog_info("get_done (in %" PRIu32 " ms): id=%ju, length=%zu", delay,
- (uintmax_t)id, strlen(payload));
+ xlog_info("get_done (in %" PRIu32 " ms): id=%ju, payload=%s", delay,
+ (uintmax_t)id, (const char *)payload);
/* Parse payload and process shared attributes. */
/*
@@ -477,13 +472,8 @@ get_done_evp2(EVP_RPC_ID id, void *cb_data, void *payload, uint32_t delay,
// TODO: Replace assert (programming error)
assert(error == 0);
- // Don't print deployment data in INFO level
- // Since it could contain user data
- xlog_debug("get_done (in %" PRIu32 " ms): id=%ju, payload=%s", delay,
- (uintmax_t)id, (const char *)payload);
-
- xlog_info("get_done (in %" PRIu32 " ms): id=%ju, length=%zu", delay,
- (uintmax_t)id, strlen(payload));
+ xlog_info("get_done (in %" PRIu32 " ms): id=%ju, payload=%s", delay,
+ (uintmax_t)id, (const char *)payload);
/* Parse payload and process shared attributes. */
/*
diff --git a/src/libevp-agent/ioutil.c b/src/libevp-agent/ioutil.c
index a174d9d9..e0a6c5e7 100644
--- a/src/libevp-agent/ioutil.c
+++ b/src/libevp-agent/ioutil.c
@@ -19,7 +19,7 @@ readall(int fd, void *buf, size_t sz)
if (want == 0) {
break; /* done */
}
- ssz = read(fd, buf + done_bytes, want);
+ ssz = read(fd, (char *)buf + done_bytes, want);
if (ssz == 0) {
break; /* EOF */
}
diff --git a/src/libevp-agent/manifest.c b/src/libevp-agent/manifest.c
index 165313a6..62546175 100644
--- a/src/libevp-agent/manifest.c
+++ b/src/libevp-agent/manifest.c
@@ -1342,13 +1342,13 @@ dump_global(void)
if (g_evp_global.desired) {
char *p =
json_serialize_to_string_pretty(g_evp_global.desired);
- xlog_debug("DESIRED: %s", p);
+ xlog_info("DESIRED: %s", p);
json_free_serialized_string(p);
}
if (g_evp_global.current) {
char *p =
json_serialize_to_string_pretty(g_evp_global.current);
- xlog_debug("CURRENT: %s", p);
+ xlog_info("CURRENT: %s", p);
json_free_serialized_string(p);
}
}
diff --git a/src/libevp-agent/module_instance.c b/src/libevp-agent/module_instance.c
index 8092433b..c3f3ff4a 100644
--- a/src/libevp-agent/module_instance.c
+++ b/src/libevp-agent/module_instance.c
@@ -884,9 +884,14 @@ module_instance_forward_fn(const void *message, const void *module_instance)
m->name, msg->topic, subscribe_alias->name,
(int)msg->bloblen, (const char *)msg->blob);
#endif
- sdk_queue_message(m->name, subscribe_alias->name,
- msg->blob, msg->bloblen);
- msg->reason = EVP_MESSAGE_SENT_CALLBACK_REASON_SENT;
+ if (sdk_queue_message(m->name, subscribe_alias->name,
+ msg->blob, msg->bloblen)) {
+ msg->reason =
+ EVP_MESSAGE_SENT_CALLBACK_REASON_ERROR;
+ } else {
+ msg->reason =
+ EVP_MESSAGE_SENT_CALLBACK_REASON_SENT;
+ }
}
}
diff --git a/src/libevp-agent/module_instance_impl_spawn.c b/src/libevp-agent/module_instance_impl_spawn.c
index 7238f0bb..d1c36c2b 100644
--- a/src/libevp-agent/module_instance_impl_spawn.c
+++ b/src/libevp-agent/module_instance_impl_spawn.c
@@ -123,7 +123,7 @@ module_instance_impl_spawn_stop(struct module_instance *m)
goto stopped;
}
- return EBUSY;
+ return EAGAIN;
stopped:
m->stopped = true;
diff --git a/src/libevp-agent/module_log_queue.c b/src/libevp-agent/module_log_queue.c
index db74710e..eeb6b06b 100644
--- a/src/libevp-agent/module_log_queue.c
+++ b/src/libevp-agent/module_log_queue.c
@@ -156,7 +156,7 @@ module_log_queue_put(const char *instance_id, const char *stream,
}
size_t
-module_log_queue_write(void *data, size_t len)
+module_log_queue_write(char *data, size_t len)
{
struct queue *self = &g_context;
size_t ret = 0;
@@ -175,7 +175,7 @@ module_log_queue_write(void *data, size_t len)
}
size_t
-module_log_queue_read(void *data, size_t len)
+module_log_queue_read(char *data, size_t len)
{
struct queue *self = &g_context;
size_t ret = 0;
diff --git a/src/libevp-agent/module_log_queue.h b/src/libevp-agent/module_log_queue.h
index 8a550c1a..b4063747 100644
--- a/src/libevp-agent/module_log_queue.h
+++ b/src/libevp-agent/module_log_queue.h
@@ -14,8 +14,8 @@ void module_log_queue_init(void);
void module_log_queue_free(void);
int module_log_queue_put(const char *instance_id, const char *stream,
const char *log);
-size_t module_log_queue_write(void *data, size_t sz);
-size_t module_log_queue_read(void *data, size_t sz);
+size_t module_log_queue_write(char *data, size_t sz);
+size_t module_log_queue_read(char *data, size_t sz);
size_t module_log_queue_get_len(void);
bool module_log_queue_is_full(void);
diff --git a/src/libevp-agent/platform.c b/src/libevp-agent/platform.c
index f0a2d410..47b3ffc4 100644
--- a/src/libevp-agent/platform.c
+++ b/src/libevp-agent/platform.c
@@ -399,11 +399,17 @@ plat_mod_fs_prune(void)
int ret;
const char *module_dir = path_get(MODULE_PATH_ID);
DIR *dir = opendir(module_dir);
+
if (dir == NULL) {
xlog_abort("opendir(3): %d (%s)", errno, strerror(errno));
}
struct dirent *d;
+ /*
+ * cppcheck doesn't follow xlog_abort well and doesnt detects
+ * the exit inside xlog_abort
+ */
+ // cppcheck-suppress nullPointerRedundantCheck
while ((d = readdir(dir)) != NULL) {
if (!strcmp(d->d_name, "..") || !strcmp(d->d_name, ".")) {
continue;
diff --git a/src/libevp-agent/req.c b/src/libevp-agent/req.c
index ac3b61d8..efa509dd 100644
--- a/src/libevp-agent/req.c
+++ b/src/libevp-agent/req.c
@@ -234,8 +234,8 @@ request_handle_response(struct evp_agent_context *agent, EVP_RPC_ID id,
uint32_t delay = now_ms - req->when_ms;
// To dicuss: Exposing the counter id it is a clue to
// impersonate the request/response
- xlog_debug("got request id %ju in %" PRIu32 " ms",
- (uintmax_t)id, delay);
+ xlog_info("got request id %ju in %" PRIu32 " ms",
+ (uintmax_t)id, delay);
if (req->callback) {
req->callback(req->id, req->callback_data, payload,
delay, 0);
@@ -254,9 +254,9 @@ request_send(struct transport_ctxt *t, struct request *req)
size_t payloadlen = strlen(req->payload);
rc = transport_send(t, topic, req->payload, payloadlen, req->qos);
- xlog_debug("%s req.id=%ju topic=%s, payload=%s, qos=%d, rc=%d",
- (req->when_ms == 0) ? "SEND" : "RESEND", req->id, topic,
- req->payload, req->qos, (int)rc);
+ xlog_info("%s req.id=%ju topic=%s, payload=%s, qos=%d, rc=%d",
+ (req->when_ms == 0) ? "SEND" : "RESEND", req->id, topic,
+ req->payload, req->qos, (int)rc);
free(topic);
if (rc != 0) {
xlog_warning("transport_send failed with %d", rc);
diff --git a/src/libevp-agent/sdk.c b/src/libevp-agent/sdk.c
index fd3b1947..94b9f2bc 100644
--- a/src/libevp-agent/sdk.c
+++ b/src/libevp-agent/sdk.c
@@ -271,11 +271,12 @@ sdk_queue_config(const char *name, const char *topic, const void *blob,
sdk_unlock();
}
-void
+int
sdk_queue_message(const char *module_instance_name,
const char *subscribe_alias, const void *blob,
size_t bloblen)
{
+ int ret = -1;
/* this function never consumes 'blob'. */
sdk_lock();
struct EVP_client *h =
@@ -287,8 +288,10 @@ sdk_queue_message(const char *module_instance_name,
struct sdk_event *event = (struct sdk_event *)inbox_msg;
TAILQ_INSERT_TAIL(&h->events, event, q);
sdk_wakeup_handle(h);
+ ret = 0;
}
sdk_unlock();
+ return ret;
}
void
@@ -1672,6 +1675,7 @@ EVP_impl_sendMessage(struct EVP_client *h, const void *rawbuf,
.bloblen = bloblen,
.cb = cb,
.cb_userdata = userData,
+ .reason = EVP_MESSAGE_SENT_CALLBACK_REASON_ERROR,
};
sdk_lock();
diff --git a/src/libevp-agent/sdk_agent.h b/src/libevp-agent/sdk_agent.h
index 325f9535..77846951 100644
--- a/src/libevp-agent/sdk_agent.h
+++ b/src/libevp-agent/sdk_agent.h
@@ -16,9 +16,9 @@
void sdk_init(void);
void sdk_queue_config(const char *name, const char *topic, const void *blob,
size_t bloblen);
-void sdk_queue_message(const char *module_instance_name,
- const char *subscribe_alias, const void *blob,
- size_t bloblen);
+int sdk_queue_message(const char *module_instance_name,
+ const char *subscribe_alias, const void *blob,
+ size_t bloblen);
void sdk_queue_rpc_request(const char *name, EVP_RPC_ID id, const char *method,
const char *params);
bool sdk_forward_local_to_publish_topic(struct sdk_event_message_sent *msg,
diff --git a/src/libevp-agent/sdk_callback_wasm.c b/src/libevp-agent/sdk_callback_wasm.c
index fd99f2e6..4feb8f89 100644
--- a/src/libevp-agent/sdk_callback_wasm.c
+++ b/src/libevp-agent/sdk_callback_wasm.c
@@ -112,8 +112,10 @@ sdk_callback_impl_wasm_invoke_config_callback(void *ctx,
};
if (!wasm_runtime_call_indirect(exec_env, func,
__arraycount(args), args)) {
- xlog_error("wasm_runtime_call_indirect failed: %s",
- topic);
+ xlog_error("wasm_runtime_call_indirect failed: "
+ "topic=%s, exception=%s",
+ topic,
+ wasm_runtime_get_exception(module_inst));
}
} else {
xlog_error("failed to allocate wasm module memory: %zu bytes",
diff --git a/src/libevp-agent/stream/stream.c b/src/libevp-agent/stream/stream.c
index 4e8e50f3..2a9aea85 100644
--- a/src/libevp-agent/stream/stream.c
+++ b/src/libevp-agent/stream/stream.c
@@ -74,13 +74,6 @@ close_stream(struct stream_impl *si)
return 0;
}
- if (si->ops != NULL) {
- ret = si->ops->close(si);
- if (ret != 0) {
- fprintf(stderr, "%s: stream close failed\n", __func__);
- }
- }
-
if (si->in_thread_init) {
int error = pthread_cancel(si->in_thread);
@@ -99,6 +92,13 @@ close_stream(struct stream_impl *si)
}
}
+ if (si->ops != NULL) {
+ ret = si->ops->close(si);
+ if (ret != 0) {
+ fprintf(stderr, "%s: stream close failed\n", __func__);
+ }
+ }
+
stream_free(&si->cfg);
return ret;
}
diff --git a/src/libevp-agent/transport.c b/src/libevp-agent/transport.c
index 9535d58e..0784b806 100644
--- a/src/libevp-agent/transport.c
+++ b/src/libevp-agent/transport.c
@@ -202,14 +202,8 @@ on_message(void **state, struct mqtt_response_publish *msg)
// TODO: Replace assert (programming error)
assert(ctxt != NULL);
- // Don't print data from/to instances in INFO level
- // Since it is user data and it can be confidential
- xlog_info("onMessage: topic=%s, id=%d, qos=%d, size=%zu", topic,
- (int)msg->packet_id, (int)msg->qos_level,
- msg->application_message_size);
-
- xlog_debug("onMessage: topic=%s, id=%d, qos=%d, payload=%s", topic,
- (int)msg->packet_id, (int)msg->qos_level, payload);
+ xlog_info("onMessage: topic=%s, id=%d, qos=%d, payload=%s", topic,
+ (int)msg->packet_id, (int)msg->qos_level, payload);
ctxt->hub_on_message(ctxt->agent, topic, msg->packet_id,
msg->qos_level, payload);
diff --git a/src/libevp-agent/util.c b/src/libevp-agent/util.c
index fd8e332d..41a9bb95 100644
--- a/src/libevp-agent/util.c
+++ b/src/libevp-agent/util.c
@@ -259,9 +259,9 @@ xmemdup_internal(const char *file, int line, const void *p0, size_t sz)
void *p = malloc(allocsz);
if (p == NULL) {
plat_out_of_memory(file, line, "xmemdup", sz);
+ } else {
+ memcpy(p, p0, sz);
}
-
- memcpy(p, p0, sz);
return p;
}
diff --git a/src/libevp-agent/webclient_mbedtls.c b/src/libevp-agent/webclient_mbedtls.c
index f342c22d..435b8803 100644
--- a/src/libevp-agent/webclient_mbedtls.c
+++ b/src/libevp-agent/webclient_mbedtls.c
@@ -146,12 +146,14 @@ _tls_send(FAR void *ctx, FAR struct webclient_tls_connection *conn,
{
ssize_t written_bytes = 0;
int rv = 0;
+ const unsigned char *buf_cpy = buf;
while (len > 0) {
if ((conn->flags & _GOT_FATAL_ERROR) != 0) {
rv = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
} else {
- rv = mbedtls_ssl_write(&conn->ctx.ssl_ctx, buf, len);
+ rv = mbedtls_ssl_write(&conn->ctx.ssl_ctx, buf_cpy,
+ len);
if (mbedtls_fatal_error(rv)) {
conn->flags |= _GOT_FATAL_ERROR;
}
@@ -159,7 +161,7 @@ _tls_send(FAR void *ctx, FAR struct webclient_tls_connection *conn,
}
if (rv >= 0) {
written_bytes += rv;
- buf += rv;
+ buf_cpy += rv;
len -= rv;
} else {
break;
@@ -194,12 +196,14 @@ _tls_recv(FAR void *ctx, FAR struct webclient_tls_connection *conn,
{
ssize_t read_bytes = 0;
int rv = 0;
+ unsigned char *buf_cpy = buf;
while (len > 0) {
if ((conn->flags & _GOT_FATAL_ERROR) != 0) {
rv = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
} else {
- rv = mbedtls_ssl_read(&conn->ctx.ssl_ctx, buf, len);
+ rv = mbedtls_ssl_read(&conn->ctx.ssl_ctx, buf_cpy,
+ len);
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && MBEDTLS_VERSION_MAJOR == 3
if (rv ==
MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) {
@@ -218,7 +222,7 @@ _tls_recv(FAR void *ctx, FAR struct webclient_tls_connection *conn,
return -EINVAL;
}
read_bytes += rv;
- buf += rv;
+ buf_cpy += rv;
len -= rv;
} else if (rv == 0) {
conn->flags |= _CLOSED_BY_PEER;
diff --git a/src/libevp-agent/work.c b/src/libevp-agent/work.c
index b4451695..18e91d49 100644
--- a/src/libevp-agent/work.c
+++ b/src/libevp-agent/work.c
@@ -347,7 +347,7 @@ work_trycancel(struct workq *q, struct work *wk)
/* NOTE: done callback has not been called */
if (status == WORK_STATUS_INPROGRESS ||
status == WORK_STATUS_NOTIFICATION) {
- return EBUSY;
+ return EAGAIN;
}
if (status == WORK_STATUS_NEW) {
return ENOENT;
diff --git a/src/libevp-agent/xmqtt.c b/src/libevp-agent/xmqtt.c
index 21373b17..2d6c900a 100644
--- a/src/libevp-agent/xmqtt.c
+++ b/src/libevp-agent/xmqtt.c
@@ -31,7 +31,7 @@ static void
mqtt_dump(struct mqtt_client *m)
{
#if defined(MQTT_LOG_VERBOSE)
- printf("error = %d (%s)\n", m->error, mqtt_error_str(m->error));
+ printf("error = %d (%s)\n", (int)m->error, mqtt_error_str(m->error));
long len = mqtt_mq_length(&m->mq);
printf("mqtt_mq_length = %ld\n", len);
printf("send_offset = %zu\n", m->send_offset);
diff --git a/src/libevp-app-sdk/sdkrpc/client_io.c b/src/libevp-app-sdk/sdkrpc/client_io.c
index 174ef17d..527d07ef 100644
--- a/src/libevp-app-sdk/sdkrpc/client_io.c
+++ b/src/libevp-app-sdk/sdkrpc/client_io.c
@@ -43,7 +43,7 @@ record_read(struct record_reader *r, struct sdk_transport *trans)
}
if (offset < r->hdr.size) {
size_t want = r->hdr.size - offset;
- ret = read(fd, r->buf + offset, want);
+ ret = read(fd, (char *)r->buf + offset, want);
if (ret == 0) {
return EIO; /* EOF */
}
@@ -104,7 +104,7 @@ record_write(struct record_writer *w, struct sdk_transport *trans)
size_t offset = w->bytes_written - sizeof(w->hdr);
if (offset < w->hdr.size) {
size_t want = w->hdr.size - offset;
- ret = write(fd, w->buf + offset, want);
+ ret = write(fd, (char *)w->buf + offset, want);
// TODO: Replace assert (runtime error)
assert(ret != 0);
if (ret == -1) {
diff --git a/src/python-evp-app-sdk/Makefile b/src/python-evp-app-sdk/Makefile
index 6a91296f..54141e2c 100644
--- a/src/python-evp-app-sdk/Makefile
+++ b/src/python-evp-app-sdk/Makefile
@@ -24,13 +24,20 @@ TARGET = $(LIBDIR)/python
all: $(TARGET)
-dist: $(DEPS)
+dist-stamp: $(DEPS)
CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' CC=$(CC) python -m build
+ set -e; for f in dist/*.whl; do \
+ plat=$$(python3 get_manylinux_platform.py $$f); \
+ auditwheel repair --plat $$plat $$f; \
+ done
+ touch $@
-$(TARGET): dist
+$(TARGET): dist-stamp
mkdir -p $@
- cp dist/* $@
+ cp wheelhouse/* $@
clean:
rm -rf $(TARGET)
rm -rf dist
+ rm -rf wheelhouse
+ rm -f dist-stamp
diff --git a/src/python-evp-app-sdk/get_manylinux_platform.py b/src/python-evp-app-sdk/get_manylinux_platform.py
new file mode 100755
index 00000000..bc8ff14d
--- /dev/null
+++ b/src/python-evp-app-sdk/get_manylinux_platform.py
@@ -0,0 +1,18 @@
+# SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+
+from auditwheel.wheel_abi import analyze_wheel_abi, NonPlatformWheel
+from auditwheel.policy import WheelPolicies
+from pathlib import Path
+import sys
+
+file = Path(sys.argv[1])
+
+try:
+ winfo = analyze_wheel_abi(WheelPolicies(), file, frozenset(), False)
+except NonPlatformWheel as e:
+ print(e.message)
+ exit(1)
+
+print(winfo.sym_policy.name)
diff --git a/src/wasm-micro-runtime b/src/wasm-micro-runtime
index f4383a9e..fe1138b0 160000
--- a/src/wasm-micro-runtime
+++ b/src/wasm-micro-runtime
@@ -1 +1 @@
-Subproject commit f4383a9e62a0f4ac97c3ab66c6b88a2aee5c24a2
+Subproject commit fe1138b0e86925ce6ec2f699d8f247f8a12254e9
diff --git a/test/Makefile b/test/Makefile
index 14d66677..e74af324 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -116,6 +116,8 @@ STESTS=\
src/systest/test_capture_mode.elf\
src/systest/test_connection_error.elf\
src/systest/test_deployment.elf\
+ src/systest/test_deployment_invalid_hash.elf\
+ src/systest/test_deployment_unload_error.elf\
src/systest/test_device_config.elf\
src/systest/test_direct_command.elf\
src/systest/test_direct_command_parallel.elf\
@@ -126,6 +128,7 @@ STESTS=\
src/systest/test_mi_denied_requests.elf\
src/systest/test_module_log.elf\
src/systest/test_mstp.elf\
+ src/systest/test_mstp_legacy.elf\
src/systest/test_mstp_null.elf\
src/systest/test_spawn_mod_config_echo.elf\
src/systest/test_spawn_mod_download_evp_file.elf\
diff --git a/test/src/st-nohub/test_connections_disconnecting.c b/test/src/st-nohub/test_connections_disconnecting.c
index 10b549be..608aad82 100644
--- a/test/src/st-nohub/test_connections_disconnecting.c
+++ b/test/src/st-nohub/test_connections_disconnecting.c
@@ -4,8 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
+#include
#include
#include
+#include
#include
#include
#include
@@ -24,7 +26,7 @@
#define TEST_HTTP_GET_FILE "foobar.txt"
#define TEST_HTTP_PUT_FILE "boofar.bin"
-static pthread_mutex_t webclient_hang_lock;
+static sem_t in_sem, out_sem;
int
__wrap_webclient_get_poll_info(FAR struct webclient_context *ctx,
@@ -36,9 +38,8 @@ __wrap_webclient_get_poll_info(FAR struct webclient_context *ctx,
int
__wrap_webclient_perform(FAR struct webclient_context *ctx)
{
- /* provide a way for us to lock the thread using the mutex */
- pthread_mutex_lock(&webclient_hang_lock);
- pthread_mutex_unlock(&webclient_hang_lock);
+ assert(!sem_post(&in_sem));
+ assert(!sem_wait(&out_sem));
return -EAGAIN;
}
@@ -51,15 +52,27 @@ blob_cb(EVP_BLOB_CALLBACK_REASON reason, const void *vp, void *userData)
check_expected(result->error);
}
+static int
+on_conn_status(const void *data, void *user)
+{
+ agent_write_to_pipe(data);
+ return 0;
+}
+
void
test_connections_disconnecting(void **state)
{
// init mutex
- pthread_mutex_init(&webclient_hang_lock, NULL);
+ assert_int_equal(sem_init(&in_sem, 0, 0), 0);
+ assert_int_equal(sem_init(&out_sem, 0, 0), 0);
// start agent
struct evp_agent_context *ctxt = agent_test_start();
- agent_poll_status(ctxt, EVP_AGENT_STATUS_CONNECTED, 10);
+
+ assert_int_equal(
+ evp_agent_notification_subscribe(ctxt, "agent/conn_status",
+ on_conn_status, NULL),
+ 0);
// create backdoor instance
struct EVP_client *sdk_handle =
@@ -78,9 +91,6 @@ test_connections_disconnecting(void **state)
.filename = filename,
};
- // Hang the webclient thread
- pthread_mutex_lock(&webclient_hang_lock);
-
// test HTTP GET to file
struct EVP_BlobRequestHttp request = {
.url = TEST_HTTP_GET_URL,
@@ -91,26 +101,23 @@ test_connections_disconnecting(void **state)
EVP_BLOB_OP_GET, &request, &localstore,
blob_cb, &cb_data);
- // wait a bit for the blob operation to start
- sleep(1);
+ // wait for webclient_perform to be called
+ assert_int_equal(sem_wait(&in_sem), 0);
// Disconnection
- result = evp_agent_disconnect(ctxt);
- assert_int_equal(result, EVP_OK);
- agent_poll_status(ctxt, EVP_AGENT_STATUS_DISCONNECTING, 0);
+ assert_int_equal(evp_agent_disconnect(ctxt), EVP_OK);
+ agent_poll(verify_equals, "disconnecting");
// let the webclient_perform thread continue
- pthread_mutex_unlock(&webclient_hang_lock);
+ assert_int_equal(sem_post(&out_sem), 0);
- // We must go to DISCONNECTED in 5 seconds maximum
- agent_poll_status(ctxt, EVP_AGENT_STATUS_DISCONNECTED, 5);
+ agent_poll(verify_equals, "disconnected");
// Expect processed blob to abort
expect_value(blob_cb, reason, EVP_BLOB_CALLBACK_REASON_DONE);
expect_value(blob_cb, result->result, EVP_BLOB_RESULT_ERROR);
expect_value(blob_cb, result->error, ENETDOWN);
- result = EVP_processEvent(sdk_handle, 2000);
- assert_int_equal(result, EVP_OK);
+ assert_int_equal(EVP_processEvent(sdk_handle, -1), EVP_OK);
free(filename);
}
diff --git a/test/src/systest/test_connection_error.c b/test/src/systest/test_connection_error.c
index 73483368..11d333ee 100644
--- a/test/src/systest/test_connection_error.c
+++ b/test/src/systest/test_connection_error.c
@@ -144,8 +144,11 @@ state_cb(EVP_STATE_CALLBACK_REASON reason, void *userData)
{
struct test_context *ctxt = userData;
- check_expected(reason);
+ xlog_info("reason=%d", reason);
+ assert(reason == EVP_STATE_CALLBACK_REASON_SENT ||
+ reason == EVP_STATE_CALLBACK_REASON_OVERWRITTEN);
check_expected(userData);
+ function_called();
ctxt->called = true;
}
@@ -156,6 +159,7 @@ telemetry_cb(EVP_TELEMETRY_CALLBACK_REASON reason, void *userData)
check_expected(reason);
check_expected(userData);
+ function_called();
ctxt->called = true;
}
@@ -215,16 +219,11 @@ test_state(void **state)
result = EVP_sendState(ctxt->h, state_topic, state_blob,
strlen(state_blob), state_cb, ctxt);
assert_int_equal(result, EVP_OK);
-
expect_value(state_cb, userData, ctxt);
-
- EVP_STATE_CALLBACK_REASON reason =
- i + 1 < 10 ? EVP_STATE_CALLBACK_REASON_OVERWRITTEN
- : EVP_STATE_CALLBACK_REASON_SENT;
-
- expect_value(state_cb, reason, reason);
}
+ expect_function_calls(state_cb, 10);
+
for (int i = 0; i < 10; i++) {
ensure_event(ctxt);
assert_int_equal(agent_test_call_count(0), 0);
@@ -264,6 +263,8 @@ test_telemetry(void **state)
expect_value(telemetry_cb, userData, ctxt);
}
+ expect_function_calls(telemetry_cb, 11);
+
for (int i = 0; i < 10; ++i) {
ensure_event(ctxt);
assert_int_equal(agent_test_call_count(0), 0);
diff --git a/test/src/systest/test_deployment_invalid_hash.c b/test/src/systest/test_deployment_invalid_hash.c
new file mode 100644
index 00000000..08c64a8a
--- /dev/null
+++ b/test/src/systest/test_deployment_invalid_hash.c
@@ -0,0 +1,316 @@
+/*
+ * SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include "agent_test.h"
+#include "hub.h"
+#include "mqtt_custom.h"
+
+enum test_deployment_payloads {
+ DEPLOYMENT_MANIFEST_1,
+ DEPLOYMENT_MANIFEST_2,
+ DEPLOYMENT_STATUS_1_FMT,
+ DEPLOYMENT_STATUS_2_FMT
+};
+
+static struct test {
+ pthread_mutex_t mtx;
+ bool fail;
+} test = {.mtx = PTHREAD_MUTEX_INITIALIZER};
+
+#define DEPLOYMENT_ID_1 "4fa905ae-e103-46ab-a8b9-73be07599708"
+#define DEPLOYMENT_ID_2 "8543e017-2d93-444b-bd4c-bcaa39c46095"
+
+#define INSTANCE1_ID "acb69828-ccd5-47ee-818c-bd6939c8f40f"
+#define INSTANCE2_ID "970ea56c-6334-4ad1-96c9-29473cd94f76"
+#define MODULE_ID "b218f90b-9228-423f-8e02-a6d3527bc15d"
+#define MODULE_URL "file://../test_modules/config_echo.wasm"
+#define MODULE_HASH \
+ "73aa09694abf7c7bb8496a82b7de38a24b81a7f93e437a74912413ac4f2be06e"
+
+#define EVP1_DEPLOY_MANIFEST_1 \
+ "\"{ " \
+ " \\\"deploymentId\\\": " \
+ "\\\"" DEPLOYMENT_ID_1 "\\\"," \
+ " \\\"instanceSpecs\\\": {" \
+ " \\\"" INSTANCE1_ID "\\\": {" \
+ " \\\"moduleId\\\": " \
+ "\\\"" MODULE_ID "\\\"," \
+ " \\\"entryPoint\\\": \\\"main\\\"," \
+ " \\\"version\\\": 1," \
+ " \\\"publish\\\": {}," \
+ " \\\"subscribe\\\": {}" \
+ " }," \
+ " \\\"" INSTANCE2_ID "\\\": {" \
+ " \\\"moduleId\\\": " \
+ "\\\"" MODULE_ID "\\\"," \
+ " \\\"entryPoint\\\": \\\"main\\\"," \
+ " \\\"version\\\": 1," \
+ " \\\"publish\\\": {}," \
+ " \\\"subscribe\\\": {}" \
+ " }" \
+ " }," \
+ " \\\"modules\\\": {" \
+ " \\\"" MODULE_ID "\\\": {" \
+ " \\\"moduleImpl\\\": \\\"wasm\\\"," \
+ " \\\"downloadUrl\\\": \\\"" MODULE_URL "\\\"," \
+ " \\\"hash\\\": \\\"deadc0ffee\\\"" \
+ " }" \
+ " }," \
+ " \\\"publishTopics\\\": {}," \
+ " \\\"subscribeTopics\\\": {}" \
+ "}\""
+
+#define EVP2_DEPLOY_MANIFEST_1 \
+ "{" \
+ " \"deploymentId\": \"" DEPLOYMENT_ID_1 "\"," \
+ " \"instanceSpecs\": {" \
+ " \"" INSTANCE1_ID "\": {" \
+ " \"moduleId\": " \
+ "\"" MODULE_ID "\"," \
+ " \"publish\": {}," \
+ " \"subscribe\": {}" \
+ " }," \
+ " \"" INSTANCE2_ID "\": {" \
+ " \"moduleId\": " \
+ "\"" MODULE_ID "\"," \
+ " \"publish\": {}," \
+ " \"subscribe\": {}" \
+ " }" \
+ " }," \
+ " \"modules\": {" \
+ " \"" MODULE_ID "\": {" \
+ " \"entryPoint\": \"main\"," \
+ " \"moduleImpl\": \"wasm\"," \
+ " \"downloadUrl\": \"" MODULE_URL "\"," \
+ " \"hash\": \"deadc0ffee\"" \
+ " }" \
+ " }," \
+ " \"publishTopics\": {}," \
+ " \"subscribeTopics\": {}" \
+ "}"
+
+#define EVP1_DEPLOY_MANIFEST_2 \
+ "\"{ " \
+ " \\\"deploymentId\\\": " \
+ "\\\"" DEPLOYMENT_ID_2 "\\\"," \
+ " \\\"instanceSpecs\\\": {" \
+ " \\\"" INSTANCE1_ID "\\\": {" \
+ " \\\"moduleId\\\": " \
+ "\\\"" MODULE_ID "\\\"," \
+ " \\\"entryPoint\\\": \\\"main\\\"," \
+ " \\\"version\\\": 1," \
+ " \\\"publish\\\": {}," \
+ " \\\"subscribe\\\": {}" \
+ " }," \
+ " \\\"" INSTANCE2_ID "\\\": {" \
+ " \\\"moduleId\\\": " \
+ "\\\"" MODULE_ID "\\\"," \
+ " \\\"entryPoint\\\": \\\"main\\\"," \
+ " \\\"version\\\": 1," \
+ " \\\"publish\\\": {}," \
+ " \\\"subscribe\\\": {}" \
+ " }" \
+ " }," \
+ " \\\"modules\\\": {" \
+ " \\\"" MODULE_ID "\\\": {" \
+ " \\\"moduleImpl\\\": \\\"wasm\\\"," \
+ " \\\"downloadUrl\\\": \\\"" MODULE_URL "\\\"," \
+ " \\\"hash\\\": \\\"" MODULE_HASH "\\\"" \
+ " }" \
+ " }," \
+ " \\\"publishTopics\\\": {}," \
+ " \\\"subscribeTopics\\\": {}" \
+ "}\""
+
+#define EVP2_DEPLOY_MANIFEST_2 \
+ "{" \
+ " \"deploymentId\": \"" DEPLOYMENT_ID_2 "\"," \
+ " \"instanceSpecs\": {" \
+ " \"" INSTANCE1_ID "\": {" \
+ " \"moduleId\": " \
+ "\"" MODULE_ID "\"," \
+ " \"publish\": {}," \
+ " \"subscribe\": {}" \
+ " }," \
+ " \"" INSTANCE2_ID "\": {" \
+ " \"moduleId\": " \
+ "\"" MODULE_ID "\"," \
+ " \"publish\": {}," \
+ " \"subscribe\": {}" \
+ " }" \
+ " }," \
+ " \"modules\": {" \
+ " \"" MODULE_ID "\": {" \
+ " \"entryPoint\": \"main\"," \
+ " \"moduleImpl\": \"wasm\"," \
+ " \"downloadUrl\": \"" MODULE_URL "\"," \
+ " \"hash\": \"" MODULE_HASH "\"" \
+ " }" \
+ " }," \
+ " \"publishTopics\": {}," \
+ " \"subscribeTopics\": {}" \
+ "}"
+
+/* clang-format off */
+
+#define EVP1_DEPLOY_STATUS_1_FMT \
+ "deploymentStatus=#{" \
+ "modules." MODULE_ID ".status=%s," \
+ "modules." MODULE_ID ".failureMessage=%s," \
+ "reconcileStatus=%s," \
+ "deploymentId=%s" \
+ "}"
+
+#define EVP2_DEPLOY_STATUS_1_FMT \
+ "deploymentStatus.modules." MODULE_ID ".status=%s," \
+ "deploymentStatus.modules." MODULE_ID ".failureMessage=%s," \
+ "deploymentStatus.reconcileStatus=%s," \
+ "deploymentStatus.deploymentId=%s"
+
+#define EVP1_DEPLOY_STATUS_2_FMT \
+ "deploymentStatus=#{" \
+ "modules." MODULE_ID ".status=%s," \
+ "reconcileStatus=%s," \
+ "deploymentId=%s" \
+ "}"
+
+#define EVP2_DEPLOY_STATUS_2_FMT \
+ "deploymentStatus.modules." MODULE_ID ".status=%s," \
+ "deploymentStatus.reconcileStatus=%s," \
+ "deploymentStatus.deploymentId=%s"
+
+/* clang-format on */
+
+int
+__wrap_check_hash(struct module *module, const unsigned char *ref,
+ size_t ref_len, char **result)
+{
+ assert(!pthread_mutex_lock(&test.mtx));
+ *result = test.fail ? xstrdup("Module hash mismatch") : NULL;
+ assert(!pthread_mutex_unlock(&test.mtx));
+ return 0;
+}
+
+static int
+on_reconcileStatus(const void *args, void *user_data)
+{
+ const struct reconcileStatusNotify *reconcileStatusData = args;
+
+ // deploymentId can be empty (Whenre there is an EmptyDeployment)
+ const char *deploymentId = reconcileStatusData->deploymentId;
+ if (!deploymentId)
+ deploymentId = "empty";
+
+ char *txt;
+ xasprintf(&txt, "%s/%s/%s", __func__, deploymentId,
+ reconcileStatusData->reconcileStatus);
+
+ agent_write_to_pipe(txt);
+ free(txt);
+ return 0;
+}
+
+static void
+set_fail(bool value)
+{
+ assert_int_equal(pthread_mutex_lock(&test.mtx), 0);
+ test.fail = value;
+ assert_int_equal(pthread_mutex_unlock(&test.mtx), 0);
+}
+
+static void
+test_deployment_invalid_hash(void **state)
+{
+ struct evp_agent_context *ctxt = *state;
+
+ set_fail(true);
+ agent_send_initial(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_1),
+ NULL, NULL);
+ agent_poll(verify_json, agent_get_payload(DEPLOYMENT_STATUS_1_FMT),
+ "error", "Module hash mismatch", "applying",
+ DEPLOYMENT_ID_1);
+}
+
+static void
+test_deployment_invalid_hash_valid(void **state)
+{
+ struct evp_agent_context *ctxt = *state;
+
+ set_fail(true);
+ agent_send_deployment(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_1));
+ agent_poll(verify_json, agent_get_payload(DEPLOYMENT_STATUS_1_FMT),
+ "error", "Module hash mismatch", "applying",
+ DEPLOYMENT_ID_1);
+ set_fail(false);
+ agent_send_deployment(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_2));
+ agent_poll(verify_json, agent_get_payload(DEPLOYMENT_STATUS_2_FMT),
+ "ok", "ok", DEPLOYMENT_ID_2);
+}
+
+static int
+setup(void **state)
+{
+ agent_test_setup();
+ // start agent
+ *state = agent_test_start();
+
+ assert_int_equal(evp_agent_notification_subscribe(
+ *state, "deployment/reconcileStatus",
+ on_reconcileStatus, NULL),
+ 0);
+
+ agent_register_payload(DEPLOYMENT_MANIFEST_1, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_MANIFEST_1);
+ agent_register_payload(DEPLOYMENT_MANIFEST_1, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_MANIFEST_1);
+
+ agent_register_payload(DEPLOYMENT_MANIFEST_2, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_MANIFEST_2);
+
+ agent_register_payload(DEPLOYMENT_MANIFEST_2, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_MANIFEST_2);
+
+ agent_register_payload(DEPLOYMENT_STATUS_1_FMT, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_STATUS_1_FMT);
+ agent_register_payload(DEPLOYMENT_STATUS_1_FMT, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_STATUS_1_FMT);
+
+ agent_register_payload(DEPLOYMENT_STATUS_2_FMT, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_STATUS_2_FMT);
+ agent_register_payload(DEPLOYMENT_STATUS_2_FMT, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_STATUS_2_FMT);
+
+ return 0;
+}
+
+static int
+teardown(void **state)
+{
+ agent_test_exit();
+ return pthread_mutex_destroy(&test.mtx);
+}
+
+int
+main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_deployment_invalid_hash),
+ cmocka_unit_test(test_deployment_invalid_hash_valid),
+ };
+
+ return cmocka_run_group_tests(tests, setup, teardown);
+}
diff --git a/test/src/systest/test_deployment_unload_error.c b/test/src/systest/test_deployment_unload_error.c
new file mode 100644
index 00000000..8d7d929f
--- /dev/null
+++ b/test/src/systest/test_deployment_unload_error.c
@@ -0,0 +1,390 @@
+/*
+ * SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include "agent_test.h"
+#include "hub.h"
+#include "module.h"
+#include "mqtt_custom.h"
+
+enum test_deployment_payloads {
+ DEPLOYMENT_MANIFEST_1,
+ DEPLOYMENT_MANIFEST_2,
+ DEPLOYMENT_STATUS_1_FMT,
+ DEPLOYMENT_STATUS_1to2_FMT,
+ DEPLOYMENT_STATUS_2_FMT
+};
+
+static struct test {
+ pthread_mutex_t mtx;
+ bool hash_fail;
+ bool unload_fail;
+
+} test = {.mtx = PTHREAD_MUTEX_INITIALIZER};
+
+#define TEST_DEPLOYMENT_ID1 "4fa905ae-e103-46ab-a8b9-111111111111"
+#define TEST_DEPLOYMENT_ID2 "4fa905ae-e103-46ab-a8b9-222222222222"
+#define TEST_EMPTY_DEPLOYMENT_ID1 "4fa905ae-e103-46ab-a8b9-73be07599709"
+
+#define TEST_MODULE_ID1 "aaaaaaaa-9228-423f-8e02-111111111111"
+#define TEST_MODULE_ID2 "bbbbbbbb-9228-423f-8e02-222222222222"
+
+#define TEST_INSTANCE_ID1 "b218f90b-9228-423f-8e02-111111111111"
+#define TEST_INSTANCE_ID2 "b218f90b-9228-423f-8e02-222222222222"
+
+#define EVP1_DEPLOY_STATUS_1_FMT \
+ "deploymentStatus=#{" \
+ "modules." TEST_MODULE_ID1 ".status=%s," \
+ "reconcileStatus=%s," \
+ "deploymentId=%s" \
+ "}"
+
+#define EVP2_DEPLOY_STATUS_1_FMT \
+ "deploymentStatus.modules." TEST_MODULE_ID1 ".status=%s," \
+ "deploymentStatus.reconcileStatus=%s," \
+ "deploymentStatus.deploymentId=%s"
+
+// 1to2 means the status when deployment 1 is still undeploying
+// but there is an error (EAGAIN) unloading the module
+// until the agent is able to fix the unloading problem
+// and finally starts to apply deployment 2
+#define EVP1_DEPLOY_STATUS_1to2_FMT \
+ "deploymentStatus=#{" \
+ "modules." TEST_MODULE_ID1 ".status=%s," \
+ "reconcileStatus=%s," \
+ "deploymentId=%s" \
+ "}"
+
+#define EVP2_DEPLOY_STATUS_1to2_FMT \
+ "deploymentStatus.modules." TEST_MODULE_ID1 ".status=%s," \
+ "deploymentStatus.reconcileStatus=%s," \
+ "deploymentStatus.deploymentId=%s"
+
+#define EVP1_DEPLOY_STATUS_2_FMT \
+ "deploymentStatus=#{" \
+ "modules." TEST_MODULE_ID2 ".status=%s," \
+ "reconcileStatus=%s," \
+ "deploymentId=%s" \
+ "}"
+
+#define EVP2_DEPLOY_STATUS_2_FMT \
+ "deploymentStatus.modules." TEST_MODULE_ID2 ".status=%s," \
+ "deploymentStatus.reconcileStatus=%s," \
+ "deploymentStatus.deploymentId=%s"
+
+#define MODULE_URL "file://../test_modules/config_echo.wasm"
+#define MODULE_HASH \
+ "579fca500ec9f67a661e8b1a3a59a114a97029c46776d6ad9502fb183f1a1f7d"
+
+#define EVP1_DEPLOYMENT_MANIFEST_1 \
+ "\"{ " \
+ " \\\"deploymentId\\\": " \
+ "\\\"" TEST_DEPLOYMENT_ID1 "\\\"," \
+ " \\\"instanceSpecs\\\": {" \
+ " \\\"" TEST_INSTANCE_ID1 "\\\": {" \
+ " \\\"moduleId\\\": " \
+ "\\\"" TEST_MODULE_ID1 "\\\"," \
+ " \\\"entryPoint\\\": \\\"main\\\"," \
+ " \\\"version\\\": 1," \
+ " \\\"publish\\\": {}," \
+ " \\\"subscribe\\\": {}" \
+ " }" \
+ " }," \
+ " \\\"modules\\\": {" \
+ " \\\"" TEST_MODULE_ID1 "\\\": {" \
+ " \\\"moduleImpl\\\": \\\"wasm\\\"," \
+ " \\\"downloadUrl\\\": \\\"" MODULE_URL "\\\"," \
+ " \\\"hash\\\": \\\"" MODULE_HASH "\\\"" \
+ " }" \
+ " }," \
+ " \\\"publishTopics\\\": {}," \
+ " \\\"subscribeTopics\\\": {}" \
+ "}\""
+
+#define EVP2_DEPLOYMENT_MANIFEST_1 \
+ "{" \
+ " \"deploymentId\": \"" TEST_DEPLOYMENT_ID1 "\"," \
+ " \"instanceSpecs\": {" \
+ " \"" TEST_INSTANCE_ID1 "\": {" \
+ " \"moduleId\": " \
+ "\"" TEST_MODULE_ID1 "\"," \
+ " \"publish\": {}," \
+ " \"subscribe\": {}" \
+ " }" \
+ " }," \
+ " \"modules\": {" \
+ " \"" TEST_MODULE_ID1 "\": {" \
+ " \"entryPoint\": \"main\"," \
+ " \"moduleImpl\": \"wasm\"," \
+ " \"downloadUrl\": " \
+ "\"" MODULE_URL "\"," \
+ " \"hash\": " \
+ "\"" MODULE_HASH "" \
+ "\"" \
+ " }" \
+ " }," \
+ " \"publishTopics\": {}," \
+ " \"subscribeTopics\": {}" \
+ "}"
+
+#define EVP1_DEPLOYMENT_MANIFEST_2 \
+ "\"{ " \
+ " \\\"deploymentId\\\": " \
+ "\\\"" TEST_DEPLOYMENT_ID2 "\\\"," \
+ " \\\"instanceSpecs\\\": {" \
+ " \\\"" TEST_INSTANCE_ID2 "\\\": {" \
+ " \\\"moduleId\\\": " \
+ "\\\"" TEST_MODULE_ID2 "\\\"," \
+ " \\\"entryPoint\\\": \\\"main\\\"," \
+ " \\\"version\\\": 1," \
+ " \\\"publish\\\": {}," \
+ " \\\"subscribe\\\": {}" \
+ " }" \
+ " }," \
+ " \\\"modules\\\": {" \
+ " \\\"" TEST_MODULE_ID2 "\\\": {" \
+ " \\\"moduleImpl\\\": \\\"wasm\\\"," \
+ " \\\"downloadUrl\\\": \\\"" MODULE_URL "\\\"," \
+ " \\\"hash\\\": \\\"" MODULE_HASH "\\\"" \
+ " }" \
+ " }," \
+ " \\\"publishTopics\\\": {}," \
+ " \\\"subscribeTopics\\\": {}" \
+ "}\""
+
+#define EVP2_DEPLOYMENT_MANIFEST_2 \
+ "{" \
+ " \"deploymentId\": \"" TEST_DEPLOYMENT_ID2 "\"," \
+ " \"instanceSpecs\": {" \
+ " \"" TEST_INSTANCE_ID2 "\": {" \
+ " \"moduleId\": " \
+ "\"" TEST_MODULE_ID2 "\"," \
+ " \"publish\": {}," \
+ " \"subscribe\": {}" \
+ " }" \
+ " }," \
+ " \"modules\": {" \
+ " \"" TEST_MODULE_ID2 "\": {" \
+ " \"entryPoint\": \"main\"," \
+ " \"moduleImpl\": \"wasm\"," \
+ " \"downloadUrl\": " \
+ "\"" MODULE_URL "\"," \
+ " \"hash\": " \
+ "\"" MODULE_HASH "" \
+ "\"" \
+ " }" \
+ " }," \
+ " \"publishTopics\": {}," \
+ " \"subscribeTopics\": {}" \
+ "}"
+
+#define EVP1_EMPTY_DEPLOYMENT_MANIFEST_1 \
+ "\"{ " \
+ " \\\"deploymentId\\\": " \
+ "\\\"" TEST_EMPTY_DEPLOYMENT_ID1 "\\\"," \
+ " \\\"instanceSpecs\\\": {}," \
+ " \\\"modules\\\": {}," \
+ " \\\"publishTopics\\\": {}," \
+ " \\\"subscribeTopics\\\": {}" \
+ "}\""
+
+#define EVP2_EMPTY_DEPLOYMENT_MANIFEST_1 \
+ "{" \
+ " \"deploymentId\": \"" TEST_EMPTY_DEPLOYMENT_ID1 "\"," \
+ " \"instanceSpecs\": {}," \
+ " \"modules\": {}," \
+ " \"publishTopics\": {}," \
+ " \"subscribeTopics\": {}" \
+ "}"
+
+/* clang-format on */
+
+int
+__wrap_module_unload(const struct ModuleList *list)
+{
+ int ret;
+ int __real_module_unload(const struct ModuleList *list);
+ assert(!pthread_mutex_lock(&test.mtx));
+ if (test.unload_fail) {
+ ret = EAGAIN;
+ } else {
+ ret = __real_module_unload(list);
+ }
+ assert(!pthread_mutex_unlock(&test.mtx));
+ return ret;
+}
+
+int
+__wrap_check_hash(struct module *module, const unsigned char *ref,
+ size_t ref_len, char **result)
+{
+ int ret;
+ assert(!pthread_mutex_lock(&test.mtx));
+ ret = test.hash_fail ? EINVAL : 0;
+ *result = NULL;
+ assert(!pthread_mutex_unlock(&test.mtx));
+ return ret;
+}
+
+static int
+on_reconcileStatus(const void *args, void *user_data)
+{
+ const struct reconcileStatusNotify *reconcileStatusData = args;
+
+ // deploymentId can be empty (Whenre there is an EmptyDeployment)
+ const char *deploymentId = reconcileStatusData->deploymentId;
+ if (!deploymentId)
+ deploymentId = "empty";
+
+ char *txt;
+ xasprintf(&txt, "%s/%s/%s", __func__, deploymentId,
+ reconcileStatusData->reconcileStatus);
+
+ agent_write_to_pipe(txt);
+ free(txt);
+ return 0;
+}
+
+static void
+set_fail(bool hash_fail, bool unload_fail)
+{
+ assert_int_equal(pthread_mutex_lock(&test.mtx), 0);
+ test.hash_fail = hash_fail;
+ test.unload_fail = unload_fail;
+ assert_int_equal(pthread_mutex_unlock(&test.mtx), 0);
+}
+
+/* clang-format off */
+/*
+ * To reproduce ADI-2283
+ * The goal of this test is to validate that a invalid deployment,
+ * for example, a deployment where there is a problem with the hash
+ * or signed module
+ * is not affecting the nexte valid deployment.
+ * The exact case is:
+ * 1- Send a deployment DEPLOYMENT_MANIFEST_1 with a module wrong
+ * signed
+ * 2- Check that the reported status is "applying" for
+ * DEPLOYMENT_MANIFEST_1 since the agent tries to download the
+ * module again when the hash or the signature is invalid.
+ * 3- Simulate that the there is a blob operation in progress so the
+ * reconcile process can not cancel the current operation and the
+ * agent has to wait until is done. The direct cause of this is that
+ * the unload operation cant not be done (see__wrap_module_unload)
+ * 4- Send a new valid deployment DEPLOYMENT_MANIFEST_2
+ * 5- Check that the reported status is "applying" for
+ * DEPLOYMENT_MANIFEST_1 but reporting the module from
+ * DEPLOYMENT_MANIFEST_1, since the unload operation is still in progress.
+ * 6- Simulate that the agent
+ * finally was able to unload the module (when the blob operation ends
+ * the agent can unload the module)
+ * 7- Finally the new deployment is correctly applied.
+ */
+
+/* clang-format on */
+static void
+test_deployment_unload_error(void **state)
+{
+ struct evp_agent_context *ctxt = *state;
+
+ /* Step 1 */
+ /* Simulate hash error, ok to unload */
+ set_fail(true, false);
+ agent_send_initial(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_1),
+ NULL, NULL);
+ /* Step 2.
+ * The module status is unknow because camFW is not reporting any
+ * status at this moment */
+ agent_poll(verify_json, agent_get_payload(DEPLOYMENT_STATUS_1_FMT),
+ "unknown", "applying", TEST_DEPLOYMENT_ID1);
+
+ /* Step 3 */
+ set_fail(true, true);
+
+ /* Step 4 */
+ agent_send_deployment(ctxt, agent_get_payload(DEPLOYMENT_MANIFEST_2));
+
+ /* Step 5 */
+ agent_poll(verify_json, agent_get_payload(DEPLOYMENT_STATUS_1to2_FMT),
+ "unknown", "applying", TEST_DEPLOYMENT_ID2);
+
+ /* Step 6 */
+ set_fail(false, false);
+ /* Step 7 */
+ agent_poll(verify_json, agent_get_payload(DEPLOYMENT_STATUS_2_FMT),
+ "ok", "ok", TEST_DEPLOYMENT_ID2);
+}
+
+static int
+setup(void **state)
+{
+ agent_test_setup();
+ // start agent
+ *state = agent_test_start();
+
+ assert_int_equal(evp_agent_notification_subscribe(
+ *state, "deployment/reconcileStatus",
+ on_reconcileStatus, NULL),
+ 0);
+
+ agent_register_payload(DEPLOYMENT_MANIFEST_1, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOYMENT_MANIFEST_1);
+ agent_register_payload(DEPLOYMENT_MANIFEST_1, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOYMENT_MANIFEST_1);
+
+ agent_register_payload(DEPLOYMENT_MANIFEST_2, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOYMENT_MANIFEST_2);
+
+ agent_register_payload(DEPLOYMENT_MANIFEST_2, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOYMENT_MANIFEST_2);
+
+ agent_register_payload(DEPLOYMENT_STATUS_1_FMT, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_STATUS_1_FMT);
+ agent_register_payload(DEPLOYMENT_STATUS_1_FMT, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_STATUS_1_FMT);
+
+ agent_register_payload(DEPLOYMENT_STATUS_1to2_FMT,
+ EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_STATUS_1to2_FMT);
+ agent_register_payload(DEPLOYMENT_STATUS_1to2_FMT,
+ EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_STATUS_1to2_FMT);
+
+ agent_register_payload(DEPLOYMENT_STATUS_2_FMT, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_DEPLOY_STATUS_2_FMT);
+ agent_register_payload(DEPLOYMENT_STATUS_2_FMT, EVP_HUB_TYPE_EVP2_TB,
+ EVP2_DEPLOY_STATUS_2_FMT);
+
+ return 0;
+}
+
+static int
+teardown(void **state)
+{
+ agent_test_exit();
+ return pthread_mutex_destroy(&test.mtx);
+}
+
+int
+main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_deployment_unload_error),
+ };
+
+ return cmocka_run_group_tests(tests, setup, teardown);
+}
diff --git a/test/src/systest/test_mstp_legacy.c b/test/src/systest/test_mstp_legacy.c
new file mode 100644
index 00000000..86437698
--- /dev/null
+++ b/test/src/systest/test_mstp_legacy.c
@@ -0,0 +1,232 @@
+/*
+ * SPDX-FileCopyrightText: 2023-2024 Sony Semiconductor Solutions Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include
+#include
+#include
+
+#include
+
+#include "agent_test.h"
+#include "blob.h"
+#include "evp/sdk.h"
+#include "module_instance_impl.h"
+#include "mqtt_custom.h"
+#include "req.h"
+#include "xlog.h"
+
+#define DEVICE_ID "10001"
+#define MODULE_NAME "requester"
+#define FILENAME "some-filename"
+#define STORAGE_NAME "storage-name"
+#define SOME_SAS_URL \
+ "https://evpstoragecontainer.blob.core.windows.net/evpcontainer/" \
+ "blob_test"
+
+enum test_mstp_payloads {
+ MSTP_REQUEST_1,
+ MSTP_REQUEST_TOPIC_1,
+ MSTP_RESPONSE_1,
+};
+
+struct test_context {
+ struct EVP_client *h;
+ struct evp_agent_context *agent;
+ EVP_RPC_ID reqid;
+};
+
+#define REQID_FMT "%s"
+
+#define EVP1_MSTP_REQUEST_1 \
+ "{" \
+ "\"method\":\"StorageToken\"," \
+ "\"params\":{" \
+ "\"filename\":\"" FILENAME "\"," \
+ "\"moduleInstanceName\":\"" MODULE_NAME "\"" \
+ "}" \
+ "}"
+
+#define EVP1_MSTP_REQUEST_TOPIC_1 "v1/devices/me/rpc/request/" REQID_FMT
+
+#define EVP1_MSTP_RESPONSE_1 \
+ "{" \
+ "\"method\":\"StorageToken\"," \
+ "\"params\":{" \
+ "\"URL\":\"" SOME_SAS_URL "\"," \
+ "\"headers\":{\"x-ms-blob-type\":" \
+ "\"BlockBlob\"}," \
+ "\"cert\":\"56176780-9747-11ed-9bd5-" \
+ "5f138e81521e\"" \
+ "}" \
+ "}"
+
+static void *user_data = "some-user-data";
+static const char reqid_signal[] = "evp_send_storagetoken_request";
+static struct test_context g_ctxt;
+
+enum MQTTErrors
+__wrap_mqtt_publish(struct mqtt_client *client, const char *topic_name,
+ const void *application_message,
+ size_t application_message_size, uint8_t publish_flags)
+{
+ agent_write_to_pipe(topic_name);
+ char *payload = xstrndup((char *)application_message,
+ application_message_size);
+ xlog_info("MQTT publish %s: %s", topic_name, payload);
+ agent_write_to_pipe(payload);
+ free(payload);
+ return MQTT_OK;
+}
+
+unsigned int
+__wrap_blob_put(struct blob_work *wk,
+ unsigned int (*do_put)(struct blob_work *, int))
+{
+ agent_write_to_pipe(wk->url);
+ return BLOB_RESULT_SUCCESS;
+}
+
+static void
+blob_cb(EVP_BLOB_CALLBACK_REASON reason, const void *vp, void *userData)
+{
+ check_expected(reason);
+ check_expected(userData);
+}
+
+static void
+agent_poll_formatted_payload(agent_test_verify_t verify, unsigned int id,
+ const char *reqid)
+{
+ char *payload;
+ payload = agent_get_payload_formatted(id, reqid);
+ agent_poll(verify, payload);
+ free(payload);
+}
+
+static void
+check_request_and_respond(struct test_context *ctxt)
+{
+ char *payload;
+ char *reqid_str;
+
+ agent_poll(verify_equals, reqid_signal);
+
+ xasprintf(&reqid_str, "%lu", ctxt->reqid);
+
+ // wait for the mstp request on mqtt
+ agent_poll_formatted_payload(verify_equals, MSTP_REQUEST_TOPIC_1,
+ reqid_str);
+ agent_poll_formatted_payload(verify_equals, MSTP_REQUEST_1, reqid_str);
+
+ payload = agent_get_payload_formatted(MSTP_RESPONSE_1, reqid_str);
+ agent_send_storagetoken_response(ctxt->agent, payload, reqid_str);
+ free(payload);
+ free(reqid_str);
+}
+
+/**
+ * The goal of this test is to be sure that the EVP SDK supports
+ * EVP1 legacy mstp. It means that storage_name field is optional.
+ * When a module send a blob operation with `storage_name = NULL`
+ * the agent will send a request without this field.
+ *
+ * This test is only executed for EVP1
+ * This test complements test_mstp.c
+ */
+void
+test_mstp_evp1_legacy(void **state)
+{
+
+ if (agent_test_get_hub_type() == EVP_HUB_TYPE_EVP2_TB) {
+ /* This test only applies for evp1 */
+ return;
+ }
+
+ struct test_context *ctxt = *state;
+ // make a blob request
+ EVP_RESULT result;
+
+ struct EVP_BlobRequestEvpExt request;
+ request.remote_name = FILENAME;
+ // storage_name is not required for evp1 (legacy)
+ request.storage_name = NULL;
+
+ // make a local store
+ struct EVP_BlobLocalStore localStore;
+ localStore.filename = FILENAME;
+
+ // the blob operation should fire an mSTP token request
+ result = EVP_blobOperation(ctxt->h, EVP_BLOB_TYPE_EVP_EXT,
+ EVP_BLOB_OP_PUT, &request, &localStore,
+ blob_cb, user_data);
+ assert_int_equal(result, EVP_OK);
+
+ // Expected after 2 other requests
+ check_request_and_respond(ctxt);
+
+ // wait for the http request
+ agent_poll(verify_equals, SOME_SAS_URL);
+
+ // wait for the blob_cb
+ expect_value(blob_cb, reason, EVP_BLOB_CALLBACK_REASON_DONE);
+ expect_value(blob_cb, userData, user_data);
+
+ EVP_processEvent(ctxt->h, 1000);
+}
+
+int
+__wrap_evp_send_storagetoken_request(struct evp_agent_context *agent,
+ struct request *req, JSON_Value *v)
+{
+ int __real_evp_send_storagetoken_request(
+ struct evp_agent_context * agent, struct request * req,
+ JSON_Value * v);
+
+ g_ctxt.reqid = req->id;
+ agent_write_to_pipe(reqid_signal);
+ return __real_evp_send_storagetoken_request(agent, req, v);
+}
+
+int
+setup(void **state)
+{
+ struct test_context *ctxt = *state = &g_ctxt;
+
+ agent_test_setup();
+ agent_register_payload(MSTP_REQUEST_1, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_MSTP_REQUEST_1);
+ agent_register_payload(MSTP_REQUEST_TOPIC_1, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_MSTP_REQUEST_TOPIC_1);
+ agent_register_payload(MSTP_RESPONSE_1, EVP_HUB_TYPE_EVP1_TB,
+ EVP1_MSTP_RESPONSE_1);
+
+ // start agent
+ ctxt->agent = agent_test_start();
+
+ // create instance
+ ctxt->h = evp_agent_add_instance(ctxt->agent, MODULE_NAME);
+ assert_non_null(ctxt->h);
+ return 0;
+}
+
+int
+teardown(void **state)
+{
+ // wait for agent to finish
+ agent_test_exit();
+ return 0;
+}
+
+int
+main(void)
+{
+ // define tests
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_mstp_evp1_legacy),
+ };
+ // setup, run tests and teardown
+ return cmocka_run_group_tests(tests, setup, teardown);
+}
diff --git a/test/src/systest/test_wasm_mod_pause_deployment.c b/test/src/systest/test_wasm_mod_pause_deployment.c
index cc665684..702a148a 100644
--- a/test/src/systest/test_wasm_mod_pause_deployment.c
+++ b/test/src/systest/test_wasm_mod_pause_deployment.c
@@ -264,7 +264,8 @@ pause_deployment_not_in_progress(void **state)
struct evp_agent_context *ctxt = *state;
// Request pause when no module is being downloaded
- assert_int_equal(evp_agent_request_pause_deployment(ctxt), 0);
+ while (evp_agent_request_pause_deployment(ctxt))
+ ;
// Send a new deployment with a module to download
send_deployment(ctxt, DEPLOYMENT_ID1, INSTANCE_ID1, MODULE_1,
diff --git a/tools/fortify/filter-agent.txt b/tools/fortify/filter-agent.txt
index 508c9a4f..17f0311c 100644
--- a/tools/fortify/filter-agent.txt
+++ b/tools/fortify/filter-agent.txt
@@ -558,19 +558,19 @@ B838E55D9366945FE643B14028366303
# sdk.c(268) : allocated -> leak : config end scope : Memory leaked
753C80AA0C46D7EFF76F1EF35D45EAA6
-#[7E30001FB07717CFF2FE5B13587B01B0 : high : Memory Leak : controlflow ]
+# [BAE2BC448B642C2CD798A8FC2C6E6506 : high : Memory Leak : controlflow ]
#
-# sdk.c(302) : Branch taken: (h != NULL)
-# sdk.c(302) : Branch taken: (h->exiting == 0)
-# sdk.c(303) : start -> allocated : r = xcalloc_internal(...)
-# util.c(188) : start -> allocated : vp = calloc(...)
-# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory
-# util.c(189) : Branch not taken: (vp != NULL)
-# util.c(192) : allocated -> allocated : return
-# sdk.c(303) : allocated -> allocated : r refers to dynamically allocated memory
-# sdk.c(310) : allocated -> allocated : r no longer refers to dynamically allocated memory
-# sdk.c(310) : allocated -> leak : r end scope : Memory leaked
-7E30001FB07717CFF2FE5B13587B01B0
+# sdk.c(305) : Branch taken: (h != NULL)
+# sdk.c(305) : Branch taken: (h->exiting == 0)
+# sdk.c(306) : start -> allocated : r = xcalloc_internal(...)
+# util.c(188) : start -> allocated : vp = calloc(...)
+# util.c(188) : allocated -> allocated : vp refers to dynamically allocated memory
+# util.c(189) : Branch not taken: (vp != NULL)
+# util.c(192) : allocated -> allocated : return
+# sdk.c(306) : allocated -> allocated : r refers to dynamically allocated memory
+# sdk.c(313) : allocated -> allocated : r no longer refers to dynamically allocated memory
+# sdk.c(313) : allocated -> leak : r end scope : Memory leaked
+BAE2BC448B642C2CD798A8FC2C6E6506
#[753C80AA0C46D7EFF76F1EF35D45EAA6 : high : Memory Leak : controlflow ]
#
@@ -589,42 +589,42 @@ B838E55D9366945FE643B14028366303
# False positive. The ownership for instance_name is transferred to the
# caller when successful. Otherwise, the memory is released via free(3).
-#[BC68A3AE07F66F3EA7F344AA1CF6B9E1 : high : Memory Leak : controlflow ]
-#
-# sdk.c(1351) : start -> allocated : instance_name = strdup(...)
-# sdk.c(1351) : allocated -> allocated : instance_name refers to dynamically allocated memory
-# sdk.c(1353) : Branch taken: (evp_ext->storage_name != NULL)
-# sdk.c(1356) : Branch taken: (storage_name == NULL)
-# sdk.c(1358) : goto
-# sdk.c(1372) : Branch not taken: (ret == 0)
-# sdk.c(1377) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory
-# sdk.c(1377) : allocated -> leak : instance_name end scope : Memory leaked
-BC68A3AE07F66F3EA7F344AA1CF6B9E1
+# [E77DED688408DBFD92E99EDCB968F3C3 : high : Memory Leak : controlflow ]
+#
+# sdk.c(1323) : start -> allocated : instance_name = strdup(...)
+# sdk.c(1323) : allocated -> allocated : instance_name refers to dynamically allocated memory
+# sdk.c(1326) : Branch not taken: (instance_name != NULL)
+# sdk.c(1326) : Branch taken: (remote_name == NULL)
+# sdk.c(1328) : goto
+# sdk.c(1338) : Branch not taken: (ret == 0)
+# sdk.c(1343) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory
+# sdk.c(1343) : allocated -> leak : instance_name end scope : Memory leaked
+E77DED688408DBFD92E99EDCB968F3C3
# False positive.
-#[88FACBFC4F408F7012D2315A7D788BF9 : high : Memory Leak : controlflow ]
+# [CF748D3292048B92728F6F86597A864C : high : Memory Leak : controlflow ]
#
-# sdk.c(1321) : start -> allocated : remote_name = strdup(...)
-# sdk.c(1321) : allocated -> allocated : remote_name refers to dynamically allocated memory
-# sdk.c(1323) : Branch taken: (instance_name == NULL)
-# sdk.c(1325) : goto
-# sdk.c(1335) : Branch not taken: (ret == 0)
-# sdk.c(1340) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory
-# sdk.c(1340) : allocated -> leak : remote_name end scope : Memory leaked
-88FACBFC4F408F7012D2315A7D788BF9
+# sdk.c(1324) : start -> allocated : remote_name = strdup(...)
+# sdk.c(1324) : allocated -> allocated : remote_name refers to dynamically allocated memory
+# sdk.c(1326) : Branch taken: (instance_name == NULL)
+# sdk.c(1328) : goto
+# sdk.c(1338) : Branch not taken: (ret == 0)
+# sdk.c(1343) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory
+# sdk.c(1343) : allocated -> leak : remote_name end scope : Memory leaked
+CF748D3292048B92728F6F86597A864C
# False positive. Similar to 2875963782EF8F6D3886C98861CEC80A.
-#[05D749459E2661F49E9A2800A98323B3 : high : Memory Leak : controlflow ]
-#
-# sdk.c(1350) : start -> allocated : remote_name = strdup(...)
-# sdk.c(1350) : allocated -> allocated : remote_name refers to dynamically allocated memory
-# sdk.c(1353) : Branch taken: (evp_ext->storage_name != NULL)
-# sdk.c(1356) : Branch taken: (storage_name == NULL)
-# sdk.c(1358) : goto
-# sdk.c(1372) : Branch not taken: (ret == 0)
-# sdk.c(1377) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory
-# sdk.c(1377) : allocated -> leak : remote_name end scope : Memory leaked
-05D749459E2661F49E9A2800A98323B3
+# [157F3BC11F711CA6BADF8A6DF41A8448 : high : Memory Leak : controlflow ]
+#
+# sdk.c(1353) : start -> allocated : remote_name = strdup(...)
+# sdk.c(1353) : allocated -> allocated : remote_name refers to dynamically allocated memory
+# sdk.c(1356) : Branch taken: (evp_ext->storage_name != NULL)
+# sdk.c(1359) : Branch taken: (storage_name == NULL)
+# sdk.c(1361) : goto
+# sdk.c(1375) : Branch not taken: (ret == 0)
+# sdk.c(1380) : allocated -> allocated : remote_name no longer refers to dynamically allocated memory
+# sdk.c(1380) : allocated -> leak : remote_name end scope : Memory leaked
+157F3BC11F711CA6BADF8A6DF41A8448
#[13DD2A203C18A517C7B4840513317DB0 : high : Memory Leak : controlflow ]
#
@@ -640,30 +640,30 @@ BC68A3AE07F66F3EA7F344AA1CF6B9E1
# sdk.c(268) : allocated -> leak : config end scope : Memory leaked
13DD2A203C18A517C7B4840513317DB0
-#[89E9B42F5C5AF6377B59C48DE9E785F7 : high : Memory Leak : controlflow ]
-#
-# sdk.c(1016) : Branch not taken: (g_mqtt_client != NULL)
-# sdk.c(1022) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, len) != 0)
-# sdk.c(1033) : start -> allocated : state = malloc(...)
-# sdk.c(1033) : allocated -> allocated : state refers to dynamically allocated memory
-# sdk.c(1034) : Branch not taken: (state != NULL)
-# sdk.c(1054) : Branch not taken: (oevent == NULL)
-# sdk.c(1082) : Branch not taken: (ret == 0)
-# sdk.c(1085) : allocated -> allocated : state no longer refers to dynamically allocated memory
-# sdk.c(1085) : allocated -> leak : state end scope : Memory leaked
-89E9B42F5C5AF6377B59C48DE9E785F7
-
-#[4E89E0F5591AA8A38639E4FE6EB0A8B2 : high : Memory Leak : controlflow ]
-#
-# sdk.c(1320) : start -> allocated : instance_name = strdup(...)
-# sdk.c(1320) : allocated -> allocated : instance_name refers to dynamically allocated memory
-# sdk.c(1323) : Branch not taken: (instance_name != NULL)
-# sdk.c(1323) : Branch taken: (remote_name == NULL)
-# sdk.c(1325) : goto
-# sdk.c(1335) : Branch not taken: (ret == 0)
-# sdk.c(1340) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory
-# sdk.c(1340) : allocated -> leak : instance_name end scope : Memory leaked
-4E89E0F5591AA8A38639E4FE6EB0A8B2
+# [A22C8E3EDE60D6EE0EDE28AA495E708C : high : Memory Leak : controlflow ]
+#
+# sdk.c(1019) : Branch not taken: (g_mqtt_client != NULL)
+# sdk.c(1025) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, len) != 0)
+# sdk.c(1036) : start -> allocated : state = malloc(...)
+# sdk.c(1036) : allocated -> allocated : state refers to dynamically allocated memory
+# sdk.c(1037) : Branch not taken: (state != NULL)
+# sdk.c(1057) : Branch not taken: (oevent == NULL)
+# sdk.c(1085) : Branch not taken: (ret == 0)
+# sdk.c(1088) : allocated -> allocated : state no longer refers to dynamically allocated memory
+# sdk.c(1088) : allocated -> leak : state end scope : Memory leaked
+A22C8E3EDE60D6EE0EDE28AA495E708C
+
+# [19F336B4C1767F9513F6BF71B012C12F : high : Memory Leak : controlflow ]
+#
+# sdk.c(1354) : start -> allocated : instance_name = strdup(...)
+# sdk.c(1354) : allocated -> allocated : instance_name refers to dynamically allocated memory
+# sdk.c(1356) : Branch taken: (evp_ext->storage_name != NULL)
+# sdk.c(1359) : Branch taken: (storage_name == NULL)
+# sdk.c(1361) : goto
+# sdk.c(1375) : Branch not taken: (ret == 0)
+# sdk.c(1380) : allocated -> allocated : instance_name no longer refers to dynamically allocated memory
+# sdk.c(1380) : allocated -> leak : instance_name end scope : Memory leaked
+19F336B4C1767F9513F6BF71B012C12F
# False positive
#
@@ -676,14 +676,14 @@ BC68A3AE07F66F3EA7F344AA1CF6B9E1
# gets each element in the queue
# cast to specific event.
# free at the end of each event by sdk_free_event
-#[3E1476C1E6658229EE0E5AF63E7786B7 : high : Memory Leak : controlflow ]
+# [581A9337EC14CC230A42B3A7DFCD1A25 : high : Memory Leak : controlflow ]
#
-# sdk.c(1659) : start -> allocated : event_message = malloc(...)
-# sdk.c(1659) : allocated -> allocated : event_message refers to dynamically allocated memory
-# sdk.c(1661) : Branch not taken: (event_message != NULL)
-# sdk.c(1692) : allocated -> allocated : event_message no longer refers to dynamically allocated memory
-# sdk.c(1692) : allocated -> leak : event_message end scope : Memory leaked
-3E1476C1E6658229EE0E5AF63E7786B7
+# sdk.c(1662) : start -> allocated : event_message = malloc(...)
+# sdk.c(1662) : allocated -> allocated : event_message refers to dynamically allocated memory
+# sdk.c(1664) : Branch not taken: (event_message != NULL)
+# sdk.c(1696) : allocated -> allocated : event_message no longer refers to dynamically allocated memory
+# sdk.c(1696) : allocated -> leak : event_message end scope : Memory leaked
+581A9337EC14CC230A42B3A7DFCD1A25
# False positive (idem of previous)
#
@@ -696,28 +696,28 @@ BC68A3AE07F66F3EA7F344AA1CF6B9E1
# gets each element in the queue
# cast to specific event.
# free at the end of each event by sdk_free_event
-#[B3B20F3988D18CC8CA5C28514719C705 : high : Memory Leak : controlflow ]
-#
-# sdk.c(1721) : Branch not taken: (g_mqtt_client != NULL)
-# sdk.c(1725) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, total_size) != 0)
-# sdk.c(1729) : start -> allocated : t = malloc(...)
-# sdk.c(1729) : allocated -> allocated : t refers to dynamically allocated memory
-# sdk.c(1730) : Branch not taken: (t != NULL)
-# sdk.c(1760) : allocated -> allocated : t no longer refers to dynamically allocated memory
-# sdk.c(1760) : allocated -> leak : t end scope : Memory leaked
-B3B20F3988D18CC8CA5C28514719C705
-
-#[D0731D514166A49C8FFB53F1F9FD92A2 : high : Memory Leak : controlflow ]
-#
-# sdk.c(1817) : Branch not taken: (response != NULL)
-# sdk.c(1826) : Branch not taken: (g_mqtt_client != NULL)
-# sdk.c(1831) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, outsz) != 0)
-# sdk.c(1835) : start -> allocated : r = malloc(...)
-# sdk.c(1835) : allocated -> allocated : r refers to dynamically allocated memory
-# sdk.c(1836) : Branch not taken: (r != NULL)
-# sdk.c(1864) : allocated -> allocated : r no longer refers to dynamically allocated memory
-# sdk.c(1864) : allocated -> leak : r end scope : Memory leaked
-D0731D514166A49C8FFB53F1F9FD92A2
+# [234DCC25865816EAF391DA8AF23E9794 : high : Memory Leak : controlflow ]
+#
+# sdk.c(1725) : Branch not taken: (g_mqtt_client != NULL)
+# sdk.c(1729) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, total_size) != 0)
+# sdk.c(1733) : start -> allocated : t = malloc(...)
+# sdk.c(1733) : allocated -> allocated : t refers to dynamically allocated memory
+# sdk.c(1734) : Branch not taken: (t != NULL)
+# sdk.c(1764) : allocated -> allocated : t no longer refers to dynamically allocated memory
+# sdk.c(1764) : allocated -> leak : t end scope : Memory leaked
+234DCC25865816EAF391DA8AF23E9794
+
+# [A68E05E17E134D7BCDF2863CB397A042 : high : Memory Leak : controlflow ]
+#
+# sdk.c(1821) : Branch not taken: (response != NULL)
+# sdk.c(1830) : Branch not taken: (g_mqtt_client != NULL)
+# sdk.c(1835) : Branch not taken: (xmqtt_request_fits(g_mqtt_client, outsz) != 0)
+# sdk.c(1839) : start -> allocated : r = malloc(...)
+# sdk.c(1839) : allocated -> allocated : r refers to dynamically allocated memory
+# sdk.c(1840) : Branch not taken: (r != NULL)
+# sdk.c(1868) : allocated -> allocated : r no longer refers to dynamically allocated memory
+# sdk.c(1868) : allocated -> leak : r end scope : Memory leaked
+A68E05E17E134D7BCDF2863CB397A042
# It is true response might not be a null-terminated string, as it is
# read from user input. However, this same assumption is made in a few
@@ -828,16 +828,16 @@ D2CB91D8DE70456F32CA8103BE32E947
# False positive.
# Fortify fails to see sem is a semaphore that would block until
# the event is handled (and free(3)d) by the module instance thread.
-#[16C3E81F20D2E967B9D97592D8968F69 : high : Memory Leak : controlflow ]
+# [B74502983F4BBB99376A68FF938F6CFB : high : Memory Leak : controlflow ]
#
-# sdk.c(1099) : Branch not taken: (sem_init((&sem), 0, 0) == 0)
-# sdk.c(1106) : Branch taken: (h->exiting == 0)
-# sdk.c(1107) : start -> allocated : event = malloc(...)
-# sdk.c(1107) : allocated -> allocated : event refers to dynamically allocated memory
-# sdk.c(1109) : Branch not taken: (event != NULL)
-# sdk.c(1133) : allocated -> allocated : event no longer refers to dynamically allocated memory
-# sdk.c(1133) : allocated -> leak : event end scope : Memory leaked
-16C3E81F20D2E967B9D97592D8968F69
+# sdk.c(1102) : Branch not taken: (sem_init((&sem), 0, 0) == 0)
+# sdk.c(1109) : Branch taken: (h->exiting == 0)
+# sdk.c(1110) : start -> allocated : event = malloc(...)
+# sdk.c(1110) : allocated -> allocated : event refers to dynamically allocated memory
+# sdk.c(1112) : Branch not taken: (event != NULL)
+# sdk.c(1136) : allocated -> allocated : event no longer refers to dynamically allocated memory
+# sdk.c(1136) : allocated -> leak : event end scope : Memory leaked
+B74502983F4BBB99376A68FF938F6CFB
# IMPORTANT NOTE: This is an actual memory leak (!)
# For implementations using sdk_local_wasm.c, response_copy is never freed.
@@ -2677,29 +2677,28 @@ C382DF34B7262C9187069ABBC7FEEDCF
# The string gets a final zero termination regardless, not counted in the
# string length (in compliance with the FlatBuffers format)."
-#[3397B3B424EF87DF712DEFD26B45C7AC : high : String Termination Error : dataflow ]
-#sdk.c(1059) : ->strcmp(1)
-# sdk_remote.c(403) : ->EVP_impl_sendState(2)
-# sdk_remote.c(397) : <=> (topic)
-# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : return
-# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : <=> (elem__tmp)
-# sdk_remote.c(397) : <->EVP_SDK_StateInput_topic(0->return)
-# sdk_remote.c(394) : <=> (state)
-# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : return
-# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : <=> (elem__tmp)
-# sdk_remote.c(394) : <->EVP_SDK_Request_body(0->return)
-# sdk_remote.c(952) : ->process_send_state(1)
-# sdk_remote.c(909) : <=> (req)
-# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1031) : return
-# sdk_remote.c(909) : <->EVP_SDK_Request_as_root(0->return)
-# sdkrpc/server.c(96) : ->sdk_process_request(0)
-# sdkrpc/server.c(85) : <- readall(1)
-# ioutil.c(22) : <- read(1)
-#
+# [E1EB5963E3FE75C62086DEB9AF360BC1 : high : String Termination Error : dataflow ]
+# sdk.c(1062) : ->strcmp(1)
+# sdk_remote.c(403) : ->EVP_impl_sendState(2)
+# sdk_remote.c(397) : <=> (topic)
+# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : return
+# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(583) : <=> (elem__tmp)
+# sdk_remote.c(397) : <->EVP_SDK_StateInput_topic(0->return)
+# sdk_remote.c(394) : <=> (state)
+# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : return
+# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1033) : <=> (elem__tmp)
+# sdk_remote.c(394) : <->EVP_SDK_Request_body(0->return)
+# sdk_remote.c(952) : ->process_send_state(1)
+# sdk_remote.c(909) : <=> (req)
+# /__w/wedge-agent/wedge-agent/include/sdkenc/sdk_reader.h(1031) : return
+# sdk_remote.c(909) : <->EVP_SDK_Request_as_root(0->return)
+# sdkrpc/server.c(96) : ->sdk_process_request(0)
+# sdkrpc/server.c(85) : <- readall(1)
+# ioutil.c(22) : <- read(1)
## StateInput_topic is a Flatbuffer String. In sdkenc/sdk.fbs:
# table StateInput {
# topic:string (required);
-3397B3B424EF87DF712DEFD26B45C7AC
+E1EB5963E3FE75C62086DEB9AF360BC1
# StateInput_topic is a Flatbuffer String. In sdkenc/sdk.fbs:
#[263E550BDAD8048B7714327862E5FA4B : high : String Termination Error : dataflow ]
diff --git a/version.mk b/version.mk
index f9d2a35b..752263c3 100644
--- a/version.mk
+++ b/version.mk
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: Apache-2.0
-VERSION = 1.45.0
+VERSION = 1.48.0
COMMIT_HASH = $(shell git describe --always --abbrev=0 --dirty --match "NOT A TAG")
define VERSION_BODY