Merge branch 'bugfix/ws_server_async_send_fin' into 'master'

http_server example: WebSocket server to set final flag in async messages

Closes IDFGH-3443

See merge request espressif/esp-idf!9251
This commit is contained in:
David Čermák 2020-07-15 05:31:02 +08:00
commit f8b649baaf
3 changed files with 19 additions and 3 deletions

View File

@ -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 */

View File

@ -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 */
#endif /* CONFIG_HTTPD_WS_SUPPORT */

View File

@ -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.