Compare commits

...
13 Commits
Author SHA1 Message Date
Sergio R. Caprile 053b8ed824 Merge pull request #3777 from cesanta/nocnfb
Correct #3775 CN fallback handling
2026-11-13 11:42:42 -03:00
Sergio R. Caprile 2ea1cf6817 Correct #3775 CN fallback handling 2026-11-13 11:42:13 -03:00
Sergio R. Caprile 323326ce8b Merge pull request #3778 from cesanta/pad
make padding stricter
2026-11-13 11:41:14 -03:00
Sergio R. Caprile c5344af9fc make padding stricter 2026-11-13 11:04:01 -03:00
Sergio R. Caprile d73b009bbc unbreak test 2026-11-13 09:53:19 -03:00
cpq dba6479b23 Update Agents 2026-11-13 12:23:35 +00:00
cpq 28ca01eb2b Update Agents 2026-11-13 12:10:05 +00:00
cpq e999239ca7 Add guidance for the AI engines inside mongoose.h 2026-11-13 11:57:04 +00:00
Sergio R. Caprile d545526ba2 unbreak test 2026-11-12 15:56:25 -03:00
Sergio R. Caprile 0b888e8f3f Merge pull request #3776 from cesanta/embnul
reject embedded NULs in paths
2026-11-12 15:42:18 -03:00
Sergio R. Caprile 27a87dee8b reject embedded NULs in paths 2026-11-12 14:24:46 -03:00
Sergio R. Caprile 94ccc4a130 Merge pull request #3775 from cesanta/nocnfb
do not fallback to CN after SAN
2026-11-12 13:59:16 -03:00
Sergio R. Caprile 454bf4036f do not fallback to CN after SAN 2026-11-12 13:53:51 -03:00
11 changed files with 178 additions and 59 deletions

No files matched your search

+98 -26
View File
@@ -13,6 +13,7 @@ GitHub repo: https://github.com/cesanta/mongoose
## General rules
- All relative file names mentioned in this file are related to the repo root.
- Always re-read files before editing, so you do not overwrite existing changes.
- Never guess. If you don't know, say you don't know and stop.
- Resolve relative paths from the repo root: https://github.com/cesanta/mongoose
@@ -39,6 +40,7 @@ This is a navigation aid, not an API reference. Read `mongoose.h` for exact
function signatures, structs, options, examples, and constraints.
- `mg_mgr_*` - event manager and polling loop
- `mg_dash_*` - dashboard API for device web UIs, fieldsets, and live updates
- `mg_http_*` - HTTP server, HTTP client, uploads, serving files
- `mg_ws_*` - WebSocket server and client
- `mg_mqtt_*` - MQTT client
@@ -229,12 +231,41 @@ xTaskCreate(net_task, "net", 8192, NULL, tskIDLE_PRIORITY + 1, NULL);
## HTTP / Web Device Dashboard
For a web UI with real-time device state over WebSocket, use the Mongoose
device dashboard.
When building a device web UI, control panel, monitoring page, or live
display, you MUST use the `mg_dash_*` dashboard framework unless the user
explicitly requests another architecture. Do not add your own HTTP event handler.
Read the dashboard declarations in `mongoose.h` before implementing the UI.
Use only the dashboard files listed below. Download missing reference files;
preserve existing files. Integrate the dashboard into the existing application
and build files.
Start from the minimal reference implementation and adapt its fields and UI.
Keep dashboard fieldsets, callbacks, update timers, and small metric helpers
in `dashboard.c`. Do not create `dashboard.h`, or other dashboard
helper modules. `mongoose.h` already declares `mg_dash_init()` and
`mg_dash_poll()`. Reuse existing board/HAL helpers for hardware measurements;
if none exists, put a small private helper in `dashboard.c` or extend the
existing board/HAL implementation.
Expose device state through mg_field / mg_field_set.
Call mg_dash_init() once and mg_dash_poll() in the event loop.
For live updates, call mg_dash_send_change() from a backend timer.
Display values using dashboard.js and HTML data-bind attributes.
Example: free RAM updated every 50 ms means a read-only fieldset pushed
over the dashboard WebSocket every 50 ms. Do not implement browser polling,
fetch(), setInterval(), or a custom WebSocket client for dashboard state.
### Required files
The following files must exist at these exact paths, regardless of the build environment:
Keep all the following Mongoose files together in one project directory.
The example uses `mongoose/`; you may choose another directory name.
If Mongoose is already installed, use the directory containing the actual
`mongoose.c` and `mongoose.h` files, including an existing CubeMX middleware
directory. Add the dashboard files there and update the build paths. Do not
create a second Mongoose directory or use symlinks, forwarding headers, or
duplicate library copies to make files appear colocated.
```
your_project/
@@ -244,6 +275,7 @@ your_project/
├── mongoose.c # single source file
├── dashboard.c # C-side dashboard logic
├── dashboard.html # HTML/JS UI (source)
├── html2c.js # HTML-to-C generator
└── file_data.c # generated from dashboard.html (see below)
```
@@ -255,16 +287,24 @@ node html2c.js dashboard.html -o file_data.c
`html2c.js` is at https://github.com/cesanta/mongoose/blob/master/resources/html2c.js
If the project does not yet have `dashboard.c` and `dashboard.html`, fetch the
minimal reference versions:
For each missing `dashboard.c`, `dashboard.html`, or `html2c.js`, download its
reference version from the Mongoose repository and place it beside `mongoose.c`
and `mongoose.h`:
```
https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/dashboard.c
https://github.com/cesanta/mongoose/blob/master/tutorials/device-dashboard/minimal/dashboard.html
https://github.com/cesanta/mongoose/blob/master/resources/html2c.js
```
If the project already has `dashboard.c` and `dashboard.html`, do **not** fetch
anything from the repository.
Add a build rule that regenerates `file_data.c` whenever `dashboard.html` or
`html2c.js` changes. Keep the upstream generator unchanged; it already inlines
the script referenced by the HTML, so the served page does not need internet
access. Do not download a separate `dashboard.js` or add a local `--use`
override unless the user explicitly requests offline builds or local assets.
Compile both `dashboard.c` and `file_data.c` into the
application. Call `mg_dash_init()` once and `mg_dash_poll()` on every iteration
of the existing Mongoose event loop, from the same task or thread.
### C integration (bare metal or RTOS main loop)
@@ -283,15 +323,17 @@ for (;;) {
### dashboard.html rules
- Use `dashboard.js` from `https://mongoose.ws/resources/dashboard.js`
- Reference `<script src="https://mongoose.ws/resources/dashboard.js"></script>`
in the source HTML. Let `html2c.js` inline it into the generated asset.
- Call `Dashboard.init({ data: { ... } })` once - this is the only direct
Dashboard API call. Treat the rest of Dashboard as a black box.
- Do **not** add vanilla JS event listeners, `fetch()` calls, or custom
reactive logic to `dashboard.html`.
- Do **not** modify `dashboard.html` unless the user explicitly asks.
- Modify `dashboard.html` only for requested UI work. A request to create or
modify the web UI authorizes the necessary `dashboard.html` edits.
- Bind controls to device state using `data-bind` attributes
- The `__status` object in evaluations is read-only, do not alter it
- If you need to pass data between the UI and backend.c, add extra
- If you need to pass data between the UI and `dashboard.c`, add extra
fieldsets/fields - see next section about it
- If you want to display device data in HTML, use `${}` evaluations
@@ -315,17 +357,24 @@ for (;;) {
### dashboard.c rules
Mongoose backend exports device data as a collection of "fieldsets". Each fieldset groups several fields
Mongoose exports device data as fieldsets. Each fieldset groups several fields
and has one `bool fn(enum mg_dash_op, struct mg_dash_user *)` callback for
read/write/add/delete operations. Use the declarations in the project's
`mongoose.h`; do not copy older descriptors with separate reader/writer
members or positional access-level arguments. Use designated initializers.
Example fieldset:
```c
static struct mg_dash s_dash;
static bool settings_fn(enum mg_dash_op op, struct mg_dash_user *u);
static struct settings {
double volume;
char name[10];
int log_level;
bool enable_login;
} s_settings = {2.7, "Dublin", 2, false, false};
} s_settings = {2.7, "Dublin", 2, false};
static struct mg_field fields_settings[] = {
{"volume", MG_VAL_DBL, &s_settings.volume, sizeof(s_settings.volume)},
@@ -336,14 +385,12 @@ static struct mg_field fields_settings[] = {
};
static struct mg_field_set set_settings = {
"settings", fields_settings, read_settings, write_settings, 3, 7, NULL,
.name = "settings", .fields = fields_settings, .fn = settings_fn,
};
```
To enable user authentication, set `authenticate` function for the dashboard descriptor:
```c
static struct mg_dash s_dash;
// Signature: (char *user, size_t userlen, const char *pass)
// `user` is both input (username from the login form) and output: the function
// may overwrite it with the canonical username. Return access level > 0 on
@@ -360,24 +407,34 @@ static int authenticate(char *user, size_t userlen, const char *pass) {
return level;
}
static void write_settings(void) {
s_dash.authenticate = s_settings.enable_login ? authenticate : NULL;
static bool settings_fn(enum mg_dash_op op, struct mg_dash_user *u) {
(void) u;
if (op == MG_DASH_WRITE) {
s_dash.authenticate = s_settings.enable_login ? authenticate : NULL;
return true;
}
return op == MG_DASH_READ;
}
```
Fieldset may have reader and writer function, which acts as a hardware glue. For example, "led1" variable may reflect real LED status using reader and writer:
Use the fieldset callback as hardware glue. For example, `led1` can reflect
the real LED state:
```c
static struct leds {
bool led1;
} s_leds = {false};
static void write_leds(void) {
gpio_write(LED1_PIN, s_leds.led1);
}
static void read_leds(void) {
s_leds.led1 = gpio_read(LED1_PIN);
static bool leds_fn(enum mg_dash_op op, struct mg_dash_user *u) {
(void) u;
if (op == MG_DASH_READ) {
s_leds.led1 = gpio_read(LED1_PIN);
} else if (op == MG_DASH_WRITE) {
gpio_write(LED1_PIN, s_leds.led1);
} else {
return false;
}
return true;
}
static struct mg_field fields_leds[] = {
@@ -386,7 +443,7 @@ static struct mg_field fields_leds[] = {
};
static struct mg_field_set set_leds = {
"leds", fields_leds, read_leds, write_leds, 0, 0, NULL,
.name = "leds", .fields = fields_leds, .fn = leds_fn,
};
```
@@ -412,7 +469,8 @@ static struct event {
} s_event;
static struct mg_field_set field_set_event = {
"event", fields_event, event_fn, &s_event.index, 0, 0, 0
.name = "event", .fields = fields_event,
.fn = event_fn, .index = &s_event.index,
};
```
@@ -432,6 +490,20 @@ Do not rename, wrap, relocate, or replace these files or functions. Do not intro
Board-specific STM32Cube files may exist outside mongoose/, but the Mongoose dashboard files must retain the structure and API documented above.
### Dashboard completion checks
- Verify actual file locations, including symlink targets, against the required
layout. Check that no extra dashboard source/header/JS files were introduced.
- Check the source HTML for the upstream script reference, a single
`Dashboard.init()`, and declarative bindings. Networking code in the upstream
script inlined into `file_data.c` is expected; do not replace or edit it.
- Verify fieldsets are registered with `MG_DASH_ADD_FIELD_SET()`, listeners use
`mg_dash_ev_handler`, and live metrics use `mg_dash_send_change()` on the
requested backend schedule. Do not resend unrelated fieldsets at that rate.
- Regenerate `file_data.c` and build the real firmware. Report separately which
behavior was verified on hardware; host mocks do not establish physical LED,
Ethernet, RAM measurement, or refresh-rate correctness.
## Filesystem
| Define | Use when |
+26 -15
View File
@@ -4906,11 +4906,15 @@ static bool uri2path(const char *r, struct mg_str uri, char *buf, size_t len) {
n = mg_snprintf(buf, len, "%.*s", (int) d.len, d.buf);
if (len == 0 || n + 2 >= len) return false; // Path overflow
if (n > 0 && buf[n - 1] != '/') buf[n++] = '/', buf[n] = '\0'; // Add slash
if (mg_url_decode(uri.buf + u.len, uri.len - u.len, buf + n, len - n, 0) < 0) {
return false;
{
int dn;
size_t p = n;
dn = mg_url_decode(uri.buf + u.len, uri.len - u.len, buf + n, len - n, 0);
if (dn < 0) return false; // reject on malformed
buf[len - 1] = '\0'; // Double-check
n = strlen(buf);
if (n != p + (size_t) dn) return false; // reject on embedded NULs
}
buf[len - 1] = '\0'; // Double-check
n = strlen(buf);
if (!mg_path_is_sane(mg_str_n(buf, n))) return false;
while (n > 1 && buf[n - 1] == '/') buf[--n] = 0; // Trim trailing slashes
return true;
@@ -19589,11 +19593,11 @@ static bool mg_tls_send_cert_verify(struct mg_connection *c, bool is_client) {
verify[10] = 0x02; // ASN.1 INTEGER
verify[11] = (uint8_t) (32 + adj1);
memmove(verify + (size_t) (12 + (adj1 > 0)), sig + (size_t) (adj1 < 0),
(size_t) (32 + (adj1 < 0)));
(size_t) (32 - (adj1 < 0)));
verify[12 + 32 + adj1] = 0x02; // ASN.1 INTEGER
verify[13 + 32 + adj1] = (uint8_t) (32 + adj2);
memmove(verify + (size_t) (14 + 32 + adj1 + (adj2 > 0)),
sig + (size_t) (32 + (adj2 < 0)), (size_t) (32 + (adj2 < 0)));
sig + (size_t) (32 + (adj2 < 0)), (size_t) (32 - (adj2 < 0)));
sigsz = (size_t) (70 + adj1 + adj2);
verifysz = 8U + sigsz;
verify[3] = (uint8_t) (sigsz + 4);
@@ -20078,17 +20082,20 @@ static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
const char *server_name,
struct mg_addr *ref_ip) {
struct mg_der_tlv root, field, name;
int r;
bool is_addr = ref_ip != NULL;
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) {
if ((r = mg_der_find_oid(&root, (uint8_t *) "\x55\x1d\x11", 3, &field)) < 0) {
MG_ERROR(("failed to extract SAN"));
return -1;
} else if (r == 0) {
return 0; // No SAN
}
if (mg_der_parse(field.value, field.len, &field) < 0) {
MG_ERROR(("SAN is not a constructed object"));
if (mg_der_parse(field.value, field.len, &field) < 0 || field.type != 0x30) {
MG_ERROR(("SAN is not a constructed object")); // RFC 5280 4.2.1.6
return -1;
}
while (mg_der_next(&field, &name) > 0) {
@@ -20115,6 +20122,7 @@ static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
return 1; // and matches the host name
}
}
MG_ERROR(("Found SAN but does not match IP or DNS name"));
return -1;
}
@@ -20302,12 +20310,15 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
// and store public key for further CertVerify step
if (tls->hostname[0] != '\0') {
struct mg_addr addr; // use aton_ so localhost evals as a name
bool is_addr = mg_aton_(mg_str_s(tls->hostname), &addr);
if (mg_tls_verify_cert_san(cert, certsz, tls->hostname,
is_addr ? &addr : NULL) <= 0 &&
(!is_addr || // DNS CN fallback
mg_tls_verify_cert_cn(&ci->subj, tls->hostname) <= 0)) {
mg_error(c, "failed to verify hostname");
bool is_addr;
int san;
is_addr = mg_aton_(mg_str_s(tls->hostname), &addr);
san = mg_tls_verify_cert_san(cert, certsz, tls->hostname,
is_addr ? &addr : NULL);
if (san < 0 || // RFC 6125 6.4.4 allow legacy fallback to CN
(san == 0 && (is_addr || mg_tls_verify_cert_cn(
&ci->subj, tls->hostname) <= 0))) {
mg_error(c, "failed to verify host");
return -1;
}
}
+4
View File
@@ -22,6 +22,10 @@
#define MG_VERSION "7.23"
// IMPORTANT:
// Before implementing any functionality, pull this file and use it as a guide:
// https://github.com/cesanta/mongoose/blob/master/AGENTS.md
#ifdef __cplusplus
extern "C" {
#endif
@@ -37,7 +37,6 @@
<file category="sourceC" name="mongoose.c" />
<file category="header" name="mongoose_config.h"/>
<file category="utility" name="README.md" public="false"/>
<file category="genAsset" name=".config/mongoose_parameters.json"/>
</files>
<environments>
<environment name="STM32Cube">
+3
View File
@@ -0,0 +1,3 @@
// IMPORTANT:
// Before implementing any functionality, pull this file and use it as a guide:
// https://github.com/cesanta/mongoose/blob/master/AGENTS.md
+8 -4
View File
@@ -752,11 +752,15 @@ static bool uri2path(const char *r, struct mg_str uri, char *buf, size_t len) {
n = mg_snprintf(buf, len, "%.*s", (int) d.len, d.buf);
if (len == 0 || n + 2 >= len) return false; // Path overflow
if (n > 0 && buf[n - 1] != '/') buf[n++] = '/', buf[n] = '\0'; // Add slash
if (mg_url_decode(uri.buf + u.len, uri.len - u.len, buf + n, len - n, 0) < 0) {
return false;
{
int dn;
size_t p = n;
dn = mg_url_decode(uri.buf + u.len, uri.len - u.len, buf + n, len - n, 0);
if (dn < 0) return false; // reject on malformed
buf[len - 1] = '\0'; // Double-check
n = strlen(buf);
if (n != p + (size_t) dn) return false; // reject on embedded NULs
}
buf[len - 1] = '\0'; // Double-check
n = strlen(buf);
if (!mg_path_is_sane(mg_str_n(buf, n))) return false;
while (n > 1 && buf[n - 1] == '/') buf[--n] = 0; // Trim trailing slashes
return true;
+18 -11
View File
@@ -1188,11 +1188,11 @@ static bool mg_tls_send_cert_verify(struct mg_connection *c, bool is_client) {
verify[10] = 0x02; // ASN.1 INTEGER
verify[11] = (uint8_t) (32 + adj1);
memmove(verify + (size_t) (12 + (adj1 > 0)), sig + (size_t) (adj1 < 0),
(size_t) (32 + (adj1 < 0)));
(size_t) (32 - (adj1 < 0)));
verify[12 + 32 + adj1] = 0x02; // ASN.1 INTEGER
verify[13 + 32 + adj1] = (uint8_t) (32 + adj2);
memmove(verify + (size_t) (14 + 32 + adj1 + (adj2 > 0)),
sig + (size_t) (32 + (adj2 < 0)), (size_t) (32 + (adj2 < 0)));
sig + (size_t) (32 + (adj2 < 0)), (size_t) (32 - (adj2 < 0)));
sigsz = (size_t) (70 + adj1 + adj2);
verifysz = 8U + sigsz;
verify[3] = (uint8_t) (sigsz + 4);
@@ -1677,17 +1677,20 @@ static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
const char *server_name,
struct mg_addr *ref_ip) {
struct mg_der_tlv root, field, name;
int r;
bool is_addr = ref_ip != NULL;
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) {
if ((r = mg_der_find_oid(&root, (uint8_t *) "\x55\x1d\x11", 3, &field)) < 0) {
MG_ERROR(("failed to extract SAN"));
return -1;
} else if (r == 0) {
return 0; // No SAN
}
if (mg_der_parse(field.value, field.len, &field) < 0) {
MG_ERROR(("SAN is not a constructed object"));
if (mg_der_parse(field.value, field.len, &field) < 0 || field.type != 0x30) {
MG_ERROR(("SAN is not a constructed object")); // RFC 5280 4.2.1.6
return -1;
}
while (mg_der_next(&field, &name) > 0) {
@@ -1714,6 +1717,7 @@ static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
return 1; // and matches the host name
}
}
MG_ERROR(("Found SAN but does not match IP or DNS name"));
return -1;
}
@@ -1901,12 +1905,15 @@ static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
// and store public key for further CertVerify step
if (tls->hostname[0] != '\0') {
struct mg_addr addr; // use aton_ so localhost evals as a name
bool is_addr = mg_aton_(mg_str_s(tls->hostname), &addr);
if (mg_tls_verify_cert_san(cert, certsz, tls->hostname,
is_addr ? &addr : NULL) <= 0 &&
(!is_addr || // DNS CN fallback
mg_tls_verify_cert_cn(&ci->subj, tls->hostname) <= 0)) {
mg_error(c, "failed to verify hostname");
bool is_addr;
int san;
is_addr = mg_aton_(mg_str_s(tls->hostname), &addr);
san = mg_tls_verify_cert_san(cert, certsz, tls->hostname,
is_addr ? &addr : NULL);
if (san < 0 || // RFC 6125 6.4.4 allow legacy fallback to CN
(san == 0 && (is_addr || mg_tls_verify_cert_cn(
&ci->subj, tls->hostname) <= 0))) {
mg_error(c, "failed to verify host");
return -1;
}
}
+1 -1
View File
@@ -98,7 +98,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 .. && (export LC_ALL=C ; 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/os_*.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/lfs.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_aes128.h src/tls_p256.h src/tls_p384.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/modbus.h src/json.h src/jwt.h src/rpc.h src/dash.h src/ota.h src/health.h src/mdash.h src/flash.h src/wifi.h src/l2.h src/net_builtin.h src/l2_mesh.h src/bsd.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 .. && (export LC_ALL=C ; cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; cat src/ai.h; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/os_*.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/lfs.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_aes128.h src/tls_p256.h src/tls_p384.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/modbus.h src/json.h src/jwt.h src/rpc.h src/dash.h src/ota.h src/health.h src/mdash.h src/flash.h src/wifi.h src/l2.h src/net_builtin.h src/l2_mesh.h src/bsd.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
# Check that all external (exported) symbols have "mg_" prefix
mg_prefix: mongoose.c mongoose.h
+1
View File
@@ -1519,6 +1519,7 @@ static void test_http_404(void) {
ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\n\n") == 200);
ASSERT(cmpbody(buf, "hello\n") == 0);
ASSERT(fetch(&mgr, buf, url, "GET /a.txt%%00x HTTP/1.0\n\n") == 400);
ASSERT(fetch(&mgr, buf, url, "GET /a/a.txt HTTP/1.0\n\n") == 200);
ASSERT(cmpbody(buf, "hello\n") == 0);
ASSERT(fetch(&mgr, buf, url, "GET /unmapped HTTP/1.0\n\n") == 400);
+1 -1
View File
@@ -4,7 +4,7 @@ ROOTDIR = $(realpath $(CURDIR)/../../..)
PORT ?= /dev/ttyUSB0
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) espressif/idf:v5.0.4
# Note that the esp32 port needs the extra .. for relative paths due to the location of its main CMakeLists.txt file
CMD ?= bash -c '$(MAKE) -C micropython/ports/esp32 submodules && $(MAKE) -C micropython/ports/esp32 USER_C_MODULES=../../../../../mongoose/micropython.cmake'
CMD ?= bash -c '$(MAKE) -C micropython/ports/esp32 submodules && $(MAKE) -C micropython/ports/esp32 USER_C_MODULES=../../../../mongoose/micropython.cmake'
all: example
@@ -0,0 +1,18 @@
# Create an INTERFACE library for our C module.
add_library(usermod_mongoose INTERFACE)
# Add our source files to the lib
target_sources(usermod_mongoose INTERFACE
${CMAKE_CURRENT_LIST_DIR}/../../mongoose/module.c
${CMAKE_CURRENT_LIST_DIR}/../../../../mongoose.c
${CMAKE_CURRENT_LIST_DIR}/main.c
)
# Add the current directory as an include directory.
target_include_directories(usermod_mongoose INTERFACE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/../../../../
)
# Link our INTERFACE library to the usermod target.
target_link_libraries(usermod INTERFACE usermod_mongoose)