esp_http_server: support dynamic payload len for ws server
Closes https://github.com/espressif/esp-idf/issues/6433
This commit is contained in:
@@ -16,6 +16,20 @@ Each outgoing frame has the FIN flag set by default.
|
||||
In case an application wants to send fragmented data, it must be done manually by setting the
|
||||
`fragmented` option and using the `final` flag as described in [RFC6455, section 5.4](https://tools.ietf.org/html/rfc6455#section-5.4).
|
||||
|
||||
`httpd_ws_recv_frame` support two ways to get frame payload.
|
||||
* Static buffer -- Allocate maximum expected packet length (either statically or dynamically) and call `httpd_ws_recv_frame()` referencing this buffer and it's size. (Unnecessarily large buffers might cause memory waste)
|
||||
|
||||
```
|
||||
#define MAX_PAYLOAD_LEN 128
|
||||
uint8_t buf[MAX_PAYLOAD_LEN] = { 0 };
|
||||
httpd_ws_frame_t ws_pkt;
|
||||
ws_pkt.payload = buf;
|
||||
httpd_ws_recv_frame(req, &ws_pkt, MAX_PAYLOAD_LEN);
|
||||
```
|
||||
* Dynamic buffer -- Refer to the examples, which receive websocket data in these three steps:
|
||||
1) Call `httpd_ws_recv_frame()` with zero buffer size
|
||||
2) Allocate the size based on the received packet length
|
||||
3) Call `httpd_ws_recv_frame()` with the allocated buffer
|
||||
|
||||
### Hardware Required
|
||||
|
||||
|
||||
@@ -67,12 +67,25 @@ static esp_err_t trigger_async_send(httpd_handle_t handle, httpd_req_t *req)
|
||||
*/
|
||||
static esp_err_t echo_handler(httpd_req_t *req)
|
||||
{
|
||||
uint8_t buf[128] = { 0 };
|
||||
httpd_ws_frame_t ws_pkt;
|
||||
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
|
||||
ws_pkt.payload = buf;
|
||||
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
|
||||
esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 128);
|
||||
/* Set max_len = 0 to get the frame len */
|
||||
esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "httpd_ws_recv_frame failed to get frame len with %d", ret);
|
||||
return ret;
|
||||
}
|
||||
ESP_LOGI(TAG, "frame len is %d", ws_pkt.len);
|
||||
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
|
||||
uint8_t *buf = calloc(1, ws_pkt.len + 1);
|
||||
if (buf == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to calloc memory for buf");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
ws_pkt.payload = buf;
|
||||
/* Set max_len = ws_pkt.len to get the frame payload */
|
||||
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret);
|
||||
return ret;
|
||||
@@ -81,6 +94,8 @@ static esp_err_t echo_handler(httpd_req_t *req)
|
||||
ESP_LOGI(TAG, "Packet type: %d", ws_pkt.type);
|
||||
if (ws_pkt.type == HTTPD_WS_TYPE_TEXT &&
|
||||
strcmp((char*)ws_pkt.payload,"Trigger async") == 0) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
return trigger_async_send(req->handle, req);
|
||||
}
|
||||
|
||||
@@ -88,6 +103,8 @@ static esp_err_t echo_handler(httpd_req_t *req)
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret);
|
||||
}
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user