161 lines
5.0 KiB
C
161 lines
5.0 KiB
C
// 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <pthread.h>
|
|
#include <libwebsockets.h>
|
|
#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;
|
|
}
|