diff options
| author | Your Name <you@example.com> | 2026-05-19 03:18:04 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-19 03:18:04 +0530 |
| commit | eeb9d2d1dfd38dd19fa641e6f733c917a3d1d005 (patch) | |
| tree | 4a3e3cf14290992a87968a833d7f041c45a7bf3b /main | |
| parent | 81f2dc52dc42d01c89dff45a5407ec40b8863052 (diff) | |
feat: CVM relay stability fix + MCP relay integration tests
Relay disconnect fix (cvm_server.c):
- TLS read timeout reduced from 15s to 1s (short poll loop)
- Ping timer fires every 30s independently of read activity
- Consecutive timeout counter (65s) detects real disconnects
- Handle relay close frames (opcode 0x08) explicitly
- Result: 120s+ stable connection (previously ~37s disconnect cycle)
MCP relay integration tests (17/17 pass via make test-cvm-mcp):
- MCP initialize roundtrip via relay.primal.net
- get_sessions returns session array
- get_usage returns metric/price/step fields
- Non-owner auth rejection (board silently drops)
- Owner control request passes after rejection test
Build fixes:
- Remove display/font/axs15231b/qrcode deps (from display branch, not here)
- Remove local_relay/relay_selector/sync_manager deps (from relay branch)
- Add esp_timer to CMakeLists REQUIRES
Host unit tests: 61/61 pass
Diffstat (limited to 'main')
| -rw-r--r-- | main/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | main/cvm_server.c | 49 | ||||
| -rw-r--r-- | main/tollgate_main.c | 12 |
3 files changed, 38 insertions, 30 deletions
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6408e14..a041bc1 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt | |||
| @@ -16,13 +16,8 @@ idf_component_register(SRCS "tollgate_main.c" | |||
| 16 | "nip04.c" | 16 | "nip04.c" |
| 17 | "mcp_handler.c" | 17 | "mcp_handler.c" |
| 18 | "cvm_server.c" | 18 | "cvm_server.c" |
| 19 | "display.c" | ||
| 20 | "font.c" | ||
| 21 | "local_relay.c" | ||
| 22 | "relay_selector.c" | ||
| 23 | "sync_manager.c" | ||
| 24 | INCLUDE_DIRS "." | 19 | INCLUDE_DIRS "." |
| 25 | REQUIRES esp_wifi esp_event esp_netif nvs_flash esp_http_server | 20 | REQUIRES esp_wifi esp_event esp_netif nvs_flash esp_http_server |
| 26 | lwip json esp_http_client mbedtls esp-tls log spiffs | 21 | lwip json esp_http_client mbedtls esp-tls log spiffs |
| 27 | nucula_lib secp256k1 axs15231b qrcode wisp_relay | 22 | nucula_lib secp256k1 esp_timer |
| 28 | PRIV_REQUIRES esp-tls) | 23 | PRIV_REQUIRES esp-tls) |
diff --git a/main/cvm_server.c b/main/cvm_server.c index dd04047..644738b 100644 --- a/main/cvm_server.c +++ b/main/cvm_server.c | |||
| @@ -30,6 +30,9 @@ static void publish_announcements_via_ws(esp_tls_t *tls); | |||
| 30 | #define CVM_WS_BUF_SIZE 8192 | 30 | #define CVM_WS_BUF_SIZE 8192 |
| 31 | #define CVM_MAX_RESPONSE_SIZE 4096 | 31 | #define CVM_MAX_RESPONSE_SIZE 4096 |
| 32 | #define CVM_RECONNECT_DELAY_MS 5000 | 32 | #define CVM_RECONNECT_DELAY_MS 5000 |
| 33 | #define CVM_WS_READ_TIMEOUT_MS 1000 | ||
| 34 | #define CVM_WS_PING_INTERVAL_S 30 | ||
| 35 | #define CVM_WS_MAX_CONSECUTIVE_TIMEOUTS 65 | ||
| 33 | 36 | ||
| 34 | static char *parse_ws_text_frame(const uint8_t *buf, int len) | 37 | static char *parse_ws_text_frame(const uint8_t *buf, int len) |
| 35 | { | 38 | { |
| @@ -553,25 +556,47 @@ static void cvm_relay_task(void *arg) | |||
| 553 | return; | 556 | return; |
| 554 | } | 557 | } |
| 555 | 558 | ||
| 559 | int64_t last_ping_time = (int64_t)esp_timer_get_time() / 1000000; | ||
| 560 | int consecutive_timeouts = 0; | ||
| 561 | |||
| 556 | while (g_running) { | 562 | while (g_running) { |
| 557 | int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); | 563 | int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); |
| 558 | if (rlen < 0) { | 564 | if (rlen < 0) { |
| 559 | ESP_LOGW(TAG, "Read error on %s (rlen=%d)", relay_url, rlen); | 565 | consecutive_timeouts++; |
| 560 | break; | 566 | if (consecutive_timeouts >= CVM_WS_MAX_CONSECUTIVE_TIMEOUTS) { |
| 561 | } | 567 | ESP_LOGW(TAG, "Read timeout on %s (%d consecutive)", relay_url, consecutive_timeouts); |
| 562 | if (rlen == 0) { | 568 | break; |
| 569 | } | ||
| 570 | } else if (rlen == 0) { | ||
| 571 | ESP_LOGW(TAG, "Connection closed by %s", relay_url); | ||
| 563 | break; | 572 | break; |
| 564 | } | 573 | } else { |
| 565 | 574 | consecutive_timeouts = 0; | |
| 566 | if ((buf[0] & 0x0F) == 0x01) { | 575 | if ((buf[0] & 0x0F) == 0x01) { |
| 567 | char *text = parse_ws_text_frame(buf, rlen); | 576 | char *text = parse_ws_text_frame(buf, rlen); |
| 568 | if (text) { | 577 | if (text) { |
| 569 | if (strlen(text) > 0) { | 578 | if (strlen(text) > 0) { |
| 570 | process_relay_message(relay_url, text); | 579 | process_relay_message(tls, relay_url, text); |
| 580 | } | ||
| 581 | free(text); | ||
| 571 | } | 582 | } |
| 572 | free(text); | 583 | } else if ((buf[0] & 0x0F) == 0x09) { |
| 584 | ESP_LOGD(TAG, "Relay ping received, sending pong"); | ||
| 585 | uint8_t pong[2] = {0x8A, 0x00}; | ||
| 586 | esp_tls_conn_write(tls, pong, 2); | ||
| 587 | } else if ((buf[0] & 0x0F) == 0x08) { | ||
| 588 | ESP_LOGW(TAG, "Relay sent close frame"); | ||
| 589 | break; | ||
| 573 | } | 590 | } |
| 574 | } | 591 | } |
| 592 | |||
| 593 | int64_t now = (int64_t)esp_timer_get_time() / 1000000; | ||
| 594 | if (now - last_ping_time >= CVM_WS_PING_INTERVAL_S) { | ||
| 595 | uint8_t ping[2] = {0x89, 0x00}; | ||
| 596 | esp_tls_conn_write(tls, ping, 2); | ||
| 597 | last_ping_time = now; | ||
| 598 | ESP_LOGD(TAG, "Sent WS keepalive ping"); | ||
| 599 | } | ||
| 575 | } | 600 | } |
| 576 | 601 | ||
| 577 | free(buf); | 602 | free(buf); |
diff --git a/main/tollgate_main.c b/main/tollgate_main.c index 4741765..fa7a692 100644 --- a/main/tollgate_main.c +++ b/main/tollgate_main.c | |||
| @@ -23,10 +23,6 @@ | |||
| 23 | #include "tollgate_client.h" | 23 | #include "tollgate_client.h" |
| 24 | #include "lightning_payout.h" | 24 | #include "lightning_payout.h" |
| 25 | #include "cvm_server.h" | 25 | #include "cvm_server.h" |
| 26 | #include "display.h" | ||
| 27 | #include "local_relay.h" | ||
| 28 | #include "relay_selector.h" | ||
| 29 | #include "sync_manager.h" | ||
| 30 | 26 | ||
| 31 | #define MAX_STA_RETRY 5 | 27 | #define MAX_STA_RETRY 5 |
| 32 | static const char *TAG = "tollgate_main"; | 28 | static const char *TAG = "tollgate_main"; |
| @@ -182,11 +178,6 @@ static void start_services(void) | |||
| 182 | s_services_running = true; | 178 | s_services_running = true; |
| 183 | if (s_services_mutex) xSemaphoreGive(s_services_mutex); | 179 | if (s_services_mutex) xSemaphoreGive(s_services_mutex); |
| 184 | ESP_LOGI(TAG, "=== TollGate services started ==="); | 180 | ESP_LOGI(TAG, "=== TollGate services started ==="); |
| 185 | |||
| 186 | display_set_state(DISPLAY_READY); | ||
| 187 | char portal_url[128]; | ||
| 188 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); | ||
| 189 | display_update(cfg->ap_ssid, 0, 0, portal_url); | ||
| 190 | } | 181 | } |
| 191 | 182 | ||
| 192 | static void stop_services(void) | 183 | static void stop_services(void) |
| @@ -270,9 +261,6 @@ void app_main(void) | |||
| 270 | { | 261 | { |
| 271 | ESP_LOGI(TAG, "=== TollGate ESP32 Starting ==="); | 262 | ESP_LOGI(TAG, "=== TollGate ESP32 Starting ==="); |
| 272 | 263 | ||
| 273 | display_init(); | ||
| 274 | display_set_state(DISPLAY_BOOT); | ||
| 275 | |||
| 276 | esp_err_t ret = nvs_flash_init(); | 264 | esp_err_t ret = nvs_flash_init(); |
| 277 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { | 265 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { |
| 278 | ESP_ERROR_CHECK(nvs_flash_erase()); | 266 | ESP_ERROR_CHECK(nvs_flash_erase()); |