web socket client issue.
Posted: Mon Jan 16, 2023 11:11 am
The web socket client example didn't work with web socket server (https://www.piesocket.com/websocket-tester) until we sent header and data at once.
Please see the the current sdk5.0 implementation and our changes below:
Please see the the current sdk5.0 implementation and our changes below:
Code: Untitled.c Select all
//////////////////////////////////////////////
// current SDK code
//////////////////////////////////////////////
static int _ws_write(esp_transport_handle_t t, int opcode, int mask_flag, const char *b, int len, int timeout_ms)
{
transport_ws_t *ws = esp_transport_get_context_data(t);
char *buffer = (char *)b;
char ws_header[MAX_WEBSOCKET_HEADER_SIZE];
char *mask;
int header_len = 0, i;
int poll_write;
if ((poll_write = esp_transport_poll_write(ws->parent, timeout_ms)) <= 0) {
ESP_LOGE(TAG, "Error transport_poll_write");
return poll_write;
}
ws_header[header_len++] = opcode;
if (len <= 125) {
ws_header[header_len++] = (uint8_t)(len | mask_flag);
} else if (len < 65536) {
ws_header[header_len++] = WS_SIZE16 | mask_flag;
ws_header[header_len++] = (uint8_t)(len >> 8);
ws_header[header_len++] = (uint8_t)(len & 0xFF);
} else {
ws_header[header_len++] = WS_SIZE64 | mask_flag;
/* Support maximum 4 bytes length */
ws_header[header_len++] = 0; //(uint8_t)((len >> 56) & 0xFF);
ws_header[header_len++] = 0; //(uint8_t)((len >> 48) & 0xFF);
ws_header[header_len++] = 0; //(uint8_t)((len >> 40) & 0xFF);
ws_header[header_len++] = 0; //(uint8_t)((len >> 32) & 0xFF);
ws_header[header_len++] = (uint8_t)((len >> 24) & 0xFF);
ws_header[header_len++] = (uint8_t)((len >> 16) & 0xFF);
ws_header[header_len++] = (uint8_t)((len >> 8) & 0xFF);
ws_header[header_len++] = (uint8_t)((len >> 0) & 0xFF);
}
if (mask_flag) {
mask = &ws_header[header_len];
getrandom(ws_header + header_len, 4, 0);
header_len += 4;
for (i = 0; i < len; ++i) {
buffer[i] = (buffer[i] ^ mask[i % 4]);
}
}
if (esp_transport_write(ws->parent, ws_header, header_len, timeout_ms) != header_len) {
ESP_LOGE(TAG, "Error write header");
return -1;
}
if (len == 0) {
return 0;
}
int ret = esp_transport_write(ws->parent, buffer, len, timeout_ms);
// in case of masked transport we have to revert back to the original data, as ws layer
// does not create its own copy of data to be sent
if (mask_flag) {
mask = &ws_header[header_len-4];
for (i = 0; i < len; ++i) {
buffer[i] = (buffer[i] ^ mask[i % 4]);
}
}
return ret;
}
//////////////////////////////////////////////
// changed code
//////////////////////////////////////////////
static int _ws_write(esp_transport_handle_t t, int opcode, int mask_flag, const char *b, int len, int timeout_ms)
{
transport_ws_t *ws = esp_transport_get_context_data(t);
int header_len = 0, i;
int poll_write;
char *pData, *pMask = NULL;
char* pBuffer = malloc(len+10); // allocation buffer with length of data plus maximal header length
if(pBuffer == NULL) {
ESP_LOGE(TAG, "Websocket transport: Failed to malloc buffer to sending...");
return 0;
}
if ((poll_write = esp_transport_poll_write(ws->parent, timeout_ms)) <= 0) {
ESP_LOGE(TAG, "Error transport_poll_write");
return poll_write;
}
pBuffer[header_len++] = opcode;
if (len <= 125) {
pBuffer[header_len++] = (uint8_t)(len | mask_flag);
} else if (len < 65536) {
pBuffer[header_len++] = WS_SIZE16 | mask_flag;
pBuffer[header_len++] = (uint8_t)(len >> 8);
pBuffer[header_len++] = (uint8_t)(len & 0xFF);
} else {
pBuffer[header_len++] = WS_SIZE64 | mask_flag;
/* Support maximum 4 bytes length */
pBuffer[header_len++] = 0; //(uint8_t)((len >> 56) & 0xFF);
pBuffer[header_len++] = 0; //(uint8_t)((len >> 48) & 0xFF);
pBuffer[header_len++] = 0; //(uint8_t)((len >> 40) & 0xFF);
pBuffer[header_len++] = 0; //(uint8_t)((len >> 32) & 0xFF);
pBuffer[header_len++] = (uint8_t)((len >> 24) & 0xFF);
pBuffer[header_len++] = (uint8_t)((len >> 16) & 0xFF);
pBuffer[header_len++] = (uint8_t)((len >> 8) & 0xFF);
pBuffer[header_len++] = (uint8_t)((len >> 0) & 0xFF);
}
if (mask_flag) {
pMask = &pBuffer[header_len];
getrandom(pMask, 4, 0);
header_len += 4;
}
pData = &pBuffer[header_len];
memcpy(pData, b, len);
if (mask_flag) {
for (i = 0; i < len; ++i) {
pData[i] = (pData[i] ^ pMask[i % 4]);
}
}
int ret = esp_transport_write(ws->parent, pBuffer, header_len+len, timeout_ms);
free(pBuffer);
return ret;
}