Skip to content

Commit 4f16476

Browse files
committed
feat(transport_ws): add support for per-message compression handshakes
1 parent ab14938 commit 4f16476

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

components/tcp_transport/include/esp_transport_ws.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef enum ws_transport_opcodes {
2424
WS_TRANSPORT_OPCODES_CLOSE = 0x08,
2525
WS_TRANSPORT_OPCODES_PING = 0x09,
2626
WS_TRANSPORT_OPCODES_PONG = 0x0a,
27+
WS_TRANSPORT_OPCODES_COMPRESSED = 0x40,
2728
WS_TRANSPORT_OPCODES_FIN = 0x80,
2829
WS_TRANSPORT_OPCODES_NONE = 0x100, /*!< not a valid opcode to indicate no message previously received
2930
* from the API esp_transport_ws_get_read_opcode() */
@@ -48,6 +49,13 @@ typedef struct {
4849
* If false, only user frames are propagated, control frames are handled
4950
* automatically during read operations
5051
*/
52+
bool per_msg_compress; /*!< Hint the server to enable per-message compression (RFC7692) */
53+
int per_msg_client_deflate_window_bit; /*!< Hint the server Per-message deflate window bit 8 to 15; or leave 0 to let server decide */
54+
int per_msg_server_deflate_window_bit; /*!< Hint the server Per-message deflate window bit 8 to 15; or leave 0 to let server decide */
55+
bool per_msg_server_no_ctx_takeover; /*!< Hint the server to reset the compression stream on every WS frame on server side
56+
* True for a safer transfer, false for better performance */
57+
bool per_msg_client_no_ctx_takeover; /*!< Hint the server to reset the compression stream on every WS frame on client side
58+
* True for a safer transfer, false for better performance */
5159
} esp_transport_ws_config_t;
5260

5361
/**

components/tcp_transport/transport_ws.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static const char *TAG = "transport_ws";
2424

2525
#define WS_BUFFER_SIZE CONFIG_WS_BUFFER_SIZE
2626
#define WS_FIN 0x80
27+
#define WS_COMPRESSED 0x40
2728
#define WS_OPCODE_CONT 0x00
2829
#define WS_OPCODE_TEXT 0x01
2930
#define WS_OPCODE_BINARY 0x02
@@ -56,6 +57,7 @@ typedef struct {
5657
int payload_len; /*!< Total length of the payload */
5758
int bytes_remaining; /*!< Bytes left to read of the payload */
5859
bool header_received; /*!< Flag to indicate that a new message header was received */
60+
bool compressed; /*!< Per-message deflate compress flag (RSV1) */
5961
} ws_transport_frame_state_t;
6062

6163
typedef struct {
@@ -75,6 +77,11 @@ typedef struct {
7577
char *redir_host;
7678
char *response_header;
7779
size_t response_header_len;
80+
bool per_msg_compress;
81+
int per_msg_client_deflate_window_bit;
82+
int per_msg_server_deflate_window_bit;
83+
bool per_msg_server_no_ctx_takeover;
84+
bool per_msg_client_no_ctx_takeover;
7885
} transport_ws_t;
7986

8087
/**
@@ -201,6 +208,20 @@ static int ws_connect(esp_transport_handle_t t, const char *host, int port, int
201208
#endif
202209

203210
size_t outlen = 0;
211+
char extension_header[160] = { 0 };
212+
if (ws->per_msg_compress) {
213+
if (ws->per_msg_client_deflate_window_bit != 0) {
214+
215+
}
216+
217+
int ext_len = snprintf(extension_header,
218+
sizeof(extension_header),
219+
"Sec-WebSocket-Extensions: permessage-deflate;%s%s%s%s",
220+
ws->per_msg_client_no_ctx_takeover ? " client_no_context_takeover; " : "",
221+
ws->per_msg_server_no_ctx_takeover ? " server_no_context_takeover; " : "",
222+
);
223+
}
224+
204225
esp_crypto_base64_encode(client_key, sizeof(client_key), &outlen, random_key, sizeof(random_key));
205226
int len = snprintf(ws->buffer, WS_BUFFER_SIZE,
206227
"GET %s HTTP/1.1\r\n"
@@ -209,7 +230,8 @@ static int ws_connect(esp_transport_handle_t t, const char *host, int port, int
209230
"User-Agent: %s\r\n"
210231
"Upgrade: websocket\r\n"
211232
"Sec-WebSocket-Version: 13\r\n"
212-
"Sec-WebSocket-Key: %s\r\n",
233+
"Sec-WebSocket-Key: %s\r\n"
234+
"%s", // For "Sec-WebSocket-Extensions"
213235
ws->path,
214236
host, port, user_agent_ptr,
215237
client_key);
@@ -575,6 +597,7 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t
575597
ws->frame_state.header_received = true;
576598
ws->frame_state.fin = (*data_ptr & 0x80) != 0;
577599
ws->frame_state.opcode = (*data_ptr & 0x0F);
600+
ws->frame_state.compressed = (*data_ptr & 0x40) != 0; // RSV1 bit in the header
578601
data_ptr ++;
579602
mask = ((*data_ptr >> 7) & 0x01);
580603
payload_len = (*data_ptr & 0x7F);
@@ -979,6 +1002,21 @@ esp_err_t esp_transport_ws_set_config(esp_transport_handle_t t, const esp_transp
9791002
}
9801003

9811004
ws->propagate_control_frames = config->propagate_control_frames;
1005+
ws->per_msg_compress = config->per_msg_compress;
1006+
ws->per_msg_client_no_ctx_takeover = config->per_msg_client_no_ctx_takeover;
1007+
ws->per_msg_server_no_ctx_takeover = config->per_msg_server_no_ctx_takeover;
1008+
1009+
if (config->per_msg_client_deflate_window_bit < 8 || config->per_msg_client_deflate_window_bit > 15) {
1010+
ws->per_msg_client_deflate_window_bit = 0;
1011+
} else {
1012+
ws->per_msg_client_deflate_window_bit = config->per_msg_client_deflate_window_bit;
1013+
}
1014+
1015+
if (config->per_msg_server_deflate_window_bit < 8 || config->per_msg_server_deflate_window_bit > 15) {
1016+
ws->per_msg_server_deflate_window_bit = 0;
1017+
} else {
1018+
ws->per_msg_server_deflate_window_bit = config->per_msg_server_deflate_window_bit;
1019+
}
9821020

9831021
return err;
9841022
}

0 commit comments

Comments
 (0)