forked from me-no-dev/ESPAsyncWebServer
Prevent Buffer Overflow and Added FlashStringHelper for text and binary (#26)
* Prevent buffer overflow on received data * pass to 7 char to avoid save to flash by SDK * return _contentLength, avoid array reparse to know len * Added FlashStringHelper for text and binary * Added FlashStringHelper also to AsyncWebSocketClient * Added PROGMEM doc * Corrected binary was sending PSTR as text, addded len * Server calls client method and code as asked @me-no-dev * server calls client method and code as asked by @me-no-dev * Changed Code presentation
This commit is contained in:
44
README.md
44
README.md
@@ -464,36 +464,48 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
|
|
||||||
### Methods for sending data to a socket client
|
### Methods for sending data to a socket client
|
||||||
```cpp
|
```cpp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Server methods
|
//Server methods
|
||||||
AsyncWebSocket ws("/ws");
|
AsyncWebSocket ws("/ws");
|
||||||
//printf to a client
|
//printf to a client
|
||||||
ws.printf([client id], [arguments...])
|
ws.printf([client id], [arguments...]);
|
||||||
//printf to all clients
|
//printf to all clients
|
||||||
ws.printfAll([arguments...])
|
ws.printfAll([arguments...]);
|
||||||
//send text to a client
|
//send text to a client
|
||||||
ws.text([client id], [(char*)text])
|
ws.text([client id], [(char*)text]);
|
||||||
ws.text([client id], [text], [len])
|
ws.text([client id], [text], [len]);
|
||||||
|
const char flash_text[] PROGMEM = "Text to send"
|
||||||
|
ws.text([client id], [PSTR("text")]);
|
||||||
|
ws.text([client id], [FPSTR(flash_text)]);
|
||||||
//send text to all clients
|
//send text to all clients
|
||||||
ws.textAll([(char*text])
|
ws.textAll([(char*text]);
|
||||||
ws.textAll([text], [len])
|
ws.textAll([text], [len]);
|
||||||
//send binary to a client
|
//send binary to a client
|
||||||
ws.binary([client id], [(char*)binary])
|
ws.binary([client id], [(char*)binary]);
|
||||||
ws.binary([client id], [binary], [len])
|
ws.binary([client id], [binary], [len]);
|
||||||
|
const uint8_t flash_binary[] PROGMEM = { 0x01, 0x02, 0x03, 0x04 };
|
||||||
|
ws.binary([client id], [flash_binary], [len]);
|
||||||
//send binary to all clients
|
//send binary to all clients
|
||||||
ws.binaryAll([(char*binary])
|
ws.binaryAll([(char*binary]);
|
||||||
ws.binaryAll([binary], [len])
|
ws.binaryAll([binary], [len]);
|
||||||
|
|
||||||
//client methods
|
//client methods
|
||||||
AsyncWebSocketClient * client;
|
AsyncWebSocketClient * client;
|
||||||
//printf to a client
|
//printf to a client
|
||||||
client->printf([arguments...])
|
client->printf([arguments...]);
|
||||||
//send text to a client
|
//send text to a client
|
||||||
client->text([(char*)text])
|
client->text([(char*)text]);
|
||||||
client->text([text], [len])
|
client->text([text], [len]);
|
||||||
|
const char flash_text[] PROGMEM = "Text to send";
|
||||||
|
client->text([PSTR("text")]);
|
||||||
|
client->text([FPSTR(flash_text)]);
|
||||||
//send binary to a client
|
//send binary to a client
|
||||||
client->binary([(char*)binary])
|
client->binary([(char*)binary]);
|
||||||
client->binary([binary], [len])
|
client->binary([binary], [len]);
|
||||||
|
const uint8_t flash_binary[] PROGMEM = { 0x01, 0x02, 0x03, 0x04 };
|
||||||
|
client->binary([flash_binary], [len]);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@@ -125,18 +125,22 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:"");
|
os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:"");
|
||||||
} else if(type == WS_EVT_DATA){
|
} else if(type == WS_EVT_DATA){
|
||||||
AwsFrameInfo * info = (AwsFrameInfo*)arg;
|
AwsFrameInfo * info = (AwsFrameInfo*)arg;
|
||||||
|
String msg = "";
|
||||||
if(info->final && info->index == 0 && info->len == len){
|
if(info->final && info->index == 0 && info->len == len){
|
||||||
//the whole message is in a single frame and we got all of it's data
|
//the whole message is in a single frame and we got all of it's data
|
||||||
os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len);
|
os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len);
|
||||||
if(info->opcode == WS_TEXT){
|
if(info->opcode == WS_TEXT){
|
||||||
data[len] = 0;
|
for(size_t i=0; i < info->len; i++) {
|
||||||
os_printf("%s\n", (char*)data);
|
msg += (char) data[i];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for(size_t i=0; i < info->len; i++){
|
char buff[3];
|
||||||
os_printf("%02x ", data[i]);
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
sprintf(buff, "%02x ", (uint8_t) data[i]);
|
||||||
|
msg += buff ;
|
||||||
}
|
}
|
||||||
os_printf("\n");
|
|
||||||
}
|
}
|
||||||
|
os_printf("%s\n",msg.c_str());
|
||||||
if(info->opcode == WS_TEXT)
|
if(info->opcode == WS_TEXT)
|
||||||
client->text("I got your text message");
|
client->text("I got your text message");
|
||||||
else
|
else
|
||||||
@@ -150,15 +154,19 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
|
os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
|
||||||
if(info->message_opcode == WS_TEXT){
|
if(info->opcode == WS_TEXT){
|
||||||
data[len] = 0;
|
for(size_t i=0; i < info->len; i++) {
|
||||||
os_printf("%s\n", (char*)data);
|
msg += (char) data[i];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for(size_t i=0; i < len; i++){
|
char buff[3];
|
||||||
os_printf("%02x ", data[i]);
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
sprintf(buff, "%02x ", (uint8_t) data[i]);
|
||||||
|
msg += buff ;
|
||||||
}
|
}
|
||||||
os_printf("\n");
|
|
||||||
}
|
}
|
||||||
|
os_printf("%s\n",msg.c_str());
|
||||||
|
|
||||||
|
|
||||||
if((info->index + len) == info->len){
|
if((info->index + len) == info->len){
|
||||||
os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
|
os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
|
||||||
@@ -174,8 +182,8 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ssid = "**********";
|
const char* ssid = "*******";
|
||||||
const char* password = "************";
|
const char* password = "*******";
|
||||||
const char* http_username = "admin";
|
const char* http_username = "admin";
|
||||||
const char* http_password = "admin";
|
const char* http_password = "admin";
|
||||||
|
|
||||||
|
@@ -128,18 +128,24 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:"");
|
os_printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:"");
|
||||||
} else if(type == WS_EVT_DATA){
|
} else if(type == WS_EVT_DATA){
|
||||||
AwsFrameInfo * info = (AwsFrameInfo*)arg;
|
AwsFrameInfo * info = (AwsFrameInfo*)arg;
|
||||||
|
String msg = "";
|
||||||
if(info->final && info->index == 0 && info->len == len){
|
if(info->final && info->index == 0 && info->len == len){
|
||||||
//the whole message is in a single frame and we got all of it's data
|
//the whole message is in a single frame and we got all of it's data
|
||||||
os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len);
|
os_printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len);
|
||||||
|
|
||||||
if(info->opcode == WS_TEXT){
|
if(info->opcode == WS_TEXT){
|
||||||
data[len] = 0;
|
for(size_t i=0; i < info->len; i++) {
|
||||||
os_printf("%s\n", (char*)data);
|
msg += (char) data[i];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for(size_t i=0; i < info->len; i++){
|
char buff[3];
|
||||||
os_printf("%02x ", data[i]);
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
sprintf(buff, "%02x ", (uint8_t) data[i]);
|
||||||
|
msg += buff ;
|
||||||
}
|
}
|
||||||
os_printf("\n");
|
|
||||||
}
|
}
|
||||||
|
os_printf("%s\n",msg.c_str());
|
||||||
|
|
||||||
if(info->opcode == WS_TEXT)
|
if(info->opcode == WS_TEXT)
|
||||||
client->text("I got your text message");
|
client->text("I got your text message");
|
||||||
else
|
else
|
||||||
@@ -153,15 +159,19 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
|
os_printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
|
||||||
if(info->message_opcode == WS_TEXT){
|
|
||||||
data[len] = 0;
|
if(info->opcode == WS_TEXT){
|
||||||
os_printf("%s\n", (char*)data);
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
msg += (char) data[i];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for(size_t i=0; i < len; i++){
|
char buff[3];
|
||||||
os_printf("%02x ", data[i]);
|
for(size_t i=0; i < info->len; i++) {
|
||||||
|
sprintf(buff, "%02x ", (uint8_t) data[i]);
|
||||||
|
msg += buff ;
|
||||||
}
|
}
|
||||||
os_printf("\n");
|
|
||||||
}
|
}
|
||||||
|
os_printf("%s\n",msg.c_str());
|
||||||
|
|
||||||
if((info->index + len) == info->len){
|
if((info->index + len) == info->len){
|
||||||
os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
|
os_printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
|
||||||
@@ -178,8 +188,8 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* ssid = "**********";
|
const char* ssid = "*******";
|
||||||
const char* password = "************";
|
const char* password = "*******";
|
||||||
const char* http_username = "admin";
|
const char* http_username = "admin";
|
||||||
const char* http_password = "admin";
|
const char* http_password = "admin";
|
||||||
|
|
||||||
|
@@ -66,9 +66,10 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
|||||||
~AsyncJsonResponse() {}
|
~AsyncJsonResponse() {}
|
||||||
JsonVariant & getRoot() { return _root; }
|
JsonVariant & getRoot() { return _root; }
|
||||||
bool _sourceValid() { return _isValid; }
|
bool _sourceValid() { return _isValid; }
|
||||||
void setLength() {
|
size_t setLength() {
|
||||||
_contentLength = _root.measureLength();
|
_contentLength = _root.measureLength();
|
||||||
if (_contentLength) { _isValid = true; }
|
if (_contentLength) { _isValid = true; }
|
||||||
|
return _contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t _fillBuffer(uint8_t *data, size_t len){
|
size_t _fillBuffer(uint8_t *data, size_t len){
|
||||||
|
@@ -504,6 +504,21 @@ void AsyncWebSocketClient::text(char * message){
|
|||||||
void AsyncWebSocketClient::text(String &message){
|
void AsyncWebSocketClient::text(String &message){
|
||||||
text(message.c_str(), message.length());
|
text(message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
|
void AsyncWebSocketClient::text(const __FlashStringHelper *data){
|
||||||
|
PGM_P p = reinterpret_cast<PGM_P>(data);
|
||||||
|
size_t n = 0;
|
||||||
|
while (1) {
|
||||||
|
if (pgm_read_byte(p+n) == 0) break;
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
char * message = (char*) malloc(n+1);
|
||||||
|
if(message){
|
||||||
|
for(size_t b=0; b<n; b++)
|
||||||
|
message[b] = pgm_read_byte(p++);
|
||||||
|
message[n] = 0;
|
||||||
|
text(message, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AsyncWebSocketClient::binary(const char * message, size_t len){
|
void AsyncWebSocketClient::binary(const char * message, size_t len){
|
||||||
_queueMessage(new AsyncWebSocketBasicMessage(message, len, WS_BINARY));
|
_queueMessage(new AsyncWebSocketBasicMessage(message, len, WS_BINARY));
|
||||||
@@ -520,6 +535,15 @@ void AsyncWebSocketClient::binary(char * message){
|
|||||||
void AsyncWebSocketClient::binary(String &message){
|
void AsyncWebSocketClient::binary(String &message){
|
||||||
binary(message.c_str(), message.length());
|
binary(message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
|
void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len){
|
||||||
|
PGM_P p = reinterpret_cast<PGM_P>(data);
|
||||||
|
char * message = (char*) malloc(len);
|
||||||
|
if(message){
|
||||||
|
for(size_t b=0; b<len; b++)
|
||||||
|
message[b] = pgm_read_byte(p++);
|
||||||
|
binary(message, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IPAddress AsyncWebSocketClient::remoteIP() {
|
IPAddress AsyncWebSocketClient::remoteIP() {
|
||||||
if(!_client) {
|
if(!_client) {
|
||||||
@@ -728,6 +752,11 @@ void AsyncWebSocket::text(uint32_t id, char * message){
|
|||||||
void AsyncWebSocket::text(uint32_t id, String &message){
|
void AsyncWebSocket::text(uint32_t id, String &message){
|
||||||
text(id, message.c_str(), message.length());
|
text(id, message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
|
void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper *message){
|
||||||
|
AsyncWebSocketClient * c = client(id);
|
||||||
|
if(c != NULL)
|
||||||
|
c->text(message);
|
||||||
|
}
|
||||||
void AsyncWebSocket::textAll(const char * message){
|
void AsyncWebSocket::textAll(const char * message){
|
||||||
textAll(message, strlen(message));
|
textAll(message, strlen(message));
|
||||||
}
|
}
|
||||||
@@ -740,6 +769,14 @@ void AsyncWebSocket::textAll(char * message){
|
|||||||
void AsyncWebSocket::textAll(String &message){
|
void AsyncWebSocket::textAll(String &message){
|
||||||
textAll(message.c_str(), message.length());
|
textAll(message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
|
void AsyncWebSocket::textAll(const __FlashStringHelper *message){
|
||||||
|
AsyncWebSocketClient * c = _clients;
|
||||||
|
while(c != NULL){
|
||||||
|
if(c->status() == WS_CONNECTED)
|
||||||
|
c->text(message);
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
void AsyncWebSocket::binary(uint32_t id, const char * message){
|
void AsyncWebSocket::binary(uint32_t id, const char * message){
|
||||||
binary(id, message, strlen(message));
|
binary(id, message, strlen(message));
|
||||||
}
|
}
|
||||||
@@ -752,6 +789,11 @@ void AsyncWebSocket::binary(uint32_t id, char * message){
|
|||||||
void AsyncWebSocket::binary(uint32_t id, String &message){
|
void AsyncWebSocket::binary(uint32_t id, String &message){
|
||||||
binary(id, message.c_str(), message.length());
|
binary(id, message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
|
void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper *message, size_t len){
|
||||||
|
AsyncWebSocketClient * c = client(id);
|
||||||
|
if(c != NULL)
|
||||||
|
c-> binary(message, len);
|
||||||
|
}
|
||||||
void AsyncWebSocket::binaryAll(const char * message){
|
void AsyncWebSocket::binaryAll(const char * message){
|
||||||
binaryAll(message, strlen(message));
|
binaryAll(message, strlen(message));
|
||||||
}
|
}
|
||||||
@@ -764,6 +806,14 @@ void AsyncWebSocket::binaryAll(char * message){
|
|||||||
void AsyncWebSocket::binaryAll(String &message){
|
void AsyncWebSocket::binaryAll(String &message){
|
||||||
binaryAll(message.c_str(), message.length());
|
binaryAll(message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
|
void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){
|
||||||
|
AsyncWebSocketClient * c = _clients;
|
||||||
|
while(c != NULL){
|
||||||
|
if(c->status() == WS_CONNECTED)
|
||||||
|
c-> binary(message, len);
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char * WS_STR_CONNECTION = "Connection";
|
const char * WS_STR_CONNECTION = "Connection";
|
||||||
const char * WS_STR_UPGRADE = "Upgrade";
|
const char * WS_STR_UPGRADE = "Upgrade";
|
||||||
|
@@ -106,12 +106,14 @@ class AsyncWebSocketClient {
|
|||||||
void text(uint8_t * message, size_t len);
|
void text(uint8_t * message, size_t len);
|
||||||
void text(char * message);
|
void text(char * message);
|
||||||
void text(String &message);
|
void text(String &message);
|
||||||
|
void text(const __FlashStringHelper *data);
|
||||||
|
|
||||||
void binary(const char * message, size_t len);
|
void binary(const char * message, size_t len);
|
||||||
void binary(const char * message);
|
void binary(const char * message);
|
||||||
void binary(uint8_t * message, size_t len);
|
void binary(uint8_t * message, size_t len);
|
||||||
void binary(char * message);
|
void binary(char * message);
|
||||||
void binary(String &message);
|
void binary(String &message);
|
||||||
|
void binary(const __FlashStringHelper *data, size_t len);
|
||||||
|
|
||||||
//system callbacks (do not call)
|
//system callbacks (do not call)
|
||||||
void _onAck(size_t len, uint32_t time);
|
void _onAck(size_t len, uint32_t time);
|
||||||
@@ -151,24 +153,28 @@ class AsyncWebSocket: public AsyncWebHandler {
|
|||||||
void text(uint32_t id, uint8_t * message, size_t len);
|
void text(uint32_t id, uint8_t * message, size_t len);
|
||||||
void text(uint32_t id, char * message);
|
void text(uint32_t id, char * message);
|
||||||
void text(uint32_t id, String &message);
|
void text(uint32_t id, String &message);
|
||||||
|
void text(uint32_t id, const __FlashStringHelper *message);
|
||||||
|
|
||||||
void textAll(const char * message, size_t len);
|
void textAll(const char * message, size_t len);
|
||||||
void textAll(const char * message);
|
void textAll(const char * message);
|
||||||
void textAll(uint8_t * message, size_t len);
|
void textAll(uint8_t * message, size_t len);
|
||||||
void textAll(char * message);
|
void textAll(char * message);
|
||||||
void textAll(String &message);
|
void textAll(String &message);
|
||||||
|
void textAll(const __FlashStringHelper *message);
|
||||||
|
|
||||||
void binary(uint32_t id, const char * message, size_t len);
|
void binary(uint32_t id, const char * message, size_t len);
|
||||||
void binary(uint32_t id, const char * message);
|
void binary(uint32_t id, const char * message);
|
||||||
void binary(uint32_t id, uint8_t * message, size_t len);
|
void binary(uint32_t id, uint8_t * message, size_t len);
|
||||||
void binary(uint32_t id, char * message);
|
void binary(uint32_t id, char * message);
|
||||||
void binary(uint32_t id, String &message);
|
void binary(uint32_t id, String &message);
|
||||||
|
void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
|
||||||
|
|
||||||
void binaryAll(const char * message, size_t len);
|
void binaryAll(const char * message, size_t len);
|
||||||
void binaryAll(const char * message);
|
void binaryAll(const char * message);
|
||||||
void binaryAll(uint8_t * message, size_t len);
|
void binaryAll(uint8_t * message, size_t len);
|
||||||
void binaryAll(char * message);
|
void binaryAll(char * message);
|
||||||
void binaryAll(String &message);
|
void binaryAll(String &message);
|
||||||
|
void binaryAll(const __FlashStringHelper *message, size_t len);
|
||||||
|
|
||||||
void message(uint32_t id, AsyncWebSocketMessage *message);
|
void message(uint32_t id, AsyncWebSocketMessage *message);
|
||||||
void messageAll(AsyncWebSocketMessage *message);
|
void messageAll(AsyncWebSocketMessage *message);
|
||||||
|
Reference in New Issue
Block a user