So i've been through the examples and the MR for the websockets support that has been added in httpd and i'm not fully following how to properly free resources once the messages have been sent. Hopefully i'm not missing something too obvious!
For instance let's say an action need to broadcast a websocket message to all connected clients. I do something along the lines of the code below.
From the examples, i get that resp_arg can be freed from ws_async_send which makes sense, however what about the payload that's being transmitted? looking through the esp-idf code from what I can see the pointer is passed around and therefore should be valid until the message has been dispatched therefore I can't free it at the same time?
Similarly when should the ws_pkt be freed? I was expecting my example below not to work as the same ws_pkt is used multiple times. I was assuming it was automatically freed after send, but the code below looks to be working okay so I would expect to have to free it at some point.
Lastly and not so relevant to the question here, for those who have implemented socket broadcast, is iterating over the server clients' list and checking for websocket connection a reasonable way to go about it? considering the small number of active connections I do think it's suitable (instead of keeping a separate collection of only websockets) but I'm sure some other people have done this so I would like to double check.
Code: Select all
struct async_resp_arg {
httpd_handle_t hd;
uint8_t *txbuf;
ring_buffer_pos_t len;
};
void ws_async_send(void *arg) {
struct async_resp_arg *resp_arg = (struct async_resp_arg *)arg;
httpd_ws_frame_t ws_pkt;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
ws_pkt.payload = resp_arg->txbuf;
ws_pkt.len = resp_arg->len;
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
size_t fds = 8;
int client_fds[8];
httpd_get_client_list(resp_arg->hd, &fds, client_fds); //todo handle error
for (int i=0; i<fds; i++) {
if (httpd_ws_get_fd_info(resp_arg->hd, client_fds[i]) == HTTPD_WS_CLIENT_WEBSOCKET) {
httpd_ws_send_frame_async(resp_arg->hd, client_fds[i], &ws_pkt);
}
}
free(arg);
}
// An async operation that should trigger a websocket broadcast to the connected clients
void myaction(uint8_t *buffer, size_t len) {
struct async_resp_arg *resp_arg = (struct async_resp_arg *)malloc(sizeof(struct async_resp_arg));
resp_arg->hd = server; // the httpd handle
resp_arg->tx_buffer = buffer; // a malloc'ed buffer to transmit
resp_arg->len = len;
httpd_queue_work(server, ws_async_send, resp_arg);
}