Files
aes67-ESP32-P4/components/aes67_web/aes67_web.c
T
bsncubed 2dd8f60cd6 Web: keep httpd warnings out of the log
httpd_txrx warned on every client reset (errno 104) and httpd_uri on
every 404 (the UI polls /api/player every 2 s until step 7), flooding
syslog. Both set to error level; our handlers log the 4xx that matter.
Remaining known line: 'httpd_resp_send_err: error calling setsockopt :
22' (error level) when a client closes right after a 4xx; a harmless
race in IDF's CONFIG_HTTPD_ERR_RESP_NO_DELAY handling, the response is
already delivered.
Verified via syslog: 10 status + 10 /api/player requests, no httpd lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 07:10:24 +10:00

141 lines
3.9 KiB
C

#include "aes67_web.h"
#include "aes67_cfg.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_timer.h"
#define MAX_STATUS_CBS 16
#define MAX_URIS 32
#define MAX_EARLY_URIS 16
static const char *TAG = "web";
extern const char index_html_start[] asm("_binary_index_html_start");
extern const char index_html_end[] asm("_binary_index_html_end");
esp_err_t cfg_web_register(void); // cfg.c
static httpd_handle_t s_httpd;
static status_cb_t s_status_cbs[MAX_STATUS_CBS];
static int s_status_n;
static httpd_uri_t s_early_uris[MAX_EARLY_URIS];
static int s_early_n;
esp_err_t status_register(status_cb_t cb)
{
if (s_status_n >= MAX_STATUS_CBS) {
return ESP_ERR_NO_MEM;
}
s_status_cbs[s_status_n++] = cb;
return ESP_OK;
}
esp_err_t web_register_uri(const httpd_uri_t *uri)
{
if (s_httpd) {
return httpd_register_uri_handler(s_httpd, uri);
}
if (s_early_n >= MAX_EARLY_URIS) {
return ESP_ERR_NO_MEM;
}
s_early_uris[s_early_n++] = *uri;
return ESP_OK;
}
esp_err_t web_send_json(httpd_req_t *req, const cJSON *json)
{
char *body = cJSON_PrintUnformatted(json);
if (!body) {
return httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "out of memory");
}
httpd_resp_set_type(req, "application/json");
httpd_resp_set_hdr(req, "Cache-Control", "no-store");
esp_err_t err = httpd_resp_sendstr(req, body);
cJSON_free(body);
return err;
}
static esp_err_t index_get(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html; charset=utf-8");
// EMBED_TXTFILES appends a NUL; don't send it.
return httpd_resp_send(req, index_html_start, index_html_end - index_html_start - 1);
}
static esp_err_t status_get(httpd_req_t *req)
{
cJSON *st = cJSON_CreateObject();
for (int i = 0; i < s_status_n; i++) {
s_status_cbs[i](st);
}
esp_err_t err = web_send_json(req, st);
cJSON_Delete(st);
return err;
}
static void reboot_cb(void *arg)
{
esp_restart();
}
void web_reboot_later(uint32_t ms)
{
const esp_timer_create_args_t args = { .callback = reboot_cb, .name = "reboot" };
esp_timer_handle_t t;
if (esp_timer_create(&args, &t) == ESP_OK) {
esp_timer_start_once(t, ms * 1000ULL);
}
}
static esp_err_t reboot_post(httpd_req_t *req)
{
ESP_LOGW(TAG, "reboot requested via API");
httpd_resp_sendstr(req, "");
web_reboot_later(500); // let the response go out first
return ESP_OK;
}
esp_err_t aes67_web_start(void)
{
esp_err_t err = cfg_web_register();
if (err != ESP_OK) {
return err;
}
// httpd warns on every client reset (errno 104) and every 404 (e.g. UI polling a route the
// firmware doesn't have yet): noise in syslog. Our handlers log the 4xx cases that matter.
esp_log_level_set("httpd_txrx", ESP_LOG_ERROR);
esp_log_level_set("httpd_uri", ESP_LOG_ERROR);
httpd_config_t cfg = HTTPD_DEFAULT_CONFIG();
cfg.max_uri_handlers = MAX_URIS;
cfg.stack_size = 8192;
cfg.lru_purge_enable = true;
cfg.uri_match_fn = httpd_uri_match_wildcard;
err = httpd_start(&s_httpd, &cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "httpd start failed: %s", esp_err_to_name(err));
return err;
}
static const httpd_uri_t core[] = {
{ .uri = "/", .method = HTTP_GET, .handler = index_get },
{ .uri = "/index.html", .method = HTTP_GET, .handler = index_get },
{ .uri = "/api/status", .method = HTTP_GET, .handler = status_get },
{ .uri = "/api/reboot", .method = HTTP_POST, .handler = reboot_post },
};
for (int i = 0; i < sizeof(core) / sizeof(core[0]); i++) {
httpd_register_uri_handler(s_httpd, &core[i]);
}
for (int i = 0; i < s_early_n; i++) {
httpd_register_uri_handler(s_httpd, &s_early_uris[i]);
}
ESP_LOGI(TAG, "httpd started, index.html %d bytes, %d extra routes",
(int)(index_html_end - index_html_start - 1), s_early_n);
return ESP_OK;
}