http_server: WebSocket server to set flag in transmitted messages by default

Add logic to set `FIN` flag automatically for transmitted WS frames, but
if `fragmented` option set indicating an expert/manual mode, then the
`FIN` flag is set according to the `final` option.
This commit is contained in:
David Cermak
2020-06-19 10:54:47 +02:00
committed by bot
parent 4da38b6769
commit ec2262e5a4
4 changed files with 19 additions and 5 deletions

View File

@@ -1483,7 +1483,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

@@ -10,7 +10,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 HTTPD server does not automatically fragment messages, so the application code must deal with fragmentation, setting `final` flag as appropriate. Single (complete/unfragmented) WebSocket frames must have the `FIN` flag set to be accepted as valid (see [RFC6455, section 5.4](https://tools.ietf.org/html/rfc6455#section-5.4)).
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

View File

@@ -48,7 +48,6 @@ static void ws_async_send(void *arg)
ws_pkt.payload = (uint8_t*)data;
ws_pkt.len = strlen(data);
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
ws_pkt.final = true;
httpd_ws_send_frame_async(hd, fd, &ws_pkt);
free(resp_arg);