feat: HTTP-Server auf Port 3333 mit App-API-Kontext

This commit is contained in:
Michael Sauer
2026-09-11 22:59:34 +02:00
parent 4c2f9e5374
commit 15f709594b
6 changed files with 261 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
#include <string.h>
#include "wm_include.h"
#include "wm_sockets.h"
#include "net/nl_http.h"
#include "net/nl_http_server.h"
#include "sys/nl_app.h"
#define NL_HTTP_PRIO 42
static u32 s_stack[1536]; /* 6 KB: cJSON + API handler */
static char s_buf[NL_HTTP_MAX_REQUEST];
static char s_out[NL_API_BODY_MAX + 160];
static nl_api_response_t s_resp;
static const nl_api_ctx_t *s_ctx;
static void send_all(int fd, const char *p, size_t n)
{
while (n) {
int w = send(fd, p, n, 0);
if (w <= 0)
return;
p += w;
n -= (size_t)w;
}
}
static void simple_error(int status, const char *msg)
{
s_resp.status = status;
s_resp.after = NL_API_AFTER_NONE;
strcpy(s_resp.body, msg);
}
static void serve(int fd)
{
struct timeval tv;
nl_http_request_t req;
nl_http_parse_t pr = NL_HTTP_INCOMPLETE;
size_t len = 0, out;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
while (pr == NL_HTTP_INCOMPLETE && len < sizeof s_buf) {
int n = recv(fd, s_buf + len, sizeof s_buf - len, 0);
if (n <= 0)
return; /* timeout or closed: drop silently */
len += (size_t)n;
pr = nl_http_parse(s_buf, len, &req);
}
if (pr == NL_HTTP_COMPLETE)
nl_api_handle(s_ctx, &req, &s_resp);
else if (pr == NL_HTTP_BAD_REQUEST)
simple_error(400, "{\"error\":\"bad request\"}");
else
simple_error(413, "{\"error\":\"request too large\"}");
out = nl_http_response(s_out, sizeof s_out, s_resp.status, s_resp.body);
if (out)
send_all(fd, s_out, out);
}
static void server_task(void *arg)
{
(void)arg;
for (;;) {
struct sockaddr_in addr;
int ls = socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(NL_HTTP_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (ls < 0 || bind(ls, (struct sockaddr *)&addr, sizeof addr) != 0 || listen(ls, 4) != 0) {
if (ls >= 0)
closesocket(ls);
tls_os_time_delay(HZ);
continue;
}
for (;;) {
struct sockaddr_in peer;
socklen_t plen = sizeof peer;
int fd = accept(ls, (struct sockaddr *)&peer, &plen);
if (fd < 0) {
tls_os_time_delay(HZ / 10);
continue;
}
s_resp.after = NL_API_AFTER_NONE;
serve(fd);
closesocket(fd);
if (s_resp.after == NL_API_AFTER_REBOOT) {
tls_os_time_delay(HZ / 2); /* let the TCP stack flush the response */
nl_app_reboot();
}
}
}
}
void nl_http_server_start(const nl_api_ctx_t *ctx)
{
s_ctx = ctx;
tls_os_task_create(NULL, "nl_http", server_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_HTTP_PRIO, 0);
}