Websocket Async Messages
Posted: Fri Dec 19, 2025 2:45 am
Hi,
I was having data consistency issues on my websocket server because I was using the same global variables for sending and receiving websocket frames.
static uint8_t buf[125] = { 0 };
static httpd_ws_frame_t ws_pkt;
So I decided to change my logic and use local allocation on the stack (maximum 125 bytes buffer) and also use allocation on the heap when necessary.
The problem is that I don't know if the functions httpd_ws_send_frame_async() and httpd_ws_send_frame() are blocking or not, or if they copy the message or not.
The problem I'm trying to solve:
Actual implementation:
A fota task called this when ws_pkt and buf they were static global.
static uint8_t buf[125] = { 0 };
static httpd_ws_frame_t ws_pkt;
The req from httpd handler is already out of scope here, i.e., the handler function has already returned and the request no longer exists, so it is mandatory to use httpd_ws_send_frame_async().
New implementation:
Using malloc allocation, but when free the memory if httpd_ws_send_frame_async() returns immediately without copying the message ???
I welcome suggestions and ideas, please.
I was having data consistency issues on my websocket server because I was using the same global variables for sending and receiving websocket frames.
static uint8_t buf[125] = { 0 };
static httpd_ws_frame_t ws_pkt;
So I decided to change my logic and use local allocation on the stack (maximum 125 bytes buffer) and also use allocation on the heap when necessary.
The problem is that I don't know if the functions httpd_ws_send_frame_async() and httpd_ws_send_frame() are blocking or not, or if they copy the message or not.
The problem I'm trying to solve:
Actual implementation:
A fota task called this when ws_pkt and buf they were static global.
static uint8_t buf[125] = { 0 };
static httpd_ws_frame_t ws_pkt;
The req from httpd handler is already out of scope here, i.e., the handler function has already returned and the request no longer exists, so it is mandatory to use httpd_ws_send_frame_async().
Code: Select all
void ws_resp_with_message_async(int sockfd, char* message, uint8_t command)
{
ESP_LOGI(TAG, LOG_USER2("FUNCTION: %s"), __func__);
ESP_LOGI(TAG, LOG_USER2("sockfd: %d"), sockfd);
ESP_LOGI(TAG, LOG_USER2("command: %u"), command);
ESP_LOGI(TAG, LOG_USER2("Message: %s"), message);
size_t strSize = strlen(message);
init_ws_pkt(1 + strSize); // command size + error message size
ws_pkt.payload[0] = command;
for (uint32_t i = 0 ; i < strSize ; i++)
{
ws_pkt.payload[i+1] = message[i]; // add message after the command.
}
httpd_ws_send_frame_async(server, sockfd, &ws_pkt); // Async message, valid after returning to uri handler and probably before returning to uri handler too.
}
New implementation:
Using malloc allocation, but when free the memory if httpd_ws_send_frame_async() returns immediately without copying the message ???
I welcome suggestions and ideas, please.
Code: Select all
static void ws_async_send_worker(void *arg)
{
httpd_ws_frame* pointer = (httpd_ws_frame*)arg;
// This is just an example; also need to receive the socket fd extracted from a struct.
httpd_ws_send_frame_async(server, sockfd, pointer);
// pointer struct with httpd_ws_frame and socket fd
free(pointer); // Can I free up memory here? If not, how will I know when I can ?
}
void ws_resp_with_message_async(int sockfd, char* message, uint8_t command)
{
Dynamically allocate memory to httpd_ws_frame
Dynamically allocate memory to buf
Assigns the buffer to httpd_ws_frame
Fill the buffer with the message
// This is just an example; also need to send the socket fd inside a struct.
httpd_queue_work(server, ws_async_send_worker, httpd_ws_frame pointer);
}