Skip to content

Commit

Permalink
fix(ws_transport): correct split header bytes
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bryghtlabs-richard committed Oct 10, 2024
1 parent 6e5a178 commit cde804b
Showing 1 changed file with 31 additions and 4 deletions.
35 changes: 31 additions & 4 deletions components/tcp_transport/transport_ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,33 @@ static int esp_transport_read_internal(transport_ws_t *ws, char *buffer, int len
return to_read;
}

static int esp_transport_read_blocking(transport_ws_t *ws, char *buffer, int len, int timeout_ms)
{
int orig_len = len;
int did_read = 0;

//Sometimes we get 1B/read, sometimes we need 8B?
//Never seen this need >2 reads, better be safe though - need those headers.
const unsigned MAX_ATTEMPT = 8;
//TODO: change this(or the underlying transports) to retry only until timeout_ms expires.
unsigned attempt = 0;
for(attempt = 0; attempt < MAX_ATTEMPT && len > 0; ++attempt){
int tmp = esp_transport_read_internal(ws, buffer, len, timeout_ms);
if(tmp < 0){
return tmp;
}

buffer += tmp;
len -= tmp;
did_read += tmp;
}

if(attempt > 1){
ESP_LOGI(TAG, "tried %u attempts to read %i bytes. did read %i bytes", attempt, orig_len, did_read);
}
return did_read;
}

static char *trimwhitespace(char *str)
{
char *end;
Expand Down Expand Up @@ -486,7 +513,7 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t
// Receive and process header first (based on header size)
int header = 2;
int mask_len = 4;
if ((rlen = esp_transport_read_internal(ws, data_ptr, header, timeout_ms)) <= 0) {
if ((rlen = esp_transport_read_blocking(ws, data_ptr, header, timeout_ms)) < header) {
ESP_LOGE(TAG, "Error read data");
return rlen;
}
Expand All @@ -500,15 +527,15 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t
ESP_LOGD(TAG, "Opcode: %d, mask: %d, len: %d", ws->frame_state.opcode, mask, payload_len);
if (payload_len == 126) {
// headerLen += 2;
if ((rlen = esp_transport_read_internal(ws, data_ptr, header, timeout_ms)) <= 0) {
if ((rlen = esp_transport_read_blocking(ws, data_ptr, header, timeout_ms)) < header) {
ESP_LOGE(TAG, "Error read data");
return rlen;
}
payload_len = (uint8_t)data_ptr[0] << 8 | (uint8_t)data_ptr[1];
} else if (payload_len == 127) {
// headerLen += 8;
header = 8;
if ((rlen = esp_transport_read_internal(ws, data_ptr, header, timeout_ms)) <= 0) {
if ((rlen = esp_transport_read_blocking(ws, data_ptr, header, timeout_ms)) < header) {
ESP_LOGE(TAG, "Error read data");
return rlen;
}
Expand All @@ -523,7 +550,7 @@ static int ws_read_header(esp_transport_handle_t t, char *buffer, int len, int t

if (mask) {
// Read and store mask
if (payload_len != 0 && (rlen = esp_transport_read_internal(ws, buffer, mask_len, timeout_ms)) <= 0) {
if (payload_len != 0 && (rlen = esp_transport_read_blocking(ws, buffer, mask_len, timeout_ms)) < mask_len) {
ESP_LOGE(TAG, "Error read data");
return rlen;
}
Expand Down

0 comments on commit cde804b

Please sign in to comment.