[修改] 增加freeRTOS
1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
63
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/CONTRIBUTING.md
vendored
Normal file
63
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
|
||||
documentation, we greatly value feedback and contributions from our community.
|
||||
|
||||
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
|
||||
information to effectively respond to your bug report or contribution.
|
||||
|
||||
|
||||
## Reporting Bugs/Feature Requests
|
||||
|
||||
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
|
||||
|
||||
When filing an issue, please check [existing open](https://github.com/FreeRTOS/coreHTTP/issues), or [recently closed](https://github.com/FreeRTOS/coreHTTP/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already
|
||||
reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
|
||||
|
||||
* A reproducible test case or series of steps
|
||||
* The version of our code being used
|
||||
* Any modifications you've made relevant to the bug
|
||||
* Anything unusual about your environment or deployment
|
||||
|
||||
|
||||
## Contributing via Pull Requests
|
||||
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
|
||||
|
||||
1. You are working against the latest source on the *main* branch.
|
||||
1. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
|
||||
1. You open an issue to discuss any significant work - we would hate for your time to be wasted.
|
||||
|
||||
To send us a pull request, please:
|
||||
|
||||
1. Fork the repository.
|
||||
1. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
|
||||
1. Ensure that your contributions conform to the [style guide](https://docs.aws.amazon.com/embedded-csdk/202011.00/lib-ref/docs/doxygen/output/html/guide_developer_styleguide.html).
|
||||
1. Format your code with uncrustify, using the config available in [FreeRTOS/CI-CD-Github-Actions](https://github.com/FreeRTOS/CI-CD-Github-Actions/blob/main/formatting/uncrustify.cfg).
|
||||
1. Ensure local tests pass.
|
||||
1. Commit to your fork using clear commit messages.
|
||||
1. Send us a pull request, answering any default questions in the pull request interface.
|
||||
1. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
|
||||
|
||||
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
|
||||
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
|
||||
|
||||
|
||||
## Finding contributions to work on
|
||||
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/FreeRTOS/coreHTTP/labels?q=help+wanted) issues is a great place to start.
|
||||
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
|
||||
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
|
||||
opensource-codeofconduct@amazon.com with any additional questions or comments.
|
||||
|
||||
|
||||
## Security issue notifications
|
||||
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
|
||||
|
||||
|
||||
## Licensing
|
||||
|
||||
See the [LICENSE](../LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
|
||||
|
||||
We may ask you to sign a [Contributor License Agreement (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
|
||||
26
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/memory_statistics_config.json
vendored
Normal file
26
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/memory_statistics_config.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"lib_name": "coreHTTP",
|
||||
"src": [
|
||||
"source/core_http_client.c",
|
||||
{
|
||||
"file": "source/dependency/3rdparty/llhttp/src/api.c",
|
||||
"tag": "llhttp"
|
||||
},
|
||||
{
|
||||
"file": "source/dependency/3rdparty/llhttp/src/http.c",
|
||||
"tag": "llhttp"
|
||||
},
|
||||
{
|
||||
"file": "source/dependency/3rdparty/llhttp/src/llhttp.c",
|
||||
"tag": "llhttp"
|
||||
}
|
||||
],
|
||||
"include": [
|
||||
"source/include",
|
||||
"source/interface",
|
||||
"source/dependency/3rdparty/llhttp/include"
|
||||
],
|
||||
"compiler_flags": [
|
||||
"HTTP_DO_NOT_USE_CUSTOM_CONFIG"
|
||||
]
|
||||
}
|
||||
126
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/workflows/ci.yml
vendored
Normal file
126
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
name: CI Checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
unittest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone This Repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: |
|
||||
sudo apt-get install -y lcov
|
||||
cmake -S test -B build/ \
|
||||
-G "Unix Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -DNDEBUG'
|
||||
make -C build/ all
|
||||
- name: Test
|
||||
run: |
|
||||
cd build/
|
||||
ctest -E system --output-on-failure
|
||||
cd ..
|
||||
- name: Run Coverage
|
||||
run: |
|
||||
make -C build/ coverage
|
||||
declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId\*" "\*mocks\*" "\*3rdparty\*")
|
||||
echo ${EXCLUDE[@]} | xargs lcov --rc lcov_branch_coverage=1 -r build/coverage.info -o build/coverage.info
|
||||
lcov --rc lcov_branch_coverage=1 --list build/coverage.info
|
||||
- name: Check Coverage
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
|
||||
with:
|
||||
path: ./build/coverage.info
|
||||
complexity:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Check complexity
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/complexity@main
|
||||
with:
|
||||
path: ./
|
||||
doxygen:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run doxygen build
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/doxygen@main
|
||||
with:
|
||||
path: ./
|
||||
spell-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone This Repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Run spellings check
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/spellings@main
|
||||
with:
|
||||
path: ./
|
||||
formatting:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Check formatting
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/formatting@main
|
||||
with:
|
||||
path: ./
|
||||
ssot-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout this repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: current
|
||||
- name: Checkout coreMQTT
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: main
|
||||
repository: FreeRTOS/coreMQTT
|
||||
path: ssot
|
||||
- name: Check transport_interface.h
|
||||
run: |
|
||||
SSOT_FILE="ssot/source/interface/transport_interface.h"
|
||||
CURRENT_FILE="current/source/interface/transport_interface.h"
|
||||
diff <(tail -n +3 $SSOT_FILE) <(tail -n +3 $CURRENT_FILE)
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "transport_interface.h differs from coreMQTT."
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
git-secrets:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout awslabs/git-secrets
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: awslabs/git-secrets
|
||||
ref: master
|
||||
path: git-secrets
|
||||
- name: Install git-secrets
|
||||
run: cd git-secrets && sudo make install && cd ..
|
||||
- name: Run git-secrets
|
||||
run: |
|
||||
git-secrets --register-aws
|
||||
git-secrets --scan
|
||||
memory_statistics:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Install Python3
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.7.10'
|
||||
- name: Measure sizes
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/memory_statistics@main
|
||||
with:
|
||||
config: .github/memory_statistics_config.json
|
||||
check_against: docs/doxygen/include/size_table.md
|
||||
11
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/workflows/doxygen.yml
vendored
Normal file
11
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/workflows/doxygen.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
name: Doxygen Generation
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
doxygen-generation:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Doxygen generation
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main
|
||||
138
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/workflows/release.yml
vendored
Normal file
138
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
name: Release automation
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit_id:
|
||||
description: 'Commit ID to tag and create a release for'
|
||||
required: true
|
||||
version_number:
|
||||
description: 'Release Version Number (Eg, v1.0.0)'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
tag-commit:
|
||||
name: Generate SBOM and tag commit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit_id }}
|
||||
- name: Configure git identity
|
||||
run: |
|
||||
git config --global user.name ${{ github.actor }}
|
||||
git config --global user.email ${{ github.actor }}@users.noreply.github.com
|
||||
- name: create a new branch that references commit id
|
||||
run: git checkout -b ${{ github.event.inputs.version_number }} ${{ github.event.inputs.commit_id }}
|
||||
- name: Generate SBOM
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/sbom-generator@main
|
||||
with:
|
||||
repo_path: ./
|
||||
source_path: ./source
|
||||
- name: commit SBOM file
|
||||
run: |
|
||||
git add .
|
||||
git commit -m 'Update SBOM'
|
||||
git push -u origin ${{ github.event.inputs.version_number }}
|
||||
- name: Tag Commit and Push to remote
|
||||
run: |
|
||||
git tag ${{ github.event.inputs.version_number }} -a -m "coreHTTP Library ${{ github.event.inputs.version_number }}"
|
||||
git push origin --tags
|
||||
- name: Verify tag on remote
|
||||
run: |
|
||||
git tag -d ${{ github.event.inputs.version_number }}
|
||||
git remote update
|
||||
git checkout tags/${{ github.event.inputs.version_number }}
|
||||
git diff ${{ github.event.inputs.commit_id }} tags/${{ github.event.inputs.version_number }}
|
||||
create-zip:
|
||||
needs: tag-commit
|
||||
name: Create ZIP and verify package for release asset.
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install ZIP tools
|
||||
run: sudo apt-get install zip unzip
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.commit_id }}
|
||||
path: coreHTTP
|
||||
submodules: recursive
|
||||
- name: Checkout disabled submodules
|
||||
run: |
|
||||
cd coreHTTP
|
||||
git submodule update --init --checkout --recursive
|
||||
- name: Create ZIP
|
||||
run: |
|
||||
zip -r coreHTTP-${{ github.event.inputs.version_number }}.zip coreHTTP -x "*.git*"
|
||||
ls ./
|
||||
- name: Validate created ZIP
|
||||
run: |
|
||||
mkdir zip-check
|
||||
mv coreHTTP-${{ github.event.inputs.version_number }}.zip zip-check
|
||||
cd zip-check
|
||||
unzip coreHTTP-${{ github.event.inputs.version_number }}.zip -d coreHTTP-${{ github.event.inputs.version_number }}
|
||||
ls coreHTTP-${{ github.event.inputs.version_number }}
|
||||
diff -r -x "*.git*" coreHTTP-${{ github.event.inputs.version_number }}/coreHTTP/ ../coreHTTP/
|
||||
cd ../
|
||||
- name: Build
|
||||
run: |
|
||||
cd zip-check/coreHTTP-${{ github.event.inputs.version_number }}/coreHTTP
|
||||
sudo apt-get install -y lcov
|
||||
cmake -S test -B build/ \
|
||||
-G "Unix Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -DNDEBUG'
|
||||
make -C build/ all
|
||||
- name: Test
|
||||
run: |
|
||||
cd zip-check/coreHTTP-${{ github.event.inputs.version_number }}/coreHTTP/build/
|
||||
ctest -E system --output-on-failure
|
||||
cd ..
|
||||
- name: Create artifact of ZIP
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: coreHTTP-${{ github.event.inputs.version_number }}.zip
|
||||
path: zip-check/coreHTTP-${{ github.event.inputs.version_number }}.zip
|
||||
deploy-doxygen:
|
||||
needs: tag-commit
|
||||
name: Deploy doxygen documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Doxygen generation
|
||||
uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main
|
||||
with:
|
||||
ref: ${{ github.event.inputs.version_number }}
|
||||
add_release: "true"
|
||||
create-release:
|
||||
needs:
|
||||
- create-zip
|
||||
- deploy-doxygen
|
||||
name: Create Release and Upload Release Asset
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.event.inputs.version_number }}
|
||||
release_name: ${{ github.event.inputs.version_number }}
|
||||
body: Release ${{ github.event.inputs.version_number }} of the coreHTTP Library.
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Download ZIP artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: coreHTTP-${{ github.event.inputs.version_number }}.zip
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./coreHTTP-${{ github.event.inputs.version_number }}.zip
|
||||
asset_name: coreHTTP-${{ github.event.inputs.version_number }}.zip
|
||||
asset_content_type: application/zip
|
||||
13
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.gitignore
vendored
Normal file
13
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Ignore documentation output.
|
||||
**/docs/**/output/*
|
||||
|
||||
# Ignore CMake build directory.
|
||||
build/
|
||||
|
||||
# Ignore build artifacts
|
||||
*.o
|
||||
|
||||
# Ignore code coverage artifacts
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
7
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.gitmodules
vendored
Normal file
7
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/.gitmodules
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
[submodule "test/unit-test/CMock"]
|
||||
path = test/unit-test/CMock
|
||||
url = https://github.com/ThrowTheSwitch/CMock.git
|
||||
update = none
|
||||
[submodule "source/dependency/3rdparty/llhttp"]
|
||||
path = source/dependency/3rdparty/llhttp
|
||||
url = https://github.com/nodejs/llhttp.git
|
||||
@ -0,0 +1,57 @@
|
||||
# Changelog for coreHTTP Client Library
|
||||
|
||||
|
||||
## v3.0.0 (October 2022)
|
||||
|
||||
### Updates
|
||||
|
||||
- [#134](https://github.com/FreeRTOS/coreHTTP/pull/134), [#138](https://github.com/FreeRTOS/coreHTTP/pull/138) Replace strncpy with memcpy to remove warnings
|
||||
- [#132](https://github.com/FreeRTOS/coreHTTP/pull/132), [#142](https://github.com/FreeRTOS/coreHTTP/pull/142), [#144](https://github.com/FreeRTOS/coreHTTP/pull/144) MISRA C:2012 compliance update
|
||||
- [#129](https://github.com/FreeRTOS/coreHTTP/pull/129) Update http-parser to use llhttp
|
||||
- [#127](https://github.com/FreeRTOS/coreHTTP/pull/127) CBMC proof changes, and updates to use llhttp
|
||||
- [#126](https://github.com/FreeRTOS/coreHTTP/pull/126) Replace http-parser with llhttp. Using llhttp requires C99, so this library will need to use C99 at minimum as well. The swap to llhttp impacts the HTTPParsingContext_t struct, as well as many of the functions in coreHTTP. coreHTTP APIs preserve backwards compatibility by usage, however any use of the internal structures or dependency on http parser directly can cause compatibility issues.
|
||||
- [#125](https://github.com/FreeRTOS/coreHTTP/pull/125) Add response buffer len check
|
||||
|
||||
## v2.1.0 (Nov 2021)
|
||||
|
||||
### Updates
|
||||
|
||||
- [#114](https://github.com/FreeRTOS/coreHTTP/pull/114) Update http-parser version in manifest to reflect commit
|
||||
- [#112](https://github.com/FreeRTOS/coreHTTP/pull/112) Add function prototypes for exported functions to CBMC proof harnesses
|
||||
- [#111](https://github.com/FreeRTOS/coreHTTP/pull/111) Update Doxygen version to 1.9.2
|
||||
|
||||
## v2.0.2 (July 2021)
|
||||
|
||||
### Updates
|
||||
|
||||
- [#109](https://github.com/FreeRTOS/coreHTTP/pull/109) Add C++ header guards
|
||||
- [#106](https://github.com/FreeRTOS/coreHTTP/pull/106) Update case-insensitive compare function for header-field parser
|
||||
- [#104](https://github.com/FreeRTOS/coreHTTP/pull/104) Update CBMC proofs to work with the latest version of CBMC
|
||||
|
||||
## v2.0.1 (February 2021)
|
||||
|
||||
### Other
|
||||
|
||||
- [#89](https://github.com/FreeRTOS/coreHTTP/pull/89) Fix documentation of memory size estimates of the library.
|
||||
|
||||
## v2.0.0 (December 2020)
|
||||
|
||||
### Updates
|
||||
|
||||
- [#83](https://github.com/FreeRTOS/coreHTTP/pull/83) Implement transport send and receive retry timeouts in coreHTTP. This change adds a timestamp callback function to the HTTPResponse_t struct, and new configuration macros to set the transport send and receive retry timeouts. Due to the HTTPResponse_t struct field addition, coreHTTP v2.0.0 is not backward compatible under certain conditions.
|
||||
- [#79](https://github.com/FreeRTOS/coreHTTP/pull/79), [#82](https://github.com/FreeRTOS/coreHTTP/pull/82) transport_interface.h documentation updates.
|
||||
- [#75](https://github.com/FreeRTOS/coreHTTP/pull/75) Small fix to cast logging arguments to types matching the format specifiers.
|
||||
|
||||
### Other
|
||||
- [#70](https://github.com/FreeRTOS/coreHTTP/pull/70), [#72](https://github.com/FreeRTOS/coreHTTP/pull/72), [#78](https://github.com/FreeRTOS/coreHTTP/pull/78) Github actions updates.
|
||||
- [#73](https://github.com/FreeRTOS/coreHTTP/pull/73), [#76](https://github.com/FreeRTOS/coreHTTP/pull/76) Github repo chores.
|
||||
- [#71](https://github.com/FreeRTOS/coreHTTP/pull/71) CBMC automation chore.
|
||||
- [#81](https://github.com/FreeRTOS/coreHTTP/pull/81), [#84](https://github.com/FreeRTOS/coreHTTP/pull/84) Doxygen memory estimates table update.
|
||||
|
||||
## v1.0.0 November 2020
|
||||
|
||||
This is the first release of the coreHTTP client library in this repository.
|
||||
|
||||
The HTTP client library is a client-side implementation that supports a subset
|
||||
of the HTTP/1.1 protocol. It is optimized for resource-constrained devices, and
|
||||
does not allocate any memory.
|
||||
@ -0,0 +1,19 @@
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -0,0 +1,95 @@
|
||||
# MISRA Compliance
|
||||
|
||||
The HTTP Client library files conform to the [MISRA C:2012](https://www.misra.org.uk)
|
||||
guidelines, with some noted exceptions. Compliance is checked with Coverity static analysis.
|
||||
The specific deviations, suppressed inline, are listed below.
|
||||
|
||||
Additionally, [MISRA configuration file](https://github.com/FreeRTOS/coreHTTP/blob/main/tools/coverity/misra.config) contains the project wide deviations.
|
||||
|
||||
### Suppressed with Coverity Comments
|
||||
To find the deviation references in the source files run grep on the source code
|
||||
with ( Assuming rule 5.4 violation; with justification in point 2 ):
|
||||
```
|
||||
grep 'MISRA Ref 5.4.2' . -rI
|
||||
```
|
||||
|
||||
#### Rule 5.4
|
||||
_Ref 5.4-1_
|
||||
|
||||
- MISRA Rule 5.4 flags the following macro's name as ambiguous from the
|
||||
one postfixed with _LEN. This rule is suppressed for naming consistency with
|
||||
other HTTP header field and value string and length macros in this file.
|
||||
|
||||
_Ref 5.4-2_
|
||||
|
||||
- MISRA Rule 5.4 flags the following macro's name as ambiguous from the one
|
||||
above it. This rule is suppressed for naming consistency with other HTTP
|
||||
header field and value string and length macros in this file.
|
||||
|
||||
_Ref 5.4-3_
|
||||
|
||||
- MISRA Rule 5.4 flags the following macro's name as ambiguous from the one
|
||||
postfixed with _LEN. This rule is suppressed for naming consistency with
|
||||
other HTTP header field and value string and length macros in this file.
|
||||
|
||||
_Ref 5.4-4_
|
||||
|
||||
- MISRA Rule 5.4 flags the following macro's name as ambiguous from the one
|
||||
above it. This rule is suppressed for naming consistency with other HTTP
|
||||
header field and value string and length macros in this file.
|
||||
|
||||
_Ref 5.4-5_
|
||||
|
||||
- MISRA Rule 5.4 flags the following macro's name as ambiguous from the one
|
||||
postfixed with _LEN. This rule is suppressed for naming consistency with
|
||||
other HTTP header field and value string and length macros in this file.
|
||||
|
||||
_Ref 5.4-6_
|
||||
|
||||
- MISRA Rule 5.4 flags the following macro's name as ambiguous from the one
|
||||
above it. This rule is suppressed for naming consistency with other HTTP
|
||||
header field and value string and length macros in this file.
|
||||
|
||||
#### Rule 10.8
|
||||
_Ref 10.8.1_
|
||||
|
||||
- MISRA Rule 10.8 The size of the headers is found by taking the current location
|
||||
being parsed and subtracting it from the start of the headers. The start of
|
||||
the headers is set on the first header field found from http-parser. This always
|
||||
comes before finding the header length; if it does not, an assertion is triggered.
|
||||
This rule is suppressed because in the previous statement it is
|
||||
asserted that the pointer difference will never be negative.
|
||||
|
||||
#### Rule 14.3
|
||||
_Ref 14.3.1_
|
||||
|
||||
- MISRA Rule 14.3 The third-party http-parser library sets a uint64_t type field to
|
||||
`ULLONG_MAX` or `( ( uint64_t ) -1 )`, during its internal parsing. Coverity MISRA does not detect
|
||||
that this variable changes. This field is checked by the HTTP Client library.
|
||||
If the Content-Length header was found, then pHttpParser->content_length
|
||||
will not be equal to the maximum 64 bit integer.
|
||||
|
||||
#### Rule 11.8
|
||||
_Ref 11.8.1_
|
||||
|
||||
- MISRA Rule 11.8 flags casting away the const qualifier in the pointer
|
||||
type. This rule is suppressed because when the body is of transfer
|
||||
encoding chunked, the body must be copied over the chunk headers that
|
||||
precede it. This is done to have a contiguous response body. This does
|
||||
affect future parsing as the changed segment will always be before the
|
||||
next place to parse.
|
||||
|
||||
#### Rule 18.3
|
||||
_Ref 18.3.1_
|
||||
|
||||
- MISRA Rule 18.3 flags pLoc and pNextWriteLoc as pointing to two different
|
||||
objects. This rule is suppressed because both pNextWriteLoc and pLoc
|
||||
point to a location in the response buffer.
|
||||
|
||||
#### Rule 21.13
|
||||
_Ref 21.13.1_
|
||||
|
||||
- MISRA Rule 21.13 flags any value passed into a ctype.h function that isn't cast
|
||||
as an unsigned char. Thorough testing by use of our CBMC proofs shows that adding
|
||||
the cast to ( unsigned char ) inside of the toupper() call has potential to lead
|
||||
to errors. Due to this we supress this warning for our use case.
|
||||
@ -0,0 +1,117 @@
|
||||
# coreHTTP Client Library
|
||||
|
||||
This repository contains a C language HTTP client library designed for embedded
|
||||
platforms. It has no dependencies on any additional libraries other than the
|
||||
standard C library, [llhttp](https://github.com/nodejs/llhttp), and
|
||||
a customer-implemented transport interface. This library is distributed under
|
||||
the [MIT Open Source License](LICENSE).
|
||||
|
||||
This library has gone through code quality checks including verification that no
|
||||
function has a [GNU Complexity](https://www.gnu.org/software/complexity/manual/complexity.html)
|
||||
score over 8. This library has also undergone both static code analysis from
|
||||
[Coverity static analysis](https://scan.coverity.com/), and validation of memory
|
||||
safety and data structure invariance through the
|
||||
[CBMC automated reasoning tool](https://www.cprover.org/cbmc/).
|
||||
|
||||
See memory requirements for this library [here](./docs/doxygen/include/size_table.md).
|
||||
|
||||
**coreHTTP v3.0.0 [source code](https://github.com/FreeRTOS/coreHTTP/tree/v3.0.0/source) is part of the [FreeRTOS 202210.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202210.00-LTS) release.**
|
||||
|
||||
**coreHTTP v2.0.0 [source code](https://github.com/FreeRTOS/coreHTTP/tree/v2.0.0/source) is part of the [FreeRTOS 202012.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202012.00-LTS) release.**
|
||||
|
||||
## coreHTTP Config File
|
||||
|
||||
The HTTP client library exposes configuration macros that are required for
|
||||
building the library. A list of all the configurations and their default values
|
||||
are defined in [core_http_config_defaults.h](source/include/core_http_config_defaults.h).
|
||||
To provide custom values for the configuration macros, a custom config file
|
||||
named `core_http_config.h` can be provided by the user application to the library.
|
||||
|
||||
By default, a `core_http_config.h` custom config is required to build the
|
||||
library. To disable this requirement and build the library with default
|
||||
configuration values, provide `HTTP_DO_NOT_USE_CUSTOM_CONFIG` as a compile time
|
||||
preprocessor macro.
|
||||
|
||||
**The HTTP client library can be built by either**:
|
||||
* Defining a `core_http_config.h` file in the application, and adding it to the
|
||||
include directories for the library build.
|
||||
**OR**
|
||||
* Defining the `HTTP_DO_NOT_USE_CUSTOM_CONFIG` preprocessor macro for the
|
||||
library build.
|
||||
|
||||
## Building the Library
|
||||
|
||||
The [httpFilePaths.cmake](httpFilePaths.cmake) file contains the information of
|
||||
all source files and header include paths required to build the HTTP client
|
||||
library.
|
||||
|
||||
As mentioned in the [previous section](#coreHTTP-Config-File), either a custom
|
||||
config file (i.e. `core_http_config.h`) OR `HTTP_DO_NOT_USE_CUSTOM_CONFIG` macro
|
||||
needs to be provided to build the HTTP client library.
|
||||
|
||||
For a CMake example of building the HTTP library with the `httpFilePaths.cmake`
|
||||
file, refer to the `coverity_analysis` library target in
|
||||
[test/CMakeLists.txt](test/CMakeLists.txt) file.
|
||||
|
||||
## Building Unit Tests
|
||||
|
||||
### Platform Prerequisites
|
||||
|
||||
- For running unit tests, the following are required:
|
||||
- **C90 compiler** like gcc
|
||||
- **CMake 3.13.0 or later**
|
||||
- **Ruby 2.0.0 or later** is required for this repository's
|
||||
[CMock test framework](https://github.com/ThrowTheSwitch/CMock).
|
||||
- For running the coverage target, the following are required:
|
||||
- **gcov**
|
||||
- **lcov**
|
||||
|
||||
### Steps to build **Unit Tests**
|
||||
|
||||
1. Go to the root directory of this repository.
|
||||
|
||||
1. Run the *cmake* command: `cmake -S test -B build -DBUILD_CLONE_SUBMODULES=ON `
|
||||
|
||||
1. Run this command to build the library and unit tests: `make -C build all`
|
||||
|
||||
1. The generated test executables will be present in `build/bin/tests` folder.
|
||||
|
||||
1. Run `cd build && ctest` to execute all tests and view the test run summary.
|
||||
|
||||
## CBMC
|
||||
|
||||
To learn more about CBMC and proofs specifically, review the training material [here](https://model-checking.github.io/cbmc-training).
|
||||
|
||||
The `test/cbmc/proofs` directory contains CBMC proofs.
|
||||
|
||||
In order to run these proofs you will need to install CBMC and other tools by following the instructions [here](https://model-checking.github.io/cbmc-training/installation.html).
|
||||
|
||||
## Reference examples
|
||||
|
||||
The AWS IoT Device SDK for Embedded C repository contains demos of using the HTTP client
|
||||
library [here](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main/demos/http)
|
||||
on a POSIX platform. These can be used as reference examples for the library API.
|
||||
|
||||
## Documentation
|
||||
|
||||
### Existing Documentation
|
||||
For pre-generated documentation, please see the documentation linked in the locations below:
|
||||
|
||||
| Location |
|
||||
| :-: |
|
||||
| [AWS IoT Device SDK for Embedded C](https://github.com/aws/aws-iot-device-sdk-embedded-C#releases-and-documentation) |
|
||||
| [FreeRTOS.org](https://freertos.org/Documentation/api-ref/coreHTTP/docs/doxygen/output/html/index.html) |
|
||||
|
||||
Note that the latest included version of coreHTTP may differ across repositories.
|
||||
|
||||
### Generating Documentation
|
||||
The Doxygen references were created using Doxygen version 1.9.2. To generate the
|
||||
Doxygen pages, please run the following command from the root of this repository:
|
||||
|
||||
```shell
|
||||
doxygen docs/doxygen/config.doxyfile
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for information on contributing.
|
||||
@ -0,0 +1,5 @@
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security
|
||||
via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com.
|
||||
Please do **not** create a public github issue.
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
@ -0,0 +1,35 @@
|
||||
@startuml
|
||||
skinparam dpi 300
|
||||
skinparam ArrowFontSize 18
|
||||
|
||||
start
|
||||
#lightblue: **Send request on the Network**;
|
||||
#lightgreen:if( Network error ) then (yes)
|
||||
#lightgray: Return ERROR;
|
||||
stop
|
||||
else (no)
|
||||
repeat
|
||||
#lightblue: **Read response on the Network**;
|
||||
#lightgreen:if( Network error ) then (yes)
|
||||
#lightgray: Return ERROR;
|
||||
stop
|
||||
else (no)
|
||||
endif
|
||||
: Parse HTTP response;
|
||||
note left: Parsing is done with\nthird-party //http-parser//
|
||||
repeat while (Response buffer is NOT full &&
|
||||
Response message is NOT complete &&
|
||||
No errors found in parsing) is ( yes)
|
||||
-> no;
|
||||
#lightgreen:if (Errors found in parsing) then (yes)
|
||||
#lightgray: Return ERROR;
|
||||
stop
|
||||
#lightgreen:(no ) elseif (Response message could not fit in response buffer) then (yes)
|
||||
#lightgray: Return ERROR;
|
||||
stop
|
||||
else (no)
|
||||
endif
|
||||
: Return response;
|
||||
stop
|
||||
|
||||
@enduml
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
@ -0,0 +1,44 @@
|
||||
@startuml
|
||||
|
||||
skinparam dpi 300
|
||||
|
||||
Application -> HTTP_Client_Lib: HTTPClient_Send(<font color=red>Request Headers</font>, <font color=blue>Request Body</font>, <font color=green>Response</font>)
|
||||
activate HTTP_Client_Lib #lightgreen
|
||||
|
||||
HTTP_Client_Lib -> Application: transport send(<font color=red>Request Headers</font>)
|
||||
activate Application #lightblue
|
||||
Application -> Application: Send <font color=red>Request Headers</font> over the network.
|
||||
Application --> HTTP_Client_Lib: Return SUCCESS
|
||||
deactivate Application
|
||||
note right: **transport send** is repeated if\nfewer bytes than requested to\nsend are sent.\nFor the sake of simplicity this\nexample returns successfully\nfrom the transport interface.
|
||||
|
||||
HTTP_Client_Lib -> Application: transport send(<font color=blue>Request Body</font>)
|
||||
activate Application #lightblue
|
||||
Application -> Application: Send <font color=blue>Request Body</font> over the network.
|
||||
Application --> HTTP_Client_Lib: Return SUCCESS
|
||||
deactivate Application
|
||||
|
||||
loop While <font color=darkgreen>response buffer</font> is NOT full &&\nResponse message is NOT complete &&\nNo errors found in parsing
|
||||
HTTP_Client_Lib -> Application: transport read(<font color=darkgreen>Response buffer</font>)
|
||||
activate Application #lightblue
|
||||
Application -> Application: Receive network data into the <font color=darkgreen>Response buffer</font>.
|
||||
Application --> HTTP_Client_Lib: Return SUCCESS
|
||||
deactivate Application
|
||||
|
||||
HTTP_Client_Lib -> HTTP_Client_Lib: Parse <font color=green>Response</font>
|
||||
activate HTTP_Client_Lib #darkgreen
|
||||
|
||||
loop for each response header found in parsing
|
||||
HTTP_Client_Lib -> Application: __**onHeaderCallback**__(<font color=green>Response Header Field</font>,\n <font color=green>Response Header Value</font>,\n <font color=green>Response Status</font>)
|
||||
activate Application #lightblue
|
||||
Application -> Application: Do stuff with the Header
|
||||
Application --> HTTP_Client_Lib: Return
|
||||
deactivate Application
|
||||
end
|
||||
deactivate HTTP_Client_Lib
|
||||
end
|
||||
|
||||
|
||||
HTTP_Client_Lib --> Application: Return HTTP_RETURN_CODE
|
||||
deactivate HTTP_Client_Lib
|
||||
@enduml
|
||||
@ -0,0 +1,35 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="3"><center><b>Code Size of coreHTTP (example generated with GCC for ARM Cortex-M)</b></center></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>File</b></td>
|
||||
<td><b><center>With -O1 Optimization</center></b></td>
|
||||
<td><b><center>With -Os Optimization</center></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>core_http_client.c</td>
|
||||
<td><center>3.1K</center></td>
|
||||
<td><center>2.5K</center></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>api.c (llhttp)</td>
|
||||
<td><center>2.6K</center></td>
|
||||
<td><center>2.0K</center></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>http.c (llhttp)</td>
|
||||
<td><center>0.3K</center></td>
|
||||
<td><center>0.3K</center></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>llhttp.c (llhttp)</td>
|
||||
<td><center>17.9K</center></td>
|
||||
<td><center>15.9K</center></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Total estimates</b></td>
|
||||
<td><b><center>23.9K</center></b></td>
|
||||
<td><b><center>20.7K</center></b></td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -0,0 +1,228 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.20 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title=""/>
|
||||
<tab type="pages" visible="yes" title="" intro=""/>
|
||||
<!-- Hide the default "Data Structures" tab and use the "Modules" tab for data
|
||||
structures. This allows internal data structures to be hidden. -->
|
||||
<tab type="modules" visible="yes" title="Data types and Constants" intro="This library defines the following data types and constants."/>
|
||||
<tab type="namespaces" visible="yes" title="">
|
||||
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="interfaces" visible="no" title="">
|
||||
<tab type="interfacelist" visible="no" title="" intro=""/>
|
||||
<tab type="interfaceindex" visible="no" title=""/>
|
||||
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="classes" visible="no" title="">
|
||||
<tab type="classlist" visible="no" title="" intro=""/>
|
||||
<tab type="classindex" visible="no" title=""/>
|
||||
<tab type="hierarchy" visible="no" title="" intro=""/>
|
||||
<tab type="classmembers" visible="no" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="structs" visible="no" title="">
|
||||
<tab type="structlist" visible="no" title="" intro=""/>
|
||||
<tab type="structindex" visible="no" title=""/>
|
||||
</tab>
|
||||
<tab type="exceptions" visible="no" title="">
|
||||
<tab type="exceptionlist" visible="no" title="" intro=""/>
|
||||
<tab type="exceptionindex" visible="no" title=""/>
|
||||
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="files" visible="no" title="">
|
||||
<tab type="filelist" visible="yes" title="Files" intro="The following files are associated with this library."/>
|
||||
<tab type="globals" visible="no" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="examples" visible="yes" title="" intro=""/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<interfaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<structs visible="yes" title=""/>
|
||||
<exceptions visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<interfaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<structs visible="yes" title=""/>
|
||||
<exceptions visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<sequences title=""/>
|
||||
<dictionaries title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
||||
@ -0,0 +1,328 @@
|
||||
/**
|
||||
@mainpage Overview
|
||||
@anchor http
|
||||
@brief HTTP Client library
|
||||
|
||||
This HTTP Client library implements a subset of the HTTP/1.1 protocol. Features
|
||||
of this library include:
|
||||
- Fully synchronous API, to allow applications to completely manage their concurrency and multi-threading.
|
||||
- Operations on user supplied buffers, so that applications have complete control of their memory allocation strategy.
|
||||
- Integration with [llhttp](https://github.com/nodejs/llhttp) to handle chunked encoding.
|
||||
|
||||
Feature of HTTP/1.1 not supported in this library:
|
||||
- Streaming uploads and downloads. Range requests for partial content responses are highly encouraged with this API.
|
||||
- Pipelining requests. There may be only one request outgoing and one response incoming, at a time, on a connection.
|
||||
- Automatic redirection. The user application owns their connection and must handle redirection status codes.
|
||||
|
||||
@section http_memory_requirements Memory Requirements
|
||||
@brief Memory requirements of the HTTP Client library.
|
||||
|
||||
@include{doc} size_table.md
|
||||
*/
|
||||
|
||||
/**
|
||||
@page http_design Design
|
||||
HTTP Client Library Architecture and Design
|
||||
|
||||
This HTTP client library implements a subset of the HTTP/1.1 protocol. It is
|
||||
optimized for resource constrained devices and does not dynamically allocate any
|
||||
memory.
|
||||
|
||||
@section http_transport_interface_blurb Transport Interface
|
||||
|
||||
For decoupling from the user platform, the HTTP client library uses a
|
||||
transport interface. The transport interface allows the HTTP client library to
|
||||
send and receive data over the user's transport layer. The user platform must
|
||||
implement a @ref TransportInterface_t to use in @ref HTTPClient_Send.
|
||||
|
||||
@see The [transport interface documentation](@ref http_transport_interface) for
|
||||
more information.
|
||||
|
||||
@section http_request_serialization Building an HTTP Request
|
||||
|
||||
The HTTP client library provides the following API to serialize request headers.
|
||||
- @ref HTTPClient_InitializeRequestHeaders
|
||||
- @ref HTTPClient_AddHeader
|
||||
- @ref HTTPClient_AddRangeHeader
|
||||
|
||||
An application is expected to create and populate an @ref HTTPRequestInfo_t and
|
||||
set a buffer to use for the headers in @ref HTTPRequestHeaders_t.pBuffer. The
|
||||
application may first call @ref HTTPClient_InitializeRequestHeaders to populate
|
||||
the @ref HTTPRequestHeaders_t with the method, the path, and the host. The
|
||||
HTTP request will be serialized to the following when HTTPRequestInfo_t.reqFlags
|
||||
is zero.
|
||||
|
||||
@code
|
||||
<METHOD> <PATH> HTTP/1.1\r\n
|
||||
User-Agent: <MY-PLATFORM>\r\n
|
||||
Host: <SERVER-URL>\r\n\r\n
|
||||
@endcode
|
||||
|
||||
When the @ref HTTPRequestInfo_t.reqFlags has @ref HTTP_REQUEST_KEEP_ALIVE_FLAG
|
||||
set, then the HTTP request will be serialized to the following:
|
||||
|
||||
@code
|
||||
<METHOD> <PATH> HTTP/1.1\r\n
|
||||
User-Agent: <MY-PLATFORM>\r\n
|
||||
Host: <SERVER-URL>\r\n
|
||||
Connection: keep-alive\r\n\r\n
|
||||
@endcode
|
||||
|
||||
The user application may add more headers using @ref HTTPClient_AddHeader or
|
||||
@ref HTTPClient_AddRangeHeader. New headers will be appended to the end of the
|
||||
existing headers. Please see the following example:
|
||||
|
||||
@code
|
||||
<METHOD> <PATH> HTTP/1.1\r\n
|
||||
User-Agent: <MY-PLATFORM>\r\n
|
||||
Host: <SERVER-URL>\r\n
|
||||
Connection: keep-alive\r\n
|
||||
Another-Header1: another-value1\r\n
|
||||
Another-Header2: another-value2\r\n
|
||||
Another-Header3: another-value3\r\n\r\n
|
||||
@endcode
|
||||
|
||||
The user application may pass a request body into the @ref HTTPClient_Send
|
||||
function when the request is ready to be sent.
|
||||
|
||||
@section http_range_support HTTP Range Requests and Partial Content Responses
|
||||
|
||||
Range Requests are strongly encouraged for downloading a large file. Large is
|
||||
defined here to be a file whose total size cannot fit into the space currently
|
||||
available in RAM. By downloading a large file using range requests the user
|
||||
application can spend time processing that part of the file (for example writing
|
||||
to flash), then request the next part of the file. If the user application were
|
||||
to request the entire file at once and process it in sections from the network,
|
||||
the system is at a high risk for dropping packets. Dropped packets cause
|
||||
retransmissions in the system's transport layer. With many, there can be a
|
||||
negative impact on the overall system throughput, network bandwidth, and battery
|
||||
life of the device.
|
||||
|
||||
Range requests are supported using @ref HTTPClient_AddRangeHeader. Please see
|
||||
the function documentation for more information.
|
||||
|
||||
@section http_response_deserialization Receiving and Parsing an HTTP Response
|
||||
|
||||
After the request headers are serialized, the user application must set a buffer
|
||||
to receive the HTTP response in @ref HTTPResponse_t.pBuffer.
|
||||
@ref HTTPClient_Send is then used to send the request and receive the response.
|
||||
If the request has a body it is passed as a parameter to @ref HTTPClient_Send.
|
||||
As soon as the response is received from the network it is parsed. The final
|
||||
parsed response is represented by the @ref HTTPResponse_t returned from
|
||||
@ref HTTPClient_Send. Parsing the HTTP response is done using
|
||||
[llhttp](https://github.com/nodejs/llhttp). llhttp invokes
|
||||
callbacks for each section in the HTTP response it finds. Using these callbacks
|
||||
the HTTP client library sets the members of @ref HTTPResponse_t to return from
|
||||
@ref HTTPClient_Send. The overall flow of @ref HTTPClient_Send is
|
||||
shown in the activity diagram below:
|
||||
|
||||
@image html httpclient_send_activity_diagram.png width=50%
|
||||
|
||||
@section http_response_headers Reading the HTTP Response Headers
|
||||
|
||||
Upon a successful return from @ref HTTPClient_Send, the HTTP Response headers
|
||||
can be read from the headers found in @ref HTTPResponse_t.pHeaders. The function
|
||||
@ref HTTPClient_ReadHeader reads the headers from an @ref HTTPResponse_t.
|
||||
@ref HTTPClient_ReadHeader will re-parse the response in
|
||||
@ref HTTPResponse_t.pBuffer, looking for the header field of interest.
|
||||
Re-parsing involves using llhttp to look at each character starting from
|
||||
the beginning of @ref HTTPResponse_t.pBuffer until the header field of interest
|
||||
is found.
|
||||
|
||||
If the user application wants to avoid re-parsing @ref HTTPResponse_t.pBuffer,
|
||||
then the user application may register a callback in
|
||||
@ref HTTPResponse_t.pHeaderParsingCallback. When the HTTP response message is
|
||||
first received from the network, in @ref HTTPClient_Send, llhttp is invoked
|
||||
to parse the response. This first parsing in @ref HTTPClient_Send will invoke
|
||||
@ref HTTPResponse_t.pHeaderParsingCallback for each header that is found
|
||||
in response. Please see the sequence diagram below for an illustration of when
|
||||
@ref HTTPClient_ResponseHeaderParsingCallback_t.onHeaderCallback is invoked
|
||||
during the operation of @ref HTTPClient_Send.
|
||||
|
||||
@image html httpclient_send_sequence_diagram.png width=50%
|
||||
*/
|
||||
|
||||
/**
|
||||
@page http_porting Porting Guide
|
||||
@brief Guide for porting the HTTP client library to a new platform.
|
||||
|
||||
To use the HTTP client library, a platform must implement the following
|
||||
components:
|
||||
1. [Configuration Macros](@ref http_porting_config)
|
||||
2. [Transport Interface](@ref http_porting_transport)
|
||||
|
||||
@section http_porting_config Configuration Macros
|
||||
@brief Settings that can be set as macros in the config header
|
||||
`core_http_config.h`, or passed in as compiler options.
|
||||
|
||||
@note If the custom configuration header `core_http_config.h` is not provided,
|
||||
then the @ref HTTP_DO_NOT_USE_CUSTOM_CONFIG macro must be defined.
|
||||
|
||||
@see [Configurations](@ref http_config)
|
||||
|
||||
The following macros can be configured for this library:
|
||||
- @ref HTTP_USER_AGENT_VALUE
|
||||
- @ref HTTP_SEND_RETRY_TIMEOUT_MS
|
||||
- @ref HTTP_RECV_RETRY_TIMEOUT_MS
|
||||
|
||||
In addition, the following logging macros are used throughout this library:
|
||||
- @ref LogError
|
||||
- @ref LogWarn
|
||||
- @ref LogInfo
|
||||
- @ref LogDebug
|
||||
|
||||
@section http_porting_transport Transport Interface
|
||||
@brief The HTTP client library relies on transport interface callbacks
|
||||
that must be implemented in order to send and receive packets on a network.
|
||||
|
||||
@see The [Transport Interface](@ref http_transport_interface) documentation for
|
||||
more information.
|
||||
|
||||
The transport interface API used by the HTTP client is defined in
|
||||
@ref transport_interface.h. A port must implement functions corresponding to the
|
||||
following functions pointers:
|
||||
- [Transport Receive](@ref TransportRecv_t): A function to receive bytes from a network.
|
||||
@code
|
||||
int32_t (* TransportRecv_t )(
|
||||
NetworkContext_t * pNetworkContext, void * pBuffer, size_t bytesToRecv
|
||||
);
|
||||
@endcode
|
||||
- [Transport Send](@ref TransportSend_t): A function to send bytes over a network.
|
||||
@code
|
||||
int32_t (* TransportSend_t )(
|
||||
NetworkContext_t * pNetworkContext, const void * pBuffer, size_t bytesToSend
|
||||
);
|
||||
@endcode
|
||||
|
||||
The above two functions take in a pointer to a @ref NetworkContext_t, the type
|
||||
name of a `struct NetworkContext`. The NetworkContext struct must also be
|
||||
defined by the user's implementation, and ought to contain any information
|
||||
necessary to send and receive data with the @ref TransportSend_t and
|
||||
@ref TransportRecv_t implementations, respectively:
|
||||
|
||||
@code
|
||||
struct NetworkContext {
|
||||
// Fields necessary for the transport implementations, e.g. a TCP socket descriptor.
|
||||
};
|
||||
@endcode
|
||||
|
||||
@section http_porting_time Time Function
|
||||
@brief The HTTP library optionally relies on a function to generate millisecond
|
||||
timestamps, for the purpose of calculating the elapsed time when no data has
|
||||
been sent or received.
|
||||
|
||||
@see @ref HTTPClient_GetCurrentTimeFunc_t
|
||||
|
||||
Applications can supply their platform-specific function capable of generating
|
||||
32-bit timestamps of millisecond resolution. These timestamps need not correspond
|
||||
with any real world clock; the only requirement is that the difference between two
|
||||
timestamps must be an accurate representation of the duration between them, in
|
||||
milliseconds.
|
||||
|
||||
This function is used in conjunction with macros @ref HTTP_SEND_RETRY_TIMEOUT_MS
|
||||
and @ref HTTP_RECV_RETRY_TIMEOUT_MS.
|
||||
*/
|
||||
|
||||
/**
|
||||
@page http_config Configurations
|
||||
@brief Configurations of the HTTP Client library.
|
||||
<!-- @par configpagestyle allows the @section titles to be styled according to style.css -->
|
||||
@par configpagestyle
|
||||
|
||||
Configuration settings are C pre-processor constants. They can be set with a \#define in the config file (core_http_config.h) or by using a compiler option such as -D in gcc.
|
||||
|
||||
|
||||
@section HTTP_DO_NOT_USE_CUSTOM_CONFIG
|
||||
@brief Define this macro to build the HTTP client library without the custom
|
||||
config file core_http_config.h.
|
||||
|
||||
Without the custom config, the HTTP client library builds with default values of
|
||||
config macros defined in core_http_config_defaults.h file.
|
||||
|
||||
If a custom config is provided, then HTTP_DO_NOT_USE_CUSTOM_CONFIG should not be
|
||||
defined.
|
||||
|
||||
@section HTTP_USER_AGENT_VALUE
|
||||
@copydoc HTTP_USER_AGENT_VALUE
|
||||
|
||||
@section HTTP_SEND_RETRY_TIMEOUT_MS
|
||||
@copydoc HTTP_SEND_RETRY_TIMEOUT_MS
|
||||
|
||||
@section HTTP_RECV_RETRY_TIMEOUT_MS
|
||||
@copydoc HTTP_RECV_RETRY_TIMEOUT_MS
|
||||
|
||||
@section http_logerror LogError
|
||||
@copydoc LogError
|
||||
|
||||
@section http_logwarn LogWarn
|
||||
@copydoc LogWarn
|
||||
|
||||
@section http_loginfo LogInfo
|
||||
@copydoc LogInfo
|
||||
|
||||
@section http_logdebug LogDebug
|
||||
@copydoc LogDebug
|
||||
*/
|
||||
|
||||
/**
|
||||
@page http_functions Functions
|
||||
@brief Primary functions of the HTTP Client library:<br><br>
|
||||
@subpage httpclient_initializerequestheaders_function <br>
|
||||
@subpage httpclient_addheader_function <br>
|
||||
@subpage httpclient_addrangeheader_function <br>
|
||||
@subpage httpclient_send_function <br>
|
||||
@subpage httpclient_readheader_function <br>
|
||||
@subpage httpclient_strerror_function <br>
|
||||
|
||||
@page httpclient_initializerequestheaders_function HTTPClient_InitializeRequestHeaders
|
||||
@snippet core_http_client.h declare_httpclient_initializerequestheaders
|
||||
@copydoc HTTPClient_InitializeRequestHeaders
|
||||
|
||||
@page httpclient_addheader_function HTTPClient_AddHeader
|
||||
@snippet core_http_client.h declare_httpclient_addheader
|
||||
@copydoc HTTPClient_AddHeader
|
||||
|
||||
@page httpclient_addrangeheader_function HTTPClient_AddRangeHeader
|
||||
@snippet core_http_client.h declare_httpclient_addrangeheader
|
||||
@copydoc HTTPClient_AddRangeHeader
|
||||
|
||||
@page httpclient_send_function HTTPClient_Send
|
||||
@snippet core_http_client.h declare_httpclient_send
|
||||
@copydoc HTTPClient_Send
|
||||
|
||||
@page httpclient_readheader_function HTTPClient_ReadHeader
|
||||
@snippet core_http_client.h declare_httpclient_readheader
|
||||
@copydoc HTTPClient_ReadHeader
|
||||
|
||||
@page httpclient_strerror_function HTTPClient_strerror
|
||||
@snippet core_http_client.h declare_httpclient_strerror
|
||||
@copydoc HTTPClient_strerror
|
||||
*/
|
||||
|
||||
<!-- We do not use doxygen ALIASes here because there have been issues in the past versions with "^^" newlines within the alias definition. -->
|
||||
/**
|
||||
@defgroup http_enum_types Enumerated Types
|
||||
@brief Enumerated types of the HTTP Client library
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup http_callback_types Callback Types
|
||||
@brief Callback function pointer types of the HTTP Client library
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup http_struct_types Parameter Structures
|
||||
@brief Structures passed as parameters to [HTTP Client library functions](@ref http_functions)
|
||||
|
||||
These structures are passed as parameters to library functions. Documentation for these structures will state the functions associated with each parameter structure and the purpose of each member.
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup http_basic_types Basic Types
|
||||
@brief Primitive types of the HTTP Client library.
|
||||
*/
|
||||
|
||||
/**
|
||||
@defgroup http_constants Constants
|
||||
@brief Constants defined in the HTTP Client library
|
||||
*/
|
||||
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Stylesheet for Doxygen HTML output.
|
||||
*
|
||||
* This file defines styles for custom elements in the header/footer and
|
||||
* overrides some of the default Doxygen styles.
|
||||
*
|
||||
* Styles in this file do not affect the treeview sidebar.
|
||||
*/
|
||||
|
||||
/* Set the margins to place a small amount of whitespace on the left and right
|
||||
* side of the page. */
|
||||
div.contents {
|
||||
margin-left:4em;
|
||||
margin-right:4em;
|
||||
}
|
||||
|
||||
/* Justify text in paragraphs. */
|
||||
p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* Style of section headings. */
|
||||
h1 {
|
||||
border-bottom: 1px solid #879ECB;
|
||||
color: #354C7B;
|
||||
font-size: 160%;
|
||||
font-weight: normal;
|
||||
padding-bottom: 4px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
/* Style of subsection headings. */
|
||||
h2:not(.memtitle):not(.groupheader) {
|
||||
font-size: 125%;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 16px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* Style of paragraphs immediately after subsection headings. */
|
||||
h2 + p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* Style of subsection headings. */
|
||||
h3 {
|
||||
font-size: 100%;
|
||||
margin-bottom: 0px;
|
||||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
/* Style of paragraphs immediately after subsubsection headings. */
|
||||
h3 + p {
|
||||
margin-top: 0px;
|
||||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
/* Style of the prefix "AWS IoT Device SDK C" that appears in the header. */
|
||||
#csdkprefix {
|
||||
color: #757575;
|
||||
}
|
||||
|
||||
/* Style of the "Return to main page" link that appears in the header. */
|
||||
#returntomain {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
/* Style of the dividers on Configuration Settings pages. */
|
||||
div.configpagedivider {
|
||||
margin-left: 0px !important;
|
||||
margin-right: 0px !important;
|
||||
margin-top: 20px !important;
|
||||
}
|
||||
|
||||
/* Style of configuration setting names. */
|
||||
dl.section.user ~ h1 {
|
||||
border-bottom: none;
|
||||
color: #000000;
|
||||
font-family: monospace, fixed;
|
||||
font-size: 16px;
|
||||
margin-bottom: 0px;
|
||||
margin-left: 2em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
/* Style of paragraphs on a configuration settings page. */
|
||||
dl.section.user ~ * {
|
||||
margin-bottom: 10px;
|
||||
margin-left: 4em;
|
||||
margin-right: 4em;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
/* Hide the configuration setting marker. */
|
||||
dl.section.user {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Overrides for code fragments and lines. */
|
||||
div.fragment {
|
||||
background: #ffffff;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
div.line {
|
||||
color: #3a3a3a;
|
||||
}
|
||||
|
||||
/* Overrides for code syntax highlighting colors. */
|
||||
span.comment {
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
span.keyword, span.keywordtype, span.keywordflow {
|
||||
color: #0000ff;
|
||||
}
|
||||
|
||||
span.preprocessor {
|
||||
color: #50015a;
|
||||
}
|
||||
|
||||
span.stringliteral, span.charliteral {
|
||||
color: #800c0c;
|
||||
}
|
||||
|
||||
a.code, a.code:visited, a.line, a.line:visited {
|
||||
color: #496194;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
# This file is to add source files and include directories
|
||||
# into variables so that it can be reused from different repositories
|
||||
# in their Cmake based build system by including this file.
|
||||
#
|
||||
# Files specific to the repository such as test runner, platform tests
|
||||
# are not added to the variables.
|
||||
|
||||
# HTTP library source files.
|
||||
set( HTTP_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/core_http_client.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/src/api.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/src/llhttp.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/src/http.c )
|
||||
|
||||
# HTTP library public include directories.
|
||||
set( HTTP_INCLUDE_PUBLIC_DIRS
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/include
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/interface
|
||||
${CMAKE_CURRENT_LIST_DIR}/source/dependency/3rdparty/llhttp/include )
|
||||
@ -0,0 +1,288 @@
|
||||
absolutevalue
|
||||
addheader
|
||||
addrangeheader
|
||||
addrangeheaders
|
||||
addrangerequest
|
||||
addtogroup
|
||||
aggregator
|
||||
api
|
||||
apis
|
||||
ascii
|
||||
aws
|
||||
bool
|
||||
br
|
||||
bufferlen
|
||||
bufferlength
|
||||
bytesreceived
|
||||
bytesremaining
|
||||
bytessent
|
||||
bytestorecv
|
||||
bytestosend
|
||||
calltlsrecvfunc
|
||||
cb
|
||||
cbmc
|
||||
chk
|
||||
chunked
|
||||
colspan
|
||||
com
|
||||
cond
|
||||
config
|
||||
configpagestyle
|
||||
const
|
||||
contentlength
|
||||
convertint
|
||||
copybrief
|
||||
copydoc
|
||||
corehttp
|
||||
coverity
|
||||
cprover
|
||||
css
|
||||
datalen
|
||||
datelen
|
||||
defgroup
|
||||
doesn
|
||||
doxygen
|
||||
endcode
|
||||
endcond
|
||||
endif
|
||||
enums
|
||||
eof
|
||||
errno
|
||||
expectedheader
|
||||
fieldfound
|
||||
fieldlen
|
||||
fieldlentoreturn
|
||||
fieldloc
|
||||
findheadercontext
|
||||
findheaderfieldparsercallback
|
||||
findheaderinresponse
|
||||
findheaderonheadercompletecallback
|
||||
findheadervalueparsercallback
|
||||
firstpartbytes
|
||||
freertos
|
||||
gcc
|
||||
getfinalresponsestatus
|
||||
gettime
|
||||
gettimestampms
|
||||
github
|
||||
headercount
|
||||
headerslen
|
||||
hostlen
|
||||
hpe
|
||||
html
|
||||
http
|
||||
httpclient
|
||||
httpheadernotfound
|
||||
httpheaderstrncpy
|
||||
httpinsufficientmemory
|
||||
httpinvalidparameter
|
||||
httpinvalidresponse
|
||||
httplibrarystatus
|
||||
httpnetworkerror
|
||||
httpnoresponse
|
||||
httpparseonstatusfieldcallback
|
||||
httpparser
|
||||
httpparserinternalerror
|
||||
httpparseronbodycallback
|
||||
httpparseronheaderfieldcallback
|
||||
httpparseronheaderscompletecallback
|
||||
httpparseronheadervaluecallback
|
||||
httpparseronmessagebegincallback
|
||||
httpparseronmessagecompletecallback
|
||||
httpparseronstatuscallback
|
||||
httpparserxxxxcallback
|
||||
httpparserxxxxcallbacks
|
||||
httpparsingcontext
|
||||
httpparsingstate
|
||||
httppartialresponse
|
||||
httprequestheaders
|
||||
httprequestinfo
|
||||
httpresponse
|
||||
https
|
||||
httpsecurityalertextraneousresponsedata
|
||||
httpsecurityalertinvalidcontentlength
|
||||
httpsecurityalertinvalidcharacter
|
||||
httpsecurityalertinvalidchunkheader
|
||||
httpsecurityalertinvalidprotocolversion
|
||||
httpsecurityalertinvalidstatuscode
|
||||
httpstatus
|
||||
httpsuccess
|
||||
ietf
|
||||
ifndef
|
||||
inbetween
|
||||
inc
|
||||
ingroup
|
||||
init
|
||||
initializerequestheaders
|
||||
int
|
||||
iot
|
||||
ioveccount
|
||||
ip
|
||||
isfield
|
||||
isheaderresponse
|
||||
isheadresponse
|
||||
iso
|
||||
lastheaderfieldlen
|
||||
lastheadervaluelen
|
||||
latin
|
||||
len
|
||||
linux
|
||||
llhttp
|
||||
llhttpparser
|
||||
llhttpsettings
|
||||
logdebug
|
||||
logerror
|
||||
loginfo
|
||||
logwarn
|
||||
mainpage
|
||||
malloc
|
||||
md
|
||||
memcpy
|
||||
memmove
|
||||
methodlen
|
||||
min
|
||||
misra
|
||||
mit
|
||||
mqtt
|
||||
msg
|
||||
mynetworkrecvimplementation
|
||||
mynetworksendimplementation
|
||||
myplatformnetworkcontext
|
||||
myplatformtransportreceive
|
||||
myplatformtransportsend
|
||||
mytcpsocketcontext
|
||||
mytlscontext
|
||||
networkcontext
|
||||
nodejs
|
||||
noninfringement
|
||||
ok
|
||||
onbody
|
||||
onheadercallback
|
||||
onheaderfield
|
||||
onheaderscomplete
|
||||
onheadervalue
|
||||
onmessagebegin
|
||||
onmessagecomplete
|
||||
onstatus
|
||||
ored
|
||||
org
|
||||
os
|
||||
param
|
||||
parsehttpresponse
|
||||
parselen
|
||||
parsersettings
|
||||
parsingstate
|
||||
pathlen
|
||||
pbuffer
|
||||
pbuffercur
|
||||
pbytesreceived
|
||||
pcontext
|
||||
pdata
|
||||
pdateloc
|
||||
pdest
|
||||
pfield
|
||||
pfieldloc
|
||||
pfindheadercontext
|
||||
pheaderparsingcallback
|
||||
pheaders
|
||||
phost
|
||||
phttpparser
|
||||
phttpparsingcontext
|
||||
piovec
|
||||
plaintext
|
||||
plastheaderfield
|
||||
plastheadervalue
|
||||
ploc
|
||||
psrc
|
||||
pmethod
|
||||
pname
|
||||
pnetworkcontext
|
||||
pnetworkdata
|
||||
pnext
|
||||
pnextwriteloc
|
||||
png
|
||||
posix
|
||||
pparsingcontext
|
||||
pparsingstate
|
||||
ppath
|
||||
pre
|
||||
prefill
|
||||
prequestbodybuf
|
||||
prequestheaders
|
||||
prequestinfo
|
||||
presponse
|
||||
processllhttperror
|
||||
ptransport
|
||||
ptransportinterface
|
||||
pvalue
|
||||
pvaluelen
|
||||
pvalueloc
|
||||
rangeend
|
||||
rangestart
|
||||
rangestartorlastnbytes
|
||||
readheader
|
||||
receivehttpdata
|
||||
recv
|
||||
recvcurrentcall
|
||||
recvstopcall
|
||||
recvtimeoutcall
|
||||
reponse
|
||||
reqbodybuflen
|
||||
reqbodylen
|
||||
reqflags
|
||||
requestbody
|
||||
requestheaderbuffer
|
||||
requestheaders
|
||||
requestinfo
|
||||
respflags
|
||||
responsebufferlen
|
||||
rfc
|
||||
rm
|
||||
sdk
|
||||
senderrorcall
|
||||
sendflags
|
||||
sendhttpbody
|
||||
sendhttpheaders
|
||||
sendpartialcall
|
||||
sensitivity
|
||||
sizeof
|
||||
snprintf
|
||||
spdx
|
||||
statuscode
|
||||
strchr
|
||||
strerror
|
||||
strncpy
|
||||
struct
|
||||
structs
|
||||
sublicense
|
||||
tcp
|
||||
tcpsocketcontext
|
||||
td
|
||||
tls
|
||||
tlscontext
|
||||
tlsrecv
|
||||
tlsrecvcount
|
||||
tlssend
|
||||
toascii
|
||||
toolchain
|
||||
totalreceived
|
||||
tr
|
||||
transportcallback
|
||||
transportinterface
|
||||
transportpage
|
||||
transportrecv
|
||||
transportsectionimplementation
|
||||
transportsectionoverview
|
||||
transportsend
|
||||
transportstatus
|
||||
transportstruct
|
||||
tx
|
||||
txt
|
||||
uint
|
||||
uri
|
||||
url
|
||||
valuefound
|
||||
valuelen
|
||||
valueloc
|
||||
writev
|
||||
xxxx
|
||||
@ -0,0 +1,11 @@
|
||||
name : "coreHTTP"
|
||||
version: "v3.0.0"
|
||||
description: "Client implementation of the HTTP/1.1 specification for embedded devices."
|
||||
license: "MIT"
|
||||
dependencies:
|
||||
- name : "llhttp"
|
||||
version: "release/v6.0.5"
|
||||
license: "MIT"
|
||||
repository:
|
||||
type: "git"
|
||||
url: "https://github.com/nodejs/llhttp.git"
|
||||
@ -0,0 +1,40 @@
|
||||
SPDXVersion: SPDX-2.2
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: coreHTTP
|
||||
DocumentNamespace: https://github.com/FreeRTOS/coreHTTP/blob/v3.0.0/sbom.spdx
|
||||
Creator: Amazon Web Services
|
||||
Created: 2022-10-14T18:19:43Z
|
||||
CreatorComment: NOASSERTION
|
||||
DocumentComment: NOASSERTION
|
||||
|
||||
PackageName: coreHTTP
|
||||
SPDXID: SPDXRef-Package-coreHTTP
|
||||
PackageVersion: v3.0.0
|
||||
PackageDownloadLocation: https://github.com/FreeRTOS/coreHTTP/tree/v3.0.0
|
||||
PackageLicenseConcluded: MIT
|
||||
FilesAnalyzed: True
|
||||
PackageVerificationCode: 9da50f28d4e05b909d6917cdc6563c434e8565e3
|
||||
PackageCopyrightText: NOASSERTION
|
||||
PackageSummary: NOASSERTION
|
||||
PackageDescription: Client implementation of the HTTP/1.1 specification for embedded devices.
|
||||
|
||||
FileName: ./core_http_client.c
|
||||
SPDXID: SPDXRef-File-core_http_client.c
|
||||
FileChecksum: SHA1: f98f83b1eabfa0a992e2f67aad63145317ca9efe
|
||||
LicenseConcluded: MIT
|
||||
FileCopyrightText: NOASSERTION
|
||||
FileComment: NOASSERTION
|
||||
|
||||
PackageName: llhttp
|
||||
SPDXID: SPDXRef-Package-llhttp
|
||||
PackageVersion: release/v6.0.5
|
||||
PackageDownloadLocation: https://github.com/nodejs/llhttp.git
|
||||
PackageLicenseConcluded: MIT
|
||||
FilesAnalyzed: True
|
||||
PackageVerificationCode: da39a3ee5e6b4b0d3255bfef95601890afd80709
|
||||
PackageCopyrightText: NOASSERTION
|
||||
PackageSummary: NOASSERTION
|
||||
PackageDescription: NOASSERTION
|
||||
|
||||
Relationship: SPDXRef-Package-coreHTTP DEPENDS_ON SPDXRef-Package-llhttp
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,53 @@
|
||||
cmake_minimum_required(VERSION 3.5.1)
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
|
||||
project(llhttp C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
#
|
||||
# Options
|
||||
#
|
||||
# Generic option
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
|
||||
|
||||
# Source code
|
||||
set(LLHTTP_SOURCES
|
||||
src/llhttp.c
|
||||
src/http.c
|
||||
src/api.c
|
||||
)
|
||||
|
||||
set(LLHTTP_HEADERS
|
||||
include/llhttp.h
|
||||
)
|
||||
|
||||
add_library(llhttp)
|
||||
add_library(llhttp::llhttp ALIAS llhttp)
|
||||
|
||||
target_sources(llhttp PRIVATE ${LLHTTP_SOURCES} ${LLHTTP_HEADERS})
|
||||
|
||||
# On windows with Visual Studio, add a debug postfix so that release
|
||||
# and debug libraries can coexist.
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
endif()
|
||||
|
||||
target_include_directories(llhttp PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
set_target_properties(llhttp PROPERTIES PUBLIC_HEADER ${LLHTTP_HEADERS})
|
||||
|
||||
install(TARGETS llhttp
|
||||
EXPORT llhttp
|
||||
ARCHIVE DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include/
|
||||
)
|
||||
|
||||
# This is required to work with FetchContent
|
||||
install(EXPORT llhttp
|
||||
FILE llhttp-config.cmake
|
||||
NAMESPACE llhttp::
|
||||
DESTINATION lib/cmake/llhttp)
|
||||
@ -0,0 +1,22 @@
|
||||
This software is licensed under the MIT License.
|
||||
|
||||
Copyright Fedor Indutny, 2018.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -0,0 +1,150 @@
|
||||
# llhttp
|
||||
[](https://github.com/nodejs/llhttp/actions?query=workflow%3ACI)
|
||||
|
||||
Port of [http_parser][0] to [llparse][1].
|
||||
|
||||
## Why?
|
||||
|
||||
Let's face it, [http_parser][0] is practically unmaintainable. Even
|
||||
introduction of a single new method results in a significant code churn.
|
||||
|
||||
This project aims to:
|
||||
|
||||
* Make it maintainable
|
||||
* Verifiable
|
||||
* Improving benchmarks where possible
|
||||
|
||||
More details in [Fedor Indutny's talk at JSConf EU 2019](https://youtu.be/x3k_5Mi66sY)
|
||||
|
||||
## How?
|
||||
|
||||
Over time, different approaches for improving [http_parser][0]'s code base
|
||||
were tried. However, all of them failed due to resulting significant performance
|
||||
degradation.
|
||||
|
||||
This project is a port of [http_parser][0] to TypeScript. [llparse][1] is used
|
||||
to generate the output C source file, which could be compiled and
|
||||
linked with the embedder's program (like [Node.js][7]).
|
||||
|
||||
## Performance
|
||||
|
||||
So far llhttp outperforms http_parser:
|
||||
|
||||
| | input size | bandwidth | reqs/sec | time |
|
||||
|:----------------|-----------:|-------------:|-----------:|--------:|
|
||||
| **llhttp** | 8192.00 mb | 1777.24 mb/s | 3583799.39 req/sec | 4.61 s |
|
||||
| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s |
|
||||
|
||||
llhttp is faster by approximately **156%**.
|
||||
|
||||
## Maintenance
|
||||
|
||||
llhttp project has about 1400 lines of TypeScript code describing the parser
|
||||
itself and around 450 lines of C code and headers providing the helper methods.
|
||||
The whole [http_parser][0] is implemented in approximately 2500 lines of C, and
|
||||
436 lines of headers.
|
||||
|
||||
All optimizations and multi-character matching in llhttp are generated
|
||||
automatically, and thus doesn't add any extra maintenance cost. On the contrary,
|
||||
most of http_parser's code is hand-optimized and unrolled. Instead describing
|
||||
"how" it should parse the HTTP requests/responses, a maintainer should
|
||||
implement the new features in [http_parser][0] cautiously, considering
|
||||
possible performance degradation and manually optimizing the new code.
|
||||
|
||||
## Verification
|
||||
|
||||
The state machine graph is encoded explicitly in llhttp. The [llparse][1]
|
||||
automatically checks the graph for absence of loops and correct reporting of the
|
||||
input ranges (spans) like header names and values. In the future, additional
|
||||
checks could be performed to get even stricter verification of the llhttp.
|
||||
|
||||
## Usage
|
||||
|
||||
```C
|
||||
#include "llhttp.h"
|
||||
|
||||
llhttp_t parser;
|
||||
llhttp_settings_t settings;
|
||||
|
||||
/* Initialize user callbacks and settings */
|
||||
llhttp_settings_init(&settings);
|
||||
|
||||
/* Set user callback */
|
||||
settings.on_message_complete = handle_on_message_complete;
|
||||
|
||||
/* Initialize the parser in HTTP_BOTH mode, meaning that it will select between
|
||||
* HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first
|
||||
* input.
|
||||
*/
|
||||
llhttp_init(&parser, HTTP_BOTH, &settings);
|
||||
|
||||
/* Parse request! */
|
||||
const char* request = "GET / HTTP/1.1\r\n\r\n";
|
||||
int request_len = strlen(request);
|
||||
|
||||
enum llhttp_errno err = llhttp_execute(&parser, request, request_len);
|
||||
if (err == HPE_OK) {
|
||||
/* Successfully parsed! */
|
||||
} else {
|
||||
fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err),
|
||||
parser.reason);
|
||||
}
|
||||
```
|
||||
For more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/master/src/native/api.h).
|
||||
|
||||
---
|
||||
|
||||
### Bindings to other languages
|
||||
|
||||
* Python: [pallas/pyllhttp][8]
|
||||
* Ruby: [metabahn/llhttp][9]
|
||||
|
||||
|
||||
### Using with CMake
|
||||
|
||||
If you want to use this library in a CMake project you can use the snippet below.
|
||||
|
||||
```
|
||||
FetchContent_Declare(llhttp
|
||||
URL "https://github.com/nodejs/llhttp/releases/download/v6.0.4/llhttp-release-v6.0.4.tar.gz") # Using version 6.0.4
|
||||
|
||||
FetchContent_MakeAvailable(llhttp)
|
||||
|
||||
target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp ${PROJECT_NAME})
|
||||
```
|
||||
|
||||
#### LICENSE
|
||||
|
||||
This software is licensed under the MIT License.
|
||||
|
||||
Copyright Fedor Indutny, 2018.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
[0]: https://github.com/nodejs/http-parser
|
||||
[1]: https://github.com/nodejs/llparse
|
||||
[2]: https://en.wikipedia.org/wiki/Register_allocation#Spilling
|
||||
[3]: https://en.wikipedia.org/wiki/Tail_call
|
||||
[4]: https://llvm.org/docs/LangRef.html
|
||||
[5]: https://llvm.org/docs/LangRef.html#call-instruction
|
||||
[6]: https://clang.llvm.org/
|
||||
[7]: https://github.com/nodejs/node
|
||||
[8]: https://github.com/pallas/pyllhttp
|
||||
[9]: https://github.com/metabahn/llhttp
|
||||
@ -0,0 +1,46 @@
|
||||
{
|
||||
'target_defaults': {
|
||||
'default_configuration': 'Debug',
|
||||
'configurations': {
|
||||
# TODO: hoist these out and put them somewhere common, because
|
||||
# RuntimeLibrary MUST MATCH across the entire project
|
||||
'Debug': {
|
||||
'defines': [ 'DEBUG', '_DEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 1, # static debug
|
||||
},
|
||||
},
|
||||
},
|
||||
'Release': {
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O3' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 0, # static release
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. llhttp.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'true',
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "win"', {
|
||||
'defines': [
|
||||
'WIN32'
|
||||
],
|
||||
}]
|
||||
],
|
||||
},
|
||||
}
|
||||
@ -0,0 +1,564 @@
|
||||
#ifndef INCLUDE_LLHTTP_H_
|
||||
#define INCLUDE_LLHTTP_H_
|
||||
|
||||
#define LLHTTP_VERSION_MAJOR 6
|
||||
#define LLHTTP_VERSION_MINOR 0
|
||||
#define LLHTTP_VERSION_PATCH 5
|
||||
|
||||
#ifndef LLHTTP_STRICT_MODE
|
||||
# define LLHTTP_STRICT_MODE 0
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_LLHTTP_ITSELF_H_
|
||||
#define INCLUDE_LLHTTP_ITSELF_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct llhttp__internal_s llhttp__internal_t;
|
||||
struct llhttp__internal_s {
|
||||
int32_t _index;
|
||||
void* _span_pos0;
|
||||
void* _span_cb0;
|
||||
int32_t error;
|
||||
const char* reason;
|
||||
const char* error_pos;
|
||||
void* data;
|
||||
void* _current;
|
||||
uint64_t content_length;
|
||||
uint8_t type;
|
||||
uint8_t method;
|
||||
uint8_t http_major;
|
||||
uint8_t http_minor;
|
||||
uint8_t header_state;
|
||||
uint8_t lenient_flags;
|
||||
uint8_t upgrade;
|
||||
uint8_t finish;
|
||||
uint16_t flags;
|
||||
uint16_t status_code;
|
||||
void* settings;
|
||||
};
|
||||
|
||||
int llhttp__internal_init(llhttp__internal_t* s);
|
||||
int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* INCLUDE_LLHTTP_ITSELF_H_ */
|
||||
|
||||
#ifndef LLLLHTTP_C_HEADERS_
|
||||
#define LLLLHTTP_C_HEADERS_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum llhttp_errno {
|
||||
HPE_OK = 0,
|
||||
HPE_INTERNAL = 1,
|
||||
HPE_STRICT = 2,
|
||||
HPE_LF_EXPECTED = 3,
|
||||
HPE_UNEXPECTED_CONTENT_LENGTH = 4,
|
||||
HPE_CLOSED_CONNECTION = 5,
|
||||
HPE_INVALID_METHOD = 6,
|
||||
HPE_INVALID_URL = 7,
|
||||
HPE_INVALID_CONSTANT = 8,
|
||||
HPE_INVALID_VERSION = 9,
|
||||
HPE_INVALID_HEADER_TOKEN = 10,
|
||||
HPE_INVALID_CONTENT_LENGTH = 11,
|
||||
HPE_INVALID_CHUNK_SIZE = 12,
|
||||
HPE_INVALID_STATUS = 13,
|
||||
HPE_INVALID_EOF_STATE = 14,
|
||||
HPE_INVALID_TRANSFER_ENCODING = 15,
|
||||
HPE_CB_MESSAGE_BEGIN = 16,
|
||||
HPE_CB_HEADERS_COMPLETE = 17,
|
||||
HPE_CB_MESSAGE_COMPLETE = 18,
|
||||
HPE_CB_CHUNK_HEADER = 19,
|
||||
HPE_CB_CHUNK_COMPLETE = 20,
|
||||
HPE_PAUSED = 21,
|
||||
HPE_PAUSED_UPGRADE = 22,
|
||||
HPE_PAUSED_H2_UPGRADE = 23,
|
||||
HPE_USER = 24
|
||||
};
|
||||
typedef enum llhttp_errno llhttp_errno_t;
|
||||
|
||||
enum llhttp_flags {
|
||||
F_CONNECTION_KEEP_ALIVE = 0x1,
|
||||
F_CONNECTION_CLOSE = 0x2,
|
||||
F_CONNECTION_UPGRADE = 0x4,
|
||||
F_CHUNKED = 0x8,
|
||||
F_UPGRADE = 0x10,
|
||||
F_CONTENT_LENGTH = 0x20,
|
||||
F_SKIPBODY = 0x40,
|
||||
F_TRAILING = 0x80,
|
||||
F_TRANSFER_ENCODING = 0x200
|
||||
};
|
||||
typedef enum llhttp_flags llhttp_flags_t;
|
||||
|
||||
enum llhttp_lenient_flags {
|
||||
LENIENT_HEADERS = 0x1,
|
||||
LENIENT_CHUNKED_LENGTH = 0x2,
|
||||
LENIENT_KEEP_ALIVE = 0x4
|
||||
};
|
||||
typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
|
||||
|
||||
enum llhttp_type {
|
||||
HTTP_BOTH = 0,
|
||||
HTTP_REQUEST = 1,
|
||||
HTTP_RESPONSE = 2
|
||||
};
|
||||
typedef enum llhttp_type llhttp_type_t;
|
||||
|
||||
enum llhttp_finish {
|
||||
HTTP_FINISH_SAFE = 0,
|
||||
HTTP_FINISH_SAFE_WITH_CB = 1,
|
||||
HTTP_FINISH_UNSAFE = 2
|
||||
};
|
||||
typedef enum llhttp_finish llhttp_finish_t;
|
||||
|
||||
enum llhttp_method {
|
||||
HTTP_DELETE = 0,
|
||||
HTTP_GET = 1,
|
||||
HTTP_HEAD = 2,
|
||||
HTTP_POST = 3,
|
||||
HTTP_PUT = 4,
|
||||
HTTP_CONNECT = 5,
|
||||
HTTP_OPTIONS = 6,
|
||||
HTTP_TRACE = 7,
|
||||
HTTP_COPY = 8,
|
||||
HTTP_LOCK = 9,
|
||||
HTTP_MKCOL = 10,
|
||||
HTTP_MOVE = 11,
|
||||
HTTP_PROPFIND = 12,
|
||||
HTTP_PROPPATCH = 13,
|
||||
HTTP_SEARCH = 14,
|
||||
HTTP_UNLOCK = 15,
|
||||
HTTP_BIND = 16,
|
||||
HTTP_REBIND = 17,
|
||||
HTTP_UNBIND = 18,
|
||||
HTTP_ACL = 19,
|
||||
HTTP_REPORT = 20,
|
||||
HTTP_MKACTIVITY = 21,
|
||||
HTTP_CHECKOUT = 22,
|
||||
HTTP_MERGE = 23,
|
||||
HTTP_MSEARCH = 24,
|
||||
HTTP_NOTIFY = 25,
|
||||
HTTP_SUBSCRIBE = 26,
|
||||
HTTP_UNSUBSCRIBE = 27,
|
||||
HTTP_PATCH = 28,
|
||||
HTTP_PURGE = 29,
|
||||
HTTP_MKCALENDAR = 30,
|
||||
HTTP_LINK = 31,
|
||||
HTTP_UNLINK = 32,
|
||||
HTTP_SOURCE = 33,
|
||||
HTTP_PRI = 34,
|
||||
HTTP_DESCRIBE = 35,
|
||||
HTTP_ANNOUNCE = 36,
|
||||
HTTP_SETUP = 37,
|
||||
HTTP_PLAY = 38,
|
||||
HTTP_PAUSE = 39,
|
||||
HTTP_TEARDOWN = 40,
|
||||
HTTP_GET_PARAMETER = 41,
|
||||
HTTP_SET_PARAMETER = 42,
|
||||
HTTP_REDIRECT = 43,
|
||||
HTTP_RECORD = 44,
|
||||
HTTP_FLUSH = 45
|
||||
};
|
||||
typedef enum llhttp_method llhttp_method_t;
|
||||
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
XX(0, OK, OK) \
|
||||
XX(1, INTERNAL, INTERNAL) \
|
||||
XX(2, STRICT, STRICT) \
|
||||
XX(3, LF_EXPECTED, LF_EXPECTED) \
|
||||
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
|
||||
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
|
||||
XX(6, INVALID_METHOD, INVALID_METHOD) \
|
||||
XX(7, INVALID_URL, INVALID_URL) \
|
||||
XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \
|
||||
XX(9, INVALID_VERSION, INVALID_VERSION) \
|
||||
XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \
|
||||
XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \
|
||||
XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \
|
||||
XX(13, INVALID_STATUS, INVALID_STATUS) \
|
||||
XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \
|
||||
XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \
|
||||
XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
|
||||
XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
|
||||
XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
|
||||
XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
|
||||
XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
|
||||
XX(21, PAUSED, PAUSED) \
|
||||
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
|
||||
XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \
|
||||
XX(24, USER, USER) \
|
||||
|
||||
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
XX(16, BIND, BIND) \
|
||||
XX(17, REBIND, REBIND) \
|
||||
XX(18, UNBIND, UNBIND) \
|
||||
XX(19, ACL, ACL) \
|
||||
XX(20, REPORT, REPORT) \
|
||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||
XX(22, CHECKOUT, CHECKOUT) \
|
||||
XX(23, MERGE, MERGE) \
|
||||
XX(24, MSEARCH, M-SEARCH) \
|
||||
XX(25, NOTIFY, NOTIFY) \
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
XX(28, PATCH, PATCH) \
|
||||
XX(29, PURGE, PURGE) \
|
||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||
XX(31, LINK, LINK) \
|
||||
XX(32, UNLINK, UNLINK) \
|
||||
XX(33, SOURCE, SOURCE) \
|
||||
|
||||
|
||||
#define RTSP_METHOD_MAP(XX) \
|
||||
XX(1, GET, GET) \
|
||||
XX(3, POST, POST) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(35, DESCRIBE, DESCRIBE) \
|
||||
XX(36, ANNOUNCE, ANNOUNCE) \
|
||||
XX(37, SETUP, SETUP) \
|
||||
XX(38, PLAY, PLAY) \
|
||||
XX(39, PAUSE, PAUSE) \
|
||||
XX(40, TEARDOWN, TEARDOWN) \
|
||||
XX(41, GET_PARAMETER, GET_PARAMETER) \
|
||||
XX(42, SET_PARAMETER, SET_PARAMETER) \
|
||||
XX(43, REDIRECT, REDIRECT) \
|
||||
XX(44, RECORD, RECORD) \
|
||||
XX(45, FLUSH, FLUSH) \
|
||||
|
||||
|
||||
#define HTTP_ALL_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
XX(16, BIND, BIND) \
|
||||
XX(17, REBIND, REBIND) \
|
||||
XX(18, UNBIND, UNBIND) \
|
||||
XX(19, ACL, ACL) \
|
||||
XX(20, REPORT, REPORT) \
|
||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||
XX(22, CHECKOUT, CHECKOUT) \
|
||||
XX(23, MERGE, MERGE) \
|
||||
XX(24, MSEARCH, M-SEARCH) \
|
||||
XX(25, NOTIFY, NOTIFY) \
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
XX(28, PATCH, PATCH) \
|
||||
XX(29, PURGE, PURGE) \
|
||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||
XX(31, LINK, LINK) \
|
||||
XX(32, UNLINK, UNLINK) \
|
||||
XX(33, SOURCE, SOURCE) \
|
||||
XX(34, PRI, PRI) \
|
||||
XX(35, DESCRIBE, DESCRIBE) \
|
||||
XX(36, ANNOUNCE, ANNOUNCE) \
|
||||
XX(37, SETUP, SETUP) \
|
||||
XX(38, PLAY, PLAY) \
|
||||
XX(39, PAUSE, PAUSE) \
|
||||
XX(40, TEARDOWN, TEARDOWN) \
|
||||
XX(41, GET_PARAMETER, GET_PARAMETER) \
|
||||
XX(42, SET_PARAMETER, SET_PARAMETER) \
|
||||
XX(43, REDIRECT, REDIRECT) \
|
||||
XX(44, RECORD, RECORD) \
|
||||
XX(45, FLUSH, FLUSH) \
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* LLLLHTTP_C_HEADERS_ */
|
||||
|
||||
#ifndef INCLUDE_LLHTTP_API_H_
|
||||
#define INCLUDE_LLHTTP_API_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__wasm__)
|
||||
#define LLHTTP_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LLHTTP_EXPORT
|
||||
#endif
|
||||
|
||||
typedef llhttp__internal_t llhttp_t;
|
||||
typedef struct llhttp_settings_s llhttp_settings_t;
|
||||
|
||||
typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);
|
||||
typedef int (*llhttp_cb)(llhttp_t*);
|
||||
|
||||
struct llhttp_settings_s {
|
||||
/* Possible return values 0, -1, `HPE_PAUSED` */
|
||||
llhttp_cb on_message_begin;
|
||||
|
||||
/* Possible return values 0, -1, HPE_USER */
|
||||
llhttp_data_cb on_url;
|
||||
llhttp_data_cb on_status;
|
||||
llhttp_data_cb on_header_field;
|
||||
llhttp_data_cb on_header_value;
|
||||
|
||||
/* Possible return values:
|
||||
* 0 - Proceed normally
|
||||
* 1 - Assume that request/response has no body, and proceed to parsing the
|
||||
* next message
|
||||
* 2 - Assume absence of body (as above) and make `llhttp_execute()` return
|
||||
* `HPE_PAUSED_UPGRADE`
|
||||
* -1 - Error
|
||||
* `HPE_PAUSED`
|
||||
*/
|
||||
llhttp_cb on_headers_complete;
|
||||
|
||||
/* Possible return values 0, -1, HPE_USER */
|
||||
llhttp_data_cb on_body;
|
||||
|
||||
/* Possible return values 0, -1, `HPE_PAUSED` */
|
||||
llhttp_cb on_message_complete;
|
||||
|
||||
/* When on_chunk_header is called, the current chunk length is stored
|
||||
* in parser->content_length.
|
||||
* Possible return values 0, -1, `HPE_PAUSED`
|
||||
*/
|
||||
llhttp_cb on_chunk_header;
|
||||
llhttp_cb on_chunk_complete;
|
||||
|
||||
/* Information-only callbacks, return value is ignored */
|
||||
llhttp_cb on_url_complete;
|
||||
llhttp_cb on_status_complete;
|
||||
llhttp_cb on_header_field_complete;
|
||||
llhttp_cb on_header_value_complete;
|
||||
};
|
||||
|
||||
/* Initialize the parser with specific type and user settings.
|
||||
*
|
||||
* NOTE: lifetime of `settings` has to be at least the same as the lifetime of
|
||||
* the `parser` here. In practice, `settings` has to be either a static
|
||||
* variable or be allocated with `malloc`, `new`, etc.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
|
||||
const llhttp_settings_t* settings);
|
||||
|
||||
#if defined(__wasm__)
|
||||
|
||||
LLHTTP_EXPORT
|
||||
llhttp_t* llhttp_alloc(llhttp_type_t type);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_free(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_type(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_http_major(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_http_minor(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_method(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
int llhttp_get_status_code(llhttp_t* parser);
|
||||
|
||||
LLHTTP_EXPORT
|
||||
uint8_t llhttp_get_upgrade(llhttp_t* parser);
|
||||
|
||||
#endif // defined(__wasm__)
|
||||
|
||||
/* Reset an already initialized parser back to the start state, preserving the
|
||||
* existing parser type, callback settings, user data, and lenient flags.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_reset(llhttp_t* parser);
|
||||
|
||||
/* Initialize the settings object */
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_settings_init(llhttp_settings_t* settings);
|
||||
|
||||
/* Parse full or partial request/response, invoking user callbacks along the
|
||||
* way.
|
||||
*
|
||||
* If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing
|
||||
* interrupts, and such errno is returned from `llhttp_execute()`. If
|
||||
* `HPE_PAUSED` was used as a errno, the execution can be resumed with
|
||||
* `llhttp_resume()` call.
|
||||
*
|
||||
* In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`
|
||||
* is returned after fully parsing the request/response. If the user wishes to
|
||||
* continue parsing, they need to invoke `llhttp_resume_after_upgrade()`.
|
||||
*
|
||||
* NOTE: if this function ever returns a non-pause type error, it will continue
|
||||
* to return the same error upon each successive call up until `llhttp_init()`
|
||||
* is called.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
|
||||
|
||||
/* This method should be called when the other side has no further bytes to
|
||||
* send (e.g. shutdown of readable side of the TCP connection.)
|
||||
*
|
||||
* Requests without `Content-Length` and other messages might require treating
|
||||
* all incoming bytes as the part of the body, up to the last byte of the
|
||||
* connection. This method will invoke `on_message_complete()` callback if the
|
||||
* request was terminated safely. Otherwise a error code would be returned.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
llhttp_errno_t llhttp_finish(llhttp_t* parser);
|
||||
|
||||
/* Returns `1` if the incoming message is parsed until the last byte, and has
|
||||
* to be completed by calling `llhttp_finish()` on EOF
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
int llhttp_message_needs_eof(const llhttp_t* parser);
|
||||
|
||||
/* Returns `1` if there might be any other messages following the last that was
|
||||
* successfully parsed.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
int llhttp_should_keep_alive(const llhttp_t* parser);
|
||||
|
||||
/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
|
||||
* appropriate error reason.
|
||||
*
|
||||
* Important: do not call this from user callbacks! User callbacks must return
|
||||
* `HPE_PAUSED` if pausing is required.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_pause(llhttp_t* parser);
|
||||
|
||||
/* Might be called to resume the execution after the pause in user's callback.
|
||||
* See `llhttp_execute()` above for details.
|
||||
*
|
||||
* Call this only if `llhttp_execute()` returns `HPE_PAUSED`.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_resume(llhttp_t* parser);
|
||||
|
||||
/* Might be called to resume the execution after the pause in user's callback.
|
||||
* See `llhttp_execute()` above for details.
|
||||
*
|
||||
* Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_resume_after_upgrade(llhttp_t* parser);
|
||||
|
||||
/* Returns the latest return error */
|
||||
LLHTTP_EXPORT
|
||||
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser);
|
||||
|
||||
/* Returns the verbal explanation of the latest returned error.
|
||||
*
|
||||
* Note: User callback should set error reason when returning the error. See
|
||||
* `llhttp_set_error_reason()` for details.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_get_error_reason(const llhttp_t* parser);
|
||||
|
||||
/* Assign verbal description to the returned error. Must be called in user
|
||||
* callbacks right before returning the errno.
|
||||
*
|
||||
* Note: `HPE_USER` error code might be useful in user callbacks.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_set_error_reason(llhttp_t* parser, const char* reason);
|
||||
|
||||
/* Returns the pointer to the last parsed byte before the returned error. The
|
||||
* pointer is relative to the `data` argument of `llhttp_execute()`.
|
||||
*
|
||||
* Note: this method might be useful for counting the number of parsed bytes.
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_get_error_pos(const llhttp_t* parser);
|
||||
|
||||
/* Returns textual name of error code */
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_errno_name(llhttp_errno_t err);
|
||||
|
||||
/* Returns textual name of HTTP method */
|
||||
LLHTTP_EXPORT
|
||||
const char* llhttp_method_name(llhttp_method_t method);
|
||||
|
||||
|
||||
/* Enables/disables lenient header value parsing (disabled by default).
|
||||
*
|
||||
* Lenient parsing disables header value token checks, extending llhttp's
|
||||
* protocol support to highly non-compliant clients/server. No
|
||||
* `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
|
||||
* lenient parsing is "on".
|
||||
*
|
||||
* **(USE AT YOUR OWN RISK)**
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
|
||||
|
||||
|
||||
/* Enables/disables lenient handling of conflicting `Transfer-Encoding` and
|
||||
* `Content-Length` headers (disabled by default).
|
||||
*
|
||||
* Normally `llhttp` would error when `Transfer-Encoding` is present in
|
||||
* conjunction with `Content-Length`. This error is important to prevent HTTP
|
||||
* request smuggling, but may be less desirable for small number of cases
|
||||
* involving legacy servers.
|
||||
*
|
||||
* **(USE AT YOUR OWN RISK)**
|
||||
*/
|
||||
LLHTTP_EXPORT
|
||||
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
|
||||
|
||||
|
||||
/* Enables/disables lenient handling of `Connection: close` and HTTP/1.0
|
||||
* requests responses.
|
||||
*
|
||||
* Normally `llhttp` would error on (in strict mode) or discard (in loose mode)
|
||||
* the HTTP request/response after the request/response with `Connection: close`
|
||||
* and `Content-Length`. This is important to prevent cache poisoning attacks,
|
||||
* but might interact badly with outdated and insecure clients. With this flag
|
||||
* the extra request/response will be parsed normally.
|
||||
*
|
||||
* **(USE AT YOUR OWN RISK)**
|
||||
*/
|
||||
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* INCLUDE_LLHTTP_API_H_ */
|
||||
|
||||
#endif /* INCLUDE_LLHTTP_H_ */
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'llhttp',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.', 'include' ],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [ 'include' ],
|
||||
},
|
||||
'sources': [ 'src/llhttp.c', 'src/api.c', 'src/http.c' ],
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,369 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "llhttp.h"
|
||||
|
||||
#define CALLBACK_MAYBE(PARSER, NAME) \
|
||||
do { \
|
||||
const llhttp_settings_t* settings; \
|
||||
settings = (const llhttp_settings_t*) (PARSER)->settings; \
|
||||
if (settings == NULL || settings->NAME == NULL) { \
|
||||
err = 0; \
|
||||
break; \
|
||||
} \
|
||||
err = settings->NAME((PARSER)); \
|
||||
} while (0)
|
||||
|
||||
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
|
||||
do { \
|
||||
const llhttp_settings_t* settings; \
|
||||
settings = (const llhttp_settings_t*) (PARSER)->settings; \
|
||||
if (settings == NULL || settings->NAME == NULL) { \
|
||||
err = 0; \
|
||||
break; \
|
||||
} \
|
||||
err = settings->NAME((PARSER), (START), (LEN)); \
|
||||
if (err == -1) { \
|
||||
err = HPE_USER; \
|
||||
llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
|
||||
const llhttp_settings_t* settings) {
|
||||
llhttp__internal_init(parser);
|
||||
|
||||
parser->type = type;
|
||||
parser->settings = (void*) settings;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__wasm__)
|
||||
|
||||
extern int wasm_on_message_begin(llhttp_t * p);
|
||||
extern int wasm_on_url(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_status(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_headers_complete(llhttp_t * p, int status_code,
|
||||
uint8_t upgrade, int should_keep_alive);
|
||||
extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
|
||||
extern int wasm_on_message_complete(llhttp_t * p);
|
||||
|
||||
static int wasm_on_headers_complete_wrap(llhttp_t* p) {
|
||||
return wasm_on_headers_complete(p, p->status_code, p->upgrade,
|
||||
llhttp_should_keep_alive(p));
|
||||
}
|
||||
|
||||
const llhttp_settings_t wasm_settings = {
|
||||
wasm_on_message_begin,
|
||||
wasm_on_url,
|
||||
wasm_on_status,
|
||||
wasm_on_header_field,
|
||||
wasm_on_header_value,
|
||||
wasm_on_headers_complete_wrap,
|
||||
wasm_on_body,
|
||||
wasm_on_message_complete,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
llhttp_t* llhttp_alloc(llhttp_type_t type) {
|
||||
llhttp_t* parser = malloc(sizeof(llhttp_t));
|
||||
llhttp_init(parser, type, &wasm_settings);
|
||||
return parser;
|
||||
}
|
||||
|
||||
void llhttp_free(llhttp_t* parser) {
|
||||
free(parser);
|
||||
}
|
||||
|
||||
/* Some getters required to get stuff from the parser */
|
||||
|
||||
uint8_t llhttp_get_type(llhttp_t* parser) {
|
||||
return parser->type;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_http_major(llhttp_t* parser) {
|
||||
return parser->http_major;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_http_minor(llhttp_t* parser) {
|
||||
return parser->http_minor;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_method(llhttp_t* parser) {
|
||||
return parser->method;
|
||||
}
|
||||
|
||||
int llhttp_get_status_code(llhttp_t* parser) {
|
||||
return parser->status_code;
|
||||
}
|
||||
|
||||
uint8_t llhttp_get_upgrade(llhttp_t* parser) {
|
||||
return parser->upgrade;
|
||||
}
|
||||
|
||||
#endif // defined(__wasm__)
|
||||
|
||||
|
||||
void llhttp_reset(llhttp_t* parser) {
|
||||
llhttp_type_t type = parser->type;
|
||||
const llhttp_settings_t* settings = parser->settings;
|
||||
void* data = parser->data;
|
||||
uint8_t lenient_flags = parser->lenient_flags;
|
||||
|
||||
llhttp__internal_init(parser);
|
||||
|
||||
parser->type = type;
|
||||
parser->settings = (void*) settings;
|
||||
parser->data = data;
|
||||
parser->lenient_flags = lenient_flags;
|
||||
}
|
||||
|
||||
|
||||
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
|
||||
return llhttp__internal_execute(parser, data, data + len);
|
||||
}
|
||||
|
||||
|
||||
void llhttp_settings_init(llhttp_settings_t* settings) {
|
||||
memset(settings, 0, sizeof(*settings));
|
||||
}
|
||||
|
||||
|
||||
llhttp_errno_t llhttp_finish(llhttp_t* parser) {
|
||||
int err;
|
||||
|
||||
/* We're in an error state. Don't bother doing anything. */
|
||||
if (parser->error != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (parser->finish) {
|
||||
case HTTP_FINISH_SAFE_WITH_CB:
|
||||
CALLBACK_MAYBE(parser, on_message_complete);
|
||||
if (err != HPE_OK) return err;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case HTTP_FINISH_SAFE:
|
||||
return HPE_OK;
|
||||
case HTTP_FINISH_UNSAFE:
|
||||
parser->reason = "Invalid EOF state";
|
||||
return HPE_INVALID_EOF_STATE;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void llhttp_pause(llhttp_t* parser) {
|
||||
if (parser->error != HPE_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = HPE_PAUSED;
|
||||
parser->reason = "Paused";
|
||||
}
|
||||
|
||||
|
||||
void llhttp_resume(llhttp_t* parser) {
|
||||
if (parser->error != HPE_PAUSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = 0;
|
||||
}
|
||||
|
||||
|
||||
void llhttp_resume_after_upgrade(llhttp_t* parser) {
|
||||
if (parser->error != HPE_PAUSED_UPGRADE) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = 0;
|
||||
}
|
||||
|
||||
|
||||
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
|
||||
return parser->error;
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_get_error_reason(const llhttp_t* parser) {
|
||||
return parser->reason;
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
|
||||
parser->reason = reason;
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_get_error_pos(const llhttp_t* parser) {
|
||||
return parser->error_pos;
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_errno_name(llhttp_errno_t err) {
|
||||
#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
|
||||
switch (err) {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
default: abort();
|
||||
}
|
||||
#undef HTTP_ERRNO_GEN
|
||||
}
|
||||
|
||||
|
||||
const char* llhttp_method_name(llhttp_method_t method) {
|
||||
#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
|
||||
switch (method) {
|
||||
HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)
|
||||
default: abort();
|
||||
}
|
||||
#undef HTTP_METHOD_GEN
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
|
||||
if (enabled) {
|
||||
parser->lenient_flags |= LENIENT_HEADERS;
|
||||
} else {
|
||||
parser->lenient_flags &= ~LENIENT_HEADERS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
|
||||
if (enabled) {
|
||||
parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;
|
||||
} else {
|
||||
parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
|
||||
if (enabled) {
|
||||
parser->lenient_flags |= LENIENT_KEEP_ALIVE;
|
||||
} else {
|
||||
parser->lenient_flags &= ~LENIENT_KEEP_ALIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
|
||||
int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_message_begin);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_url_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_status_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_header_field_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_header_value_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_headers_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_message_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_chunk_header);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
CALLBACK_MAYBE(s, on_chunk_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Private */
|
||||
|
||||
|
||||
void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
|
||||
const char* msg) {
|
||||
if (p == endp) {
|
||||
fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
|
||||
s->flags, msg);
|
||||
} else {
|
||||
fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
|
||||
s->type, s->flags, *p, msg);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
#include <stdio.h>
|
||||
#ifndef LLHTTP__TEST
|
||||
# include "llhttp.h"
|
||||
#else
|
||||
# define llhttp_t llparse_t
|
||||
#endif /* */
|
||||
|
||||
int llhttp_message_needs_eof(const llhttp_t* parser);
|
||||
int llhttp_should_keep_alive(const llhttp_t* parser);
|
||||
|
||||
int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
|
||||
const char* endp) {
|
||||
/* Set this here so that on_headers_complete() callbacks can see it */
|
||||
if ((parser->flags & F_UPGRADE) &&
|
||||
(parser->flags & F_CONNECTION_UPGRADE)) {
|
||||
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
|
||||
* mandatory only when it is a 101 Switching Protocols response,
|
||||
* otherwise it is purely informational, to announce support.
|
||||
*/
|
||||
parser->upgrade =
|
||||
(parser->type == HTTP_REQUEST || parser->status_code == 101);
|
||||
} else {
|
||||
parser->upgrade = (parser->method == HTTP_CONNECT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return values:
|
||||
* 0 - No body, `restart`, message_complete
|
||||
* 1 - CONNECT request, `restart`, message_complete, and pause
|
||||
* 2 - chunk_size_start
|
||||
* 3 - body_identity
|
||||
* 4 - body_identity_eof
|
||||
* 5 - invalid transfer-encoding for request
|
||||
*/
|
||||
int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
|
||||
const char* endp) {
|
||||
int hasBody;
|
||||
|
||||
hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
|
||||
if (parser->upgrade && (parser->method == HTTP_CONNECT ||
|
||||
(parser->flags & F_SKIPBODY) || !hasBody)) {
|
||||
/* Exit, the rest of the message is in a different protocol. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parser->flags & F_SKIPBODY) {
|
||||
return 0;
|
||||
} else if (parser->flags & F_CHUNKED) {
|
||||
/* chunked encoding - ignore Content-Length header, prepare for a chunk */
|
||||
return 2;
|
||||
} else if (parser->flags & F_TRANSFER_ENCODING) {
|
||||
if (parser->type == HTTP_REQUEST &&
|
||||
(parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0) {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field
|
||||
* is present in a request and the chunked transfer coding is not
|
||||
* the final encoding, the message body length cannot be determined
|
||||
* reliably; the server MUST respond with the 400 (Bad Request)
|
||||
* status code and then close the connection.
|
||||
*/
|
||||
return 5;
|
||||
} else {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field is present in a response and
|
||||
* the chunked transfer coding is not the final encoding, the
|
||||
* message body length is determined by reading the connection until
|
||||
* it is closed by the server.
|
||||
*/
|
||||
return 4;
|
||||
}
|
||||
} else {
|
||||
if (!(parser->flags & F_CONTENT_LENGTH)) {
|
||||
if (!llhttp_message_needs_eof(parser)) {
|
||||
/* Assume content-length 0 - read the next */
|
||||
return 0;
|
||||
} else {
|
||||
/* Read body until EOF */
|
||||
return 4;
|
||||
}
|
||||
} else if (parser->content_length == 0) {
|
||||
/* Content-Length header given but zero: Content-Length: 0\r\n */
|
||||
return 0;
|
||||
} else {
|
||||
/* Content-Length header given and non-zero */
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int llhttp__after_message_complete(llhttp_t* parser, const char* p,
|
||||
const char* endp) {
|
||||
int should_keep_alive;
|
||||
|
||||
should_keep_alive = llhttp_should_keep_alive(parser);
|
||||
parser->finish = HTTP_FINISH_SAFE;
|
||||
parser->flags = 0;
|
||||
|
||||
/* NOTE: this is ignored in loose parsing mode */
|
||||
return should_keep_alive;
|
||||
}
|
||||
|
||||
|
||||
int llhttp_message_needs_eof(const llhttp_t* parser) {
|
||||
if (parser->type == HTTP_REQUEST) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See RFC 2616 section 4.4 */
|
||||
if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
|
||||
parser->status_code == 204 || /* No Content */
|
||||
parser->status_code == 304 || /* Not Modified */
|
||||
(parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
|
||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
||||
(parser->flags & F_CHUNKED) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int llhttp_should_keep_alive(const llhttp_t* parser) {
|
||||
if (parser->http_major > 0 && parser->http_minor > 0) {
|
||||
/* HTTP/1.1 */
|
||||
if (parser->flags & F_CONNECTION_CLOSE) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* HTTP/1.0 or earlier */
|
||||
if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return !llhttp_message_needs_eof(parser);
|
||||
}
|
||||
14926
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/source/dependency/3rdparty/llhttp/src/llhttp.c
vendored
Normal file
14926
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/source/dependency/3rdparty/llhttp/src/llhttp.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,899 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core_http_client.h
|
||||
* @brief User facing functions of the HTTP Client library.
|
||||
*/
|
||||
|
||||
#ifndef CORE_HTTP_CLIENT_H_
|
||||
#define CORE_HTTP_CLIENT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* HTTP_DO_NOT_USE_CUSTOM_CONFIG allows building the HTTP Client library
|
||||
* without a config file. If a config file is provided, the
|
||||
* HTTP_DO_NOT_USE_CUSTOM_CONFIG macro must not be defined.
|
||||
*/
|
||||
#ifndef HTTP_DO_NOT_USE_CUSTOM_CONFIG
|
||||
#include "core_http_config.h"
|
||||
#endif
|
||||
|
||||
/* Include config defaults header to get default values of configurations not
|
||||
* defined in core_http_config.h file. */
|
||||
#include "core_http_config_defaults.h"
|
||||
|
||||
/* Transport interface include. */
|
||||
#include "transport_interface.h"
|
||||
|
||||
/* Convenience macros for some HTTP request methods. */
|
||||
|
||||
/** @addtogroup http_constants
|
||||
* @{
|
||||
*/
|
||||
#define HTTP_METHOD_GET "GET" /**< HTTP Method GET string. */
|
||||
#define HTTP_METHOD_PUT "PUT" /**< HTTP Method PUT string. */
|
||||
#define HTTP_METHOD_POST "POST" /**< HTTP Method POST string. */
|
||||
#define HTTP_METHOD_HEAD "HEAD" /**< HTTP Method HEAD string. */
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @ingroup http_constants
|
||||
* @brief The maximum Content-Length header field and value that could be
|
||||
* written to the request header buffer.
|
||||
*/
|
||||
#define HTTP_MAX_CONTENT_LENGTH_HEADER_LENGTH sizeof( "Content-Length: 4294967295" ) - 1U
|
||||
|
||||
/**
|
||||
* @defgroup http_send_flags HTTPClient_Send Flags
|
||||
* @brief Values for #HTTPClient_Send sendFlags parameter.
|
||||
* These flags control some behavior of sending the request or receiving the
|
||||
* response.
|
||||
*
|
||||
* Flags should be bitwise-ORed with each other to change the behavior of
|
||||
* #HTTPClient_Send.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup http_send_flags
|
||||
* @brief Set this flag to disable automatically writing the Content-Length
|
||||
* header to send to the server.
|
||||
*
|
||||
* This flag is valid only for #HTTPClient_Send sendFlags parameter.
|
||||
*/
|
||||
#define HTTP_SEND_DISABLE_CONTENT_LENGTH_FLAG 0x1U
|
||||
|
||||
/**
|
||||
* @defgroup http_request_flags HTTPRequestInfo_t Flags
|
||||
* @brief Flags for #HTTPRequestInfo_t.reqFlags.
|
||||
* These flags control what headers are written or not to the
|
||||
* #HTTPRequestHeaders_t.pBuffer by #HTTPClient_InitializeRequestHeaders.
|
||||
*
|
||||
* Flags should be bitwise-ORed with each other to change the behavior of
|
||||
* #HTTPClient_InitializeRequestHeaders.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup http_request_flags
|
||||
* @brief Set this flag to indicate that the request is for a persistent
|
||||
* connection.
|
||||
*
|
||||
* Setting this will cause a "Connection: Keep-Alive" to be written to the
|
||||
* request headers.
|
||||
*
|
||||
* This flag is valid only for #HTTPRequestInfo_t reqFlags parameter.
|
||||
*/
|
||||
#define HTTP_REQUEST_KEEP_ALIVE_FLAG 0x1U
|
||||
|
||||
/**
|
||||
* @defgroup http_response_flags HTTPResponse_t Flags
|
||||
* @brief Flags for #HTTPResponse_t.respFlags.
|
||||
* These flags are populated in #HTTPResponse_t.respFlags by the #HTTPClient_Send
|
||||
* function.
|
||||
*
|
||||
* A flag's value can be extracted from #HTTPResponse_t.respFlags with a
|
||||
* bitwise-AND.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup http_response_flags
|
||||
* @brief This will be set to true if header "Connection: close" is found.
|
||||
*
|
||||
* If a "Connection: close" header is present the application should always
|
||||
* close the connection.
|
||||
*
|
||||
* This flag is valid only for #HTTPResponse_t.respFlags.
|
||||
*/
|
||||
#define HTTP_RESPONSE_CONNECTION_CLOSE_FLAG 0x1U
|
||||
|
||||
/**
|
||||
* @ingroup http_response_flags
|
||||
* @brief This will be set to true if header "Connection: Keep-Alive" is found.
|
||||
*
|
||||
* This flag is valid only for #HTTPResponse_t.respFlags.
|
||||
*/
|
||||
#define HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG 0x2U
|
||||
|
||||
/**
|
||||
* @ingroup http_constants
|
||||
* @brief Flag that represents End of File byte in the range specification of
|
||||
* a Range Request.
|
||||
* This flag should be used ONLY for 2 kinds of range specifications when
|
||||
* creating the Range Request header through the #HTTPClient_AddRangeHeader
|
||||
* function:
|
||||
* - When the requested range is all bytes from the starting range byte to
|
||||
* the end of file.
|
||||
* - When the requested range is for the last N bytes of the file.
|
||||
* In both cases, this value should be used for the "rangeEnd" parameter.
|
||||
*/
|
||||
#define HTTP_RANGE_REQUEST_END_OF_FILE -1
|
||||
|
||||
/**
|
||||
* @ingroup http_enum_types
|
||||
* @brief The HTTP Client library return status.
|
||||
*/
|
||||
typedef enum HTTPStatus
|
||||
{
|
||||
/**
|
||||
* @brief The HTTP Client library function completed successfully.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_InitializeRequestHeaders
|
||||
* - #HTTPClient_AddHeader
|
||||
* - #HTTPClient_AddRangeHeader
|
||||
* - #HTTPClient_Send
|
||||
* - #HTTPClient_ReadHeader
|
||||
*/
|
||||
HTTPSuccess,
|
||||
|
||||
/**
|
||||
* @brief The HTTP Client library function input an invalid parameter.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_InitializeRequestHeaders
|
||||
* - #HTTPClient_AddHeader
|
||||
* - #HTTPClient_AddRangeHeader
|
||||
* - #HTTPClient_Send
|
||||
* - #HTTPClient_ReadHeader
|
||||
*/
|
||||
HTTPInvalidParameter,
|
||||
|
||||
/**
|
||||
* @brief A network error was returned from the transport interface.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPNetworkError,
|
||||
|
||||
/**
|
||||
* @brief Part of the HTTP response was received from the network.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPPartialResponse,
|
||||
|
||||
/**
|
||||
* @brief No HTTP response was received from the network.
|
||||
*
|
||||
* This can occur only if there was no data received from the transport
|
||||
* interface.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPNoResponse,
|
||||
|
||||
/**
|
||||
* @brief The application buffer was not large enough for the HTTP request
|
||||
* headers or the HTTP response message.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_InitializeRequestHeaders
|
||||
* - #HTTPClient_AddHeader
|
||||
* - #HTTPClient_AddRangeHeader
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPInsufficientMemory,
|
||||
|
||||
/**
|
||||
* @brief A response contained the "Connection: close" header, but there
|
||||
* was more data at the end of the complete message.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPSecurityAlertExtraneousResponseData,
|
||||
|
||||
/**
|
||||
* @brief The server sent a chunk header containing an invalid character.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPSecurityAlertInvalidChunkHeader,
|
||||
|
||||
/**
|
||||
* @brief The server sent a response with an invalid character in the
|
||||
* HTTP protocol version.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPSecurityAlertInvalidProtocolVersion,
|
||||
|
||||
/**
|
||||
* @brief The server sent a response with an invalid character in the
|
||||
* HTTP status-code or the HTTP status code is out of range.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPSecurityAlertInvalidStatusCode,
|
||||
|
||||
/**
|
||||
* @brief An invalid character was found in the HTTP response message or in
|
||||
* the HTTP request header.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_AddHeader
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPSecurityAlertInvalidCharacter,
|
||||
|
||||
/**
|
||||
* @brief The response contains either an invalid character in the
|
||||
* Content-Length header or a Content-Length header when it was not expected
|
||||
* to be present.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
*/
|
||||
HTTPSecurityAlertInvalidContentLength,
|
||||
|
||||
/**
|
||||
* @brief An error occurred in the third-party parsing library.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_Send
|
||||
* - #HTTPClient_ReadHeader
|
||||
*/
|
||||
HTTPParserInternalError,
|
||||
|
||||
/**
|
||||
* @brief The requested header field was not found in the response buffer.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_ReadHeader
|
||||
*/
|
||||
HTTPHeaderNotFound,
|
||||
|
||||
/**
|
||||
* @brief The HTTP response, provided for parsing, is either corrupt or
|
||||
* incomplete.
|
||||
*
|
||||
* Functions that may return this value:
|
||||
* - #HTTPClient_ReadHeader
|
||||
*/
|
||||
HTTPInvalidResponse
|
||||
} HTTPStatus_t;
|
||||
|
||||
/**
|
||||
* @ingroup http_struct_types
|
||||
* @brief Represents header data that will be sent in an HTTP request.
|
||||
*
|
||||
* The memory for the header data buffer is supplied by the user. Information in
|
||||
* the buffer will be filled by calling #HTTPClient_InitializeRequestHeaders and
|
||||
* #HTTPClient_AddHeader. This buffer may be automatically filled with the
|
||||
* Content-Length header in #HTTPClient_Send, please see
|
||||
* HTTP_MAX_CONTENT_LENGTH_HEADER_LENGTH for the maximum amount of space needed
|
||||
* to accommodate the Content-Length header.
|
||||
*/
|
||||
typedef struct HTTPRequestHeaders
|
||||
{
|
||||
/**
|
||||
* @brief Buffer to hold the raw HTTP request headers.
|
||||
*
|
||||
* This buffer is supplied by the application.
|
||||
*
|
||||
* This buffer is owned by the library during #HTTPClient_AddHeader,
|
||||
* #HTTPClient_AddRangeHeader, #HTTPClient_InitializeRequestHeaders, and
|
||||
* #HTTPClient_Send. This buffer should not be modified until
|
||||
* after these functions return.
|
||||
*
|
||||
* For optimization this buffer may be re-used with the response. The user
|
||||
* can re-use this buffer for the storing the response from the server in
|
||||
* #HTTPResponse_t.pBuffer.
|
||||
*/
|
||||
uint8_t * pBuffer;
|
||||
size_t bufferLen; /**< The length of pBuffer in bytes. */
|
||||
|
||||
/**
|
||||
* @brief The actual size in bytes of headers in the buffer. This field
|
||||
* is updated by the HTTP Client library functions #HTTPClient_AddHeader,
|
||||
* and #HTTPClient_InitializeRequestHeaders.
|
||||
*/
|
||||
size_t headersLen;
|
||||
} HTTPRequestHeaders_t;
|
||||
|
||||
/**
|
||||
* @ingroup http_struct_types
|
||||
* @brief Configurations of the initial request headers.
|
||||
*/
|
||||
typedef struct HTTPRequestInfo
|
||||
{
|
||||
/**
|
||||
* @brief The HTTP request method e.g. "GET", "POST", "PUT", or "HEAD".
|
||||
*/
|
||||
const char * pMethod;
|
||||
size_t methodLen; /**< The length of the method in bytes. */
|
||||
|
||||
/**
|
||||
* @brief The Request-URI to the objects of interest, e.g. "/path/to/item.txt".
|
||||
*/
|
||||
const char * pPath;
|
||||
size_t pathLen; /**< The length of the path in bytes. */
|
||||
|
||||
/**
|
||||
* @brief The server's host name, e.g. "my-storage.my-cloud.com".
|
||||
*
|
||||
* The host does not have a "https://" or "http://" prepending.
|
||||
*/
|
||||
const char * pHost;
|
||||
size_t hostLen; /**< The length of the host in bytes. */
|
||||
|
||||
/**
|
||||
* @brief Flags to activate other request header configurations.
|
||||
*
|
||||
* Please see @ref http_request_flags for more information.
|
||||
*/
|
||||
uint32_t reqFlags;
|
||||
} HTTPRequestInfo_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup http_struct_types
|
||||
* @brief Callback to intercept headers during the first parse through of the
|
||||
* response as it is received from the network.
|
||||
*/
|
||||
typedef struct HTTPClient_ResponseHeaderParsingCallback
|
||||
{
|
||||
/**
|
||||
* @brief Invoked when both a header field and its associated header value are found.
|
||||
* @param[in] pContext User context.
|
||||
* @param[in] fieldLoc Location of the header field name in the response buffer.
|
||||
* @param[in] fieldLen Length in bytes of the field name.
|
||||
* @param[in] valueLoc Location of the header value in the response buffer.
|
||||
* @param[in] valueLen Length in bytes of the value.
|
||||
* @param[in] statusCode The HTTP response status-code.
|
||||
*/
|
||||
void ( * onHeaderCallback )( void * pContext,
|
||||
const char * fieldLoc,
|
||||
size_t fieldLen,
|
||||
const char * valueLoc,
|
||||
size_t valueLen,
|
||||
uint16_t statusCode );
|
||||
|
||||
/**
|
||||
* @brief Private context for the application.
|
||||
*/
|
||||
void * pContext;
|
||||
} HTTPClient_ResponseHeaderParsingCallback_t;
|
||||
|
||||
/**
|
||||
* @ingroup http_callback_types
|
||||
* @brief Application provided function to query the current time in
|
||||
* milliseconds.
|
||||
*
|
||||
* @return The current time in milliseconds.
|
||||
*/
|
||||
typedef uint32_t (* HTTPClient_GetCurrentTimeFunc_t )( void );
|
||||
|
||||
/**
|
||||
* @ingroup http_struct_types
|
||||
* @brief Represents an HTTP response.
|
||||
*/
|
||||
typedef struct HTTPResponse
|
||||
{
|
||||
/**
|
||||
* @brief Buffer for both the raw HTTP header and body.
|
||||
*
|
||||
* This buffer is supplied by the application.
|
||||
*
|
||||
* This buffer is owned by the library during #HTTPClient_Send and
|
||||
* #HTTPClient_ReadHeader. This buffer should not be modified until after
|
||||
* these functions return.
|
||||
*
|
||||
* For optimization this buffer may be used with the request headers. The
|
||||
* request header buffer is configured in #HTTPRequestHeaders_t.pBuffer.
|
||||
* When the same buffer is used for the request headers, #HTTPClient_Send
|
||||
* will send the headers in the buffer first, then fill the buffer with
|
||||
* the response message.
|
||||
*/
|
||||
uint8_t * pBuffer;
|
||||
size_t bufferLen; /**< The length of the response buffer in bytes. */
|
||||
|
||||
/**
|
||||
* @brief Optional callback for intercepting the header during the first
|
||||
* parse through of the response as is it receive from the network.
|
||||
* Set to NULL to disable.
|
||||
*/
|
||||
HTTPClient_ResponseHeaderParsingCallback_t * pHeaderParsingCallback;
|
||||
|
||||
/**
|
||||
* @brief Optional callback for getting the system time.
|
||||
*
|
||||
* This is used to calculate the elapsed time when retrying network reads or
|
||||
* sends that return zero bytes received or sent, respectively. If this
|
||||
* field is set to NULL, then network send and receive won't be retried
|
||||
* after a zero is returned.
|
||||
*
|
||||
* If this function is set, then the maximum time for retrying network reads
|
||||
* that return zero bytes can be set through #HTTP_RECV_RETRY_TIMEOUT_MS.
|
||||
*
|
||||
* If this function is set, then the maximum elapsed time between network
|
||||
* sends greater than zero is set in HTTP_SEND_RETRY_TIMEOUT_MS.
|
||||
*/
|
||||
HTTPClient_GetCurrentTimeFunc_t getTime;
|
||||
|
||||
/**
|
||||
* @brief The starting location of the response headers in pBuffer.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
const uint8_t * pHeaders;
|
||||
|
||||
/**
|
||||
* @brief Byte length of the response headers in pBuffer.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
size_t headersLen;
|
||||
|
||||
/**
|
||||
* @brief The starting location of the response body in pBuffer.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
const uint8_t * pBody;
|
||||
|
||||
/**
|
||||
* @brief Byte length of the body in pBuffer.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
size_t bodyLen;
|
||||
|
||||
/* Useful HTTP header values found. */
|
||||
|
||||
/**
|
||||
* @brief The HTTP response Status-Code.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
uint16_t statusCode;
|
||||
|
||||
/**
|
||||
* @brief The value in the "Content-Length" header is returned here.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
size_t contentLength;
|
||||
|
||||
/**
|
||||
* @brief Count of the headers sent by the server.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send.
|
||||
*/
|
||||
size_t headerCount;
|
||||
|
||||
/**
|
||||
* @brief Flags of useful headers found in the response.
|
||||
*
|
||||
* This is updated by #HTTPClient_Send. Please see @ref http_response_flags
|
||||
* for more information.
|
||||
*/
|
||||
uint32_t respFlags;
|
||||
} HTTPResponse_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the request headers, stored in
|
||||
* #HTTPRequestHeaders_t.pBuffer, with initial configurations from
|
||||
* #HTTPRequestInfo_t. This method is expected to be called before sending a
|
||||
* new request.
|
||||
*
|
||||
* Upon return, #HTTPRequestHeaders_t.headersLen will be updated with the number
|
||||
* of bytes written.
|
||||
*
|
||||
* Each line in the header is listed below and written in this order:
|
||||
* <#HTTPRequestInfo_t.pMethod> <#HTTPRequestInfo_t.pPath> <#HTTP_PROTOCOL_VERSION>
|
||||
* User-Agent: <#HTTP_USER_AGENT_VALUE>
|
||||
* Host: <#HTTPRequestInfo_t.pHost>
|
||||
*
|
||||
* Note that "Connection" header can be added and set to "keep-alive" by
|
||||
* activating the HTTP_REQUEST_KEEP_ALIVE_FLAG in #HTTPRequestInfo_t.reqFlags.
|
||||
*
|
||||
* @param[in] pRequestHeaders Request header buffer information.
|
||||
* @param[in] pRequestInfo Initial request header configurations.
|
||||
* @return One of the following:
|
||||
* - #HTTPSuccess (If successful)
|
||||
* - #HTTPInvalidParameter (If any provided parameters or their members are invalid.)
|
||||
* - #HTTPInsufficientMemory (If provided buffer size is not large enough to hold headers.)
|
||||
*
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* // Declare an HTTPRequestHeaders_t and HTTPRequestInfo_t.
|
||||
* HTTPRequestHeaders_t requestHeaders = { 0 };
|
||||
* HTTPRequestInfo_t requestInfo = { 0 };
|
||||
* // A buffer that will fit the Request-Line, the User-Agent header line, and
|
||||
* // the Host header line.
|
||||
* uint8_t requestHeaderBuffer[ 256 ] = { 0 };
|
||||
*
|
||||
* // Set a buffer to serialize request headers to.
|
||||
* requestHeaders.pBuffer = requestHeaderBuffer;
|
||||
* requestHeaders.bufferLen = 256;
|
||||
*
|
||||
* // Set the Method, Path, and Host in the HTTPRequestInfo_t.
|
||||
* requestInfo.pMethod = HTTP_METHOD_GET;
|
||||
* requestInfo.methodLen = sizeof( HTTP_METHOD_GET ) - 1U;
|
||||
* requestInfo.pPath = "/html/rfc2616"
|
||||
* requestInfo.pathLen = sizeof( "/html/rfc2616" ) - 1U;
|
||||
* requestInfo.pHost = "tools.ietf.org"
|
||||
* requestInfo.hostLen = sizeof( "tools.ietf.org" ) - 1U;
|
||||
* requestInfo.reqFlags |= HTTP_REQUEST_KEEP_ALIVE_FLAG;
|
||||
*
|
||||
* httpLibraryStatus = HTTPClient_InitializeRequestHeaders( &requestHeaders,
|
||||
* &requestInfo );
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_httpclient_initializerequestheaders] */
|
||||
HTTPStatus_t HTTPClient_InitializeRequestHeaders( HTTPRequestHeaders_t * pRequestHeaders,
|
||||
const HTTPRequestInfo_t * pRequestInfo );
|
||||
/* @[declare_httpclient_initializerequestheaders] */
|
||||
|
||||
/**
|
||||
* @brief Add a header to the request headers stored in
|
||||
* #HTTPRequestHeaders_t.pBuffer.
|
||||
*
|
||||
* Upon return, pRequestHeaders->headersLen will be updated with the number of
|
||||
* bytes written.
|
||||
*
|
||||
* Headers are written in the following format:
|
||||
*
|
||||
* @code
|
||||
* <field>: <value>\r\n\r\n
|
||||
* @endcode
|
||||
*
|
||||
* The trailing `\r\n` that denotes the end of the header lines is overwritten,
|
||||
* if it already exists in the buffer.
|
||||
*
|
||||
* @note This function validates only that `\r`, `\n`, and `:` are not present
|
||||
* in @p pValue or @p pField. `:` is allowed in @p pValue.
|
||||
*
|
||||
* @param[in] pRequestHeaders Request header buffer information.
|
||||
* @param[in] pField The header field name to write.
|
||||
* The data should be ISO 8859-1 (Latin-1) encoded per the HTTP standard,
|
||||
* but the API does not perform the character set validation.
|
||||
* @param[in] fieldLen The byte length of the header field name.
|
||||
* @param[in] pValue The header value to write.
|
||||
* The data should be ISO 8859-1 (Latin-1) encoded per the HTTP standard,
|
||||
* but the API does not perform the character set validation.
|
||||
* @param[in] valueLen The byte length of the header field value.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #HTTPSuccess (If successful.)
|
||||
* - #HTTPInvalidParameter (If any provided parameters or their members are invalid.)
|
||||
* - #HTTPInsufficientMemory (If application-provided buffer is not large enough to hold headers.)
|
||||
* - #HTTPSecurityAlertInvalidCharacter (If an invalid character was found in @p pField or @p pValue.)
|
||||
*
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* // Assume that requestHeaders has already been initialized with
|
||||
* // HTTPClient_InitializeRequestHeaders().
|
||||
* HTTPRequestHeaders_t requestHeaders;
|
||||
*
|
||||
* httpLibraryStatus = HTTPClient_AddHeader( &requestHeaders,
|
||||
* "Request-Header-Field",
|
||||
* sizeof( "Request-Header-Field" ) - 1U,
|
||||
* "Request-Header-Value",
|
||||
* sizeof("Request-Header-Value") - 1U );
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_httpclient_addheader] */
|
||||
HTTPStatus_t HTTPClient_AddHeader( HTTPRequestHeaders_t * pRequestHeaders,
|
||||
const char * pField,
|
||||
size_t fieldLen,
|
||||
const char * pValue,
|
||||
size_t valueLen );
|
||||
/* @[declare_httpclient_addheader] */
|
||||
|
||||
/**
|
||||
* @brief Add the byte range request header to the request headers store in
|
||||
* #HTTPRequestHeaders_t.pBuffer.
|
||||
*
|
||||
* For example, if requesting for the first 1kB of a file the following would be
|
||||
* written: `Range: bytes=0-1023\r\n\r\n`.
|
||||
*
|
||||
* The trailing `\r\n` that denotes the end of the header lines is overwritten,
|
||||
* if it already exists in the buffer.
|
||||
*
|
||||
* There are 3 different forms of range specification, determined by the
|
||||
* combination of @a rangeStartOrLastNBytes and @a rangeEnd parameter values:
|
||||
*
|
||||
* 1. Request containing both parameters for the byte range [rangeStart, rangeEnd]
|
||||
* where @a rangeStartOrLastNBytes <= @a rangeEnd.
|
||||
* Example request header line: `Range: bytes=0-1023\r\n` for requesting bytes in the range [0, 1023].<br>
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* // Assume that requestHeaders has already been initialized with
|
||||
* // HTTPClient_InitializeRequestHeaders().
|
||||
* HTTPRequestHeaders_t requestHeaders;
|
||||
*
|
||||
* // Request for bytes 0 to 1023.
|
||||
* httpLibraryStatus = HTTPClient_AddRangeHeader( &requestHeaders, 0, 1023 );
|
||||
* @endcode
|
||||
*
|
||||
* 2. Request for the last N bytes, represented by @p rangeStartOrlastNbytes.
|
||||
* @p rangeStartOrlastNbytes should be negative and @p rangeEnd should be
|
||||
* #HTTP_RANGE_REQUEST_END_OF_FILE.
|
||||
* Example request header line: `Range: bytes=-512\r\n` for requesting the last 512 bytes
|
||||
* (or bytes in the range [512, 1023] for a 1KB sized file).<br>
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* // Assume that requestHeaders has already been initialized with
|
||||
* // HTTPClient_InitializeRequestHeaders().
|
||||
* HTTPRequestHeaders_t requestHeaders;
|
||||
*
|
||||
* // Request for the last 512 bytes.
|
||||
* httpLibraryStatus = HTTPClient_AddRangeHeader( &requestHeaders, -512, HTTP_RANGE_REQUEST_END_OF_FILE)
|
||||
* @endcode
|
||||
*
|
||||
* 3. Request for all bytes (till the end of byte sequence) from byte N,
|
||||
* represented by @p rangeStartOrlastNbytes.
|
||||
* @p rangeStartOrlastNbytes should be >= 0 and @p rangeEnd should be
|
||||
* #HTTP_RANGE_REQUEST_END_OF_FILE.<br>
|
||||
* Example request header line: `Range: bytes=256-\r\n` for requesting all bytes after and
|
||||
* including byte 256 (or bytes in the range [256,1023] for a 1kB sized file).<br>
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* // Assume that requestHeaders has already been initialized with
|
||||
* // HTTPClient_InitializeRequestHeaders().
|
||||
* HTTPRequestHeaders_t requestHeaders;
|
||||
*
|
||||
* // Request for all bytes from byte 256 onward.
|
||||
* httpLibraryStatus = HTTPClient_AddRangeHeader( &requestHeaders, 256, HTTP_RANGE_REQUEST_END_OF_FILE)
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] pRequestHeaders Request header buffer information.
|
||||
* @param[in] rangeStartOrlastNbytes Represents either the starting byte
|
||||
* for a range OR the last N number of bytes in the requested file.
|
||||
* @param[in] rangeEnd The ending range for the requested file. For end of file
|
||||
* byte in Range Specifications 2. and 3., #HTTP_RANGE_REQUEST_END_OF_FILE
|
||||
* should be passed.
|
||||
*
|
||||
* @return Returns the following status codes:
|
||||
* #HTTPSuccess, if successful.
|
||||
* #HTTPInvalidParameter, if input parameters are invalid, including when
|
||||
* the @p rangeStartOrlastNbytes and @p rangeEnd parameter combination is invalid.
|
||||
* #HTTPInsufficientMemory, if the passed #HTTPRequestHeaders_t.pBuffer
|
||||
* contains insufficient remaining memory for storing the range request.
|
||||
*/
|
||||
/* @[declare_httpclient_addrangeheader] */
|
||||
HTTPStatus_t HTTPClient_AddRangeHeader( HTTPRequestHeaders_t * pRequestHeaders,
|
||||
int32_t rangeStartOrlastNbytes,
|
||||
int32_t rangeEnd );
|
||||
/* @[declare_httpclient_addrangeheader] */
|
||||
|
||||
/**
|
||||
* @brief Send the request headers in #HTTPRequestHeaders_t.pBuffer and request
|
||||
* body in @p pRequestBodyBuf over the transport. The response is received in
|
||||
* #HTTPResponse_t.pBuffer.
|
||||
*
|
||||
* If #HTTP_SEND_DISABLE_CONTENT_LENGTH_FLAG is not set in parameter @p sendFlags,
|
||||
* then the Content-Length to be sent to the server is automatically written to
|
||||
* @p pRequestHeaders. The Content-Length will not be written when there is
|
||||
* no request body. If there is not enough room in the buffer to write the
|
||||
* Content-Length then #HTTPInsufficientMemory is returned. Please see
|
||||
* #HTTP_MAX_CONTENT_LENGTH_HEADER_LENGTH for the maximum Content-Length header
|
||||
* field and value that could be written to the buffer.
|
||||
*
|
||||
* The application should close the connection with the server if any of the
|
||||
* following errors are returned:
|
||||
* - #HTTPSecurityAlertExtraneousResponseData
|
||||
* - #HTTPSecurityAlertInvalidChunkHeader
|
||||
* - #HTTPSecurityAlertInvalidProtocolVersion
|
||||
* - #HTTPSecurityAlertInvalidStatusCode
|
||||
* - #HTTPSecurityAlertInvalidCharacter
|
||||
* - #HTTPSecurityAlertInvalidContentLength
|
||||
*
|
||||
* The @p pResponse returned is valid only if this function returns HTTPSuccess.
|
||||
*
|
||||
* @param[in] pTransport Transport interface, see #TransportInterface_t for
|
||||
* more information.
|
||||
* @param[in] pRequestHeaders Request configuration containing the buffer of
|
||||
* headers to send.
|
||||
* @param[in] pRequestBodyBuf Optional Request entity body. Set to NULL if there
|
||||
* is no request body.
|
||||
* @param[in] reqBodyBufLen The length of the request entity in bytes.
|
||||
* @param[in] pResponse The response message and some notable response
|
||||
* parameters will be returned here on success.
|
||||
* @param[in] sendFlags Flags which modify the behavior of this function. Please
|
||||
* see @ref http_send_flags for more information.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #HTTPSuccess (If successful.)
|
||||
* - #HTTPInvalidParameter (If any provided parameters or their members are invalid.)
|
||||
* - #HTTPNetworkError (Errors in sending or receiving over the transport interface.)
|
||||
* - #HTTPPartialResponse (Part of an HTTP response was received in a partially filled response buffer.)
|
||||
* - #HTTPNoResponse (No data was received from the transport interface.)
|
||||
* - #HTTPInsufficientMemory (The response received could not fit into the response buffer
|
||||
* or extra headers could not be sent in the request.)
|
||||
* - #HTTPParserInternalError (Internal parsing error.)\n\n
|
||||
* Security alerts are listed below, please see #HTTPStatus_t for more information:
|
||||
* - #HTTPSecurityAlertExtraneousResponseData
|
||||
* - #HTTPSecurityAlertInvalidChunkHeader
|
||||
* - #HTTPSecurityAlertInvalidProtocolVersion
|
||||
* - #HTTPSecurityAlertInvalidStatusCode
|
||||
* - #HTTPSecurityAlertInvalidCharacter
|
||||
* - #HTTPSecurityAlertInvalidContentLength
|
||||
*
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* // Variables used in this example.
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* TransportInterface_t transportInterface = { 0 };
|
||||
* HTTPResponse_t = { 0 };
|
||||
* char requestBody[] = "This is an example request body.";
|
||||
*
|
||||
* // Assume that requestHeaders has been initialized with
|
||||
* // HTTPClient_InitializeResponseHeaders() and any additional headers have
|
||||
* // been added with HTTPClient_AddHeader().
|
||||
* HTTPRequestHeaders_t requestHeaders;
|
||||
*
|
||||
* // Set the transport interface with platform specific functions that are
|
||||
* // assumed to be implemented elsewhere.
|
||||
* transportInterface.recv = myPlatformTransportReceive;
|
||||
* transportInterface.send = myPlatformTransportSend;
|
||||
* transportInterface.pNetworkContext = myPlatformNetworkContext;
|
||||
*
|
||||
* // Set the buffer to receive the HTTP response message into. The buffer is
|
||||
* // dynamically allocated for demonstration purposes only.
|
||||
* response.pBuffer = ( uint8_t* )malloc( 1024 );
|
||||
* response.bufferLen = 1024;
|
||||
*
|
||||
* httpLibraryStatus = HTTPClient_Send( &transportInterface,
|
||||
* &requestHeaders,
|
||||
* requestBody,
|
||||
* sizeof( requestBody ) - 1U,
|
||||
* &response,
|
||||
* 0 );
|
||||
*
|
||||
* if( httpLibraryStatus == HTTPSuccess )
|
||||
* {
|
||||
* if( response.status == 200 )
|
||||
* {
|
||||
* // Handle a response Status-Code of 200 OK.
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_httpclient_send] */
|
||||
HTTPStatus_t HTTPClient_Send( const TransportInterface_t * pTransport,
|
||||
HTTPRequestHeaders_t * pRequestHeaders,
|
||||
const uint8_t * pRequestBodyBuf,
|
||||
size_t reqBodyBufLen,
|
||||
HTTPResponse_t * pResponse,
|
||||
uint32_t sendFlags );
|
||||
/* @[declare_httpclient_send] */
|
||||
|
||||
/**
|
||||
* @brief Read a header from a buffer containing a complete HTTP response.
|
||||
* This will return the location of the response header value in the
|
||||
* #HTTPResponse_t.pBuffer buffer.
|
||||
*
|
||||
* The location, within #HTTPResponse_t.pBuffer, of the value found, will be
|
||||
* returned in @p pValue. If the header value is empty for the found @p pField,
|
||||
* then this function will return #HTTPSuccess, and set the values for
|
||||
* @p pValueLoc and @p pValueLen as NULL and zero respectively. According to
|
||||
* RFC 2616, it is not invalid to have an empty value for some header fields.
|
||||
*
|
||||
* @note This function should only be called on a complete HTTP response. If the
|
||||
* request is sent through the #HTTPClient_Send function, the #HTTPResponse_t is
|
||||
* incomplete until #HTTPClient_Send returns.
|
||||
*
|
||||
* @param[in] pResponse The buffer containing the completed HTTP response.
|
||||
* @param[in] pField The header field name to read.
|
||||
* @param[in] fieldLen The length of the header field name in bytes.
|
||||
* @param[out] pValueLoc This will be populated with the location of the
|
||||
* header value in the response buffer, #HTTPResponse_t.pBuffer.
|
||||
* @param[out] pValueLen This will be populated with the length of the
|
||||
* header value in bytes.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #HTTPSuccess (If successful.)
|
||||
* - #HTTPInvalidParameter (If any provided parameters or their members are invalid.)
|
||||
* - #HTTPHeaderNotFound (Header is not found in the passed response buffer.)
|
||||
* - #HTTPInvalidResponse (Provided response is not a valid HTTP response for parsing.)
|
||||
* - #HTTPParserInternalError(If an error in the response parser.)
|
||||
*
|
||||
* **Example**
|
||||
* @code{c}
|
||||
* HTTPStatus_t httpLibraryStatus = HTTPSuccess;
|
||||
* // Assume that response is returned from a successful invocation of
|
||||
* // HTTPClient_Send().
|
||||
* HTTPResponse_t response;
|
||||
*
|
||||
* char * pDateLoc = NULL;
|
||||
* size_t dateLen = 0;
|
||||
* // Search for a "Date" header field. pDateLoc will be the location of the
|
||||
* // Date header value in response.pBuffer.
|
||||
* httpLibraryStatus = HTTPClient_ReadHeader( &response,
|
||||
* "Date",
|
||||
* sizeof("Date") - 1,
|
||||
* &pDateLoc,
|
||||
* &dateLen );
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_httpclient_readheader] */
|
||||
HTTPStatus_t HTTPClient_ReadHeader( const HTTPResponse_t * pResponse,
|
||||
const char * pField,
|
||||
size_t fieldLen,
|
||||
const char ** pValueLoc,
|
||||
size_t * pValueLen );
|
||||
/* @[declare_httpclient_readheader] */
|
||||
|
||||
/**
|
||||
* @brief Error code to string conversion utility for HTTP Client library.
|
||||
*
|
||||
* @note This returns constant strings, which should not be modified.
|
||||
*
|
||||
* @param[in] status The status code to convert to a string.
|
||||
*
|
||||
* @return The string representation of the status code.
|
||||
*/
|
||||
/* @[declare_httpclient_strerror] */
|
||||
const char * HTTPClient_strerror( HTTPStatus_t status );
|
||||
/* @[declare_httpclient_strerror] */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef CORE_HTTP_CLIENT_H_ */
|
||||
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core_http_client_private.h
|
||||
* @brief Internal definitions to the HTTP Client library.
|
||||
*/
|
||||
|
||||
#ifndef CORE_HTTP_CLIENT_PRIVATE_H_
|
||||
#define CORE_HTTP_CLIENT_PRIVATE_H_
|
||||
|
||||
/**
|
||||
* @cond DOXYGEN_IGNORE
|
||||
* http-parser defaults this to 1, llhttp to 0.
|
||||
*/
|
||||
#ifndef LLHTTP_STRICT_MODE
|
||||
#define LLHTTP_STRICT_MODE 0
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
/* Third-party llhttp include. */
|
||||
#include "llhttp.h"
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* @brief The HTTP protocol version of this library is HTTP/1.1.
|
||||
*/
|
||||
#define HTTP_PROTOCOL_VERSION "HTTP/1.1"
|
||||
#define HTTP_PROTOCOL_VERSION_LEN ( sizeof( HTTP_PROTOCOL_VERSION ) - 1U ) /**< The length of #HTTP_PROTOCOL_VERSION. */
|
||||
|
||||
/**
|
||||
* @brief Default value when pRequestInfo->pPath == NULL.
|
||||
*/
|
||||
#define HTTP_EMPTY_PATH "/"
|
||||
#define HTTP_EMPTY_PATH_LEN ( sizeof( HTTP_EMPTY_PATH ) - 1U ) /**< The length of #HTTP_EMPTY_PATH. */
|
||||
|
||||
/* Constants for HTTP header formatting. */
|
||||
#define HTTP_HEADER_LINE_SEPARATOR "\r\n" /**< HTTP header field lines are separated by `\r\n`. */
|
||||
#define HTTP_HEADER_LINE_SEPARATOR_LEN ( sizeof( HTTP_HEADER_LINE_SEPARATOR ) - 1U ) /**< The length of #HTTP_HEADER_LINE_SEPARATOR. */
|
||||
#define HTTP_HEADER_END_INDICATOR "\r\n\r\n" /**< The HTTP header is complete when `\r\n\r\n` is found. */
|
||||
#define HTTP_HEADER_END_INDICATOR_LEN ( sizeof( HTTP_HEADER_END_INDICATOR ) - 1U ) /**< The length of #HTTP_HEADER_END_INDICATOR. */
|
||||
#define HTTP_HEADER_FIELD_SEPARATOR ": " /**< HTTP header field and values are separated by ": ". */
|
||||
#define HTTP_HEADER_FIELD_SEPARATOR_LEN ( sizeof( HTTP_HEADER_FIELD_SEPARATOR ) - 1U ) /**< The length of #HTTP_HEADER_FIELD_SEPARATOR. */
|
||||
#define SPACE_CHARACTER ' ' /**< A space character macro to help with serializing a request. */
|
||||
#define SPACE_CHARACTER_LEN ( 1U ) /**< The length of #SPACE_CHARACTER. */
|
||||
#define DASH_CHARACTER '-' /**< A dash character macro to help with serializing a request. */
|
||||
#define DASH_CHARACTER_LEN ( 1U ) /**< The length of #DASH_CHARACTER. */
|
||||
|
||||
/* Constants for HTTP header copy checks. */
|
||||
#define CARRIAGE_RETURN_CHARACTER '\r' /**< A carriage return character to help with header validation. */
|
||||
#define LINEFEED_CHARACTER '\n' /**< A linefeed character to help with header validation. */
|
||||
#define COLON_CHARACTER ':' /**< A colon character to help with header validation. */
|
||||
|
||||
/**
|
||||
* @brief Indicator for function #httpHeaderStrncpy that the pSrc parameter is a
|
||||
* header value.
|
||||
*/
|
||||
#define HTTP_HEADER_STRNCPY_IS_VALUE 0U
|
||||
|
||||
/**
|
||||
* @brief Indicator for function #httpHeaderStrncpy that the pSrc parameter is a
|
||||
* header field.
|
||||
*/
|
||||
#define HTTP_HEADER_STRNCPY_IS_FIELD 1U
|
||||
|
||||
/* Constants for header fields added automatically during the request
|
||||
* initialization. */
|
||||
#define HTTP_USER_AGENT_FIELD "User-Agent" /**< HTTP header field "User-Agent". */
|
||||
#define HTTP_USER_AGENT_FIELD_LEN ( sizeof( HTTP_USER_AGENT_FIELD ) - 1U ) /**< The length of #HTTP_USER_AGENT_FIELD. */
|
||||
#define HTTP_HOST_FIELD "Host" /**< HTTP header field "Host". */
|
||||
#define HTTP_HOST_FIELD_LEN ( sizeof( HTTP_HOST_FIELD ) - 1U ) /**< The length of #HTTP_HOST_FIELD. */
|
||||
#define HTTP_USER_AGENT_VALUE_LEN ( sizeof( HTTP_USER_AGENT_VALUE ) - 1U ) /**< The length of #HTTP_USER_AGENT_VALUE. */
|
||||
|
||||
/* Constants for header fields added based on flags. */
|
||||
#define HTTP_CONNECTION_FIELD "Connection" /**< HTTP header field "Connection". */
|
||||
#define HTTP_CONNECTION_FIELD_LEN ( sizeof( HTTP_CONNECTION_FIELD ) - 1U ) /**< The length of #HTTP_CONNECTION_FIELD. */
|
||||
#define HTTP_CONTENT_LENGTH_FIELD "Content-Length" /**< HTTP header field "Content-Length". */
|
||||
#define HTTP_CONTENT_LENGTH_FIELD_LEN ( sizeof( HTTP_CONTENT_LENGTH_FIELD ) - 1U ) /**< The length of #HTTP_CONTENT_LENGTH_FIELD. */
|
||||
|
||||
/* Constants for header values added based on flags. */
|
||||
|
||||
/* MISRA Ref 5.4.1 [Macro identifiers] */
|
||||
/* More details at: https://github.com/FreeRTOS/coreHTTP/blob/main/MISRA.md#rule-54 */
|
||||
/* coverity[other_declaration] */
|
||||
#define HTTP_CONNECTION_KEEP_ALIVE_VALUE "keep-alive" /**< HTTP header value "keep-alive" for the "Connection" header field. */
|
||||
|
||||
/* MISRA Ref 5.4.2 [Macro identifiers] */
|
||||
/* More details at: https://github.com/FreeRTOS/coreHTTP/blob/main/MISRA.md#rule-54 */
|
||||
/* coverity[misra_c_2012_rule_5_4_violation] */
|
||||
#define HTTP_CONNECTION_KEEP_ALIVE_VALUE_LEN ( sizeof( HTTP_CONNECTION_KEEP_ALIVE_VALUE ) - 1U ) /**< The length of #HTTP_CONNECTION_KEEP_ALIVE_VALUE. */
|
||||
|
||||
/* Constants relating to Range Requests. */
|
||||
|
||||
/* MISRA Ref 5.4.3 [Macro identifiers] */
|
||||
/* More details at: https://github.com/FreeRTOS/coreHTTP/blob/main/MISRA.md#rule-54 */
|
||||
/* coverity[other_declaration] */
|
||||
#define HTTP_RANGE_REQUEST_HEADER_FIELD "Range" /**< HTTP header field "Range". */
|
||||
|
||||
/* MISRA Ref 5.4.4 [Macro identifiers] */
|
||||
/* More details at: https://github.com/FreeRTOS/coreHTTP/blob/main/MISRA.md#rule-54 */
|
||||
/* coverity[misra_c_2012_rule_5_4_violation] */
|
||||
#define HTTP_RANGE_REQUEST_HEADER_FIELD_LEN ( sizeof( HTTP_RANGE_REQUEST_HEADER_FIELD ) - 1U ) /**< The length of #HTTP_RANGE_REQUEST_HEADER_FIELD. */
|
||||
|
||||
/* MISRA Ref 5.4.5 [Macro identifiers] */
|
||||
/* More details at: https://github.com/FreeRTOS/coreHTTP/blob/main/MISRA.md#rule-54 */
|
||||
/* coverity[other_declaration] */
|
||||
#define HTTP_RANGE_REQUEST_HEADER_VALUE_PREFIX "bytes=" /**< HTTP required header value prefix when specifying a byte range for partial content. */
|
||||
|
||||
/* MISRA Ref 5.4.6 [Macro identifiers] */
|
||||
/* More details at: https://github.com/FreeRTOS/coreHTTP/blob/main/MISRA.md#rule-54 */
|
||||
/* coverity[misra_c_2012_rule_5_4_violation] */
|
||||
#define HTTP_RANGE_REQUEST_HEADER_VALUE_PREFIX_LEN ( sizeof( HTTP_RANGE_REQUEST_HEADER_VALUE_PREFIX ) - 1U ) /**< The length of #HTTP_RANGE_REQUEST_HEADER_VALUE_PREFIX. */
|
||||
|
||||
/**
|
||||
* @brief Maximum value of a 32 bit signed integer is 2,147,483,647.
|
||||
*
|
||||
* Used for calculating buffer space for ASCII representation of range values.
|
||||
*/
|
||||
#define MAX_INT32_NO_OF_DECIMAL_DIGITS 10U
|
||||
|
||||
/**
|
||||
* @brief Maximum buffer space for storing a Range Request Value.
|
||||
*
|
||||
* The largest Range Request value is of the form:
|
||||
* "bytes=<Max-Integer-Value>-<Max-Integer-Value>"
|
||||
*/
|
||||
#define HTTP_MAX_RANGE_REQUEST_VALUE_LEN \
|
||||
( HTTP_RANGE_REQUEST_HEADER_VALUE_PREFIX_LEN + MAX_INT32_NO_OF_DECIMAL_DIGITS + \
|
||||
1U /* Dash character '-' */ + MAX_INT32_NO_OF_DECIMAL_DIGITS )
|
||||
|
||||
/**
|
||||
* @brief Return value for llhttp registered callback to signal
|
||||
* continuation of HTTP response parsing. Equal to HPE_OK.
|
||||
*/
|
||||
#define LLHTTP_CONTINUE_PARSING 0
|
||||
|
||||
/**
|
||||
* @brief Return value for llhttp registered callback to signal halting
|
||||
* further execution.
|
||||
*/
|
||||
#define LLHTTP_STOP_PARSING HPE_USER
|
||||
|
||||
/**
|
||||
* @brief Return value for llhttp_t.on_headers_complete to signal
|
||||
* that the HTTP response has no body and to halt further execution.
|
||||
*/
|
||||
#define LLHTTP_STOP_PARSING_NO_BODY 1
|
||||
|
||||
/**
|
||||
* @brief Return value for llhttp_t.on_headers_complete to signal
|
||||
* halting further execution. This is the same return value that
|
||||
* indicates the HTTP response has no body, but unlike the -1 error
|
||||
* code, gives consistent return values for llhttp_execute in both
|
||||
* strict and non-strict modes.
|
||||
*/
|
||||
#define LLHTTP_STOP_PARSING_NO_HEADER 1
|
||||
|
||||
/**
|
||||
* @brief The minimum request-line in the headers has a possible one character
|
||||
* custom method and a single forward / or asterisk * for the path:
|
||||
*
|
||||
* @code
|
||||
* <1 character custom method> <1 character / or *> HTTP/1.x\r\n\r\n
|
||||
* @endcode
|
||||
*
|
||||
* Therefore the minimum length is 16. If this minimum request-line is not
|
||||
* satisfied, then the request headers to send are invalid.
|
||||
*
|
||||
* Note that custom methods are allowed per:
|
||||
* https://tools.ietf.org/html/rfc2616#section-5.1.1.
|
||||
*/
|
||||
#define HTTP_MINIMUM_REQUEST_LINE_LENGTH 16u
|
||||
|
||||
/**
|
||||
* @brief The state of the response message parsed after function
|
||||
* #parseHttpResponse returns.
|
||||
*/
|
||||
typedef enum HTTPParsingState_t
|
||||
{
|
||||
HTTP_PARSING_NONE = 0, /**< The parser has not started reading any response. */
|
||||
HTTP_PARSING_INCOMPLETE, /**< The parser found a partial reponse. */
|
||||
HTTP_PARSING_COMPLETE /**< The parser found the entire response. */
|
||||
} HTTPParsingState_t;
|
||||
|
||||
/**
|
||||
* @brief An aggregator that represents the user-provided parameters to the
|
||||
* #HTTPClient_ReadHeader API function. This will be used as context parameter
|
||||
* for the parsing callbacks used by the API function.
|
||||
*/
|
||||
typedef struct findHeaderContext
|
||||
{
|
||||
const char * pField; /**< The field that is being searched for. */
|
||||
size_t fieldLen; /**< The length of pField. */
|
||||
const char ** pValueLoc; /**< The location of the value found in the buffer. */
|
||||
size_t * pValueLen; /**< the length of the value found. */
|
||||
uint8_t fieldFound; /**< Indicates that the header field was found during parsing. */
|
||||
uint8_t valueFound; /**< Indicates that the header value was found during parsing. */
|
||||
} findHeaderContext_t;
|
||||
|
||||
/**
|
||||
* @brief The HTTP response parsing context for a response fresh from the
|
||||
* server. This context is passed into the http-parser registered callbacks.
|
||||
* The registered callbacks are private functions of the form
|
||||
* httpParserXXXXCallbacks().
|
||||
*
|
||||
* The transitions of the httpParserXXXXCallback() functions are shown below.
|
||||
* The XXXX is replaced by the strings in the state boxes:
|
||||
*
|
||||
* +---------------------+
|
||||
* |onMessageBegin |
|
||||
* +--------+------------+
|
||||
* |
|
||||
* |
|
||||
* |
|
||||
* v
|
||||
* +--------+------------+
|
||||
* |onStatus |
|
||||
* +--------+------------+
|
||||
* |
|
||||
* |
|
||||
* |
|
||||
* v
|
||||
* +--------+------------+
|
||||
* |onHeaderField +<---+
|
||||
* +--------+------------+ |
|
||||
* | |
|
||||
* | |(More headers)
|
||||
* | |
|
||||
* v |
|
||||
* +--------+------------+ |
|
||||
* |onHeaderValue +----^
|
||||
* +--------+------------+
|
||||
* |
|
||||
* |
|
||||
* |
|
||||
* v
|
||||
* +--------+------------+
|
||||
* |onHeadersComplete |
|
||||
* +---------------------+
|
||||
* |
|
||||
* |
|
||||
* |
|
||||
* v
|
||||
* +--------+------------+
|
||||
* |onBody +<---+
|
||||
* +--------+--------+---+ |
|
||||
* | | |(Transfer-encoding chunked body)
|
||||
* | | |
|
||||
* | +--------+
|
||||
* |
|
||||
* v
|
||||
* +--------+------------+
|
||||
* |onMessageComplete |
|
||||
* +---------------------+
|
||||
*/
|
||||
typedef struct HTTPParsingContext
|
||||
{
|
||||
llhttp_t llhttpParser; /**< Third-party llhttp context. */
|
||||
llhttp_settings_t llhttpSettings; /**< Third-party parser settings. */
|
||||
HTTPParsingState_t state; /**< The current state of the HTTP response parsed. */
|
||||
HTTPResponse_t * pResponse; /**< HTTP response associated with this parsing context. */
|
||||
uint8_t isHeadResponse; /**< HTTP response is for a HEAD request. */
|
||||
|
||||
const char * pBufferCur; /**< The current location of the parser in the response buffer. */
|
||||
const char * pLastHeaderField; /**< Holds the last part of the header field parsed. */
|
||||
size_t lastHeaderFieldLen; /**< The length of the last header field parsed. */
|
||||
const char * pLastHeaderValue; /**< Holds the last part of the header value parsed. */
|
||||
size_t lastHeaderValueLen; /**< The length of the last value field parsed. */
|
||||
} HTTPParsingContext_t;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef CORE_HTTP_CLIENT_PRIVATE_H_ */
|
||||
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core_http_config_defaults.h
|
||||
* @brief The default values for the configuration macros for the HTTP Client
|
||||
* library.
|
||||
*
|
||||
* @note This file SHOULD NOT be modified. If custom values are needed for
|
||||
* any configuration macro, a core_http_config.h file should be provided to
|
||||
* the HTTP Client library to override the default values defined in this file.
|
||||
* To use the custom config file, the HTTP_DO_NOT_USE_CUSTOM_CONFIG preprocessor
|
||||
* macro SHOULD NOT be set.
|
||||
*/
|
||||
|
||||
#ifndef CORE_HTTP_CONFIG_DEFAULTS_
|
||||
#define CORE_HTTP_CONFIG_DEFAULTS_
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* @brief The HTTP header "User-Agent" value.
|
||||
*
|
||||
* The following header line is automatically written to
|
||||
* #HTTPRequestHeaders_t.pBuffer:
|
||||
* "User-Agent: my-platform-name\r\n"
|
||||
*
|
||||
* <b>Possible values:</b> Any string. <br>
|
||||
* <b>Default value:</b> `my-platform-name`
|
||||
*/
|
||||
#ifndef HTTP_USER_AGENT_VALUE
|
||||
#define HTTP_USER_AGENT_VALUE "my-platform-name"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The maximum duration between non-empty network reads while receiving
|
||||
* an HTTP response via the #HTTPClient_Send API function.
|
||||
*
|
||||
* The transport receive function may be called multiple times until the end of
|
||||
* the response is detected by the parser. This timeout represents the maximum
|
||||
* duration that is allowed without any data reception from the network for the
|
||||
* incoming response.
|
||||
*
|
||||
* If the timeout expires, the #HTTPClient_Send function will return
|
||||
* #HTTPNetworkError.
|
||||
*
|
||||
* If #HTTPResponse_t.getTime is set to NULL, then this HTTP_RECV_RETRY_TIMEOUT_MS
|
||||
* is unused. When this timeout is unused, #HTTPClient_Send will not retry the
|
||||
* transport receive calls that return zero bytes read.
|
||||
*
|
||||
* <b>Possible values:</b> Any positive 32 bit integer. A small timeout value
|
||||
* is recommended. <br>
|
||||
* <b>Default value:</b> `10`
|
||||
*/
|
||||
#ifndef HTTP_RECV_RETRY_TIMEOUT_MS
|
||||
#define HTTP_RECV_RETRY_TIMEOUT_MS ( 10U )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The maximum duration between non-empty network transmissions while
|
||||
* sending an HTTP request via the #HTTPClient_Send API function.
|
||||
*
|
||||
* When sending an HTTP request, the transport send function may be called multiple
|
||||
* times until all of the required number of bytes are sent.
|
||||
* This timeout represents the maximum duration that is allowed for no data
|
||||
* transmission over the network through the transport send function.
|
||||
*
|
||||
* If the timeout expires, the #HTTPClient_Send function returns #HTTPNetworkError.
|
||||
*
|
||||
* If #HTTPResponse_t.getTime is set to NULL, then this HTTP_RECV_RETRY_TIMEOUT_MS
|
||||
* is unused. When this timeout is unused, #HTTPClient_Send will not retry the
|
||||
* transport send calls that return zero bytes sent.
|
||||
*
|
||||
* <b>Possible values:</b> Any positive 32 bit integer. A small timeout value
|
||||
* is recommended. <br>
|
||||
* <b>Default value:</b> `10`
|
||||
*/
|
||||
#ifndef HTTP_SEND_RETRY_TIMEOUT_MS
|
||||
#define HTTP_SEND_RETRY_TIMEOUT_MS ( 10U )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Macro that is called in the HTTP Client library for logging "Error" level
|
||||
* messages.
|
||||
*
|
||||
* To enable error level logging in the HTTP Client library, this macro should be mapped to the
|
||||
* application-specific logging implementation that supports error logging.
|
||||
*
|
||||
* @note This logging macro is called in the HTTP Client library with parameters wrapped in
|
||||
* double parentheses to be ISO C89/C90 standard compliant. For a reference
|
||||
* POSIX implementation of the logging macros, refer to core_http_config.h files, and the
|
||||
* logging-stack in demos folder of the
|
||||
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
|
||||
*
|
||||
* <b>Default value</b>: Error logging is turned off, and no code is generated for calls
|
||||
* to the macro in the HTTP Client library on compilation.
|
||||
*/
|
||||
#ifndef LogError
|
||||
#define LogError( message )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Macro that is called in the HTTP Client library for logging "Warning" level
|
||||
* messages.
|
||||
*
|
||||
* To enable warning level logging in the HTTP Client library, this macro should be mapped to the
|
||||
* application-specific logging implementation that supports warning logging.
|
||||
*
|
||||
* @note This logging macro is called in the HTTP Client library with parameters wrapped in
|
||||
* double parentheses to be ISO C89/C90 standard compliant. For a reference
|
||||
* POSIX implementation of the logging macros, refer to core_http_config.h files, and the
|
||||
* logging-stack in demos folder of the
|
||||
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
|
||||
*
|
||||
* <b>Default value</b>: Warning logs are turned off, and no code is generated for calls
|
||||
* to the macro in the HTTP Client library on compilation.
|
||||
*/
|
||||
#ifndef LogWarn
|
||||
#define LogWarn( message )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Macro that is called in the HTTP Client library for logging "Info" level
|
||||
* messages.
|
||||
*
|
||||
* To enable info level logging in the HTTP Client library, this macro should be mapped to the
|
||||
* application-specific logging implementation that supports info logging.
|
||||
*
|
||||
* @note This logging macro is called in the HTTP Client library with parameters wrapped in
|
||||
* double parentheses to be ISO C89/C90 standard compliant. For a reference
|
||||
* POSIX implementation of the logging macros, refer to core_http_config.h files, and the
|
||||
* logging-stack in demos folder of the
|
||||
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
|
||||
*
|
||||
* <b>Default value</b>: Info logging is turned off, and no code is generated for calls
|
||||
* to the macro in the HTTP Client library on compilation.
|
||||
*/
|
||||
#ifndef LogInfo
|
||||
#define LogInfo( message )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Macro that is called in the HTTP Client library for logging "Debug" level
|
||||
* messages.
|
||||
*
|
||||
* To enable debug level logging from HTTP Client library, this macro should be mapped to the
|
||||
* application-specific logging implementation that supports debug logging.
|
||||
*
|
||||
* @note This logging macro is called in the HTTP Client library with parameters wrapped in
|
||||
* double parentheses to be ISO C89/C90 standard compliant. For a reference
|
||||
* POSIX implementation of the logging macros, refer to core_http_config.h files, and the
|
||||
* logging-stack in demos folder of the
|
||||
* [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
|
||||
*
|
||||
* <b>Default value</b>: Debug logging is turned off, and no code is generated for calls
|
||||
* to the macro in the HTTP Client library on compilation.
|
||||
*/
|
||||
#ifndef LogDebug
|
||||
#define LogDebug( message )
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef CORE_HTTP_CONFIG_DEFAULTS_ */
|
||||
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file transport_interface.h
|
||||
* @brief Transport interface definitions to send and receive data over the
|
||||
* network.
|
||||
*/
|
||||
#ifndef TRANSPORT_INTERFACE_H_
|
||||
#define TRANSPORT_INTERFACE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* @transportpage
|
||||
* @brief The transport interface definition.
|
||||
*
|
||||
* @transportsectionoverview
|
||||
*
|
||||
* The transport interface is a set of APIs that must be implemented using an
|
||||
* external transport layer protocol. The transport interface is defined in
|
||||
* @ref transport_interface.h. This interface allows protocols like MQTT and
|
||||
* HTTP to send and receive data over the transport layer. This
|
||||
* interface does not handle connection and disconnection to the server of
|
||||
* interest. The connection, disconnection, and other transport settings, like
|
||||
* timeout and TLS setup, must be handled in the user application.
|
||||
* <br>
|
||||
*
|
||||
* The functions that must be implemented are:<br>
|
||||
* - [Transport Receive](@ref TransportRecv_t)
|
||||
* - [Transport Send](@ref TransportSend_t)
|
||||
*
|
||||
* Each of the functions above take in an opaque context @ref NetworkContext_t.
|
||||
* The functions above and the context are also grouped together in the
|
||||
* @ref TransportInterface_t structure:<br><br>
|
||||
* @snippet this define_transportinterface
|
||||
* <br>
|
||||
*
|
||||
* @transportsectionimplementation
|
||||
*
|
||||
* The following steps give guidance on implementing the transport interface:
|
||||
*
|
||||
* -# Implementing @ref NetworkContext_t<br><br>
|
||||
* @snippet this define_networkcontext
|
||||
* <br>
|
||||
* @ref NetworkContext_t is the incomplete type <b>struct NetworkContext</b>.
|
||||
* The implemented struct NetworkContext must contain all of the information
|
||||
* that is needed to receive and send data with the @ref TransportRecv_t
|
||||
* and the @ref TransportSend_t implementations.<br>
|
||||
* In the case of TLS over TCP, struct NetworkContext is typically implemented
|
||||
* with the TCP socket context and a TLS context.<br><br>
|
||||
* <b>Example code:</b>
|
||||
* @code{c}
|
||||
* struct NetworkContext
|
||||
* {
|
||||
* struct MyTCPSocketContext tcpSocketContext;
|
||||
* struct MyTLSContext tlsContext;
|
||||
* };
|
||||
* @endcode
|
||||
* <br>
|
||||
* -# Implementing @ref TransportRecv_t<br><br>
|
||||
* @snippet this define_transportrecv
|
||||
* <br>
|
||||
* This function is expected to populate a buffer, with bytes received from the
|
||||
* transport, and return the number of bytes placed in the buffer.
|
||||
* In the case of TLS over TCP, @ref TransportRecv_t is typically implemented by
|
||||
* calling the TLS layer function to receive data. In case of plaintext TCP
|
||||
* without TLS, it is typically implemented by calling the TCP layer receive
|
||||
* function. @ref TransportRecv_t may be invoked multiple times by the protocol
|
||||
* library, if fewer bytes than were requested to receive are returned.
|
||||
* <br><br>
|
||||
* <b>Example code:</b>
|
||||
* @code{c}
|
||||
* int32_t myNetworkRecvImplementation( NetworkContext_t * pNetworkContext,
|
||||
* void * pBuffer,
|
||||
* size_t bytesToRecv )
|
||||
* {
|
||||
* int32_t bytesReceived = 0;
|
||||
* bool callTlsRecvFunc = true;
|
||||
*
|
||||
* // For a single byte read request, check if data is available on the network.
|
||||
* if( bytesToRecv == 1 )
|
||||
* {
|
||||
* // If no data is available on the network, do not call TLSRecv
|
||||
* // to avoid blocking for socket timeout.
|
||||
* if( TLSRecvCount( pNetworkContext->tlsContext ) == 0 )
|
||||
* {
|
||||
* callTlsRecvFunc = false;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* if( callTlsRecvFunc == true )
|
||||
* {
|
||||
* bytesReceived = TLSRecv( pNetworkContext->tlsContext,
|
||||
* pBuffer,
|
||||
* bytesToRecv,
|
||||
* MY_SOCKET_TIMEOUT );
|
||||
* if( bytesReceived < 0 )
|
||||
* {
|
||||
* // If the error code represents a timeout, then the return
|
||||
* // code should be translated to zero so that the caller
|
||||
* // can retry the read operation.
|
||||
* if( bytesReceived == MY_SOCKET_ERROR_TIMEOUT )
|
||||
* {
|
||||
* bytesReceived = 0;
|
||||
* }
|
||||
* }
|
||||
* // Handle other cases.
|
||||
* }
|
||||
* return bytesReceived;
|
||||
* }
|
||||
* @endcode
|
||||
* <br>
|
||||
* -# Implementing @ref TransportSend_t<br><br>
|
||||
* @snippet this define_transportsend
|
||||
* <br>
|
||||
* This function is expected to send the bytes, in the given buffer over the
|
||||
* transport, and return the number of bytes sent.
|
||||
* In the case of TLS over TCP, @ref TransportSend_t is typically implemented by
|
||||
* calling the TLS layer function to send data. In case of plaintext TCP
|
||||
* without TLS, it is typically implemented by calling the TCP layer send
|
||||
* function. @ref TransportSend_t may be invoked multiple times by the protocol
|
||||
* library, if fewer bytes than were requested to send are returned.
|
||||
* <br><br>
|
||||
* <b>Example code:</b>
|
||||
* @code{c}
|
||||
* int32_t myNetworkSendImplementation( NetworkContext_t * pNetworkContext,
|
||||
* const void * pBuffer,
|
||||
* size_t bytesToSend )
|
||||
* {
|
||||
* int32_t bytesSent = 0;
|
||||
* bytesSent = TLSSend( pNetworkContext->tlsContext,
|
||||
* pBuffer,
|
||||
* bytesToSend,
|
||||
* MY_SOCKET_TIMEOUT );
|
||||
*
|
||||
* // If underlying TCP buffer is full, set the return value to zero
|
||||
* // so that caller can retry the send operation.
|
||||
* if( bytesSent == MY_SOCKET_ERROR_BUFFER_FULL )
|
||||
* {
|
||||
* bytesSent = 0;
|
||||
* }
|
||||
* else if( bytesSent < 0 )
|
||||
* {
|
||||
* // Handle socket error.
|
||||
* }
|
||||
* // Handle other cases.
|
||||
*
|
||||
* return bytesSent;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
* @transportstruct
|
||||
* @typedef NetworkContext_t
|
||||
* @brief The NetworkContext is an incomplete type. An implementation of this
|
||||
* interface must define struct NetworkContext for the system requirements.
|
||||
* This context is passed into the network interface functions.
|
||||
*/
|
||||
/* @[define_networkcontext] */
|
||||
struct NetworkContext;
|
||||
typedef struct NetworkContext NetworkContext_t;
|
||||
/* @[define_networkcontext] */
|
||||
|
||||
/**
|
||||
* @transportcallback
|
||||
* @brief Transport interface for receiving data on the network.
|
||||
*
|
||||
* @note It is RECOMMENDED that the transport receive implementation
|
||||
* does NOT block when requested to read a single byte. A single byte
|
||||
* read request can be made by the caller to check whether there is a
|
||||
* new frame available on the network for reading.
|
||||
* However, the receive implementation MAY block for a timeout period when
|
||||
* it is requested to read more than 1 byte. This is because once the caller
|
||||
* is aware that a new frame is available to read on the network, then
|
||||
* the likelihood of reading more than one byte over the network becomes high.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
* @param[in] pBuffer Buffer to receive the data into.
|
||||
* @param[in] bytesToRecv Number of bytes requested from the network.
|
||||
*
|
||||
* @return The number of bytes received or a negative value to indicate
|
||||
* error.
|
||||
*
|
||||
* @note If no data is available on the network to read and no error
|
||||
* has occurred, zero MUST be the return value. A zero return value
|
||||
* SHOULD represent that the read operation can be retried by calling
|
||||
* the API function. Zero MUST NOT be returned if a network disconnection
|
||||
* has occurred.
|
||||
*/
|
||||
/* @[define_transportrecv] */
|
||||
typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
|
||||
void * pBuffer,
|
||||
size_t bytesToRecv );
|
||||
/* @[define_transportrecv] */
|
||||
|
||||
/**
|
||||
* @transportcallback
|
||||
* @brief Transport interface for sending data over the network.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
* @param[in] pBuffer Buffer containing the bytes to send over the network stack.
|
||||
* @param[in] bytesToSend Number of bytes to send over the network.
|
||||
*
|
||||
* @return The number of bytes sent or a negative value to indicate error.
|
||||
*
|
||||
* @note If no data is transmitted over the network due to a full TX buffer and
|
||||
* no network error has occurred, this MUST return zero as the return value.
|
||||
* A zero return value SHOULD represent that the send operation can be retried
|
||||
* by calling the API function. Zero MUST NOT be returned if a network disconnection
|
||||
* has occurred.
|
||||
*/
|
||||
/* @[define_transportsend] */
|
||||
typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
|
||||
const void * pBuffer,
|
||||
size_t bytesToSend );
|
||||
/* @[define_transportsend] */
|
||||
|
||||
/**
|
||||
* @brief Transport vector structure for sending multiple messages.
|
||||
*/
|
||||
typedef struct TransportOutVector
|
||||
{
|
||||
/**
|
||||
* @brief Base address of data.
|
||||
*/
|
||||
const void * iov_base;
|
||||
|
||||
/**
|
||||
* @brief Length of data in buffer.
|
||||
*/
|
||||
size_t iov_len;
|
||||
} TransportOutVector_t;
|
||||
|
||||
/**
|
||||
* @transportcallback
|
||||
* @brief Transport interface function for "vectored" / scatter-gather based
|
||||
* writes. This function is expected to iterate over the list of vectors pIoVec
|
||||
* having ioVecCount entries containing portions of one MQTT message at a maximum.
|
||||
* If the proper functionality is available, then the data in the list should be
|
||||
* copied to the underlying TCP buffer before flushing the buffer. Implementing it
|
||||
* in this fashion will lead to sending of fewer TCP packets for all the values
|
||||
* in the list.
|
||||
*
|
||||
* @note If the proper write functionality is not present for a given device/IP-stack,
|
||||
* then there is no strict requirement to implement write. Only the send and recv
|
||||
* interfaces must be defined for the application to work properly.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
* @param[in] pIoVec An array of TransportIoVector_t structs.
|
||||
* @param[in] ioVecCount Number of TransportIoVector_t in pIoVec.
|
||||
*
|
||||
* @return The number of bytes written or a negative value to indicate error.
|
||||
*
|
||||
* @note If no data is written to the buffer due to the buffer being full this MUST
|
||||
* return zero as the return value.
|
||||
* A zero return value SHOULD represent that the write operation can be retried
|
||||
* by calling the API function. Zero MUST NOT be returned if a network disconnection
|
||||
* has occurred.
|
||||
*/
|
||||
/* @[define_transportwritev] */
|
||||
typedef int32_t ( * TransportWritev_t )( NetworkContext_t * pNetworkContext,
|
||||
TransportOutVector_t * pIoVec,
|
||||
size_t ioVecCount );
|
||||
/* @[define_transportwritev] */
|
||||
|
||||
/**
|
||||
* @transportstruct
|
||||
* @brief The transport layer interface.
|
||||
*/
|
||||
/* @[define_transportinterface] */
|
||||
typedef struct TransportInterface
|
||||
{
|
||||
TransportRecv_t recv; /**< Transport receive function pointer. */
|
||||
TransportSend_t send; /**< Transport send function pointer. */
|
||||
TransportWritev_t writev; /**< Transport writev function pointer. */
|
||||
NetworkContext_t * pNetworkContext; /**< Implementation-defined network context. */
|
||||
} TransportInterface_t;
|
||||
/* @[define_transportinterface] */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef TRANSPORT_INTERFACE_H_ */
|
||||
@ -0,0 +1,109 @@
|
||||
# Project information.
|
||||
cmake_minimum_required ( VERSION 3.13.0 )
|
||||
project ( "coreHTTP unit test"
|
||||
VERSION 1.0.0
|
||||
LANGUAGES C )
|
||||
|
||||
# Allow the project to be organized into folders.
|
||||
set_property( GLOBAL PROPERTY USE_FOLDERS ON )
|
||||
|
||||
# Use C90.
|
||||
set( CMAKE_C_STANDARD 90 )
|
||||
set( CMAKE_C_STANDARD_REQUIRED ON )
|
||||
|
||||
# Do not allow in-source build.
|
||||
if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} )
|
||||
message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." )
|
||||
endif()
|
||||
|
||||
# Set global path variables.
|
||||
get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
||||
set(MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "coreHTTP repository root.")
|
||||
|
||||
# Configure options to always show in CMake GUI.
|
||||
option( BUILD_CLONE_SUBMODULES
|
||||
"Set this to ON to automatically clone any required Git submodules. When OFF, submodules must be manually cloned."
|
||||
ON )
|
||||
|
||||
# Set output directories.
|
||||
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
|
||||
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
|
||||
|
||||
# ====================== Coverity Analysis Configuration =======================
|
||||
|
||||
# Include filepaths for source and include.
|
||||
include( ${MODULE_ROOT_DIR}/httpFilePaths.cmake )
|
||||
|
||||
# Target for Coverity analysis that builds the library.
|
||||
add_library( coverity_analysis
|
||||
${HTTP_SOURCES} )
|
||||
|
||||
# Build HTTP library target without custom config dependency.
|
||||
target_compile_definitions( coverity_analysis PUBLIC HTTP_DO_NOT_USE_CUSTOM_CONFIG=1 )
|
||||
|
||||
# HTTP public include path.
|
||||
target_include_directories( coverity_analysis PUBLIC ${HTTP_INCLUDE_PUBLIC_DIRS} )
|
||||
|
||||
# Build HTTP library target without logging
|
||||
target_compile_options(coverity_analysis PUBLIC -DNDEBUG )
|
||||
# ===================== Clone needed third-party libraries ======================
|
||||
|
||||
# Define an llhttp paser resource path.
|
||||
set( LLHTTP_DIR ${MODULE_ROOT_DIR}/source/dependency/3rdparty/llhttp CACHE INTERNAL "llhttp library source directory." )
|
||||
|
||||
include( llhttp_build.cmake )
|
||||
|
||||
# Check if the llhttp_source directory exists.
|
||||
if( NOT EXISTS ${LLHTTP_DIR}/src/llhttp.c )
|
||||
# Attempt to clone llhttp.
|
||||
if( ${BUILD_CLONE_SUBMODULES} )
|
||||
clone_llhttp()
|
||||
else()
|
||||
message( FATAL_ERROR "The required submodule llhttp does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ============================ Test configuration ==============================
|
||||
|
||||
# Define a CMock resource path.
|
||||
set( CMOCK_DIR ${MODULE_ROOT_DIR}/test/unit-test/CMock CACHE INTERNAL "CMock library source directory." )
|
||||
|
||||
# Include CMock build configuration.
|
||||
include( unit-test/cmock_build.cmake )
|
||||
|
||||
# Check if the CMock source directory exists, and if not present, clone the submodule
|
||||
# if BUILD_CLONE_SUBMODULES configuration is enabled.
|
||||
if( NOT EXISTS ${CMOCK_DIR}/src )
|
||||
# Attempt to clone CMock.
|
||||
if( ${BUILD_CLONE_SUBMODULES} )
|
||||
clone_cmock()
|
||||
else()
|
||||
message( FATAL_ERROR "The required submodule CMock does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add unit test and coverage configuration.
|
||||
|
||||
# Use CTest utility for managing test runs. This has to be added BEFORE
|
||||
# defining test targets with add_test()
|
||||
enable_testing()
|
||||
|
||||
# Add build targets for CMock and Unit, required for unit testing.
|
||||
add_cmock_targets()
|
||||
|
||||
# Add function to enable CMock based tests and coverage.
|
||||
include( ${MODULE_ROOT_DIR}/tools/cmock/create_test.cmake )
|
||||
|
||||
# Include build configuration for unit tests.
|
||||
add_subdirectory( unit-test )
|
||||
|
||||
# ==================== Coverage Analysis configuration ========================
|
||||
|
||||
# Add a target for running coverage on tests.
|
||||
add_custom_target( coverage
|
||||
COMMAND ${CMAKE_COMMAND} -DCMOCK_DIR=${CMOCK_DIR}
|
||||
-P ${MODULE_ROOT_DIR}/tools/cmock/coverage.cmake
|
||||
DEPENDS cmock unity core_http_utest core_http_send_utest
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
24
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/test/cbmc/.gitignore
vendored
Normal file
24
kernel/FreeRTOS-Plus/Source/Application-Protocols/coreHTTP/test/cbmc/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Emitted when running CBMC proofs
|
||||
proofs/**/logs
|
||||
proofs/**/gotos
|
||||
proofs/**/report
|
||||
proofs/**/html
|
||||
proofs/output
|
||||
|
||||
# Emitted by CBMC Viewer
|
||||
TAGS-*
|
||||
|
||||
# Emitted by Arpa
|
||||
arpa_cmake/
|
||||
arpa-validation-logs/
|
||||
Makefile.arpa
|
||||
|
||||
# Emitted by litani
|
||||
.ninja_deps
|
||||
.ninja_log
|
||||
.litani_cache_dir
|
||||
|
||||
# These files should be overwritten whenever prepare.py runs
|
||||
cbmc-batch.yaml
|
||||
|
||||
__pycache__/
|
||||
@ -0,0 +1,6 @@
|
||||
CBMC proof include files
|
||||
========================
|
||||
|
||||
This directory contains include files written for CBMC proof. It is
|
||||
common to write some code to model aspects of the system under test,
|
||||
and the header files for this code go here.
|
||||
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file callback_stubs.h
|
||||
* @brief Defines a stub function for
|
||||
* #HTTPClient_ResponseHeaderParsingCallback_t.onHeaderCallback
|
||||
*/
|
||||
|
||||
#ifndef CALLBACK_STUBS_H_
|
||||
#define CALLBACK_STUBS_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Invoked when both a header field and its associated header value are found.
|
||||
*
|
||||
* @param[in] pContext User context.
|
||||
* @param[in] fieldLoc Location of the header field name in the response buffer.
|
||||
* @param[in] fieldLen Length in bytes of the field name.
|
||||
* @param[in] valueLoc Location of the header value in the response buffer.
|
||||
* @param[in] valueLen Length in bytes of the value.
|
||||
* @param[in] statusCode The HTTP response status-code.
|
||||
*/
|
||||
void onHeaderCallbackStub( void * pContext,
|
||||
const char * fieldLoc,
|
||||
size_t fieldLen,
|
||||
const char * valueLoc,
|
||||
size_t valueLen,
|
||||
uint16_t statusCode );
|
||||
|
||||
#endif /* ifndef CALLBACK_STUBS_H_ */
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core_http_config.h
|
||||
* @brief Custom configurations for the coreHTTP library.
|
||||
*/
|
||||
|
||||
#ifndef CORE_HTTP_CONFIG_H
|
||||
#define CORE_HTTP_CONFIG_H
|
||||
|
||||
/**
|
||||
* @brief The maximum duration between non-empty network reads while receiving
|
||||
* an HTTP response via the #HTTPClient_Send API function.
|
||||
*
|
||||
* The transport receive function may be called multiple times until the end of
|
||||
* the response is detected by the parser. This timeout represents the maximum
|
||||
* duration that is allowed without any data reception from the network for the
|
||||
* incoming response.
|
||||
*
|
||||
* If the timeout expires, the #HTTPClient_Send function will return
|
||||
* #HTTPNetworkError.
|
||||
*
|
||||
* This is set to 1 to exit right away after a zero is received in the transport
|
||||
* receive stub. There is no added value, in proving memory safety, to repeat
|
||||
* the logic that checks if the retry timeout is reached.
|
||||
*/
|
||||
#define HTTP_RECV_RETRY_TIMEOUT_MS ( 1U )
|
||||
|
||||
/**
|
||||
* @brief The maximum duration between non-empty network transmissions while
|
||||
* sending an HTTP request via the #HTTPClient_Send API function.
|
||||
*
|
||||
* When sending an HTTP request, the transport send function may be called multiple
|
||||
* times until all of the required number of bytes are sent.
|
||||
* This timeout represents the maximum duration that is allowed for no data
|
||||
* transmission over the network through the transport send function.
|
||||
*
|
||||
* If the timeout expires, the #HTTPClient_Send function returns #HTTPNetworkError.
|
||||
*
|
||||
* This is set to 1 to exit right away after a zero is received in the transport
|
||||
* send stub. There is no added value, in proving memory safety, to repeat
|
||||
* the logic that checks if the retry timeout is reached.
|
||||
*/
|
||||
#define HTTP_SEND_RETRY_TIMEOUT_MS ( 1U )
|
||||
|
||||
|
||||
#endif /* ifndef CORE_HTTP_CONFIG_H */
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file get_time_stub.h
|
||||
* @brief Stub definition for the application defined callback to retrieve the
|
||||
* current time in milliseconds.
|
||||
*/
|
||||
#ifndef GET_TIME_STUB_H_
|
||||
#define GET_TIME_STUB_H_
|
||||
|
||||
/**
|
||||
* Application defined callback to retrieve the current time in milliseconds.
|
||||
*
|
||||
* @return The current time in milliseconds.
|
||||
*/
|
||||
uint32_t GetCurrentTimeStub( void );
|
||||
|
||||
#endif /* ifndef GET_TIME_STUB_H_ */
|
||||
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file http_cbmc_state.h
|
||||
* @brief Functions to allocate memory and validate data types for proofs.
|
||||
*/
|
||||
|
||||
#ifndef HTTP_CBMC_STATE_H_
|
||||
#define HTTP_CBMC_STATE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core_http_client.h"
|
||||
#include "core_http_client_private.h"
|
||||
#include "llhttp.h"
|
||||
#include "transport_interface_stubs.h"
|
||||
|
||||
struct NetworkContext
|
||||
{
|
||||
int filler;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attains coverage when a variable needs to possibly contain two values.
|
||||
*/
|
||||
bool nondet_bool();
|
||||
|
||||
/**
|
||||
* @brief Calls malloc based on given size or returns NULL for coverage.
|
||||
*
|
||||
* Implementation of safe malloc which returns NULL if the requested size is 0.
|
||||
* The behavior of malloc(0) is platform dependent.
|
||||
* It is possible for malloc(0) to return an address without allocating memory.
|
||||
*
|
||||
* @param[in] size Requested size to malloc.
|
||||
*
|
||||
* @return Requested memory or NULL.
|
||||
*/
|
||||
void * mallocCanFail( size_t size );
|
||||
|
||||
/**
|
||||
* @brief Allocates an #HTTPRequestHeaders_t object.
|
||||
*
|
||||
* @param[in] pRequestHeaders #HTTPRequestHeaders_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #HTTPRequestHeaders_t object.
|
||||
*/
|
||||
HTTPRequestHeaders_t * allocateHttpRequestHeaders( HTTPRequestHeaders_t * pRequestHeaders );
|
||||
|
||||
/**
|
||||
* @brief Validates if a #HTTPRequestHeaders_t object is feasible.
|
||||
*
|
||||
* @param[in] pRequestHeaders #HTTPRequestHeaders_t object to validate.
|
||||
*
|
||||
* @return True if #pRequestHeaders is feasible; false otherwise.
|
||||
*/
|
||||
bool isValidHttpRequestHeaders( const HTTPRequestHeaders_t * pRequestHeaders );
|
||||
|
||||
/**
|
||||
* @brief Allocates a #HTTPRequestInfo_t object.
|
||||
*
|
||||
* @param[in] pRequestInfo #HTTPRequestInfo_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #HTTPRequestInfo_t object.
|
||||
*/
|
||||
HTTPRequestInfo_t * allocateHttpRequestInfo( HTTPRequestInfo_t * pRequestInfo );
|
||||
|
||||
/**
|
||||
* @brief Validates if a #HTTPRequestInfo_t object is feasible.
|
||||
*
|
||||
* @param[in] pRequestInfo #HTTPRequestInfo_t object to validate.
|
||||
*
|
||||
* @return True if #pRequestInfo is feasible; false otherwise.
|
||||
*/
|
||||
bool isValidHttpRequestInfo( const HTTPRequestInfo_t * pRequestInfo );
|
||||
|
||||
/**
|
||||
* @brief Allocates a #HTTPResponse_t object.
|
||||
*
|
||||
* @param[in] pResponse #HTTPResponse_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #HTTPResponse_t object.
|
||||
*/
|
||||
HTTPResponse_t * allocateHttpResponse( HTTPResponse_t * pResponse );
|
||||
|
||||
/**
|
||||
* @brief Validates if a #HTTPResponse_t object is feasible.
|
||||
*
|
||||
* @param[in] pResponse #HTTPResponse_t object to validate.
|
||||
*
|
||||
* @return True if #HTTPResponse_t is feasible; false otherwise.
|
||||
*/
|
||||
bool isValidHttpResponse( const HTTPResponse_t * pResponse );
|
||||
|
||||
/**
|
||||
* @brief Allocates a #TransportInterface_t object.
|
||||
*
|
||||
* @param[in] pTransport #TransportInterface_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #TransportInterface_t object.
|
||||
*/
|
||||
TransportInterface_t * allocateTransportInterface( TransportInterface_t * pTransport );
|
||||
|
||||
/**
|
||||
* @brief Validates if a #TransportInterface_t object is feasible.
|
||||
*
|
||||
* @param[in] pTransportInterface #TransportInterface_t object to validate.
|
||||
*
|
||||
* @return True if #pTransportInterface is feasible; false otherwise.
|
||||
*/
|
||||
bool isValidTransportInterface( TransportInterface_t * pTransportInterface );
|
||||
|
||||
/**
|
||||
* @brief Allocate an #llhttp_t object that is valid in the context of the
|
||||
* HTTPClient_Send() function.
|
||||
*
|
||||
* @param[in] pHttpParser #llhttp_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #llhttp_t object.
|
||||
*/
|
||||
llhttp_t * allocateHttpSendParser( llhttp_t * pHttpParser );
|
||||
|
||||
/**
|
||||
* @brief Allocate an #HTTPParsingContext_t object.
|
||||
*
|
||||
* @param[in] pHttpParsingContext #HTTPParsingContext_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #HTTPParsingContext_t object.
|
||||
*/
|
||||
HTTPParsingContext_t * allocateHttpSendParsingContext( HTTPParsingContext_t * pHttpParsingContext );
|
||||
|
||||
/**
|
||||
* @brief Validates if a #HTTPParsingContext_t object is feasible.
|
||||
*
|
||||
* @param[in] pHttpParsingContext #HTTPParsingContext_t object to validate.
|
||||
*
|
||||
* @return True if #pHttpParsingContext is feasible; false otherwise.
|
||||
*/
|
||||
bool isValidHttpSendParsingContext( const HTTPParsingContext_t * pHttpParsingContext );
|
||||
|
||||
/**
|
||||
* @brief Allocate an #llhttp_t object that is valid in the context of the
|
||||
* HTTPClient_ReadHeader() function.
|
||||
*
|
||||
* @param[in] pHttpParser #llhttp_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #llhttp_t object.
|
||||
*/
|
||||
llhttp_t * allocateHttpReadHeaderParser( llhttp_t * pHttpParser );
|
||||
|
||||
/**
|
||||
* @brief Allocate an #findHeaderContext_t object.
|
||||
*
|
||||
* @param[in] pFindHeaderContext #findHeaderContext_t object to allocate.
|
||||
*
|
||||
* @return NULL or pointer to allocated #findHeaderContext_t object.
|
||||
*/
|
||||
findHeaderContext_t * allocateFindHeaderContext( findHeaderContext_t * pFindHeaderContext );
|
||||
|
||||
|
||||
#endif /* ifndef HTTP_CBMC_STATE_H_ */
|
||||
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file transport_interface_stubs.h
|
||||
* @brief Functions, for CBMC proofs, to mock transport sending and receiving
|
||||
* implementations.
|
||||
*/
|
||||
|
||||
#ifndef TRANSPORT_INTERFACE_STUBS_H_
|
||||
#define TRANSPORT_INTERFACE_STUBS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core_http_client.h"
|
||||
|
||||
#ifndef MAX_TRIES
|
||||
#define MAX_TRIES 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Transport interface stub for mocking data sent over the network.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
* @param[in] pBuffer Buffer containing the bytes to send over the network stack.
|
||||
* @param[in] bytesToSend Number of bytes to send over the network.
|
||||
*
|
||||
* @return The number of bytes sent or a negative error code.
|
||||
*/
|
||||
int32_t TransportInterfaceSendStub( NetworkContext_t * pNetworkContext,
|
||||
void * pBuffer,
|
||||
size_t bytesToSend );
|
||||
|
||||
/**
|
||||
* @brief Transport interface for mocking data received over the network.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
* @param[in] pBuffer Buffer to receive the data into.
|
||||
* @param[in] bytesToRecv Number of bytes requested from the network.
|
||||
*
|
||||
* @return The number of bytes received or a negative error code.
|
||||
*/
|
||||
int32_t TransportInterfaceReceiveStub( NetworkContext_t * pNetworkContext,
|
||||
void * pBuffer,
|
||||
size_t bytesToRecv );
|
||||
|
||||
#endif /* ifndef TRANSPORT_INTERFACE_STUBS_H_ */
|
||||
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HTTPClient_AddHeader_harness.c
|
||||
* @brief Implements the proof harness for HTTPClient_AddHeader function.
|
||||
*/
|
||||
|
||||
#include "core_http_client.h"
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
|
||||
void HTTPClient_AddHeader_harness()
|
||||
{
|
||||
HTTPRequestHeaders_t * pRequestHeaders;
|
||||
char * pField;
|
||||
char * pValue;
|
||||
size_t fieldLen;
|
||||
size_t valueLen;
|
||||
|
||||
/* Initialize and make assumptions for request headers. */
|
||||
pRequestHeaders = allocateHttpRequestHeaders( NULL );
|
||||
__CPROVER_assume( isValidHttpRequestHeaders( pRequestHeaders ) );
|
||||
|
||||
/* Initialize and make assumptions for header field. */
|
||||
__CPROVER_assume( fieldLen < CBMC_MAX_OBJECT_SIZE );
|
||||
pField = mallocCanFail( fieldLen );
|
||||
|
||||
/* Initialize and make assumptions for header value. */
|
||||
__CPROVER_assume( valueLen < CBMC_MAX_OBJECT_SIZE );
|
||||
pValue = mallocCanFail( valueLen );
|
||||
|
||||
HTTPClient_AddHeader( pRequestHeaders,
|
||||
pField, fieldLen, pValue, valueLen );
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
#
|
||||
# Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
HARNESS_ENTRY=HTTPClient_AddHeader_harness
|
||||
PROOF_UID=HTTPClient_AddHeader
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
# We remove these function bodies so that they aren't categorized as possible
|
||||
# function pointer targets, leading to faster execution time.
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderFieldParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderValueParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnBodyCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeaderFieldCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeaderValueCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnStatusCallback
|
||||
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeadersCompleteCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnMessageBeginCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnMessageCompleteCallback
|
||||
|
||||
# These functions are removed and replace with stubs that check that the
|
||||
# destination parameter is writeable and that the source parameter is readable.
|
||||
# This decreases the run-time of the proof. This is safe to do for this proof
|
||||
# because HTTPClient_AddHeader does not use the results of the copy later in the
|
||||
# function.
|
||||
REMOVE_FUNCTION_BODY += strncpy
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpHeaderStrncpy
|
||||
|
||||
# strncmp is used to find if there exists "\r\n\r\n" at the end of the header
|
||||
# buffer. Therefore, we need to unwind strncmp the length of "\r\n\r\n" + 1.
|
||||
UNWINDSET += strncmp.0:5
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/strncpy.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/httpHeaderStrncpy.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
HTTPClient_AddHeader proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for HTTPClient_AddHeader.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "HTTPClient_AddHeader",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HTTPClient_AddRangeHeader_harness.c
|
||||
* @brief Implements the proof harness for HTTPClient_AddRangeHeader function.
|
||||
*/
|
||||
|
||||
#include "core_http_client.h"
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
|
||||
void HTTPClient_AddRangeHeader_harness()
|
||||
{
|
||||
HTTPRequestHeaders_t * pRequestHeaders;
|
||||
int32_t rangeStartOrlastNbytes;
|
||||
int32_t rangeEnd;
|
||||
|
||||
/* Initialize and make assumptions for request headers. */
|
||||
pRequestHeaders = allocateHttpRequestHeaders( NULL );
|
||||
__CPROVER_assume( isValidHttpRequestHeaders( pRequestHeaders ) );
|
||||
|
||||
HTTPClient_AddRangeHeader( pRequestHeaders, rangeStartOrlastNbytes, rangeEnd );
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
#
|
||||
# Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
HARNESS_ENTRY=HTTPClient_AddRangeHeader_harness
|
||||
PROOF_UID=HTTPClient_AddRangeHeader
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
# These functions are removed and replace with stubs that check that the
|
||||
# destination parameter is writeable and that the source parameter is readable.
|
||||
# This decreases the run-time of the proof. This is safe to do for this proof
|
||||
# because HTTPClient_AddRangeHeader does not use the results of the copy later
|
||||
# in the function.
|
||||
REMOVE_FUNCTION_BODY += strncpy
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpHeaderStrncpy
|
||||
|
||||
# strncmp is used to find if there exists "\r\n\r\n" at the end of the header
|
||||
# buffer. Therefore, we need to unwind strncmp the length of "\r\n\r\n" + 1.
|
||||
UNWINDSET += strncmp.0:5
|
||||
# Maximum value of a 32 bit signed integer is 2,147,483,647, which is 10 digits.
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.0:11
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.1:11
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/strncpy.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/httpHeaderStrncpy.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
HTTPClient_AddRangeHeader proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for HTTPClient_AddRangeHeader.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "HTTPClient_AddRangeHeader",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HTTPClient_InitializeRequestHeaders_harness.c
|
||||
* @brief Implements the proof harness for HTTPClient_InitializeRequestHeaders function.
|
||||
*/
|
||||
|
||||
#include "core_http_client.h"
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
|
||||
void HTTPClient_InitializeRequestHeaders_harness()
|
||||
{
|
||||
HTTPRequestHeaders_t * pRequestHeaders;
|
||||
HTTPRequestInfo_t * pRequestInfo;
|
||||
|
||||
/* Initialize and make assumptions for the request headers object. */
|
||||
pRequestHeaders = allocateHttpRequestHeaders( NULL );
|
||||
__CPROVER_assume( isValidHttpRequestHeaders( pRequestHeaders ) );
|
||||
|
||||
/* Initialize and make assumptions for the request info object. */
|
||||
pRequestInfo = allocateHttpRequestInfo( NULL );
|
||||
__CPROVER_assume( isValidHttpRequestInfo( pRequestInfo ) );
|
||||
|
||||
HTTPClient_InitializeRequestHeaders( pRequestHeaders, pRequestInfo );
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
#
|
||||
# Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
HARNESS_ENTRY=HTTPClient_InitializeRequestHeaders_harness
|
||||
PROOF_UID=HTTPClient_InitializeRequestHeaders
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
# We remove these function bodies so that they aren't categorized as possible
|
||||
# function pointer targets, leading to faster execution time.
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderFieldParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderValueParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnBodyCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeaderFieldCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeaderValueCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnStatusCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeadersCompleteCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnMessageBeginCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnMessageCompleteCallback
|
||||
|
||||
# These functions are removed and replace with stubs that check that the
|
||||
# destination parameter is writeable and that the source parameter is readable.
|
||||
# This decreases the run-time of the proof. This is safe to do for this proof
|
||||
# because HTTPClient_InitializeRequestHeaders does not use the results of the
|
||||
# copy later in the function.
|
||||
REMOVE_FUNCTION_BODY += strncpy
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpHeaderStrncpy
|
||||
|
||||
# strncmp is used to find if there exists "\r\n\r\n" at the end of the header
|
||||
# buffer. Therefore, we need to unwind strncmp the length of "\r\n\r\n" + 1.
|
||||
UNWINDSET += strncmp.0:5
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/strncpy.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/httpHeaderStrncpy.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
HTTPClient_InitializeRequestHeaders proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for HTTPClient_InitializeRequestHeaders.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "HTTPClient_InitializeRequestHeaders",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HTTPClient_ReadHeader_harness.c
|
||||
* @brief Implements the proof harness for HTTPClient_ReadHeader function.
|
||||
*/
|
||||
|
||||
#include "core_http_client.h"
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
|
||||
void HTTPClient_ReadHeader_harness()
|
||||
{
|
||||
HTTPResponse_t * pResponse;
|
||||
char * pField;
|
||||
char ** pValue;
|
||||
size_t fieldLen;
|
||||
size_t valueLen;
|
||||
|
||||
/* Initialize and make assumptions for header field. */
|
||||
__CPROVER_assume( fieldLen < CBMC_MAX_OBJECT_SIZE );
|
||||
pField = mallocCanFail( fieldLen );
|
||||
|
||||
/* Initialize and make assumptions for header value. */
|
||||
__CPROVER_assume( valueLen < CBMC_MAX_OBJECT_SIZE );
|
||||
pValue = mallocCanFail( sizeof( char * ) );
|
||||
|
||||
/* Initialize and make assumptions for response object. */
|
||||
pResponse = allocateHttpResponse( NULL );
|
||||
__CPROVER_assume( isValidHttpResponse( pResponse ) );
|
||||
|
||||
HTTPClient_ReadHeader( pResponse,
|
||||
pField,
|
||||
fieldLen,
|
||||
pValue,
|
||||
valueLen );
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
HARNESS_ENTRY=HTTPClient_ReadHeader_harness
|
||||
PROOF_UID=HTTPClient_ReadHeader
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
# The memory safety of the http-parser callbacks are proven separately.
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderFieldParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderValueParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderOnHeaderCompleteCallback
|
||||
|
||||
# Remove any unused functions for http parser
|
||||
REMOVE_FUNCTION_BODY += llhttp_init
|
||||
REMOVE_FUNCTION_BODY += llhttp_settings_init
|
||||
|
||||
UNWINDSET +=
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/HTTPClient_ReadHeader_llhttp_execute.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
HTTPClient_ReadHeader proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for HTTPClient_ReadHeader.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "HTTPClient_ReadHeader",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HTTPClient_Send_harness.c
|
||||
* @brief Implements the proof harness for HTTPClient_Send function.
|
||||
*/
|
||||
|
||||
#include "core_http_client.h"
|
||||
#include "http_cbmc_state.h"
|
||||
#include "transport_interface_stubs.h"
|
||||
#include "get_time_stub.h"
|
||||
|
||||
void HTTPClient_Send_harness()
|
||||
{
|
||||
HTTPRequestHeaders_t * pRequestHeaders;
|
||||
HTTPResponse_t * pResponse;
|
||||
TransportInterface_t * pTransportInterface;
|
||||
uint8_t * pRequestBodyBuf;
|
||||
size_t reqBodyBufLen;
|
||||
uint32_t sendFlags;
|
||||
|
||||
/* Initialize and make assumptions for request headers. */
|
||||
pRequestHeaders = allocateHttpRequestHeaders( NULL );
|
||||
__CPROVER_assume( isValidHttpRequestHeaders( pRequestHeaders ) );
|
||||
|
||||
/* Initialize and make assumptions for buffer to receive request body. */
|
||||
__CPROVER_assume( reqBodyBufLen < CBMC_MAX_OBJECT_SIZE );
|
||||
pRequestBodyBuf = mallocCanFail( reqBodyBufLen );
|
||||
|
||||
/* Initialize and make assumptions for response object. */
|
||||
pResponse = allocateHttpResponse( NULL );
|
||||
__CPROVER_assume( isValidHttpResponse( pResponse ) );
|
||||
|
||||
/* Initialize transport interface. */
|
||||
pTransportInterface = allocateTransportInterface( NULL );
|
||||
|
||||
if( pTransportInterface != NULL )
|
||||
{
|
||||
/* Ideally, we want to set the function pointers below with __CPROVER_assume()
|
||||
* but doing so makes CBMC run out of memory. */
|
||||
pTransportInterface->send = nondet_bool() ? NULL : TransportInterfaceSendStub;
|
||||
pTransportInterface->recv = nondet_bool() ? NULL : TransportInterfaceReceiveStub;
|
||||
}
|
||||
|
||||
if( pResponse != NULL )
|
||||
{
|
||||
pResponse->getTime = nondet_boot() ? NULL : GetCurrentTimeStub;
|
||||
}
|
||||
|
||||
HTTPClient_Send( pTransportInterface,
|
||||
pRequestHeaders,
|
||||
pRequestBodyBuf,
|
||||
reqBodyBufLen,
|
||||
pResponse,
|
||||
sendFlags );
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
#
|
||||
# Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
HARNESS_ENTRY=HTTPClient_Send_harness
|
||||
PROOF_UID=HTTPClient_Send
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
# We remove these function bodies so that they aren't categorized as possible
|
||||
# function pointer targets, leading to faster execution time.
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderFieldParserCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_findHeaderValueParserCallback
|
||||
# The memory safety of the http-parser callbacks are proven separately. The
|
||||
# proofs for the functions below must have assumptions that are satisfied by the
|
||||
# calling context in HTTPClient_Send.
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnBodyCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeaderFieldCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeaderValueCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnStatusCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnHeadersCompleteCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnMessageBeginCallback
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpParserOnMessageCompleteCallback
|
||||
|
||||
# Remove any unused functions for http parser
|
||||
REMOVE_FUNCTION_BODY += llhttp_init
|
||||
REMOVE_FUNCTION_BODY += llhttp_settings_init
|
||||
|
||||
# These functions are removed and replace with stubs that check that the
|
||||
# destination parameter is writeable and that the source parameter is readable.
|
||||
# This decreases the run-time of the proof. This is safe to do for this proof
|
||||
# because all of the functions, in HTTPClient_Send, that would have used the
|
||||
# results of the copy are stubbed out to be proven separately.
|
||||
REMOVE_FUNCTION_BODY += strncpy
|
||||
REMOVE_FUNCTION_BODY += __CPROVER_file_local_core_http_client_c_httpHeaderStrncpy
|
||||
|
||||
# There is a total of 10 digits in INT32_MAX. These loops are unwound once more
|
||||
# than the total possible iterations in the int32_t to ASCII converation.
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.0:11
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_convertInt32ToAscii.1:11
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_receiveAndParseHttpResponse.0:10
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_sendHttpData.0:10
|
||||
|
||||
# strncmp is used to find if there exists "\r\n\r\n" at the end of the header
|
||||
# buffer. Therefore, we need to unwind strncmp to the length of "\r\n\r\n" + 1.
|
||||
UNWINDSET += strncmp.0:5
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/HTTPClient_Send_llhttp_execute.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/transport_interface_stubs.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/get_time_stub.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/strncpy.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/httpHeaderStrncpy.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
HTTPClient_Send proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for HTTPClient_Send.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path
|
||||
* Run "make"
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "HTTPClient_Send",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file HTTPClient_strerror_harness.c
|
||||
* @brief Implements the proof harness for HTTPClient_strerror function.
|
||||
*/
|
||||
|
||||
#include "core_http_client.h"
|
||||
|
||||
void HTTPClient_strerror_harness()
|
||||
{
|
||||
HTTPStatus_t status;
|
||||
|
||||
HTTPClient_strerror( status );
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal in
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
HARNESS_ENTRY=HTTPClient_strerror_harness
|
||||
PROOF_UID=HTTPClient_strerror
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
REMOVE_FUNCTION_BODY +=
|
||||
UNWINDSET +=
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
HTTPClient_strerror proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for HTTPClient_strerror.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "HTTPClient_strerror",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
# -*- mode: makefile -*-
|
||||
# The first line sets the emacs major mode to Makefile
|
||||
|
||||
################################################################
|
||||
# Use this file to give project-specific definitions of the command
|
||||
# line arguments to pass to CBMC tools like goto-cc to build the goto
|
||||
# binaries and cbmc to do the property and coverage checking.
|
||||
#
|
||||
# Use this file to override most default definitions of variables in
|
||||
# Makefile.common.
|
||||
################################################################
|
||||
|
||||
# Flags to pass to goto-cc for compilation (typically those passed to gcc -c)
|
||||
COMPILE_FLAGS += -fPIC
|
||||
COMPILE_FLAGS += -std=gnu90
|
||||
|
||||
# Path to litani executable, used for running proofs and displaying report
|
||||
LITANI ?= litani
|
||||
PROJECT_NAME = "FreeRTOS coreHTTP"
|
||||
|
||||
# Flags to pass to goto-cc for linking (typically those passed to gcc)
|
||||
# LINK_FLAGS =
|
||||
|
||||
# Preprocessor include paths -I...
|
||||
INCLUDES += -I$(SRCDIR)/test/cbmc/include
|
||||
INCLUDES += -I$(SRCDIR)/source/include
|
||||
INCLUDES += -I$(SRCDIR)/source/interface
|
||||
INCLUDES += -I$(SRCDIR)/source
|
||||
INCLUDES += -I$(SRCDIR)/source/dependency/3rdparty/llhttp/include
|
||||
|
||||
# Preprocessor definitions -D...
|
||||
DEFINES += -Dhttp_EXPORTS
|
||||
|
||||
# Ensure that all assumptions are sound by checking that "all pointers
|
||||
# in pointer primitives are valid or null"
|
||||
CHECKFLAGS += --pointer-primitive-check
|
||||
@ -0,0 +1,10 @@
|
||||
# -*- mode: makefile -*-
|
||||
# The first line sets the emacs major mode to Makefile
|
||||
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
################################################################
|
||||
# Use this file to give project-specific targets, including targets
|
||||
# that may depend on targets defined in Makefile.common.
|
||||
################################################################
|
||||
@ -0,0 +1,11 @@
|
||||
# -*- mode: makefile -*-
|
||||
# The first line sets the emacs major mode to Makefile
|
||||
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
################################################################
|
||||
# Use this file to define project-specific targets and definitions for
|
||||
# unit testing or continuous integration that may depend on targets
|
||||
# defined in Makefile.common
|
||||
################################################################
|
||||
@ -0,0 +1 @@
|
||||
SRCDIR ?= $(abspath $(PROOF_ROOT)/../../..)
|
||||
@ -0,0 +1,999 @@
|
||||
# -*- mode: makefile -*-
|
||||
# The first line sets the emacs major mode to Makefile
|
||||
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
CBMC_STARTER_KIT_VERSION = CBMC starter kit 2.5
|
||||
|
||||
################################################################
|
||||
# The CBMC Starter Kit depends on the files Makefile.common and
|
||||
# run-cbmc-proofs.py. They are installed by the setup script
|
||||
# cbmc-starter-kit-setup and updated to the latest version by the
|
||||
# update script cbmc-starter-kit-update. For more information about
|
||||
# the starter kit and these files and these scripts, see
|
||||
# https://model-checking.github.io/cbmc-starter-kit
|
||||
#
|
||||
# Makefile.common implements what we consider to be some best
|
||||
# practices for using cbmc for software verification.
|
||||
#
|
||||
# Section I gives default values for a large number of Makefile
|
||||
# variables that control
|
||||
# * how your code is built (include paths, etc),
|
||||
# * what program transformations are applied to your code (loop
|
||||
# unwinding, etc), and
|
||||
# * what properties cbmc checks for in your code (memory safety, etc).
|
||||
#
|
||||
# These variables are defined below with definitions of the form
|
||||
# VARIABLE ?= DEFAULT_VALUE
|
||||
# meaning VARIABLE is set to DEFAULT_VALUE if VARIABLE has not already
|
||||
# been given a value.
|
||||
#
|
||||
# For your project, you can override these default values with
|
||||
# project-specific definitions in Makefile-project-defines.
|
||||
#
|
||||
# For any individual proof, you can override these default values and
|
||||
# project-specific values with proof-specific definitions in the
|
||||
# Makefile for your proof.
|
||||
#
|
||||
# The definitions in the proof Makefile override definitions in the
|
||||
# project Makefile-project-defines which override definitions in this
|
||||
# Makefile.common.
|
||||
#
|
||||
# Section II uses the values defined in Section I to build your code, run
|
||||
# your proof, and build a report of your results. You should not need
|
||||
# to modify or override anything in Section II, but you may want to
|
||||
# read it to understand how the values defined in Section I control
|
||||
# things.
|
||||
#
|
||||
# To use Makefile.common, set variables as described above as needed,
|
||||
# and then for each proof,
|
||||
#
|
||||
# * Create a subdirectory <DIR>.
|
||||
# * Write a proof harness (a function) with the name <HARNESS_ENTRY>
|
||||
# in a file with the name <DIR>/<HARNESS_FILE>.c
|
||||
# * Write a makefile with the name <DIR>/Makefile that looks
|
||||
# something like
|
||||
#
|
||||
# HARNESS_FILE=<HARNESS_FILE>
|
||||
# HARNESS_ENTRY=<HARNESS_ENTRY>
|
||||
# PROOF_UID=<PROOF_UID>
|
||||
#
|
||||
# PROJECT_SOURCES += $(SRCDIR)/libraries/api_1.c
|
||||
# PROJECT_SOURCES += $(SRCDIR)/libraries/api_2.c
|
||||
#
|
||||
# PROOF_SOURCES += $(PROOFDIR)/harness.c
|
||||
# PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_a.c
|
||||
# PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_b.c
|
||||
#
|
||||
# UNWINDSET += foo.0:3
|
||||
# UNWINDSET += bar.1:6
|
||||
#
|
||||
# REMOVE_FUNCTION_BODY += api_stub_a
|
||||
# REMOVE_FUNCTION_BODY += api_stub_b
|
||||
#
|
||||
# DEFINES = -DDEBUG=0
|
||||
#
|
||||
# include ../Makefile.common
|
||||
#
|
||||
# * Change directory to <DIR> and run make
|
||||
#
|
||||
# The proof setup script cbmc-starter-kit-setup-proof from the CBMC
|
||||
# Starter Kit will do most of this for, creating a directory and
|
||||
# writing a basic Makefile and proof harness into it that you can edit
|
||||
# as described above.
|
||||
#
|
||||
# Warning: If you get results that are hard to explain, consider
|
||||
# running "make clean" or "make veryclean" before "make" if you get
|
||||
# results that are hard to explain. Dependency handling in this
|
||||
# Makefile.common may not be perfect.
|
||||
|
||||
SHELL=/bin/bash
|
||||
|
||||
default: report
|
||||
|
||||
################################################################
|
||||
################################################################
|
||||
## Section I: This section gives common variable definitions.
|
||||
##
|
||||
## Override these definitions in Makefile-project-defines or
|
||||
## your proof Makefile.
|
||||
##
|
||||
## Remember that Makefile.common and Makefile-project-defines are
|
||||
## included into the proof Makefile in your proof directory, so all
|
||||
## relative pathnames defined there should be relative to your proof
|
||||
## directory.
|
||||
|
||||
################################################################
|
||||
# Define the layout of the source tree and the proof subtree
|
||||
#
|
||||
# Generally speaking,
|
||||
#
|
||||
# SRCDIR = the root of the repository
|
||||
# CBMC_ROOT = /srcdir/cbmc
|
||||
# PROOF_ROOT = /srcdir/cbmc/proofs
|
||||
# PROOF_SOURCE = /srcdir/cbmc/sources
|
||||
# PROOF_INCLUDE = /srcdir/cbmc/include
|
||||
# PROOF_STUB = /srcdir/cbmc/stubs
|
||||
# PROOFDIR = the directory containing the Makefile for your proof
|
||||
#
|
||||
# The path /srcdir/cbmc used in the example above is determined by the
|
||||
# setup script cbmc-starter-kit-setup. Projects usually create a cbmc
|
||||
# directory somewhere in the source tree, and run the setup script in
|
||||
# that directory. The value of CBMC_ROOT becomes the absolute path to
|
||||
# that directory.
|
||||
#
|
||||
# The location of that cbmc directory in the source tree affects the
|
||||
# definition of SRCDIR, which is defined in terms of the relative path
|
||||
# from a proof directory to the repository root. The definition is
|
||||
# usually determined by the setup script cbmc-starter-kit-setup and
|
||||
# written to Makefile-template-defines, but you can override it for a
|
||||
# project in Makefile-project-defines and for a specific proof in the
|
||||
# Makefile for the proof.
|
||||
|
||||
# Absolute path to the directory containing this Makefile.common
|
||||
# See https://ftp.gnu.org/old-gnu/Manuals/make-3.80/html_node/make_17.html
|
||||
#
|
||||
# Note: We compute the absolute paths to the makefiles in MAKEFILE_LIST
|
||||
# before we filter the list of makefiles for %/Makefile.common.
|
||||
# Otherwise an invocation of the form "make -f Makefile.common" will set
|
||||
# MAKEFILE_LIST to "Makefile.common" which will fail to match the
|
||||
# pattern %/Makefile.common.
|
||||
#
|
||||
MAKEFILE_PATHS = $(foreach makefile,$(MAKEFILE_LIST),$(abspath $(makefile)))
|
||||
PROOF_ROOT = $(dir $(filter %/Makefile.common,$(MAKEFILE_PATHS)))
|
||||
|
||||
CBMC_ROOT = $(shell dirname $(PROOF_ROOT))
|
||||
PROOF_SOURCE = $(CBMC_ROOT)/sources
|
||||
PROOF_INCLUDE = $(CBMC_ROOT)/include
|
||||
PROOF_STUB = $(CBMC_ROOT)/stubs
|
||||
|
||||
# Project-specific definitions to override default definitions below
|
||||
# * Makefile-project-defines will never be overwritten
|
||||
# * Makefile-template-defines may be overwritten when the starter
|
||||
# kit is updated
|
||||
sinclude $(PROOF_ROOT)/Makefile-project-defines
|
||||
sinclude $(PROOF_ROOT)/Makefile-template-defines
|
||||
|
||||
# SRCDIR is the path to the root of the source tree
|
||||
# This is a default definition that is frequently overridden in
|
||||
# another Makefile, see the discussion of SRCDIR above.
|
||||
SRCDIR ?= $(abspath ../..)
|
||||
|
||||
# PROOFDIR is the path to the directory containing the proof harness
|
||||
PROOFDIR ?= $(abspath .)
|
||||
|
||||
################################################################
|
||||
# Define how to run CBMC
|
||||
|
||||
# Do property checking with the external SAT solver given by
|
||||
# EXTERNAL_SAT_SOLVER. Do coverage checking with the default solver,
|
||||
# since coverage checking requires the use of an incremental solver.
|
||||
# The EXTERNAL_SAT_SOLVER variable is typically set (if it is at all)
|
||||
# as an environment variable or as a makefile variable in
|
||||
# Makefile-project-defines.
|
||||
#
|
||||
# For a particular proof, if the default solver is faster, do property
|
||||
# checking with the default solver by including this definition in the
|
||||
# proof Makefile:
|
||||
# USE_EXTERNAL_SAT_SOLVER =
|
||||
#
|
||||
ifneq ($(strip $(EXTERNAL_SAT_SOLVER)),)
|
||||
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver $(EXTERNAL_SAT_SOLVER)
|
||||
endif
|
||||
CHECKFLAGS += $(USE_EXTERNAL_SAT_SOLVER)
|
||||
|
||||
# Job pools
|
||||
# For version of Litani that are new enough (where `litani print-capabilities`
|
||||
# prints "pools"), proofs for which `EXPENSIVE = true` is set can be added to a
|
||||
# "job pool" that restricts how many expensive proofs are run at a time. All
|
||||
# other proofs will be built in parallel as usual.
|
||||
#
|
||||
# In more detail: all compilation, instrumentation, and report jobs are run with
|
||||
# full parallelism as usual, even for expensive proofs. The CBMC jobs for
|
||||
# non-expensive proofs are also run in parallel. The only difference is that the
|
||||
# CBMC safety checks and coverage checks for expensive proofs are run with a
|
||||
# restricted parallelism level. At any one time, only N of these jobs are run at
|
||||
# once, amongst all the proofs.
|
||||
#
|
||||
# To configure N, Litani needs to be initialized with a pool called "expensive".
|
||||
# For example, to only run two CBMC safety/coverage jobs at a time from amongst
|
||||
# all the proofs, you would initialize litani like
|
||||
# litani init --pools expensive:2
|
||||
# The run-cbmc-proofs.py script takes care of this initialization through the
|
||||
# --expensive-jobs-parallelism flag.
|
||||
#
|
||||
# To enable this feature, set
|
||||
# the ENABLE_POOLS variable when running Make, like
|
||||
# `make ENABLE_POOLS=true report`
|
||||
# The run-cbmc-proofs.py script takes care of this through the
|
||||
# --restrict-expensive-jobs flag.
|
||||
|
||||
ifeq ($(strip $(ENABLE_POOLS)),)
|
||||
POOL =
|
||||
else ifeq ($(strip $(EXPENSIVE)),)
|
||||
POOL =
|
||||
else
|
||||
POOL = --pool expensive
|
||||
endif
|
||||
|
||||
# Similar to the pool feature above. If Litani is new enough, enable
|
||||
# profiling CBMC's memory use.
|
||||
ifeq ($(strip $(ENABLE_MEMORY_PROFILING)),)
|
||||
MEMORY_PROFILING =
|
||||
else
|
||||
MEMORY_PROFILING = --profile-memory
|
||||
endif
|
||||
|
||||
# Property checking flags
|
||||
#
|
||||
# Each variable below controls a specific property checking flag
|
||||
# within CBMC. If desired, a property flag can be disabled within
|
||||
# a particular proof by nulling the corresponding variable. For
|
||||
# instance, the following line:
|
||||
#
|
||||
# CHECK_FLAG_POINTER_CHECK =
|
||||
#
|
||||
# would disable the --pointer-check CBMC flag within:
|
||||
# * an entire project when added to Makefile-project-defines
|
||||
# * a specific proof when added to the harness Makefile
|
||||
|
||||
CBMC_FLAG_MALLOC_MAY_FAIL ?= --malloc-may-fail
|
||||
CBMC_FLAG_MALLOC_FAIL_NULL ?= --malloc-fail-null
|
||||
CBMC_FLAG_BOUNDS_CHECK ?= --bounds-check
|
||||
CBMC_FLAG_CONVERSION_CHECK ?= --conversion-check
|
||||
CBMC_FLAG_DIV_BY_ZERO_CHECK ?= --div-by-zero-check
|
||||
CBMC_FLAG_FLOAT_OVERFLOW_CHECK ?= --float-overflow-check
|
||||
CBMC_FLAG_NAN_CHECK ?= --nan-check
|
||||
CBMC_FLAG_POINTER_CHECK ?= --pointer-check
|
||||
CBMC_FLAG_POINTER_OVERFLOW_CHECK ?= --pointer-overflow-check
|
||||
CBMC_FLAG_POINTER_PRIMITIVE_CHECK ?= --pointer-primitive-check
|
||||
CBMC_FLAG_SIGNED_OVERFLOW_CHECK ?= --signed-overflow-check
|
||||
CBMC_FLAG_UNDEFINED_SHIFT_CHECK ?= --undefined-shift-check
|
||||
CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK ?= --unsigned-overflow-check
|
||||
CBMC_FLAG_UNWINDING_ASSERTIONS ?= --unwinding-assertions
|
||||
CBMC_FLAG_UNWIND ?= --unwind 1
|
||||
CBMC_FLAG_FLUSH ?= --flush
|
||||
|
||||
# CBMC flags used for property checking and coverage checking
|
||||
|
||||
CBMCFLAGS += $(CBMC_FLAG_UNWIND) $(CBMC_UNWINDSET) $(CBMC_FLAG_FLUSH)
|
||||
|
||||
# CBMC flags used for property checking
|
||||
|
||||
CHECKFLAGS += $(CBMC_FLAG_MALLOC_MAY_FAIL)
|
||||
CHECKFLAGS += $(CBMC_FLAG_MALLOC_FAIL_NULL)
|
||||
CHECKFLAGS += $(CBMC_FLAG_BOUNDS_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_CONVERSION_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_DIV_BY_ZERO_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_FLOAT_OVERFLOW_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_NAN_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_POINTER_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_POINTER_OVERFLOW_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_POINTER_PRIMITIVE_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_SIGNED_OVERFLOW_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_UNDEFINED_SHIFT_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK)
|
||||
CHECKFLAGS += $(CBMC_FLAG_UNWINDING_ASSERTIONS)
|
||||
|
||||
# CBMC flags used for coverage checking
|
||||
|
||||
COVERFLAGS += $(CBMC_FLAG_MALLOC_MAY_FAIL)
|
||||
COVERFLAGS += $(CBMC_FLAG_MALLOC_FAIL_NULL)
|
||||
|
||||
# Additional CBMC flag to CBMC control verbosity.
|
||||
#
|
||||
# Meaningful values are
|
||||
# 0 none
|
||||
# 1 only errors
|
||||
# 2 + warnings
|
||||
# 4 + results
|
||||
# 6 + status/phase information
|
||||
# 8 + statistical information
|
||||
# 9 + progress information
|
||||
# 10 + debug info
|
||||
#
|
||||
# Uncomment the following line or set in Makefile-project-defines
|
||||
# CBMC_VERBOSITY ?= --verbosity 4
|
||||
|
||||
# Additional CBMC flag to control how CBMC treats static variables.
|
||||
#
|
||||
# NONDET_STATIC is a list of flags of the form --nondet-static
|
||||
# and --nondet-static-exclude VAR. The --nondet-static flag causes
|
||||
# CBMC to initialize static variables with unconstrained value
|
||||
# (ignoring initializers and default zero-initialization). The
|
||||
# --nondet-static-exclude VAR excludes VAR for the variables
|
||||
# initialized with unconstrained values.
|
||||
NONDET_STATIC ?=
|
||||
|
||||
# Flags to pass to goto-cc for compilation and linking
|
||||
COMPILE_FLAGS ?= -Wall
|
||||
LINK_FLAGS ?= -Wall
|
||||
EXPORT_FILE_LOCAL_SYMBOLS ?= --export-file-local-symbols
|
||||
|
||||
# Preprocessor include paths -I...
|
||||
INCLUDES ?=
|
||||
|
||||
# Preprocessor definitions -D...
|
||||
DEFINES ?=
|
||||
|
||||
# CBMC object model
|
||||
#
|
||||
# CBMC_OBJECT_BITS is the number of bits in a pointer CBMC uses for
|
||||
# the id of the object to which a pointer is pointing. CBMC uses 8
|
||||
# bits for the object id by default. The remaining bits in the pointer
|
||||
# are used for offset into the object. This limits the size of the
|
||||
# objects that CBMC can model. This Makefile defines this bound on
|
||||
# object size to be CBMC_MAX_OBJECT_SIZE. You are likely to get
|
||||
# unexpected results if you try to malloc an object larger than this
|
||||
# bound.
|
||||
CBMC_OBJECT_BITS ?= 8
|
||||
|
||||
# CBMC loop unwinding (Normally set in the proof Makefile)
|
||||
#
|
||||
# UNWINDSET is a list of pairs of the form foo.1:4 meaning that
|
||||
# CBMC should unwind loop 1 in function foo no more than 4 times.
|
||||
# For historical reasons, the number 4 is one more than the number
|
||||
# of times CBMC actually unwinds the loop.
|
||||
UNWINDSET ?=
|
||||
|
||||
# CBMC early loop unwinding (Normally set in the proof Makefile)
|
||||
#
|
||||
# Most users can ignore this variable.
|
||||
#
|
||||
# This variable exists to support the use of loop and function
|
||||
# contracts, two features under development for CBMC. Checking the
|
||||
# assigns clause for function contracts and loop invariants currently
|
||||
# assumes loop-free bodies for loops and functions with contracts
|
||||
# (possibly after replacing nested loops with their own loop
|
||||
# contracts). To satisfy this requirement, it may be necessary to
|
||||
# unwind some loops before the function contract and loop invariant
|
||||
# transformations are applied to the goto program. This variable
|
||||
# EARLY_UNWINDSET is identical to UNWINDSET, and we assume that the
|
||||
# loops mentioned in EARLY_UNWINDSET and UNWINDSET are disjoint.
|
||||
EARLY_UNWINDSET ?=
|
||||
|
||||
# CBMC function removal (Normally set set in the proof Makefile)
|
||||
#
|
||||
# REMOVE_FUNCTION_BODY is a list of function names. CBMC will "undefine"
|
||||
# the function, and CBMC will treat the function as having no side effects
|
||||
# and returning an unconstrained value of the appropriate return type.
|
||||
# The list should include the names of functions being stubbed out.
|
||||
REMOVE_FUNCTION_BODY ?=
|
||||
|
||||
# CBMC function pointer restriction (Normally set in the proof Makefile)
|
||||
#
|
||||
# RESTRICT_FUNCTION_POINTER is a list of function pointer restriction
|
||||
# instructions of the form:
|
||||
#
|
||||
# <fun_id>.function_pointer_call.<N>/<fun_id>[,<fun_id>]*
|
||||
#
|
||||
# The function pointer call number <N> in the specified function gets
|
||||
# rewritten to a case switch over a finite list of functions.
|
||||
# If some possible target functions are omitted from the list a counter
|
||||
# example trace will be found by CBMC, i.e. the transformation is sound.
|
||||
# If the target functions are file-local symbols, then mangled names must
|
||||
# be used.
|
||||
RESTRICT_FUNCTION_POINTER ?=
|
||||
|
||||
# The project source files (Normally set set in the proof Makefile)
|
||||
#
|
||||
# PROJECT_SOURCES is the list of project source files to compile,
|
||||
# including the source file defining the function under test.
|
||||
PROJECT_SOURCES ?=
|
||||
|
||||
# The proof source files (Normally set in the proof Makefile)
|
||||
#
|
||||
# PROOF_SOURCES is the list of proof source files to compile, including
|
||||
# the proof harness, and including any function stubs being used.
|
||||
PROOF_SOURCES ?=
|
||||
|
||||
# The number of seconds that CBMC should be allowed to run for before
|
||||
# being forcefully terminated. Currently, this is set to be less than
|
||||
# the time limit for a CodeBuild job, which is eight hours. If a proof
|
||||
# run takes longer than the time limit of the CI environment, the
|
||||
# environment will halt the proof run without updating the Litani
|
||||
# report, making the proof run appear to "hang".
|
||||
CBMC_TIMEOUT ?= 21600
|
||||
|
||||
# Proof writers could add function contracts in their source code.
|
||||
# These contracts are ignored by default, but may be enabled in two distinct
|
||||
# contexts using the following two variables:
|
||||
# 1. To check whether one or more function contracts are sound with respect to
|
||||
# the function implementation, CHECK_FUNCTION_CONTRACTS should be a list of
|
||||
# function names.
|
||||
# 2. To replace calls to certain functions with their correspondent function
|
||||
# contracts, USE_FUNCTION_CONTRACTS should be a list of function names.
|
||||
# One must check separately whether a function contract is sound before
|
||||
# replacing it in calling contexts.
|
||||
CHECK_FUNCTION_CONTRACTS ?=
|
||||
CBMC_CHECK_FUNCTION_CONTRACTS := $(patsubst %,--enforce-contract %, $(CHECK_FUNCTION_CONTRACTS))
|
||||
|
||||
USE_FUNCTION_CONTRACTS ?=
|
||||
CBMC_USE_FUNCTION_CONTRACTS := $(patsubst %,--replace-call-with-contract %, $(USE_FUNCTION_CONTRACTS))
|
||||
|
||||
# Similarly, proof writers could also add loop contracts in their source code
|
||||
# to obtain unbounded correctness proofs. Unlike function contracts, loop
|
||||
# contracts are not reusable and thus are checked and used simultaneously.
|
||||
# These contracts are also ignored by default, but may be enabled by setting
|
||||
# the APPLY_LOOP_CONTRACTS variable to 1.
|
||||
APPLY_LOOP_CONTRACTS ?= 0
|
||||
ifeq ($(APPLY_LOOP_CONTRACTS),1)
|
||||
CBMC_APPLY_LOOP_CONTRACTS ?= --apply-loop-contracts
|
||||
endif
|
||||
|
||||
# Silence makefile output (eg, long litani commands) unless VERBOSE is set.
|
||||
ifndef VERBOSE
|
||||
MAKEFLAGS := $(MAKEFLAGS) -s
|
||||
endif
|
||||
|
||||
################################################################
|
||||
################################################################
|
||||
## Section II: This section defines the process of running a proof
|
||||
##
|
||||
## There should be no reason to edit anything below this line.
|
||||
|
||||
################################################################
|
||||
# Paths
|
||||
|
||||
CBMC ?= cbmc
|
||||
GOTO_ANALYZER ?= goto-analyzer
|
||||
GOTO_CC ?= goto-cc
|
||||
GOTO_INSTRUMENT ?= goto-instrument
|
||||
CRANGLER ?= crangler
|
||||
VIEWER ?= cbmc-viewer
|
||||
MAKE_SOURCE ?= make-source
|
||||
VIEWER2 ?= cbmc-viewer
|
||||
CMAKE ?= cmake
|
||||
|
||||
GOTODIR ?= $(PROOFDIR)/gotos
|
||||
LOGDIR ?= $(PROOFDIR)/logs
|
||||
|
||||
PROJECT ?= project
|
||||
PROOF ?= proof
|
||||
|
||||
HARNESS_GOTO ?= $(GOTODIR)/$(HARNESS_FILE)
|
||||
PROJECT_GOTO ?= $(GOTODIR)/$(PROJECT)
|
||||
PROOF_GOTO ?= $(GOTODIR)/$(PROOF)
|
||||
|
||||
################################################################
|
||||
# Useful macros for values that are hard to reference
|
||||
SPACE :=$() $()
|
||||
COMMA :=,
|
||||
|
||||
################################################################
|
||||
# Set C compiler defines
|
||||
|
||||
CBMCFLAGS += --object-bits $(CBMC_OBJECT_BITS)
|
||||
COMPILE_FLAGS += --object-bits $(CBMC_OBJECT_BITS)
|
||||
|
||||
DEFINES += -DCBMC=1
|
||||
DEFINES += -DCBMC_OBJECT_BITS=$(CBMC_OBJECT_BITS)
|
||||
DEFINES += -DCBMC_MAX_OBJECT_SIZE="(SIZE_MAX>>(CBMC_OBJECT_BITS+1))"
|
||||
|
||||
# CI currently assumes cbmc invocation has at most one --unwindset
|
||||
ifdef UNWINDSET
|
||||
ifneq ($(strip $(UNWINDSET)),"")
|
||||
CBMC_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(UNWINDSET)))
|
||||
endif
|
||||
endif
|
||||
ifdef EARLY_UNWINDSET
|
||||
ifneq ($(strip $(EARLY_UNWINDSET)),"")
|
||||
CBMC_EARLY_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(EARLY_UNWINDSET)))
|
||||
endif
|
||||
endif
|
||||
|
||||
CBMC_REMOVE_FUNCTION_BODY := $(patsubst %,--remove-function-body %, $(REMOVE_FUNCTION_BODY))
|
||||
CBMC_RESTRICT_FUNCTION_POINTER := $(patsubst %,--restrict-function-pointer %, $(RESTRICT_FUNCTION_POINTER))
|
||||
|
||||
################################################################
|
||||
# Targets for rewriting source files with crangler
|
||||
|
||||
# Construct crangler configuration files
|
||||
#
|
||||
# REWRITTEN_SOURCES is a list of crangler output files source.i.
|
||||
# This target assumes that for each source.i
|
||||
# * source.i_SOURCE is the path to a source file,
|
||||
# * source.i_FUNCTIONS is a list of functions (may be empty)
|
||||
# * source.i_OBJECTS is a list of variables (may be empty)
|
||||
# This target constructs the crangler configuration file source.i.json
|
||||
# of the form
|
||||
# {
|
||||
# "sources": [ "/proj/code.c" ],
|
||||
# "includes": [ "/proj/include" ],
|
||||
# "defines": [ "VAR=1" ],
|
||||
# "functions": [ {"function_name": ["remove static"]} ],
|
||||
# "objects": [ {"variable_name": ["remove static"]} ],
|
||||
# "output": "source.i"
|
||||
# }
|
||||
# to remove the static attribute from function_name and variable_name
|
||||
# in the source file source.c and write the result to source.i.
|
||||
#
|
||||
# This target assumes that filenames include no spaces and that
|
||||
# the INCLUDES and DEFINES variables include no spaces after -I
|
||||
# and -D. For example, use "-DVAR=1" and not "-D VAR=1".
|
||||
#
|
||||
# Define *_SOURCE, *_FUNCTIONS, and *_OBJECTS in the proof Makefile.
|
||||
# The string source.i is usually an absolute path $(PROOFDIR)/code.i
|
||||
# to a file in the proof directory that contains the proof Makefile.
|
||||
# The proof Makefile usually includes the definitions
|
||||
# $(PROOFDIR)/code.i_SOURCE = /proj/code.c
|
||||
# $(PROOFDIR)/code.i_FUNCTIONS = function_name
|
||||
# $(PROOFDIR)/code.i_OBJECTS = variable_name
|
||||
# Because these definitions refer to PROOFDIR that is defined in this
|
||||
# Makefile.common, these definitions must appear after the inclusion
|
||||
# of Makefile.common in the proof Makefile.
|
||||
#
|
||||
$(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs).json: $($(rs)_SOURCE)))
|
||||
$(foreach rs,$(REWRITTEN_SOURCES),$(rs).json):
|
||||
echo '{'\
|
||||
'"sources": ['\
|
||||
'"$($(@:.json=)_SOURCE)"'\
|
||||
'],'\
|
||||
'"includes": ['\
|
||||
'$(subst $(SPACE),$(COMMA),$(patsubst -I%,"%",$(strip $(INCLUDES))))' \
|
||||
'],'\
|
||||
'"defines": ['\
|
||||
'$(subst $(SPACE),$(COMMA),$(patsubst -D%,"%",$(subst ",\",$(strip $(DEFINES)))))' \
|
||||
'],'\
|
||||
'"functions": ['\
|
||||
'{'\
|
||||
'$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_FUNCTIONS))))' \
|
||||
'}'\
|
||||
'],'\
|
||||
'"objects": ['\
|
||||
'{'\
|
||||
'$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_OBJECTS))))' \
|
||||
'}'\
|
||||
'],'\
|
||||
'"output": "$(@:.json=)"'\
|
||||
'}' > $@
|
||||
|
||||
# Rewrite source files with crangler
|
||||
#
|
||||
$(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs): $(rs).json))
|
||||
$(REWRITTEN_SOURCES):
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(CRANGLER) $@.json' \
|
||||
--inputs $($@_SOURCE) \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/crangler-$(subst /,_,$(subst .,_,$@))-log.txt \
|
||||
--interleave-stdout-stderr \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): removing static"
|
||||
|
||||
################################################################
|
||||
# Build targets that make the relevant .goto files
|
||||
|
||||
# Compile project sources
|
||||
$(PROJECT_GOTO)1.goto: $(PROJECT_SOURCES) $(REWRITTEN_SOURCES)
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/project_sources-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): building project binary"
|
||||
|
||||
# Compile proof sources
|
||||
$(PROOF_GOTO)1.goto: $(PROOF_SOURCES)
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/proof_sources-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): building proof binary"
|
||||
|
||||
# Remove function bodies from project sources
|
||||
$(PROJECT_GOTO)2.goto: $(PROJECT_GOTO)1.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_REMOVE_FUNCTION_BODY) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/remove_function_body-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): removing function bodies from project sources"
|
||||
|
||||
# Link project and proof sources into the proof harness
|
||||
$(HARNESS_GOTO)1.goto: $(PROOF_GOTO)1.goto $(PROJECT_GOTO)2.goto
|
||||
$(LITANI) add-job \
|
||||
--command '$(GOTO_CC) $(CBMC_VERBOSITY) --function $(HARNESS_ENTRY) $^ $(LINK_FLAGS) -o $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/link_proof_project-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): linking project to proof"
|
||||
|
||||
# Restrict function pointers
|
||||
$(HARNESS_GOTO)2.goto: $(HARNESS_GOTO)1.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_RESTRICT_FUNCTION_POINTER) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/restrict_function_pointer-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): restricting function pointers in project sources"
|
||||
|
||||
# Fill static variable with unconstrained values
|
||||
$(HARNESS_GOTO)3.goto: $(HARNESS_GOTO)2.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(NONDET_STATIC) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/nondet_static-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): setting static variables to nondet"
|
||||
|
||||
# Omit unused functions (sharpens coverage calculations)
|
||||
$(HARNESS_GOTO)4.goto: $(HARNESS_GOTO)3.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --drop-unused-functions $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/drop_unused_functions-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): dropping unused functions"
|
||||
|
||||
# Omit initialization of unused global variables (reduces problem size)
|
||||
$(HARNESS_GOTO)5.goto: $(HARNESS_GOTO)4.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --slice-global-inits $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/slice_global_inits-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): slicing global initializations"
|
||||
|
||||
# Replace function calls with function contracts
|
||||
# This must be done before enforcing function contracts,
|
||||
# since contract enforcement inlines all function calls.
|
||||
$(HARNESS_GOTO)6.goto: $(HARNESS_GOTO)5.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_USE_FUNCTION_CONTRACTS) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/use_function_contracts-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): replacing function calls with function contracts"
|
||||
|
||||
# Unwind loops for loop and function contracts
|
||||
$(HARNESS_GOTO)7.goto: $(HARNESS_GOTO)6.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_EARLY_UNWINDSET) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/unwind_loops-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): unwinding loops"
|
||||
|
||||
# Apply loop contracts
|
||||
$(HARNESS_GOTO)8.goto: $(HARNESS_GOTO)7.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_APPLY_LOOP_CONTRACTS) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/apply_loop_contracts-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): applying loop contracts"
|
||||
|
||||
# Check function contracts
|
||||
$(HARNESS_GOTO)9.goto: $(HARNESS_GOTO)8.goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_CHECK_FUNCTION_CONTRACTS) $^ $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--stdout-file $(LOGDIR)/check_function_contracts-log.txt \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): checking function contracts"
|
||||
|
||||
# Final name for proof harness
|
||||
$(HARNESS_GOTO).goto: $(HARNESS_GOTO)9.goto
|
||||
$(LITANI) add-job \
|
||||
--command 'cp $< $@' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage build \
|
||||
--description "$(PROOF_UID): copying final goto-binary"
|
||||
|
||||
################################################################
|
||||
# Targets to run the analysis commands
|
||||
|
||||
$(LOGDIR)/result.txt: $(HARNESS_GOTO).goto
|
||||
$(LITANI) add-job \
|
||||
$(POOL) \
|
||||
--command \
|
||||
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace $<' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--ci-stage test \
|
||||
--stdout-file $@ \
|
||||
$(MEMORY_PROFILING) \
|
||||
--ignore-returns 10 \
|
||||
--timeout $(CBMC_TIMEOUT) \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--tags "stats-group:safety checks" \
|
||||
--stderr-file $(LOGDIR)/result-err-log.txt \
|
||||
--description "$(PROOF_UID): checking safety properties"
|
||||
|
||||
$(LOGDIR)/result.xml: $(HARNESS_GOTO).goto
|
||||
$(LITANI) add-job \
|
||||
$(POOL) \
|
||||
--command \
|
||||
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace --xml-ui $<' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--ci-stage test \
|
||||
--stdout-file $@ \
|
||||
$(MEMORY_PROFILING) \
|
||||
--ignore-returns 10 \
|
||||
--timeout $(CBMC_TIMEOUT) \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--tags "stats-group:safety checks" \
|
||||
--stderr-file $(LOGDIR)/result-err-log.txt \
|
||||
--description "$(PROOF_UID): checking safety properties"
|
||||
|
||||
$(LOGDIR)/property.xml: $(HARNESS_GOTO).goto
|
||||
$(LITANI) add-job \
|
||||
--command \
|
||||
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --show-properties --xml-ui $<' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--ci-stage test \
|
||||
--stdout-file $@ \
|
||||
--ignore-returns 10 \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--stderr-file $(LOGDIR)/property-err-log.txt \
|
||||
--description "$(PROOF_UID): printing safety properties"
|
||||
|
||||
$(LOGDIR)/coverage.xml: $(HARNESS_GOTO).goto
|
||||
$(LITANI) add-job \
|
||||
$(POOL) \
|
||||
--command \
|
||||
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(COVERFLAGS) --cover location --xml-ui $<' \
|
||||
--inputs $^ \
|
||||
--outputs $@ \
|
||||
--ci-stage test \
|
||||
--stdout-file $@ \
|
||||
$(MEMORY_PROFILING) \
|
||||
--ignore-returns 10 \
|
||||
--timeout $(CBMC_TIMEOUT) \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--tags "stats-group:coverage computation" \
|
||||
--stderr-file $(LOGDIR)/coverage-err-log.txt \
|
||||
--description "$(PROOF_UID): calculating coverage"
|
||||
|
||||
define VIEWER_CMD
|
||||
$(VIEWER) \
|
||||
--result $(LOGDIR)/result.txt \
|
||||
--block $(LOGDIR)/coverage.xml \
|
||||
--property $(LOGDIR)/property.xml \
|
||||
--srcdir $(SRCDIR) \
|
||||
--goto $(HARNESS_GOTO).goto \
|
||||
--htmldir $(PROOFDIR)/html
|
||||
endef
|
||||
export VIEWER_CMD
|
||||
|
||||
$(PROOFDIR)/html: $(LOGDIR)/result.txt $(LOGDIR)/property.xml $(LOGDIR)/coverage.xml
|
||||
$(LITANI) add-job \
|
||||
--command "$$VIEWER_CMD" \
|
||||
--inputs $^ \
|
||||
--outputs $(PROOFDIR)/html \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--ci-stage report \
|
||||
--stdout-file $(LOGDIR)/viewer-log.txt \
|
||||
--description "$(PROOF_UID): generating report"
|
||||
|
||||
|
||||
# Caution: run make-source before running property and coverage checking
|
||||
# The current make-source script removes the goto binary
|
||||
$(LOGDIR)/source.json:
|
||||
mkdir -p $(dir $@)
|
||||
$(RM) -r $(GOTODIR)
|
||||
$(MAKE_SOURCE) --srcdir $(SRCDIR) --wkdir $(PROOFDIR) > $@
|
||||
$(RM) -r $(GOTODIR)
|
||||
|
||||
define VIEWER2_CMD
|
||||
$(VIEWER2) \
|
||||
--result $(LOGDIR)/result.xml \
|
||||
--coverage $(LOGDIR)/coverage.xml \
|
||||
--property $(LOGDIR)/property.xml \
|
||||
--srcdir $(SRCDIR) \
|
||||
--goto $(HARNESS_GOTO).goto \
|
||||
--reportdir $(PROOFDIR)/report \
|
||||
--config $(PROOFDIR)/cbmc-viewer.json
|
||||
endef
|
||||
export VIEWER2_CMD
|
||||
|
||||
# Omit logs/source.json from report generation until make-sources
|
||||
# works correctly with Makefiles that invoke the compiler with
|
||||
# mutliple source files at once.
|
||||
$(PROOFDIR)/report: $(LOGDIR)/result.xml $(LOGDIR)/property.xml $(LOGDIR)/coverage.xml
|
||||
$(LITANI) add-job \
|
||||
--command "$$VIEWER2_CMD" \
|
||||
--inputs $^ \
|
||||
--outputs $(PROOFDIR)/report \
|
||||
--pipeline-name "$(PROOF_UID)" \
|
||||
--stdout-file $(LOGDIR)/viewer-log.txt \
|
||||
--ci-stage report \
|
||||
--description "$(PROOF_UID): generating report"
|
||||
|
||||
litani-path:
|
||||
@echo $(LITANI)
|
||||
|
||||
# ##############################################################
|
||||
# Phony Rules
|
||||
#
|
||||
# These rules provide a convenient way to run a single proof up to a
|
||||
# certain stage. Users can browse into a proof directory and run
|
||||
# "make -Bj 3 report" to generate a report for just that proof, or
|
||||
# "make goto" to build the goto binary. Under the hood, this runs litani
|
||||
# for just that proof.
|
||||
|
||||
_goto: $(HARNESS_GOTO).goto
|
||||
goto:
|
||||
@ echo Running 'litani init'
|
||||
$(LITANI) init --project $(PROJECT_NAME)
|
||||
@ echo Running 'litani add-job'
|
||||
$(MAKE) -B _goto
|
||||
@ echo Running 'litani build'
|
||||
$(LITANI) run-build
|
||||
|
||||
_result: $(LOGDIR)/result.txt
|
||||
result:
|
||||
@ echo Running 'litani init'
|
||||
$(LITANI) init --project $(PROJECT_NAME)
|
||||
@ echo Running 'litani add-job'
|
||||
$(MAKE) -B _result
|
||||
@ echo Running 'litani build'
|
||||
$(LITANI) run-build
|
||||
|
||||
_property: $(LOGDIR)/property.xml
|
||||
property:
|
||||
@ echo Running 'litani init'
|
||||
$(LITANI) init --project $(PROJECT_NAME)
|
||||
@ echo Running 'litani add-job'
|
||||
$(MAKE) -B _property
|
||||
@ echo Running 'litani build'
|
||||
$(LITANI) run-build
|
||||
|
||||
_coverage: $(LOGDIR)/coverage.xml
|
||||
coverage:
|
||||
@ echo Running 'litani init'
|
||||
$(LITANI) init --project $(PROJECT_NAME)
|
||||
@ echo Running 'litani add-job'
|
||||
$(MAKE) -B _coverage
|
||||
@ echo Running 'litani build'
|
||||
$(LITANI) run-build
|
||||
|
||||
# Choose the invocation of cbmc-viewer depending on which version of
|
||||
# cbmc-viewer is installed. The --version flag is not implemented in
|
||||
# version 1 --- it is an "unrecognized argument" --- but it is
|
||||
# implemented in version 2.
|
||||
_report1: $(PROOFDIR)/html
|
||||
_report2: $(PROOFDIR)/report
|
||||
_report:
|
||||
(cbmc-viewer --version 2>&1 | grep "unrecognized argument" > /dev/null) && \
|
||||
$(MAKE) -B _report1 || $(MAKE) -B _report2
|
||||
|
||||
report report1 report2:
|
||||
@ echo Running 'litani init'
|
||||
$(LITANI) init --project $(PROJECT_NAME)
|
||||
@ echo Running 'litani add-job'
|
||||
$(MAKE) -B _report
|
||||
@ echo Running 'litani build'
|
||||
$(LITANI) run-build
|
||||
|
||||
################################################################
|
||||
# Targets to clean up after ourselves
|
||||
clean:
|
||||
-$(RM) $(DEPENDENT_GOTOS)
|
||||
-$(RM) TAGS*
|
||||
-$(RM) *~ \#*
|
||||
-$(RM) $(REWRITTEN_SOURCES) $(foreach rs,$(REWRITTEN_SOURCES),$(rs).json)
|
||||
|
||||
veryclean: clean
|
||||
-$(RM) -r html report
|
||||
-$(RM) -r $(LOGDIR) $(GOTODIR)
|
||||
|
||||
.PHONY: \
|
||||
_coverage \
|
||||
_goto \
|
||||
_property \
|
||||
_report \
|
||||
_report2 \
|
||||
_result \
|
||||
clean \
|
||||
coverage \
|
||||
goto \
|
||||
litani-path \
|
||||
property \
|
||||
report \
|
||||
report2 \
|
||||
result \
|
||||
setup_dependencies \
|
||||
testdeps \
|
||||
veryclean \
|
||||
#
|
||||
|
||||
################################################################
|
||||
|
||||
# Rule for generating cbmc-batch.yaml, used by the CI at
|
||||
# https://github.com/awslabs/aws-batch-cbmc/
|
||||
|
||||
JOB_OS ?= ubuntu16
|
||||
JOB_MEMORY ?= 32000
|
||||
|
||||
# Proofs that are expected to fail should set EXPECTED to
|
||||
# "FAILED" in their Makefile. Values other than SUCCESSFUL
|
||||
# or FAILED will cause a CI error.
|
||||
EXPECTED ?= SUCCESSFUL
|
||||
|
||||
define yaml_encode_options
|
||||
"$(shell echo $(1) | sed 's/ ,/ /g' | sed 's/ /;/g')"
|
||||
endef
|
||||
|
||||
CI_FLAGS = $(CBMCFLAGS) $(CHECKFLAGS) $(COVERFLAGS)
|
||||
|
||||
cbmc-batch.yaml:
|
||||
@$(RM) $@
|
||||
@echo 'build_memory: $(JOB_MEMORY)' > $@
|
||||
@echo 'cbmcflags: $(strip $(call yaml_encode_options,$(CI_FLAGS)))' >> $@
|
||||
@echo 'coverage_memory: $(JOB_MEMORY)' >> $@
|
||||
@echo 'expected: $(EXPECTED)' >> $@
|
||||
@echo 'goto: $(HARNESS_GOTO).goto' >> $@
|
||||
@echo 'jobos: $(JOB_OS)' >> $@
|
||||
@echo 'property_memory: $(JOB_MEMORY)' >> $@
|
||||
@echo 'report_memory: $(JOB_MEMORY)' >> $@
|
||||
|
||||
.PHONY: cbmc-batch.yaml
|
||||
|
||||
################################################################
|
||||
|
||||
# Run "make echo-proof-uid" to print the proof ID of a proof. This can be
|
||||
# used by scripts to ensure that every proof has an ID, that there are
|
||||
# no duplicates, etc.
|
||||
|
||||
.PHONY: echo-proof-uid
|
||||
echo-proof-uid:
|
||||
@echo $(PROOF_UID)
|
||||
|
||||
.PHONY: echo-project-name
|
||||
echo-project-name:
|
||||
@echo $(PROJECT_NAME)
|
||||
|
||||
################################################################
|
||||
|
||||
# Project-specific targets requiring values defined above
|
||||
sinclude $(PROOF_ROOT)/Makefile-project-targets
|
||||
|
||||
# CI-specific targets to drive cbmc in CI
|
||||
sinclude $(PROOF_ROOT)/Makefile-project-testing
|
||||
|
||||
################################################################
|
||||
@ -0,0 +1,27 @@
|
||||
CBMC proofs
|
||||
===========
|
||||
|
||||
This directory contains the CBMC proofs. Each proof is in its own
|
||||
directory.
|
||||
|
||||
This directory includes four Makefiles.
|
||||
|
||||
One Makefile describes the basic workflow for building and running proofs:
|
||||
|
||||
* Makefile.common:
|
||||
* make: builds the goto binary, does the cbmc property checking
|
||||
and coverage checking, and builds the final report.
|
||||
* make goto: builds the goto binary
|
||||
* make result: does cbmc property checking
|
||||
* make coverage: does cbmc coverage checking
|
||||
* make report: builds the final report
|
||||
|
||||
Three included Makefiles describe project-specific settings and can override
|
||||
definitions in Makefile.common:
|
||||
|
||||
* Makefile-project-defines: definitions like compiler flags
|
||||
required to build the goto binaries, and definitions to override
|
||||
definitions in Makefile.common.
|
||||
* Makefile-project-targets: other make targets needed for the project
|
||||
* Makefile-project-testing: other definitions and targets needed for
|
||||
unit testing or continuous integration.
|
||||
@ -0,0 +1,23 @@
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
HARNESS_ENTRY=findHeaderFieldParserCallback_harness
|
||||
PROOF_UID=findHeaderFieldParserCallback
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
# The header field length is bounded, so strncasecmp can be unwound to an expected
|
||||
# amount that won't make the proof run too long.
|
||||
MAX_HEADER_FIELD_LENGTH=11
|
||||
|
||||
DEFINES += -DMAX_HEADER_FIELD_LENGTH=$(MAX_HEADER_FIELD_LENGTH)
|
||||
INCLUDES +=
|
||||
|
||||
REMOVE_FUNCTION_BODY +=
|
||||
UNWINDSET += __CPROVER_file_local_core_http_client_c_caseInsensitiveStringCmp.0:$(MAX_HEADER_FIELD_LENGTH)
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
findHeaderFieldParserCallback proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for findHeaderFieldParserCallback.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "findHeaderFieldParserCallback",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file findHeaderFieldParserCallback_harness.c
|
||||
* @brief Implements the proof harness for findHeaderFieldParserCallback function.
|
||||
*/
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
#include "llhttp.h"
|
||||
#include "core_http_client.h"
|
||||
|
||||
int __CPROVER_file_local_core_http_client_c_findHeaderFieldParserCallback( llhttp_t * pHttpParser,
|
||||
const char * pFieldLoc,
|
||||
size_t fieldLen );
|
||||
|
||||
|
||||
void findHeaderFieldParserCallback_harness()
|
||||
{
|
||||
llhttp_t * pHttpParser;
|
||||
HTTPResponse_t * pResponse;
|
||||
findHeaderContext_t * pFindHeaderContext;
|
||||
size_t fieldLen, fieldContextLen, fieldOffset, valueLen, valueOffset;
|
||||
char * pFieldLoc;
|
||||
|
||||
pHttpParser = allocateHttpReadHeaderParser( NULL );
|
||||
pFindHeaderContext = allocateFindHeaderContext( NULL );
|
||||
pResponse = allocateHttpResponse( NULL );
|
||||
__CPROVER_assume( isValidHttpResponse( pResponse ) &&
|
||||
pResponse != NULL &&
|
||||
pResponse->pBuffer != NULL &&
|
||||
pResponse->bufferLen > 0 );
|
||||
|
||||
__CPROVER_assume( 0 < fieldLen && fieldLen < MAX_HEADER_FIELD_LENGTH && fieldLen <= pResponse->bufferLen );
|
||||
__CPROVER_assume( fieldOffset <= pResponse->bufferLen - fieldLen );
|
||||
pFieldLoc = pResponse->pBuffer + fieldOffset;
|
||||
|
||||
__CPROVER_assume( 0 < fieldContextLen && fieldContextLen < CBMC_MAX_OBJECT_SIZE );
|
||||
pFindHeaderContext->pField = ( char * ) malloc( fieldContextLen );
|
||||
__CPROVER_assume( pFindHeaderContext->pField != NULL );
|
||||
pFindHeaderContext->fieldLen = fieldContextLen;
|
||||
pFindHeaderContext->fieldFound = 0;
|
||||
pFindHeaderContext->valueFound = 0;
|
||||
pHttpParser->data = ( void * ) pFindHeaderContext;
|
||||
|
||||
__CPROVER_file_local_core_http_client_c_findHeaderFieldParserCallback( pHttpParser, pFieldLoc, fieldLen );
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
HARNESS_ENTRY=findHeaderOnHeaderCompleteCallback_harness
|
||||
PROOF_UID=findHeaderOnHeaderCompleteCallback
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
REMOVE_FUNCTION_BODY +=
|
||||
UNWINDSET +=
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
findHeaderOnHeaderCompleteCallback proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for findHeaderOnHeaderCompleteCallback.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "findHeaderOnHeaderCompleteCallback",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file findHeaderOnHeaderCompleteCallback_harness.c
|
||||
* @brief Implements the proof harness for findHeaderOnHeaderCompleteCallback function.
|
||||
*/
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
#include "llhttp.h"
|
||||
#include "core_http_client.h"
|
||||
|
||||
int __CPROVER_file_local_core_http_client_c_findHeaderOnHeaderCompleteCallback( llhttp_t * pHttpParser );
|
||||
|
||||
void findHeaderOnHeaderCompleteCallback_harness()
|
||||
{
|
||||
llhttp_t * pHttpParser;
|
||||
|
||||
pHttpParser = allocateHttpReadHeaderParser( NULL );
|
||||
|
||||
__CPROVER_file_local_core_http_client_c_findHeaderOnHeaderCompleteCallback( pHttpParser );
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
HARNESS_ENTRY=findHeaderValueParserCallback_harness
|
||||
PROOF_UID=findHeaderValueParserCallback
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
REMOVE_FUNCTION_BODY +=
|
||||
UNWINDSET +=
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
findHeaderValueParserCallback proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for findHeaderValueParserCallback.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
@ -0,0 +1 @@
|
||||
# This file marks this directory as containing a CBMC proof.
|
||||
@ -0,0 +1,7 @@
|
||||
{ "expected-missing-functions":
|
||||
[
|
||||
|
||||
],
|
||||
"proof-name": "findHeaderValueParserCallback",
|
||||
"proof-root": "cbmc/proofs"
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* coreHTTP v3.0.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file findHeaderValueParserCallback_harness.c
|
||||
* @brief Implements the proof harness for findHeaderValueParserCallback function.
|
||||
*/
|
||||
|
||||
#include "http_cbmc_state.h"
|
||||
#include "llhttp.h"
|
||||
#include "core_http_client.h"
|
||||
|
||||
int __CPROVER_file_local_core_http_client_c_findHeaderValueParserCallback( llhttp_t * pHttpParser,
|
||||
const char * pValueLoc,
|
||||
size_t valueLen );
|
||||
|
||||
void findHeaderValueParserCallback_harness()
|
||||
{
|
||||
llhttp_t * pHttpParser;
|
||||
HTTPResponse_t * pResponse;
|
||||
findHeaderContext_t * pFindHeaderContext;
|
||||
size_t fieldLen, fieldOffset, valueLen, valueOffset;
|
||||
char * pValueLoc;
|
||||
|
||||
pHttpParser = allocateHttpReadHeaderParser( NULL );
|
||||
pResponse = allocateHttpResponse( NULL );
|
||||
pFindHeaderContext = allocateFindHeaderContext( NULL );
|
||||
__CPROVER_assume( isValidHttpResponse( pResponse ) &&
|
||||
pResponse != NULL &&
|
||||
pResponse->pBuffer != NULL &&
|
||||
pResponse->bufferLen > 0 );
|
||||
|
||||
__CPROVER_assume( valueOffset <= pResponse->bufferLen );
|
||||
__CPROVER_assume( valueLen <= pResponse->bufferLen - valueOffset );
|
||||
pValueLoc = pResponse->pBuffer + valueOffset;
|
||||
|
||||
__CPROVER_assume( fieldOffset <= pResponse->bufferLen );
|
||||
__CPROVER_assume( fieldLen > 0 );
|
||||
__CPROVER_assume( fieldLen <= pResponse->bufferLen - fieldOffset );
|
||||
pFindHeaderContext->pField = pResponse->pBuffer + fieldOffset;
|
||||
pFindHeaderContext->fieldLen = fieldLen;
|
||||
pFindHeaderContext->pValueLen = &valueLen;
|
||||
pFindHeaderContext->pValueLoc = &pValueLoc;
|
||||
pFindHeaderContext->fieldFound = nondet_bool() ? 0 : 1;
|
||||
pFindHeaderContext->valueFound = 0;
|
||||
pHttpParser->data = ( void * ) pFindHeaderContext;
|
||||
|
||||
__CPROVER_file_local_core_http_client_c_findHeaderValueParserCallback( pHttpParser, pValueLoc, valueLen );
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# SPDX-License-Identifier: MIT-0
|
||||
|
||||
HARNESS_ENTRY=httpParserOnBodyCallback_harness
|
||||
PROOF_UID=httpParserOnBodyCallback
|
||||
HARNESS_FILE=$(HARNESS_ENTRY)
|
||||
|
||||
DEFINES +=
|
||||
INCLUDES +=
|
||||
|
||||
REMOVE_FUNCTION_BODY += memmove
|
||||
|
||||
UNWINDSET +=
|
||||
|
||||
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/sources/http_cbmc_state.c
|
||||
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/memmove.c
|
||||
|
||||
PROJECT_SOURCES += $(SRCDIR)/source/core_http_client.c
|
||||
|
||||
include ../Makefile.common
|
||||
@ -0,0 +1,10 @@
|
||||
httpParserOnBodyCallback proof
|
||||
==============
|
||||
|
||||
This directory contains a memory safety proof for httpParserOnBodyCallback.
|
||||
|
||||
To run the proof.
|
||||
* Add cbmc, goto-cc, goto-instrument, goto-analyzer, and cbmc-viewer
|
||||
to your path.
|
||||
* Run "make".
|
||||
* Open html/index.html in a web browser.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user