diff options
Diffstat (limited to 'main/cvm_server.c')
| -rw-r--r-- | main/cvm_server.c | 95 |
1 files changed, 10 insertions, 85 deletions
diff --git a/main/cvm_server.c b/main/cvm_server.c index b93e176..dd04047 100644 --- a/main/cvm_server.c +++ b/main/cvm_server.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include "esp_tls.h" | 11 | #include "esp_tls.h" |
| 12 | #include "esp_crt_bundle.h" | 12 | #include "esp_crt_bundle.h" |
| 13 | #include "esp_random.h" | 13 | #include "esp_random.h" |
| 14 | #include "esp_timer.h" | ||
| 15 | #include "freertos/FreeRTOS.h" | 14 | #include "freertos/FreeRTOS.h" |
| 16 | #include "freertos/task.h" | 15 | #include "freertos/task.h" |
| 17 | #include <string.h> | 16 | #include <string.h> |
| @@ -31,8 +30,6 @@ static void publish_announcements_via_ws(esp_tls_t *tls); | |||
| 31 | #define CVM_WS_BUF_SIZE 8192 | 30 | #define CVM_WS_BUF_SIZE 8192 |
| 32 | #define CVM_MAX_RESPONSE_SIZE 4096 | 31 | #define CVM_MAX_RESPONSE_SIZE 4096 |
| 33 | #define CVM_RECONNECT_DELAY_MS 5000 | 32 | #define CVM_RECONNECT_DELAY_MS 5000 |
| 34 | #define CVM_WS_READ_TIMEOUT_MS 60000 | ||
| 35 | #define CVM_WS_PING_INTERVAL_S 30 | ||
| 36 | 33 | ||
| 37 | static char *parse_ws_text_frame(const uint8_t *buf, int len) | 34 | static char *parse_ws_text_frame(const uint8_t *buf, int len) |
| 38 | { | 35 | { |
| @@ -151,7 +148,7 @@ static esp_err_t ws_connect(const char *relay_url, esp_tls_t **tls_out) | |||
| 151 | 148 | ||
| 152 | esp_tls_cfg_t tls_cfg = { | 149 | esp_tls_cfg_t tls_cfg = { |
| 153 | .crt_bundle_attach = esp_crt_bundle_attach, | 150 | .crt_bundle_attach = esp_crt_bundle_attach, |
| 154 | .timeout_ms = CVM_WS_READ_TIMEOUT_MS, | 151 | .timeout_ms = 15000, |
| 155 | }; | 152 | }; |
| 156 | esp_tls_t *tls = esp_tls_init(); | 153 | esp_tls_t *tls = esp_tls_init(); |
| 157 | if (!tls) return ESP_ERR_NO_MEM; | 154 | if (!tls) return ESP_ERR_NO_MEM; |
| @@ -326,54 +323,6 @@ static esp_err_t publish_event_to_relay(const char *relay_url, const char *event | |||
| 326 | return ESP_OK; | 323 | return ESP_OK; |
| 327 | } | 324 | } |
| 328 | 325 | ||
| 329 | static esp_err_t publish_kind_25910_response_ws(esp_tls_t *tls, | ||
| 330 | const char *content_json, | ||
| 331 | const char *request_event_id) | ||
| 332 | { | ||
| 333 | const tollgate_identity_t *id = identity_get(); | ||
| 334 | if (!id || !id->initialized) return ESP_FAIL; | ||
| 335 | |||
| 336 | cJSON *tags = cJSON_CreateArray(); | ||
| 337 | cJSON *e_tag = cJSON_CreateArray(); | ||
| 338 | cJSON_AddItemToArray(e_tag, cJSON_CreateString("e")); | ||
| 339 | cJSON_AddItemToArray(e_tag, cJSON_CreateString(request_event_id)); | ||
| 340 | cJSON_AddItemToArray(tags, e_tag); | ||
| 341 | |||
| 342 | char *tags_str = cJSON_PrintUnformatted(tags); | ||
| 343 | cJSON_Delete(tags); | ||
| 344 | |||
| 345 | nostr_event_t event; | ||
| 346 | nostr_event_init(&event, id->npub_hex, 25910, tags_str, content_json); | ||
| 347 | nostr_event_sign(&event, id->nsec); | ||
| 348 | |||
| 349 | char *event_json = malloc(8192); | ||
| 350 | if (!event_json) { | ||
| 351 | free(tags_str); | ||
| 352 | return ESP_ERR_NO_MEM; | ||
| 353 | } | ||
| 354 | |||
| 355 | esp_err_t ret = nostr_event_to_json(&event, event_json, 8192); | ||
| 356 | free(tags_str); | ||
| 357 | if (ret != ESP_OK) { | ||
| 358 | free(event_json); | ||
| 359 | return ret; | ||
| 360 | } | ||
| 361 | |||
| 362 | size_t msg_len = 10 + strlen(event_json) + 2; | ||
| 363 | char *msg = malloc(msg_len); | ||
| 364 | if (!msg) { | ||
| 365 | free(event_json); | ||
| 366 | return ESP_ERR_NO_MEM; | ||
| 367 | } | ||
| 368 | snprintf(msg, msg_len, "[\"EVENT\",%s]", event_json); | ||
| 369 | ESP_LOGD(TAG, "Sending WS response (%d bytes)", (int)strlen(msg)); | ||
| 370 | int rc = ws_send_text(tls, msg); | ||
| 371 | ESP_LOGD(TAG, "WS send result: %d", rc); | ||
| 372 | free(msg); | ||
| 373 | free(event_json); | ||
| 374 | return ESP_OK; | ||
| 375 | } | ||
| 376 | |||
| 377 | static esp_err_t publish_kind_25910_response(const char *relay_url, | 326 | static esp_err_t publish_kind_25910_response(const char *relay_url, |
| 378 | const char *content_json, | 327 | const char *content_json, |
| 379 | const char *request_event_id) | 328 | const char *request_event_id) |
| @@ -417,7 +366,7 @@ static bool is_owner_pubkey(const char *pubkey_hex) | |||
| 417 | return strcmp(id->npub_hex, pubkey_hex) == 0; | 366 | return strcmp(id->npub_hex, pubkey_hex) == 0; |
| 418 | } | 367 | } |
| 419 | 368 | ||
| 420 | static void handle_mcp_message(esp_tls_t *tls, const char *sender_pubkey, | 369 | static void handle_mcp_message(const char *relay_url, const char *sender_pubkey, |
| 421 | const char *event_id, const char *content) | 370 | const char *event_id, const char *content) |
| 422 | { | 371 | { |
| 423 | cJSON *msg = cJSON_Parse(content); | 372 | cJSON *msg = cJSON_Parse(content); |
| @@ -437,20 +386,14 @@ static void handle_mcp_message(esp_tls_t *tls, const char *sender_pubkey, | |||
| 437 | if (strcmp(m, "initialize") == 0) { | 386 | if (strcmp(m, "initialize") == 0) { |
| 438 | ESP_LOGI(TAG, "MCP initialize from %s", sender_pubkey); | 387 | ESP_LOGI(TAG, "MCP initialize from %s", sender_pubkey); |
| 439 | char *resp = build_initialize_response(id_str, sender_pubkey); | 388 | char *resp = build_initialize_response(id_str, sender_pubkey); |
| 440 | if (tls) { | 389 | publish_kind_25910_response(relay_url, resp, event_id); |
| 441 | publish_kind_25910_response_ws(tls, resp, event_id); | ||
| 442 | } else { | ||
| 443 | ESP_LOGW(TAG, "No TLS for response"); | ||
| 444 | } | ||
| 445 | free(resp); | 390 | free(resp); |
| 446 | } else if (strcmp(m, "notifications/initialized") == 0) { | 391 | } else if (strcmp(m, "notifications/initialized") == 0) { |
| 447 | ESP_LOGI(TAG, "Client initialized: %s", sender_pubkey); | 392 | ESP_LOGI(TAG, "Client initialized: %s", sender_pubkey); |
| 448 | } else if (strcmp(m, "tools/list") == 0) { | 393 | } else if (strcmp(m, "tools/list") == 0) { |
| 449 | ESP_LOGI(TAG, "tools/list from %s", sender_pubkey); | 394 | ESP_LOGI(TAG, "tools/list from %s", sender_pubkey); |
| 450 | char *resp = build_tools_list_response(id_str); | 395 | char *resp = build_tools_list_response(id_str); |
| 451 | if (tls) { | 396 | publish_kind_25910_response(relay_url, resp, event_id); |
| 452 | publish_kind_25910_response_ws(tls, resp, event_id); | ||
| 453 | } | ||
| 454 | free(resp); | 397 | free(resp); |
| 455 | } else if (strcmp(m, "tools/call") == 0) { | 398 | } else if (strcmp(m, "tools/call") == 0) { |
| 456 | cJSON *params = cJSON_GetObjectItem(msg, "params"); | 399 | cJSON *params = cJSON_GetObjectItem(msg, "params"); |
| @@ -471,16 +414,12 @@ static void handle_mcp_message(esp_tls_t *tls, const char *sender_pubkey, | |||
| 471 | 414 | ||
| 472 | mcp_response_t mcp_resp = mcp_dispatch(&req); | 415 | mcp_response_t mcp_resp = mcp_dispatch(&req); |
| 473 | char *resp = build_tool_call_response(id_str, &mcp_resp); | 416 | char *resp = build_tool_call_response(id_str, &mcp_resp); |
| 474 | if (tls) { | 417 | publish_kind_25910_response(relay_url, resp, event_id); |
| 475 | publish_kind_25910_response_ws(tls, resp, event_id); | ||
| 476 | } | ||
| 477 | free(resp); | 418 | free(resp); |
| 478 | } | 419 | } |
| 479 | } else if (strcmp(m, "ping") == 0) { | 420 | } else if (strcmp(m, "ping") == 0) { |
| 480 | char *resp = build_ping_response(id_str); | 421 | char *resp = build_ping_response(id_str); |
| 481 | if (tls) { | 422 | publish_kind_25910_response(relay_url, resp, event_id); |
| 482 | publish_kind_25910_response_ws(tls, resp, event_id); | ||
| 483 | } | ||
| 484 | free(resp); | 423 | free(resp); |
| 485 | } else { | 424 | } else { |
| 486 | ESP_LOGW(TAG, "Unknown MCP method: %s", m); | 425 | ESP_LOGW(TAG, "Unknown MCP method: %s", m); |
| @@ -494,7 +433,7 @@ static void handle_mcp_message(esp_tls_t *tls, const char *sender_pubkey, | |||
| 494 | cJSON_Delete(msg); | 433 | cJSON_Delete(msg); |
| 495 | } | 434 | } |
| 496 | 435 | ||
| 497 | static void process_relay_message(esp_tls_t *tls, const char *relay_url, const char *msg_str) | 436 | static void process_relay_message(const char *relay_url, const char *msg_str) |
| 498 | { | 437 | { |
| 499 | cJSON *arr = cJSON_Parse(msg_str); | 438 | cJSON *arr = cJSON_Parse(msg_str); |
| 500 | if (!arr || !cJSON_IsArray(arr)) { | 439 | if (!arr || !cJSON_IsArray(arr)) { |
| @@ -553,7 +492,7 @@ static void process_relay_message(esp_tls_t *tls, const char *relay_url, const c | |||
| 553 | return; | 492 | return; |
| 554 | } | 493 | } |
| 555 | 494 | ||
| 556 | handle_mcp_message(tls, pubkey->valuestring, event_id->valuestring, content->valuestring); | 495 | handle_mcp_message(relay_url, pubkey->valuestring, event_id->valuestring, content->valuestring); |
| 557 | cJSON_Delete(arr); | 496 | cJSON_Delete(arr); |
| 558 | } | 497 | } |
| 559 | 498 | ||
| @@ -566,9 +505,7 @@ static esp_err_t subscribe_to_relay(esp_tls_t *tls, const char *npub) | |||
| 566 | cJSON *kinds = cJSON_CreateArray(); | 505 | cJSON *kinds = cJSON_CreateArray(); |
| 567 | cJSON_AddItemToArray(kinds, cJSON_CreateNumber(25910)); | 506 | cJSON_AddItemToArray(kinds, cJSON_CreateNumber(25910)); |
| 568 | cJSON_AddItemToObject(filter, "kinds", kinds); | 507 | cJSON_AddItemToObject(filter, "kinds", kinds); |
| 569 | cJSON *p_tags = cJSON_CreateArray(); | 508 | cJSON_AddStringToObject(filter, "#p", npub); |
| 570 | cJSON_AddItemToArray(p_tags, cJSON_CreateString(npub)); | ||
| 571 | cJSON_AddItemToObject(filter, "#p", p_tags); | ||
| 572 | cJSON_AddNumberToObject(filter, "limit", 100); | 509 | cJSON_AddNumberToObject(filter, "limit", 100); |
| 573 | cJSON_AddItemToArray(sub, filter); | 510 | cJSON_AddItemToArray(sub, filter); |
| 574 | 511 | ||
| @@ -616,8 +553,6 @@ static void cvm_relay_task(void *arg) | |||
| 616 | return; | 553 | return; |
| 617 | } | 554 | } |
| 618 | 555 | ||
| 619 | int64_t last_ping_time = 0; | ||
| 620 | |||
| 621 | while (g_running) { | 556 | while (g_running) { |
| 622 | int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); | 557 | int rlen = esp_tls_conn_read(tls, buf, CVM_WS_BUF_SIZE - 1); |
| 623 | if (rlen < 0) { | 558 | if (rlen < 0) { |
| @@ -632,20 +567,10 @@ static void cvm_relay_task(void *arg) | |||
| 632 | char *text = parse_ws_text_frame(buf, rlen); | 567 | char *text = parse_ws_text_frame(buf, rlen); |
| 633 | if (text) { | 568 | if (text) { |
| 634 | if (strlen(text) > 0) { | 569 | if (strlen(text) > 0) { |
| 635 | process_relay_message(tls, relay_url, text); | 570 | process_relay_message(relay_url, text); |
| 636 | } | 571 | } |
| 637 | free(text); | 572 | free(text); |
| 638 | } | 573 | } |
| 639 | } else if ((buf[0] & 0x0F) == 0x09) { | ||
| 640 | uint8_t pong[2] = {0x8A, 0x00}; | ||
| 641 | esp_tls_conn_write(tls, pong, 2); | ||
| 642 | } | ||
| 643 | |||
| 644 | int64_t now = (int64_t)esp_timer_get_time() / 1000000; | ||
| 645 | if (now - last_ping_time >= CVM_WS_PING_INTERVAL_S) { | ||
| 646 | uint8_t ping[2] = {0x89, 0x00}; | ||
| 647 | esp_tls_conn_write(tls, ping, 2); | ||
| 648 | last_ping_time = now; | ||
| 649 | } | 574 | } |
| 650 | } | 575 | } |
| 651 | 576 | ||