From 3a0fe5288cd8f50fdef7b1928901baef706d5e1b Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Tue, 10 Jun 2025 10:51:21 +0100 Subject: [PATCH] Add MG_ARCH_TREADX --- mongoose.c | 33 ++++++++++--------- mongoose.h | 75 +++++++++++++++++++++++++++----------------- src/arch.h | 5 +-- src/arch_azurertos.h | 27 ---------------- src/arch_threadx.h | 43 +++++++++++++++++++++++++ src/http.c | 8 ++--- src/net.c | 2 +- src/net_builtin.h | 1 + src/sock.c | 21 ++++++++----- src/util.c | 2 +- test/pack.c | 4 +-- test/pack.js | 4 +-- 12 files changed, 133 insertions(+), 92 deletions(-) delete mode 100644 src/arch_azurertos.h create mode 100644 src/arch_threadx.h diff --git a/mongoose.c b/mongoose.c index e6952fec..f0bd66ea 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2028,13 +2028,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); @@ -2125,7 +2123,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) { @@ -2416,7 +2414,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); @@ -4064,7 +4062,7 @@ struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, 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); c = NULL; @@ -8779,8 +8777,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)); @@ -8987,7 +8987,7 @@ static void connect_conn(struct mg_connection *c) { } 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 @@ -9059,8 +9059,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) @@ -9221,11 +9221,11 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { if (c->is_closing) tvp = &tv_zero; } - 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); @@ -9234,7 +9234,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); @@ -19850,7 +19855,7 @@ 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_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(); diff --git a/mongoose.h b/mongoose.h index 80db5e6b..6bb83927 100644 --- a/mongoose.h +++ b/mongoose.h @@ -33,7 +33,7 @@ extern "C" { #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_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX) @@ -57,7 +57,7 @@ extern "C" { #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 @@ -77,6 +77,7 @@ extern "C" { + #if MG_ARCH == MG_ARCH_ARMCGT #include @@ -96,33 +97,6 @@ extern "C" { #endif -#if MG_ARCH == MG_ARCH_AZURERTOS - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#define PATH_MAX FX_MAXIMUM_PATH -#define MG_DIRSEP '\\' - -#define socklen_t int -#define closesocket(x) soc_close(x) - -#undef FOPEN_MAX - -#endif - - #if MG_ARCH == MG_ARCH_ESP32 #include @@ -347,6 +321,49 @@ static inline int mg_mkdir(const char *path, mode_t mode) { #endif +#if MG_ARCH == MG_ARCH_THREADX + +#include +#include +#include +#include + +// Do not include time.h and stdlib.h, since they conflict with nxd_bsd.h +// extern time_t time(time_t *); +#include + +#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 + + #if MG_ARCH == MG_ARCH_TIRTOS #include diff --git a/src/arch.h b/src/arch.h index 84188792..58375649 100644 --- a/src/arch.h +++ b/src/arch.h @@ -6,7 +6,7 @@ #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_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX) @@ -30,7 +30,7 @@ #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 @@ -44,6 +44,7 @@ #include "arch_unix.h" #include "arch_win32.h" #include "arch_zephyr.h" +#include "arch_threadx.h" #include "net_ft.h" #include "net_lwip.h" diff --git a/src/arch_azurertos.h b/src/arch_azurertos.h deleted file mode 100644 index 6e0e294b..00000000 --- a/src/arch_azurertos.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#if MG_ARCH == MG_ARCH_AZURERTOS - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#define PATH_MAX FX_MAXIMUM_PATH -#define MG_DIRSEP '\\' - -#define socklen_t int -#define closesocket(x) soc_close(x) - -#undef FOPEN_MAX - -#endif diff --git a/src/arch_threadx.h b/src/arch_threadx.h new file mode 100644 index 00000000..dcec4b52 --- /dev/null +++ b/src/arch_threadx.h @@ -0,0 +1,43 @@ +#pragma once + +#if MG_ARCH == MG_ARCH_THREADX + +#include +#include +#include +#include + +// Do not include time.h and stdlib.h, since they conflict with nxd_bsd.h +// extern time_t time(time_t *); +#include + +#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 diff --git a/src/http.c b/src/http.c index 2cae9909..6f1b1604 100644 --- a/src/http.c +++ b/src/http.c @@ -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); diff --git a/src/net.c b/src/net.c index ce39134d..2510b49a 100644 --- a/src/net.c +++ b/src/net.c @@ -184,7 +184,7 @@ struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, 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); c = NULL; diff --git a/src/net_builtin.h b/src/net_builtin.h index 6520e133..c14d02d8 100644 --- a/src/net_builtin.h +++ b/src/net_builtin.h @@ -103,4 +103,5 @@ struct mg_tcpip_spi { uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply }; + #endif diff --git a/src/sock.c b/src/sock.c index e29e4d5e..e33ac09b 100644 --- a/src/sock.c +++ b/src/sock.c @@ -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)); @@ -368,7 +370,7 @@ static void connect_conn(struct mg_connection *c) { } 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 @@ -440,8 +442,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) @@ -602,11 +604,11 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { if (c->is_closing) tvp = &tv_zero; } - 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); @@ -615,7 +617,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); diff --git a/src/util.c b/src/util.c index d25278f1..538036d6 100644 --- a/src/util.c +++ b/src/util.c @@ -147,7 +147,7 @@ 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_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(); diff --git a/test/pack.c b/test/pack.c index 3c3c4d6a..6fd6f6de 100644 --- a/test/pack.c +++ b/test/pack.c @@ -47,9 +47,7 @@ int main(int argc, char *argv[]) { int i, j, ch; const char *strip_prefix = ""; - printf("%s", "#include \n"); - printf("%s", "#include \n"); - printf("%s", "#include \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"); diff --git a/test/pack.js b/test/pack.js index e7e57b4f..c14a403e 100644 --- a/test/pack.js +++ b/test/pack.js @@ -2,9 +2,7 @@ const Pack = async function(files) { let out = `// DO NOT EDIT. This file is generated -#include -#include -#include +#include "mongoose.h" #if defined(__cplusplus) extern "C" {