diff --git a/examples/protocols/http_server/ws_echo_server/README.md b/examples/protocols/http_server/ws_echo_server/README.md index d3dbe7f2e4..34254b6e48 100644 --- a/examples/protocols/http_server/ws_echo_server/README.md +++ b/examples/protocols/http_server/ws_echo_server/README.md @@ -5,16 +5,50 @@ This example demonstrates the HTTPD server using the WebSocket feature. ## How to Use Example -The example starts a WS server on a local network, so a WS client is needed to interact with the server (an example test -ws_server_example_test.py could be used as a simple WS client). +The example starts a websocket server on a local network. You need a websocket client to interact with the server (an example test +ws_server_example_test.py could be used as the simple websocket client). -The server registers WebSocket handler which echoes back the received WebSocket frame. It also demonstrates +The server registers websocket handler which echoes back the received WebSocket frame. It also demonstrates use of asynchronous send, which is triggered on reception of a certain message. -Please note that the WebSocket HTTP server does not automatically fragment messages. -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). +### Websocket support in `http_server` + +Websocket echo server is build on top of the HTTP server component using [Websocket server](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/protocols/esp_http_server.html#websocket-server) configuration. +This feature is very limited, and a special care must be taken while implementing websocket URI handlers. + +#### Configure URI handler + +We register the URI handler with the standard API `httpd_register_uri_handler()` with `is_websocket` enabled and other optional parameters: + +```c +static const httpd_uri_t ws_uri_handler_options = { + ... // httpd options + + .is_websocket = true, // Mandatory: set to `true` to handler websocket protocol + .handle_ws_control_frames = false, // Optional: set to `true` for the handler to receive control packets, too + .supported_subprotocol = "chat", // Optional: set supported subprotocol for this handler +}; + +``` + +#### Implement URI handler + +The URI handler is called on every URI request, but also before the websocket handshake, so it is very important to check the request type before reading websocket frame: + +```c + // beginning of the ws URI handler + if (req->method == HTTP_GET) { + // action before ws handshake + return ESP_OK; + } + // action after the handshake (read frames) +``` + +#### Handling incoming data + +To receive websocket frames, use `httpd_ws_recv_frame()` after the websocket handshake, with `httpd_ws_frame_t` parameters set accordingly: +* `payload` to a valid buffer for the received data +* `len` set to `0` for the first call of `httpd_ws_recv_frame()`. Note that this value is used to indicate the packet length has been read in the previous call if we use dynamic buffers. `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) @@ -27,9 +61,17 @@ 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 + 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 + +#### Handling outgoing data + +Please note that the WebSocket HTTP server does not automatically fragment messages. +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). + ### Hardware Required diff --git a/examples/protocols/https_server/wss_server/README.md b/examples/protocols/https_server/wss_server/README.md index bd9d696235..b3c16835b8 100644 --- a/examples/protocols/https_server/wss_server/README.md +++ b/examples/protocols/https_server/wss_server/README.md @@ -8,20 +8,10 @@ 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) +### Websocket support in `http_server` -``` -#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 +Please refer to the documentation of [Websocket server](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/protocols/esp_http_server.html#websocket-server) feature in the documentation, +or to the description of using websocket handlers in httpd in the [simple ws echo](../../http_server/ws_echo_server/README.md#how-to-use-example) example. ## Certificates