Merge pull request #318 from eandersson/websocket_fix

Fix websocket logs causing device to crash #277
This commit is contained in:
WantClue 2024-09-06 10:01:18 +02:00 committed by GitHub
commit d925d615ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -35,6 +35,7 @@ static const char * TAG = "http_server";
static GlobalState * GLOBAL_STATE;
static httpd_handle_t server = NULL;
QueueHandle_t log_queue = NULL;
static int fd = -1;
@ -48,6 +49,7 @@ static int fd = -1;
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
#define SCRATCH_BUFSIZE (10240)
#define MESSAGE_QUEUE_SIZE (128)
typedef struct rest_server_context
{
@ -534,12 +536,8 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
return ESP_OK;
}
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
void log_to_websocket(const char * format, va_list args)
void log_to_queue(const char * format, va_list args)
{
pthread_mutex_lock(&log_mutex);
va_list args_copy;
va_copy(args_copy, args);
@ -550,7 +548,6 @@ void log_to_websocket(const char * format, va_list args)
// Allocate the buffer dynamically
char * log_buffer = (char *) calloc(needed_size + 2, sizeof(char)); // +2 for potential \n and \0
if (log_buffer == NULL) {
pthread_mutex_unlock(&log_mutex);
return;
}
@ -567,16 +564,25 @@ void log_to_websocket(const char * format, va_list args)
len++;
}
// Print to standard output
printf("%s", log_buffer);
if (xQueueSendToBack(log_queue, (void*)&log_buffer, (TickType_t) 0) != pdPASS) {
if (log_buffer != NULL) {
free((void*)log_buffer);
}
}
}
void send_log_to_websocket(char *message)
{
// Prepare the WebSocket frame
httpd_ws_frame_t ws_pkt;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
ws_pkt.payload = (uint8_t *) log_buffer;
ws_pkt.len = len;
ws_pkt.payload = (uint8_t *)message;
ws_pkt.len = strlen(message);
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
// Print to standard output
printf("%s", log_buffer);
// Ensure server and fd are valid
if (server != NULL && fd >= 0) {
// Send the WebSocket frame asynchronously
@ -586,9 +592,7 @@ void log_to_websocket(const char * format, va_list args)
}
// Free the allocated buffer
free(log_buffer);
pthread_mutex_unlock(&log_mutex);
free((void*)message);
}
/*
@ -597,14 +601,12 @@ void log_to_websocket(const char * format, va_list args)
*/
esp_err_t echo_handler(httpd_req_t * req)
{
if (req->method == HTTP_GET) {
ESP_LOGI(TAG, "Handshake done, the new connection was opened");
fd = httpd_req_to_sockfd(req);
esp_log_set_vprintf(log_to_websocket);
esp_log_set_vprintf(log_to_queue);
return ESP_OK;
}
return ESP_OK;
}
@ -622,6 +624,29 @@ esp_err_t http_404_error_handler(httpd_req_t * req, httpd_err_code_t err)
return ESP_OK;
}
void websocket_log_handler()
{
while (true)
{
char *message;
if (xQueueReceive(log_queue, &message, (TickType_t) portMAX_DELAY) != pdPASS) {
if (message != NULL) {
free((void*)message);
}
vTaskDelay(10 / portTICK_PERIOD_MS);
continue;
}
if (fd == -1) {
free((void*)message);
vTaskDelay(100 / portTICK_PERIOD_MS);
continue;
}
send_log_to_websocket(message);
}
}
esp_err_t start_rest_server(void * pvParameters)
{
GLOBAL_STATE = (GlobalState *) pvParameters;
@ -639,6 +664,8 @@ esp_err_t start_rest_server(void * pvParameters)
REST_CHECK(rest_context, "No memory for rest context", err);
strlcpy(rest_context->base_path, base_path, sizeof(rest_context->base_path));
log_queue = xQueueCreate(MESSAGE_QUEUE_SIZE, sizeof(char*));
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.uri_match_fn = httpd_uri_match_wildcard;
config.max_uri_handlers = 20;
@ -711,8 +738,10 @@ esp_err_t start_rest_server(void * pvParameters)
httpd_register_err_handler(server, HTTPD_404_NOT_FOUND, http_404_error_handler);
// Start the DNS server that will redirect all queries to the softAP IP
// Start websocket log handler thread
xTaskCreate(&websocket_log_handler, "websocket_log_handler", 4096, NULL, 2, NULL);
// Start the DNS server that will redirect all queries to the softAP IP
dns_server_config_t dns_config = DNS_SERVER_CONFIG_SINGLE("*" /* all A queries */, "WIFI_AP_DEF" /* softAP netif ID */);
start_dns_server(&dns_config);