feat: establish the bounded production architecture

This commit is contained in:
2026-08-28 22:28:24 +03:00
parent 4ff1718307
commit a957d0defc
21 changed files with 235 additions and 5 deletions
+17 -2
View File
@@ -6,6 +6,7 @@
#include "esp_check.h"
#include "esp_event.h"
#include "esp_heap_caps.h"
#include "esp_http_server.h"
#include "esp_littlefs.h"
#include "esp_log.h"
@@ -55,6 +56,7 @@ static bool s_littlefs_mounted;
static httpd_handle_t s_server;
static esp_timer_handle_t s_state_timer;
static portMUX_TYPE s_capacity_lock = portMUX_INITIALIZER_UNLOCKED;
static uint16_t s_rejected_oversized_input;
typedef enum { VIEW_PLAYER_1, VIEW_PLAYER_2, VIEW_SPECTATOR } view_role_t;
typedef struct { int fd; view_role_t role; } ws_client_t;
@@ -260,6 +262,7 @@ static void make_capacity_state(capacity_state_t *state) {
static esp_err_t capacity_run_handler(httpd_req_t *request) {
if (request->content_len != 0) {
++s_rejected_oversized_input;
return httpd_resp_send_err(request, HTTPD_400_BAD_REQUEST, "capacity run accepts no body");
}
capacity_state_t fresh_state;
@@ -310,7 +313,10 @@ static esp_err_t websocket_handler(httpd_req_t *request) {
}
httpd_ws_frame_t frame = {0};
ESP_RETURN_ON_ERROR(httpd_ws_recv_frame(request, &frame, 0), kLogTag, "websocket frame read failed");
if (frame.len > 64 || frame.type != HTTPD_WS_TYPE_TEXT) return ESP_OK;
if (frame.len > 64 || frame.type != HTTPD_WS_TYPE_TEXT) {
++s_rejected_oversized_input;
return ESP_OK;
}
char message[65] = {0};
frame.payload = (uint8_t *)message;
frame.len = sizeof(message) - 1;
@@ -462,23 +468,32 @@ static const char *wifi_state_name(const wifi_state_t *state) {
static esp_err_t health_handler(httpd_req_t *request) {
const wifi_state_t wifi_state = wifi_state_snapshot();
size_t client_count = kHttpMaxOpenSockets;
int clients[kHttpMaxOpenSockets];
if (s_server == NULL || httpd_get_client_list(s_server, &client_count, clients) != ESP_OK) client_count = 0;
int8_t rssi_dbm = 0;
wifi_ap_record_t access_point = {0};
if (wifi_state.connected && esp_wifi_sta_get_ap_info(&access_point) == ESP_OK) {
rssi_dbm = access_point.rssi;
}
char response[320];
char response[384];
const int written = snprintf(response,
sizeof(response),
"{\"uptime_ms\":%" PRIu64
",\"wifi_state\":\"%s\",\"rssi_dbm\":%d"
",\"free_heap_bytes\":%u,\"min_free_heap_bytes\":%u"
",\"largest_free_block_bytes\":%u,\"connected_clients\":%u"
",\"rejected_oversized_input\":%u,\"reset_reason\":%d"
",\"build_version\":\"%s\"}",
(uint64_t)(esp_timer_get_time() / 1000),
wifi_state_name(&wifi_state),
(int)rssi_dbm,
(unsigned int)esp_get_free_heap_size(),
(unsigned int)esp_get_minimum_free_heap_size(),
(unsigned int)heap_caps_get_largest_free_block(MALLOC_CAP_8BIT),
(unsigned int)client_count,
(unsigned int)s_rejected_oversized_input,
(int)esp_reset_reason(),
kBuildVersion);
if (written < 0 || (size_t)written >= sizeof(response)) {
return httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "health response failed");