make BSD C++ compatible,survive to FreeRTOS not being so

This commit is contained in:
Sergio R. Caprile 2026-08-10 10:16:05 -03:00
parent 282ae0d968
commit f58f29b9a0
6 changed files with 58 additions and 20 deletions

View file

@ -281,10 +281,10 @@ jobs:
make -C test/bsd shm_tap_bridge
test/bsd/shm_tap_bridge &
sleep 2
set -o pipefail; make -C test/bsd CC=${{ matrix.cc }} | tee log
make -C test/bsd CC=${{ matrix.cc }} > log
- if: success() || failure()
run: |
# cat log
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/bsd_${{ matrix.cc }}_$(date +"%Y%m%d").json"

View file

@ -294,7 +294,8 @@ int listen(int fd, int backlog) {
int accept(int fd, struct sockaddr *addr, socklen_t *addrlen) {
struct mg_bsd_sock *ls = get(fd);
if (!ls) return -1;
struct sockaddr_in peer = {0};
struct sockaddr_in peer;
memset(&peer, 0, sizeof(peer));
void *t = mg_bsd_transport_accept(ls->t, &peer, ls->nonblock);
if (!t) return -1; // errno was set by transport_accept()
struct mg_bsd_sock *ns = (struct mg_bsd_sock *) calloc(1, sizeof(*ns));
@ -417,7 +418,8 @@ void freeaddrinfo(struct addrinfo *res) { (void) res; }
#endif
int inet_pton(int af, const char *src, void *dst) {
struct mg_addr a = {0};
struct mg_addr a;
memset(&a, 0, sizeof(a));
if (af == AF_INET && mg_aton(mg_str_s(src), &a)) { memcpy(dst, &a.addr.ip4, 4); return 1; }
return 0;
}
@ -432,7 +434,8 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {
}
in_addr_t inet_addr(const char *cp) {
struct mg_addr a = {0};
struct mg_addr a;
memset(&a, 0, sizeof(a));
return mg_aton(mg_str_s(cp), &a) ? a.addr.ip4 : (in_addr_t) -1;
}

View file

@ -127,7 +127,8 @@ int listen(int fd, int backlog) {
int accept(int fd, struct sockaddr *addr, socklen_t *addrlen) {
struct mg_bsd_sock *ls = get(fd);
if (!ls) return -1;
struct sockaddr_in peer = {0};
struct sockaddr_in peer;
memset(&peer, 0, sizeof(peer));
void *t = mg_bsd_transport_accept(ls->t, &peer, ls->nonblock);
if (!t) return -1; // errno was set by transport_accept()
struct mg_bsd_sock *ns = (struct mg_bsd_sock *) calloc(1, sizeof(*ns));
@ -250,7 +251,8 @@ void freeaddrinfo(struct addrinfo *res) { (void) res; }
#endif
int inet_pton(int af, const char *src, void *dst) {
struct mg_addr a = {0};
struct mg_addr a;
memset(&a, 0, sizeof(a));
if (af == AF_INET && mg_aton(mg_str_s(src), &a)) { memcpy(dst, &a.addr.ip4, 4); return 1; }
return 0;
}
@ -265,7 +267,8 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {
}
in_addr_t inet_addr(const char *cp) {
struct mg_addr a = {0};
struct mg_addr a;
memset(&a, 0, sizeof(a));
return mg_aton(mg_str_s(cp), &a) ? a.addr.ip4 : (in_addr_t) -1;
}

View file

@ -15,15 +15,25 @@ endif
.PHONY: all bsd_test bsd_client shm_tap_bridge shm_port_bridge bsd_s390 clean
SOURCES = bsd_shm_test.c ../../mongoose.c
# FreeRTOS
SOURCES += FreeRTOS-Kernel/portable/MemMang/heap_4.c
SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/port.c
SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c
TEST_SOURCES = bsd_shm_test.c
# A C++ application compiles its sources as C++, linking Mongoose and FreeRTOS as C.
# FreeRTOS does not build as C++, so C sources are compiled separately.
C_SOURCES = ../../mongoose.c
C_SOURCES += FreeRTOS-Kernel/portable/MemMang/heap_4.c
C_SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/port.c
C_SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c
C_SOURCES += $(wildcard FreeRTOS-Kernel/*.c)
C_OBJECTS = $(notdir $(C_SOURCES:.c=.o))
C_INPUTS = $(foreach S,$(C_SOURCES),-x c $(S))
CFLAGS += -IFreeRTOS-Kernel/include
CFLAGS += -IFreeRTOS-Kernel/portable/ThirdParty/GCC/Posix -Wno-conversion -Wno-undef
ifeq "$(findstring ++,$(CC))" ""
TEST_LANGUAGE = c
else
TEST_LANGUAGE = c++
endif
DOCKER_BIN ?= docker
CWD ?= $(realpath $(CURDIR))
ROOT_DIR = $(realpath $(CWD)/../..)
@ -38,8 +48,10 @@ all bsd: shm_tap_bridge bsd_client FreeRTOS-Kernel bsd_test
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./bsd_test $(ARGS)
# requires shm_tap_bridge to be running
bsd_test: $(SOURCES) bsd_x_test.c ../../mongoose.h shm_queue.h
$(CC) $(SOURCES) $(wildcard FreeRTOS-Kernel/*.c) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@
bsd_test: FreeRTOS-Kernel
$(CC) $(C_INPUTS) -c $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA)
$(CC) -x $(TEST_LANGUAGE) -c $(TEST_SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA)
$(CC) $(C_OBJECTS) $(TEST_SOURCES:.c=.o) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@
bsd_client: bsd_client.c
$(CC) bsd_client.c -pthread -o $@

View file

@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#define PORT 1234
@ -46,6 +47,7 @@ static void *worker(void *arg) {
const char *host = (const char *) arg;
char tx[DATA_SIZE], rx[DATA_SIZE];
struct sockaddr_in sa;
struct timeval timeout;
unsigned port = 0;
int fd;
@ -54,6 +56,11 @@ static void *worker(void *arg) {
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) goto fail;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != 0 ||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0)
goto fail_close;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;

View file

@ -42,7 +42,10 @@ static void client_task(void *args) {
struct client_data *d = (struct client_data *) args;
char req[256];
fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa = {.sin_family = AF_INET, .sin_port = htons(80)};
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(80);
memcpy(&sa.sin_addr, &d->ip, 4);
c = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
ASSERT(c >= 0);
@ -73,6 +76,7 @@ static void echo_task(void *args) {
char buf[512];
size_t i = 0;
ssize_t n;
MG_INFO(("Echo task started: %d", fd));
while ((n = recv(fd, buf, sizes[i++ % (sizeof(sizes) / sizeof(sizes[0]))], 0)) > 0)
send(fd, buf, (size_t) n, 0);
close(fd);
@ -82,9 +86,14 @@ static void echo_task(void *args) {
// accept loop. Waits for incoming connections on port 1234 and spawns
// an echo_task for each one, allowing concurrent clients.
static void atask(void *args) {
BaseType_t result;
mg_bsd_init();
int lfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa = {.sin_family = AF_INET, .sin_port = htons(1234), .sin_addr = {INADDR_ANY}};
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(1234);
sa.sin_addr.s_addr = INADDR_ANY;
bind(lfd, (struct sockaddr *) &sa, sizeof(sa));
listen(lfd, 5);
fcntl(lfd, F_SETFL, O_NONBLOCK);
@ -93,7 +102,10 @@ static void atask(void *args) {
int fd = accept(lfd, NULL, NULL);
if (fd < 0) { vTaskDelay(pdMS_TO_TICKS(10)); continue; }
// echo_task at higher priority than task1
xTaskCreate(echo_task, "echo", 512, (void *) (uintptr_t) fd, configMAX_PRIORITIES - 1, NULL);
result = xTaskCreate(echo_task, "echo", 512, (void *) (uintptr_t) fd,
configMAX_PRIORITIES - 1, NULL);
MG_INFO(("Echo task %d: %s", fd, result == pdPASS ? "created" : "FAILED"));
ASSERT(result == pdPASS);
}
close(lfd);
s_wait = false;
@ -118,7 +130,7 @@ static void task2(void *args) {
// atask at higher priority than task1
xTaskCreate(atask, "atask", 256, NULL, configMAX_PRIORITIES - 1, NULL);
ip = mg_mprintf("%M", mg_print_ip4, &mgr->ifp->ip);
cmd[0] = "./bsd_client";
cmd[0] = (char *) "./bsd_client";
cmd[1] = ip;
cmd[2] = NULL;
ASSERT(posix_spawn(&pid, cmd[0], NULL, NULL, cmd, environ) == 0);
@ -217,6 +229,7 @@ static void task1(void *args) {
while (!s_done) {
mg_mgr_poll(mgr, 0);
mg_bsd_poll(mgr);
vTaskDelay(1); // Let idle reclaim deleted echo tasks
}
s_done = false;
vTaskDelete(NULL);