Skip to content

Commit 367f5d2

Browse files
committed
Refactor the code handling WS data event to remove code duplication
1 parent e3fd7ad commit 367f5d2

2 files changed

Lines changed: 27 additions & 49 deletions

File tree

src/AsyncWebSocket.cpp

Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -656,31 +656,7 @@ void AsyncWebSocketClient::_onData(void *pbuf, size_t plen) {
656656
}
657657

658658
if (datalen > 0) {
659-
// ------------------------------------------------------------
660-
// Issue 384: https://github.com/ESP32Async/ESPAsyncWebServer/issues/384
661-
// Discussion: https://github.com/ESP32Async/ESPAsyncWebServer/pull/383#discussion_r2760425739
662-
// The initial design of the library was doing a backup of the byte following the data buffer because the client code
663-
// was allowed and documented to do something like data[len] = 0; to facilitate null-terminated string handling.
664-
// This was a bit hacky but it was working and it was documented, although completely incorrect because it was modifying a byte outside of the data buffer.
665-
// So to fix this behavior and to avoid breaking existing client code that may be relying on this behavior, we now have to copy the data to a temporary buffer that has an extra byte for the null terminator.
666-
// ------------------------------------------------------------
667-
uint8_t *copy = (uint8_t *)malloc(datalen + 1);
668-
669-
if (copy == NULL) {
670-
async_ws_log_e("Failed to allocate");
671-
_status = WS_DISCONNECTED;
672-
if (_client) {
673-
_client->abort();
674-
}
675-
return;
676-
}
677-
678-
memcpy(copy, data, datalen);
679-
copy[datalen] = 0;
680-
681-
_server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, copy, datalen);
682-
683-
free(copy);
659+
_handleDataEvent(data, datalen);
684660
}
685661

686662
// track index for next fragment
@@ -727,36 +703,13 @@ void AsyncWebSocketClient::_onData(void *pbuf, size_t plen) {
727703
} else if (_pinfo.opcode < WS_DISCONNECT) { // continuation or text/binary frame
728704
async_ws_log_v("WS[%" PRIu32 "]: processing data frame num=%" PRIu32 "", _clientId, _pinfo.num);
729705

730-
// ------------------------------------------------------------
731-
// Issue 384: https://github.com/ESP32Async/ESPAsyncWebServer/issues/384
732-
// Discussion: https://github.com/ESP32Async/ESPAsyncWebServer/pull/383#discussion_r2760425739
733-
// The initial design of the library was doing a backup of the byte following the data buffer because the client code
734-
// was allowed and documented to do something like data[len] = 0; to facilitate null-terminated string handling.
735-
// This was a bit hacky but it was working and it was documented, although completely incorrect because it was modifying a byte outside of the data buffer.
736-
// So to fix this behavior and to avoid breaking existing client code that may be relying on this behavior, we now have to copy the data to a temporary buffer that has an extra byte for the null terminator.
737-
// ------------------------------------------------------------
738-
uint8_t *copy = (uint8_t *)malloc(datalen + 1);
739-
740-
if (copy == NULL) {
741-
async_ws_log_e("Failed to allocate");
742-
_status = WS_DISCONNECTED;
743-
if (_client) {
744-
_client->abort();
745-
}
746-
return;
747-
}
748-
749-
memcpy(copy, data, datalen);
750-
copy[datalen] = 0;
706+
_handleDataEvent(data, datalen);
751707

752-
_server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, copy, datalen);
753708
if (_pinfo.final) {
754709
_pinfo.num = 0;
755710
} else {
756711
_pinfo.num += 1;
757712
}
758-
759-
free(copy);
760713
}
761714

762715
} else {
@@ -778,6 +731,28 @@ void AsyncWebSocketClient::_onData(void *pbuf, size_t plen) {
778731
}
779732
}
780733

734+
void AsyncWebSocketClient::_handleDataEvent(uint8_t *data, size_t len) {
735+
// ------------------------------------------------------------
736+
// Issue 384: https://github.com/ESP32Async/ESPAsyncWebServer/issues/384
737+
// Discussion: https://github.com/ESP32Async/ESPAsyncWebServer/pull/383#discussion_r2760425739
738+
// The initial design of the library was doing a backup of the byte following the data buffer because the client code
739+
// was allowed and documented to do something like data[len] = 0; to facilitate null-terminated string handling.
740+
// This was a bit hacky but it was working and it was documented, although completely incorrect because it was modifying a byte outside of the data buffer.
741+
// So to fix this behavior and to avoid breaking existing client code that may be relying on this behavior, we now have to copy the data to a temporary buffer that has an extra byte for the null terminator.
742+
// ------------------------------------------------------------
743+
std::unique_ptr<uint8_t[]> copy(new (std::nothrow) uint8_t[len + 1]());
744+
if (copy) {
745+
memcpy(copy.get(), data, len);
746+
copy[len] = 0;
747+
_server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, copy.get(), len);
748+
} else {
749+
async_ws_log_e("Failed to allocate");
750+
if (_client) {
751+
_client->abort();
752+
}
753+
}
754+
}
755+
781756
size_t AsyncWebSocketClient::printf(const char *format, ...) {
782757
va_list arg;
783758
va_start(arg, format);

src/AsyncWebSocket.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ class AsyncWebSocketClient {
236236
void _runQueue();
237237
void _clearQueue();
238238

239+
// this function is called when a text message is received, in order to copy the buffer and place a null terminator at the end of the buffer for easier handling of text messages.
240+
void _handleDataEvent(uint8_t *data, size_t len);
241+
239242
public:
240243
void *_tempObject;
241244

0 commit comments

Comments
 (0)