esp_http_server: support dynamic payload len for ws server

Closes https://github.com/espressif/esp-idf/issues/6433
This commit is contained in:
yuanjm
2021-02-02 15:00:01 +08:00
committed by bot
parent 56ca89f0f5
commit cd521d4ae3
7 changed files with 131 additions and 56 deletions

View File

@@ -8,6 +8,21 @@ See the `esp_https_server` component documentation for details.
Before using the example, open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
`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
## Certificates
You will need to approve a security exception in your browser. This is because of a self signed

View File

@@ -33,13 +33,26 @@ static const size_t max_clients = 4;
static esp_err_t ws_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;
// First receive the full ws message
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;
@@ -48,6 +61,8 @@ static esp_err_t ws_handler(httpd_req_t *req)
// If it was a PONG, update the keep-alive
if (ws_pkt.type == HTTPD_WS_TYPE_PONG) {
ESP_LOGD(TAG, "Received PONG message");
free(buf);
buf = NULL;
return wss_keep_alive_client_is_active(httpd_get_global_user_ctx(req->handle),
httpd_req_to_sockfd(req));
@@ -60,8 +75,12 @@ static esp_err_t ws_handler(httpd_req_t *req)
}
ESP_LOGI(TAG, "ws_handler: httpd_handle_t=%p, sockfd=%d, client_info:%d", req->handle,
httpd_req_to_sockfd(req), httpd_ws_get_fd_info(req->handle, httpd_req_to_sockfd(req)));
free(buf);
buf = NULL;
return ret;
}
free(buf);
buf = NULL;
return ESP_OK;
}