Skip to content

Commit 14635c6

Browse files
bryghtlabs-richarddavid-cermak
authored andcommitted
fix(ws_transport): Fix reading WS header bytes
Correct split header bytes When the underlying transport returns header, length, or mask bytes early, again call the underlying transport. This solves the WS parser getting offset when the server sends a burst of frames where the last WS header is split across packet boundaries, so fewer than the needed bytes may be available. Merges espressif#14706
1 parent 4143156 commit 14635c6

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

components/tcp_transport/transport_ws.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,34 @@ static int esp_transport_read_internal(transport_ws_t *ws, char *buffer, int len
131131
return to_read;
132132
}
133133

134+
static int esp_transport_read_exact_size(transport_ws_t *ws, char *buffer, int requested_len, int timeout_ms)
135+
{
136+
int total_read = 0;
137+
int len = requested_len;
138+
139+
while (len > 0) {
140+
int bytes_read = esp_transport_read_internal(ws, buffer, len, timeout_ms);
141+
142+
if (bytes_read < 0) {
143+
return bytes_read; // Return error from the underlying read
144+
}
145+
146+
if (bytes_read == 0) {
147+
// If we read 0 bytes, we return an error, since reading exact number of bytes resulted in a timeout operation
148+
ESP_LOGW(TAG, "Requested to read %d, actually read %d bytes", requested_len, total_read);
149+
return -1;
150+
}
151+
152+
// Update buffer and remaining length
153+
buffer += bytes_read;
154+
len -= bytes_read;
155+
total_read += bytes_read;
156+
157+
ESP_LOGV(TAG, "Read fragment of %d bytes", bytes_read);
158+
}
159+
return total_read;
160+
}
161+
134162
static char *trimwhitespace(char *str)
135163
{
136164
char *end;
@@ -484,7 +512,7 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t
484512
// Receive and process header first (based on header size)
485513
int header = 2;
486514
int mask_len = 4;
487-
if ((rlen = esp_transport_read_internal(ws, data_ptr, header, timeout_ms)) <= 0) {
515+
if ((rlen = esp_transport_read_exact_size(ws, data_ptr, header, timeout_ms)) <= 0) {
488516
ESP_LOGE(TAG, "Error read data");
489517
return rlen;
490518
}
@@ -498,15 +526,15 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t
498526
ESP_LOGD(TAG, "Opcode: %d, mask: %d, len: %d", ws->frame_state.opcode, mask, payload_len);
499527
if (payload_len == 126) {
500528
// headerLen += 2;
501-
if ((rlen = esp_transport_read_internal(ws, data_ptr, header, timeout_ms)) <= 0) {
529+
if ((rlen = esp_transport_read_exact_size(ws, data_ptr, header, timeout_ms)) <= 0) {
502530
ESP_LOGE(TAG, "Error read data");
503531
return rlen;
504532
}
505533
payload_len = (uint8_t)data_ptr[0] << 8 | (uint8_t)data_ptr[1];
506534
} else if (payload_len == 127) {
507535
// headerLen += 8;
508536
header = 8;
509-
if ((rlen = esp_transport_read_internal(ws, data_ptr, header, timeout_ms)) <= 0) {
537+
if ((rlen = esp_transport_read_exact_size(ws, data_ptr, header, timeout_ms)) <= 0) {
510538
ESP_LOGE(TAG, "Error read data");
511539
return rlen;
512540
}
@@ -521,7 +549,7 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t
521549

522550
if (mask) {
523551
// Read and store mask
524-
if (payload_len != 0 && (rlen = esp_transport_read_internal(ws, buffer, mask_len, timeout_ms)) <= 0) {
552+
if (payload_len != 0 && (rlen = esp_transport_read_exact_size(ws, buffer, mask_len, timeout_ms)) <= 0) {
525553
ESP_LOGE(TAG, "Error read data");
526554
return rlen;
527555
}

0 commit comments

Comments
 (0)