// Define _GNU_SOURCE to ensure all POSIX features are available #define _GNU_SOURCE // API module for serving embedded web content and NIP-17 admin messaging #include #include #include #include #include #include "api.h" #include "embedded_web_content.h" #include "config.h" #include "debug.h" // Forward declarations for database functions int store_event(cJSON* event); // Handle HTTP request for embedded files (assumes GET) int handle_embedded_file_request(struct lws* wsi, const char* requested_uri) { const char* file_path; // Handle /api requests char temp_path[256]; if (strcmp(requested_uri, "/api") == 0) { // /api -> serve index.html file_path = "/"; } else if (strncmp(requested_uri, "/api/", 5) == 0) { // Extract file path from /api/ prefix and add leading slash for lookup snprintf(temp_path, sizeof(temp_path), "/%s", requested_uri + 5); // Add leading slash file_path = temp_path; } else { DEBUG_WARN("Embedded file request without /api prefix"); lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); return -1; } // Get embedded file embedded_file_t* file = get_embedded_file(file_path); if (!file) { DEBUG_WARN("Embedded file not found"); lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); return -1; } // Allocate session data struct embedded_file_session_data* session_data = malloc(sizeof(struct embedded_file_session_data)); if (!session_data) { DEBUG_ERROR("Failed to allocate embedded file session data"); return -1; } session_data->type = 1; // Embedded file session_data->data = file->data; session_data->size = file->size; session_data->content_type = file->content_type; session_data->headers_sent = 0; session_data->body_sent = 0; // Store session data lws_set_wsi_user(wsi, session_data); // Prepare HTTP response headers unsigned char buf[LWS_PRE + 1024]; unsigned char *p = &buf[LWS_PRE]; unsigned char *start = p; unsigned char *end = &buf[sizeof(buf) - 1]; if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) { free(session_data); return -1; } if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char*)file->content_type, strlen(file->content_type), &p, end)) { free(session_data); return -1; } if (lws_add_http_header_content_length(wsi, file->size, &p, end)) { free(session_data); return -1; } // Add CORS headers (same as NIP-11 for consistency) if (lws_add_http_header_by_name(wsi, (unsigned char*)"access-control-allow-origin:", (unsigned char*)"*", 1, &p, end)) { free(session_data); return -1; } if (lws_add_http_header_by_name(wsi, (unsigned char*)"access-control-allow-headers:", (unsigned char*)"content-type, accept", 20, &p, end)) { free(session_data); return -1; } if (lws_add_http_header_by_name(wsi, (unsigned char*)"access-control-allow-methods:", (unsigned char*)"GET, OPTIONS", 12, &p, end)) { free(session_data); return -1; } // Add Connection: close to ensure connection closes after response if (lws_add_http_header_by_name(wsi, (unsigned char*)"connection:", (unsigned char*)"close", 5, &p, end)) { free(session_data); return -1; } if (lws_finalize_http_header(wsi, &p, end)) { free(session_data); return -1; } // Write headers if (lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS) < 0) { free(session_data); return -1; } session_data->headers_sent = 1; // Request callback for body transmission lws_callback_on_writable(wsi); return 0; } // Handle HTTP_WRITEABLE for embedded files int handle_embedded_file_writeable(struct lws* wsi) { struct embedded_file_session_data* session_data = (struct embedded_file_session_data*)lws_wsi_user(wsi); if (!session_data || session_data->headers_sent == 0 || session_data->body_sent == 1) { return 0; } // Allocate buffer for data transmission unsigned char *buf = malloc(LWS_PRE + session_data->size); if (!buf) { DEBUG_ERROR("Failed to allocate buffer for embedded file transmission"); free(session_data); lws_set_wsi_user(wsi, NULL); return -1; } // Copy data to buffer memcpy(buf + LWS_PRE, session_data->data, session_data->size); // Write data int write_result = lws_write(wsi, buf + LWS_PRE, session_data->size, LWS_WRITE_HTTP); // Free the transmission buffer free(buf); if (write_result < 0) { DEBUG_ERROR("Failed to write embedded file data"); free(session_data); lws_set_wsi_user(wsi, NULL); return -1; } // Mark as sent and clean up session_data->body_sent = 1; free(session_data); lws_set_wsi_user(wsi, NULL); return 0; }