Skip to content

Commit 10ed338

Browse files
committed
ws: Support fragmented WS frames
Handling of fragments is left to the callback. Use ws_pkt->final to distinguish between incomplete and final fragments.
1 parent 16b21f7 commit 10ed338

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

software/src/modules/ws/web_sockets.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,35 @@ esp_err_t WebSockets::ws_handler(httpd_req_t *req)
161161
}
162162
}
163163

164-
if (ws_pkt.type == HTTPD_WS_TYPE_PING) {
164+
WebSocketsClient *client = static_cast<WebSocketsClient *>(req->sess_ctx);
165+
httpd_ws_type_t frame_type;
166+
167+
if (ws_pkt.type == HTTPD_WS_TYPE_CONTINUE) {
168+
frame_type = client->last_received_frame_type;
169+
} else {
170+
frame_type = ws_pkt.type;
171+
client->last_received_frame_type = frame_type;
172+
}
173+
174+
if (frame_type == HTTPD_WS_TYPE_PING) {
165175
// We use a patched version of esp-idf that does not handle ping frames in a strange way.
166176
// We have to send the pong ourselves.
167177
ws_pkt.type = HTTPD_WS_TYPE_PONG;
168178
httpd_ws_send_frame(req, &ws_pkt);
169-
} else if (ws_pkt.type == HTTPD_WS_TYPE_PONG) {
179+
} else if (frame_type == HTTPD_WS_TYPE_PONG) {
170180
// If it was a PONG, update the keep-alive
171181
WebSockets *ws = static_cast<WebSockets *>(req->user_ctx);
172182
ws->receivedPong(httpd_req_to_sockfd(req));
173-
} else if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) {
183+
} else if (frame_type == HTTPD_WS_TYPE_TEXT) {
174184
// If it was a TEXT message, print it
175185
logger.printfln("Ignoring received packet with message: \"%s\" (web sockets are unidirectional for now)", ws_pkt.payload);
176186
// FIXME: input handling
177-
} else if (ws_pkt.type == HTTPD_WS_TYPE_BINARY) {
187+
} else if (frame_type == HTTPD_WS_TYPE_BINARY) {
178188
WebSockets *ws = static_cast<WebSockets *>(req->user_ctx);
179189
if (ws->on_binary_data_received_fn != nullptr) {
180-
WebSocketsClient *client = static_cast<WebSocketsClient *>(req->sess_ctx);
181190
ws->on_binary_data_received_fn(client, &ws_pkt);
182191
}
183-
} else if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) {
192+
} else if (frame_type == HTTPD_WS_TYPE_CLOSE) {
184193
// If it was a CLOSE, remove it from the keep-alive list
185194
WebSockets *ws = static_cast<WebSockets *>(req->user_ctx);
186195
ws->keepAliveRemove(httpd_req_to_sockfd(req));
@@ -191,10 +200,12 @@ esp_err_t WebSockets::ws_handler(httpd_req_t *req)
191200
aux->sd->ws_control_frames = false;
192201

193202
if (ws->on_client_disconnect_fn != nullptr) {
194-
WebSocketsClient *client = static_cast<WebSocketsClient *>(req->sess_ctx);
195203
ws->on_client_disconnect_fn(client, true);
196204
}
205+
} else {
206+
logger.printfln("Received unexpected frame type=%u final=%i len=%zu", static_cast<unsigned>(ws_pkt.type), ws_pkt.final, ws_pkt.len);
197207
}
208+
198209
free(buf);
199210
return ESP_OK;
200211
}

software/src/modules/ws/web_sockets_client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class WebSocketsClient {
3535
inline void *getCtx() {return ctx;};
3636
inline int getFd() {return fd;};
3737

38+
httpd_ws_type_t last_received_frame_type = HTTPD_WS_TYPE_CONTINUE;
39+
3840
private:
3941
int fd;
4042
WebSockets *ws;

0 commit comments

Comments
 (0)