mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-26 12:14:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
739d78a45a | ||
|
|
8a62633b2f | ||
|
|
aae1a687a9 | ||
|
|
61285ec418 | ||
|
|
a00b3f1c6c | ||
|
|
2c813f3e72 | ||
|
|
ea68d7a705 | ||
|
|
654f401038 | ||
|
|
ad89122a06 | ||
|
|
73ed158e76 | ||
|
|
548c3dc77f | ||
|
|
c1fa067a1f | ||
|
|
9fd87060f9 | ||
|
|
de0a3b035a | ||
|
|
9f76ea8030 | ||
|
|
76b7356873 | ||
|
|
c24d5aabd8 | ||
|
|
0df6645b90 | ||
|
|
b19cf8654f | ||
|
|
19933a4673 | ||
|
|
76963f7d01 | ||
|
|
e670ea3d61 | ||
|
|
fa33b57e4f | ||
|
|
77e369bc79 | ||
|
|
94ad9767d3 | ||
|
|
aa76f5673b | ||
|
|
81a699c801 | ||
|
|
bd15c456b2 | ||
|
|
10d9e1e9ae | ||
|
|
6a3813f633 | ||
|
|
51fe22a95f | ||
|
|
105762416f | ||
|
|
db7087f455 | ||
|
|
c5693503cb | ||
|
|
b74590a4a5 | ||
|
|
d5eeed48eb | ||
|
|
fc5c0d0964 | ||
|
|
aa2647c0bc | ||
|
|
cef0acdb40 | ||
|
|
2140656acc | ||
|
|
fd0c969f16 | ||
|
|
dfeb929e0e | ||
|
|
d3e67733a6 | ||
|
|
eff74fdc9d | ||
|
|
5e4c40ad09 | ||
|
|
087e6d3142 | ||
|
|
587b074822 | ||
|
|
6aa8c01ac7 | ||
|
|
3bbcd5df3e | ||
|
|
af512c57ef | ||
|
|
58297a7871 | ||
|
|
18a530048c | ||
|
|
f9ed75d6b3 | ||
|
|
3c1f41e575 | ||
|
|
c772936dd1 | ||
|
|
253696be45 | ||
|
|
79b7accc55 | ||
|
|
7a1e846c73 | ||
|
|
ce59ff89c3 | ||
|
|
d31d064d5e | ||
|
|
467fbf4bb4 | ||
|
|
6769223ce1 | ||
|
|
294e483885 | ||
|
|
43513e2d56 | ||
|
|
d1b7687e98 | ||
|
|
9ac09da1d2 | ||
|
|
24a330c750 | ||
|
|
13a9c773f2 | ||
|
|
3cd166d065 | ||
|
|
490066fd17 | ||
|
|
94fce72ade | ||
|
|
eacc64bdd1 | ||
|
|
7b037f4957 | ||
|
|
fa841916c1 | ||
|
|
75c11436ff | ||
|
|
e07a8283ec | ||
|
|
2a174b0d3b | ||
|
|
013993abae | ||
|
|
dccc153c68 | ||
|
|
db0867f435 | ||
|
|
7234121835 | ||
|
|
3aafc073d8 | ||
|
|
b527ed313c | ||
|
|
cd86559685 | ||
|
|
f67e843be6 | ||
|
|
4f9ebd8092 | ||
|
|
6c044d6aeb | ||
|
|
c6ee909aa4 | ||
|
|
393063428e | ||
|
|
1494f5e831 | ||
|
|
8bfd0c2ca3 | ||
|
|
e9de2f3eb1 | ||
|
|
8bf9d09d96 | ||
|
|
67255ce8f5 | ||
|
|
5db89aa264 | ||
|
|
8a9b1d9873 | ||
|
|
c08c1afb1e | ||
|
|
2c7f58aed2 | ||
|
|
b3ee71acbe | ||
|
|
52ab6bc499 | ||
|
|
bf059ad42f | ||
|
|
85df6a6131 | ||
|
|
d840b4a4ee | ||
|
|
a8c2ce544e | ||
|
|
b95022a3b3 | ||
|
|
8c45a9d2c9 | ||
|
|
0fe64fbff9 | ||
|
|
64e806628b | ||
|
|
ccd2b2699f | ||
|
|
0b5c0c9889 | ||
|
|
6293e7dbec | ||
|
|
87325ece82 | ||
|
|
6cbd9b3067 | ||
|
|
aa27fde9d0 | ||
|
|
e854585802 | ||
|
|
2c5aba24cc | ||
|
|
806ee0f2cb | ||
|
|
e72b95fb1c | ||
|
|
471e7ff61a | ||
|
|
3d2de154d1 | ||
|
|
fc551ec2e9 | ||
|
|
f5e2c68c8b | ||
|
|
074ef5197b | ||
|
|
5f1f4a0df8 | ||
|
|
86334e9040 | ||
|
|
f71cc3ebc3 | ||
|
|
00910462e7 | ||
|
|
2fc56dd1d0 | ||
|
|
a5ebe71394 | ||
|
|
0eb8bf6b51 | ||
|
|
3a0fe5288c | ||
|
|
bfca233160 | ||
|
|
acf217601b | ||
|
|
b0d0fbfd9f | ||
|
|
9411f1c7b6 | ||
|
|
d7d7ebf99a | ||
|
|
8072ae2057 | ||
|
|
e529e644ab | ||
|
|
d6fdfe5b1b | ||
|
|
50e15e574f | ||
|
|
58f1533779 | ||
|
|
f4a49829ea | ||
|
|
3efe6641eb | ||
|
|
0459d9e106 | ||
|
|
305d69ee36 | ||
|
|
98e744a9ad | ||
|
|
1d97f2e2b5 | ||
|
|
c92bc4b4ac | ||
|
|
6a3e1e41c4 | ||
|
|
650caface3 | ||
|
|
8b6e02e985 | ||
|
|
3ee6fe45f9 | ||
|
|
e811afd397 | ||
|
|
b197a674e1 | ||
|
|
08f6b99b13 | ||
|
|
b18d0301f3 | ||
|
|
5596621420 | ||
|
|
bd8a66eee7 | ||
|
|
b62ebb3c10 | ||
|
|
45d796fe5b | ||
|
|
d8a3b90cad | ||
|
|
5be9e55425 | ||
|
|
6b6acd3967 | ||
|
|
1b06403a19 | ||
|
|
b740c80855 | ||
|
|
29594283c1 | ||
|
|
51f54f9b7e | ||
|
|
1f48b1ca65 | ||
|
|
fd2d7cccf3 | ||
|
|
5726e680ec | ||
|
|
fadf28adb4 | ||
|
|
a321c2d096 | ||
|
|
bbb07bf6f7 | ||
|
|
a801160bc0 | ||
|
|
662cc27f4f | ||
|
|
d01aa01a51 |
No files matched your search
@@ -11,17 +11,14 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if ./test/match_changed_files.sh '^src/' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
if: ${{ env.GO == 1 }}
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'mongoose'
|
||||
dry-run: false
|
||||
language: c++
|
||||
- name: Run Fuzzers
|
||||
if: ${{ env.GO == 1 }}
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'mongoose'
|
||||
@@ -30,7 +27,7 @@ jobs:
|
||||
language: c++
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
if: env.GO == 1 && failure() && steps.build.outcome == 'success'
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
@@ -2,8 +2,8 @@ name: "CodeQL Scanning"
|
||||
# https://github.com/github/codeql-action
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 23 * * *' # run at 11:30 PM UTC
|
||||
#schedule:
|
||||
# - cron: '30 23 * * *' # run at 11:30 PM UTC
|
||||
# Allow manual runs
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
@@ -17,4 +17,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: make -C test ${{ matrix.target }}
|
||||
- run: make -C test ${{ matrix.target }} ARGS="-max_total_time=7200"
|
||||
|
||||
# as we're not getting access to test units causing a problem, convert from the log:
|
||||
# base64 -d > dataofdeath
|
||||
# then paste the base64 data, enter, Ctrl-D; maybe check with hexdump -C dataofdeath
|
||||
@@ -33,11 +33,11 @@ jobs:
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
SSL: ${{ matrix.ssl }}
|
||||
TFLAGS: ${{ matrix.select }}
|
||||
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }}
|
||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && test/setup_mqtt_server.sh && make -C test ${{ matrix.target }}
|
||||
mip:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -46,14 +46,31 @@ jobs:
|
||||
cc: [gcc, clang, g++, clang++]
|
||||
target: [mip_test, mip_tap_test]
|
||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||
# #3226: built-in TCP is currently not working with WolfSSL (builds fine)
|
||||
exclude:
|
||||
- ssl: WOLFSSL
|
||||
target: mip_tap_test
|
||||
name: ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
SSL: ${{ matrix.ssl }}
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} IPV6=0
|
||||
mip89:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1 # no parallel runs, to minimize MQTT errors
|
||||
matrix:
|
||||
target: [mip_vc98]
|
||||
name: mip89 ${{ matrix.target }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: make -C test ${{ matrix.target }}
|
||||
s390:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -61,10 +78,12 @@ jobs:
|
||||
matrix:
|
||||
ssl: ["", BUILTIN]
|
||||
name: S390 SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }}
|
||||
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }} MULTIREC=NO
|
||||
armhf:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -72,10 +91,12 @@ jobs:
|
||||
matrix:
|
||||
ssl: ["", BUILTIN]
|
||||
name: ArmHF SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }}
|
||||
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }} MULTIREC=NO
|
||||
unamalgamated-mg_prefix:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -87,7 +108,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev
|
||||
- run: make -C test unamalgamated && make -C test mg_prefix
|
||||
- run: make -C test unamalgamated SSL=${{ matrix.ssl }} && make -C test mg_prefix
|
||||
valgrind:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -95,34 +116,43 @@ jobs:
|
||||
matrix:
|
||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||
name: Valgrind SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev valgrind
|
||||
- run: make -C test valgrind SSL=${{ matrix.ssl }}
|
||||
- run: ./test/setup_mqtt_server.sh && make -C test valgrind SSL=${{ matrix.ssl }}
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||
# Mongoose does not work with WolfSSL version in MacOS
|
||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL] # , WOLFSSL]
|
||||
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
||||
include:
|
||||
- ssl: MBEDTLS
|
||||
env:
|
||||
# MbedTLS version in MacOS refuses to validate a certificate without a hostname, causing MQTT tests to fail when using MQTT_LOCALHOST
|
||||
tflags: -DNO_MQTT_TESTS
|
||||
exclude:
|
||||
- ssl: MBEDTLS
|
||||
select: -DMG_ENABLE_POLL=0
|
||||
- ssl: OPENSSL
|
||||
select: -DMG_ENABLE_POLL=0
|
||||
- ssl: WOLFSSL
|
||||
select: -DMG_ENABLE_POLL=0
|
||||
#- ssl: WOLFSSL
|
||||
# select: -DMG_ENABLE_POLL=0
|
||||
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||
env:
|
||||
SSL: ${{ matrix.ssl }}
|
||||
TFLAGS: ${{ matrix.select }} -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
|
||||
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST ${{ matrix.env.tflags }} -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: brew install mbedtls wolfssl # jq openssl already pre-installed
|
||||
- run: brew install mbedtls wolfssl mosquitto # jq openssl already pre-installed
|
||||
- run: /opt/homebrew/opt/mosquitto/sbin/mosquitto -c /Users/runner/work/mongoose/mongoose/test/mosquitto.conf.macos &
|
||||
- run: make -C test test ASAN_OPTIONS= MBEDTLS=$(echo $(brew --cellar)/mbedtls*/*) OPENSSL=$(echo $(brew --cellar)/openssl*/*) WOLFSSL=$(echo $(brew --cellar)/wolfssl*/*)
|
||||
windows:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -138,12 +168,12 @@ jobs:
|
||||
select: -DMG_ENABLE_POLL=1
|
||||
name: windows ${{ matrix.target }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||
env:
|
||||
SSL: SSL=${{ matrix.ssl }}
|
||||
TFLAGS: ${{ matrix.select }}
|
||||
SSL: ${{ matrix.ssl }}
|
||||
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: make -C test ${{ matrix.target }}
|
||||
- run: ./test/setup_mqtt_server.sh && make -C test ${{ matrix.target }}
|
||||
arm:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -303,7 +333,6 @@ jobs:
|
||||
matrix:
|
||||
example:
|
||||
- path: mqtt/mqtt-client/microchip/same54-xpro
|
||||
- path: nxp/nxp-mimxrt1020-azurertos
|
||||
- path: nxp/nxp-frdmk66f-freertos
|
||||
- path: nxp/nxp-lpcxpresso54s018m-freertos
|
||||
- path: nxp/nxp-mimxrt1020-freertos
|
||||
@@ -357,7 +386,7 @@ jobs:
|
||||
matrix:
|
||||
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||
example:
|
||||
- path: tutorials/http/device-dashboard/microchip/same54-xpro
|
||||
- path: http/device-dashboard/microchip/same54-xpro
|
||||
- path: nxp/rt1020-evk-make-freertos-builtin
|
||||
- path: nxp/rt1060-evk-make-freertos-builtin
|
||||
- path: nxp/rt1170-evk-make-freertos-builtin
|
||||
@@ -425,24 +454,6 @@ jobs:
|
||||
- run: sudo pip install yq
|
||||
- run: cd test/cube && make
|
||||
|
||||
zephyr_examples:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
- run: make -C tutorials/zephyr init REPO=zephyrprojectrtos/ci:v0.26.14 # "no space left on device" with newers
|
||||
- name: minify manifest
|
||||
uses: mikefarah/yq@master
|
||||
with:
|
||||
cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' tutorials/zephyr/zephyrproject/zephyr/west.yml
|
||||
- run: make -C tutorials/zephyr update
|
||||
- run: make -C tutorials/zephyr/device-dashboard build
|
||||
- run: make -C tutorials/zephyr/http-client build
|
||||
- run: make -C tutorials/zephyr/http-server build
|
||||
- run: make -C tutorials/zephyr/mqtt-aws-client build
|
||||
- run: make -C tutorials/zephyr/websocket-server build
|
||||
|
||||
test_f7:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
+351
-339
@@ -5,6 +5,8 @@ on:
|
||||
- "**Makefile"
|
||||
- "**.c"
|
||||
- "**.h"
|
||||
# Allow manual runs
|
||||
workflow_dispatch:
|
||||
env:
|
||||
IPV6: 0
|
||||
jobs:
|
||||
@@ -20,28 +22,33 @@ jobs:
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
SSL: ${{ matrix.ssl }}
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: make -C test ${{ matrix.target }}
|
||||
run: if [ "${{ matrix.target }}" == "test" ]; then ./test/setup_mqtt_server.sh ; fi && make -C test ${{ matrix.target }}
|
||||
s390:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
|
||||
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
|
||||
armhf:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
|
||||
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
|
||||
unamalgamated-mg_prefix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -59,14 +66,17 @@ jobs:
|
||||
name: macos SSL=${{ matrix.ssl }}
|
||||
env:
|
||||
SSL: ${{ matrix.ssl }}
|
||||
#TFLAGS: -DNO_SNTP_CHECK
|
||||
TFLAGS: -DMQTT_LOCALHOST # -DNO_SNTP_CHECK
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: make -C test test ASAN_OPTIONS=
|
||||
run: |
|
||||
brew install mosquitto
|
||||
/opt/homebrew/opt/mosquitto/sbin/mosquitto -c /Users/runner/work/mongoose/mongoose/test/mosquitto.conf.macos &
|
||||
make -C test test ASAN_OPTIONS=
|
||||
windows:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -74,12 +84,14 @@ jobs:
|
||||
matrix:
|
||||
target: [vc98, vc22, mingw++]
|
||||
name: windows ${{ matrix.target }}
|
||||
env:
|
||||
TFLAGS: -DMQTT_LOCALHOST
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: make -C test ${{ matrix.target }}
|
||||
run: ./test/setup_mqtt_server.sh && make -C test ${{ matrix.target }}
|
||||
arm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -335,360 +347,360 @@ jobs:
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: cd test/cube && make
|
||||
|
||||
test_f7:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f7.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
# always run baremetal on core or dashboard or specific example changes; other examples only on specific example changes
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true # continue so next test has a chance to re-flash and exit from collisions and flash failures
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f746zg-make-baremetal-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-tcp'; then
|
||||
make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- name: Cube
|
||||
run: |
|
||||
echo GO=0 >> $GITHUB_ENV
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f7.*-cube-'; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
# nothing specific to install or do
|
||||
fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# test_f7:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 2 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f7.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# # always run baremetal on core or dashboard or specific example changes; other examples only on specific example changes
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true # continue so next test has a chance to re-flash and exit from collisions and flash failures
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f746zg-make-baremetal-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-builtin'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||
# fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-lwip'; then
|
||||
make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||
fi
|
||||
|
||||
|
||||
test_f4:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f4.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f429zi-make-baremetal-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-make-freertos-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- name: Cube
|
||||
run: |
|
||||
echo GO=0 >> $GITHUB_ENV
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f4.*-cube-'; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
# nothing specific to install or do
|
||||
fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-builtin'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-tcp'; then
|
||||
# make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-lwip'; then
|
||||
make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||
fi
|
||||
|
||||
test_h743:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h74.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h743zi-make-baremetal-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-make-freertos-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
# - name: Cube
|
||||
# run: |
|
||||
# echo GO=0 >> $GITHUB_ENV
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h74.*-cube-'; then
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f7.*-cube-'; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# # nothing specific to install or do
|
||||
# fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
|
||||
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||
## fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-builtin'; then
|
||||
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||
## fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-lwip'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||
# fi
|
||||
#
|
||||
#
|
||||
# test_f4:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 2 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f4.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f429zi-make-baremetal-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-freertos-builtin'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-make-freertos-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
|
||||
test_h723:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h72.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h723zg-make-baremetal-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h723zg-make-freertos-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_h5:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h5.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h563zi-make-baremetal-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h563zi-make-freertos-builtin'; then
|
||||
make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_rt1020:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020-evk-make-baremetal-builtin'; then
|
||||
make -C tutorials/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/nxp/rt1020-evk-make-freertos-builtin'; then
|
||||
make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_rt1060:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060-evk-make-baremetal-builtin'; then
|
||||
make -C tutorials/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/nxp/rt1060-evk-make-freertos-builtin'; then
|
||||
make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_rt1170:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170-evk-make-baremetal-builtin'; then
|
||||
make -C tutorials/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/nxp/rt1170-evk-make-freertos-builtin'; then
|
||||
make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_ra6m4:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 3 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4-make-baremetal-builtin'; then
|
||||
make -C tutorials/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
# - name: Cube
|
||||
# run: |
|
||||
# echo GO=0 >> $GITHUB_ENV
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f4.*-cube-'; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# # nothing specific to install or do
|
||||
# fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
|
||||
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||
## fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-builtin'; then
|
||||
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||
## fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/renesas/ek-ra6m4-make-freertos-builtin'; then
|
||||
# make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-lwip'; then
|
||||
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||
# fi
|
||||
|
||||
test_tm4c:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c.*-make-" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
|
||||
make -C tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh 'tutorials/ti/ek-tm4c1294xl-make-freertos-builtin'; then
|
||||
make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_same54:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- name: baremetal
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/mqtt/mqtt-client" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
|
||||
make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: |
|
||||
if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
|
||||
make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
fi
|
||||
|
||||
test_pico_w5500:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- name: SDK
|
||||
run: |
|
||||
if ./test/match_changed_files.sh "^src" ; then
|
||||
echo GO=1 >> $GITHUB_ENV
|
||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
fi
|
||||
- if: ${{ env.GO == 1 }}
|
||||
run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
#
|
||||
# test_h743:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h74.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h743zi-make-baremetal-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-make-freertos-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
## - name: Cube
|
||||
## run: |
|
||||
## echo GO=0 >> $GITHUB_ENV
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h74.*-cube-'; then
|
||||
## echo GO=1 >> $GITHUB_ENV
|
||||
## # nothing specific to install or do
|
||||
## fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
|
||||
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||
## fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-freertos-builtin'; then
|
||||
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||
## fi
|
||||
#
|
||||
# test_h723:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h72.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h723zg-make-baremetal-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h723zg-make-freertos-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_h5:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h5.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h563zi-make-baremetal-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h563zi-make-freertos-builtin'; then
|
||||
# make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_rt1020:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020-evk-make-baremetal-builtin'; then
|
||||
# make -C tutorials/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/nxp/rt1020-evk-make-freertos-builtin'; then
|
||||
# make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_rt1060:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060-evk-make-baremetal-builtin'; then
|
||||
# make -C tutorials/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/nxp/rt1060-evk-make-freertos-builtin'; then
|
||||
# make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_rt1170:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170-evk-make-baremetal-builtin'; then
|
||||
# make -C tutorials/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/nxp/rt1170-evk-make-freertos-builtin'; then
|
||||
# make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_ra6m4:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 3 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# continue-on-error: true
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4-make-baremetal-builtin'; then
|
||||
# make -C tutorials/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
## - if: ${{ env.GO == 1 }}
|
||||
## run: |
|
||||
## if ./test/match_changed_files.sh 'tutorials/renesas/ek-ra6m4-make-freertos-builtin'; then
|
||||
## make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
## fi
|
||||
#
|
||||
# test_tm4c:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 2 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c.*-make-" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
|
||||
# make -C tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh 'tutorials/ti/ek-tm4c1294xl-make-freertos-builtin'; then
|
||||
# make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_same54:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 2 }
|
||||
# - name: baremetal
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/mqtt/mqtt-client" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
|
||||
# make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
|
||||
# make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
# fi
|
||||
#
|
||||
# test_pico_w5500:
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# GO: 0
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# with: { fetch-depth: 2 }
|
||||
# - name: SDK
|
||||
# run: |
|
||||
# if ./test/match_changed_files.sh "^src" ; then
|
||||
# echo GO=1 >> $GITHUB_ENV
|
||||
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||
# fi
|
||||
# - if: ${{ env.GO == 1 }}
|
||||
# run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Zephyr
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # run at 12 AM UTC
|
||||
# Allow manual runs
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
zephyr_examples:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
revno: ["--mr v3.7-branch", "--mr v4.2.0"] # LTS, latest stable
|
||||
name: Zephyr ${{ matrix.revno }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with: { fetch-depth: 2 }
|
||||
- run: test/setup_ga_docker_filesystem.sh
|
||||
- run: make -C tutorials/zephyr init REPO=zephyrprojectrtos/ci REVNO="${{ matrix.revno }}"
|
||||
- run: make -C tutorials/zephyr minify REVNO="${{ matrix.revno }}"
|
||||
- run: make -C tutorials/zephyr update
|
||||
- run: make -C tutorials/zephyr/device-dashboard build
|
||||
- run: make -C tutorials/zephyr/http-client build
|
||||
- run: make -C tutorials/zephyr/http-server build
|
||||
- run: make -C tutorials/zephyr/mqtt-aws-client build
|
||||
- run: make -C tutorials/zephyr/websocket-server build
|
||||
@@ -1,10 +1,9 @@
|
||||
# Mongoose - Embedded Web Server / Embedded Network Library
|
||||
|
||||
[](https://opensource.org/licenses/gpl-2.0.php)
|
||||
[](https://github.com/cesanta/mongoose/actions)
|
||||
[](https://github.com/cesanta/mongoose/actions)
|
||||
[](https://codecov.io/gh/cesanta/mongoose)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
||||
[](https://gurubase.io/g/mongoose)
|
||||
[](https://issues.oss-fuzz.com/issues?sort=-opened&can=1&q=proj:mongoose)
|
||||
|
||||
Mongoose is a network library for C/C++. It provides event-driven non-blocking
|
||||
APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocols. It is designed
|
||||
@@ -35,6 +34,35 @@ robust, and easy. Features include:
|
||||
|
||||
See https://mongoose.ws/ for complete documentation, videos, case studies, etc.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
Mongoose can work on top of any TCP/IP stack that supports BSD sockets API.
|
||||
Platforms supported by the 3rd party TCP/IP stacks:
|
||||
|
||||
| TCP/IP stack | Notes |
|
||||
| :-------------- | :------- |
|
||||
| **lwIP** | All devices running lwIP, for example ESP32, ESP32S3, ESP32C3, ESP32C6, etc |
|
||||
| **Zephyr** | All devices supported by Zephyr |
|
||||
| **Other** | Any other TCP/IP stack that supports BSD socket API, for example Amazon FreeRTOS-TCP |
|
||||
| **Linux, Mac, Windows** | Workstations, server, single board computers, embedded Linux devices running on MPUs or FPGAs |
|
||||
|
||||
Optionally, Mongoose provides its own built-in TCP/IP stack, eliminating the
|
||||
need for additional software to implement networking functionality. The
|
||||
built-in stack supports operation in both bare-metal and RTOS environments.
|
||||
Platforms supported by the Mongoose built-in TCP/IP stack:
|
||||
|
||||
| Hardware | Notes |
|
||||
| :------------- | :------- |
|
||||
| **STM32** | All STM32 MCUs with built-in Ethernet: STM32Fxx, STM32H5xx, STM32H7xx |
|
||||
| **NXP** | All NXP MCUs with built-in Ethernet: IMXRT102x, IMXRT104x, IMXRT105x, IMXRT106x, IMXRT117x, RW612, MCXN94x |
|
||||
| **Microchip** | ATSAME54 MCUs with built-int Ethernet |
|
||||
| **Renesas** | RA5M, RA6M, RA8M MCUs with built-in Ethernet |
|
||||
| **Infineon** | XMC4, XMC7 MCUs with built-in Ethernet |
|
||||
| **Texas Instruments** | TM4C, TMS570 MCUs with built-in Ethernet |
|
||||
| **Cypress WiFi** | Any MCU with CY43xx WiFi chips, like RP2040 Pico-W, RP2350 Pico2-W, Arduino Portenta |
|
||||
| **Wiznet Ethernet** | Any MCU that use Wiznet W5500 or Wiznet 5100 MAC+PHY chips |
|
||||
| **Cellular** | NRF9160, SIM800 |
|
||||
|
||||
## Usage Examples
|
||||
|
||||
Below are quick snippets that should give an idea how simple the API is and
|
||||
@@ -177,6 +205,10 @@ Technical guides and deep dives into embedded web servers, WebUI integration and
|
||||
- [Embedded Web Server: A Comprehensive Guide for Modern Connected Devices](https://mongoose.ws/articles/embedded-web-server-a-comprehensive-guide-for-modern-connected-devices/)
|
||||
- [Building Embedded Web Device Dashboards](https://mongoose.ws/articles/building-embedded-web-device-dashboard/)
|
||||
- [ESP32 Device Dashboard: A Step-by-Step Guide for Developers](https://mongoose.ws/articles/esp32-device-dashboard/)
|
||||
- [How to build an STM32 Web Dashboard](https://mongoose.ws/articles/stm32-device-dashboard/)
|
||||
- [STM32 WebSocket Guide](https://mongoose.ws/articles/stm32-websocket-guide/)
|
||||
- [Web File Manager on STM32, ESP32 and Embedded Linux](https://mongoose.ws/articles/building-a-web-file-manager-on-stm32-esp32-embedded-linux/)
|
||||
- [Web dashboard on Zephyr RTOS](https://mongoose.ws/articles/web-dashboard-on-zephyr-rtos/)
|
||||
|
||||
|
||||
## Contributions
|
||||
|
||||
+1229
-666
File diff suppressed because it is too large.
Load diff
+620
-383
File diff suppressed because it is too large.
Load diff
+9
-4
@@ -6,9 +6,9 @@
|
||||
#define MG_ARCH_ESP32 3 // ESP32
|
||||
#define MG_ARCH_ESP8266 4 // ESP8266
|
||||
#define MG_ARCH_FREERTOS 5 // FreeRTOS
|
||||
#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
|
||||
#define MG_ARCH_THREADX 6 // Eclipse ThreadX (former MS Azure RTOS)
|
||||
#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
|
||||
#define MG_ARCH_NEWLIB 8 // Bare metal ARM
|
||||
#define MG_ARCH_ARMGCC 8 // Plain ARM GCC
|
||||
#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
|
||||
#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
|
||||
#define MG_ARCH_PICOSDK 11 // Raspberry Pi Pico-SDK (RP2040, RP2350)
|
||||
@@ -16,6 +16,9 @@
|
||||
#define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS)
|
||||
#define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS
|
||||
#define MG_ARCH_ARMCGT 15 // Texas Semi ARM-CGT
|
||||
#define MG_ARCH_CUBE 16 // STM32Cube environment
|
||||
|
||||
#define MG_ARCH_NEWLIB MG_ARCH_ARMGCC // Alias, deprecate in 2025
|
||||
|
||||
#if !defined(MG_ARCH)
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
@@ -30,17 +33,19 @@
|
||||
#endif
|
||||
|
||||
#if !defined(MG_ARCH)
|
||||
#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in your compiler"
|
||||
#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in mongoose_config.h"
|
||||
#endif
|
||||
|
||||
// http://esr.ibiblio.org/?p=5095
|
||||
#define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
|
||||
|
||||
#include "arch_armgcc.h"
|
||||
#include "arch_cube.h"
|
||||
#include "arch_esp32.h"
|
||||
#include "arch_esp8266.h"
|
||||
#include "arch_freertos.h"
|
||||
#include "arch_newlib.h"
|
||||
#include "arch_rtx.h"
|
||||
#include "arch_threadx.h"
|
||||
#include "arch_unix.h"
|
||||
#include "arch_win32.h"
|
||||
#include "arch_zephyr.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ARCH == MG_ARCH_NEWLIB
|
||||
#if MG_ARCH == MG_ARCH_ARMGCC
|
||||
#define _POSIX_TIMERS
|
||||
|
||||
#include <ctype.h>
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ARCH == MG_ARCH_AZURERTOS
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <fx_api.h>
|
||||
#include <tx_api.h>
|
||||
|
||||
#include <nx_api.h>
|
||||
#include <nx_bsd.h>
|
||||
#include <nx_port.h>
|
||||
#include <tx_port.h>
|
||||
|
||||
#define PATH_MAX FX_MAXIMUM_PATH
|
||||
#define MG_DIRSEP '\\'
|
||||
|
||||
#define socklen_t int
|
||||
#define closesocket(x) soc_close(x)
|
||||
|
||||
#undef FOPEN_MAX
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ARCH == MG_ARCH_CUBE
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Cube-generated header, includes ST Cube HAL
|
||||
// NOTE: use angle brackets to prevent amalgamator ditching it
|
||||
#include <main.h>
|
||||
|
||||
#ifndef MG_PATH_MAX
|
||||
#define MG_PATH_MAX 100
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_DIRLIST
|
||||
#define MG_ENABLE_DIRLIST 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_SOCKET
|
||||
#define MG_ENABLE_SOCKET 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_TCPIP
|
||||
#define MG_ENABLE_TCPIP 1 // Enable built-in TCP/IP stack
|
||||
#endif
|
||||
|
||||
#if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_STM32F) && !defined(MG_ENABLE_DRIVER_STM32H)
|
||||
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
|
||||
#define MG_ENABLE_DRIVER_STM32F 1
|
||||
#elif defined(STM32H5) || defined(STM32H7)
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#else
|
||||
#error Select a driver in mongoose_config.h
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MG_TLS
|
||||
#define MG_TLS MG_TLS_BUILTIN
|
||||
#endif
|
||||
|
||||
#if !defined(MG_OTA) && defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
|
||||
#define MG_OTA MG_OTA_STM32F
|
||||
#elif !defined(MG_OTA) && defined(STM32H5)
|
||||
#define MG_OTA MG_OTA_STM32H5
|
||||
#elif !defined(MG_OTA) && defined(STM32H7)
|
||||
#define MG_OTA MG_OTA_STM32H7
|
||||
#endif
|
||||
// use HAL-defined execute-in-ram section
|
||||
#define MG_IRAM __attribute__((section(".RamFunc")))
|
||||
|
||||
#ifndef HAL_ICACHE_MODULE_ENABLED
|
||||
#define HAL_ICACHE_IsEnabled() 0
|
||||
#define HAL_ICACHE_Enable() (void) 0
|
||||
#define HAL_ICACHE_Disable() (void) 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_SET_MAC_ADDRESS
|
||||
// Construct MAC address from UUID
|
||||
#define MGUID ((uint32_t *) UID_BASE) // Unique 96-bit chip ID
|
||||
#define MG_SET_MAC_ADDRESS(mac) \
|
||||
do { \
|
||||
int icache_enabled_ = HAL_ICACHE_IsEnabled(); \
|
||||
if (icache_enabled_) HAL_ICACHE_Disable(); \
|
||||
mac[0] = 42; \
|
||||
mac[1] = ((MGUID[0] >> 0) & 255) ^ ((MGUID[2] >> 19) & 255); \
|
||||
mac[2] = ((MGUID[0] >> 10) & 255) ^ ((MGUID[1] >> 10) & 255); \
|
||||
mac[3] = (MGUID[0] >> 19) & 255; \
|
||||
mac[4] = ((MGUID[1] >> 0) & 255) ^ ((MGUID[2] >> 10) & 255); \
|
||||
mac[5] = ((MGUID[2] >> 0) & 255) ^ ((MGUID[1] >> 19) & 255); \
|
||||
if (icache_enabled_) HAL_ICACHE_Enable(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -22,4 +22,12 @@
|
||||
|
||||
#define MG_PATH_MAX 128
|
||||
|
||||
#ifndef MG_ENABLE_POSIX_FS
|
||||
#define MG_ENABLE_POSIX_FS 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_DIRLIST
|
||||
#define MG_ENABLE_DIRLIST 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+8
-4
@@ -25,10 +25,11 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#define calloc(a, b) mg_calloc(a, b)
|
||||
#define free(a) vPortFree(a)
|
||||
#define malloc(a) pvPortMalloc(a)
|
||||
#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
|
||||
#define MG_ENABLE_CUSTOM_CALLOC 1
|
||||
|
||||
static inline void mg_free(void *ptr) {
|
||||
vPortFree(ptr);
|
||||
}
|
||||
|
||||
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||||
static inline void *mg_calloc(size_t cnt, size_t size) {
|
||||
@@ -37,10 +38,13 @@ static inline void *mg_calloc(size_t cnt, size_t size) {
|
||||
return p;
|
||||
}
|
||||
|
||||
#if !defined(MG_ENABLE_POSIX_FS) || !MG_ENABLE_POSIX_FS
|
||||
#else
|
||||
#define mkdir(a, b) mg_mkdir(a, b)
|
||||
static inline int mg_mkdir(const char *path, mode_t mode) {
|
||||
(void) path, (void) mode;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MG_ARCH == MG_ARCH_FREERTOS
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ARCH == MG_ARCH_THREADX
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Do not include time.h and stdlib.h, since they conflict with nxd_bsd.h
|
||||
// extern time_t time(time_t *);
|
||||
#include <nxd_bsd.h>
|
||||
|
||||
#define MG_DIRSEP '\\'
|
||||
#undef FOPEN_MAX
|
||||
|
||||
#ifndef MG_PATH_MAX
|
||||
#define MG_PATH_MAX 32
|
||||
#endif
|
||||
|
||||
#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
|
||||
#define MG_SOCK_LISTEN_BACKLOG_SIZE 3
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_IPV6
|
||||
#define MG_ENABLE_IPV6 0
|
||||
#endif
|
||||
|
||||
#define socklen_t int
|
||||
#define closesocket(x) soc_close(x)
|
||||
|
||||
// In order to enable BSD support in NetxDuo, do the following (assuming Cube):
|
||||
// 1. Add nxd_bsd.h and nxd_bsd.c to the repo:
|
||||
// https://github.com/eclipse-threadx/netxduo/blob/v6.1.12_rel/addons/BSD/nxd_bsd.c
|
||||
// https://github.com/eclipse-threadx/netxduo/blob/v6.1.12_rel/addons/BSD/nxd_bsd.h
|
||||
// 2. Add to tx_user.h
|
||||
// #define TX_THREAD_USER_EXTENSION int bsd_errno;
|
||||
// 3. Add to nx_user.h
|
||||
// #define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
|
||||
// 4. Add __CCRX__ build preprocessor constant
|
||||
// Project -> Properties -> C/C++ -> Settings -> MCU Compiler -> Preprocessor
|
||||
|
||||
#endif
|
||||
+13
-4
@@ -18,6 +18,17 @@
|
||||
#define _CRT_RAND_S
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||
#define _WIN32_WINNT 0x0400 // Let vc98 pick up wincrypt.h
|
||||
#else
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WINVER
|
||||
#define WINVER _WIN32_WINNT
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
@@ -45,6 +56,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <winsock2.h> // fix missing macros and types
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||
#define __func__ ""
|
||||
typedef __int64 int64_t;
|
||||
@@ -66,13 +79,9 @@ typedef enum { false = 0, true = 1 } bool;
|
||||
|
||||
#include <process.h>
|
||||
#include <winerror.h>
|
||||
#include <winsock2.h> // fix missing macros and types
|
||||
|
||||
// For mg_random()
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x400 // Let vc98 pick up wincrypt.h
|
||||
#endif
|
||||
#include <wincrypt.h>
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#if MG_ARCH == MG_ARCH_ZEPHYR
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/version.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
#define MG_ENABLE_LOG 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_CUSTOM_CALLOC
|
||||
#define MG_ENABLE_CUSTOM_CALLOC 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_CUSTOM_LOG
|
||||
#define MG_ENABLE_CUSTOM_LOG 0 // Let user define their own MG_LOG
|
||||
#endif
|
||||
@@ -182,3 +186,7 @@
|
||||
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
|
||||
#define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_CHACHA20
|
||||
#define MG_ENABLE_CHACHA20 1 // When set to 0, GCM is used. For MG_TLS_BUILTIN
|
||||
#endif
|
||||
@@ -18,7 +18,7 @@ static void mg_sendnsreq(struct mg_connection *, struct mg_str *, int,
|
||||
|
||||
static void mg_dns_free(struct dns_data **head, struct dns_data *d) {
|
||||
LIST_DELETE(struct dns_data, head, d);
|
||||
free(d);
|
||||
mg_free(d);
|
||||
}
|
||||
|
||||
void mg_resolve_cancel(struct mg_connection *c) {
|
||||
@@ -232,21 +232,26 @@ static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
||||
return mg_send(c, &pkt, sizeof(pkt.header) + n);
|
||||
}
|
||||
|
||||
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc);
|
||||
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc) {
|
||||
if (dnsc->url == NULL) {
|
||||
mg_error(0, "DNS server URL is NULL. Call mg_mgr_init()");
|
||||
return false;
|
||||
}
|
||||
if (dnsc->c == NULL) {
|
||||
dnsc->c = mg_connect(mgr, dnsc->url, NULL, NULL);
|
||||
if (dnsc->c == NULL) return false;
|
||||
dnsc->c->pfn = dns_cb;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
|
||||
struct mg_dns *dnsc, bool ipv6) {
|
||||
struct dns_data *d = NULL;
|
||||
if (dnsc->url == NULL) {
|
||||
mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()");
|
||||
} else if (dnsc->c == NULL) {
|
||||
dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL);
|
||||
if (dnsc->c != NULL) {
|
||||
dnsc->c->pfn = dns_cb;
|
||||
// dnsc->c->is_hexdumping = 1;
|
||||
}
|
||||
}
|
||||
if (dnsc->c == NULL) {
|
||||
if (!mg_dnsc_init(c->mgr, dnsc)) {
|
||||
mg_error(c, "resolver");
|
||||
} else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
|
||||
} else if ((d = (struct dns_data *) mg_calloc(1, sizeof(*d))) == NULL) {
|
||||
mg_error(c, "resolve OOM");
|
||||
} else {
|
||||
struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
|
||||
@@ -345,3 +350,4 @@ struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
|
||||
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
|
||||
return c;
|
||||
}
|
||||
|
||||
+330
-135
@@ -1,8 +1,16 @@
|
||||
#include "cyw.h"
|
||||
#include "net.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
((defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW) || \
|
||||
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO))
|
||||
|
||||
#ifndef MG_ENABLE_DRIVER_CYW
|
||||
#define MG_ENABLE_DRIVER_CYW 0
|
||||
#endif
|
||||
#ifndef MG_ENABLE_DRIVER_CYW_SDIO
|
||||
#define MG_ENABLE_DRIVER_CYW_SDIO 0
|
||||
#endif
|
||||
|
||||
static struct mg_tcpip_if *s_ifp;
|
||||
static bool s_link, s_auth, s_join;
|
||||
@@ -68,10 +76,12 @@ struct mg_tcpip_driver mg_tcpip_driver_cyw = {mg_tcpip_driver_cyw_init,
|
||||
// SPI | SDIO <-- padded to 32-bit | 64-bytes
|
||||
//
|
||||
// - SDPCM has 3 channels (control, data, and asynchronous data)
|
||||
// - SPI (and SDIO) has 4 "functions", F0 to F3, to access different
|
||||
// blocks in the chip, like the SPI/SDIO controller, chip backplane, and 2 DMA
|
||||
// I/Os; these are usually handled by SDPCM but we need to explicitly access
|
||||
// the I/O controller and chip backplane during initialization
|
||||
// - SPI has 4 "functions", F0 to F3, to access different blocks in the chip,
|
||||
// like the SPI/SDIO controller, chip backplane, and 2 DMA I/Os; these are
|
||||
// usually handled by SDPCM but we need to explicitly access the I/O controller
|
||||
// and chip backplane during initialization
|
||||
// - SDIO has 3 functions (proper SDIO terminology), F0 to F2, coincident with
|
||||
// those for SPI, accessed through standard SDIO practices. There is no F3.
|
||||
|
||||
// Processor core firmware is loaded to TCM RAM, along with module-dependent
|
||||
// (hardware design) NVRAM data, via the chip backplane access through the bus
|
||||
@@ -121,10 +131,15 @@ struct data_hdr {
|
||||
struct bdc_hdr bdc;
|
||||
};
|
||||
|
||||
// gSPI, DS 4.2.1 Fig.12, 2-bit field
|
||||
#define CYW_SD_FUNC_BUS 0 // F0
|
||||
#define CYW_SD_FUNC_CHIP 1 // F1
|
||||
#define CYW_SD_FUNC_WLAN 2 // F2
|
||||
// gSPI, CYW43439 DS 4.2.1 Fig.12, 2-bit field
|
||||
#define CYW_SPID_FUNC_BUS 0 // F0
|
||||
#define CYW_SPID_FUNC_CHIP 1 // F1
|
||||
#define CYW_SPID_FUNC_WLAN 2 // F2
|
||||
|
||||
// SDIO functions, 3-bit field; CYW4343W and CYW43439 DS 4.1
|
||||
#define CYW_SDIO_FUNC_BUS 0 // F0
|
||||
#define CYW_SDIO_FUNC_CHIP 1 // F1
|
||||
#define CYW_SDIO_FUNC_WLAN 2 // F2
|
||||
|
||||
#define CYW_SDPCM_CTRL_HDR 0
|
||||
#define CYW_SDPCM_ASYNC_HDR 1
|
||||
@@ -139,7 +154,7 @@ static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len);
|
||||
static void cyw_handle_bdc(struct bdc_hdr *bdc, size_t len);
|
||||
static void cyw_handle_bdc_evnt(struct bdc_hdr *bdc, size_t len);
|
||||
|
||||
static size_t cyw_spi_poll(uint8_t *dest);
|
||||
static size_t cyw_bus_specific_poll(uint32_t *dest);
|
||||
static void cyw_update_hash_table(void);
|
||||
|
||||
// High-level comm stuff
|
||||
@@ -152,7 +167,7 @@ static void cyw_poll(void) {
|
||||
cyw_update_hash_table();
|
||||
s_ifp->update_mac_hash_table = false;
|
||||
}
|
||||
if (cyw_spi_poll((uint8_t *) resp) == 0) return; // BUS DEPENDENCY
|
||||
if (cyw_bus_specific_poll(resp) == 0) return;
|
||||
if ((sdpcm->len ^ sdpcm->_len) != 0xffff || sdpcm->len < sizeof(*sdpcm) ||
|
||||
sdpcm->len > 2048 - sizeof(*sdpcm))
|
||||
return;
|
||||
@@ -185,7 +200,7 @@ static void cyw_handle_bdc(struct bdc_hdr *bdc, size_t len) {
|
||||
mg_tcpip_qwrite(payload, len - (payload - (uint8_t *) bdc), s_ifp);
|
||||
}
|
||||
|
||||
static size_t cyw_bus_tx(uint32_t *data, uint16_t len);
|
||||
static size_t cyw_bus_specific_tx(uint32_t *data, uint16_t len);
|
||||
|
||||
// WLAN frame transmission
|
||||
static size_t mg_cyw_tx(unsigned int ifc, void *data, size_t len) {
|
||||
@@ -194,15 +209,15 @@ static size_t mg_cyw_tx(unsigned int ifc, void *data, size_t len) {
|
||||
memset(txdata, 0, sizeof(*hdr));
|
||||
memcpy((uint8_t *) txdata + sizeof(*hdr), data, len);
|
||||
// TODO(): hdr->bdc.priority = map IP to TOS if supporting QoS/ToS
|
||||
hdr->bdc.flags = 2 << 4; // BDC version 2
|
||||
hdr->bdc.flags2 = ifc; // 0 -> STA, 1 -> AP
|
||||
hdr->bdc.flags = 2 << 4; // BDC version 2
|
||||
hdr->bdc.flags2 = (uint8_t) ifc; // 0 -> STA, 1 -> AP
|
||||
// hdr->bdc.data_offset = 0; // actually zeroed above
|
||||
hdr->sdpcm.len = txlen;
|
||||
hdr->sdpcm._len = (uint16_t) ~txlen;
|
||||
hdr->sdpcm.sw_hdr.sequence = ++s_tx_seqno;
|
||||
hdr->sdpcm.sw_hdr.channel_and_flags = CYW_SDPCM_DATA_HDR,
|
||||
hdr->sdpcm.sw_hdr.header_length = offsetof(struct data_hdr, bdc);
|
||||
return cyw_bus_tx(txdata, txlen);
|
||||
return cyw_bus_specific_tx(txdata, txlen);
|
||||
}
|
||||
|
||||
// WLAN event handling
|
||||
@@ -250,6 +265,7 @@ struct scan_result;
|
||||
static void cyw_handle_scan_result(uint32_t status, struct scan_result *data,
|
||||
size_t len);
|
||||
|
||||
// Do not call any IOCTL functions here, otherwise revise cyw_ioctl_wait()
|
||||
static void cyw_handle_bdc_evnt(struct bdc_hdr *bdc, size_t len) {
|
||||
struct evnt_msg *msg = (struct evnt_msg *) &bdc[bdc->data_offset + 1];
|
||||
MG_VERBOSE(("%u bytes event", len));
|
||||
@@ -313,7 +329,7 @@ static bool cyw_ioctl_iovar_set_(unsigned int ifc, char *var, void *data,
|
||||
size_t len);
|
||||
// clang-format off
|
||||
// convenience: ioctl funcs on default ifc (0), as only AP needs ifc 1
|
||||
static bool cyw_ioctl_get(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_get_(0, cmd, data, len); }
|
||||
__attribute__((unused)) static bool cyw_ioctl_get(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_get_(0, cmd, data, len); }
|
||||
static bool cyw_ioctl_set(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_set_(0, cmd, data, len); }
|
||||
static bool cyw_ioctl_iovar_get(char *var, void *data, size_t len) { return cyw_ioctl_iovar_get_(0, var, data, len); }
|
||||
static bool cyw_ioctl_iovar_set(char *var, void *data, size_t len) { return cyw_ioctl_iovar_set_(0, var, data, len); }
|
||||
@@ -324,9 +340,10 @@ static bool cyw_ioctl_iovar_set(char *var, void *data, size_t len) { return cyw_
|
||||
// clang-format off
|
||||
static bool cyw_wifi_connect(char *ssid, char *pass) {
|
||||
uint32_t sup_wpa[2] = {0, 1}; // bss index 0 = STA, not open
|
||||
static const uint32_t const eapver[2] = {0, (uint32_t) -1}, // accept AP version
|
||||
static const uint32_t eapver[2] = {0, (uint32_t) -1}, // accept AP version
|
||||
tmo[2] = {0, 2500};
|
||||
uint32_t data[64/4 + 1]; // max pass length: 64 for WPA, 128 for WPA3 SAE
|
||||
uint16_t *da = (uint16_t *) data;
|
||||
unsigned int len;
|
||||
uint32_t val;
|
||||
val = 4; // security type: 0 for none, 2 for WPA, 4 for WPA2/WPA3, 6 for mixed WPA/WPA2
|
||||
@@ -340,8 +357,8 @@ static bool cyw_wifi_connect(char *ssid, char *pass) {
|
||||
// skip if not using auth
|
||||
memset(data, 0, sizeof(data));
|
||||
len = strlen(pass);
|
||||
((uint16_t *)data)[0] = (uint16_t) len;
|
||||
((uint16_t *)data)[1] = 1; // indicates wireless security key, skip for WPA3 SAE
|
||||
da[0] = (uint16_t) len;
|
||||
da[1] = 1; // indicates wireless security key, skip for WPA3 SAE
|
||||
memcpy((uint8_t *)data + 2 * sizeof(uint16_t), pass, len); // skip for WPA3 SAE
|
||||
if (!cyw_ioctl_set(268 /* SET_WSEC_PMK */, data, sizeof(data))) return false; // skip for WPA3 SAE, sizeof/2 if supporting SAE but using WPA
|
||||
// for WPA3 SAE: memcpy((uint8_t *)data + sizeof(uint16_t), pass, len); cyw_ioctl_iovar_set("sae_password", data, sizeof(data));
|
||||
@@ -368,6 +385,7 @@ static bool cyw_wifi_disconnect(void) {
|
||||
|
||||
static bool cyw_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
|
||||
uint32_t data[64/4 + 2]; // max pass length: 64 for WPA, 128 for WPA3 SAE
|
||||
uint16_t *da = (uint16_t *) data;
|
||||
unsigned int len;
|
||||
uint32_t val;
|
||||
// CHIP DEPENDENCY
|
||||
@@ -394,8 +412,8 @@ static bool cyw_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
|
||||
// NOTE(): WHD does not set SAE password for shared WPA2/WPA3, same do we
|
||||
memset(data, 0, sizeof(data));
|
||||
len = strlen(pass);
|
||||
((uint16_t *)data)[0] = (uint16_t) len; // skip for WPA3 SAE
|
||||
((uint16_t *)data)[1] = 1; // indicates wireless security key, skip for WPA3 SAE
|
||||
da[0] = (uint16_t) len; // skip for WPA3 SAE (43430 does NOT support WPA3 in AP)
|
||||
da[1] = 1; // indicates wireless security key, skip for WPA3 SAE
|
||||
memcpy((uint8_t *)data + 2 * sizeof(uint16_t), pass, len); // skip for WPA3 SAE
|
||||
if (!cyw_ioctl_set_(1, 268 /* SET_WSEC_PMK */, data, sizeof(data))) return false; // skip for WPA3 SAE, sizeof/2 if supporting SAE but using WPA
|
||||
/* for WPA3 SAE:
|
||||
@@ -539,8 +557,8 @@ static void cyw_handle_scan_result(uint32_t status, struct scan_result *data, si
|
||||
if (sbss->length > len - offsetof(struct scan_result, bss) || sbss->SSID_len > sizeof(sbss->SSID) || sbss->ie_offset < sizeof(*sbss) || sbss->ie_offset > (sizeof(*sbss) + sbss->ie_length) || sbss->ie_offset + sbss->ie_length > sbss->length)
|
||||
return; // silently discard malformed data
|
||||
if (!(sbss->flags & MG_BIT(2))) return; // RSSI_ONCHANNEL, ignore off-channel results
|
||||
bss.SSID = mg_str_n(sbss->SSID, sbss->SSID_len);
|
||||
bss.BSSID = sbss->BSSID;
|
||||
bss.SSID = mg_str_n((char *)sbss->SSID, sbss->SSID_len);
|
||||
bss.BSSID = (char *)sbss->BSSID;
|
||||
bss.RSSI = (int8_t)sbss->RSSI;
|
||||
bss.has_n = sbss->n_cap != 0;
|
||||
bss.channel = bss.has_n ? sbss->ctl_ch : (uint8_t)(sbss->chanspec & 0xff); // n 40MHz vs a/b/g and 20MHz
|
||||
@@ -575,7 +593,7 @@ static uint8_t *s_ioctl_resp;
|
||||
static bool s_ioctl_err;
|
||||
|
||||
static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len) {
|
||||
uint8_t *resp = (uint8_t *) cdc + sizeof(*cdc);
|
||||
uint8_t *r = (uint8_t *) cdc + sizeof(*cdc);
|
||||
MG_VERBOSE(("%u bytes CDC frame", len));
|
||||
if ((cdc->flags >> 16) != s_ioctl_reqid) return;
|
||||
if (cdc->flags & 1) {
|
||||
@@ -584,9 +602,8 @@ static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len) {
|
||||
return;
|
||||
}
|
||||
if (mg_log_level >= MG_LL_VERBOSE) mg_hexdump((void *) cdc, len);
|
||||
MG_DEBUG(("IOCTL result: %02x %02x %02x %02x ...", resp[0], resp[1], resp[2],
|
||||
resp[3]));
|
||||
s_ioctl_resp = resp;
|
||||
MG_DEBUG(("IOCTL result: %02x %02x %02x %02x ...", r[0], r[1], r[2], r[3]));
|
||||
s_ioctl_resp = r;
|
||||
}
|
||||
// NOTE(): alt no loop handler dispatching IOCTL response to current handler:
|
||||
// static void *s_ioctl_hnd; *s_ioctl_hnd(ioctl, len);
|
||||
@@ -618,7 +635,7 @@ static void cyw_ioctl_send_cmd(unsigned int ifc, unsigned int cmd, bool set,
|
||||
hdr->sdpcm.sw_hdr.sequence = ++s_tx_seqno;
|
||||
hdr->sdpcm.sw_hdr.channel_and_flags = CYW_SDPCM_CTRL_HDR;
|
||||
hdr->sdpcm.sw_hdr.header_length = offsetof(struct ctrl_hdr, cdc);
|
||||
cyw_bus_tx(txdata, txlen);
|
||||
cyw_bus_specific_tx(txdata, txlen);
|
||||
}
|
||||
|
||||
// just send respective commands, response handled via CDC handler
|
||||
@@ -652,20 +669,29 @@ static void cyw_ioctl_send_iovar_set2(unsigned int ifc, char *var, void *data1,
|
||||
cyw_ioctl_send_cmd(ifc, 263, true, txlen); // cmd = SET IOVAR
|
||||
}
|
||||
|
||||
static void cyw_ioctl_send_iovar_set(unsigned int ifc, char *var, void *data,
|
||||
size_t len) {
|
||||
__attribute__((unused)) static void cyw_ioctl_send_iovar_set(unsigned int ifc,
|
||||
char *var,
|
||||
void *data,
|
||||
size_t len) {
|
||||
cyw_ioctl_send_iovar_set2(ifc, var, data, len, NULL, 0);
|
||||
}
|
||||
|
||||
static inline bool delayms(unsigned int ms) {
|
||||
mg_delayms(ms);
|
||||
return true;
|
||||
}
|
||||
|
||||
// wait for a response, meanwhile delivering received frames and events
|
||||
static bool cyw_ioctl_wait(void) {
|
||||
unsigned int times = 6000;
|
||||
unsigned int times = 100;
|
||||
s_ioctl_resp = NULL;
|
||||
s_ioctl_err = false;
|
||||
while (s_ioctl_resp == NULL && !s_ioctl_err && times-- > 0)
|
||||
cyw_poll(); // TODO(scaprile): review wait/sleep strategy (this loop is executed only when initializing/acting on the chip)
|
||||
MG_DEBUG(("resp: %lp, err: %c, times: %d", s_ioctl_resp,
|
||||
s_ioctl_err ? '1' : '0', (int) times));
|
||||
do { // IOCTL response processing does not call any other IOCTL function
|
||||
cyw_poll(); // otherwise we can't allow them to pile up here
|
||||
// network frames will be pushed to the queue so that is safe
|
||||
} while (s_ioctl_resp == NULL && !s_ioctl_err && times-- > 0 && delayms(1));
|
||||
MG_VERBOSE(("resp: %lp, err: %c, times: %d", s_ioctl_resp,
|
||||
s_ioctl_err ? '1' : '0', (int) times));
|
||||
return s_ioctl_resp != NULL;
|
||||
}
|
||||
|
||||
@@ -723,15 +749,22 @@ struct clm_hdr {
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// worlwide rev0, try rev 17 for 4343W
|
||||
// worlwide rev0, TODO(): try rev 17 for 4343W
|
||||
static const uint32_t country_code = 'X' + ('X' << 8) + (0 << 16);
|
||||
|
||||
static bool cyw_spi_init();
|
||||
static bool cyw_bus_specific_init();
|
||||
static bool cyw_load_clmll(void *data, size_t len);
|
||||
|
||||
static bool cyw_load_clm(struct mg_tcpip_driver_cyw_firmware *fw) {
|
||||
return cyw_load_clmll((void *) fw->clm_addr, fw->clm_len);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static bool cyw_init(uint8_t *mac) {
|
||||
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
uint32_t val = 0;
|
||||
if (!cyw_spi_init()) return false; // BUS DEPENDENCY
|
||||
if (!cyw_bus_specific_init()) return false;
|
||||
if (!cyw_load_clm(d->fw)) return false; // Load CLM blob
|
||||
// BT-ENABLED DEPENDENCY
|
||||
// set Wi-Fi up
|
||||
val = 0 /* disable */; cyw_ioctl_iovar_set("bus:txglom", (uint8_t *)&val, sizeof(val));
|
||||
@@ -759,7 +792,7 @@ static bool cyw_init(uint8_t *mac) {
|
||||
unsigned int times = 100;
|
||||
while (times --)
|
||||
if (cyw_ioctl_iovar_set("bsscfg:event_msgs", (uint8_t *)data, sizeof(data))) break;
|
||||
if (times == ~0) return false;
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
}
|
||||
val = 0; if (!cyw_ioctl_set(64 /* SET_ANTDIV */, (uint8_t *)&val, sizeof(val))) return false;
|
||||
if (!cyw_ioctl_set(2 /* UP, interface up */, NULL, 0)) return false;
|
||||
@@ -818,20 +851,18 @@ static bool cyw_load_clmll(void *data, size_t len) {
|
||||
break;
|
||||
sent += bytes;
|
||||
offset += bytes;
|
||||
hdr.flag &= ~MG_BIT(1); // DL_BEGIN
|
||||
hdr.flag &= (uint16_t)~MG_BIT(1); // DL_BEGIN
|
||||
}
|
||||
return sent >= len;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
static bool cyw_load_clm(struct mg_tcpip_driver_cyw_firmware *fw) {
|
||||
return cyw_load_clmll((void *) fw->clm_addr, fw->clm_len);
|
||||
}
|
||||
|
||||
static void cyw_update_hash_table(void) {
|
||||
// TODO(): read database, rebuild hash table
|
||||
uint32_t val = 0;
|
||||
val = 1; cyw_ioctl_iovar_set2_(0, "mcast_list", (uint8_t *)&val, sizeof(val), (uint8_t *)mcast_addr, sizeof(mcast_addr));
|
||||
val = 1;
|
||||
cyw_ioctl_iovar_set2_(0, "mcast_list", (uint8_t *) &val, sizeof(val),
|
||||
(uint8_t *) mcast_addr, sizeof(mcast_addr));
|
||||
mg_delayms(50);
|
||||
}
|
||||
|
||||
@@ -848,8 +879,16 @@ static void cyw_update_hash_table(void) {
|
||||
#define CYW_CHIP_BCKPLN_ADDRMSK 0x7fff
|
||||
#define CYW_CHIP_BCKPLN_ACCSS4B MG_BIT(15)
|
||||
#define CYW_CHIP_BCKPLN_WRAPPOFF 0x100000
|
||||
// BUS DEPENDENCY: max bus to backplane transfer size, bus function id
|
||||
#define CYW_CHIP_BCKPLN_SPIMAX 64
|
||||
#define CYW_CHIP_BCKPLN_SDIOMAX 1536
|
||||
#if MG_ENABLE_DRIVER_CYW_SDIO
|
||||
#define CYW_CHIP_BCKPLN_BUSMAX CYW_CHIP_BCKPLN_SDIOMAX
|
||||
#define CYW_BUS_FUNC_CHIP CYW_SDIO_FUNC_CHIP
|
||||
#else
|
||||
#define CYW_CHIP_BCKPLN_BUSMAX CYW_CHIP_BCKPLN_SPIMAX
|
||||
#define CYW_BUS_FUNC_CHIP CYW_SPID_FUNC_CHIP
|
||||
#endif
|
||||
|
||||
// CHIP DEPENDENCY
|
||||
#define CYW_CHIP_ARMCORE_BASE (CYW_CHIP_CHIPCOMMON + 0x3000)
|
||||
@@ -874,9 +913,9 @@ static void cyw_update_hash_table(void) {
|
||||
#define CYW_CHIP_AI_IOCTRL 0x408
|
||||
#define CYW_CHIP_AI_RESETCTRL 0x800
|
||||
|
||||
static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
|
||||
static bool cyw_bus_write(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len);
|
||||
static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
|
||||
static bool cyw_bus_read(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len);
|
||||
|
||||
// clang-format off
|
||||
@@ -884,9 +923,9 @@ static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
|
||||
static void cyw_set_backplane_window(uint32_t addr) {
|
||||
uint32_t val;
|
||||
addr &= ~CYW_CHIP_BCKPLN_ADDRMSK;
|
||||
val = (addr >> 24) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRHIGH, &val, 1);
|
||||
val = (addr >> 16) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRMID, &val, 1);
|
||||
val = (addr >> 8) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRLOW, &val, 1);
|
||||
val = (addr >> 24) & 0xff; cyw_bus_write(CYW_BUS_FUNC_CHIP, CYW_CHIP_ADDRHIGH, &val, 1);
|
||||
val = (addr >> 16) & 0xff; cyw_bus_write(CYW_BUS_FUNC_CHIP, CYW_CHIP_ADDRMID, &val, 1);
|
||||
val = (addr >> 8) & 0xff; cyw_bus_write(CYW_BUS_FUNC_CHIP, CYW_CHIP_ADDRLOW, &val, 1);
|
||||
}
|
||||
|
||||
static bool cyw_core_reset(uint32_t core_base, bool check) {
|
||||
@@ -894,21 +933,21 @@ static bool cyw_core_reset(uint32_t core_base, bool check) {
|
||||
// core disabled after chip reset
|
||||
cyw_set_backplane_window(core_base); // set backplane window for requested area; we do know offsets fall within that window
|
||||
// possible CHIP DEPENDENCY: AI_RESETSTATUS check and wait (instead of these cool reads) to ensure backplane operations end
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
|
||||
val = MG_BIT(1) | MG_BIT(0) /* SICF_FGC | SICF_CLOCK_EN */; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // reset
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
|
||||
val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // release reset
|
||||
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
|
||||
val = MG_BIT(1) | MG_BIT(0) /* SICF_FGC | SICF_CLOCK_EN */; cyw_bus_write(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // reset
|
||||
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
|
||||
val = 0x00; cyw_bus_write(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // release reset
|
||||
mg_delayms(1);
|
||||
val = MG_BIT(0) /* SICF_CLOCK_EN */; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
|
||||
val = MG_BIT(0) /* SICF_CLOCK_EN */; cyw_bus_write(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
|
||||
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
|
||||
mg_delayms(1);
|
||||
|
||||
if (check) {
|
||||
// Verify only clock is enabled
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
|
||||
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
|
||||
if ((val & (MG_BIT(1) | MG_BIT(0)) /* SICF_FGC | SICF_CLOCK_EN) */) != MG_BIT(0)) return false;
|
||||
// Verify it is not in reset state
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
|
||||
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
|
||||
if (val & MG_BIT(0)) return false; // AIRC_RESET
|
||||
}
|
||||
return true;
|
||||
@@ -916,29 +955,28 @@ static bool cyw_core_reset(uint32_t core_base, bool check) {
|
||||
|
||||
static void cyw_socram_init(void) {
|
||||
uint32_t val;
|
||||
// CHIP DEPENDENCY: disable remap for SRAM_3
|
||||
// CHIP DEPENDENCY: disable remap for SRAM_3: 43430 and 43439 only
|
||||
cyw_set_backplane_window(CYW_CHIP_SOCSRAM_BASE); // set backplane window for requested area; we do know offsets fall within that window
|
||||
val = 0x03; cyw_spi_write(CYW_SD_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXIDX) & CYW_CHIP_BCKPLN_ADDRMSK) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
|
||||
val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXPDA) & CYW_CHIP_BCKPLN_ADDRMSK) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
|
||||
val = 0x03; cyw_bus_write(CYW_BUS_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXIDX) & CYW_CHIP_BCKPLN_ADDRMSK), &val, sizeof(val));
|
||||
val = 0x00; cyw_bus_write(CYW_BUS_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXPDA) & CYW_CHIP_BCKPLN_ADDRMSK), &val, sizeof(val));
|
||||
}
|
||||
|
||||
// transfer is fractioned in bus-to-backplane-size units within backplane windows
|
||||
static void cyw_load_data(uint32_t dest, void *data, size_t len) {
|
||||
size_t sent = 0, offset = 0;
|
||||
uint32_t last_addr = ~0;
|
||||
uint32_t last_addr = (uint32_t) ~0;
|
||||
while (sent < len) {
|
||||
size_t bytes = len - sent, avail;
|
||||
uint32_t addr = dest + offset;
|
||||
if (addr - last_addr >= CYW_CHIP_BCKPLN_WINSZ || last_addr == ~0) {
|
||||
if (addr - last_addr >= CYW_CHIP_BCKPLN_WINSZ || last_addr == (uint32_t) ~0) {
|
||||
cyw_set_backplane_window(addr); // set backplane window for requested area
|
||||
last_addr = addr & ~CYW_CHIP_BCKPLN_ADDRMSK;
|
||||
}
|
||||
addr &= CYW_CHIP_BCKPLN_ADDRMSK;
|
||||
avail = CYW_CHIP_BCKPLN_WINSZ - (unsigned int) addr;
|
||||
avail = CYW_CHIP_BCKPLN_WINSZ - (unsigned int) addr; // internal backplane limit
|
||||
if (bytes > avail) bytes = avail;
|
||||
// BUS DEPENDENCY: max bus to backplane transfer size
|
||||
if (bytes > CYW_CHIP_BCKPLN_SPIMAX) bytes = CYW_CHIP_BCKPLN_SPIMAX;
|
||||
cyw_spi_write(CYW_SD_FUNC_CHIP, addr | CYW_CHIP_BCKPLN_ACCSS4B, (uint8_t *)data + offset, bytes);
|
||||
if (bytes > CYW_CHIP_BCKPLN_BUSMAX) bytes = CYW_CHIP_BCKPLN_BUSMAX; // bus to backplane transfer limit
|
||||
cyw_bus_write(CYW_BUS_FUNC_CHIP, addr, (uint8_t *)data + offset, (uint16_t) bytes);
|
||||
sent += bytes;
|
||||
offset += bytes;
|
||||
}
|
||||
@@ -950,13 +988,13 @@ static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nv
|
||||
cyw_core_reset(CYW_CHIP_SOCSRAM, false); // cores were disabled at chip reset
|
||||
cyw_socram_init();
|
||||
cyw_load_data(CYW_CHIP_ATCMRAM_BASE, fwdata, fwlen);
|
||||
mg_delayms(5); // ************ CHECK IF THIS IS ACTUALLY NEEDED
|
||||
mg_delayms(5); // TODO(scaprile): CHECK IF THIS IS ACTUALLY NEEDED
|
||||
// Load NVRAM and place 'length ~length' at the end; end of chip RAM
|
||||
{
|
||||
const uint32_t start = CYW_CHIP_RAM_SIZE - 4 - nvramlen;
|
||||
cyw_load_data(start, nvramdata, nvramlen); // nvramlen must be a multiple of 4
|
||||
// RAM_SIZE is a multiple of WINSZ, so the place for len ~len will be at the end of the window
|
||||
cyw_spi_write(CYW_SD_FUNC_CHIP, (CYW_CHIP_BCKPLN_WINSZ - 4) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
|
||||
cyw_bus_write(CYW_BUS_FUNC_CHIP, (CYW_CHIP_BCKPLN_WINSZ - 4), &val, sizeof(val));
|
||||
}
|
||||
// Reset ARM core and check it starts
|
||||
if (!cyw_core_reset(CYW_CHIP_ARMCORE, true)) return false;
|
||||
@@ -964,6 +1002,8 @@ static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nv
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
#if !MG_ENABLE_DRIVER_CYW_SDIO
|
||||
|
||||
// CYW43 SPI bus specifics
|
||||
|
||||
#define CYW_BUS_SPI_BUSCTRL 0x00 // 4 regs, 0 to 3
|
||||
@@ -975,29 +1015,33 @@ static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nv
|
||||
|
||||
#define CYW_BUS_STS_LEN(x) ((x >> 9) & 0x7ff)
|
||||
|
||||
static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len);
|
||||
static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len);
|
||||
|
||||
// clang-format off
|
||||
static size_t cyw_spi_poll(uint8_t *response) {
|
||||
size_t len;
|
||||
uint32_t res;
|
||||
// SPI poll
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &res, sizeof(res));
|
||||
if (res == ~0 || !(res & MG_BIT(8) /* packet available */ )) return 0;
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_STATUS, &res, sizeof(res));
|
||||
if (res == (uint32_t) ~0 || !(res & MG_BIT(8) /* packet available */ )) return 0;
|
||||
len = CYW_BUS_STS_LEN(res);
|
||||
if (len == 0) { // just ack IRQ
|
||||
uint16_t val = 1;
|
||||
cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_SPIFRCTRL, &val, 1);
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
|
||||
cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
|
||||
cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_SPIFRCTRL, &val, 1);
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
|
||||
cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
|
||||
return 0;
|
||||
}
|
||||
cyw_spi_read(CYW_SD_FUNC_WLAN, 0, response, len);
|
||||
cyw_spi_read(CYW_SPID_FUNC_WLAN, 0, response, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
// BUS DEPENDENCY: name is generic but function is bus dependent
|
||||
static size_t cyw_bus_tx(uint32_t *data, uint16_t len) {
|
||||
while (len & 3) data[len++] = 0; // SPI 32-bit padding (SDIO->64-byte)
|
||||
return cyw_spi_write(CYW_SD_FUNC_WLAN, 0, data, len) ? len: 0;
|
||||
static size_t cyw_spi_tx(uint32_t *data, uint16_t len) {
|
||||
while (len & 3) data[len++] = 0; // SPI 32-bit padding
|
||||
return cyw_spi_write(CYW_SPID_FUNC_WLAN, 0, data, len) ? len: 0;
|
||||
}
|
||||
|
||||
// this can be integrated in lowest level SPI read/write _driver_ functions
|
||||
@@ -1007,20 +1051,19 @@ uint32_t sw16_2(uint32_t data) {
|
||||
}
|
||||
|
||||
// DS 4.2.2 Table 6: signal we're working in 16-bit mode
|
||||
#define CYW_SD_16bMODE MG_BIT(2) // arbitrary bit out of the FUNC space
|
||||
#define CYW_SPI_16bMODE MG_BIT(2) // arbitrary bit out of the FUNC space
|
||||
|
||||
static bool cyw_spi_init() {
|
||||
struct mg_tcpip_driver_cyw_data *d =
|
||||
(struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
uint32_t val = 0;
|
||||
// DS 4.2.3 Boot-Up Sequence; WHD: other chips might require more effort
|
||||
unsigned int times = 51;
|
||||
while (times--) {
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS | CYW_SD_16bMODE, CYW_BUS_SPI_TEST, &val, sizeof(val));
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS | CYW_SPI_16bMODE, CYW_BUS_SPI_TEST, &val, sizeof(val));
|
||||
if (sw16_2(val) == 0xFEEDBEAD) break;
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == ~0) return false;
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
// DS 4.2.3 Table 6. Chip starts in 16-bit little-endian mode.
|
||||
// Configure SPI and switch to 32-bit big-endian mode:
|
||||
// - High-speed mode: d->hs true
|
||||
@@ -1028,33 +1071,34 @@ static bool cyw_spi_init() {
|
||||
// - SPI RESPONSE DELAY 4 bytes time [not in DS] TODO(scaprile): logic ana
|
||||
// - Status not sent after command, IRQ with status
|
||||
val = sw16_2(0x000204a3 | (d->hs ? MG_BIT(4) : 0)); // 4 reg content
|
||||
cyw_spi_write(CYW_SD_FUNC_BUS | CYW_SD_16bMODE, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
|
||||
cyw_spi_write(CYW_SPID_FUNC_BUS | CYW_SPI_16bMODE, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
|
||||
mg_tcpip_call(s_ifp, MG_TCPIP_EV_DRIVER, NULL);
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_TEST, &val, sizeof(val));
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_TEST, &val, sizeof(val));
|
||||
if (val != 0xFEEDBEAD) return false;
|
||||
val = 4; cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_RESPDLY_F1, &val, 1);
|
||||
val = 4; cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_RESPDLY_F1, &val, 1);
|
||||
val = 0x99; // clear error bits DATA_UNAVAILABLE, COMMAND_ERROR, DATA_ERROR, F1_OVERFLOW
|
||||
cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, 1);
|
||||
cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INT, &val, 1);
|
||||
val = 0x00be; // Enable IRQs F2_F3_FIFO_RD_UNDERFLOW, F2_F3_FIFO_WR_OVERFLOW, COMMAND_ERROR, DATA_ERROR, F2_PACKET_AVAILABLE, F1_OVERFLOW
|
||||
// BT-ENABLED DEPENDENCY: add F1_INTR (bit 13)
|
||||
cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
|
||||
cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
|
||||
|
||||
// chip backplane is ready, initialize it
|
||||
// request ALP (Active Low Power) clock
|
||||
val = MG_BIT(3) /* ALP_REQ */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
val = MG_BIT(3) /* ALP_REQ */; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
// BT-ENABLED DEPENDENCY
|
||||
times = 10;
|
||||
while (times--) {
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
if (val & MG_BIT(6)) break; // ALP_AVAIL
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == ~0) return false;
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
// clear request
|
||||
val = 0; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
val = 0; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
cyw_set_backplane_window(CYW_CHIP_CHIPCOMMON); // set backplane window to start of CHIPCOMMON area
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
|
||||
MG_INFO(("WLAN chip is CYW%u", *((uint16_t *)&val)));
|
||||
cyw_spi_read(CYW_SPID_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
|
||||
if (val == 43430) val = 4343;
|
||||
MG_INFO(("WLAN chip is CYW%u%c", val), val == 4343 ? 'W' : ' '));
|
||||
|
||||
// Load firmware (code and NVRAM)
|
||||
if (!cyw_load_firmware(d->fw)) return false;
|
||||
@@ -1062,77 +1106,74 @@ static bool cyw_spi_init() {
|
||||
// Wait for High Throughput (HT) clock ready
|
||||
times = 50;
|
||||
while (times--) {
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
if (val & MG_BIT(7)) break; // HT_AVAIL
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == ~0) return false;
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
// Wait for backplane ready
|
||||
times = 1000;
|
||||
while (times--) {
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
|
||||
if (val & MG_BIT(5)) break; // F2_RX_READY
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == ~0) return false;
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
|
||||
// CHIP DEPENDENCY
|
||||
// Enable save / restore
|
||||
// Configure WakeupCtrl, set HT_AVAIL in CLOCK_CSR
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
|
||||
val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
|
||||
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
|
||||
val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
|
||||
#if 0
|
||||
// Set BRCM_CARDCAP to CMD_NODEC. NOTE(): This is probably only necessary for SDIO, not SPI
|
||||
val = MG_BIT(3); cyw_spi_write(CYW_SD_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
|
||||
val = MG_BIT(3); cyw_spi_write(CYW_SPID_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
|
||||
#endif
|
||||
// Force HT request to chip backplane
|
||||
val = MG_BIT(1) /* FORCE_HT */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
val = MG_BIT(1) /* FORCE_HT */; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
// Enable Keep SDIO On (KSO)
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
|
||||
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
|
||||
if (!(val & MG_BIT(0))) {
|
||||
val |= MG_BIT(0); cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
|
||||
val |= MG_BIT(0); cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
|
||||
}
|
||||
// The SPI bus can be configured for sleep (KSO controls wlan block sleep)
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
|
||||
val &= ~MG_BIT(7) /* WAKE_UP */; cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
|
||||
val &= ~MG_BIT(7) /* WAKE_UP */; cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
|
||||
// Set SPI bus sleep
|
||||
val = 0x0f; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
val = 0x0f; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
|
||||
// Clear pullups. NOTE(): ?
|
||||
val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
val = 0x00; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
// Clear possible data unavailable error
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
|
||||
if (val & MG_BIT(0)) cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
|
||||
|
||||
// Load CLM blob
|
||||
if (!cyw_load_clm(d->fw)) return false;
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
|
||||
if (val & MG_BIT(0)) cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
|
||||
|
||||
return true;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
// gSPI, DS 4.2.1 Fig.12
|
||||
#define CYW_SD_LEN(x) ((x) &0x7FF) // bits 0-10
|
||||
#define CYW_SD_ADDR(x) (((x) &0x1FFFF) << 11) // bits 11-27,
|
||||
#define CYW_SD_FUNC(x) (((x) &3) << 28) // bits 28-29
|
||||
#define CYW_SD_INC MG_BIT(30)
|
||||
#define CYW_SD_WR MG_BIT(31)
|
||||
// gSPI, CYW43439 DS 4.2.1 Fig.12
|
||||
#define CYW_SPID_LEN(x) ((x) &0x7FF) // bits 0-10
|
||||
#define CYW_SPID_ADDR(x) (((x) &0x1FFFF) << 11) // bits 11-27,
|
||||
#define CYW_SPID_FUNC(x) (((x) &3) << 28) // bits 28-29
|
||||
#define CYW_SPID_INC MG_BIT(30)
|
||||
#define CYW_SPID_WR MG_BIT(31)
|
||||
|
||||
static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len) {
|
||||
struct mg_tcpip_driver_cyw_data *d =
|
||||
(struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->spi;
|
||||
uint32_t hdr = CYW_SD_WR | CYW_SD_INC | CYW_SD_FUNC(f) | CYW_SD_ADDR(addr) |
|
||||
CYW_SD_LEN(len); // gSPI header
|
||||
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->bus;
|
||||
uint32_t hdr = CYW_SPID_WR | CYW_SPID_INC | CYW_SPID_FUNC(f) |
|
||||
CYW_SPID_ADDR(addr) | CYW_SPID_LEN(len); // gSPI header
|
||||
// TODO(scaprile): check spin in between and timeout values, return false
|
||||
if (f == CYW_SD_FUNC_WLAN) {
|
||||
if (f == CYW_SPID_FUNC_WLAN) {
|
||||
uint32_t val = 0;
|
||||
while ((val & MG_BIT(5)) != MG_BIT(5)) // F2 rx ready (FIFO ready)
|
||||
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
|
||||
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
|
||||
}
|
||||
if (f & CYW_SD_16bMODE)
|
||||
if (f & CYW_SPI_16bMODE)
|
||||
hdr = sw16_2(hdr); // swap half-words in 16-bit little-endian mode
|
||||
|
||||
s->begin(NULL);
|
||||
@@ -1148,26 +1189,26 @@ static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
|
||||
return true;
|
||||
}
|
||||
|
||||
// will write 32-bit aligned quantities to data if f == CYW_SD_FUNC_WLAN
|
||||
// will write 32-bit aligned quantities to data if f == CYW_SPID_FUNC_WLAN
|
||||
static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len) {
|
||||
struct mg_tcpip_driver_cyw_data *d =
|
||||
(struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->spi;
|
||||
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->bus;
|
||||
uint32_t padding =
|
||||
f == CYW_SD_FUNC_CHIP
|
||||
f == CYW_SPID_FUNC_CHIP
|
||||
? 4
|
||||
: 0; // add padding to chip backplane reads as a response delay
|
||||
uint32_t hdr = CYW_SD_INC | CYW_SD_FUNC(f) | CYW_SD_ADDR(addr) |
|
||||
CYW_SD_LEN(len + padding); // gSPI header
|
||||
if (f == CYW_SD_FUNC_WLAN && (len & 3))
|
||||
uint32_t hdr = CYW_SPID_INC | CYW_SPID_FUNC(f) | CYW_SPID_ADDR(addr) |
|
||||
CYW_SPID_LEN(len + padding); // gSPI header
|
||||
if (f == CYW_SPID_FUNC_WLAN && (len & 3))
|
||||
len = (len + 4) & ~3; // align WLAN transfers to 32-bit
|
||||
if (f & CYW_SD_16bMODE)
|
||||
if (f & CYW_SPI_16bMODE)
|
||||
hdr = sw16_2(hdr); // swap half-words in 16-bit little-endian mode
|
||||
|
||||
s->begin(NULL);
|
||||
s->txn(NULL, (uint8_t *) &hdr, NULL, sizeof(hdr));
|
||||
if (f == CYW_SD_FUNC_CHIP) {
|
||||
if (f == CYW_SPID_FUNC_CHIP) {
|
||||
uint32_t pad;
|
||||
s->txn(NULL, NULL, (uint8_t *) &pad, 4); // read padding back and discard
|
||||
}
|
||||
@@ -1175,6 +1216,160 @@ static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
|
||||
s->end(NULL);
|
||||
}
|
||||
|
||||
static bool cyw_bus_specific_init(void) {
|
||||
return cyw_spi_init();
|
||||
}
|
||||
static size_t cyw_bus_specific_poll(uint32_t *response) {
|
||||
return cyw_spi_poll((uint8_t *) response);
|
||||
}
|
||||
static size_t cyw_bus_specific_tx(uint32_t *data, uint16_t len) {
|
||||
return cyw_spi_tx(data, len);
|
||||
}
|
||||
static bool cyw_bus_write(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len) {
|
||||
if (f == CYW_SPID_FUNC_CHIP && len >= 4) addr |= CYW_CHIP_BCKPLN_ACCSS4B;
|
||||
return cyw_spi_write(f, addr, data, len);
|
||||
}
|
||||
static bool cyw_bus_read(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len) {
|
||||
cyw_spi_read(f, addr, data, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // MG_ENABLE_DRIVER_CYW_SDIO
|
||||
|
||||
#include "sdio.h"
|
||||
|
||||
// CYW43 SDIO bus specifics
|
||||
|
||||
// CYW4343W and CYW43439 DS 4.1 SDIO v2.0:
|
||||
//- F0: max block size is 32 bytes
|
||||
//- F1: max block size is 64 bytes
|
||||
//- F2: max block size is 512 bytes
|
||||
|
||||
// clang-format off
|
||||
static bool cyw_sdio_transfer(bool write, unsigned int f, uint32_t addr, void *data, uint32_t len) {
|
||||
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
struct mg_tcpip_sdio *s = (struct mg_tcpip_sdio *) d->bus;
|
||||
uint32_t *ptr = (uint32_t *) data; // assume 32-bit aligned data (all except firmware)
|
||||
if (write && (size_t) data & 3) { // missed, source data is not 32-bit aligned
|
||||
memcpy(txdata, data, len); // copy to an aligned buffer, we know it fits
|
||||
ptr = txdata;
|
||||
} // all possible read destinations are 32-bit aligned
|
||||
// mg_sdio_transfer requires 32-bit alignment for > 1 byte transfers
|
||||
return mg_sdio_transfer(s, write, f, addr, ptr, len);
|
||||
}
|
||||
|
||||
static size_t cyw_sdio_poll(uint32_t *response) {
|
||||
uint32_t res;
|
||||
uint16_t *len = (uint16_t *)&res;
|
||||
// WHD: internal docs, "tag" hinting a possible packet.
|
||||
// This is actually the len / ~len field of a possible struct sdpcm_hdr, if there is a packet available, or 0 if there is none.
|
||||
cyw_sdio_transfer(false, CYW_SDIO_FUNC_WLAN, 0, &res, sizeof(res)); // read "the tag"
|
||||
if ((len[0] | len[1]) == 0 || (len[0] ^ len[1]) != 0xffff || *len <= 4) return 0;
|
||||
response[0] = res; // copy what we already read, then read the rest
|
||||
cyw_sdio_transfer(false, CYW_SDIO_FUNC_WLAN, 0, response + 1, *len - sizeof(res));
|
||||
return (size_t)*len;
|
||||
}
|
||||
|
||||
static size_t cyw_sdio_tx(uint32_t *data, uint16_t len) {
|
||||
return cyw_sdio_transfer(true, CYW_SDIO_FUNC_WLAN, 0, data, len) ? len: 0;
|
||||
}
|
||||
|
||||
static bool cyw_sdio_init() {
|
||||
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
|
||||
struct mg_tcpip_sdio *s = (struct mg_tcpip_sdio *) d->bus;
|
||||
uint32_t val = 0;
|
||||
if (!mg_sdio_init(s)) return false;
|
||||
// no block transfers on F0. if (!mg_sdio_set_blksz(s, CYW_SDIO_FUNC_BUS, 32)) return false;
|
||||
if (!mg_sdio_set_blksz(s, CYW_SDIO_FUNC_CHIP, 64)) return false;
|
||||
if (!mg_sdio_set_blksz(s, CYW_SDIO_FUNC_WLAN, 64)) return false;
|
||||
// TODO(scaprile): we don't handle SDIO interrupts, study CCCR INTEN and SDIO support (SDIO 6.3, 8)
|
||||
// Enable chip backplane (F1)
|
||||
if (!mg_sdio_enable_f(s, CYW_SDIO_FUNC_CHIP)) return false;
|
||||
// Wait for F1 to be ready
|
||||
if (!mg_sdio_waitready_f(s, CYW_SDIO_FUNC_CHIP)) return false;
|
||||
// chip backplane is ready, initialize it
|
||||
// request ALP (Active Low Power) clock
|
||||
val = MG_BIT(5) | MG_BIT(3) | MG_BIT(0); // HW_CLKREQ_OFF ALP_REQ FORCE_ALP
|
||||
cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
// BT-ENABLED DEPENDENCY
|
||||
unsigned int times = 10;
|
||||
while (times--) {
|
||||
if(!cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1)) return false;
|
||||
if (val & MG_BIT(6)) break; // ALP_AVAIL
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
// clear request
|
||||
val = 0; cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
|
||||
// Enable WLAN (F2)
|
||||
if (!mg_sdio_enable_f(s, CYW_SDIO_FUNC_WLAN)) return false;
|
||||
// Clear pullups. NOTE(): ?
|
||||
val = 0x00; cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
|
||||
// we don't handle wake nor OOB interrupts; SEP_INT_CTL is a vendor specific SDIO register
|
||||
// SDIO interrupts: enable F2 interrupt only
|
||||
|
||||
cyw_set_backplane_window(CYW_CHIP_CHIPCOMMON); // set backplane window to start of CHIPCOMMON area
|
||||
cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
|
||||
if (val == 43430) val = 4343;
|
||||
MG_INFO(("WLAN chip is CYW%u%c", val, val == 4343 ? 'W' : ' '));
|
||||
// Load firmware (code and NVRAM)
|
||||
if (!cyw_load_firmware(d->fw)) return false;
|
||||
|
||||
// Wait for High Throughput (HT) clock ready
|
||||
times = 50;
|
||||
while (times--) {
|
||||
if(!cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1)) return false;
|
||||
if (val & MG_BIT(7)) break; // HT_AVAIL
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
// Wait for WLAN ready
|
||||
if (!mg_sdio_waitready_f(s, CYW_SDIO_FUNC_WLAN)) return false;
|
||||
|
||||
// CHIP DEPENDENCY
|
||||
// Enable save / restore
|
||||
// Configure WakeupCtrl, set HT_AVAIL in CLOCK_CSR
|
||||
if(!cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1)) return false;
|
||||
val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
|
||||
#if 0 // TODO(scaprile): Check if this is actually necessary
|
||||
// Set BRCM_CARDCAP to CMD_NODEC. This is a vendor specific SDIO register
|
||||
val = MG_BIT(3); cyw_sdio_transfer(true, CYW_SDIO_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
|
||||
#endif
|
||||
// Force HT request to chip backplane
|
||||
val = MG_BIT(1) /* FORCE_HT */; if(!cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1)) return false;
|
||||
// Enable Keep SDIO On (KSO)
|
||||
cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
|
||||
if (!(val & MG_BIT(0))) {
|
||||
val |= MG_BIT(0); cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
static bool cyw_bus_specific_init(void) {
|
||||
return cyw_sdio_init();
|
||||
}
|
||||
static size_t cyw_bus_specific_poll(uint32_t *response) {
|
||||
return cyw_sdio_poll(response);
|
||||
}
|
||||
static size_t cyw_bus_specific_tx(uint32_t *data, uint16_t len) {
|
||||
return cyw_sdio_tx(data, len);
|
||||
}
|
||||
static bool cyw_bus_write(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len) {
|
||||
if (f == CYW_SDIO_FUNC_CHIP && len == 4) addr |= CYW_CHIP_BCKPLN_ACCSS4B;
|
||||
return cyw_sdio_transfer(true, f, addr, data, (uint32_t) len);
|
||||
}
|
||||
static bool cyw_bus_read(unsigned int f, uint32_t addr, void *data,
|
||||
uint16_t len) {
|
||||
return cyw_sdio_transfer(false, f, addr, data, (uint32_t) len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Mongoose Wi-Fi API functions
|
||||
|
||||
bool mg_wifi_scan(void) {
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
((defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW) || \
|
||||
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO))
|
||||
|
||||
struct mg_tcpip_spi_ {
|
||||
void *spi; // Opaque SPI bus descriptor
|
||||
@@ -20,7 +22,7 @@ struct mg_tcpip_driver_cyw_firmware {
|
||||
};
|
||||
|
||||
struct mg_tcpip_driver_cyw_data {
|
||||
struct mg_tcpip_spi_ *spi;
|
||||
void *bus;
|
||||
struct mg_tcpip_driver_cyw_firmware *fw;
|
||||
char *ssid;
|
||||
char *pass;
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
#include "net_builtin.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
(defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10) || \
|
||||
(defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11)
|
||||
struct imxrt_enet {
|
||||
volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3],
|
||||
ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR,
|
||||
@@ -26,7 +28,7 @@ struct imxrt_enet {
|
||||
};
|
||||
|
||||
#undef ENET
|
||||
#if defined(MG_DRIVER_IMXRT_RT11) && MG_DRIVER_IMXRT_RT11
|
||||
#if defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11
|
||||
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40424000U)
|
||||
#define ETH_DESC_CNT 5 // Descriptors count
|
||||
#else
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
(defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10) || \
|
||||
(defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11)
|
||||
|
||||
struct mg_tcpip_driver_imxrt_data {
|
||||
// MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
|
||||
|
||||
+20
-9
@@ -1,13 +1,15 @@
|
||||
#include "phy.h"
|
||||
|
||||
enum { // ID1 ID2
|
||||
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
|
||||
enum { // ID1 ID2
|
||||
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
|
||||
MG_PHY_DP83x = 0x2000,
|
||||
MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
|
||||
MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
|
||||
MG_PHY_DP83848 = 0x5ca2, // 2000 5ca2 - TI DP83848I
|
||||
MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
|
||||
MG_PHY_RTL8201 = 0x1C // 001c c816 - RTL8201
|
||||
MG_PHY_RTL8201 = 0x1C, // 001c c816 - RTL8201,
|
||||
MG_PHY_ICS1894x = 0x15,
|
||||
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -23,7 +25,8 @@ enum {
|
||||
MG_PHY_KSZ8x_REG_PC2R = 31,
|
||||
MG_PHY_LAN87x_REG_SCSR = 31,
|
||||
MG_PHY_RTL8201_REG_RMSR = 16, // in page 7
|
||||
MG_PHY_RTL8201_REG_PAGESEL = 31
|
||||
MG_PHY_RTL8201_REG_PAGESEL = 31,
|
||||
MG_PHY_ICS189432_REG_POLL = 17
|
||||
};
|
||||
|
||||
static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
||||
@@ -45,6 +48,8 @@ static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
||||
return "LAN87x";
|
||||
case MG_PHY_RTL8201:
|
||||
return "RTL8201";
|
||||
case MG_PHY_ICS1894x:
|
||||
return "ICS1894x";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
@@ -77,11 +82,13 @@ void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
|
||||
phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
|
||||
} else if (id1 == MG_PHY_KSZ8x) {
|
||||
// Disable isolation (override hw, it doesn't make sense at this point)
|
||||
phy->write_reg( // #2848, some NXP boards set ISO, even though
|
||||
phy_addr, MG_PHY_REG_BCR, // docs say they don't
|
||||
phy->read_reg(phy_addr, MG_PHY_REG_BCR) & (uint16_t) ~MG_BIT(10));
|
||||
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R, // now do clock stuff
|
||||
MG_BIT(15) | MG_BIT(8) | MG_BIT(7));
|
||||
// - #2848, some NXP boards set ISO, even though docs say they don't
|
||||
phy->write_reg(phy_addr, MG_PHY_REG_BCR,
|
||||
(uint16_t) (phy->read_reg(phy_addr, MG_PHY_REG_BCR) &
|
||||
(uint16_t) ~MG_BIT(10)));
|
||||
// now do clock stuff
|
||||
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R,
|
||||
(uint16_t) (MG_BIT(15) | MG_BIT(8) | MG_BIT(7)));
|
||||
} else if (id1 == MG_PHY_LAN87x) {
|
||||
// nothing to do
|
||||
} else if (id1 == MG_PHY_RTL8201) {
|
||||
@@ -134,6 +141,10 @@ bool mg_phy_up(struct mg_phy *phy, uint8_t phy_addr, bool *full_duplex,
|
||||
uint16_t bcr = phy->read_reg(phy_addr, MG_PHY_REG_BCR);
|
||||
*full_duplex = bcr & MG_BIT(8);
|
||||
*speed = (bcr & MG_BIT(13)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
|
||||
} else if (id1 == MG_PHY_ICS1894x) {
|
||||
uint16_t poll_reg = phy->read_reg(phy_addr, MG_PHY_ICS189432_REG_POLL);
|
||||
*full_duplex = poll_reg & MG_BIT(14);
|
||||
*speed = (poll_reg & MG_BIT(15)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
|
||||
}
|
||||
}
|
||||
return up;
|
||||
|
||||
+1
-1
@@ -323,6 +323,6 @@ static size_t mg_ppp_rx(void *ethbuf, size_t ethlen, struct mg_tcpip_if *ifp) {
|
||||
}
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_ppp = {mg_ppp_init, mg_ppp_tx, mg_ppp_rx,
|
||||
mg_ppp_up};
|
||||
mg_ppp_poll};
|
||||
|
||||
#endif
|
||||
+13
-4
@@ -1,6 +1,8 @@
|
||||
#include "net_builtin.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
(defined(MG_ENABLE_DRIVER_RA6) && MG_ENABLE_DRIVER_RA6) || \
|
||||
(defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8)
|
||||
struct ra_etherc {
|
||||
volatile uint32_t ECMR, RESERVED, RFLR, RESERVED1, ECSR, RESERVED2, ECSIPR,
|
||||
RESERVED3, PIR, RESERVED4, PSR, RESERVED5[5], RDMLR, RESERVED6[3], IPGR,
|
||||
@@ -18,13 +20,20 @@ struct ra_edmac {
|
||||
};
|
||||
|
||||
#undef ETHERC
|
||||
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
|
||||
#undef EDMAC
|
||||
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
|
||||
#undef RASYSC
|
||||
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
|
||||
#undef ICU_IELSR
|
||||
#if defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8
|
||||
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40354100U)
|
||||
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40354000U)
|
||||
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
|
||||
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x4000C300U)
|
||||
#else
|
||||
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
|
||||
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
|
||||
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
|
||||
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x40006300U)
|
||||
#endif
|
||||
|
||||
#define ETH_PKT_SIZE 1536 // Max frame size, multiple of 32
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
(defined(MG_ENABLE_DRIVER_RA6) && MG_ENABLE_DRIVER_RA6) || \
|
||||
(defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8)
|
||||
|
||||
struct mg_tcpip_driver_ra_data {
|
||||
// MDC clock "divider". MDC clock is software generated,
|
||||
|
||||
+100
-82
@@ -3,7 +3,35 @@
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||
MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
#include <sam.h>
|
||||
struct GMAC_REGS_ {
|
||||
uint32_t GMAC_NCR, GMAC_NCFGR, GMAC_NSR, GMAC_UR, GMAC_DCFGR, GMAC_TSR,
|
||||
GMAC_RBQB, GMAC_TBQB, GMAC_RSR, GMAC_ISR, GMAC_IER, GMAC_IDR, GMAC_IMR,
|
||||
GMAC_MAN, GMAC_RPQ, GMAC_TPQ, GMAC_TPSF, GMAC_RPSF, GMAC_RJFML,
|
||||
Reserved1[13], GMAC_HRB, GMAC_HRT, GMAC_SAB0, GMAC_SAT0, GMAC_SAB1,
|
||||
GMAC_SAT1, GMAC_SAB2, GMAC_SAT2, GMAC_SAB3, GMAC_SAT3, GMAC_TIDM[4],
|
||||
GMAC_WOL, GMAC_IPGS, GMAC_SVLAN, GMAC_TPFCP, GMAC_SAMB1, GMAC_SAMT1,
|
||||
Reserved2[3], GMAC_NSC, GMAC_SCL, GMAC_SCH, GMAC_EFTSH, GMAC_EFRSH,
|
||||
GMAC_PEFTSH, GMAC_PEFRSH, Reserved3[2], GMAC_OTLO, GMAC_OTHI, GMAC_FT,
|
||||
GMAC_BCFT, GMAC_MFT, GMAC_PFT, GMAC_BFT64, GMAC_TBFT127, GMAC_TBFT255,
|
||||
GMAC_TBFT511, GMAC_TBFT1023, GMAC_TBFT1518, GMAC_GTBFT1518, GMAC_TUR,
|
||||
GMAC_SCF, GMAC_MCF, GMAC_EC, GMAC_LC, GMAC_DTF, GMAC_CSE, GMAC_ORLO,
|
||||
GMAC_ORHI, GMAC_FR, GMAC_BCFR, GMAC_MFR, GMAC_PFR, GMAC_BFR64,
|
||||
GMAC_TBFR127, GMAC_TBFR255, GMAC_TBFR511, GMAC_TBFR1023, GMAC_TBFR1518,
|
||||
GMAC_TMXBFR, GMAC_UFR, GMAC_OFR, GMAC_JR, GMAC_FCSE, GMAC_LFFE, GMAC_RSE,
|
||||
GMAC_AE, GMAC_RRE, GMAC_ROE, GMAC_IHCE, GMAC_TCE, GMAC_UCE, Reserved4[2],
|
||||
GMAC_TISUBN, GMAC_TSH, Reserved5, GMAC_TSSSL, GMAC_TSSN, GMAC_TSL,
|
||||
GMAC_TN, GMAC_TA, GMAC_TI, GMAC_EFTSL, GMAC_EFTN, GMAC_EFRSL, GMAC_EFRN,
|
||||
GMAC_PEFTSL, GMAC_PEFTN, GMAC_PEFRSL, GMAC_PEFRN, Reserved6[28],
|
||||
GMAC_RLPITR, GMAC_RLPITI, GMAC_TLPITR, GMAC_TLPITI;
|
||||
};
|
||||
|
||||
struct GCLK_REGS_ {
|
||||
uint32_t GCLK_CTRLA_RESERVED, GCLK_SYNCBUSY, Reserved2[6], GCLK_GENCTRL[12],
|
||||
Reserved3[12], GCLK_PCHCTRL[48];
|
||||
};
|
||||
|
||||
#define GMAC_REGS ((struct GMAC_REGS_ *) 0x42000800)
|
||||
#define GCLK_REGS ((struct GCLK_REGS_ *) 0x40001c00)
|
||||
|
||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
@@ -17,72 +45,67 @@ static uint8_t s_txno; // Current TX descriptor
|
||||
static uint8_t s_rxno; // Current RX descriptor
|
||||
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
|
||||
|
||||
#define MG_PHYREGBIT_BCR_DUPLEX_MODE MG_BIT(8)
|
||||
#define MG_PHYREGBIT_BCR_SPEED MG_BIT(13)
|
||||
#define MG_PHYREGBIT_BSR_LINK_STATUS MG_BIT(2)
|
||||
|
||||
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
|
||||
GMAC_MAN_OP(2) | // Setting the read operation
|
||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
||||
GMAC_MAN_REGA(reg); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0;
|
||||
return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value
|
||||
GMAC_REGS->GMAC_MAN = MG_BIT(30) | // Clause 22
|
||||
MG_BIT(29) | // Setting the read operation
|
||||
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||
((reg & 0x1f) << 18); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))) (void) 0;
|
||||
return GMAC_REGS->GMAC_MAN & 0xffff; // Getting the read value
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation
|
||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
||||
GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete
|
||||
GMAC_REGS->GMAC_MAN = MG_BIT(30) |
|
||||
MG_BIT(28) | // Setting the write operation
|
||||
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||
((reg & 0x1f) << 18) | val; // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2)))
|
||||
; // Waiting until the write op is complete
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||
uint32_t get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||
if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
|
||||
return d->mdc_cr;
|
||||
} else {
|
||||
// get MCLK from GCLK_GENERATOR 0
|
||||
uint32_t div = 512;
|
||||
uint32_t mclk;
|
||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) {
|
||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & MG_BIT(12))) {
|
||||
div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
|
||||
if (div == 0) div = 1;
|
||||
}
|
||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) {
|
||||
case GCLK_GENCTRL_SRC_XOSC0_Val:
|
||||
mclk = 32000000UL; /* 32MHz */
|
||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & 0xF) {
|
||||
case 0: // GCLK_GENCTRL_SRC_XOSC0_Val
|
||||
mclk = 32000000UL; // 32MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_XOSC1_Val:
|
||||
mclk = 32000000UL; /* 32MHz */
|
||||
case 1: // GCLK_GENCTRL_SRC_XOSC1_Val
|
||||
mclk = 32000000UL; // 32MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_OSCULP32K_Val:
|
||||
mclk = 32000UL;
|
||||
case 4: // GCLK_GENCTRL_SRC_OSCULP32K_Val
|
||||
mclk = 32000UL; // 32Khz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_XOSC32K_Val:
|
||||
mclk = 32000UL;
|
||||
case 5: // GCLK_GENCTRL_SRC_XOSC32K_Val
|
||||
mclk = 32000UL; // 32Khz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DFLL_Val:
|
||||
mclk = 48000000UL; /* 48MHz */
|
||||
case 6: // GCLK_GENCTRL_SRC_DFLL_Val
|
||||
mclk = 48000000UL; // 48MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
case 7: // GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||
mclk = 200000000UL; // 200MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DPLL1_Val:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
case 8: // GCLK_GENCTRL_SRC_DPLL1_Val
|
||||
mclk = 200000000UL; // 200MHz
|
||||
break;
|
||||
default:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
mclk = 200000000UL; // 200MHz
|
||||
}
|
||||
|
||||
mclk /= div;
|
||||
uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
|
||||
uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) {
|
||||
if (mclk / dividers[i] <= 2375000UL) { // 2.5MHz - 5%
|
||||
return crs[i];
|
||||
}
|
||||
}
|
||||
@@ -96,11 +119,12 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
(struct mg_tcpip_driver_same54_data *) ifp->driver_data;
|
||||
s_ifp = ifp;
|
||||
|
||||
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk;
|
||||
MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk;
|
||||
GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider
|
||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO
|
||||
GMAC_REGS->GMAC_NCFGR = get_clock_rate(d) << 18; // Set MDC divider
|
||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(4); // Enable MDC & MDIO
|
||||
|
||||
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||
mg_phy_init(&phy, d->phy_addr, 0);
|
||||
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
||||
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
||||
@@ -108,38 +132,33 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18) // DMA recv buf 1536
|
||||
| GMAC_DCFGR_RXBMS(GMAC_DCFGR_RXBMS_FULL_Val) |
|
||||
GMAC_DCFGR_TXPBMS(1); // See #2487
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||
s_rxdesc[i][1] = 0; // Clear status
|
||||
GMAC_REGS->GMAC_DCFGR = (0x18 << 16) | // DMA recv buf 1536
|
||||
(3 << 8) | // RXBMS
|
||||
MG_BIT(10); // See #2487
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||
s_rxdesc[i][1] = 0; // Clear status
|
||||
}
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
||||
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
||||
|
||||
GMAC_REGS->SA[0].GMAC_SAB =
|
||||
GMAC_REGS->GMAC_SAB0 =
|
||||
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
|
||||
GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||
GMAC_REGS->GMAC_SAT0 = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||
|
||||
GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII
|
||||
GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk |
|
||||
GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk;
|
||||
GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
|
||||
GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk |
|
||||
GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk;
|
||||
GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk |
|
||||
GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk;
|
||||
GMAC_REGS->GMAC_UR &= ~MG_BIT(0); // Disable MII, use RMII
|
||||
GMAC_REGS->GMAC_NCFGR |= MG_BIT(8) | MG_BIT(6) | // MAXFX, MTIHEN
|
||||
MG_BIT(25) | MG_BIT(4); // EFRHD, CAF
|
||||
GMAC_REGS->GMAC_TSR = 0x17f; // all transmit statuses
|
||||
GMAC_REGS->GMAC_RSR = 0xf; // all recv statuses
|
||||
GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
|
||||
GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk |
|
||||
GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk |
|
||||
GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk |
|
||||
GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk;
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk;
|
||||
NVIC_EnableIRQ(GMAC_IRQn);
|
||||
GMAC_REGS->GMAC_IER = MG_BIT(11) | MG_BIT(10) | // HRESP, ROVR
|
||||
MG_BIT(7) | MG_BIT(6) | // TCOMP, TFC
|
||||
MG_BIT(5) | MG_BIT(4) | // RLEX, TUR
|
||||
MG_BIT(2) | MG_BIT(1); // RXUBR, RCOMP
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(3) | MG_BIT(2); // TXEN, RXEN
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -160,8 +179,8 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
|
||||
s_txdesc[s_txno][1] = status;
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
__DSB(); // Ensure descriptors have been written
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission
|
||||
MG_DSB(); // Ensure descriptors have been written
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(9); // Enable transmission
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -172,7 +191,7 @@ static void mg_tcpip_driver_same54_update_hash_table(struct mg_tcpip_if *ifp) {
|
||||
// computed hash is 55, which means bit 23 (55 - 32) in
|
||||
// HRT register must be set
|
||||
GMAC_REGS->GMAC_HRT = MG_BIT(23);
|
||||
GMAC_REGS->GMAC_NCFGR |= MG_BIT(6); // enable multicast hash filtering
|
||||
GMAC_REGS->GMAC_NCFGR |= MG_BIT(6); // enable multicast hash filtering
|
||||
(void) ifp;
|
||||
}
|
||||
|
||||
@@ -181,21 +200,22 @@ static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
mg_tcpip_driver_same54_update_hash_table(ifp);
|
||||
ifp->update_mac_hash_table = false;
|
||||
}
|
||||
|
||||
bool up = false;
|
||||
if (s1) {
|
||||
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
|
||||
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
|
||||
uint8_t speed = MG_PHY_SPEED_10M;
|
||||
bool full_duplex = false;
|
||||
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||
up = mg_phy_up(&phy, 0, &full_duplex, &speed);
|
||||
|
||||
// If PHY is ready, update NCFGR accordingly
|
||||
if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
|
||||
uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
|
||||
bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0;
|
||||
bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
|
||||
GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
|
||||
~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
|
||||
GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
|
||||
GMAC_REGS->GMAC_NCFGR =
|
||||
(GMAC_REGS->GMAC_NCFGR & ~(MG_BIT(0) | MG_BIT(1))) | (speed & 1) |
|
||||
(full_duplex << 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return up;
|
||||
}
|
||||
|
||||
void GMAC_Handler(void);
|
||||
@@ -203,8 +223,8 @@ void GMAC_Handler(void) {
|
||||
uint32_t isr = GMAC_REGS->GMAC_ISR;
|
||||
uint32_t rsr = GMAC_REGS->GMAC_RSR;
|
||||
uint32_t tsr = GMAC_REGS->GMAC_TSR;
|
||||
if (isr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (rsr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (isr & MG_BIT(1)) {
|
||||
if (rsr & MG_BIT(1)) {
|
||||
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
||||
@@ -215,9 +235,7 @@ void GMAC_Handler(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk |
|
||||
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
|
||||
if (tsr != 0) {
|
||||
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
||||
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
||||
}
|
||||
|
||||
+27
-5
@@ -1,13 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
struct mg_tcpip_driver_same54_data {
|
||||
int mdc_cr;
|
||||
};
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||
MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
#ifndef MG_DRIVER_MDC_CR
|
||||
#define MG_DRIVER_MDC_CR 5
|
||||
#endif
|
||||
|
||||
#ifndef MG_DRIVER_PHY_ADDR
|
||||
#define MG_DRIVER_PHY_ADDR 0
|
||||
#endif
|
||||
|
||||
struct mg_tcpip_driver_same54_data {
|
||||
int mdc_cr;
|
||||
uint8_t phy_addr;
|
||||
};
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_same54_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
|
||||
driver_data_.phy_addr = MG_DRIVER_PHY_ADDR; \
|
||||
mif_.ip = MG_TCPIP_IP; \
|
||||
mif_.mask = MG_TCPIP_MASK; \
|
||||
mif_.gw = MG_TCPIP_GW; \
|
||||
mif_.driver = &mg_tcpip_driver_same54; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: same54, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,169 @@
|
||||
#include "sdio.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO)
|
||||
|
||||
// SDIO 6.9 Table 6-1 CCCR (Common Card Control Registers)
|
||||
#define MG_SDIO_CCCR_SDIOREV 0x000
|
||||
#define MG_SDIO_CCCR_SDREV 0x001
|
||||
#define MG_SDIO_CCCR_IOEN 0x002
|
||||
#define MG_SDIO_CCCR_IORDY 0x003
|
||||
#define MG_SDIO_CCCR_INTEN 0x004
|
||||
#define MG_SDIO_CCCR_BIC 0x007
|
||||
#define MG_SDIO_CCCR_CCAP 0x008
|
||||
#define MG_SDIO_CCCR_CCIS 0x009 // 3 registers
|
||||
#define MG_SDIO_CCCR_F0BLKSZ 0x010 // 2 registers
|
||||
#define MG_SDIO_CCCR_HISPD 0x013
|
||||
// SDIO 6.10 Table 6-3 FBR (Function Basic Registers)
|
||||
#define MG_SDIO_FBR_FnBLKSZ(n) (((n) &7) * 0x100 + 0x10) // 2 registers
|
||||
|
||||
// SDIO 5.1 IO_RW_DIRECT Command (CMD52)
|
||||
#define MG_SDIO_DATA(x) ((x) &0xFF) // bits 0-7
|
||||
#define MG_SDIO_ADDR(x) (((x) &0x1FFFF) << 9) // bits 9-25
|
||||
#define MG_SDIO_FUNC(x) (((x) &3) << 28) // bits 28-30 (30 unused here)
|
||||
#define MG_SDIO_WR MG_BIT(31)
|
||||
|
||||
// SDIO 5.3 IO_RW_EXTENDED Command (CMD53)
|
||||
#define MG_SDIO_LEN(x) ((x) &0x1FF) // bits 0-8
|
||||
#define MG_SDIO_OPINC MG_BIT(26)
|
||||
#define MG_SDIO_BLKMODE MG_BIT(27)
|
||||
|
||||
// - Drivers set blocksize, drivers request transfers. Requesting a read
|
||||
// transfer > blocksize means block transfer will be used.
|
||||
// - To simplify the use of DMA transfers and avoid intermediate buffers,
|
||||
// drivers must have room to accomodate a whole block transfer, e.g.: blocksize
|
||||
// = 64, read 65 => 2 blocks = 128 bytes
|
||||
// - Transfers of more than 1 byte assume (uint32_t *) data. 1-byte transfers
|
||||
// use (uint8_t *) data
|
||||
// - 'len' is the number of _bytes_ to transfer
|
||||
bool mg_sdio_transfer(struct mg_tcpip_sdio *sdio, bool write, unsigned int f,
|
||||
uint32_t addr, void *data, uint32_t len) {
|
||||
uint32_t arg, val = 0;
|
||||
unsigned int blksz = 64; // TODO(): mg_sdio_set_blksz() stores in an array,
|
||||
// index on f, skip if 0
|
||||
if (len == 1) {
|
||||
arg = (write ? MG_SDIO_WR : 0) | MG_SDIO_FUNC(f) | MG_SDIO_ADDR(addr) |
|
||||
(write ? MG_SDIO_DATA(*(uint8_t *) data) : 0);
|
||||
bool res = sdio->txn(sdio, 52, arg, &val); // IO_RW_DIRECT
|
||||
if (!write) *(uint8_t *) data = (uint8_t) val;
|
||||
return res;
|
||||
}
|
||||
// IO_RW_EXTENDED
|
||||
arg = (write ? MG_SDIO_WR : 0) | MG_SDIO_OPINC | MG_SDIO_FUNC(f) |
|
||||
MG_SDIO_ADDR(addr);
|
||||
if (len > 512 || (blksz != 0 && len > blksz)) { // SDIO 5.3 512 -> len=0
|
||||
unsigned int blkcnt;
|
||||
if (blksz == 0) return false; // > 512 requires block size set
|
||||
blkcnt = (len + blksz - 1) / blksz;
|
||||
if (blkcnt > 511) return false; // we don't support "infinite" blocks
|
||||
arg |= MG_SDIO_BLKMODE | MG_SDIO_LEN(blkcnt); // block transfer
|
||||
len = blksz * blkcnt;
|
||||
} else {
|
||||
arg |= MG_SDIO_LEN(len); // multi-byte transfer
|
||||
}
|
||||
return sdio->xfr(sdio, write, arg,
|
||||
(arg & MG_SDIO_BLKMODE) ? (uint16_t) blksz : 0,
|
||||
(uint32_t *) data, len, &val);
|
||||
}
|
||||
|
||||
bool mg_sdio_set_blksz(struct mg_tcpip_sdio *sdio, unsigned int f,
|
||||
uint16_t blksz) {
|
||||
uint32_t val = blksz & 0xff;
|
||||
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_FBR_FnBLKSZ(f), &val, 1))
|
||||
return false;
|
||||
val = (blksz >> 8) & 0x0f; // SDIO 6.10 Table 6-4, max 2048
|
||||
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_FBR_FnBLKSZ(f) + 1, &val, 1))
|
||||
return false;
|
||||
// TODO(): store in an array, index on f. Static 8-element array
|
||||
MG_VERBOSE(("F%c block size set", (f & 7) + '0'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Enable Fx
|
||||
bool mg_sdio_enable_f(struct mg_tcpip_sdio *sdio, unsigned int f) {
|
||||
uint8_t bit = 1U << (f & 7), bits;
|
||||
uint32_t val = 0;
|
||||
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IOEN, &val, 1))
|
||||
return false;
|
||||
bits = (uint8_t) val | bit;
|
||||
unsigned int times = 501;
|
||||
while (times--) {
|
||||
val = bits; /* IOEf */
|
||||
;
|
||||
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_IOEN, &val, 1))
|
||||
return false;
|
||||
mg_delayms(1);
|
||||
val = 0;
|
||||
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IOEN, &val, 1))
|
||||
return false;
|
||||
if (val & bit) break;
|
||||
}
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
MG_VERBOSE(("F%c enabled", (f & 7) + '0'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wait for Fx to be ready
|
||||
bool mg_sdio_waitready_f(struct mg_tcpip_sdio *sdio, unsigned int f) {
|
||||
uint8_t bit = 1U << (f & 7);
|
||||
unsigned int times = 501;
|
||||
while (times--) {
|
||||
uint32_t val;
|
||||
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IORDY, &val, 1))
|
||||
return false;
|
||||
if (val & bit) break; // IORf
|
||||
mg_delayms(1);
|
||||
}
|
||||
if (times == (unsigned int) ~0) return false;
|
||||
MG_VERBOSE(("F%c ready", (f & 7) + '0'));
|
||||
return true;
|
||||
}
|
||||
|
||||
// SDIO 6.14 Bus State Diagram
|
||||
bool mg_sdio_init(struct mg_tcpip_sdio *sdio) {
|
||||
uint32_t val = 0;
|
||||
if (!sdio->txn(sdio, 0, 0, NULL)) return false; // GO_IDLE_STATE
|
||||
sdio->txn(sdio, 5, 0, &val); // IO_SEND_OP_COND, no CRC
|
||||
MG_VERBOSE(("IO Functions: %u, Memory: %c", 1 + ((val >> 28) & 7),
|
||||
(val & MG_BIT(27)) ? 'Y' : 'N'));
|
||||
if (!sdio->txn(sdio, 3, 0, &val)) return false; // SEND_RELATIVE_ADDR
|
||||
val = ((uint32_t) val) >> 16; // RCA
|
||||
if (!sdio->txn(sdio, 7, val << 16, &val))
|
||||
return false; // SELECT/DESELECT_CARD
|
||||
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_SDIOREV, &val, 1);
|
||||
MG_DEBUG(("CCCR: %u.%u, SDIO: %u.%u", 1 + ((val >> 2) & 3), (val >> 0) & 3,
|
||||
1 + ((val >> 6) & 3), (val >> 4) & 3));
|
||||
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_SDREV, &val, 1);
|
||||
MG_VERBOSE(("SD: %u.%u", 1 + ((val >> 2) & 3), (val >> 0) & 3));
|
||||
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_BIC, &val, 1);
|
||||
MG_SET_BITS(val, 3,
|
||||
MG_BIT(7) | MG_BIT(1)); // SDIO 6.9 Tables 6-1 6-2, 4-bit bus
|
||||
mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_BIC, &val, 1);
|
||||
// All Full-Speed SDIO cards support a 4-bit bus. Skip for Low-Speed SDIO
|
||||
// cards, we don't provide separate low-level functions for width and speed
|
||||
sdio->cfg(sdio, 0); // set DS;
|
||||
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_HISPD, &val, 1))
|
||||
return false;
|
||||
if (val & MG_BIT(0) /* SHS */) {
|
||||
val = MG_BIT(1); /* EHS */
|
||||
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_HISPD, &val, 1))
|
||||
return false;
|
||||
sdio->cfg(sdio, 1); // set HS;
|
||||
MG_VERBOSE(("Bus set to 4-bit @50MHz"));
|
||||
} else {
|
||||
MG_VERBOSE(("Bus set to 4-bit @25MHz"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// - 6.11 Card Information Structure (CIS): 0x0001000-0x017FF; for card common
|
||||
// and all functions
|
||||
// - 16.5 SDIO Card Metaformat
|
||||
// - 16.7.2 CISTPL_FUNCE (0x22): Function Extension Tuple, provides standard
|
||||
// information about the card (common) and each individual function. One
|
||||
// CISTPL_FUNCE in each function’s CIS, immediately following the CISTPL_FUNCID
|
||||
// tuple
|
||||
// - 16.7.3 CISTPL_FUNCE Tuple for Function 0 (common)
|
||||
// - 16.7.4 CISTPL_FUNCE Tuple for Function 1-7
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && \
|
||||
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO)
|
||||
|
||||
// Specific chip/card driver --> SDIO driver --> HAL --> SDIO hw controller
|
||||
|
||||
// API with HAL for hardware controller
|
||||
// - Provide a function to init the controller (external)
|
||||
// - Provide these functions:
|
||||
struct mg_tcpip_sdio {
|
||||
void *sdio; // Opaque SDIO bus descriptor
|
||||
void (*cfg)(void *, uint8_t); // select operating parameters
|
||||
// SDIO transaction: send cmd with a possible 1-byte read or write
|
||||
bool (*txn)(void *, uint8_t cmd, uint32_t arg, uint32_t *r);
|
||||
// SDIO extended transaction: write or read len bytes, using blksz blocks
|
||||
bool (*xfr)(void *, bool write, uint32_t arg, uint16_t blksz, uint32_t *,
|
||||
uint32_t len, uint32_t *r);
|
||||
};
|
||||
|
||||
// API with driver (e.g.: cyw.c)
|
||||
// Once the hardware controller has been initialized:
|
||||
// - Init card: selects the card, sets F0 block size, sets bus width and speed
|
||||
bool mg_sdio_init(struct mg_tcpip_sdio *sdio);
|
||||
// - Enable other possible functions (F1 to F7)
|
||||
bool mg_sdio_enable_f(struct mg_tcpip_sdio *sdio, unsigned int f);
|
||||
// - Wait for them to be ready
|
||||
bool mg_sdio_waitready_f(struct mg_tcpip_sdio *sdio, unsigned int f);
|
||||
// - Set their transfer block length
|
||||
bool mg_sdio_set_blksz(struct mg_tcpip_sdio *sdio, unsigned int f,
|
||||
uint16_t blksz);
|
||||
// - Transfer data to/from a function (abstracts from transaction type)
|
||||
// - Requesting a read transfer > blocksize means block transfer will be used.
|
||||
// - Drivers must have room to accomodate a whole block transfer, see sdio.c
|
||||
// - Transfers of > 1 byte --> (uint32_t *) data. 1-byte --> (uint8_t *) data
|
||||
bool mg_sdio_transfer(struct mg_tcpip_sdio *sdio, bool write, unsigned int f,
|
||||
uint32_t addr, void *data, uint32_t len);
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,12 @@ struct mg_tcpip_driver_stm32f_data {
|
||||
#define MG_DRIVER_MDC_CR 4
|
||||
#endif
|
||||
|
||||
#if MG_ARCH == MG_ARCH_CUBE
|
||||
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH_IRQn)
|
||||
#else
|
||||
#define MG_ENABLE_ETH_IRQ()
|
||||
#endif
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_stm32f_data driver_data_; \
|
||||
@@ -40,6 +46,7 @@ struct mg_tcpip_driver_stm32f_data {
|
||||
mif_.driver = &mg_tcpip_driver_stm32f; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
MG_ENABLE_ETH_IRQ(); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: stm32f, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||
} while (0)
|
||||
|
||||
@@ -40,6 +40,12 @@ struct mg_tcpip_driver_stm32h_data {
|
||||
#define MG_DRIVER_MDC_CR 4
|
||||
#endif
|
||||
|
||||
#if MG_ENABLE_DRIVER_STM32H && MG_ARCH == MG_ARCH_CUBE
|
||||
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH_IRQn)
|
||||
#else
|
||||
#define MG_ENABLE_ETH_IRQ()
|
||||
#endif
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_stm32h_data driver_data_; \
|
||||
@@ -54,6 +60,7 @@ struct mg_tcpip_driver_stm32h_data {
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_ENABLE_ETH_IRQ(); \
|
||||
MG_INFO(("Driver: stm32h, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#include "fs.h"
|
||||
#include "printf.h"
|
||||
#include "str.h"
|
||||
#include "util.h"
|
||||
|
||||
struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
|
||||
struct mg_fd *fd = (struct mg_fd *) calloc(1, sizeof(*fd));
|
||||
struct mg_fd *fd = (struct mg_fd *) mg_calloc(1, sizeof(*fd));
|
||||
if (fd != NULL) {
|
||||
fd->fd = fs->op(path, flags);
|
||||
fd->fs = fs;
|
||||
if (fd->fd == NULL) {
|
||||
free(fd);
|
||||
mg_free(fd);
|
||||
fd = NULL;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +19,7 @@ struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
|
||||
void mg_fs_close(struct mg_fd *fd) {
|
||||
if (fd != NULL) {
|
||||
fd->fs->cl(fd->fd);
|
||||
free(fd);
|
||||
mg_free(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +28,10 @@ struct mg_str mg_file_read(struct mg_fs *fs, const char *path) {
|
||||
void *fp;
|
||||
fs->st(path, &result.len, NULL);
|
||||
if ((fp = fs->op(path, MG_FS_READ)) != NULL) {
|
||||
result.buf = (char *) calloc(1, result.len + 1);
|
||||
result.buf = (char *) mg_calloc(1, result.len + 1);
|
||||
if (result.buf != NULL &&
|
||||
fs->rd(fp, (void *) result.buf, result.len) != result.len) {
|
||||
free((void *) result.buf);
|
||||
mg_free((void *) result.buf);
|
||||
result.buf = NULL;
|
||||
}
|
||||
fs->cl(fp);
|
||||
@@ -66,7 +67,7 @@ bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...) {
|
||||
data = mg_vmprintf(fmt, &ap);
|
||||
va_end(ap);
|
||||
result = mg_file_write(fs, path, data, strlen(data));
|
||||
free(data);
|
||||
mg_free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -74,7 +74,7 @@ static void *ff_open(const char *path, int flags) {
|
||||
if (flags & MG_FS_WRITE) mode |= FA_WRITE | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
|
||||
if (f_open(&f, path, mode) == 0) {
|
||||
FIL *fp;
|
||||
if ((fp = calloc(1, sizeof(*fp))) != NULL) {
|
||||
if ((fp = mg_calloc(1, sizeof(*fp))) != NULL) {
|
||||
memcpy(fp, &f, sizeof(*fp));
|
||||
return fp;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ static void *ff_open(const char *path, int flags) {
|
||||
static void ff_close(void *fp) {
|
||||
if (fp != NULL) {
|
||||
f_close((FIL *) fp);
|
||||
free(fp);
|
||||
mg_free(fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
#include "fs.h"
|
||||
#include "printf.h"
|
||||
#include "str.h"
|
||||
#include "util.h"
|
||||
|
||||
struct packed_file {
|
||||
const char *data;
|
||||
@@ -72,7 +73,7 @@ static void *packed_open(const char *path, int flags) {
|
||||
struct packed_file *fp = NULL;
|
||||
if (data == NULL) return NULL;
|
||||
if (flags & MG_FS_WRITE) return NULL;
|
||||
if ((fp = (struct packed_file *) calloc(1, sizeof(*fp))) != NULL) {
|
||||
if ((fp = (struct packed_file *) mg_calloc(1, sizeof(*fp))) != NULL) {
|
||||
fp->size = size;
|
||||
fp->data = data;
|
||||
}
|
||||
@@ -80,7 +81,7 @@ static void *packed_open(const char *path, int flags) {
|
||||
}
|
||||
|
||||
static void packed_close(void *fp) {
|
||||
if (fp != NULL) free(fp);
|
||||
if (fp != NULL) mg_free(fp);
|
||||
}
|
||||
|
||||
static size_t packed_read(void *fd, void *buf, size_t len) {
|
||||
|
||||
+3
-3
@@ -99,7 +99,7 @@ DIR *opendir(const char *name) {
|
||||
|
||||
if (name == NULL) {
|
||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||
} else if ((d = (DIR *) calloc(1, sizeof(*d))) == NULL) {
|
||||
} else if ((d = (DIR *) mg_calloc(1, sizeof(*d))) == NULL) {
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
} else {
|
||||
to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
|
||||
@@ -109,7 +109,7 @@ DIR *opendir(const char *name) {
|
||||
d->handle = FindFirstFileW(wpath, &d->info);
|
||||
d->result.d_name[0] = '\0';
|
||||
} else {
|
||||
free(d);
|
||||
mg_free(d);
|
||||
d = NULL;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ int closedir(DIR *d) {
|
||||
if (d != NULL) {
|
||||
if (d->handle != INVALID_HANDLE_VALUE)
|
||||
result = FindClose(d->handle) ? 0 : -1;
|
||||
free(d);
|
||||
mg_free(d);
|
||||
} else {
|
||||
result = -1;
|
||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||
|
||||
+16
-47
@@ -216,7 +216,7 @@ static bool vcb(uint8_t c) {
|
||||
static size_t clen(const char *s, const char *end) {
|
||||
const unsigned char *u = (unsigned char *) s, c = *u;
|
||||
long n = (long) (end - s);
|
||||
if (c > ' ' && c < '~') return 1; // Usual ascii printed char
|
||||
if (c > ' ' && c <= '~') return 1; // Usual ascii printed char
|
||||
if ((c & 0xe0) == 0xc0 && n > 1 && vcb(u[1])) return 2; // 2-byte UTF8
|
||||
if ((c & 0xf0) == 0xe0 && n > 2 && vcb(u[1]) && vcb(u[2])) return 3;
|
||||
if ((c & 0xf8) == 0xf0 && n > 3 && vcb(u[1]) && vcb(u[2]) && vcb(u[3]))
|
||||
@@ -280,17 +280,17 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
||||
hm->uri.buf = (char *) s;
|
||||
while (s < end && (n = clen(s, end)) > 0) s += n, hm->uri.len += n;
|
||||
while (s < end && s[0] == ' ') s++; // Skip spaces
|
||||
is_response = hm->method.len > 5 &&
|
||||
(mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
|
||||
is_response =
|
||||
hm->method.len > 5 && (mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
|
||||
if ((s = skiptorn(s, end, &hm->proto)) == NULL) return false;
|
||||
// If we're given a version, check that it is HTTP/x.x
|
||||
version_prefix_valid = hm->proto.len > 5 &&
|
||||
(mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
|
||||
version_prefix_valid =
|
||||
hm->proto.len > 5 && (mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
|
||||
if (!is_response && hm->proto.len > 0 &&
|
||||
(!version_prefix_valid || hm->proto.len != 8 ||
|
||||
(hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
|
||||
(hm->proto.buf[6] != '.') ||
|
||||
(hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
|
||||
(!version_prefix_valid || hm->proto.len != 8 ||
|
||||
(hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
|
||||
(hm->proto.buf[6] != '.') ||
|
||||
(hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -589,13 +589,11 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
|
||||
// If a browser sends us "Accept-Encoding: gzip", try to open .gz first
|
||||
struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
|
||||
if (ae != NULL) {
|
||||
char *ae_ = mg_mprintf("%.*s", ae->len, ae->buf);
|
||||
if (ae_ != NULL && strstr(ae_, "gzip") != NULL) {
|
||||
if (mg_match(*ae, mg_str("*gzip*"), NULL)) {
|
||||
mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
|
||||
fd = mg_fs_open(fs, tmp, MG_FS_READ);
|
||||
if (fd != NULL) gzip = true, path = tmp;
|
||||
}
|
||||
free(ae_);
|
||||
}
|
||||
// No luck opening .gz? Open what we've told to open
|
||||
if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
|
||||
@@ -686,7 +684,7 @@ static void printdirentry(const char *name, void *userdata) {
|
||||
sizeof(path)) {
|
||||
MG_ERROR(("%s truncated", name));
|
||||
} else if ((flags = fs->st(path, &size, &t)) == 0) {
|
||||
MG_ERROR(("%lu stat(%s): %d", d->c->id, path, errno));
|
||||
MG_ERROR(("%lu stat(%s)", d->c->id, path));
|
||||
} else {
|
||||
const char *slash = flags & MG_FS_DIR ? "/" : "";
|
||||
if (flags & MG_FS_DIR) {
|
||||
@@ -977,7 +975,7 @@ long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
|
||||
mg_http_reply(c, 400, "", "%s: offset mismatch", path);
|
||||
res = -5;
|
||||
} else if ((fd = mg_fs_open(fs, path, MG_FS_WRITE)) == NULL) {
|
||||
mg_http_reply(c, 400, "", "open(%s): %d", path, errno);
|
||||
mg_http_reply(c, 400, "", "open(%s)", path);
|
||||
res = -6;
|
||||
} else {
|
||||
res = offset + (long) fs->wr(fd->fd, hm->body.buf, hm->body.len);
|
||||
@@ -1042,7 +1040,7 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
c->pfn = NULL;
|
||||
return;
|
||||
}
|
||||
if (ev == MG_EV_CLOSE) { // If client did not set Content-Length
|
||||
if (ev == MG_EV_CLOSE) { // If client did not set Content-Length
|
||||
hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG
|
||||
hm.body.len = hm.message.len - (size_t) (hm.body.buf - hm.message.buf);
|
||||
}
|
||||
@@ -1073,7 +1071,8 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
}
|
||||
if (require_content_len) {
|
||||
if (!c->is_client) mg_http_reply(c, 411, "", "");
|
||||
MG_ERROR(("Content length missing from %s", is_response ? "response" : "request"));
|
||||
MG_ERROR(("Content length missing from %s",
|
||||
is_response ? "response" : "request"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,39 +1119,9 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
(void) ev_data;
|
||||
}
|
||||
|
||||
static void mg_hfn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/quit"), NULL)) {
|
||||
mg_http_reply(c, 200, "", "ok\n");
|
||||
c->is_draining = 1;
|
||||
c->data[0] = 'X';
|
||||
} else if (mg_match(hm->uri, mg_str("/debug"), NULL)) {
|
||||
int level = (int) mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
|
||||
mg_log_set(level);
|
||||
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
|
||||
} else {
|
||||
mg_http_reply(c, 200, "", "hi\n");
|
||||
}
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
if (c->data[0] == 'X') *(bool *) c->fn_data = true;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_hello(const char *url) {
|
||||
struct mg_mgr mgr;
|
||||
bool done = false;
|
||||
mg_mgr_init(&mgr);
|
||||
if (mg_http_listen(&mgr, url, mg_hfn, &done) == NULL) done = true;
|
||||
while (done == false) mg_mgr_poll(&mgr, 100);
|
||||
mg_mgr_free(&mgr);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_http_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
|
||||
if (c != NULL) c->pfn = http_cb;
|
||||
return c;
|
||||
return mg_connect_svc(mgr, url, fn, fn_data, http_cb, NULL);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
|
||||
|
||||
@@ -63,4 +63,3 @@ void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
||||
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
|
||||
size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
|
||||
int mg_http_status(const struct mg_http_message *hm);
|
||||
void mg_hello(const char *url);
|
||||
+4
-5
@@ -12,18 +12,17 @@ int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
|
||||
new_size = roundup(new_size, io->align);
|
||||
if (new_size == 0) {
|
||||
mg_bzero(io->buf, io->size);
|
||||
free(io->buf);
|
||||
mg_free(io->buf);
|
||||
io->buf = NULL;
|
||||
io->len = io->size = 0;
|
||||
} else if (new_size != io->size) {
|
||||
// NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
|
||||
// porting to some obscure platforms like FreeRTOS
|
||||
void *p = calloc(1, new_size);
|
||||
// NOTE(lsm): do not use realloc here. Use mg_calloc/mg_free only
|
||||
void *p = mg_calloc(1, new_size);
|
||||
if (p != NULL) {
|
||||
size_t len = new_size < io->len ? new_size : io->len;
|
||||
if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
|
||||
mg_bzero(io->buf, io->size);
|
||||
free(io->buf);
|
||||
mg_free(io->buf);
|
||||
io->buf = (unsigned char *) p;
|
||||
io->size = new_size;
|
||||
} else {
|
||||
|
||||
+5
-4
@@ -1,6 +1,7 @@
|
||||
#include "json.h"
|
||||
#include "base64.h"
|
||||
#include "fmt.h"
|
||||
#include "util.h"
|
||||
|
||||
static const char *escapeseq(int esc) {
|
||||
return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
|
||||
@@ -320,10 +321,10 @@ char *mg_json_get_str(struct mg_str json, const char *path) {
|
||||
char *result = NULL;
|
||||
int len = 0, off = mg_json_get(json, path, &len);
|
||||
if (off >= 0 && len > 1 && json.buf[off] == '"') {
|
||||
if ((result = (char *) calloc(1, (size_t) len)) != NULL &&
|
||||
if ((result = (char *) mg_calloc(1, (size_t) len)) != NULL &&
|
||||
!mg_json_unescape(mg_str_n(json.buf + off + 1, (size_t) (len - 2)),
|
||||
result, (size_t) len)) {
|
||||
free(result);
|
||||
mg_free(result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
@@ -334,7 +335,7 @@ char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) {
|
||||
char *result = NULL;
|
||||
int len = 0, off = mg_json_get(json, path, &len);
|
||||
if (off >= 0 && json.buf[off] == '"' && len > 1 &&
|
||||
(result = (char *) calloc(1, (size_t) len)) != NULL) {
|
||||
(result = (char *) mg_calloc(1, (size_t) len)) != NULL) {
|
||||
size_t k = mg_base64_decode(json.buf + off + 1, (size_t) (len - 2), result,
|
||||
(size_t) len);
|
||||
if (slen != NULL) *slen = (int) k;
|
||||
@@ -346,7 +347,7 @@ char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) {
|
||||
char *result = NULL;
|
||||
int len = 0, off = mg_json_get(json, path, &len);
|
||||
if (off >= 0 && json.buf[off] == '"' && len > 1 &&
|
||||
(result = (char *) calloc(1, (size_t) len / 2)) != NULL) {
|
||||
(result = (char *) mg_calloc(1, (size_t) len / 2)) != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < len - 2; i += 2) {
|
||||
mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, &result[i >> 1],
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "str.h"
|
||||
#include "util.h"
|
||||
|
||||
int mg_log_level = MG_LL_INFO;
|
||||
int mg_log_level = MG_LL_DEBUG;
|
||||
static mg_pfn_t s_log_func = mg_pfn_stdout;
|
||||
static void *s_log_func_param = NULL;
|
||||
|
||||
|
||||
+1
-2
@@ -529,12 +529,11 @@ void mg_mqtt_disconnect(struct mg_connection *c,
|
||||
struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
|
||||
const struct mg_mqtt_opts *opts,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
|
||||
struct mg_connection *c = mg_connect_svc(mgr, url, fn, fn_data, mqtt_cb, NULL);
|
||||
if (c != NULL) {
|
||||
struct mg_mqtt_opts empty;
|
||||
memset(&empty, 0, sizeof(empty));
|
||||
mg_mqtt_login(c, opts == NULL ? &empty : opts);
|
||||
c->pfn = mqtt_cb;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "net.h"
|
||||
#include "dns.h"
|
||||
#include "fmt.h"
|
||||
#include "log.h"
|
||||
#include "net.h"
|
||||
#include "printf.h"
|
||||
#include "profile.h"
|
||||
#include "timer.h"
|
||||
@@ -126,7 +126,7 @@ bool mg_aton(struct mg_str str, struct mg_addr *addr) {
|
||||
|
||||
struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
|
||||
struct mg_connection *c =
|
||||
(struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
|
||||
(struct mg_connection *) mg_calloc(1, sizeof(*c) + mgr->extraconnsize);
|
||||
if (c != NULL) {
|
||||
c->mgr = mgr;
|
||||
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
|
||||
@@ -153,11 +153,12 @@ void mg_close_conn(struct mg_connection *c) {
|
||||
mg_iobuf_free(&c->send);
|
||||
mg_iobuf_free(&c->rtls);
|
||||
mg_bzero((unsigned char *) c, sizeof(*c));
|
||||
free(c);
|
||||
mg_free(c);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *mg_connect_svc(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data,
|
||||
mg_event_handler_t pfn, void *pfn_data) {
|
||||
struct mg_connection *c = NULL;
|
||||
if (url == NULL || url[0] == '\0') {
|
||||
MG_ERROR(("null url"));
|
||||
@@ -170,22 +171,30 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
||||
c->fn = fn;
|
||||
c->is_client = true;
|
||||
c->fn_data = fn_data;
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
c->is_tls = (mg_url_is_ssl(url) != 0);
|
||||
c->pfn = pfn;
|
||||
c->pfn_data = pfn_data;
|
||||
mg_call(c, MG_EV_OPEN, (void *) url);
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
mg_resolve(c, url);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
return mg_connect_svc(mgr, url, fn, fn_data, NULL, NULL);
|
||||
}
|
||||
|
||||
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
struct mg_connection *c = NULL;
|
||||
if ((c = mg_alloc_conn(mgr)) == NULL) {
|
||||
MG_ERROR(("OOM %s", url));
|
||||
} else if (!mg_open_listener(c, url)) {
|
||||
MG_ERROR(("Failed: %s, errno %d", url, errno));
|
||||
MG_ERROR(("Failed: %s", url));
|
||||
MG_PROF_FREE(c);
|
||||
free(c);
|
||||
mg_free(c);
|
||||
c = NULL;
|
||||
} else {
|
||||
c->is_listening = 1;
|
||||
@@ -193,8 +202,8 @@ struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
|
||||
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
|
||||
c->fn = fn;
|
||||
c->fn_data = fn_data;
|
||||
c->is_tls = (mg_url_is_ssl(url) != 0);
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must
|
||||
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
|
||||
}
|
||||
return c;
|
||||
@@ -216,9 +225,9 @@ struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
|
||||
|
||||
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
|
||||
unsigned flags, void (*fn)(void *), void *arg) {
|
||||
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
|
||||
struct mg_timer *t = (struct mg_timer *) mg_calloc(1, sizeof(*t));
|
||||
if (t != NULL) {
|
||||
flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete
|
||||
flags |= MG_TIMER_AUTODELETE; // We have alloc'ed it, so autodelete
|
||||
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
|
||||
}
|
||||
return t;
|
||||
@@ -235,7 +244,7 @@ long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||
void mg_mgr_free(struct mg_mgr *mgr) {
|
||||
struct mg_connection *c;
|
||||
struct mg_timer *tmp, *t = mgr->timers;
|
||||
while (t != NULL) tmp = t->next, free(t), t = tmp;
|
||||
while (t != NULL) tmp = t->next, mg_free(t), t = tmp;
|
||||
mgr->timers = NULL; // Important. Next call to poll won't touch timers
|
||||
for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
|
||||
mg_mgr_poll(mgr, 0);
|
||||
@@ -266,7 +275,7 @@ void mg_mgr_init(struct mg_mgr *mgr) {
|
||||
// clang-format on
|
||||
#elif MG_ENABLE_FREERTOS_TCP
|
||||
mgr->ss = FreeRTOS_CreateSocketSet();
|
||||
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
|
||||
#elif MG_ARCH == MG_ARCH_UNIX
|
||||
// Ignore SIGPIPE signal, so if client cancels the request, it
|
||||
// won't kill the whole process.
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
@@ -278,4 +287,11 @@ void mg_mgr_init(struct mg_mgr *mgr) {
|
||||
mgr->dns4.url = "udp://8.8.8.8:53";
|
||||
mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
|
||||
mg_tls_ctx_init(mgr);
|
||||
MG_DEBUG(("MG_IO_SIZE: %lu, TLS: %s", MG_IO_SIZE,
|
||||
MG_TLS == MG_TLS_NONE ? "none"
|
||||
: MG_TLS == MG_TLS_MBED ? "MbedTLS"
|
||||
: MG_TLS == MG_TLS_OPENSSL ? "OpenSSL"
|
||||
: MG_TLS == MG_TLS_BUILTIN ? "builtin"
|
||||
: MG_TLS == MG_TLS_WOLFSSL ? "WolfSSL"
|
||||
: "custom"));
|
||||
}
|
||||
@@ -105,3 +105,6 @@ bool mg_wakeup(struct mg_mgr *, unsigned long id, const void *buf, size_t len);
|
||||
bool mg_wakeup_init(struct mg_mgr *);
|
||||
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
|
||||
unsigned flags, void (*fn)(void *), void *arg);
|
||||
struct mg_connection *mg_connect_svc(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data,
|
||||
mg_event_handler_t pfn, void *pfn_data);
|
||||
+95
-46
@@ -161,7 +161,7 @@ static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
|
||||
|
||||
static uint16_t csumfin(uint32_t sum) {
|
||||
while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
|
||||
return mg_htons(~sum & 0xffff);
|
||||
return mg_htons((uint16_t) ((uint16_t) ~sum & 0xffff));
|
||||
}
|
||||
|
||||
static uint16_t ipcsum(const void *buf, size_t len) {
|
||||
@@ -177,7 +177,7 @@ static void settmout(struct mg_connection *c, uint8_t type) {
|
||||
: type == MIP_TTYPE_SYN ? MIP_TCP_SYN_MS
|
||||
: type == MIP_TTYPE_FIN ? MIP_TCP_FIN_MS
|
||||
: MIP_TCP_KEEPALIVE_MS;
|
||||
if (s->ttype == MIP_TTYPE_FIN) return; // skip if 3-way closing
|
||||
if (s->ttype == MIP_TTYPE_FIN) return; // skip if 3-way closing
|
||||
s->timer = ifp->now + n;
|
||||
s->ttype = type;
|
||||
MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
|
||||
@@ -210,10 +210,8 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
|
||||
MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
|
||||
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
|
||||
} else if (ifp->state == MG_TCPIP_STATE_IP) {
|
||||
MG_ERROR(("Got IP"));
|
||||
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
|
||||
} else if (ifp->state == MG_TCPIP_STATE_UP) {
|
||||
MG_ERROR(("Link up"));
|
||||
srand((unsigned int) mg_millis());
|
||||
} else if (ifp->state == MG_TCPIP_STATE_DOWN) {
|
||||
MG_ERROR(("Link down"));
|
||||
@@ -241,18 +239,20 @@ static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
|
||||
return ip;
|
||||
}
|
||||
|
||||
static void tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
|
||||
static bool tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
|
||||
uint16_t sport, uint32_t ip_dst, uint16_t dport,
|
||||
const void *buf, size_t len) {
|
||||
struct ip *ip =
|
||||
tx_ip(ifp, mac_dst, 17, ip_src, ip_dst, len + sizeof(struct udp));
|
||||
struct udp *udp = (struct udp *) (ip + 1);
|
||||
size_t eth_len;
|
||||
uint32_t cs;
|
||||
// MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len));
|
||||
udp->sport = sport;
|
||||
udp->dport = dport;
|
||||
udp->len = mg_htons((uint16_t) (sizeof(*udp) + len));
|
||||
udp->csum = 0;
|
||||
uint32_t cs = csumup(0, udp, sizeof(*udp));
|
||||
cs = csumup(0, udp, sizeof(*udp));
|
||||
cs = csumup(cs, buf, len);
|
||||
cs = csumup(cs, &ip->src, sizeof(ip->src));
|
||||
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
|
||||
@@ -260,7 +260,8 @@ static void tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
|
||||
udp->csum = csumfin(cs);
|
||||
memmove(udp + 1, buf, len);
|
||||
// MG_DEBUG(("UDP LEN %d %d", (int) len, (int) ifp->frame_len));
|
||||
ether_output(ifp, sizeof(struct eth) + sizeof(*ip) + sizeof(*udp) + len);
|
||||
eth_len = sizeof(struct eth) + sizeof(*ip) + sizeof(*udp) + len;
|
||||
return (ether_output(ifp, eth_len) == eth_len);
|
||||
}
|
||||
|
||||
static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
|
||||
@@ -335,7 +336,8 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
|
||||
break;
|
||||
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport) break;
|
||||
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
|
||||
lsn == c->is_listening && (lsn || c->rem.port == pkt->tcp->sport))
|
||||
lsn == (bool) c->is_listening &&
|
||||
(lsn || c->rem.port == pkt->tcp->sport))
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
@@ -390,10 +392,12 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
|
||||
size_t hlen = sizeof(struct eth) + sizeof(struct ip) + sizeof(struct icmp);
|
||||
size_t space = ifp->tx.len - hlen, plen = pkt->pay.len;
|
||||
struct ip *ip;
|
||||
struct icmp *icmp;
|
||||
if (plen > space) plen = space;
|
||||
struct ip *ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
|
||||
sizeof(struct icmp) + plen);
|
||||
struct icmp *icmp = (struct icmp *) (ip + 1);
|
||||
ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
|
||||
sizeof(*icmp) + plen);
|
||||
icmp = (struct icmp *) (ip + 1);
|
||||
memset(icmp, 0, sizeof(*icmp)); // Set csum to 0
|
||||
memcpy(icmp + 1, pkt->pay.buf, plen); // Copy RX payload to TX
|
||||
icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
|
||||
@@ -401,6 +405,8 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
}
|
||||
}
|
||||
|
||||
static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip);
|
||||
|
||||
static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0;
|
||||
uint8_t msgtype = 0, state = ifp->state;
|
||||
@@ -440,17 +446,19 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
ifp->state = MG_TCPIP_STATE_REQ; // REQUESTING state
|
||||
} else if (msgtype == 5) { // DHCPACK
|
||||
if (ifp->state == MG_TCPIP_STATE_REQ && ip && gw && lease) { // got an IP
|
||||
uint64_t rand;
|
||||
ifp->lease_expire = ifp->now + lease * 1000;
|
||||
MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
|
||||
// assume DHCP server = router until ARP resolves
|
||||
memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
|
||||
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
|
||||
ifp->state = MG_TCPIP_STATE_IP; // BOUND state
|
||||
uint64_t rand;
|
||||
mg_random(&rand, sizeof(rand));
|
||||
srand((unsigned int) (rand + mg_millis()));
|
||||
if (ifp->enable_req_dns && dns != 0)
|
||||
if (ifp->enable_req_dns && dns != 0) {
|
||||
setdns4(ifp, &dns);
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_DNS, &dns);
|
||||
}
|
||||
if (ifp->enable_req_sntp && sntp != 0)
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_SNTP, &sntp);
|
||||
} else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew
|
||||
@@ -465,9 +473,9 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint8_t op = 0, *p = pkt->dhcp->options,
|
||||
*end = (uint8_t *) &pkt->raw.buf[pkt->raw.len];
|
||||
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
|
||||
// struct dhcp *req = pkt->dhcp;
|
||||
struct dhcp res = {2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
|
||||
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
|
||||
res.yiaddr = ifp->ip;
|
||||
((uint8_t *) (&res.yiaddr))[3]++; // Offer our IP + 1
|
||||
while (p + 1 < end && p[0] != 255) { // Parse options
|
||||
@@ -506,9 +514,9 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
if (c == NULL) {
|
||||
// No UDP listener on this port. Should send ICMP, but keep silent.
|
||||
} else {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
c->rem.port = pkt->udp->sport;
|
||||
memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||
if (c->recv.len >= MG_MAX_RECV_SIZE) {
|
||||
mg_error(c, "max_recv_buf_size reached");
|
||||
@@ -529,9 +537,9 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
|
||||
struct ip *ip;
|
||||
struct tcp *tcp;
|
||||
uint16_t opts[4 / 2];
|
||||
if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
|
||||
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
|
||||
opts[1] = mg_htons(ifp->mtu - 40); // RFC-6691
|
||||
if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
|
||||
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
|
||||
opts[1] = mg_htons((uint16_t) (ifp->mtu - 40)); // RFC-6691
|
||||
buf = opts;
|
||||
len = sizeof(opts);
|
||||
}
|
||||
@@ -547,15 +555,16 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
|
||||
tcp->win = mg_htons(MIP_TCP_WIN);
|
||||
tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
|
||||
if (flags & TH_SYN) tcp->off += (uint8_t) (sizeof(opts) / 4 << 4);
|
||||
|
||||
uint32_t cs = 0;
|
||||
uint16_t n = (uint16_t) (sizeof(*tcp) + len);
|
||||
uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
|
||||
cs = csumup(cs, tcp, n);
|
||||
cs = csumup(cs, &ip->src, sizeof(ip->src));
|
||||
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
|
||||
cs = csumup(cs, pseudo, sizeof(pseudo));
|
||||
tcp->csum = csumfin(cs);
|
||||
{
|
||||
uint32_t cs = 0;
|
||||
uint16_t n = (uint16_t) (sizeof(*tcp) + len);
|
||||
uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
|
||||
cs = csumup(cs, tcp, n);
|
||||
cs = csumup(cs, &ip->src, sizeof(ip->src));
|
||||
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
|
||||
cs = csumup(cs, pseudo, sizeof(pseudo));
|
||||
tcp->csum = csumfin(cs);
|
||||
}
|
||||
MG_VERBOSE(("TCP %M:%hu -> %M:%hu fl %x len %u", mg_print_ip4, &ip->src,
|
||||
mg_ntohs(tcp->sport), mg_print_ip4, &ip->dst,
|
||||
mg_ntohs(tcp->dport), tcp->flags, len));
|
||||
@@ -575,12 +584,13 @@ static size_t tx_tcp_pkt(struct mg_tcpip_if *ifp, struct pkt *pkt,
|
||||
static struct mg_connection *accept_conn(struct mg_connection *lsn,
|
||||
struct pkt *pkt) {
|
||||
struct mg_connection *c = mg_alloc_conn(lsn->mgr);
|
||||
struct connstate *s;
|
||||
if (c == NULL) {
|
||||
MG_ERROR(("OOM"));
|
||||
return NULL;
|
||||
}
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
s->dmss = 1460; // TODO(scaprile): 536; // assume default, RFC-9293 3.7.1
|
||||
s = (struct connstate *) (c + 1);
|
||||
s->dmss = 536; // assume default, RFC-9293 3.7.1
|
||||
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
|
||||
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
|
||||
settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||
@@ -595,8 +605,10 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn,
|
||||
c->pfn_data = lsn->pfn_data;
|
||||
c->fn = lsn->fn;
|
||||
c->fn_data = lsn->fn_data;
|
||||
c->is_tls = lsn->is_tls;
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
mg_call(c, MG_EV_ACCEPT, NULL);
|
||||
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -633,7 +645,9 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
uint32_t dst_ip = *(uint32_t *) c->rem.ip;
|
||||
len = trim_len(c, len);
|
||||
if (c->is_udp) {
|
||||
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, dst_ip, c->rem.port, buf, len);
|
||||
if (!tx_udp(ifp, s->mac, ifp->ip, c->loc.port, dst_ip, c->rem.port, buf,
|
||||
len))
|
||||
return MG_IO_WAIT;
|
||||
} else { // TCP, cap to peer's MSS
|
||||
size_t sent;
|
||||
if (len > s->dmss) len = s->dmss; // RFC-6691: reduce if sending opts
|
||||
@@ -678,10 +692,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
||||
uint32_t rem_ip;
|
||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||
if (pkt->tcp->flags & TH_FIN) {
|
||||
uint8_t flags = TH_ACK;
|
||||
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
|
||||
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
|
||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||
return;
|
||||
}
|
||||
// If we initiated the closure, we reply with ACK upon receiving FIN
|
||||
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
||||
// closure process
|
||||
uint8_t flags = TH_ACK;
|
||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
||||
s->fin_rcvd = true;
|
||||
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||
@@ -699,7 +719,13 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
|
||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||
if (pkt->pay.len == 0) return; // if no data, we're done
|
||||
} else if (pkt->pay.len == 0) { // this is an ACK
|
||||
} else if (pkt->pay.len <= 1 && mg_ntohl(pkt->tcp->seq) == s->ack - 1) {
|
||||
// Keep-Alive (RFC-9293 3.8.4, allow erroneous implementations)
|
||||
MG_VERBOSE(("%lu keepalive ACK", c->id));
|
||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
||||
return; // no data to process
|
||||
} else if (pkt->pay.len == 0) { // this is an ACK
|
||||
if (s->fin_rcvd && s->ttype == MIP_TTYPE_FIN) s->twclosure = true;
|
||||
return; // no data to process
|
||||
} else if (seq != s->ack) {
|
||||
@@ -784,6 +810,7 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
settmout(c, MIP_TTYPE_KEEPALIVE);
|
||||
mg_call(c, MG_EV_CONNECT, NULL); // Let user know
|
||||
if (c->is_tls_hs) mg_tls_handshake(c);
|
||||
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
|
||||
} else if (c != NULL && c->is_connecting && pkt->tcp->flags != TH_ACK) {
|
||||
// mg_hexdump(pkt->raw.buf, pkt->raw.len);
|
||||
tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
|
||||
@@ -826,9 +853,10 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint16_t frag = mg_ntohs(pkt->ip->frag);
|
||||
if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
|
||||
struct mg_connection *c;
|
||||
if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
|
||||
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
|
||||
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
|
||||
c = getpeer(ifp->mgr, pkt, false);
|
||||
if (c) mg_error(c, "Received fragmented packet");
|
||||
} else if (pkt->ip->proto == 1) {
|
||||
pkt->icmp = (struct icmp *) (pkt->ip + 1);
|
||||
@@ -854,11 +882,12 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
rx_udp(ifp, pkt);
|
||||
}
|
||||
} else if (pkt->ip->proto == 6) {
|
||||
uint16_t iplen, off;
|
||||
pkt->tcp = (struct tcp *) (pkt->ip + 1);
|
||||
if (pkt->pay.len < sizeof(*pkt->tcp)) return;
|
||||
mkpay(pkt, pkt->tcp + 1);
|
||||
uint16_t iplen = mg_ntohs(pkt->ip->len);
|
||||
uint16_t off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
|
||||
iplen = mg_ntohs(pkt->ip->len);
|
||||
off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
|
||||
if (iplen >= off) pkt->pay.len = (size_t) (iplen - off);
|
||||
MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
|
||||
mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
|
||||
@@ -896,8 +925,9 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
|
||||
memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
|
||||
return;
|
||||
if (ifp->enable_crc32_check && len > 4) {
|
||||
uint32_t crc;
|
||||
len -= 4; // TODO(scaprile): check on bigendian
|
||||
uint32_t crc = mg_crc32(0, (const char *) buf, len);
|
||||
crc = mg_crc32(0, (const char *) buf, len);
|
||||
if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
|
||||
}
|
||||
if (pkt.eth->type == mg_htons(0x806)) {
|
||||
@@ -1006,10 +1036,10 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
|
||||
|
||||
// Process timeouts
|
||||
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
|
||||
if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
|
||||
continue;
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
uint32_t rem_ip;
|
||||
if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
|
||||
continue;
|
||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||
if (ifp->now > s->timer) {
|
||||
if (s->ttype == MIP_TTYPE_ARP) {
|
||||
@@ -1074,10 +1104,10 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
|
||||
MG_ERROR(("driver init failed"));
|
||||
} else {
|
||||
size_t framesize = 1540;
|
||||
ifp->tx.buf = (char *) calloc(1, framesize), ifp->tx.len = framesize;
|
||||
ifp->tx.buf = (char *) mg_calloc(1, framesize), ifp->tx.len = framesize;
|
||||
if (ifp->recv_queue.size == 0)
|
||||
ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192;
|
||||
ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size);
|
||||
ifp->recv_queue.buf = (char *) mg_calloc(1, ifp->recv_queue.size);
|
||||
ifp->timer_1000ms = mg_millis();
|
||||
mgr->ifp = ifp;
|
||||
ifp->mgr = mgr;
|
||||
@@ -1093,8 +1123,9 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
|
||||
}
|
||||
|
||||
void mg_tcpip_free(struct mg_tcpip_if *ifp) {
|
||||
free(ifp->recv_queue.buf);
|
||||
free(ifp->tx.buf);
|
||||
mg_free(ifp->recv_queue.buf);
|
||||
mg_free(ifp->tx.buf);
|
||||
mg_free(ifp->dns4_url);
|
||||
}
|
||||
|
||||
static void send_syn(struct mg_connection *c) {
|
||||
@@ -1207,17 +1238,20 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
||||
if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
|
||||
mg_tcpip_poll(mgr->ifp, now);
|
||||
for (c = mgr->conns; c != NULL; c = tmp) {
|
||||
tmp = c->next;
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
bool is_tls = c->is_tls && !c->is_resolving && !c->is_arplooking &&
|
||||
!c->is_listening && !c->is_connecting;
|
||||
tmp = c->next;
|
||||
mg_call(c, MG_EV_POLL, &now);
|
||||
MG_VERBOSE(("%lu .. %c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
|
||||
c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
|
||||
c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c',
|
||||
mg_tls_pending(c), c->rtls.len));
|
||||
// order is important, TLS conn close with > 1 record in buffer (below)
|
||||
if (c->is_tls && (c->rtls.len > 0 || mg_tls_pending(c) > 0))
|
||||
if (is_tls && (c->rtls.len > 0 || mg_tls_pending(c) > 0))
|
||||
handle_tls_recv(c);
|
||||
if (can_write(c)) write_conn(c);
|
||||
if (is_tls && c->send.len == 0) mg_tls_flush(c);
|
||||
if (c->is_draining && c->send.len == 0 && s->ttype != MIP_TTYPE_FIN)
|
||||
init_closure(c);
|
||||
// For non-TLS, close immediately upon completing the 3-way closure
|
||||
@@ -1243,8 +1277,8 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
} else if (c->is_udp) {
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
len = trim_len(c, len); // Trimming length if necessary
|
||||
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len);
|
||||
res = true;
|
||||
res = tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf,
|
||||
len);
|
||||
} else {
|
||||
res = mg_iobuf_add(&c->send, c->send.len, buf, len);
|
||||
}
|
||||
@@ -1258,4 +1292,19 @@ void mg_multicast_add(struct mg_connection *c, char *ip) {
|
||||
c->mgr->ifp->update_mac_hash_table = true; // mark dirty
|
||||
}
|
||||
|
||||
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc);
|
||||
|
||||
static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip) {
|
||||
struct mg_dns *dnsc;
|
||||
mg_free(ifp->dns4_url);
|
||||
ifp->dns4_url = mg_mprintf("udp://%M:53", mg_print_ip4, ip);
|
||||
dnsc = &ifp->mgr->dns4;
|
||||
dnsc->url = (const char *) ifp->dns4_url;
|
||||
MG_DEBUG(("Set DNS URL to %s", dnsc->url));
|
||||
if (ifp->mgr->use_dns6) return;
|
||||
if (dnsc->c != NULL) mg_close_conn(dnsc->c);
|
||||
if (!mg_dnsc_init(ifp->mgr, dnsc)) // create DNS connection
|
||||
MG_ERROR(("DNS connection creation failed"));
|
||||
}
|
||||
|
||||
#endif // MG_ENABLE_TCPIP
|
||||
@@ -57,6 +57,7 @@ struct mg_tcpip_if {
|
||||
|
||||
// Internal state, user can use it but should not change it
|
||||
uint8_t gwmac[6]; // Router's MAC
|
||||
char *dns4_url; // DNS server URL
|
||||
uint64_t now; // Current time
|
||||
uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
|
||||
uint64_t lease_expire; // Lease expiration time, in ms
|
||||
@@ -103,4 +104,5 @@ struct mg_tcpip_spi {
|
||||
uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -150,7 +150,7 @@ fwxit:
|
||||
|
||||
// try to swap (honor dual image), otherwise just overwrite
|
||||
MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
|
||||
char *tmp = malloc(ss);
|
||||
char *tmp = mg_calloc(1, ss);
|
||||
// no stdlib calls here
|
||||
for (size_t ofs = 0; ofs < s; ofs += ss) {
|
||||
if (tmp != NULL)
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ static bool __no_inline_not_in_flash_func(mg_picosdk_write)(void *addr,
|
||||
static void __no_inline_not_in_flash_func(single_bank_swap)(char *p1, char *p2,
|
||||
size_t s,
|
||||
size_t ss) {
|
||||
char *tmp = malloc(ss);
|
||||
char *tmp = mg_calloc(1, ss);
|
||||
if (tmp == NULL) return;
|
||||
#if PICO_RP2040
|
||||
uint32_t xip[256 / sizeof(uint32_t)];
|
||||
|
||||
@@ -200,6 +200,10 @@ MG_IRAM void single_bank_swap(char *p1, char *p2, size_t size) {
|
||||
|
||||
bool mg_ota_begin(size_t new_firmware_size) {
|
||||
s_mg_flash_stm32f.size = flash_size();
|
||||
#ifdef __ZEPHYR__
|
||||
*((uint32_t *)0xE000ED94) = 0;
|
||||
MG_DEBUG(("Jailbreak %s", *((uint32_t *)0xE000ED94) == 0 ? "successful" : "failed"));
|
||||
#endif
|
||||
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32f);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,10 @@ static bool mg_stm32h5_write(void *addr, const void *buf, size_t len) {
|
||||
}
|
||||
|
||||
bool mg_ota_begin(size_t new_firmware_size) {
|
||||
#ifdef __ZEPHYR__
|
||||
*((uint32_t *)0xE000ED94) = 0;
|
||||
MG_DEBUG(("Jailbreak %s", *((uint32_t *)0xE000ED94) == 0 ? "successful" : "failed"));
|
||||
#endif
|
||||
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32h5);
|
||||
}
|
||||
|
||||
|
||||
@@ -184,6 +184,10 @@ bool mg_ota_begin(size_t new_firmware_size) {
|
||||
// Using only the 1st bank (mapped to CM7)
|
||||
s_mg_flash_stm32h7.size /= 2;
|
||||
}
|
||||
#ifdef __ZEPHYR__
|
||||
*((uint32_t *)0xE000ED94) = 0;
|
||||
MG_DEBUG(("Jailbreak %s", *((uint32_t *)0xE000ED94) == 0 ? "successful" : "failed"));
|
||||
#endif
|
||||
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32h7);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "rpc.h"
|
||||
#include "printf.h"
|
||||
#include "util.h"
|
||||
|
||||
void mg_rpc_add(struct mg_rpc **head, struct mg_str method,
|
||||
void (*fn)(struct mg_rpc_req *), void *fn_data) {
|
||||
struct mg_rpc *rpc = (struct mg_rpc *) calloc(1, sizeof(*rpc));
|
||||
struct mg_rpc *rpc = (struct mg_rpc *) mg_calloc(1, sizeof(*rpc));
|
||||
if (rpc != NULL) {
|
||||
rpc->method = mg_strdup(method);
|
||||
rpc->fn = fn;
|
||||
@@ -17,8 +18,8 @@ void mg_rpc_del(struct mg_rpc **head, void (*fn)(struct mg_rpc_req *)) {
|
||||
while ((r = *head) != NULL) {
|
||||
if (r->fn == fn || fn == NULL) {
|
||||
*head = r->next;
|
||||
free((void *) r->method.buf);
|
||||
free(r);
|
||||
mg_free((void *) r->method.buf);
|
||||
mg_free(r);
|
||||
} else {
|
||||
head = &(*head)->next;
|
||||
}
|
||||
|
||||
+2
-7
@@ -82,12 +82,7 @@ void mg_sntp_request(struct mg_connection *c) {
|
||||
}
|
||||
|
||||
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fnd) {
|
||||
struct mg_connection *c = NULL;
|
||||
mg_event_handler_t fn, void *fn_data) {
|
||||
if (url == NULL) url = "udp://time.google.com:123";
|
||||
if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) {
|
||||
c->pfn = sntp_cb;
|
||||
sntp_cb(c, MG_EV_OPEN, (void *) url);
|
||||
}
|
||||
return c;
|
||||
return mg_connect_svc(mgr, url, fn, fn_data, sntp_cb, NULL);
|
||||
}
|
||||
+28
-14
@@ -160,8 +160,10 @@ static void mg_set_non_blocking_mode(MG_SOCKET_TYPE fd) {
|
||||
if (setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off)) != 0) (void) 0;
|
||||
#elif MG_ENABLE_LWIP
|
||||
lwip_fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
#elif MG_ARCH == MG_ARCH_AZURERTOS
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
#elif MG_ARCH == MG_ARCH_THREADX
|
||||
// NetxDuo fails to send large blocks of data to the non-blocking sockets
|
||||
(void) fd;
|
||||
//fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
#elif MG_ARCH == MG_ARCH_TIRTOS
|
||||
int val = 0;
|
||||
setsockopt(fd, SOL_SOCKET, SO_BLOCKING, &val, sizeof(val));
|
||||
@@ -183,15 +185,19 @@ void mg_multicast_add(struct mg_connection *c, char *ip) {
|
||||
#elif MG_ENABLE_FREERTOS_TCP
|
||||
// TODO(): prvAllowIPPacketIPv4()
|
||||
#else
|
||||
// lwIP, Unix, Windows, Zephyr(, AzureRTOS ?)
|
||||
// lwIP, Unix, Windows, Zephyr 4+(, AzureRTOS ?)
|
||||
#if MG_ENABLE_LWIP && !LWIP_IGMP
|
||||
MG_ERROR(("LWIP_IGMP not defined, no multicast support"));
|
||||
#else
|
||||
#if defined(__ZEPHYR__) && ZEPHYR_VERSION_CODE < 0x40000
|
||||
MG_ERROR(("struct ip_mreq not defined"));
|
||||
#else
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(ip);
|
||||
mreq.imr_interface.s_addr = mg_htonl(INADDR_ANY);
|
||||
setsockopt(FD(c), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
|
||||
#endif
|
||||
#endif // !Zephyr
|
||||
#endif // !lwIP
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -361,13 +367,14 @@ static void connect_conn(struct mg_connection *c) {
|
||||
mg_call(c, MG_EV_CONNECT, NULL);
|
||||
MG_EPOLL_MOD(c, 0);
|
||||
if (c->is_tls_hs) mg_tls_handshake(c);
|
||||
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
|
||||
} else {
|
||||
mg_error(c, "socket error");
|
||||
}
|
||||
}
|
||||
|
||||
static void setsockopts(struct mg_connection *c) {
|
||||
#if MG_ENABLE_FREERTOS_TCP || MG_ARCH == MG_ARCH_AZURERTOS || \
|
||||
#if MG_ENABLE_FREERTOS_TCP || MG_ARCH == MG_ARCH_THREADX || \
|
||||
MG_ARCH == MG_ARCH_TIRTOS
|
||||
(void) c;
|
||||
#else
|
||||
@@ -413,6 +420,7 @@ void mg_connect_resolved(struct mg_connection *c) {
|
||||
if (rc == 0) { // Success
|
||||
setlocaddr(FD(c), &c->loc);
|
||||
mg_call(c, MG_EV_CONNECT, NULL); // Send MG_EV_CONNECT to the user
|
||||
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
|
||||
} else if (MG_SOCK_PENDING(rc)) { // Need to wait for TCP handshake
|
||||
MG_DEBUG(("%lu %ld -> %M pend", c->id, c->fd, mg_print_ip_port, &c->rem));
|
||||
c->is_connecting = 1;
|
||||
@@ -438,8 +446,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
|
||||
socklen_t sa_len = sizeof(usa);
|
||||
MG_SOCKET_TYPE fd = raccept(FD(lsn), &usa, &sa_len);
|
||||
if (fd == MG_INVALID_SOCKET) {
|
||||
#if MG_ARCH == MG_ARCH_AZURERTOS || defined(__ECOS)
|
||||
// AzureRTOS, in non-block socket mode can mark listening socket readable
|
||||
#if MG_ARCH == MG_ARCH_THREADX || defined(__ECOS)
|
||||
// NetxDuo, in non-block socket mode can mark listening socket readable
|
||||
// even it is not. See comment for 'select' func implementation in
|
||||
// nx_bsd.c That's not an error, just should try later
|
||||
if (errno != EAGAIN)
|
||||
@@ -468,10 +476,12 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
|
||||
c->pfn_data = lsn->pfn_data;
|
||||
c->fn = lsn->fn;
|
||||
c->fn_data = lsn->fn_data;
|
||||
c->is_tls = lsn->is_tls;
|
||||
MG_DEBUG(("%lu %ld accepted %M -> %M", c->id, c->fd, mg_print_ip_port,
|
||||
&c->rem, mg_print_ip_port, &c->loc));
|
||||
mg_call(c, MG_EV_OPEN, NULL);
|
||||
mg_call(c, MG_EV_ACCEPT, NULL);
|
||||
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,7 +587,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct timeval tv = {ms / 1000, (ms % 1000) * 1000}, tv_zero = {0, 0}, *tvp;
|
||||
struct timeval tv = {ms / 1000, (ms % 1000) * 1000}, tv_1ms = {0, 1000}, *tvp;
|
||||
struct mg_connection *c;
|
||||
fd_set rset, wset, eset;
|
||||
MG_SOCKET_TYPE maxfd = 0;
|
||||
@@ -593,16 +603,16 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
||||
FD_SET(FD(c), &eset);
|
||||
if (can_read(c)) FD_SET(FD(c), &rset);
|
||||
if (can_write(c)) FD_SET(FD(c), &wset);
|
||||
if (c->rtls.len > 0 || mg_tls_pending(c) > 0) tvp = &tv_zero;
|
||||
if (c->rtls.len > 0 || mg_tls_pending(c) > 0) tvp = &tv_1ms;
|
||||
if (FD(c) > maxfd) maxfd = FD(c);
|
||||
if (c->is_closing) tvp = &tv_zero;
|
||||
if (c->is_closing) tvp = &tv_1ms;
|
||||
}
|
||||
|
||||
if ((rc = select((int) maxfd + 1, &rset, &wset, &eset, tvp)) < 0) {
|
||||
if ((rc = select((int) maxfd + 1, &rset, &wset, &eset, tvp)) <= 0) {
|
||||
#if MG_ARCH == MG_ARCH_WIN32
|
||||
if (maxfd == 0) Sleep(ms); // On Windows, select fails if no sockets
|
||||
#else
|
||||
MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc)));
|
||||
if (rc < 0) MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc)));
|
||||
#endif
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
@@ -611,7 +621,12 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
|
||||
|
||||
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||
if (FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &eset)) {
|
||||
#if MG_ARCH == MG_ARCH_THREADX
|
||||
// NetxDuo stack returns exceptions for listening connection after accept
|
||||
if (c->is_listening == 0) mg_error(c, "socket error");
|
||||
#else
|
||||
mg_error(c, "socket error");
|
||||
#endif
|
||||
} else {
|
||||
c->is_readable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &rset);
|
||||
c->is_writable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &wset);
|
||||
@@ -734,11 +749,10 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
||||
if (c->is_readable) accept_conn(mgr, c);
|
||||
} else if (c->is_connecting) {
|
||||
if (c->is_readable || c->is_writable) connect_conn(c);
|
||||
//} else if (c->is_tls_hs) {
|
||||
// if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
|
||||
} else {
|
||||
if (c->is_readable) read_conn(c);
|
||||
if (c->is_writable) write_conn(c);
|
||||
if (c->is_tls && !c->is_tls_hs && c->send.len == 0) mg_tls_flush(c);
|
||||
}
|
||||
|
||||
if (c->is_draining && c->send.len == 0) c->is_closing = 1;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "log.h"
|
||||
#include "printf.h"
|
||||
#include "ssi.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifndef MG_MAX_SSI_DEPTH
|
||||
#define MG_MAX_SSI_DEPTH 5
|
||||
@@ -31,7 +32,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
|
||||
if (depth < MG_MAX_SSI_DEPTH &&
|
||||
(data = mg_ssi(tmp, root, depth + 1)) != NULL) {
|
||||
mg_iobuf_add(&b, b.len, data, strlen(data));
|
||||
free(data);
|
||||
mg_free(data);
|
||||
} else {
|
||||
MG_ERROR(("%s: file=%s error or too deep", path, arg));
|
||||
}
|
||||
@@ -41,7 +42,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
|
||||
if (depth < MG_MAX_SSI_DEPTH &&
|
||||
(data = mg_ssi(tmp, root, depth + 1)) != NULL) {
|
||||
mg_iobuf_add(&b, b.len, data, strlen(data));
|
||||
free(data);
|
||||
mg_free(data);
|
||||
} else {
|
||||
MG_ERROR(("%s: virtual=%s error or too deep", path, arg));
|
||||
}
|
||||
@@ -87,7 +88,7 @@ void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
||||
const char *headers = "Content-Type: text/html; charset=utf-8\r\n";
|
||||
char *data = mg_ssi(fullpath, root, 0);
|
||||
mg_http_reply(c, 200, headers, "%s", data == NULL ? "" : data);
|
||||
free(data);
|
||||
mg_free(data);
|
||||
}
|
||||
#else
|
||||
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "str.h"
|
||||
#include "util.h"
|
||||
|
||||
struct mg_str mg_str_s(const char *s) {
|
||||
struct mg_str str = {(char *) s, s == NULL ? 0 : strlen(s)};
|
||||
@@ -26,7 +27,7 @@ int mg_casecmp(const char *s1, const char *s2) {
|
||||
struct mg_str mg_strdup(const struct mg_str s) {
|
||||
struct mg_str r = {NULL, 0};
|
||||
if (s.len > 0 && s.buf != NULL) {
|
||||
char *sc = (char *) calloc(1, s.len + 1);
|
||||
char *sc = (char *) mg_calloc(1, s.len + 1);
|
||||
if (sc != NULL) {
|
||||
memcpy(sc, s.buf, s.len);
|
||||
sc[s.len] = '\0';
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
#include "arch.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
|
||||
unsigned flags, void (*fn)(void *), void *arg) {
|
||||
@@ -38,7 +39,7 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
|
||||
// If this timer is not repeating and marked AUTODELETE, remove it
|
||||
if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
|
||||
mg_timer_free(head, t);
|
||||
free(t);
|
||||
mg_free(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ struct mg_timer {
|
||||
#define MG_TIMER_REPEAT 1 // Call function periodically
|
||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||
#define MG_TIMER_CALLED 4 // Timer function was called at least once
|
||||
#define MG_TIMER_AUTODELETE 8 // free() timer when done
|
||||
#define MG_TIMER_AUTODELETE 8 // mg_free() timer when done
|
||||
void (*fn)(void *); // Function to call
|
||||
void *arg; // Function argument
|
||||
struct mg_timer *next; // Linkage
|
||||
|
||||
@@ -28,6 +28,7 @@ void mg_tls_free(struct mg_connection *);
|
||||
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
|
||||
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
|
||||
size_t mg_tls_pending(struct mg_connection *);
|
||||
void mg_tls_flush(struct mg_connection *);
|
||||
void mg_tls_handshake(struct mg_connection *);
|
||||
|
||||
// Private
|
||||
|
||||
+3
-3
@@ -20,6 +20,9 @@
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "arch.h"
|
||||
#include "tls.h"
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
/******************************************************************************/
|
||||
#define AES_DECRYPTION 1 // whether AES decryption is supported
|
||||
/******************************************************************************/
|
||||
@@ -27,11 +30,8 @@
|
||||
#define MG_ENCRYPT 1 // specify whether we're encrypting
|
||||
#define MG_DECRYPT 0 // or decrypting
|
||||
|
||||
#include "arch.h"
|
||||
#include "tls.h"
|
||||
#include "tls_aes128.h"
|
||||
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
/******************************************************************************
|
||||
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
|
||||
******************************************************************************/
|
||||
|
||||
+242
-215
@@ -12,8 +12,6 @@
|
||||
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
|
||||
#define CHACHA20 1
|
||||
|
||||
/* TLS 1.3 Record Content Type (RFC8446 B.1) */
|
||||
#define MG_TLS_CHANGE_CIPHER 20
|
||||
#define MG_TLS_ALERT 21
|
||||
@@ -34,17 +32,17 @@
|
||||
// refer to RFC8446#A.1
|
||||
enum mg_tls_hs_state {
|
||||
// Client state machine:
|
||||
MG_TLS_STATE_CLIENT_START, // Send ClientHello
|
||||
MG_TLS_STATE_CLIENT_WAIT_SH, // Wait for ServerHello
|
||||
MG_TLS_STATE_CLIENT_WAIT_EE, // Wait for EncryptedExtensions
|
||||
MG_TLS_STATE_CLIENT_WAIT_CERT, // Wait for Certificate
|
||||
MG_TLS_STATE_CLIENT_WAIT_CV, // Wait for CertificateVerify
|
||||
MG_TLS_STATE_CLIENT_WAIT_FINISHED, // Wait for Finished
|
||||
MG_TLS_STATE_CLIENT_CONNECTED, // Done
|
||||
MG_TLS_STATE_CLIENT_START, // Send ClientHello
|
||||
MG_TLS_STATE_CLIENT_WAIT_SH, // Wait for ServerHello
|
||||
MG_TLS_STATE_CLIENT_WAIT_EE, // Wait for EncryptedExtensions
|
||||
MG_TLS_STATE_CLIENT_WAIT_CERT, // Wait for Certificate
|
||||
MG_TLS_STATE_CLIENT_WAIT_CV, // Wait for CertificateVerify
|
||||
MG_TLS_STATE_CLIENT_WAIT_FINISH, // Wait for Finish
|
||||
MG_TLS_STATE_CLIENT_CONNECTED, // Done
|
||||
|
||||
// Server state machine:
|
||||
MG_TLS_STATE_SERVER_START, // Wait for ClientHello
|
||||
MG_TLS_STATE_SERVER_NEGOTIATED, // Wait for Finished
|
||||
MG_TLS_STATE_SERVER_NEGOTIATED, // Wait for Finish
|
||||
MG_TLS_STATE_SERVER_CONNECTED // Done
|
||||
};
|
||||
|
||||
@@ -150,10 +148,10 @@ static int mg_der_parse(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
|
||||
if (dersz < 2) return -1; // Invalid DER
|
||||
tlv->type = der[0];
|
||||
if (len > 0x7F) { // long-form length
|
||||
uint8_t len_bytes = len & 0x7F;
|
||||
uint8_t len_bytes = len & 0x7F, i;
|
||||
if (dersz < (size_t) (2 + len_bytes)) return -1;
|
||||
len = 0;
|
||||
for (uint8_t i = 0; i < len_bytes; i++) {
|
||||
for (i = 0; i < len_bytes; i++) {
|
||||
len = (len << 8) | der[2 + i];
|
||||
}
|
||||
header_len += len_bytes;
|
||||
@@ -165,8 +163,9 @@ static int mg_der_parse(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
|
||||
}
|
||||
|
||||
static int mg_der_next(struct mg_der_tlv *parent, struct mg_der_tlv *child) {
|
||||
int consumed;
|
||||
if (parent->len == 0) return 0;
|
||||
int consumed = mg_der_parse(parent->value, parent->len, child);
|
||||
consumed = mg_der_parse(parent->value, parent->len, child);
|
||||
if (consumed < 0) return -1;
|
||||
parent->value += consumed;
|
||||
parent->len -= (uint32_t) consumed;
|
||||
@@ -288,7 +287,7 @@ static void mg_tls_generate_handshake_keys(struct mg_connection *c) {
|
||||
uint8_t hello_hash[32];
|
||||
uint8_t server_hs_secret[32];
|
||||
uint8_t client_hs_secret[32];
|
||||
#if CHACHA20
|
||||
#if MG_ENABLE_CHACHA20
|
||||
const size_t keysz = 32;
|
||||
#else
|
||||
const size_t keysz = 16;
|
||||
@@ -352,7 +351,7 @@ static void mg_tls_generate_application_keys(struct mg_connection *c) {
|
||||
uint8_t master_secret[32];
|
||||
uint8_t server_secret[32];
|
||||
uint8_t client_secret[32];
|
||||
#if CHACHA20
|
||||
#if MG_ENABLE_CHACHA20
|
||||
const size_t keysz = 32;
|
||||
#else
|
||||
const size_t keysz = 16;
|
||||
@@ -416,7 +415,8 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
|
||||
uint8_t *iv =
|
||||
c->is_client ? tls->enc.client_write_iv : tls->enc.server_write_iv;
|
||||
|
||||
#if !CHACHA20
|
||||
#if MG_ENABLE_CHACHA20
|
||||
#else
|
||||
mg_gcm_initialize();
|
||||
#endif
|
||||
|
||||
@@ -424,7 +424,7 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
|
||||
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
|
||||
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
|
||||
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
|
||||
nonce[11] ^= (uint8_t) ((seq) &255U);
|
||||
nonce[11] ^= (uint8_t) ((seq) & 255U);
|
||||
|
||||
mg_iobuf_add(wio, wio->len, hdr, sizeof(hdr));
|
||||
mg_iobuf_resize(wio, wio->len + encsz);
|
||||
@@ -432,11 +432,11 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
|
||||
tag = wio->buf + wio->len + msgsz + 1;
|
||||
memmove(outmsg, msg, msgsz);
|
||||
outmsg[msgsz] = msgtype;
|
||||
#if CHACHA20
|
||||
#if MG_ENABLE_CHACHA20
|
||||
(void) tag; // tag is only used in aes gcm
|
||||
{
|
||||
size_t maxlen = MG_IO_SIZE > 16384 ? 16384 : MG_IO_SIZE;
|
||||
uint8_t *enc = (uint8_t *) calloc(1, maxlen + 256 + 1);
|
||||
uint8_t *enc = (uint8_t *) mg_calloc(1, maxlen + 256 + 1);
|
||||
if (enc == NULL) {
|
||||
mg_error(c, "TLS OOM");
|
||||
return;
|
||||
@@ -445,7 +445,7 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
|
||||
sizeof(associated_data), outmsg,
|
||||
msgsz + 1);
|
||||
memmove(outmsg, enc, n);
|
||||
free(enc);
|
||||
mg_free(enc);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -503,10 +503,10 @@ static int mg_tls_recv_record(struct mg_connection *c) {
|
||||
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
|
||||
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
|
||||
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
|
||||
nonce[11] ^= (uint8_t) ((seq) &255U);
|
||||
#if CHACHA20
|
||||
nonce[11] ^= (uint8_t) ((seq) & 255U);
|
||||
#if MG_ENABLE_CHACHA20
|
||||
{
|
||||
uint8_t *dec = (uint8_t *) calloc(1, msgsz);
|
||||
uint8_t *dec = (uint8_t *) mg_calloc(1, msgsz);
|
||||
size_t n;
|
||||
if (dec == NULL) {
|
||||
mg_error(c, "TLS OOM");
|
||||
@@ -514,7 +514,7 @@ static int mg_tls_recv_record(struct mg_connection *c) {
|
||||
}
|
||||
n = mg_chacha20_poly1305_decrypt(dec, key, nonce, msg, msgsz);
|
||||
memmove(msg, dec, n);
|
||||
free(dec);
|
||||
mg_free(dec);
|
||||
}
|
||||
#else
|
||||
mg_gcm_initialize();
|
||||
@@ -594,6 +594,7 @@ static int mg_tls_server_recv_hello(struct mg_connection *c) {
|
||||
uint16_t key_exchange_len;
|
||||
uint8_t *key_exchange;
|
||||
uint16_t n = MG_LOAD_BE16(ext + j + 2);
|
||||
if (((uint32_t) n + j + 4) > ext_len) goto fail;
|
||||
if (MG_LOAD_BE16(ext + j) != 0x0033) { // not a key share extension, ignore
|
||||
j += (uint16_t) (n + 4);
|
||||
continue;
|
||||
@@ -637,7 +638,7 @@ static void mg_tls_server_send_hello(struct mg_connection *c) {
|
||||
PLACEHOLDER_32B,
|
||||
// session ID length + session ID (32 bytes)
|
||||
0x20, PLACEHOLDER_32B,
|
||||
#if defined(CHACHA20) && CHACHA20
|
||||
#if MG_ENABLE_CHACHA20
|
||||
// TLS_CHACHA20_POLY1305_SHA256 + no compression
|
||||
0x13, 0x03, 0x00,
|
||||
#else
|
||||
@@ -687,7 +688,7 @@ static void mg_tls_server_send_cert(struct mg_connection *c) {
|
||||
int send_ca = !c->is_client && tls->ca_der.len > 0;
|
||||
// server DER certificate + CA (optional)
|
||||
size_t n = tls->cert_der.len + (send_ca ? tls->ca_der.len + 5 : 0);
|
||||
uint8_t *cert = (uint8_t *) calloc(1, 13 + n);
|
||||
uint8_t *cert = (uint8_t *) mg_calloc(1, 13 + n);
|
||||
if (cert == NULL) {
|
||||
mg_error(c, "tls cert oom");
|
||||
return;
|
||||
@@ -710,7 +711,7 @@ static void mg_tls_server_send_cert(struct mg_connection *c) {
|
||||
}
|
||||
mg_sha256_update(&tls->sha256, cert, 13 + n);
|
||||
mg_tls_encrypt(c, cert, 13 + n, MG_TLS_HANDSHAKE);
|
||||
free(cert);
|
||||
mg_free(cert);
|
||||
}
|
||||
|
||||
// type adapter between uECC hash context and our sha256 implementation
|
||||
@@ -774,7 +775,6 @@ static void mg_tls_send_cert_verify(struct mg_connection *c, int is_client) {
|
||||
|
||||
static void mg_tls_server_send_finish(struct mg_connection *c) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
struct mg_iobuf *wio = &tls->send;
|
||||
mg_sha256_ctx sha256;
|
||||
uint8_t hash[32];
|
||||
uint8_t finish[36] = {0x14, 0, 0, 32};
|
||||
@@ -782,9 +782,6 @@ static void mg_tls_server_send_finish(struct mg_connection *c) {
|
||||
mg_sha256_final(hash, &sha256);
|
||||
mg_hmac_sha256(finish + 4, tls->enc.server_finished_key, 32, hash, 32);
|
||||
mg_tls_encrypt(c, finish, sizeof(finish), MG_TLS_HANDSHAKE);
|
||||
mg_io_send(c, wio->buf, wio->len);
|
||||
wio->len = 0;
|
||||
|
||||
mg_sha256_update(&tls->sha256, finish, sizeof(finish));
|
||||
}
|
||||
|
||||
@@ -840,7 +837,7 @@ static void mg_tls_client_send_hello(struct mg_connection *c) {
|
||||
// session ID length + session ID (32 bytes)
|
||||
0x20, PLACEHOLDER_32B, 0x00,
|
||||
0x02, // size = 2 bytes
|
||||
#if defined(CHACHA20) && CHACHA20
|
||||
#if MG_ENABLE_CHACHA20
|
||||
// TLS_CHACHA20_POLY1305_SHA256
|
||||
0x13, 0x03,
|
||||
#else
|
||||
@@ -909,8 +906,6 @@ static void mg_tls_client_send_hello(struct mg_connection *c) {
|
||||
|
||||
// change cipher message
|
||||
mg_iobuf_add(wio, wio->len, (const char *) "\x14\x03\x03\x00\x01\x01", 6);
|
||||
mg_io_send(c, wio->buf, wio->len);
|
||||
wio->len = 0;
|
||||
}
|
||||
|
||||
static int mg_tls_client_recv_hello(struct mg_connection *c) {
|
||||
@@ -994,6 +989,7 @@ struct mg_tls_cert {
|
||||
int is_ec_pubkey;
|
||||
struct mg_str sn;
|
||||
struct mg_str pubkey;
|
||||
struct mg_der_tlv subj;
|
||||
struct mg_str sig; // signature
|
||||
uint8_t tbshash[48]; // 32b for sha256/secp256, 48b for sha384/secp384
|
||||
size_t tbshashsz; // actual TBS hash size
|
||||
@@ -1050,22 +1046,25 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
|
||||
MG_VERBOSE(("sig algo (oid): %M", mg_print_hex, algo.len, algo.value));
|
||||
// Signature algorithm OID mapping
|
||||
if (memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x02", algo.len) == 0) {
|
||||
if (algo.len == 8 &&
|
||||
memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x02", 8) == 0) {
|
||||
MG_VERBOSE(("sig algo: ECDSA with SHA256"));
|
||||
mg_sha256(cert->tbshash, tbs, tbssz);
|
||||
cert->tbshashsz = 32;
|
||||
} else if (memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B",
|
||||
algo.len) == 0) {
|
||||
} else if (algo.len == 9 &&
|
||||
memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B", 9) ==
|
||||
0) {
|
||||
MG_VERBOSE(("sig algo: RSA with SHA256"));
|
||||
mg_sha256(cert->tbshash, tbs, tbssz);
|
||||
cert->tbshashsz = 32;
|
||||
} else if (memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x03", algo.len) ==
|
||||
0) {
|
||||
} else if (algo.len == 8 &&
|
||||
memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x03", 8) == 0) {
|
||||
MG_VERBOSE(("sig algo: ECDSA with SHA384"));
|
||||
mg_sha384(cert->tbshash, tbs, tbssz);
|
||||
cert->tbshashsz = 48;
|
||||
} else if (memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C",
|
||||
algo.len) == 0) {
|
||||
} else if (algo.len == 9 &&
|
||||
memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C", 9) ==
|
||||
0) {
|
||||
MG_VERBOSE(("sig algo: RSA with SHA384"));
|
||||
mg_sha384(cert->tbshash, tbs, tbssz);
|
||||
cert->tbshashsz = 48;
|
||||
@@ -1086,7 +1085,7 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
struct mg_der_tlv before, after;
|
||||
mg_der_next(&field, &before);
|
||||
mg_der_next(&field, &after);
|
||||
if (memcmp(after.value, "250101000000Z", after.len) < 0) {
|
||||
if (after.len == 13 && memcmp(after.value, "250101000000Z", 13) < 0) {
|
||||
MG_ERROR(("invalid validity dates: before=%M after=%M", mg_print_hex,
|
||||
before.len, before.value, mg_print_hex, after.len,
|
||||
after.value));
|
||||
@@ -1096,6 +1095,7 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
|
||||
// subject
|
||||
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
|
||||
cert->subj = field;
|
||||
mg_der_debug_cert_name("subject", &field);
|
||||
|
||||
// subject public key info
|
||||
@@ -1106,20 +1106,22 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
|
||||
// public key algorithm
|
||||
MG_VERBOSE(("pk algo (oid): %M", mg_print_hex, pki_algo.len, pki_algo.value));
|
||||
if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x07",
|
||||
pki_algo.len) == 0) {
|
||||
if (pki_algo.len == 8 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8) == 0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
MG_VERBOSE(("pk algo: ECDSA secp256r1"));
|
||||
} else if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x08",
|
||||
pki_algo.len) == 0) {
|
||||
} else if (pki_algo.len == 8 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x08", 8) ==
|
||||
0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
MG_VERBOSE(("pk algo: ECDSA secp384r1"));
|
||||
} else if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x02\x01",
|
||||
pki_algo.len) == 0) {
|
||||
} else if (pki_algo.len == 7 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x02\x01", 7) == 0) {
|
||||
cert->is_ec_pubkey = 1;
|
||||
MG_VERBOSE(("pk algo: EC public key"));
|
||||
} else if (memcmp(pki_algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01",
|
||||
pki_algo.len) == 0) {
|
||||
} else if (pki_algo.len == 9 &&
|
||||
memcmp(pki_algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01",
|
||||
9) == 0) {
|
||||
cert->is_ec_pubkey = 0;
|
||||
MG_VERBOSE(("pk algo: RSA"));
|
||||
} else {
|
||||
@@ -1154,19 +1156,22 @@ static int mg_tls_parse_cert_der(void *buf, size_t dersz,
|
||||
static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
|
||||
const char *server_name) {
|
||||
struct mg_der_tlv root, field, name;
|
||||
if (mg_der_parse((uint8_t *) der, dersz, &root) < 0 ||
|
||||
mg_der_find_oid(&root, (uint8_t *) "\x55\x1d\x11", 3, &field) < 0) {
|
||||
MG_ERROR(("failed to parse certificate to extract SAN"));
|
||||
if (mg_der_parse((uint8_t *) der, dersz, &root) < 0) {
|
||||
MG_ERROR(("failed to parse certificate"));
|
||||
return -1;
|
||||
}
|
||||
if (mg_der_find_oid(&root, (uint8_t *) "\x55\x1d\x11", 3, &field) <= 0) {
|
||||
MG_ERROR(("failed to extract SAN"));
|
||||
return -1;
|
||||
}
|
||||
if (mg_der_parse(field.value, field.len, &field) < 0) {
|
||||
MG_ERROR(
|
||||
("certificate subject alternative names is not a constructed object"));
|
||||
MG_ERROR(("SAN is not a constructed object"));
|
||||
return -1;
|
||||
}
|
||||
while (mg_der_next(&field, &name) > 0) {
|
||||
if (mg_match(mg_str(server_name),
|
||||
mg_str_n((const char *) name.value, name.len), NULL)) {
|
||||
MG_DEBUG(("Found SAN: %.*s", name.len, name.value));
|
||||
if (mg_match(mg_str(server_name), mg_str_n((char *) name.value, name.len),
|
||||
NULL)) {
|
||||
// Found SAN that matches the host name
|
||||
return 1;
|
||||
}
|
||||
@@ -1222,11 +1227,19 @@ static int mg_tls_verify_cert_signature(const struct mg_tls_cert *cert,
|
||||
}
|
||||
}
|
||||
|
||||
static int mg_tls_verify_cert_cn(struct mg_der_tlv *subj, const char *host) {
|
||||
struct mg_der_tlv v;
|
||||
int matched = 0;
|
||||
if (mg_der_find_oid(subj, (uint8_t *) "\x55\x04\x03", 3, &v) > 0) {
|
||||
MG_DEBUG(("using CN: %.*s <-> %s", v.len, v.value, host));
|
||||
matched = mg_match(mg_str(host), mg_str_n((char *) v.value, v.len), NULL);
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
static int mg_tls_client_recv_cert(struct mg_connection *c) {
|
||||
int subj_match = 0;
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
unsigned char *recv_buf;
|
||||
(void) subj_match;
|
||||
|
||||
if (mg_tls_recv_record(c) < 0) {
|
||||
return -1;
|
||||
@@ -1251,91 +1264,92 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t full_cert_chain_len = MG_LOAD_BE24(recv_buf + 1);
|
||||
uint32_t cert_chain_len = MG_LOAD_BE24(recv_buf + 5);
|
||||
if (cert_chain_len != full_cert_chain_len - 4) {
|
||||
MG_ERROR(("full chain length: %d, chain length: %d", full_cert_chain_len,
|
||||
cert_chain_len));
|
||||
mg_error(c, "certificate chain length mismatch");
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
// Normally, there are 2-3 certs in a chain
|
||||
struct mg_tls_cert certs[8];
|
||||
int certnum = 0;
|
||||
uint32_t full_cert_chain_len = MG_LOAD_BE24(recv_buf + 1);
|
||||
uint32_t cert_chain_len = MG_LOAD_BE24(recv_buf + 5);
|
||||
uint8_t *p = recv_buf + 8;
|
||||
uint8_t *endp = recv_buf + cert_chain_len;
|
||||
bool found_ca = false;
|
||||
struct mg_tls_cert ca;
|
||||
|
||||
// Normally, there are 2-3 certs in a chain
|
||||
struct mg_tls_cert certs[8];
|
||||
int certnum = 0;
|
||||
uint8_t *p = recv_buf + 8;
|
||||
// uint8_t *endp = recv_buf + tls->recv_len;
|
||||
uint8_t *endp = recv_buf + cert_chain_len;
|
||||
|
||||
int found_ca = 0;
|
||||
struct mg_tls_cert ca;
|
||||
|
||||
memset(certs, 0, sizeof(certs));
|
||||
memset(&ca, 0, sizeof(ca));
|
||||
|
||||
if (tls->ca_der.len > 0) {
|
||||
if (mg_tls_parse_cert_der(tls->ca_der.buf, tls->ca_der.len, &ca) < 0) {
|
||||
mg_error(c, "failed to parse CA certificate");
|
||||
return -1;
|
||||
}
|
||||
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
|
||||
}
|
||||
|
||||
while (p < endp) {
|
||||
struct mg_tls_cert *ci = &certs[certnum++];
|
||||
uint32_t certsz = MG_LOAD_BE24(p);
|
||||
uint8_t *cert = p + 3;
|
||||
uint16_t certext = MG_LOAD_BE16(cert + certsz);
|
||||
if (certext != 0) {
|
||||
mg_error(c, "certificate extensions are not supported");
|
||||
return -1;
|
||||
}
|
||||
p = cert + certsz + 2;
|
||||
|
||||
if (mg_tls_parse_cert_der(cert, certsz, ci) < 0) {
|
||||
mg_error(c, "failed to parse certificate");
|
||||
if (cert_chain_len != full_cert_chain_len - 4) {
|
||||
MG_ERROR(("full chain length: %d, chain length: %d", full_cert_chain_len,
|
||||
cert_chain_len));
|
||||
mg_error(c, "certificate chain length mismatch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ci == certs) {
|
||||
// First certificate in the chain is peer cert, check SAN and store
|
||||
// public key for further CertVerify step
|
||||
if (mg_tls_verify_cert_san(cert, certsz, tls->hostname) <= 0) {
|
||||
mg_error(c, "failed to verify hostname");
|
||||
memset(certs, 0, sizeof(certs));
|
||||
memset(&ca, 0, sizeof(ca));
|
||||
|
||||
if (tls->ca_der.len > 0) {
|
||||
if (mg_tls_parse_cert_der(tls->ca_der.buf, tls->ca_der.len, &ca) < 0) {
|
||||
mg_error(c, "failed to parse CA certificate");
|
||||
return -1;
|
||||
}
|
||||
memmove(tls->pubkey, ci->pubkey.buf, ci->pubkey.len);
|
||||
tls->pubkeysz = ci->pubkey.len;
|
||||
} else {
|
||||
if (!mg_tls_verify_cert_signature(ci - 1, ci)) {
|
||||
mg_error(c, "failed to verify certificate chain");
|
||||
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
|
||||
}
|
||||
|
||||
while (p < endp) {
|
||||
struct mg_tls_cert *ci = &certs[certnum++];
|
||||
uint32_t certsz = MG_LOAD_BE24(p);
|
||||
uint8_t *cert = p + 3;
|
||||
uint16_t certext = MG_LOAD_BE16(cert + certsz);
|
||||
if (certext != 0) {
|
||||
mg_error(c, "certificate extensions are not supported");
|
||||
return -1;
|
||||
}
|
||||
p = cert + certsz + 2;
|
||||
|
||||
if (mg_tls_parse_cert_der(cert, certsz, ci) < 0) {
|
||||
mg_error(c, "failed to parse certificate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ci == certs) {
|
||||
// First certificate in the chain is peer cert, check SAN and store
|
||||
// public key for further CertVerify step
|
||||
if (mg_tls_verify_cert_san(cert, certsz, tls->hostname) <= 0 &&
|
||||
mg_tls_verify_cert_cn(&ci->subj, tls->hostname) <= 0) {
|
||||
mg_error(c, "failed to verify hostname");
|
||||
return -1;
|
||||
}
|
||||
memmove(tls->pubkey, ci->pubkey.buf, ci->pubkey.len);
|
||||
tls->pubkeysz = ci->pubkey.len;
|
||||
} else {
|
||||
if (!mg_tls_verify_cert_signature(ci - 1, ci)) {
|
||||
mg_error(c, "failed to verify certificate chain");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ca.pubkey.len == ci->pubkey.len &&
|
||||
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
|
||||
found_ca = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (certnum == sizeof(certs) / sizeof(certs[0]) - 1) {
|
||||
mg_error(c, "too many certificates in the chain");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ca.pubkey.len == ci->pubkey.len &&
|
||||
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
|
||||
found_ca = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (certnum == sizeof(certs) / sizeof(certs[0]) - 1) {
|
||||
mg_error(c, "too many certificates in the chain");
|
||||
return -1;
|
||||
if (!found_ca && tls->ca_der.len > 0) {
|
||||
if (certnum < 1 ||
|
||||
!mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
|
||||
mg_error(c, "failed to verify CA");
|
||||
return -1;
|
||||
} else {
|
||||
MG_VERBOSE(
|
||||
("CA was not in the chain, but verification with builtin CA "
|
||||
"passed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_ca && tls->ca_der.len > 0) {
|
||||
if (certnum < 1 ||
|
||||
!mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
|
||||
mg_error(c, "failed to verify CA");
|
||||
return -1;
|
||||
} else {
|
||||
MG_VERBOSE(
|
||||
("CA was not in the chain, but verification with builtin CA passed"));
|
||||
}
|
||||
}
|
||||
|
||||
mg_tls_drop_message(c);
|
||||
mg_tls_calc_cert_verify_hash(c, tls->sighash, 0);
|
||||
return 0;
|
||||
@@ -1365,78 +1379,80 @@ static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t sigalg = MG_LOAD_BE16(recv_buf + 4);
|
||||
uint16_t siglen = MG_LOAD_BE16(recv_buf + 6);
|
||||
uint8_t *sigbuf = recv_buf + 8;
|
||||
if (siglen > tls->recv_len - 8) {
|
||||
mg_error(c, "invalid certverify signature length: %d, expected %d", siglen,
|
||||
tls->recv_len - 8);
|
||||
return -1;
|
||||
}
|
||||
MG_VERBOSE(
|
||||
("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
|
||||
|
||||
if (sigalg == 0x0804) { // rsa_pss_rsae_sha256
|
||||
uint8_t sig2[512]; // 2048 or 4096 bits
|
||||
struct mg_der_tlv seq, modulus, exponent;
|
||||
|
||||
if (mg_der_parse(tls->pubkey, tls->pubkeysz, &seq) <= 0 ||
|
||||
mg_der_next(&seq, &modulus) <= 0 || modulus.type != 2 ||
|
||||
mg_der_next(&seq, &exponent) <= 0 || exponent.type != 2) {
|
||||
mg_error(c, "invalid public key");
|
||||
{
|
||||
uint16_t sigalg = MG_LOAD_BE16(recv_buf + 4);
|
||||
uint16_t siglen = MG_LOAD_BE16(recv_buf + 6);
|
||||
uint8_t *sigbuf = recv_buf + 8;
|
||||
if (siglen > tls->recv_len - 8) {
|
||||
mg_error(c, "invalid certverify signature length: %d, expected %d",
|
||||
siglen, tls->recv_len - 8);
|
||||
return -1;
|
||||
}
|
||||
MG_VERBOSE(
|
||||
("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
|
||||
|
||||
mg_rsa_mod_pow(modulus.value, modulus.len, exponent.value, exponent.len,
|
||||
sigbuf, siglen, sig2, sizeof(sig2));
|
||||
if (sigalg == 0x0804) { // rsa_pss_rsae_sha256
|
||||
uint8_t sig2[512]; // 2048 or 4096 bits
|
||||
struct mg_der_tlv seq, modulus, exponent;
|
||||
|
||||
if (sig2[sizeof(sig2) - 1] != 0xbc) {
|
||||
mg_error(c, "failed to verify RSA certificate (certverify)");
|
||||
return -1;
|
||||
}
|
||||
MG_DEBUG(("certificate verification successful (RSA)"));
|
||||
} else if (sigalg == 0x0403) { // ecdsa_secp256r1_sha256
|
||||
// Extract certificate signature and verify it using pubkey and sighash
|
||||
uint8_t sig[64];
|
||||
struct mg_der_tlv seq, r, s;
|
||||
if (mg_der_to_tlv(sigbuf, siglen, &seq) < 0) {
|
||||
mg_error(c, "verification message is not an ASN.1 DER sequence");
|
||||
return -1;
|
||||
}
|
||||
if (mg_der_to_tlv(seq.value, seq.len, &r) < 0) {
|
||||
mg_error(c, "missing first part of the signature");
|
||||
return -1;
|
||||
}
|
||||
if (mg_der_to_tlv(r.value + r.len, seq.len - r.len, &s) < 0) {
|
||||
mg_error(c, "missing second part of the signature");
|
||||
return -1;
|
||||
}
|
||||
// Integers may be padded with zeroes
|
||||
if (r.len > 32) r.value = r.value + (r.len - 32), r.len = 32;
|
||||
if (s.len > 32) s.value = s.value + (s.len - 32), s.len = 32;
|
||||
if (mg_der_parse(tls->pubkey, tls->pubkeysz, &seq) <= 0 ||
|
||||
mg_der_next(&seq, &modulus) <= 0 || modulus.type != 2 ||
|
||||
mg_der_next(&seq, &exponent) <= 0 || exponent.type != 2) {
|
||||
mg_error(c, "invalid public key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memmove(sig, r.value, r.len);
|
||||
memmove(sig + 32, s.value, s.len);
|
||||
mg_rsa_mod_pow(modulus.value, modulus.len, exponent.value, exponent.len,
|
||||
sigbuf, siglen, sig2, sizeof(sig2));
|
||||
|
||||
if (mg_uecc_verify(tls->pubkey, tls->sighash, sizeof(tls->sighash), sig,
|
||||
mg_uecc_secp256r1()) != 1) {
|
||||
mg_error(c, "failed to verify EC certificate (certverify)");
|
||||
if (sig2[sizeof(sig2) - 1] != 0xbc) {
|
||||
mg_error(c, "failed to verify RSA certificate (certverify)");
|
||||
return -1;
|
||||
}
|
||||
MG_DEBUG(("certificate verification successful (RSA)"));
|
||||
} else if (sigalg == 0x0403) { // ecdsa_secp256r1_sha256
|
||||
// Extract certificate signature and verify it using pubkey and sighash
|
||||
uint8_t sig[64];
|
||||
struct mg_der_tlv seq, r, s;
|
||||
if (mg_der_to_tlv(sigbuf, siglen, &seq) < 0) {
|
||||
mg_error(c, "verification message is not an ASN.1 DER sequence");
|
||||
return -1;
|
||||
}
|
||||
if (mg_der_to_tlv(seq.value, seq.len, &r) < 0) {
|
||||
mg_error(c, "missing first part of the signature");
|
||||
return -1;
|
||||
}
|
||||
if (mg_der_to_tlv(r.value + r.len, seq.len - r.len, &s) < 0) {
|
||||
mg_error(c, "missing second part of the signature");
|
||||
return -1;
|
||||
}
|
||||
// Integers may be padded with zeroes
|
||||
if (r.len > 32) r.value = r.value + (r.len - 32), r.len = 32;
|
||||
if (s.len > 32) s.value = s.value + (s.len - 32), s.len = 32;
|
||||
|
||||
memmove(sig, r.value, r.len);
|
||||
memmove(sig + 32, s.value, s.len);
|
||||
|
||||
if (mg_uecc_verify(tls->pubkey, tls->sighash, sizeof(tls->sighash), sig,
|
||||
mg_uecc_secp256r1()) != 1) {
|
||||
mg_error(c, "failed to verify EC certificate (certverify)");
|
||||
return -1;
|
||||
}
|
||||
MG_DEBUG(("certificate verification successful (EC)"));
|
||||
} else {
|
||||
// From
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml:
|
||||
// 0805 = rsa_pss_rsae_sha384
|
||||
// 0806 = rsa_pss_rsae_sha512
|
||||
// 0807 = ed25519
|
||||
// 0808 = ed448
|
||||
// 0809 = rsa_pss_pss_sha256
|
||||
// 080A = rsa_pss_pss_sha384
|
||||
// 080B = rsa_pss_pss_sha512
|
||||
MG_ERROR(("unsupported certverify signature scheme: %x of %d bytes",
|
||||
sigalg, siglen));
|
||||
return -1;
|
||||
}
|
||||
MG_DEBUG(("certificate verification successful (EC)"));
|
||||
} else {
|
||||
// From
|
||||
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml:
|
||||
// 0805 = rsa_pss_rsae_sha384
|
||||
// 0806 = rsa_pss_rsae_sha512
|
||||
// 0807 = ed25519
|
||||
// 0808 = ed448
|
||||
// 0809 = rsa_pss_pss_sha256
|
||||
// 080A = rsa_pss_pss_sha384
|
||||
// 080B = rsa_pss_pss_sha512
|
||||
MG_ERROR(("unsupported certverify signature scheme: %x of %d bytes", sigalg,
|
||||
siglen));
|
||||
return -1;
|
||||
}
|
||||
mg_tls_drop_message(c);
|
||||
return 0;
|
||||
@@ -1459,7 +1475,6 @@ static int mg_tls_client_recv_finish(struct mg_connection *c) {
|
||||
|
||||
static void mg_tls_client_send_finish(struct mg_connection *c) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
struct mg_iobuf *wio = &tls->send;
|
||||
mg_sha256_ctx sha256;
|
||||
uint8_t hash[32];
|
||||
uint8_t finish[36] = {0x14, 0, 0, 32};
|
||||
@@ -1467,8 +1482,6 @@ static void mg_tls_client_send_finish(struct mg_connection *c) {
|
||||
mg_sha256_final(hash, &sha256);
|
||||
mg_hmac_sha256(finish + 4, tls->enc.client_finished_key, 32, hash, 32);
|
||||
mg_tls_encrypt(c, finish, sizeof(finish), MG_TLS_HANDSHAKE);
|
||||
mg_io_send(c, wio->buf, wio->len);
|
||||
wio->len = 0;
|
||||
}
|
||||
|
||||
static void mg_tls_client_handshake(struct mg_connection *c) {
|
||||
@@ -1500,9 +1513,9 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
|
||||
if (mg_tls_client_recv_cert_verify(c) < 0) {
|
||||
break;
|
||||
}
|
||||
tls->state = MG_TLS_STATE_CLIENT_WAIT_FINISHED;
|
||||
tls->state = MG_TLS_STATE_CLIENT_WAIT_FINISH;
|
||||
// Fallthrough
|
||||
case MG_TLS_STATE_CLIENT_WAIT_FINISHED:
|
||||
case MG_TLS_STATE_CLIENT_WAIT_FINISH:
|
||||
if (mg_tls_client_recv_finish(c) < 0) {
|
||||
break;
|
||||
}
|
||||
@@ -1527,9 +1540,7 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
|
||||
c->is_tls_hs = 0;
|
||||
mg_call(c, MG_EV_TLS_HS, NULL);
|
||||
break;
|
||||
default:
|
||||
mg_error(c, "unexpected client state: %d", tls->state);
|
||||
break;
|
||||
default: mg_error(c, "unexpected client state: %d", tls->state); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1556,18 +1567,24 @@ static void mg_tls_server_handshake(struct mg_connection *c) {
|
||||
tls->state = MG_TLS_STATE_SERVER_CONNECTED;
|
||||
c->is_tls_hs = 0;
|
||||
return;
|
||||
default:
|
||||
mg_error(c, "unexpected server state: %d", tls->state);
|
||||
break;
|
||||
default: mg_error(c, "unexpected server state: %d", tls->state); break;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_tls_handshake(struct mg_connection *c) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
long n;
|
||||
if (c->is_client) {
|
||||
// will clear is_hs when sending last chunk
|
||||
mg_tls_client_handshake(c);
|
||||
} else {
|
||||
mg_tls_server_handshake(c);
|
||||
}
|
||||
while (tls->send.len > 0 &&
|
||||
(n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) {
|
||||
mg_iobuf_del(&tls->send, 0, (size_t) n);
|
||||
} // if last chunk fails to be sent, it will be sent with first app data,
|
||||
// otherwise, it needs to be flushed
|
||||
}
|
||||
|
||||
static int mg_parse_pem(const struct mg_str pem, const struct mg_str label,
|
||||
@@ -1583,7 +1600,7 @@ static int mg_parse_pem(const struct mg_str pem, const struct mg_str label,
|
||||
if (mg_strcmp(caps[1], label) != 0 || mg_strcmp(caps[3], label) != 0) {
|
||||
return -1; // bad label
|
||||
}
|
||||
if ((s = (char *) calloc(1, caps[2].len)) == NULL) {
|
||||
if ((s = (char *) mg_calloc(1, caps[2].len)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1595,7 +1612,7 @@ static int mg_parse_pem(const struct mg_str pem, const struct mg_str label,
|
||||
}
|
||||
m = mg_base64_decode(s, n, s, n);
|
||||
if (m == 0) {
|
||||
free(s);
|
||||
mg_free(s);
|
||||
return -1;
|
||||
}
|
||||
der->buf = s;
|
||||
@@ -1605,7 +1622,8 @@ static int mg_parse_pem(const struct mg_str pem, const struct mg_str label,
|
||||
|
||||
void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
struct mg_str key;
|
||||
struct tls_data *tls = (struct tls_data *) calloc(1, sizeof(struct tls_data));
|
||||
struct tls_data *tls =
|
||||
(struct tls_data *) mg_calloc(1, sizeof(struct tls_data));
|
||||
if (tls == NULL) {
|
||||
mg_error(c, "tls oom");
|
||||
return;
|
||||
@@ -1670,7 +1688,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
MG_ERROR(("EC private key: ASN.1 bad data"));
|
||||
}
|
||||
memmove(tls->ec_key, key.buf + 7, 32);
|
||||
free((void *) key.buf);
|
||||
mg_free((void *) key.buf);
|
||||
} else if (mg_parse_pem(opts->key, mg_str_s("PRIVATE KEY"), &key) == 0) {
|
||||
mg_error(c, "PKCS8 private key format is not supported");
|
||||
} else {
|
||||
@@ -1682,10 +1700,10 @@ void mg_tls_free(struct mg_connection *c) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
if (tls != NULL) {
|
||||
mg_iobuf_free(&tls->send);
|
||||
free((void *) tls->cert_der.buf);
|
||||
free((void *) tls->ca_der.buf);
|
||||
mg_free((void *) tls->cert_der.buf);
|
||||
mg_free((void *) tls->ca_der.buf);
|
||||
}
|
||||
free(c->tls);
|
||||
mg_free(c->tls);
|
||||
c->tls = NULL;
|
||||
}
|
||||
|
||||
@@ -1701,7 +1719,7 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
while (tls->send.len > 0 &&
|
||||
(n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) {
|
||||
mg_iobuf_del(&tls->send, 0, (size_t) n);
|
||||
}
|
||||
} // if last chunk fails to be sent, it needs to be flushed
|
||||
c->is_tls_throttled = (tls->send.len > 0 && n == MG_IO_WAIT);
|
||||
MG_VERBOSE(("%lu %ld %ld %ld %c %c", c->id, (long) len, (long) tls->send.len,
|
||||
n, was_throttled ? 'T' : 't', c->is_tls_throttled ? 'T' : 't'));
|
||||
@@ -1743,6 +1761,15 @@ size_t mg_tls_pending(struct mg_connection *c) {
|
||||
return tls != NULL ? tls->recv_len : 0;
|
||||
}
|
||||
|
||||
void mg_tls_flush(struct mg_connection *c) {
|
||||
struct tls_data *tls = (struct tls_data *) c->tls;
|
||||
long n;
|
||||
while (tls->send.len > 0 &&
|
||||
(n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) {
|
||||
mg_iobuf_del(&tls->send, 0, (size_t) n);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_tls_ctx_init(struct mg_mgr *mgr) {
|
||||
(void) mgr;
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#if defined(_MSC_VER) || defined(__cplusplus)
|
||||
// add restrict support
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || defined(__clang__) || \
|
||||
defined(__GNUC__)
|
||||
#if ((defined(_MSC_VER) && _MSC_VER >= 1900) && !defined(__cplusplus)) || \
|
||||
defined(__clang__) || defined(__GNUC__)
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#include "arch.h"
|
||||
#include "config.h"
|
||||
#include "tls.h"
|
||||
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
#ifndef __PORTABLE_8439_H
|
||||
#define __PORTABLE_8439_H
|
||||
#if defined(__cplusplus)
|
||||
@@ -108,3 +110,4 @@ PORTABLE_8439_DECL size_t mg_chacha20_poly1305_decrypt(
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -21,6 +21,9 @@ size_t mg_tls_pending(struct mg_connection *c) {
|
||||
(void) c;
|
||||
return 0;
|
||||
}
|
||||
void mg_tls_flush(struct mg_connection *c) {
|
||||
(void) c;
|
||||
}
|
||||
void mg_tls_ctx_init(struct mg_mgr *mgr) {
|
||||
(void) mgr;
|
||||
}
|
||||
|
||||
+28
-10
@@ -1,5 +1,8 @@
|
||||
#include "log.h"
|
||||
#include "printf.h"
|
||||
#include "profile.h"
|
||||
#include "tls.h"
|
||||
#include "util.h"
|
||||
|
||||
#if MG_TLS == MG_TLS_MBED
|
||||
|
||||
@@ -9,6 +12,13 @@
|
||||
#define MG_MBEDTLS_RNG_GET
|
||||
#endif
|
||||
|
||||
static int mg_tls_err(struct mg_connection *c, int rc) {
|
||||
char s[80];
|
||||
mbedtls_strerror(rc, s, sizeof(s));
|
||||
MG_ERROR(("%lu %s", ((struct mg_connection *) c)->id, s));
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mg_mbed_rng(void *ctx, unsigned char *buf, size_t len) {
|
||||
mg_random(buf, len);
|
||||
(void) ctx;
|
||||
@@ -49,7 +59,7 @@ void mg_tls_free(struct mg_connection *c) {
|
||||
#ifdef MBEDTLS_SSL_SESSION_TICKETS
|
||||
mbedtls_ssl_ticket_free(&tls->ticket);
|
||||
#endif
|
||||
free(tls);
|
||||
mg_free(tls);
|
||||
c->tls = NULL;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +94,7 @@ void mg_tls_handshake(struct mg_connection *c) {
|
||||
MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
|
||||
c->is_tls_hs, rc, -rc));
|
||||
} else {
|
||||
mg_error(c, "TLS handshake: -%#x", -rc); // Error
|
||||
mg_error(c, "TLS handshake: -%#x", -mg_tls_err(c, rc)); // Error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +105,7 @@ static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
|
||||
}
|
||||
|
||||
void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
|
||||
struct mg_tls *tls = (struct mg_tls *) mg_calloc(1, sizeof(*tls));
|
||||
int rc = 0;
|
||||
c->tls = tls;
|
||||
if (c->tls == NULL) {
|
||||
@@ -122,7 +132,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
&tls->conf,
|
||||
c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
mg_error(c, "tls defaults %#x", -rc);
|
||||
mg_error(c, "tls defaults %#x", -mg_tls_err(c, rc));
|
||||
goto fail;
|
||||
}
|
||||
mbedtls_ssl_conf_rng(&tls->conf, mg_mbed_rng, c);
|
||||
@@ -138,7 +148,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
char *host = mg_mprintf("%.*s", opts->name.len, opts->name.buf);
|
||||
mbedtls_ssl_set_hostname(&tls->ssl, host);
|
||||
MG_DEBUG(("%lu hostname verification: %s", c->id, host));
|
||||
free(host);
|
||||
mg_free(host);
|
||||
}
|
||||
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
}
|
||||
@@ -146,7 +156,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
if (!mg_load_key(opts->key, &tls->pk)) goto fail;
|
||||
if (tls->cert.version &&
|
||||
(rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk)) != 0) {
|
||||
mg_error(c, "own cert %#x", -rc);
|
||||
mg_error(c, "own cert %#x", -mg_tls_err(c, rc));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -157,7 +167,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
#endif
|
||||
|
||||
if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) {
|
||||
mg_error(c, "setup err %#x", -rc);
|
||||
mg_error(c, "setup err %#x", -mg_tls_err(c, rc));
|
||||
goto fail;
|
||||
}
|
||||
c->is_tls = 1;
|
||||
@@ -204,13 +214,21 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
tls->throttled_buf = (unsigned char *)buf; // MbedTLS code actually ignores
|
||||
tls->throttled_len = len; // these, but let's play API rules
|
||||
return (long) len; // already encripted that when throttled
|
||||
}
|
||||
} // if last chunk fails to be sent, it needs to be flushed
|
||||
if (n <= 0) return MG_IO_ERR;
|
||||
return n;
|
||||
}
|
||||
|
||||
void mg_tls_flush(struct mg_connection *c) {
|
||||
struct mg_tls *tls = (struct mg_tls *) c->tls;
|
||||
if (c->is_tls_throttled) {
|
||||
long n = mbedtls_ssl_write(&tls->ssl, tls->throttled_buf, tls->throttled_len);
|
||||
c->is_tls_throttled = (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_tls_ctx_init(struct mg_mgr *mgr) {
|
||||
struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx));
|
||||
struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mg_calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
MG_ERROR(("TLS context init OOM"));
|
||||
} else {
|
||||
@@ -233,7 +251,7 @@ void mg_tls_ctx_free(struct mg_mgr *mgr) {
|
||||
#ifdef MBEDTLS_SSL_SESSION_TICKETS
|
||||
mbedtls_ssl_ticket_free(&ctx->tickets);
|
||||
#endif
|
||||
free(ctx);
|
||||
mg_free(ctx);
|
||||
mgr->tls_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#if MG_TLS == MG_TLS_MBED
|
||||
#include <mbedtls/debug.h>
|
||||
#include <mbedtls/error.h>
|
||||
#include <mbedtls/net_sockets.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/ssl_ticket.h>
|
||||
|
||||
+9
-3
@@ -1,5 +1,6 @@
|
||||
#include "printf.h"
|
||||
#include "tls.h"
|
||||
#include "util.h"
|
||||
|
||||
#if MG_TLS == MG_TLS_OPENSSL || MG_TLS == MG_TLS_WOLFSSL
|
||||
|
||||
@@ -104,6 +105,7 @@ static void ssl_keylog_cb(const SSL *ssl, const char *line) {
|
||||
fprintf(f, "%s\n", line);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
(void) ssl;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -113,12 +115,12 @@ void mg_tls_free(struct mg_connection *c) {
|
||||
SSL_free(tls->ssl);
|
||||
SSL_CTX_free(tls->ctx);
|
||||
BIO_meth_free(tls->bm);
|
||||
free(tls);
|
||||
mg_free(tls);
|
||||
c->tls = NULL;
|
||||
}
|
||||
|
||||
void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
|
||||
struct mg_tls *tls = (struct mg_tls *) mg_calloc(1, sizeof(*tls));
|
||||
const char *id = "mongoose";
|
||||
static unsigned char s_initialised = 0;
|
||||
BIO *bio = NULL;
|
||||
@@ -211,7 +213,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
|
||||
X509_VERIFY_PARAM_set1_host(SSL_get0_param(tls->ssl), s, 0);
|
||||
#endif
|
||||
SSL_set_tlsext_host_name(tls->ssl, s);
|
||||
free(s);
|
||||
mg_free(s);
|
||||
}
|
||||
#endif
|
||||
#if MG_TLS == MG_TLS_WOLFSSL
|
||||
@@ -270,6 +272,10 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
return n;
|
||||
}
|
||||
|
||||
void mg_tls_flush(struct mg_connection *c) {
|
||||
(void) c;
|
||||
}
|
||||
|
||||
void mg_tls_ctx_init(struct mg_mgr *mgr) {
|
||||
(void) mgr;
|
||||
}
|
||||
|
||||
+36
-25
@@ -1,5 +1,6 @@
|
||||
#include "tls.h"
|
||||
#include "tls_rsa.h"
|
||||
#include "util.h"
|
||||
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
|
||||
@@ -62,7 +63,7 @@ typedef uint16_t comp; /**< A single precision component. */
|
||||
typedef uint32_t long_comp; /**< A double precision component. */
|
||||
typedef int32_t slong_comp; /**< A signed double precision component. */
|
||||
#else /* regular 32 bit */
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
#define COMP_RADIX 4294967296i64
|
||||
#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64
|
||||
#else
|
||||
@@ -158,10 +159,10 @@ typedef struct _BI_CTX BI_CTX;
|
||||
*/
|
||||
|
||||
NS_INTERNAL BI_CTX *bi_initialize(void);
|
||||
//NS_INTERNAL void bi_terminate(BI_CTX *ctx);
|
||||
NS_INTERNAL void bi_terminate(BI_CTX *ctx);
|
||||
NS_INTERNAL void bi_permanent(bigint *bi);
|
||||
NS_INTERNAL void bi_depermanent(bigint *bi);
|
||||
//NS_INTERNAL void bi_clear_cache(BI_CTX *ctx);
|
||||
NS_INTERNAL void bi_clear_cache(BI_CTX *ctx);
|
||||
NS_INTERNAL void bi_free(BI_CTX *ctx, bigint *bi);
|
||||
NS_INTERNAL bigint *bi_copy(bigint *bi);
|
||||
NS_INTERNAL bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
|
||||
@@ -183,7 +184,7 @@ NS_INTERNAL bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi,
|
||||
#endif
|
||||
NS_INTERNAL int bi_compare(bigint *bia, bigint *bib);
|
||||
NS_INTERNAL void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
|
||||
//NS_INTERNAL void bi_free_mod(BI_CTX *ctx, int mod_offset);
|
||||
NS_INTERNAL void bi_free_mod(BI_CTX *ctx, int mod_offset);
|
||||
|
||||
#ifdef CONFIG_SSL_FULL_MODE
|
||||
NS_INTERNAL void bi_print(const char *label, bigint *bi);
|
||||
@@ -309,8 +310,8 @@ static void check(const bigint *bi);
|
||||
* @return A bigint context.
|
||||
*/
|
||||
NS_INTERNAL BI_CTX *bi_initialize(void) {
|
||||
/* calloc() sets everything to zero */
|
||||
BI_CTX *ctx = (BI_CTX *) calloc(1, sizeof(BI_CTX));
|
||||
/* mg_calloc() sets everything to zero */
|
||||
BI_CTX *ctx = (BI_CTX *) mg_calloc(1, sizeof(BI_CTX));
|
||||
|
||||
/* the radix */
|
||||
ctx->bi_radix = alloc(ctx, 2);
|
||||
@@ -320,7 +321,6 @@ NS_INTERNAL BI_CTX *bi_initialize(void) {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Close the bigint context and free any resources.
|
||||
*
|
||||
@@ -340,7 +340,7 @@ NS_INTERNAL void bi_terminate(BI_CTX *ctx) {
|
||||
}
|
||||
|
||||
bi_clear_cache(ctx);
|
||||
free(ctx);
|
||||
mg_free(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,14 +353,13 @@ NS_INTERNAL void bi_clear_cache(BI_CTX *ctx) {
|
||||
|
||||
for (p = ctx->free_list; p != NULL; p = pn) {
|
||||
pn = p->next;
|
||||
free(p->comps);
|
||||
free(p);
|
||||
mg_free(p->comps);
|
||||
mg_free(p);
|
||||
}
|
||||
|
||||
ctx->free_count = 0;
|
||||
ctx->free_list = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Increment the number of references to this object.
|
||||
@@ -930,7 +929,6 @@ NS_INTERNAL void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Used when cleaning various bigints at the end of a session.
|
||||
* @param ctx [in] The bigint session context.
|
||||
@@ -952,7 +950,6 @@ void bi_free_mod(BI_CTX *ctx, int mod_offset) {
|
||||
bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
|
||||
bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Perform a standard multiplication between two bigints.
|
||||
@@ -1192,9 +1189,9 @@ NS_INTERNAL int bi_compare(bigint *bia, bigint *bib) {
|
||||
static void more_comps(bigint *bi, int n) {
|
||||
if (n > bi->max_comps) {
|
||||
int max = MAX(bi->max_comps * 2, n);
|
||||
void *p = calloc(1, (size_t) max * COMP_BYTE_SIZE);
|
||||
void *p = mg_calloc(1, (size_t) max * COMP_BYTE_SIZE);
|
||||
if (p != NULL && bi->size > 0) memcpy(p, bi->comps, (size_t) bi->max_comps * COMP_BYTE_SIZE);
|
||||
free(bi->comps);
|
||||
mg_free(bi->comps);
|
||||
bi->max_comps = (short) max;
|
||||
bi->comps = (comp *) p;
|
||||
}
|
||||
@@ -1229,8 +1226,8 @@ static bigint *alloc(BI_CTX *ctx, int size) {
|
||||
more_comps(biR, size);
|
||||
} else {
|
||||
/* No free bigints available - create a new one. */
|
||||
biR = (bigint *) calloc(1, sizeof(bigint));
|
||||
biR->comps = (comp *) calloc(1, (size_t) size * COMP_BYTE_SIZE);
|
||||
biR = (bigint *) mg_calloc(1, sizeof(bigint));
|
||||
biR->comps = (comp *) mg_calloc(1, (size_t) size * COMP_BYTE_SIZE);
|
||||
biR->max_comps = (short) size; /* give some space to spare */
|
||||
}
|
||||
|
||||
@@ -1419,7 +1416,7 @@ static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) {
|
||||
k <<= 1;
|
||||
}
|
||||
|
||||
ctx->g = (bigint **) calloc(1, k * sizeof(bigint *));
|
||||
ctx->g = (bigint **) mg_calloc(1, k * sizeof(bigint *));
|
||||
ctx->g[0] = bi_clone(ctx, g1);
|
||||
bi_permanent(ctx->g[0]);
|
||||
g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */
|
||||
@@ -1470,7 +1467,7 @@ NS_INTERNAL bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) {
|
||||
/* work out the slide constants */
|
||||
precompute_slide_window(ctx, window_size, bi);
|
||||
#else /* just one constant */
|
||||
ctx->g = (bigint **) calloc(1, sizeof(bigint *));
|
||||
ctx->g = (bigint **) mg_calloc(1, sizeof(bigint *));
|
||||
ctx->g[0] = bi_clone(ctx, bi);
|
||||
ctx->window = 1;
|
||||
bi_permanent(ctx->g[0]);
|
||||
@@ -1513,7 +1510,7 @@ NS_INTERNAL bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) {
|
||||
bi_free(ctx, ctx->g[i]);
|
||||
}
|
||||
|
||||
free(ctx->g);
|
||||
mg_free(ctx->g);
|
||||
bi_free(ctx, bi);
|
||||
bi_free(ctx, biexp);
|
||||
#if defined CONFIG_BIGINT_MONTGOMERY
|
||||
@@ -1562,18 +1559,32 @@ NS_INTERNAL bigint *bi_crt(BI_CTX *ctx, bigint *bi, bigint *dP, bigint *dQ,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Proper lib usage:
|
||||
// - BI_CTX *c = bi_initialize()
|
||||
// - allocate bigints (e.g.: calling bi_import(), int_to_bi(), ...)
|
||||
// - function calls, allocate bigints, etc.
|
||||
// - bigint *n = bi_import(c, indata, insize)
|
||||
// - bi_set_mod(c, n, x)
|
||||
// - mod function calls
|
||||
// - bigint *nn = bi_mod_pwr(c, m, e) <-- frees m, e
|
||||
// - bi_free_mod(c, x) <-- frees n
|
||||
// - bi_export(c, nn, outdata, outsize) <-- frees nn
|
||||
// - function calls
|
||||
// - free bigints calling bi_free()
|
||||
// - bi_terminate(c) <-- frees c
|
||||
|
||||
int mg_rsa_mod_pow(const uint8_t *mod, size_t modsz, const uint8_t *exp, size_t expsz, const uint8_t *msg, size_t msgsz, uint8_t *out, size_t outsz) {
|
||||
BI_CTX *bi_ctx = bi_initialize();
|
||||
bigint *m1;
|
||||
bigint *n = bi_import(bi_ctx, mod, (int) modsz);
|
||||
bigint *e = bi_import(bi_ctx, exp, (int) expsz);
|
||||
bigint *h = bi_import(bi_ctx, msg, (int) msgsz);
|
||||
bi_set_mod(bi_ctx, n, 0);
|
||||
bigint *m1 = bi_mod_power(bi_ctx, h, e);
|
||||
m1 = bi_mod_power(bi_ctx, h, e);
|
||||
bi_free_mod(bi_ctx, 0);
|
||||
bi_export(bi_ctx, m1, out, (int) outsz);
|
||||
bi_free(bi_ctx, n);
|
||||
bi_free(bi_ctx, e);
|
||||
bi_free(bi_ctx, h);
|
||||
bi_free(bi_ctx, m1);
|
||||
bi_terminate(bi_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+23
-1
@@ -17,6 +17,13 @@ bool mg_random(void *buf, size_t len) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32
|
||||
while (len--) *p++ = (unsigned char) (esp_random() & 255);
|
||||
success = true;
|
||||
#elif MG_ARCH == MG_ARCH_CUBE && defined(HAL_RNG_MODULE_ENABLED)
|
||||
extern RNG_HandleTypeDef hrng;
|
||||
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
|
||||
uint32_t r = HAL_RNG_ReadLastRandomNumber(&hrng);
|
||||
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
|
||||
}
|
||||
success = true;
|
||||
#elif MG_ARCH == MG_ARCH_PICOSDK
|
||||
while (len--) *p++ = (unsigned char) (get_rand_32() & 255);
|
||||
success = true;
|
||||
@@ -127,6 +134,7 @@ int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip) {
|
||||
bool mg_path_is_sane(const struct mg_str path) {
|
||||
const char *s = path.buf;
|
||||
size_t n = path.len;
|
||||
if (path.buf[0] == '~') return false; // Starts with ~
|
||||
if (path.buf[0] == '.' && path.buf[1] == '.') return false; // Starts with ..
|
||||
for (; s[0] != '\0' && n > 0; s++, n--) {
|
||||
if ((s[0] == '/' || s[0] == '\\') && n >= 2) { // Subdir?
|
||||
@@ -146,7 +154,9 @@ uint64_t mg_millis(void) {
|
||||
#elif MG_ARCH == MG_ARCH_ESP8266 || MG_ARCH == MG_ARCH_ESP32 || \
|
||||
MG_ARCH == MG_ARCH_FREERTOS
|
||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||
#elif MG_ARCH == MG_ARCH_AZURERTOS
|
||||
#elif MG_ARCH == MG_ARCH_CUBE
|
||||
return (uint64_t) HAL_GetTick();
|
||||
#elif MG_ARCH == MG_ARCH_THREADX
|
||||
return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
|
||||
#elif MG_ARCH == MG_ARCH_TIRTOS
|
||||
return (uint64_t) Clock_getTicks();
|
||||
@@ -198,3 +208,15 @@ void mg_delayms(unsigned int ms) {
|
||||
uint64_t to = mg_millis() + ms + 1;
|
||||
while (mg_millis() < to) (void) 0;
|
||||
}
|
||||
|
||||
|
||||
#if MG_ENABLE_CUSTOM_CALLOC
|
||||
#else
|
||||
void *mg_calloc(size_t count, size_t size) {
|
||||
return calloc(count, size);
|
||||
}
|
||||
|
||||
void mg_free(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
+12
-1
@@ -11,6 +11,8 @@
|
||||
#define assert(x)
|
||||
#endif
|
||||
|
||||
void *mg_calloc(size_t count, size_t size);
|
||||
void mg_free(void *ptr);
|
||||
void mg_bzero(volatile unsigned char *buf, size_t len);
|
||||
bool mg_random(void *buf, size_t len);
|
||||
char *mg_random_str(char *buf, size_t len);
|
||||
@@ -70,9 +72,14 @@ uint32_t mg_ntohl(uint32_t net);
|
||||
#define MG_ROUND_UP(x, a) ((a) == 0 ? (x) : ((((x) + (a) -1) / (a)) * (a)))
|
||||
#define MG_ROUND_DOWN(x, a) ((a) == 0 ? (x) : (((x) / (a)) * (a)))
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__GNUC__) && defined(__arm__)
|
||||
#ifdef __ZEPHYR__
|
||||
#define MG_ARM_DISABLE_IRQ() __asm__ __volatile__("cpsid i" : : : "memory")
|
||||
#define MG_ARM_ENABLE_IRQ() __asm__ __volatile__("cpsie i" : : : "memory")
|
||||
#else
|
||||
#define MG_ARM_DISABLE_IRQ() asm volatile("cpsid i" : : : "memory")
|
||||
#define MG_ARM_ENABLE_IRQ() asm volatile("cpsie i" : : : "memory")
|
||||
#endif // !ZEPHYR
|
||||
#elif defined(__CCRH__)
|
||||
#define MG_RH850_DISABLE_IRQ() __DI()
|
||||
#define MG_RH850_ENABLE_IRQ() __EI()
|
||||
@@ -86,7 +93,11 @@ uint32_t mg_ntohl(uint32_t net);
|
||||
#elif defined(__ARMCC_VERSION)
|
||||
#define MG_DSB() __builtin_arm_dsb(0xf)
|
||||
#elif defined(__GNUC__) && defined(__arm__) && defined(__thumb__)
|
||||
#ifdef __ZEPHYR__
|
||||
#define MG_DSB() __asm__("DSB 0xf")
|
||||
#else
|
||||
#define MG_DSB() asm("DSB 0xf")
|
||||
#endif // !ZEPHYR
|
||||
#elif defined(__ICCARM__)
|
||||
#define MG_DSB() __iar_builtin_DSB()
|
||||
#else
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
#define MG_VERSION "7.18"
|
||||
#define MG_VERSION "7.19"
|
||||
+3
-1
@@ -1,7 +1,9 @@
|
||||
#include "wifi.h"
|
||||
|
||||
#if (!defined(MG_ENABLE_DRIVER_PICO_W) || !MG_ENABLE_DRIVER_PICO_W) && \
|
||||
(!defined(MG_ENABLE_DRIVER_CYW) || !MG_ENABLE_DRIVER_CYW)
|
||||
(!defined(MG_ENABLE_DRIVER_CYW) || !MG_ENABLE_DRIVER_CYW) && \
|
||||
(!defined(MG_ENABLE_DRIVER_CYW_SDIO) || !MG_ENABLE_DRIVER_CYW_SDIO)
|
||||
|
||||
|
||||
bool mg_wifi_scan(void) {
|
||||
MG_ERROR(("No Wi-Fi driver enabled"));
|
||||
|
||||
+34
-17
@@ -9,12 +9,12 @@ CWD ?= $(realpath $(CURDIR))
|
||||
ROOT_DIR = $(realpath $(CWD)/..)
|
||||
ENV ?= -e Tmp=. -e WINEDEBUG=-all
|
||||
DOCKER_BIN ?= docker
|
||||
DOCKER ?= $(DOCKER_BIN) run --platform linux/amd64 --rm $(ENV) -v $(ROOT_DIR):$(ROOT_DIR) -w $(CWD)
|
||||
VCFLAGS = /nologo /W3 /O2 /MD /I. $(DEFS) $(TFLAGS)
|
||||
# use net=host so all tests have the same network and can access localhost and ad hoc services
|
||||
DOCKER ?= $(DOCKER_BIN) run --platform linux/amd64 --net=host --rm $(ENV) -v $(ROOT_DIR):$(ROOT_DIR) -w $(CWD)
|
||||
VCFLAGS ?= /nologo /W3 /O2 /MD /I.
|
||||
IPV6 ?= 1
|
||||
ASAN ?= -fsanitize=address,undefined,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
|
||||
ASAN_OPTIONS ?= detect_leaks=1
|
||||
REFPROJS := $(dir $(wildcard ../reference-projects/windows-macos-linux/*/Makefile))
|
||||
# This does not include ESP32, ESP8266, Microchip; all examples that are directly placed under an OS tutorial. Also, it is needed that way...
|
||||
TUTORIALS_EMBEDDED := $(dir $(wildcard ../tutorials/infineon/*/Makefile)) $(dir $(wildcard ../tutorials/nxp/*/Makefile)) $(dir $(wildcard ../tutorials/pico-sdk/*/Makefile)) $(dir $(wildcard ../tutorials/renesas/*/Makefile)) $(dir $(wildcard ../tutorials/stm32/*/Makefile)) $(dir $(wildcard ../tutorials/ti/*/Makefile)) $(dir $(wildcard ../tutorials/wch/*/Makefile))
|
||||
TUTORIALS := ../tutorials/micropython/ $(filter-out $(TUTORIALS_EMBEDDED), $(dir $(wildcard ../tutorials/*/*/Makefile)))
|
||||
@@ -75,13 +75,13 @@ LDFLAGS += -L$(WOLFSSL)/lib -lwolfssl
|
||||
endif
|
||||
|
||||
ifeq "$(SSL)" "BUILTIN"
|
||||
CFLAGS += -DMG_TLS=MG_TLS_BUILTIN
|
||||
DEFS += -DMG_TLS=MG_TLS_BUILTIN
|
||||
endif
|
||||
|
||||
all:
|
||||
$(MAKE) -C ../tutorials/http/http-server
|
||||
|
||||
tall: mg_prefix unamalgamated test mip_test arm tutorials vc98 vc17 vc22 mingw mingw++ fuzz
|
||||
tall: mg_prefix unamalgamated test valgrind fuzz fuzz_tls vc98 vc17 vc22 mingw mingw++ arm armhf riscv s390 tutorials tutorials_win tutorials_embedded mip_test mip_vc98
|
||||
|
||||
mip_test: mip_test.c mongoose.c mongoose.h packed_fs.c Makefile
|
||||
$(CC) mip_test.c packed_fs.c $(CFLAGS) $(LDFLAGS) -o $@
|
||||
@@ -91,6 +91,10 @@ mip_tap_test: mip_tap_test.c mongoose.c mongoose.h packed_fs.c Makefile tls_mult
|
||||
$(CC) mip_tap_test.c packed_fs.c $(CFLAGS) $(LDFLAGS) -o $@
|
||||
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
|
||||
|
||||
mip_vc98: mip_test.c mongoose.c mongoose.h packed_fs.c Makefile
|
||||
$(DOCKER) mdashnet/vc98 wine cl mip_test.c packed_fs.c $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc98 wine $@.exe
|
||||
|
||||
packed_fs.c: Makefile data/ssi.h fuzz.c data/a.txt data/ca.pem certs/ca.crt certs/server.crt certs/server.key
|
||||
$(CC) $(CFLAGS) pack.c -o pack
|
||||
$(RUN) ./pack Makefile data/ssi.h fuzz.c data/a.txt data/range.txt data/ca.pem certs/ca.crt certs/server.crt certs/server.key certs/client.key certs/client.crt > $@
|
||||
@@ -113,7 +117,7 @@ unamalgamated: $(HDRS) Makefile packed_fs.c
|
||||
fuzz: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined
|
||||
fuzz: mongoose.c mongoose.h Makefile fuzz.c
|
||||
$(CC) fuzz.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer
|
||||
$(RUN) ./fuzzer
|
||||
$(RUN) ./fuzzer $(ARGS)
|
||||
|
||||
FUZZDATA ?= /tmp/fuzzdata
|
||||
fuzz2: mongoose.c mongoose.h Makefile fuzz.c
|
||||
@@ -123,7 +127,11 @@ fuzz2: mongoose.c mongoose.h Makefile fuzz.c
|
||||
fuzz_tls: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined
|
||||
fuzz_tls: mongoose.c mongoose.h Makefile fuzz_tls.c
|
||||
$(CC) fuzz_tls.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer_tls
|
||||
$(RUN) ./fuzzer_tls -max_len=17000
|
||||
$(RUN) ./fuzzer_tls -max_len=17000 $(ARGS)
|
||||
|
||||
fuzz_tls2: mongoose.c mongoose.h Makefile fuzz_tls.c
|
||||
$(CC) fuzz_tls.c -DMAIN $(OPTS) $(WARN) $(ASAN) $(INCS) -o fuzzer_tls
|
||||
$(RUN) ./fuzzer_tls $(FUZZDATA)
|
||||
|
||||
|
||||
|
||||
@@ -132,7 +140,12 @@ test: Makefile mongoose.h $(SRCS) tls_multirec/server
|
||||
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./unit_test
|
||||
|
||||
tls_multirec/server: FORCE
|
||||
ifneq "$(SSL)" ""
|
||||
ifeq "$(MULTIREC)" ""
|
||||
$(MAKE) -C tls_multirec CC=gcc
|
||||
endif
|
||||
endif
|
||||
true
|
||||
|
||||
FORCE:
|
||||
true
|
||||
@@ -156,44 +169,48 @@ misra:
|
||||
cppcheck --addon=misra --clang -DMG_ENABLE_LINES=1 -DMG_ENABLE_SSI=1 mongoose.c >>/tmp/x 2>&1
|
||||
less /tmp/x
|
||||
|
||||
# https://ddanilov.me/how-signals-are-handled-in-a-docker-container
|
||||
armhf: ASAN=
|
||||
armhf: IPV6=0
|
||||
armhf: CC = $(DOCKER) mdashnet/armhf cc
|
||||
armhf: RUN = $(DOCKER) mdashnet/armhf
|
||||
armhf: RUN = $(DOCKER) --init mdashnet/armhf
|
||||
armhf: test
|
||||
|
||||
s390: ASAN=
|
||||
s390: IPV6=0
|
||||
s390: CFLAGS += -Wno-stringop-overflow
|
||||
s390: DEFS += -DMG_ENABLE_CHACHA20=0
|
||||
s390: CC = $(DOCKER) mdashnet/s390 cc
|
||||
s390: RUN = $(DOCKER) mdashnet/s390
|
||||
s390: RUN = $(DOCKER) --init mdashnet/s390
|
||||
s390: test
|
||||
|
||||
arm: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_NEWLIB -DNO_SLEEP_ABORT
|
||||
arm: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_ARMGCC -DNO_SLEEP_ABORT
|
||||
arm: mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/armgcc arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test -nostartfiles --specs nosys.specs -e 0
|
||||
|
||||
riscv: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_NEWLIB -DNO_SLEEP_ABORT
|
||||
riscv: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_ARMGCC -DNO_SLEEP_ABORT
|
||||
riscv: mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/riscv riscv-none-elf-gcc -march=rv32imc -mabi=ilp32 $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test
|
||||
|
||||
vc98: Makefile mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc98 wine $@.exe
|
||||
|
||||
vc17: Makefile mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc17 wine64 $@.exe
|
||||
|
||||
vc22: Makefile mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
|
||||
$(DOCKER) mdashnet/vc22 wine64 $@.exe
|
||||
|
||||
mingw: Makefile mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -lbcrypt -o $@.exe
|
||||
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) $(TFLAGS) -lws2_32 -lbcrypt -o $@.exe
|
||||
$(DOCKER) mdashnet/mingw wine64 $@.exe
|
||||
|
||||
mingw++: Makefile mongoose.h $(SRCS)
|
||||
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -lbcrypt -o $@.exe
|
||||
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) $(TFLAGS) -lws2_32 -lbcrypt -o $@.exe
|
||||
@echo "NOT RUNNING"
|
||||
|
||||
linux-libs: CFLAGS += -fPIC
|
||||
linux-libs: LDFLAGS += -Wl,-soname,libmongoose.so.$(VERSION)
|
||||
@@ -213,7 +230,7 @@ mongoose.c: Makefile $(wildcard ../src/*.c) $(wildcard ../src/drivers/*.c)
|
||||
cd .. && (export LC_ALL=C ; cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/drivers/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
||||
|
||||
mongoose.h: $(HDRS) Makefile
|
||||
cd .. && (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/tls_chacha20.h src/tls_rsa.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/flash.h src/wifi.h src/net_builtin.h src/profile.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
||||
cd .. && (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/profile.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/tls_chacha20.h src/tls_rsa.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/flash.h src/wifi.h src/net_builtin.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
||||
|
||||
|
||||
clean: clean_tutorials clean_tutorials_embedded
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
// Build environment. Possible options are at https://github.com/cesanta/mongoose/blob/master/src/arch.h
|
||||
// #define MG_ARCH MG_ARCH_CUSTOM
|
||||
|
||||
// Choice of the network stack. By default, use an external BSD-compatible stack
|
||||
// #define MG_ENABLE_FREERTOS_TCP 0 // Amazon FreeRTOS-TCP
|
||||
// #define MG_ENABLE_LWIP 0 // lWIP
|
||||
// #define MG_ENABLE_TCPIP 0 // Mongoose built-in
|
||||
// #define MG_ENABLE_RL 0 // ARM MDK
|
||||
// #define MG_ENABLE_POLL 0 // Only for BSD stack. Use poll()
|
||||
// #define MG_ENABLE_EPOLL 0 // Only for Linux/BSD stack. Use epoll()
|
||||
// #define MG_ENABLE_WINSOCK 1 // Only for Windows stack. Use Winsock
|
||||
// #define MG_ENABLE_SOCKET !MG_ENABLE_TCPIP
|
||||
// #define MG_SOCK_LISTEN_BACKLOG_SIZE 3 // Only for socket-based stacks
|
||||
|
||||
// Only for built-in network stack, MG_ENABLE_TCPIP == 1
|
||||
// #define MG_ENABLE_TCPIP_DRIVER_INIT 1 // enabled built-in driver for
|
||||
// #define MG_SET_MAC_ADDRESS(mac) // set MAC address for built-in driver
|
||||
// #define MG_SET_WIFI_CONFIG(data)
|
||||
// #define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
|
||||
|
||||
// Choose a driver for built-in network stack, MG_ENABLE_TCPIP == 1
|
||||
// #define MG_ENABLE_DRIVER_STM32H 0
|
||||
// #define MG_ENABLE_DRIVER_STM32F 0
|
||||
// #define MG_ENABLE_DRIVER_IMXRT 0
|
||||
// #define MG_ENABLE_DRIVER_CMSIS 0
|
||||
// #define MG_ENABLE_DRIVER_RA 0
|
||||
// #define MG_ENABLE_DRIVER_RW612 0
|
||||
// #define MG_ENABLE_DRIVER_SAME54 0
|
||||
// #define MG_ENABLE_DRIVER_MCXN 0
|
||||
// #define MG_ENABLE_DRIVER_TM4C 0
|
||||
// #define MG_ENABLE_DRIVER_TMS570 0
|
||||
// #define MG_ENABLE_DRIVER_XMC7 0
|
||||
// #define MG_ENABLE_DRIVER_XMC 0
|
||||
|
||||
// Filesystem support
|
||||
// #define MG_ENABLE_PACKED_FS 0 // Enable packed filesystem support
|
||||
// #define MG_ENABLE_FATFS 0 // Enable FATFS support, mg_fs_packed
|
||||
// #define MG_ENABLE_POSIX_FS 0 // Enable POSIX filesystem support, mg_fs_posix
|
||||
// #define MG_PATH_MAX 128 // Maximum path length
|
||||
// #define MG_DIRSEP '/' // Directory separator
|
||||
|
||||
// Misc options
|
||||
// #define MG_ENABLE_LOG 1 // Enable logging
|
||||
// #define MG_TLS MG_TLS_NONE // MG_TLS_NONE, MG_TLS_MBED, MG_TLS_OPENSSL, MG_TLS_CUSTOM
|
||||
// #define MG_ENABLE_IPV6 0 // Enable IPv6 support
|
||||
// #define MG_IPV6_V6ONLY 0 // IPv6 socket binds only to V6, not V4 address
|
||||
// #define MG_ENABLE_CUSTOM_CALLOC 0 // Set to 1 to let user define mg_calloc() and mg_free()
|
||||
// #define MG_ENABLE_CUSTOM_RANDOM 0 // Set to 1 to let user define mg_random()
|
||||
// #define MG_ENABLE_CUSTOM_MILLIS 0 // Set to 1 to let user define mg_millis()
|
||||
// #define MG_ENABLE_SSI 0 // Enable SSI support
|
||||
// #define MG_ENABLE_DIRLIST 0 // Enable directory listing
|
||||
// #define MG_IO_SIZE 512 // Granularity of the send/recv IO buffer growth
|
||||
// #define MG_MAX_RECV_SIZE (3UL * 1024UL * 1024UL) // Maximum recv IO buffer size
|
||||
// #define MG_DATA_SIZE 32 // struct mg_connection :: data size
|
||||
// #define MG_MAX_HTTP_HEADERS 30 // Maximum number of HTTP headers
|
||||
// #define MG_HTTP_INDEX "index.html" // Default HTTP index file
|
||||
// #define MG_ENABLE_LINES 0 // Show unamalgamated line numbers
|
||||
+7
-2
@@ -7,18 +7,23 @@ IMAGE ?= scaprile/cubeozone
|
||||
|
||||
all: $(PROJECTS)
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -removeAll workspace
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf workspace/.metadata"
|
||||
|
||||
$(PROJECTS): FORCE
|
||||
(make -C $@ && sudo make -C $@ clean) || ( \
|
||||
COREDIRS=`find $@ -maxdepth 1 -name 'CM*' -print` && ( \
|
||||
(test "$$COREDIRS" = "" && \
|
||||
PROJNAME=`xq -r .projectDescription.name $@/.project` && \
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@ -cleanBuild $$PROJNAME/$(TARGET) ) || ( \
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@ -cleanBuild $$PROJNAME/$(TARGET) && \
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -remove $@ && \
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf $@/.settings $@/$(TARGET)") || ( \
|
||||
(test "$$COREDIRS" != "" && \
|
||||
for core in $$COREDIRS; do \
|
||||
DIR=`basename $$core` \
|
||||
PROJNAME=`xq -r .projectDescription.name $@/$$DIR/.project` && \
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@/$$DIR -cleanBuild $$PROJNAME/$(TARGET) || exit 1; \
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@/$$DIR -cleanBuild $$PROJNAME/$(TARGET) && \
|
||||
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -remove $@/$$DIR && \
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf $@/$$DIR/.settings $@/$$DIR/Drivers $@/$$DIR/Middlewares $@/$$DIR/$(TARGET)" || exit 1; \
|
||||
done ))))
|
||||
|
||||
FORCE:
|
||||
@@ -0,0 +1,33 @@
|
||||
- Make sure your PEM file starts with a dash -
|
||||
|
||||
|
||||
Issuer: C=US, O=Internet Security Research Group, CN=ISRG Root X1
|
||||
Not Before: Mar 13 00:00:00 2024 GMT
|
||||
Not After : Mar 12 23:59:59 2027 GMT
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK
|
||||
a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO
|
||||
VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw
|
||||
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw
|
||||
i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
|
||||
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
|
||||
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
|
||||
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAH3KdNEVCQdqk0LKyuNImTKdRJY1C
|
||||
2uw2SJajuhqkyGPY8C+zzsufZ+mgnhnq1A2KVQOSykOEnUbx1cy637rBAihx97r+
|
||||
bcwbZM6sTDIaEriR/PLk6LKs9Be0uoVxgOKDcpG9svD33J+G9Lcfv1K9luDmSTgG
|
||||
6XNFIN5vfI5gs/lMPyojEMdIzK9blcl2/1vKxO8WGCcjvsQ1nJ/Pwt8LQZBfOFyV
|
||||
XP8ubAp/au3dc4EKWG9MO5zcx1qT9+NXRGdVWxGvmBFRAajciMfXME1ZuGmk3/GO
|
||||
koAM7ZkjZmleyokP1LGzmfJcUd9s7eeu1/9/eg5XlXd/55GtYjAM+C4DG5i7eaNq
|
||||
cm2F+yxYIPt6cbbtYVNJCGfHWqHEQ4FYStUyFnv8sjyqU8ypgZaNJ9aVcWSICLOI
|
||||
E1/Qv/7oKsnZCWJ926wU6RqG1OYPGOi1zuABhLw61cuPVDT28nQS/e6z95cJXq0e
|
||||
K1BcaJ6fJZsmbjRgD5p3mvEf5vdQM7MCEvU0tHbsx2I5mHHJoABHb8KVBgWp/lcX
|
||||
GWiWaeOyB7RP+OfDtvi2OsapxXiV7vNVs7fMlrRjY1joKaqmmycnBvAq14AEbtyL
|
||||
sVfOS66B8apkeFX2NY4XPEYV4ZSCe8VHPrdrERk2wILG3T/EGmSIkCYVUMSnjmJd
|
||||
VQD9F6Na/+zmXCc=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -11,6 +11,6 @@ all: $(PROJECTS)
|
||||
$(PROJECTS): FORCE
|
||||
(make -C $@ build && make -C $@ clean) || ( \
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c 'cd $@ && idf.py build' && \
|
||||
rm -rf build sdkconfig )
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c 'rm -rf .cache && cd $@ && rm -rf build sdkconfig')
|
||||
|
||||
FORCE:
|
||||
@@ -1,3 +1,5 @@
|
||||
// https://llvm.org/docs/LibFuzzer.html
|
||||
|
||||
#define MG_ENABLE_SOCKET 0
|
||||
#define MG_ENABLE_LOG 0
|
||||
#define MG_ENABLE_LINES 1
|
||||
@@ -146,6 +148,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
c->pfn(c, MG_EV_READ, NULL); // manually invoke protocol event handler
|
||||
|
||||
free(pkt);
|
||||
mg_mgr_free(&mgr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+30
-13
@@ -1,3 +1,5 @@
|
||||
// https://llvm.org/docs/LibFuzzer.html
|
||||
|
||||
#define MG_ENABLE_SOCKET 1
|
||||
#define MG_ENABLE_LOG 0
|
||||
#define MG_ENABLE_LINES 1
|
||||
@@ -12,28 +14,40 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
|
||||
#else
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
|
||||
#endif
|
||||
typedef int (*f)(struct mg_connection *);
|
||||
|
||||
f f_[] = {
|
||||
mg_tls_server_recv_hello,
|
||||
#if 0
|
||||
mg_tls_client_recv_hello,
|
||||
mg_tls_client_recv_ext,
|
||||
mg_tls_client_recv_cert,
|
||||
mg_tls_client_recv_cert_verify
|
||||
#endif
|
||||
// Preprocessor magic, just add/remove functions here and leave the rest alone
|
||||
#define TABLE(_) \
|
||||
_(mg_tls_server_recv_hello) \
|
||||
//_(mg_tls_client_recv_hello) \
|
||||
//_(mg_tls_client_recv_ext ) \
|
||||
//_(mg_tls_client_recv_cert) \
|
||||
//_(mg_tls_client_recv_cert_verify) \
|
||||
// ...
|
||||
|
||||
struct f {
|
||||
int (*f)(struct mg_connection *);
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct f f_[] = {
|
||||
#define ENTRY(func) { func, #func },
|
||||
TABLE(ENTRY)
|
||||
#undef ENTRY
|
||||
};
|
||||
// end of preprocessor magic
|
||||
|
||||
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
struct mg_connection c_[sizeof(f_)/sizeof(f)], *c = &c_[0];
|
||||
struct tls_data tls_[sizeof(f_)/sizeof(f)];
|
||||
struct mg_connection c_[sizeof(f_)/sizeof(struct f)], *c = &c_[0];
|
||||
struct tls_data tls_[sizeof(f_)/sizeof(struct f)];
|
||||
int i;
|
||||
if (size == 0) return 0;
|
||||
mg_log_set(MG_LL_INFO);
|
||||
memset(c, 0, sizeof(*c));
|
||||
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
|
||||
c->is_tls = c->is_tls_hs = 1;
|
||||
for (i = 0; i < (int)(sizeof(f_)/sizeof(f)); i++) {
|
||||
for (i = 0; i < (int)(sizeof(f_)/sizeof(struct f)); i++) {
|
||||
struct mg_iobuf *io;
|
||||
c = &c_[i];
|
||||
io = &c->rtls;
|
||||
@@ -47,7 +61,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
memcpy(&io->buf[io->len], data, size);
|
||||
io->len += size;
|
||||
c->tls = &tls_[i];
|
||||
f_[i](&c[i]);
|
||||
#ifdef PRINT_FUNCNAME
|
||||
printf("CALLING %s\n", f_[i].name);
|
||||
#endif
|
||||
f_[i].f(&c[i]);
|
||||
mg_iobuf_free(io);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"data-root": "/mnt/docker"
|
||||
}
|
||||
+95
-20
@@ -20,9 +20,13 @@
|
||||
|
||||
#include "driver_mock.c"
|
||||
|
||||
#define MQTT_URL "mqtt://broker.hivemq.com:1883" // MQTT broker URL
|
||||
#ifdef MQTT_LOCALHOST
|
||||
#define MQTT_URL "mqtt://127.0.0.1:1883"
|
||||
#else
|
||||
#define MQTT_URL "mqtt://broker.hivemq.com:1883"
|
||||
#endif
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
#define MQTTS_URL "mqtts://mongoose.ws:8883" // HiveMQ does not do TLS1.3
|
||||
#define MQTTS_URL "mqtts://mongoose.ws:8883" // test requires TLS 1.3
|
||||
#define MQTTS_CA mg_str(s_ca_cert)
|
||||
static const char *s_ca_cert =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
@@ -57,23 +61,42 @@ static const char *s_ca_cert =
|
||||
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
#elif MG_TLS
|
||||
#define MQTTS_URL "mqtts://broker.hivemq.com:8883" // MQTT broker URL
|
||||
#ifdef MQTT_LOCALHOST
|
||||
// we'll generate MQTTS_URL
|
||||
#define MQTTS_CA mg_str(s_ca_cert)
|
||||
static const char *s_ca_cert =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIBFTCBvAIJAMNTFtpfcq8NMAoGCCqGSM49BAMCMBMxETAPBgNVBAMMCE1vbmdv\n"
|
||||
"b3NlMB4XDTI0MDUwNzE0MzczNloXDTM0MDUwNTE0MzczNlowEzERMA8GA1UEAwwI\n"
|
||||
"TW9uZ29vc2UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASuP+86T/rOWnGpEVhl\n"
|
||||
"fxYZ+pjMbCmDZ+vdnP0rjoxudwRMRQCv5slRlDK7Lxue761sdvqxWr0Ma6TFGTNg\n"
|
||||
"epsRMAoGCCqGSM49BAMCA0gAMEUCIQCwb2CxuAKm51s81S6BIoy1IcandXSohnqs\n"
|
||||
"us64BAA7QgIgGGtUrpkgFSS0oPBlCUG6YPHFVw42vTfpTC0ySwAS0M4=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
#else
|
||||
#define MQTTS_URL "mqtts://broker.hivemq.com:8883"
|
||||
#define MQTTS_CA mg_unpacked("/data/ca.pem")
|
||||
#endif // MQTT_LOCALHOST
|
||||
#endif
|
||||
|
||||
static char *host_ip;
|
||||
|
||||
static int s_num_tests = 0;
|
||||
|
||||
#define ABORT() \
|
||||
usleep(500000); /* 500 ms, GH print reason */ \
|
||||
#ifdef NO_SLEEP_ABORT
|
||||
#define ABORT() abort()
|
||||
#else
|
||||
#define ABORT() \
|
||||
sleep(2); /* 2s, GH print reason */ \
|
||||
abort();
|
||||
#endif
|
||||
|
||||
#define ASSERT(expr) \
|
||||
do { \
|
||||
s_num_tests++; \
|
||||
if (!(expr)) { \
|
||||
printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr); \
|
||||
fflush(stdout); \
|
||||
ABORT(); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -156,14 +179,22 @@ static void fcb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (mg_url_is_ssl(fd->url)) {
|
||||
struct mg_tls_opts opts;
|
||||
memset(&opts, 0, sizeof(opts)); // read CA from packed_fs
|
||||
opts.name = mg_url_host(fd->url);
|
||||
opts.ca = mg_unpacked("/data/ca.pem");
|
||||
if (host_ip != NULL && strstr(fd->url, host_ip) != NULL) {
|
||||
MG_DEBUG(("Local connection, using self-signed certificates"));
|
||||
opts.name = mg_str_s("localhost");
|
||||
opts.ca = mg_unpacked("/certs/ca.crt");
|
||||
} else {
|
||||
opts.name = mg_url_host(fd->url);
|
||||
opts.ca = mg_unpacked("/data/ca.pem");
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
// our TLS does not search for the proper CA in a bundle
|
||||
opts.ca = mg_file_read(&mg_fs_posix, "data/e5.crt");
|
||||
#endif
|
||||
}
|
||||
mg_tls_init(c, &opts);
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
mg_free((void *) opts.ca.buf);
|
||||
#endif
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
@@ -241,14 +272,20 @@ static void test_http_client(struct mg_mgr *mgr) {
|
||||
static struct mg_connection *s_conn;
|
||||
static char s_topic[16];
|
||||
|
||||
struct mqtt_data {
|
||||
char *url;
|
||||
bool passed;
|
||||
};
|
||||
|
||||
static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mqtt_data *data = (struct mqtt_data *) c->fn_data;
|
||||
if (ev == MG_EV_CONNECT) {
|
||||
MG_DEBUG(("CONNECT"));
|
||||
#if MG_TLS
|
||||
struct mg_tls_opts opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.ca = MQTTS_CA;
|
||||
opts.name = mg_url_host(MQTTS_URL);
|
||||
opts.name = mg_url_host(data->url);
|
||||
mg_tls_init(c, &opts);
|
||||
#endif
|
||||
} else if (ev == MG_EV_MQTT_OPEN) {
|
||||
@@ -267,12 +304,32 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
} else if (ev == MG_EV_MQTT_MSG) {
|
||||
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
||||
MG_DEBUG(("TOPIC: %.*s, MSG: %.*s", (int) mm->topic.len, mm->topic.buf,
|
||||
(int) mm->data.len, mm->data.buf));
|
||||
mm->data.len > 10 ? 10 : (int) mm->data.len, mm->data.buf));
|
||||
ASSERT(mm->topic.len == strlen(s_topic) &&
|
||||
strcmp(mm->topic.buf, s_topic) == 0);
|
||||
ASSERT(mm->data.len == 2 && strcmp(mm->data.buf, "hi") == 0);
|
||||
mg_mqtt_disconnect(c, NULL);
|
||||
*(bool *) c->fn_data = true;
|
||||
strncmp(mm->topic.buf, s_topic, mm->topic.len) == 0);
|
||||
if (mm->data.len == 2 && strncmp(mm->data.buf, "hi", 2) == 0) {
|
||||
struct mg_mqtt_opts pub_opts;
|
||||
memset(&pub_opts, 0, sizeof(pub_opts));
|
||||
pub_opts.topic = mm->topic;
|
||||
// send more than 1 record, content is not relevant
|
||||
pub_opts.message = mg_str_n((char *)(size_t) mqtt_fn, 21098);
|
||||
pub_opts.qos = 1, pub_opts.retain = false;
|
||||
mg_mqtt_pub(c, &pub_opts);
|
||||
} else if (mm->data.len == 8 && strncmp(mm->data.buf, "farewell", 8) == 0) {
|
||||
// close on farewell
|
||||
MG_INFO(("%lu CLOSING", c->id));
|
||||
mg_mqtt_disconnect(c, NULL);
|
||||
data->passed = true;
|
||||
} else if (mm->data.len == 21098) {
|
||||
struct mg_mqtt_opts pub_opts;
|
||||
ASSERT(memcmp((const char *) (size_t) mqtt_fn, mm->data.buf, 21098) == 0);
|
||||
// send farewell after receiving big data
|
||||
memset(&pub_opts, 0, sizeof(pub_opts));
|
||||
pub_opts.topic = mm->topic;
|
||||
pub_opts.message = mg_str("farewell");
|
||||
pub_opts.qos = 1, pub_opts.retain = false;
|
||||
mg_mqtt_pub(c, &pub_opts);
|
||||
}
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
MG_DEBUG(("CLOSE"));
|
||||
s_conn = NULL;
|
||||
@@ -282,22 +339,40 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
}
|
||||
|
||||
static void test_mqtt_connsubpub(struct mg_mgr *mgr) {
|
||||
bool passed = false;
|
||||
struct mqtt_data data;
|
||||
struct mg_mqtt_opts opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.clean = true, opts.version = 4;
|
||||
#if MG_TLS
|
||||
s_conn = mg_mqtt_connect(mgr, MQTTS_URL, &opts, mqtt_fn, &passed);
|
||||
#else
|
||||
s_conn = mg_mqtt_connect(mgr, MQTT_URL, &opts, mqtt_fn, &passed);
|
||||
data.passed = false;
|
||||
#if defined(MQTT_LOCALHOST) && MG_TLS != MG_TLS_BUILTIN
|
||||
if (host_ip == NULL) {
|
||||
printf("\nMQTT_LOCALHOST defined but no HOST_IP provided, skipping MQTTS tests\n");
|
||||
return;
|
||||
}
|
||||
printf("HOST_IP: %s\n", host_ip);
|
||||
#endif
|
||||
#if MG_TLS
|
||||
#if defined(MQTT_LOCALHOST) && MG_TLS != MG_TLS_BUILTIN
|
||||
data.url = mg_mprintf("mqtts://%s:8883", host_ip);
|
||||
#else
|
||||
data.url = strdup(MQTTS_URL);
|
||||
#endif
|
||||
#else
|
||||
#ifdef MQTT_LOCALHOST
|
||||
data.url = mg_mprintf("mqtt://%s:1883", host_ip);
|
||||
#else
|
||||
data.url = strdup(MQTT_URL);
|
||||
#endif
|
||||
#endif
|
||||
s_conn = mg_mqtt_connect(mgr, data.url, &opts, mqtt_fn, &data);
|
||||
ASSERT(s_conn != NULL);
|
||||
for (int i = 0; i < 500 && s_conn != NULL && !s_conn->is_closing; i++) {
|
||||
for (int i = 0; i < 1000 && s_conn != NULL && !s_conn->is_closing; i++) {
|
||||
mg_mgr_poll(mgr, 0);
|
||||
usleep(10000); // 10 ms. Slow down poll loop to ensure packets transit
|
||||
}
|
||||
ASSERT(passed);
|
||||
ASSERT(data.passed);
|
||||
mg_mgr_poll(mgr, 0);
|
||||
free(data.url);
|
||||
}
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
+97
-49
@@ -1,19 +1,19 @@
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
|
||||
|
||||
#include "mongoose.c"
|
||||
#include "mongoose.c" // order is important, this one first
|
||||
#include "driver_mock.c"
|
||||
|
||||
static int s_num_tests = 0;
|
||||
static bool s_sent_fragment = 0;
|
||||
static int s_sent_fragment = 0;
|
||||
static int s_seg_sent = 0;
|
||||
|
||||
#ifdef NO_SLEEP_ABORT
|
||||
#define ABORT() abort()
|
||||
#else
|
||||
#define ABORT() \
|
||||
sleep(2); /* 2s, GH print reason */ \
|
||||
abort();
|
||||
#define ABORT() \
|
||||
sleep(2); /* 2s, GH print reason */ \
|
||||
abort();
|
||||
#endif
|
||||
|
||||
#define ASSERT(expr) \
|
||||
@@ -21,10 +21,18 @@ static int s_seg_sent = 0;
|
||||
s_num_tests++; \
|
||||
if (!(expr)) { \
|
||||
printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr); \
|
||||
fflush(stdout); \
|
||||
ABORT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void test_csum(void) {
|
||||
uint8_t ip[20] = {0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x11,
|
||||
0x94, 0xcf, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01};
|
||||
ASSERT(ipcsum(ip, 20) == 0);
|
||||
// UDP and TCP checksum calc funcions use the same basic calls as ipcsum()
|
||||
}
|
||||
|
||||
static void test_statechange(void) {
|
||||
char tx[1540];
|
||||
struct mg_tcpip_if iface;
|
||||
@@ -47,19 +55,24 @@ static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
|
||||
static void frag_recv_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_ERROR) {
|
||||
if (s_sent_fragment) {
|
||||
ASSERT(strcmp((char*) ev_data, "Received fragmented packet") == 0);
|
||||
if (s_sent_fragment > 0) {
|
||||
ASSERT(s_sent_fragment == 1);
|
||||
ASSERT(strcmp((char *) ev_data, "Received fragmented packet") == 0);
|
||||
s_sent_fragment = 2;
|
||||
}
|
||||
}
|
||||
(void) c, (void) ev_data;
|
||||
}
|
||||
|
||||
// mock send to a non-existent peer using the listener connection
|
||||
static void frag_send_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
static bool s_sent;
|
||||
static int s_seg_sizes[] = {416, 416, 368};
|
||||
static int s_seg_sizes[] = {416, 416, 368}; // based on len=1200 and MTU=500
|
||||
if (ev == MG_EV_POLL) {
|
||||
if (!s_sent) {
|
||||
c->send.len = 1200; // setting TCP payload size
|
||||
struct connstate *s = (struct connstate *) (c + 1);
|
||||
s->dmss = 1500; // mock set some destination MSS way larger
|
||||
c->send.len = 1200; // setting TCP payload size
|
||||
s_sent = true;
|
||||
}
|
||||
} else if (ev == MG_EV_WRITE) {
|
||||
@@ -71,9 +84,9 @@ static void frag_send_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
|
||||
static void test_poll(void) {
|
||||
int count = 0, i;
|
||||
struct mg_tcpip_if mif;
|
||||
struct mg_mgr mgr;
|
||||
mg_mgr_init(&mgr);
|
||||
struct mg_tcpip_if mif;
|
||||
memset(&mif, 0, sizeof(mif));
|
||||
mif.driver = &mg_tcpip_driver_mock;
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
@@ -88,7 +101,7 @@ static void test_poll(void) {
|
||||
struct driver_data {
|
||||
char buf[DRIVER_BUF_SIZE];
|
||||
size_t len;
|
||||
bool tx_ready; // data can be read from tx
|
||||
bool tx_ready; // data can be read from tx
|
||||
};
|
||||
|
||||
static struct driver_data s_driver_data;
|
||||
@@ -108,10 +121,10 @@ static bool if_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
|
||||
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
||||
if (!driver_data->len) return 0;
|
||||
if (driver_data->len == 0) return 0;
|
||||
if (len > driver_data->len) len = driver_data->len;
|
||||
memcpy(buf, driver_data->buf, len);
|
||||
driver_data->len = 0; // cleaning up the buffer
|
||||
driver_data->len = 0; // cleaning up the buffer
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -130,10 +143,10 @@ static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
|
||||
t.ack = mg_htonl(ack);
|
||||
t.off = 5 << 4;
|
||||
memcpy(s_driver_data.buf, e, sizeof(*e));
|
||||
ip->len = mg_htons((uint16_t)(sizeof(*ip) + sizeof(struct tcp) + payload_len));
|
||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
|
||||
s_driver_data.len = sizeof(*e) + sizeof(*ip)
|
||||
+ sizeof(struct tcp) + payload_len;
|
||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(t));
|
||||
s_driver_data.len = sizeof(*e) + sizeof(*ip) + sizeof(t) + payload_len;
|
||||
}
|
||||
|
||||
static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
|
||||
@@ -143,9 +156,9 @@ static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
|
||||
mg_mgr_poll(mgr, 0);
|
||||
|
||||
// SYN-ACK
|
||||
while(!received_response(&s_driver_data)) mg_mgr_poll(mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(mgr, 0);
|
||||
tcp = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
sizeof(struct ip));
|
||||
ASSERT((tcp->flags == (TH_SYN | TH_ACK)));
|
||||
ASSERT((tcp->ack == mg_htonl(1001)));
|
||||
|
||||
@@ -154,6 +167,9 @@ static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
|
||||
mg_mgr_poll(mgr, 0);
|
||||
}
|
||||
|
||||
// NOTE: a 1-byte payload could be an erroneous Keep-Alive, keep length > 1 in
|
||||
// this operation, we're testing retransmissions and having len=1 won't work
|
||||
|
||||
static void test_retransmit(void) {
|
||||
struct mg_mgr mgr;
|
||||
struct eth e;
|
||||
@@ -167,12 +183,13 @@ static void test_retransmit(void) {
|
||||
mg_mgr_init(&mgr);
|
||||
memset(&mif, 0, sizeof(mif));
|
||||
memset(&s_driver_data, 0, sizeof(struct driver_data));
|
||||
driver.init = NULL, driver.tx = if_tx, driver.poll = if_poll, driver.rx = if_rx;
|
||||
driver.init = NULL, driver.tx = if_tx, driver.poll = if_poll,
|
||||
driver.rx = if_rx;
|
||||
mif.driver = &driver;
|
||||
mif.driver_data = &s_driver_data;
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
mg_http_listen(&mgr, "http://0.0.0.0:0", fn, NULL);
|
||||
mgr.conns->pfn = NULL; // HTTP handler not needed
|
||||
mgr.conns->pfn = NULL; // HTTP handler not needed
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
|
||||
// setting the Ethernet header
|
||||
@@ -183,26 +200,23 @@ static void test_retransmit(void) {
|
||||
// setting the IP header
|
||||
memset(&ip, 0, sizeof(ip));
|
||||
ip.ver = 4 << 4, ip.proto = 6;
|
||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
||||
|
||||
init_tcp_handshake(&e, &ip, t, &mgr);
|
||||
|
||||
// packet with seq_no = 1001
|
||||
ip.len =
|
||||
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 1);
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1002))); // OK
|
||||
ASSERT((t->ack == mg_htonl(1003))); // OK
|
||||
|
||||
// resend packet with seq_no = 1001 (e.g.: MIP ACK lost)
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1);
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
start = mg_millis();
|
||||
while(!received_response(&s_driver_data)) {
|
||||
while (!received_response(&s_driver_data)) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
now = mg_millis() - start;
|
||||
// we wait enough time for a reply
|
||||
@@ -211,31 +225,64 @@ static void test_retransmit(void) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT((!response_recv)); // replies should not be sent for duplicate packets
|
||||
ASSERT((!response_recv)); // replies should not be sent for duplicate packets
|
||||
|
||||
// packet with seq_no = 1002 got lost/delayed, send seq_no = 1003
|
||||
create_tcp_pkt(&e, &ip, 1003, 1, TH_PUSH | TH_ACK, 1);
|
||||
// packet with seq_no = 1003 got lost/delayed, send seq_no = 1005
|
||||
create_tcp_pkt(&e, &ip, 1005, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
start = mg_millis();
|
||||
while(!received_response(&s_driver_data)) {
|
||||
while (!received_response(&s_driver_data)) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
now = mg_millis() - start;
|
||||
if (now > 2 * MIP_TCP_ACK_MS)
|
||||
ASSERT(0); // response should have been received by now
|
||||
ASSERT(0); // response should have been received by now
|
||||
}
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1002))); // dup ACK
|
||||
ASSERT((t->ack == mg_htonl(1003))); // dup ACK
|
||||
|
||||
// retransmitting packet with seq_no = 1002
|
||||
create_tcp_pkt(&e, &ip, 1002, 1, TH_PUSH | TH_ACK, 1);
|
||||
// retransmitting packet with seq_no = 1003
|
||||
create_tcp_pkt(&e, &ip, 1003, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while(!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1003))); // OK
|
||||
ASSERT((t->ack == mg_htonl(1005))); // OK
|
||||
|
||||
// packet with seq_no = 1005 got delayed, send FIN with seq_no = 1007
|
||||
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN, 0);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
start = mg_millis();
|
||||
while (!received_response(&s_driver_data)) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
now = mg_millis() - start;
|
||||
if (now > 2 * MIP_TCP_ACK_MS)
|
||||
ASSERT(0); // response should have been received by now
|
||||
}
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1005))); // dup ACK
|
||||
|
||||
// retransmitting packet with seq_no = 1005
|
||||
create_tcp_pkt(&e, &ip, 1005, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1007))); // OK
|
||||
|
||||
// retransmitting FIN packet with seq_no = 1007
|
||||
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN | TH_ACK, 0);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == (TH_FIN | TH_ACK))); // check we respond with FIN ACK
|
||||
ASSERT((t->ack == mg_htonl(1008))); // OK
|
||||
|
||||
s_driver_data.len = 0;
|
||||
mg_mgr_free(&mgr);
|
||||
@@ -252,7 +299,8 @@ static void test_frag_recv_path(void) {
|
||||
mg_mgr_init(&mgr);
|
||||
memset(&mif, 0, sizeof(mif));
|
||||
memset(&s_driver_data, 0, sizeof(struct driver_data));
|
||||
driver.init = NULL, driver.tx = if_tx, driver.poll = if_poll, driver.rx = if_rx;
|
||||
driver.init = NULL, driver.tx = if_tx, driver.poll = if_poll,
|
||||
driver.rx = if_rx;
|
||||
mif.driver = &driver;
|
||||
mif.driver_data = &s_driver_data;
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
@@ -268,17 +316,15 @@ static void test_frag_recv_path(void) {
|
||||
// setting the IP header
|
||||
memset(&ip, 0, sizeof(ip));
|
||||
ip.ver = 0x45, ip.proto = 6;
|
||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
||||
|
||||
init_tcp_handshake(&e, &ip, t, &mgr);
|
||||
|
||||
// send fragmented TCP packet
|
||||
ip.len =
|
||||
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + 1000);
|
||||
ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
|
||||
ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1000);
|
||||
s_sent_fragment = true;
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
s_sent_fragment = 1; // "enable" fn
|
||||
mg_mgr_poll(&mgr, 0); // call it (process fake frag IP)
|
||||
ASSERT(s_sent_fragment == 2); // check it followed the right path
|
||||
|
||||
s_driver_data.len = 0;
|
||||
mg_mgr_free(&mgr);
|
||||
@@ -288,19 +334,20 @@ static void test_frag_send_path(void) {
|
||||
struct mg_mgr mgr;
|
||||
struct mg_tcpip_driver driver;
|
||||
struct mg_tcpip_if mif;
|
||||
unsigned int i;
|
||||
|
||||
mg_mgr_init(&mgr);
|
||||
memset(&mif, 0, sizeof(mif));
|
||||
memset(&s_driver_data, 0, sizeof(struct driver_data));
|
||||
driver.init = NULL, driver.tx = if_tx, driver.poll = if_poll, driver.rx = if_rx;
|
||||
driver.init = NULL, driver.tx = if_tx, driver.poll = if_poll,
|
||||
driver.rx = if_rx;
|
||||
mif.driver = &driver;
|
||||
mif.driver_data = &s_driver_data;
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
mif.mtu = 500;
|
||||
mif.mtu = 500; // force ad hoc small MTU to fragment IP
|
||||
mg_http_listen(&mgr, "http://0.0.0.0:0", frag_send_fn, NULL);
|
||||
mgr.conns->pfn = NULL;
|
||||
for (int i = 0; i < 10; i++)
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
for (i = 0; i < 10; i++) mg_mgr_poll(&mgr, 0);
|
||||
ASSERT(s_seg_sent == 3);
|
||||
s_driver_data.len = 0;
|
||||
mg_mgr_free(&mgr);
|
||||
@@ -312,6 +359,7 @@ static void test_fragmentation(void) {
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
test_csum();
|
||||
test_statechange();
|
||||
test_poll();
|
||||
test_retransmit();
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
allow_anonymous true
|
||||
listener 8883 127.0.0.1
|
||||
cafile /etc/mosquitto/certs/ca.crt
|
||||
certfile /etc/mosquitto/certs/server.crt
|
||||
keyfile /etc/mosquitto/certs/server.key
|
||||
#
|
||||
listener 1883 127.0.0.1
|
||||
@@ -0,0 +1,7 @@
|
||||
allow_anonymous true
|
||||
listener 8883 127.0.0.1
|
||||
cafile /Users/runner/work/mongoose/mongoose/test/certs/ca.crt
|
||||
certfile /Users/runner/work/mongoose/mongoose/test/certs/server.crt
|
||||
keyfile /Users/runner/work/mongoose/mongoose/test/certs/server.key
|
||||
#
|
||||
listener 1883 127.0.0.1
|
||||
+1
-3
@@ -47,9 +47,7 @@ int main(int argc, char *argv[]) {
|
||||
int i, j, ch;
|
||||
const char *strip_prefix = "";
|
||||
|
||||
printf("%s", "#include <stddef.h>\n");
|
||||
printf("%s", "#include <string.h>\n");
|
||||
printf("%s", "#include <time.h>\n");
|
||||
printf("%s", "#include \"mongoose.h\"\n");
|
||||
printf("%s", "\n");
|
||||
printf("%s", "#if defined(__cplusplus)\nextern \"C\" {\n#endif\n");
|
||||
printf("%s", "const char *mg_unlist(size_t no);\n");
|
||||
|
||||
+1
-3
@@ -2,9 +2,7 @@
|
||||
|
||||
const Pack = async function(files) {
|
||||
let out = `// DO NOT EDIT. This file is generated
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
df
|
||||
ls -l /mnt
|
||||
sudo systemctl stop docker
|
||||
sudo mkdir -p /mnt/docker
|
||||
sudo cp test/ga_docker_daemon.json /etc/docker/daemon.json
|
||||
sudo systemctl start docker
|
||||
|
||||
+11
-10
@@ -2,9 +2,9 @@
|
||||
BRIDGE=mg_bridge0
|
||||
BRIDGE_BROADCAST=192.168.32.255
|
||||
BRIDGE_IP=192.168.32.1
|
||||
BRIDGE_IP_MASK=192.168.32.0/24
|
||||
BRIDGE_NETWORK=192.168.32.0/24
|
||||
BRIDGE_MASK=255.255.255.0
|
||||
PHY=eth0
|
||||
// Host network is 'eth0'
|
||||
TAP=tap0
|
||||
|
||||
# see our network configuration
|
||||
@@ -33,23 +33,24 @@ sudo ip link set $TAP up
|
||||
echo
|
||||
|
||||
echo "Network configuration script: NAT"
|
||||
sudo iptables -A FORWARD -d $BRIDGE_IP_MASK -o $BRIDGE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
sudo iptables -A FORWARD -s $BRIDGE_IP_MASK -i $BRIDGE -j ACCEPT
|
||||
sudo iptables -A FORWARD -d $BRIDGE_NETWORK -o $BRIDGE -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
sudo iptables -A FORWARD -s $BRIDGE_NETWORK -i $BRIDGE -j ACCEPT
|
||||
sudo iptables -A FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT
|
||||
sudo iptables -A FORWARD -o $BRIDGE -j REJECT --reject-with icmp-port-unreachable
|
||||
sudo iptables -A FORWARD -i $BRIDGE -j REJECT --reject-with icmp-port-unreachable
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_IP_MASK -d 224.0.0.0/24 -j RETURN
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_IP_MASK -d 255.255.255.255/32 -j RETURN
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_IP_MASK ! -d $BRIDGE_IP_MASK -p tcp -j MASQUERADE --to-ports 1024-65535
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_IP_MASK ! -d $BRIDGE_IP_MASK -p udp -j MASQUERADE --to-ports 1024-65535
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_IP_MASK ! -d $BRIDGE_IP_MASK -j MASQUERADE
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_NETWORK -d 224.0.0.0/24 -j RETURN
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_NETWORK -d 255.255.255.255/32 -j RETURN
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_NETWORK ! -d $BRIDGE_NETWORK -p tcp -j MASQUERADE --to-ports 1024-65535
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_NETWORK ! -d $BRIDGE_NETWORK -p udp -j MASQUERADE --to-ports 1024-65535
|
||||
sudo iptables -t nat -A POSTROUTING -s $BRIDGE_NETWORK ! -d $BRIDGE_NETWORK -j MASQUERADE
|
||||
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
|
||||
echo
|
||||
|
||||
# Setup DHCP server
|
||||
echo "Network configuration script: DHCP server"
|
||||
echo "Serving from $BRIDGE_IP"
|
||||
export HOST_IP = $BRIDGE_IP
|
||||
HOST_IP=$BRIDGE_IP
|
||||
export HOST_IP
|
||||
echo "dhcpd.conf:"
|
||||
cat test/dhcpd.conf
|
||||
echo
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
sudo apt-get -y install mosquitto
|
||||
# "for some reason" they think starting the server is cool
|
||||
sudo cp test/mosquitto.conf /etc/mosquitto/conf.d/
|
||||
sudo cp test/certs/ca.crt /etc/mosquitto/certs/
|
||||
sudo cp test/certs/server.crt /etc/mosquitto/certs/
|
||||
sudo cp test/certs/server.key /etc/mosquitto/certs/
|
||||
sudo ss -tpln | grep 883
|
||||
# so we need to restart it with the actual config
|
||||
sudo systemctl restart mosquitto
|
||||
sudo ss -tpln | grep 883
|
||||
sudo cat /var/log/mosquitto/*
|
||||
@@ -1,4 +1,4 @@
|
||||
CFLAGS = -W -Wall -Wextra -g -I. # Build options
|
||||
CFLAGS = -g -I. # This is a known version, no need to check
|
||||
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_IPV6=1
|
||||
CFLAGS_EXTRA ?= -DMG_TLS=MG_TLS_BUILTIN
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ static void cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
mg_tls_init(c, &opts);
|
||||
}
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = ev_data;
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
|
||||
if (mg_match(hm->uri, mg_str("/upload"), NULL)) {
|
||||
// Serve file upload
|
||||
|
||||
@@ -35,7 +35,7 @@ extern "C" {
|
||||
#define MG_ARCH_FREERTOS 5 // FreeRTOS
|
||||
#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
|
||||
#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
|
||||
#define MG_ARCH_NEWLIB 8 // Bare metal ARM
|
||||
#define MG_ARCH_ARMGCC 8 // Bare metal ARM
|
||||
#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
|
||||
#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
|
||||
#define MG_ARCH_PICOSDK 11 // Raspberry Pi Pico-SDK (RP2040, RP2350)
|
||||
@@ -220,7 +220,7 @@ static inline int mg_mkdir(const char *path, mode_t mode) {
|
||||
#endif // MG_ARCH == MG_ARCH_FREERTOS
|
||||
|
||||
|
||||
#if MG_ARCH == MG_ARCH_NEWLIB
|
||||
#if MG_ARCH == MG_ARCH_ARMGCC
|
||||
#define _POSIX_TIMERS
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
+258
-73
@@ -18,6 +18,7 @@ static int s_num_tests = 0;
|
||||
s_num_tests++; \
|
||||
if (!(expr)) { \
|
||||
printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr); \
|
||||
fflush(stdout); \
|
||||
ABORT(); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -374,6 +375,65 @@ static void test_sntp(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MQTT_LOCALHOST
|
||||
#define MQTT_URL "mqtt://127.0.0.1:1883"
|
||||
#else
|
||||
#define MQTT_URL "mqtt://broker.hivemq.com:1883"
|
||||
#endif
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
#define MQTTS_URL "mqtts://mongoose.ws:8883" // test requires TLS 1.3
|
||||
#define MQTTS_CA mg_str(s_ca_cert)
|
||||
static const char *s_ca_cert =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
|
||||
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
|
||||
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n"
|
||||
"WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n"
|
||||
"ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n"
|
||||
"MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n"
|
||||
"h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n"
|
||||
"0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n"
|
||||
"A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n"
|
||||
"T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n"
|
||||
"B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n"
|
||||
"B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n"
|
||||
"KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n"
|
||||
"OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n"
|
||||
"jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n"
|
||||
"qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n"
|
||||
"rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n"
|
||||
"HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n"
|
||||
"hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n"
|
||||
"ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n"
|
||||
"3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n"
|
||||
"NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n"
|
||||
"ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n"
|
||||
"TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n"
|
||||
"jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n"
|
||||
"oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n"
|
||||
"4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n"
|
||||
"mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
|
||||
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
#elif MG_TLS
|
||||
#ifdef MQTT_LOCALHOST
|
||||
#define MQTTS_URL "mqtts://127.0.0.1:8883"
|
||||
#define MQTTS_CA mg_str(s_ca_cert)
|
||||
static const char *s_ca_cert =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIBFTCBvAIJAMNTFtpfcq8NMAoGCCqGSM49BAMCMBMxETAPBgNVBAMMCE1vbmdv\n"
|
||||
"b3NlMB4XDTI0MDUwNzE0MzczNloXDTM0MDUwNTE0MzczNlowEzERMA8GA1UEAwwI\n"
|
||||
"TW9uZ29vc2UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASuP+86T/rOWnGpEVhl\n"
|
||||
"fxYZ+pjMbCmDZ+vdnP0rjoxudwRMRQCv5slRlDK7Lxue761sdvqxWr0Ma6TFGTNg\n"
|
||||
"epsRMAoGCCqGSM49BAMCA0gAMEUCIQCwb2CxuAKm51s81S6BIoy1IcandXSohnqs\n"
|
||||
"us64BAA7QgIgGGtUrpkgFSS0oPBlCUG6YPHFVw42vTfpTC0ySwAS0M4=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
#else
|
||||
#define MQTTS_URL "mqtts://broker.hivemq.com:8883"
|
||||
#define MQTTS_CA mg_unpacked("/data/ca.pem")
|
||||
#endif // MQTT_LOCALHOST
|
||||
#endif
|
||||
|
||||
struct mqtt_data {
|
||||
char *topic;
|
||||
char *msg;
|
||||
@@ -390,8 +450,20 @@ struct mqtt_data {
|
||||
static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mqtt_data *test_data = (struct mqtt_data *) c->fn_data;
|
||||
char *buf = test_data->msg;
|
||||
|
||||
if (ev == MG_EV_MQTT_OPEN) {
|
||||
#if MG_TLS
|
||||
if (c->is_tls && ev == MG_EV_CONNECT) {
|
||||
struct mg_tls_opts opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.ca = MQTTS_CA;
|
||||
#if defined( MQTT_LOCALHOST) && MG_TLS != MG_TLS_BUILTIN
|
||||
MG_ERROR(("Hostname not tested"));
|
||||
#else
|
||||
opts.name = mg_url_host(MQTTS_URL);
|
||||
#endif
|
||||
mg_tls_init(c, &opts);
|
||||
} else
|
||||
#endif
|
||||
if (ev == MG_EV_MQTT_OPEN) {
|
||||
buf[0] = *(int *) ev_data == 0 ? 'X' : 'Y';
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
buf[0] = 0;
|
||||
@@ -416,35 +488,34 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||
mm->data.buf);
|
||||
|
||||
if (mm->cmd == MQTT_CMD_PUBLISH && c->is_mqtt5) {
|
||||
size_t pos = 0;
|
||||
size_t pos = 0, i = 0, j = 0;
|
||||
struct mg_mqtt_prop prop;
|
||||
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) > 0);
|
||||
ASSERT(prop.iv == 10 && prop.id == MQTT_PROP_MESSAGE_EXPIRY_INTERVAL);
|
||||
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) > 0);
|
||||
ASSERT(prop.id == MQTT_PROP_PAYLOAD_FORMAT_INDICATOR);
|
||||
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) > 0);
|
||||
ASSERT(prop.id == MQTT_PROP_CONTENT_TYPE);
|
||||
ASSERT(strncmp(prop.val.buf, "test_content_val_2", prop.val.len) == 0 &&
|
||||
prop.val.len == strlen("test_content_val_2"));
|
||||
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) > 0);
|
||||
ASSERT(prop.id == MQTT_PROP_USER_PROPERTY);
|
||||
ASSERT(strncmp(prop.key.buf, "test_key_1", prop.key.len) == 0 &&
|
||||
prop.key.len == strlen("test_key_1"));
|
||||
ASSERT(strncmp(prop.val.buf, "test_value_1", prop.val.len) == 0 &&
|
||||
prop.val.len == strlen("test_value_1"));
|
||||
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) > 0);
|
||||
ASSERT(prop.id == MQTT_PROP_USER_PROPERTY);
|
||||
ASSERT(strncmp(prop.key.buf, "test_key_2", prop.key.len) == 0 &&
|
||||
prop.key.len == strlen("test_key_2"));
|
||||
ASSERT(strncmp(prop.val.buf, "test_value_2", prop.val.len) == 0 &&
|
||||
prop.val.len == strlen("test_value_2"));
|
||||
|
||||
for (i = 0; i < 5 ; i++) {
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) > 0);
|
||||
if (prop.id == MQTT_PROP_MESSAGE_EXPIRY_INTERVAL) {
|
||||
ASSERT(prop.iv == 10);
|
||||
j += 1;
|
||||
} else if (prop.id == MQTT_PROP_PAYLOAD_FORMAT_INDICATOR) {
|
||||
j += 2;
|
||||
continue;
|
||||
} else if (prop.id == MQTT_PROP_CONTENT_TYPE) {
|
||||
ASSERT(strncmp(prop.val.buf, "test_content_val_2", prop.val.len) == 0 && prop.val.len == strlen("test_content_val_2"));
|
||||
j += 4;
|
||||
} else if (prop.id == MQTT_PROP_USER_PROPERTY) {
|
||||
if (strncmp(prop.key.buf, "test_key_1", prop.key.len) == 0 && prop.key.len == strlen("test_key_1")) {
|
||||
ASSERT(strncmp(prop.val.buf, "test_value_1", prop.val.len) == 0 && prop.val.len == strlen("test_value_1"));
|
||||
j += 8;
|
||||
} else if (strncmp(prop.key.buf, "test_key_2", prop.key.len) == 0 && prop.key.len == strlen("test_key_2")) {
|
||||
ASSERT(strncmp(prop.val.buf, "test_value_2", prop.val.len) == 0 && prop.val.len == strlen("test_value_2"));
|
||||
j += 16;
|
||||
} else {
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT((pos = mg_mqtt_next_prop(mm, &prop, pos)) == 0);
|
||||
ASSERT(j == 31);
|
||||
}
|
||||
}
|
||||
(void) c;
|
||||
@@ -475,7 +546,7 @@ static void test_mqtt_base(void) {
|
||||
struct mqtt_data test_data = {buf, buf, 10, 10, 0};
|
||||
struct mg_mgr mgr;
|
||||
struct mg_connection *c;
|
||||
const char *url = "mqtt://broker.hivemq.com:1883";
|
||||
const char *url = MQTT_URL;
|
||||
int i;
|
||||
mg_mgr_init(&mgr);
|
||||
|
||||
@@ -517,7 +588,11 @@ static void test_mqtt_basic(void) {
|
||||
struct mg_mgr mgr;
|
||||
struct mg_connection *c;
|
||||
struct mg_mqtt_opts opts;
|
||||
const char *url = "mqtt://broker.hivemq.com:1883";
|
||||
#if MG_TLS
|
||||
const char *url = MQTTS_URL;
|
||||
#else
|
||||
const char *url = MQTT_URL;
|
||||
#endif
|
||||
int i, retries;
|
||||
|
||||
// Connect with empty client ID, no options, ergo MQTT = 3.1.1
|
||||
@@ -562,6 +637,25 @@ static void test_mqtt_basic(void) {
|
||||
test_data.flags = 0;
|
||||
opts.retransmit_id = 0;
|
||||
|
||||
#if MG_TLS
|
||||
// send more than 1 record, content is not relevant
|
||||
{
|
||||
static char somedata[21098];
|
||||
mg_random(somedata, sizeof(somedata));
|
||||
opts.message = mg_str_n(somedata, sizeof(somedata));
|
||||
}
|
||||
opts.qos = 1, opts.retain = false, opts.retransmit_id = 0;
|
||||
mg_mqtt_pub(c, &opts);
|
||||
tbuf[0] = 0;
|
||||
for (i = 0; i < 1000 && test_data.flags == 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
ASSERT(test_data.flags == flags_published);
|
||||
for (i = 0; i < 1000 && tbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
ASSERT(tbuf[0] != 0); // just check we were able to send and receive
|
||||
memset(mbuf + 1, 0, sizeof(mbuf) - 1);
|
||||
test_data.flags = 0;
|
||||
opts.retransmit_id = 0;
|
||||
#endif
|
||||
|
||||
// Clean Disconnect !
|
||||
mg_mqtt_disconnect(c, NULL);
|
||||
for (i = 0; i < 10 && mbuf[0] != 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
@@ -576,7 +670,7 @@ static void test_mqtt_ver(uint8_t mqtt_version) {
|
||||
struct mg_connection *c;
|
||||
struct mg_mqtt_opts opts;
|
||||
struct mg_mqtt_prop properties[5];
|
||||
const char *url = "mqtt://broker.hivemq.com:1883";
|
||||
const char *url = MQTT_URL;
|
||||
int i, retries;
|
||||
|
||||
MG_DEBUG(("ver: %u", mqtt_version));
|
||||
@@ -593,7 +687,7 @@ static void test_mqtt_ver(uint8_t mqtt_version) {
|
||||
opts.message = mg_str("mg_will_messsage");
|
||||
opts.client_id = genstring(client_id, sizeof(client_id));
|
||||
c = mg_mqtt_connect(&mgr, url, &opts, mqtt_cb, &test_data);
|
||||
for (i = 0; i < 300 && mbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
for (i = 0; i < 500 && mbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
if (mbuf[0] != 'X') MG_INFO(("[%s]", mbuf));
|
||||
ASSERT(mbuf[0] == 'X');
|
||||
ASSERT(test_data.flags == 0);
|
||||
@@ -664,9 +758,14 @@ static void test_mqtt_ver(uint8_t mqtt_version) {
|
||||
|
||||
static void test_mqtt(void) {
|
||||
test_mqtt_base();
|
||||
#ifdef NO_MQTT_TESTS
|
||||
MG_ERROR(("MQTT tests skipped on request"));
|
||||
(void) test_mqtt_basic, (void) test_mqtt_ver;
|
||||
#else
|
||||
test_mqtt_basic();
|
||||
test_mqtt_ver(4);
|
||||
test_mqtt_ver(5);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eh1(struct mg_connection *c, int ev, void *ev_data) {
|
||||
@@ -1098,7 +1197,7 @@ static void test_http_server(void) {
|
||||
struct mg_str data = mg_file_read(&mg_fs_posix, "./data/ca.pem");
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /ca.pem HTTP/1.0\r\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, data.buf) == 0);
|
||||
free((void *) data.buf);
|
||||
mg_free((void *) data.buf);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1178,7 +1277,7 @@ static void test_http_server(void) {
|
||||
s = mg_file_read(&mg_fs_posix, "uploaded.txt");
|
||||
ASSERT(s.buf != NULL);
|
||||
ASSERT(strcmp(s.buf, "hello\nworld") == 0);
|
||||
free((void *) s.buf);
|
||||
mg_free((void *) s.buf);
|
||||
remove("uploaded.txt");
|
||||
}
|
||||
|
||||
@@ -1311,6 +1410,9 @@ static void test_tls(void) {
|
||||
char buf[FETCH_BUF_SIZE];
|
||||
struct mg_tls_opts opts;
|
||||
struct mg_str data = mg_unpacked("/Makefile");
|
||||
char bigdata[FETCH_BUF_SIZE - 256]; // leave extra room
|
||||
struct mg_str bd;
|
||||
ASSERT(data.buf != NULL && data.len > 0);
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
// opts.ca = mg_str(s_tls_ca);
|
||||
opts.cert = mg_unpacked("/certs/server.crt");
|
||||
@@ -1321,17 +1423,29 @@ static void test_tls(void) {
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\n\n") == 200);
|
||||
// MG_INFO(("%s", buf));
|
||||
ASSERT(cmpbody(buf, "hello\n") == 0);
|
||||
// POST a large file, make sure we drain TLS buffers and read all, #2619
|
||||
ASSERT(data.buf != NULL && data.len > 0);
|
||||
// POST a large file, several MSS but less than max TLS record length
|
||||
// make sure we drain TLS buffers and read all, #2619
|
||||
ASSERT(data.len > 3100 && data.len < 16384); // pick another file on failure
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"POST /foo/bar HTTP/1.0\n"
|
||||
"POST /body HTTP/1.0\n"
|
||||
"Content-Length: %lu\n\n"
|
||||
"%s",
|
||||
data.len, data.buf) == 200);
|
||||
// /body returns data back, so verify contents (both server and client send
|
||||
// and receive the whole file
|
||||
ASSERT(cmpbody(buf, data.buf) == 0);
|
||||
// repeat with a really large "file", several times max TLS record length
|
||||
bd = genstring(bigdata, sizeof(bigdata));
|
||||
ASSERT(fetch(&mgr, buf, url,
|
||||
"POST /body HTTP/1.0\n"
|
||||
"Content-Length: %lu\n\n"
|
||||
"%s",
|
||||
bd.len, bd.buf) == 200);
|
||||
ASSERT(cmpbody(buf, bd.buf) == 0);
|
||||
#if MG_TLS == MG_TLS_BUILTIN && defined(__linux__)
|
||||
// fire patched server, test multiple TLS records per TCP segment handling
|
||||
// skip other TLS stacks to avoid "bad client hello", we are 1.3 only
|
||||
{
|
||||
if (access("tls_multirec/server", X_OK) == 0) {
|
||||
ASSERT(system("tls_multirec/server -d tls_multirec &") == 0);
|
||||
sleep(1);
|
||||
// fetch() needs to loop enough times in order to process all TLS records;
|
||||
@@ -1340,6 +1454,8 @@ static void test_tls(void) {
|
||||
"GET /thefile HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, data.buf) == 0); // "thefile" links to Makefile
|
||||
ASSERT(system("killall tls_multirec/server") == 0);
|
||||
} else {
|
||||
MG_ERROR(("SKIPPED TLS MULTIPLE RECORDS TEST, tls_multirec/server NOT PRESENT"));
|
||||
}
|
||||
#else
|
||||
printf(
|
||||
@@ -1389,21 +1505,28 @@ static void test_http_client(void) {
|
||||
mg_mgr_init(&mgr);
|
||||
c = mg_http_connect(&mgr, url, f3, &ok);
|
||||
ASSERT(c != NULL);
|
||||
for (i = 0; i < 500 && ok <= 0; i++) mg_mgr_poll(&mgr, 1);
|
||||
MG_INFO(("%d", ok));
|
||||
ASSERT(ok == 301);
|
||||
for (i = 0; i < 1000 && ok <= 0; i++) mg_mgr_poll(&mgr, 1);
|
||||
MG_INFO(("OK: %d", ok));
|
||||
ASSERT(ok == 301 || ok == 200);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
ok = 0;
|
||||
#if MG_TLS
|
||||
c = mg_http_connect(&mgr, "https://cesanta.com", f3, &ok);
|
||||
url = "https://cesanta.com";
|
||||
opts.name = mg_url_host(url);
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
// our TLS does not search for the proper CA in a bundle
|
||||
opts.ca = mg_file_read(&mg_fs_posix, "data/e5.crt");
|
||||
#endif
|
||||
c = mg_http_connect(&mgr, url, f3, &ok);
|
||||
ASSERT(c != NULL);
|
||||
mg_tls_init(c, &opts);
|
||||
for (i = 0; i < 1500 && ok <= 0; i++) mg_mgr_poll(&mgr, 1);
|
||||
MG_INFO(("OK: %d", ok));
|
||||
ASSERT(ok == 200);
|
||||
mg_mgr_poll(&mgr, 1);
|
||||
|
||||
// Test failed host validation
|
||||
c = mg_http_connect(&mgr, "https://cesanta.com", f3, &ok);
|
||||
// Make host validationfail
|
||||
c = mg_http_connect(&mgr, url, f3, &ok);
|
||||
ASSERT(c != NULL);
|
||||
opts.name = mg_str("dummy"); // Set some invalid hostname value
|
||||
mg_tls_init(c, &opts);
|
||||
@@ -1412,16 +1535,19 @@ static void test_http_client(void) {
|
||||
MG_INFO(("OK: %d", ok));
|
||||
ASSERT(ok == 777);
|
||||
mg_mgr_poll(&mgr, 1);
|
||||
opts.name = mg_url_host(url);
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
mg_free((void *) opts.ca.buf);
|
||||
#endif
|
||||
|
||||
// Test empty CA
|
||||
// Disable mbedTLS: https://github.com/Mbed-TLS/mbedtls/issues/7075
|
||||
#if MG_TLS != MG_TLS_MBED
|
||||
opts.name = mg_str("cesanta.com");
|
||||
opts.ca = mg_str("");
|
||||
c = mg_http_connect(&mgr, "https://cesanta.com", f3, &ok);
|
||||
c = mg_http_connect(&mgr, url, f3, &ok);
|
||||
mg_tls_init(c, &opts);
|
||||
ok = 0;
|
||||
for (i = 0; i < 500 && ok <= 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
for (i = 0; i < 1000 && ok <= 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
MG_INFO(("OK: %d", ok));
|
||||
ASSERT(ok == 200);
|
||||
mg_mgr_poll(&mgr, 1);
|
||||
@@ -1434,6 +1560,7 @@ static void test_http_client(void) {
|
||||
// it is guaranteed to hit IPv6 resolution path.
|
||||
c = mg_http_connect(&mgr, "http://ipv6.google.com", f3, &ok);
|
||||
for (i = 0; i < 500 && ok <= 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
MG_INFO(("OK: %d", ok));
|
||||
ASSERT(ok == 200);
|
||||
#endif
|
||||
|
||||
@@ -1976,7 +2103,6 @@ static void test_timer(void) {
|
||||
ASSERT(mgr.timers == NULL);
|
||||
ASSERT(mgr.conns == NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool sn(const char *fmt, ...) {
|
||||
@@ -2028,7 +2154,7 @@ static void test_str(void) {
|
||||
{
|
||||
struct mg_str s = mg_strdup(mg_str("a"));
|
||||
ASSERT(mg_strcmp(s, mg_str("a")) == 0);
|
||||
free((void *) s.buf);
|
||||
mg_free((void *) s.buf);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -2144,11 +2270,11 @@ static void test_str(void) {
|
||||
|
||||
p = mg_mprintf("[%s,%M,%s]", "null", pf1, 2, 3, "hi");
|
||||
ASSERT(strcmp(p, "[null,5,hi]") == 0);
|
||||
free(p);
|
||||
mg_free(p);
|
||||
|
||||
p = mg_mprintf("[%M,%d]", pf2, 10, 7);
|
||||
ASSERT(strcmp(p, "[9876543210,7]") == 0);
|
||||
free(p);
|
||||
mg_free(p);
|
||||
|
||||
mg_xprintf(mg_pfn_iobuf, &io, "[%M", pf2, 10);
|
||||
mg_xprintf(mg_pfn_iobuf, &io, ",");
|
||||
@@ -2349,7 +2475,7 @@ static void test_str(void) {
|
||||
|
||||
static void fn1(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_ERROR) {
|
||||
free(*(char **) c->fn_data); // See #2263
|
||||
mg_free(*(char **) c->fn_data); // See #2263
|
||||
*(char **) c->fn_data = mg_mprintf("%s", (char *) ev_data);
|
||||
}
|
||||
(void) c;
|
||||
@@ -2370,7 +2496,7 @@ static void test_dns_error(const char *dns_server_url, const char *errstr) {
|
||||
mg_mgr_free(&mgr);
|
||||
// MG_DEBUG(("buf: [%s] [%s]", buf, errstr));
|
||||
ASSERT(buf != NULL && strcmp(buf, errstr) == 0);
|
||||
free(buf);
|
||||
mg_free(buf);
|
||||
}
|
||||
|
||||
static void test_dns(void) {
|
||||
@@ -2424,14 +2550,14 @@ static void test_dns(void) {
|
||||
// 0000 00 00 00 00 00 01 00 00 00 00 00 00 03 61 62 63 .............abc
|
||||
// 0010 05 6c 6f 63 61 6c 00 00 01 00 01 .local.....
|
||||
uint8_t d[] = {
|
||||
0x00, 0x00, // txid: 0
|
||||
0x00, 0x00, // flags: 0 (Query flag = 0)
|
||||
0x00, 0x01, // numQuestions: 1
|
||||
0x00, 0x00, // numAnswers: 1
|
||||
0x00, 0x00, 0x00, 0x00, // additional RRs
|
||||
0x03, 0x61, 0x62, 0x63, // "abc"
|
||||
0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // "local"
|
||||
0x00, 0x00, 0x01, 0x00, 0x01 // domain end, type, class
|
||||
0x00, 0x00, // txid: 0
|
||||
0x00, 0x00, // flags: 0 (Query flag = 0)
|
||||
0x00, 0x01, // numQuestions: 1
|
||||
0x00, 0x00, // numAnswers: 1
|
||||
0x00, 0x00, 0x00, 0x00, // additional RRs
|
||||
0x03, 0x61, 0x62, 0x63, // "abc"
|
||||
0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // "local"
|
||||
0x00, 0x00, 0x01, 0x00, 0x01 // domain end, type, class
|
||||
};
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
ASSERT(mg_dns_parse(d, sizeof(d), &dm) == 1);
|
||||
@@ -2457,7 +2583,7 @@ static void test_util(void) {
|
||||
data = mg_file_read(&mg_fs_posix, "data.txt");
|
||||
ASSERT(data.buf != NULL);
|
||||
ASSERT(strcmp(data.buf, "hi") == 0);
|
||||
free((void *) data.buf);
|
||||
mg_free((void *) data.buf);
|
||||
remove("data.txt");
|
||||
ASSERT(mg_aton(mg_str("0"), &a) == false);
|
||||
ASSERT(mg_aton(mg_str("0.0.0."), &a) == false);
|
||||
@@ -2469,15 +2595,17 @@ static void test_util(void) {
|
||||
ASSERT(ipv4 == mg_htonl(0x7f000001));
|
||||
ASSERT(mg_ntohl(ipv4) == 0x7f000001);
|
||||
MG_STORE_BE32(&ipv4, 0x5678abcd);
|
||||
ASSERT(((uint8_t *)&ipv4)[0] == 0x56 && ((uint8_t *)&ipv4)[1] == 0x78 && ((uint8_t *)&ipv4)[2] == 0xab && ((uint8_t *)&ipv4)[3] == 0xcd);
|
||||
ASSERT(((uint8_t *) &ipv4)[0] == 0x56 && ((uint8_t *) &ipv4)[1] == 0x78 &&
|
||||
((uint8_t *) &ipv4)[2] == 0xab && ((uint8_t *) &ipv4)[3] == 0xcd);
|
||||
ASSERT(MG_LOAD_BE32(&ipv4) == 0x5678abcd);
|
||||
MG_STORE_BE16(&port, 0x1234);
|
||||
ASSERT(((uint8_t *)&port)[0] == 0x12 && ((uint8_t *)&port)[1] == 0x34);
|
||||
ASSERT(((uint8_t *) &port)[0] == 0x12 && ((uint8_t *) &port)[1] == 0x34);
|
||||
ASSERT(MG_LOAD_BE16(&port) == 0x1234);
|
||||
ASSERT(port == mg_htons(0x1234));
|
||||
ASSERT(mg_ntohs(port) == 0x1234);
|
||||
MG_STORE_BE24(&ipv4, 0xef2345);
|
||||
ASSERT(((uint8_t *)&ipv4)[0] == 0xef && ((uint8_t *)&ipv4)[1] == 0x23 && ((uint8_t *)&ipv4)[2] == 0x45);
|
||||
ASSERT(((uint8_t *) &ipv4)[0] == 0xef && ((uint8_t *) &ipv4)[1] == 0x23 &&
|
||||
((uint8_t *) &ipv4)[2] == 0x45);
|
||||
ASSERT(MG_LOAD_BE24(&ipv4) == 0xef2345);
|
||||
|
||||
memset(a.ip, 0xa5, sizeof(a.ip));
|
||||
@@ -2567,7 +2695,7 @@ static void test_util(void) {
|
||||
{
|
||||
s = mg_mprintf("%3d", 123);
|
||||
ASSERT(strcmp(s, "123") == 0);
|
||||
free(s);
|
||||
mg_free(s);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -2991,13 +3119,13 @@ static void test_packed(void) {
|
||||
// printf("---> %s\n", buf);
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /Makefile HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, data.buf) == 0);
|
||||
free((void *) data.buf);
|
||||
mg_free((void *) data.buf);
|
||||
|
||||
// Load file deeper in the FS tree directly
|
||||
data = mg_file_read(&mg_fs_posix, "data/ssi.h");
|
||||
ASSERT(fetch(&mgr, buf, url, "GET /data/ssi.h HTTP/1.0\n\n") == 200);
|
||||
ASSERT(cmpbody(buf, data.buf) == 0);
|
||||
free((void *) data.buf);
|
||||
mg_free((void *) data.buf);
|
||||
|
||||
// List root dir
|
||||
ASSERT(fetch(&mgr, buf, url, "GET / HTTP/1.0\n\n") == 200);
|
||||
@@ -3298,14 +3426,14 @@ static void test_json(void) {
|
||||
ASSERT(str != NULL);
|
||||
// printf("---> [%s]\n", str);
|
||||
ASSERT(strcmp(str, "b") == 0);
|
||||
free(str);
|
||||
mg_free(str);
|
||||
|
||||
json = mg_str("{\"a\": \"hi\\nthere\",\"b\": [12345, true]}");
|
||||
str = mg_json_get_str(json, "$.a");
|
||||
|
||||
ASSERT(str != NULL);
|
||||
ASSERT(strcmp(str, "hi\nthere") == 0);
|
||||
free(str);
|
||||
mg_free(str);
|
||||
|
||||
ASSERT(mg_json_get_long(json, "$.foo", -42) == -42);
|
||||
ASSERT(mg_json_get_long(json, "$.b[0]", -42) == 12345);
|
||||
@@ -3324,10 +3452,10 @@ static void test_json(void) {
|
||||
json = mg_str("[\"YWJj\", \"0100026869\"]");
|
||||
ASSERT((str = mg_json_get_b64(json, "$[0]", &len)) != NULL);
|
||||
ASSERT(len == 3 && memcmp(str, "abc", (size_t) len) == 0);
|
||||
free(str);
|
||||
mg_free(str);
|
||||
ASSERT((str = mg_json_get_hex(json, "$[1]", &len)) != NULL);
|
||||
ASSERT(len == 5 && memcmp(str, "\x01\x00\x02hi", (size_t) len) == 0);
|
||||
free(str);
|
||||
mg_free(str);
|
||||
|
||||
json = mg_str("{\"a\":[1,2,3], \"ab\": 2}");
|
||||
ASSERT(mg_json_get_long(json, "$.a[0]", -42) == 1);
|
||||
@@ -3760,12 +3888,69 @@ static void test_x25519(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_rsa(void) {
|
||||
#if MG_TLS == MG_TLS_BUILTIN
|
||||
const unsigned char mod[] = {
|
||||
0x00, 0xba, 0xee, 0x3b, 0x0b, 0x89, 0x58, 0xa6, 0x19, 0x0d, 0x4c, 0x89,
|
||||
0x1a, 0x85, 0x9a, 0xf4, 0x55, 0xc2, 0xdd, 0x0d, 0xd4, 0x4a, 0xf5, 0xed,
|
||||
0xda, 0x28, 0x55, 0x2f, 0x64, 0x46, 0x21, 0x9f, 0x46, 0x5c, 0xfa, 0x37,
|
||||
0x88, 0x11, 0xdf, 0xcb, 0x51, 0x73, 0x42, 0x3d, 0x5e, 0x50, 0xde, 0x11,
|
||||
0x30, 0x61, 0x04, 0x59, 0xd0, 0xf4, 0x57, 0xed, 0x13, 0x90, 0x32, 0xc5,
|
||||
0x3f, 0xe6, 0x66, 0xfc, 0x2a, 0x12, 0xa3, 0x1f, 0xd1, 0x77, 0x21, 0x65,
|
||||
0xdf, 0x9a, 0xcf, 0x04, 0x05, 0xc3, 0x1c, 0xf8, 0x79, 0xb5, 0xf5, 0x97,
|
||||
0x68, 0x98, 0x2e, 0x96, 0x85, 0x3f, 0xee, 0x71, 0x91, 0xc1, 0x54, 0x71,
|
||||
0x9a, 0x80, 0x1f, 0xbe, 0x21, 0xd9, 0xc1, 0x80, 0x9b, 0xd0, 0x5d, 0xb3,
|
||||
0x76, 0x3e, 0xcc, 0x14, 0x3d, 0xec, 0xb7, 0x18, 0x74, 0xfb, 0xc4, 0x0e,
|
||||
0x56, 0x8d, 0x3d, 0x78, 0xe6, 0xca, 0xcd, 0x9d, 0xc6, 0x20, 0x5a, 0xeb,
|
||||
0x9b, 0xc8, 0x19, 0x5e, 0xeb, 0x80, 0xd2, 0xb2, 0xfe, 0x88, 0x15, 0x5c,
|
||||
0x7c, 0x6b, 0x26, 0xe0, 0x43, 0xda, 0xa4, 0x07, 0x85, 0x73, 0xc4, 0x80,
|
||||
0x28, 0xcb, 0xda, 0x18, 0x56, 0x37, 0x91, 0xd6, 0x41, 0xa1, 0x0b, 0xa2,
|
||||
0x77, 0xd0, 0x62, 0x31, 0xc7, 0xc2, 0x67, 0x6d, 0x75, 0x08, 0x80, 0xe7,
|
||||
0xb6, 0xbe, 0xc2, 0x25, 0xc9, 0xe0, 0x2c, 0x02, 0xbf, 0x39, 0x61, 0x7e,
|
||||
0x32, 0xa4, 0xc9, 0xe7, 0x91, 0xe3, 0xa0, 0xcd, 0x94, 0x24, 0xbf, 0x8c,
|
||||
0xeb, 0x47, 0x76, 0x53, 0x85, 0xb3, 0xb7, 0x31, 0x80, 0x3c, 0x77, 0x10,
|
||||
0x69, 0xc3, 0x04, 0xd1, 0x60, 0x4c, 0x74, 0xda, 0x15, 0x18, 0x0b, 0x20,
|
||||
0x6f, 0xb3, 0x03, 0x58, 0x4a, 0xfc, 0xd1, 0xd2, 0xcf, 0x37, 0x15, 0x0a,
|
||||
0x63, 0xc8, 0xe9, 0xd5, 0x7d, 0xd5, 0xf2, 0x90, 0x78, 0x53, 0x49, 0xa9,
|
||||
0xc5, 0x25, 0x65, 0x5c, 0x01};
|
||||
const unsigned char exp[] = {1, 0, 1}; // 65537
|
||||
const unsigned char sig[] = {
|
||||
0x1e, 0xb1, 0x6a, 0xcb, 0x39, 0x63, 0x12, 0xed, 0x85, 0x62, 0x4b, 0x85,
|
||||
0x47, 0x25, 0x67, 0xbd, 0xbd, 0x0e, 0xaa, 0x73, 0x34, 0x5f, 0x07, 0x2b,
|
||||
0xbb, 0x4f, 0xf5, 0x21, 0x88, 0xb1, 0x04, 0x2c, 0xbb, 0x52, 0x72, 0x64,
|
||||
0x89, 0x45, 0x50, 0x41, 0x73, 0xca, 0xda, 0x97, 0xae, 0x81, 0x89, 0x4f,
|
||||
0x83, 0x8d, 0x48, 0x65, 0x63, 0xe7, 0x82, 0x03, 0xd2, 0x40, 0x07, 0x1c,
|
||||
0x86, 0x58, 0xd5, 0xac, 0x89, 0xb1, 0xca, 0x5c, 0xde, 0x21, 0x06, 0x88,
|
||||
0x88, 0x0c, 0xe1, 0x20, 0xc0, 0xdf, 0xf1, 0x92, 0x9b, 0xb8, 0xa5, 0xeb,
|
||||
0x6d, 0x89, 0xcc, 0x5c, 0x5c, 0x24, 0x3e, 0x9b, 0x3c, 0x35, 0x32, 0xa5,
|
||||
0x04, 0x9e, 0x8c, 0x49, 0x01, 0xee, 0xbf, 0x1f, 0x2c, 0xb0, 0x52, 0xa8,
|
||||
0xab, 0x79, 0x11, 0xcf, 0xb5, 0x5a, 0x16, 0xa1, 0xee, 0x21, 0x6a, 0x5a,
|
||||
0x2b, 0x14, 0xae, 0x32, 0x3c, 0xa2, 0x6c, 0xa2, 0x40, 0x0c, 0xcb, 0x9e,
|
||||
0x8f, 0x69, 0xab, 0xd7, 0xf3, 0xd8, 0xd1, 0xfb, 0x2d, 0xfa, 0xa9, 0x13,
|
||||
0x09, 0xbf, 0xa7, 0xca, 0xc8, 0x90, 0x74, 0x23, 0x7b, 0x3e, 0xdd, 0x81,
|
||||
0x32, 0xa7, 0x88, 0x42, 0x56, 0x8a, 0xcb, 0xe8, 0x8f, 0xef, 0x06, 0x9f,
|
||||
0x39, 0x7e, 0x8e, 0x24, 0x07, 0xb3, 0xae, 0x7e, 0x13, 0x6b, 0xf2, 0xf8,
|
||||
0x35, 0xe4, 0x16, 0x3e, 0xae, 0xf2, 0x55, 0x79, 0x10, 0x39, 0xfa, 0x70,
|
||||
0x3a, 0x1b, 0x02, 0xb3, 0x2b, 0x1d, 0x44, 0xac, 0x30, 0x81, 0xd3, 0x11,
|
||||
0xdd, 0x34, 0x1e, 0xcd, 0x26, 0xf5, 0x89, 0xc6, 0x55, 0x23, 0x17, 0x09,
|
||||
0xd2, 0xc1, 0xdc, 0x49, 0xf9, 0x99, 0x36, 0x2b, 0xf5, 0xae, 0x42, 0x5c,
|
||||
0xb7, 0x80, 0xda, 0x32, 0x69, 0x28, 0xa3, 0xee, 0xb9, 0xd4, 0x90, 0xa6,
|
||||
0xab, 0x34, 0x17, 0x5e, 0xa0, 0xd6, 0xc1, 0x54, 0xc6, 0x9c, 0x58, 0x3a,
|
||||
0xaf, 0xbf, 0xdc, 0x64};
|
||||
unsigned char v[256]; // 2048 bits
|
||||
mg_rsa_mod_pow(mod, sizeof(mod), exp, sizeof(exp), sig, sizeof(sig), v,
|
||||
sizeof(v));
|
||||
ASSERT(v[sizeof(v) - 1] == 0xbc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_crypto(void) {
|
||||
test_md5();
|
||||
test_sha1();
|
||||
test_sha256();
|
||||
test_sha384();
|
||||
test_x25519();
|
||||
test_rsa();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -3809,7 +3994,7 @@ int main(void) {
|
||||
test_http_range();
|
||||
#ifndef LOCALHOST_ONLY
|
||||
test_sntp();
|
||||
test_mqtt();
|
||||
test_mqtt(); // sorry, MQTT_LOCALHOST is also skipped
|
||||
test_http_client();
|
||||
#else
|
||||
(void) test_sntp, (void) test_mqtt, (void) test_http_client;
|
||||
|
||||
+10
-3
@@ -6,12 +6,15 @@ ifeq "$(IDE)" "GCC+make"
|
||||
BUILD = $(MAKE) -f ../gcc+make/Makefile PROJECTS=wizard
|
||||
endif
|
||||
ifeq "$(IDE)" "CubeIDE"
|
||||
BUILD = $(MAKE) -f ../cube/Makefile PROJECTS=wizard && rm -rf workspace
|
||||
BUILD = mkdir -p workspace && $(MAKE) -k -f ../cube/Makefile PROJECTS=wizard && rmdir workspace
|
||||
endif
|
||||
ifeq "$(IDE)" "MCUXpresso"
|
||||
BUILD = $(MAKE) -f ../xpresso/Makefile PROJECTS=wizard && rm -rf workspace
|
||||
BUILD = mkdir -p workspace && $(MAKE) -k -f ../xpresso/Makefile PROJECTS=wizard && rmdir workspace
|
||||
endif
|
||||
ifeq "$(IDE)" "Keil"
|
||||
ifeq "$(IDE)" "ModusIDE"
|
||||
BUILD = true
|
||||
endif
|
||||
ifeq "$(IDE)" "e2studio"
|
||||
BUILD = true
|
||||
endif
|
||||
ifeq "$(IDE)" "Pico-SDK"
|
||||
@@ -20,6 +23,9 @@ endif
|
||||
ifeq "$(IDE)" "ESP-IDF"
|
||||
BUILD = $(MAKE) -f ../esp-idf/Makefile PROJECTS=wizard
|
||||
endif
|
||||
ifeq "$(IDE)" "Keil"
|
||||
BUILD = true
|
||||
endif
|
||||
ifeq "$(IDE)" "Arduino"
|
||||
BUILD = true
|
||||
endif
|
||||
@@ -32,6 +38,7 @@ endif
|
||||
|
||||
|
||||
firmware.bin: wizard
|
||||
(test "$(BUILD)" == "true" && echo "NOT TESTING $(BOARD) $(IDE) $(RTOS): don't know how to test $(IDE) projects" >> test.log) || true
|
||||
$(BUILD) && rm -rf wizard*
|
||||
|
||||
wizard: FORCE
|
||||
|
||||
+33
-15
@@ -29,7 +29,7 @@ done
|
||||
dotest h7s3l8 GCC+make baremetal
|
||||
|
||||
|
||||
NXP="mcxn947"
|
||||
NXP="rt1020 rt1024 rt1040 rt1060 rt1064 rt1170 mcxn947"
|
||||
NXPIDES="GCC+make MCUXpresso"
|
||||
for board in $NXP; do
|
||||
for ide in $NXPIDES; do
|
||||
@@ -38,16 +38,9 @@ for board in $NXP; do
|
||||
done
|
||||
done
|
||||
done
|
||||
NXP="rt1020 rt1024 rt1040 rt1060 rt1064 rt1170"
|
||||
NXP="rw612"
|
||||
for board in $NXP; do
|
||||
dotest $board "GCC+make" "baremetal"
|
||||
done
|
||||
|
||||
|
||||
INFINEON="xmc4400 xmc4700 xmc7200"
|
||||
INFINEONIDES="GCC+make"
|
||||
for board in $INFINEON; do
|
||||
for ide in $INFINEONIDES; do
|
||||
for ide in $NXPIDES; do
|
||||
for rtos in "baremetal"; do
|
||||
dotest $board $ide $rtos
|
||||
done
|
||||
@@ -67,10 +60,13 @@ done
|
||||
dotest "tms570" "CGT+make" "baremetal"
|
||||
|
||||
|
||||
PICO="evb-pico evb-pico2 evb-pico2-w5100 pico-w pico2-w"
|
||||
for board in $PICO; do
|
||||
for rtos in "baremetal"; do
|
||||
dotest $board "Pico-SDK" $rtos
|
||||
INFINEON="xmc4400 xmc4700 xmc7200"
|
||||
INFINEONIDES="GCC+make ModusIDE"
|
||||
for board in $INFINEON; do
|
||||
for ide in $INFINEONIDES; do
|
||||
for rtos in "baremetal"; do
|
||||
dotest $board $ide $rtos
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
@@ -80,10 +76,32 @@ for board in $ESP; do
|
||||
dotest $board "ESP-IDF" "baremetal"
|
||||
done
|
||||
|
||||
|
||||
PICO="evb-pico evb-pico2 evb-pico2-w5100 pico-w pico2-w"
|
||||
for board in $PICO; do
|
||||
for rtos in "baremetal"; do
|
||||
dotest $board "Pico-SDK" $rtos
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
#NORDIC
|
||||
|
||||
RENESAS="ra6 ra8m1"
|
||||
RENESASIDES="GCC+make e2studio"
|
||||
for board in $RENESAS; do
|
||||
for ide in $RENESASIDES; do
|
||||
for rtos in "baremetal"; do
|
||||
dotest $board $ide $rtos
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
# f439 not supported
|
||||
# h755 not supported in 3.7.0 branch; master branch currently not building
|
||||
# other ST boards (PHY address != 0) might build and not work
|
||||
ZEPHYR="zephyr zephyr-w5500 f207 f429 f746 f756 f767 h563 h573 h723 h735 h743 h745 h747 h753 mcxn947 rt1060 rt1064 evb-pico"
|
||||
ZEPHYR="zephyr zephyr-w5500 f207 f429 f746 f756 f767 h563 h573 h723 h735 h743 h745 h747 h753 mcxn947 rt1060 rt1064 evb-pico nrf91"
|
||||
for board in $ZEPHYR; do
|
||||
dotest $board "Zephyr" "baremetal"
|
||||
done
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
# NXP command line tool is useless for this task, using Eclipse headless build
|
||||
|
||||
ROOT ?= $(realpath $(CURDIR)/../..)
|
||||
PROJECTS ?= $(wildcard ../../tutorials/nxp/*-xpresso-*)
|
||||
TARGET ?= Debug
|
||||
DOCKER = docker run --rm -v $(ROOT):$(ROOT) -v $(CURDIR):/root -w $(CURDIR)
|
||||
DOCKER = docker run --rm --ulimit nofile=1024:524288 -v $(ROOT):$(ROOT) -v $(CURDIR):/root -w $(CURDIR)
|
||||
IMAGE ?= scaprile/xpresso
|
||||
HEADLESS_BUILD = /usr/local/mcuxpressoide/ide/mcuxpressoide --launcher.suppressErrors -nosplash -application org.eclipse.cdt.managedbuilder.core.headlessbuild
|
||||
|
||||
all: $(PROJECTS)
|
||||
$(DOCKER) $(IMAGE) $(HEADLESS_BUILD) -data workspace -removeAll workspace
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf workspace/.metadata workspace/.mcuxpressoide* workspace/.gitignore mcuxpresso .cache .p2 .eclipse"
|
||||
|
||||
$(PROJECTS): FORCE
|
||||
(make -C $@ && make -C $@ clean) || ( \
|
||||
PROJNAME=`xq -r .projectDescription.name $@/.project` && \
|
||||
($(DOCKER) $(IMAGE) $(HEADLESS_BUILD) -data workspace -import wizard -cleanBuild $$PROJNAME/$(TARGET) || true) && \
|
||||
test -f $(@F)/$(TARGET)/$$PROJNAME.axf )
|
||||
($(DOCKER) $(IMAGE) $(HEADLESS_BUILD) -data workspace -import $@ -cleanBuild $$PROJNAME/$(TARGET) || true) && \
|
||||
test -f $(@F)/$(TARGET)/$$PROJNAME.axf && \
|
||||
$(DOCKER) $(IMAGE) /bin/bash -c "find $@/$(TARGET) -mindepth 1 ! -name '*.ld' -exec rm -rf {} +")
|
||||
|
||||
FORCE:
|
||||
@@ -33,7 +33,7 @@ static void *thread_function(void *param) {
|
||||
struct thread_data *p = (struct thread_data *) param;
|
||||
sleep(2); // Simulate long execution
|
||||
mg_wakeup(p->mgr, p->conn_id, "hi!", 3); // Respond to parent
|
||||
free((void *) p->message.buf); // Free all resources that were
|
||||
mg_free((void *) p->message.buf); // Free all resources that were
|
||||
free(p); // passed to us
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ DELETE = rm -rf # Command to remove files
|
||||
OUT ?= -o $(PROG) # Compiler argument for output file
|
||||
SOURCES = main.c mongoose.c net.c packed_fs.c # Source code files
|
||||
CFLAGS = -W -Wall -Wextra -g -I. # Build options
|
||||
NPX ?= npx
|
||||
|
||||
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
|
||||
CFLAGS_MONGOOSE += -DMG_ENABLE_PACKED_FS=1
|
||||
@@ -27,12 +26,8 @@ $(PROG): $(SOURCES)
|
||||
web_root/bundle.js:
|
||||
curl -s https://npm.reversehttp.com/preact,preact/hooks,htm/preact,preact-router -o $@
|
||||
|
||||
# Create optimised CSS. Prerequisite: npm -g i tailwindcss tailwindcss-font-inter
|
||||
web_root/main.css: web_root/index.html $(wildcard web_root/*.js)
|
||||
$(NPX) tailwindcss -o $@ --minify
|
||||
|
||||
# Generate packed filesystem for serving Web UI
|
||||
packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile web_root/main.css web_root/bundle.js
|
||||
packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile web_root/bundle.js
|
||||
node pack.js $(addsuffix ::gzip, $(wildcard web_root/*)) certs/* > $@
|
||||
|
||||
mbedtls:
|
||||
|
||||
Loaded 100 of 960 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user