diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h index 30d6549cc5..0d936de88a 100644 --- a/components/esp_http_server/include/esp_http_server.h +++ b/components/esp_http_server/include/esp_http_server.h @@ -1530,7 +1530,15 @@ typedef enum { * @brief WebSocket frame format */ typedef struct httpd_ws_frame { - bool final; /*!< Final frame */ + bool final; /*!< Final frame: + For received frames this field indicates whether the `FIN` flag was set. + For frames to be transmitted, this field is only used if the `fragmented` + option is set as well. If `fragmented` is false, the `FIN` flag is set + by default, marking the ws_frame as a complete/unfragmented message + (esp_http_server doesn't automatically fragment messages) */ + bool fragmented; /*!< Indication that the frame allocated for transmission is a message fragment, + so the `FIN` flag is set manually according to the `final` option. + This flag is never set for received messages */ httpd_ws_type_t type; /*!< WebSocket frame type */ uint8_t *payload; /*!< Pre-allocated data buffer */ size_t len; /*!< Length of the WebSocket data */ diff --git a/components/esp_http_server/src/httpd_ws.c b/components/esp_http_server/src/httpd_ws.c index d9a1cc7676..a6af5c5d9e 100644 --- a/components/esp_http_server/src/httpd_ws.c +++ b/components/esp_http_server/src/httpd_ws.c @@ -32,6 +32,7 @@ static const char *TAG="httpd_ws"; * Bit masks for WebSocket frames. * Please refer to RFC6455 Section 5.2 for more details. */ +#define HTTPD_WS_CONTINUE 0x00U #define HTTPD_WS_FIN_BIT 0x80U #define HTTPD_WS_OPCODE_BITS 0x0fU #define HTTPD_WS_MASK_BIT 0x80U @@ -279,7 +280,8 @@ esp_err_t httpd_ws_send_frame_async(httpd_handle_t hd, int fd, httpd_ws_frame_t /* Prepare Tx buffer - maximum length is 14, which includes 2 bytes header, 8 bytes length, 4 bytes mask key */ uint8_t tx_len = 0; uint8_t header_buf[10] = {0 }; - header_buf[0] |= frame->final ? HTTPD_WS_FIN_BIT : 0; /* Final (FIN) bit */ + /* Set the `FIN` bit by default if message is not fragmented. Else, set it as per the `final` field */ + header_buf[0] |= (!frame->fragmented) ? HTTPD_WS_FIN_BIT : (frame->final? HTTPD_WS_FIN_BIT: HTTPD_WS_CONTINUE); header_buf[0] |= frame->type; /* Type (opcode): 4 bits */ if (frame->len <= 125) { @@ -381,4 +383,4 @@ esp_err_t httpd_ws_get_frame_type(httpd_req_t *req) return ESP_OK; } -#endif /* CONFIG_HTTPD_WS_SUPPORT */ \ No newline at end of file +#endif /* CONFIG_HTTPD_WS_SUPPORT */ diff --git a/examples/protocols/http_server/ws_echo_server/README.md b/examples/protocols/http_server/ws_echo_server/README.md index 61bcc0fbbd..8fa4219337 100644 --- a/examples/protocols/http_server/ws_echo_server/README.md +++ b/examples/protocols/http_server/ws_echo_server/README.md @@ -11,6 +11,12 @@ ws_server_example_test.py could be used as a simple WS client). 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). + + ### Hardware Required This example can be executed on any common development board, the only required interface is WiFi or Ethernet connection to a local network.