Skip to content
This repository was archived by the owner on Jan 21, 2025. It is now read-only.

Commit 984284d

Browse files
committed
API Compatibility with AsyncWebSocketMessageBuffer and makeBuffer()
1 parent 0d96aac commit 984284d

File tree

3 files changed

+122
-12
lines changed

3 files changed

+122
-12
lines changed

README.md

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This fork is based on https://github.com/yubox-node-org/ESPAsyncWebServer and in
1515
- Deployed in PlatformIO registry and Arduino IDE library manager
1616
- CI
1717
- Only supports ESP32
18+
- Resurrected `AsyncWebSocketMessageBuffer` and `makeBuffer()` in order to make the fork API-compatible with the original library from me-no-dev regarding WebSocket.
1819

1920
## Documentation
2021

@@ -23,13 +24,29 @@ Please look at the original libraries for more examples and documentation.
2324

2425
[https://github.com/yubox-node-org/ESPAsyncWebServer](https://github.com/yubox-node-org/ESPAsyncWebServer)
2526

26-
## Pitfalls
27+
## `AsyncWebSocketMessageBuffer` and `makeBuffer()`
2728

28-
The fork from yubox introduces some breaking API changes compared to the original library, especially regarding the use of `std::shared_ptr<std::vector<uint8_t>>` for WebSocket.
29-
Thanks to this fork, you can handle them by using `ASYNCWEBSERVER_FORK_mathieucarbou`.
29+
The fork from `yubox-node-org` introduces some breaking API changes compared to the original library, especially regarding the use of `std::shared_ptr<std::vector<uint8_t>>` for WebSocket.
3030

31-
Here is an example for serializing a Json document in a websocket message buffer directly.
32-
This code is compatible with both forks.
31+
This fork is compatible with the original library from `me-no-dev` regarding WebSocket, and wraps the optimizations done by `yubox-node-org` in the `AsyncWebSocketMessageBuffer` class.
32+
So you have the choice of which API to use.
33+
I strongly suggest to use the optimized API from `yubox-node-org` as it is much more efficient.
34+
35+
Here is an example for serializing a Json document in a websocket message buffer. This code is compatible with any forks, but not optimized:
36+
37+
```cpp
38+
void send(JsonDocument& doc) {
39+
const size_t len = measureJson(doc);
40+
41+
// original API from me-no-dev
42+
AsyncWebSocketMessageBuffer* buffer = _ws->makeBuffer(len);
43+
assert(buffer); // up to you to keep or remove this
44+
serializeJson(doc, buffer->get(), len);
45+
_ws->textAll(buffer);
46+
}
47+
```
48+
49+
Here is an example for serializing a Json document in a more optimized way, and compatible with both forks:
3350
3451
```cpp
3552
void send(JsonDocument& doc) {

src/AsyncWebSocket.cpp

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,39 @@ size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool
123123

124124

125125

126+
/*
127+
* AsyncWebSocketMessageBuffer
128+
*/
129+
130+
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer()
131+
: _buffer(std::make_shared<std::vector<uint8_t>>(0))
132+
{
133+
}
134+
135+
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t* data, size_t size)
136+
: _buffer(std::make_shared<std::vector<uint8_t>>(size))
137+
{
138+
std::memcpy(_buffer->data(), data, size);
139+
}
140+
141+
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size)
142+
: _buffer(std::make_shared<std::vector<uint8_t>>(size))
143+
{
144+
}
145+
146+
AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer()
147+
{
148+
_buffer.reset();
149+
}
150+
151+
bool AsyncWebSocketMessageBuffer::reserve(size_t size)
152+
{
153+
if (_buffer->capacity() >= size)
154+
return true;
155+
_buffer->reserve(size);
156+
return _buffer->capacity() >= size;
157+
}
158+
126159
/*
127160
* Control Frame
128161
*/
@@ -644,22 +677,28 @@ size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...)
644677
#endif
645678

646679
namespace {
647-
std::shared_ptr<std::vector<uint8_t>> makeBuffer(const uint8_t *message, size_t len)
680+
std::shared_ptr<std::vector<uint8_t>> makeSharedBuffer(const uint8_t *message, size_t len)
648681
{
649682
auto buffer = std::make_shared<std::vector<uint8_t>>(len);
650683
std::memcpy(buffer->data(), message, len);
651684
return buffer;
652685
}
653686
}
654687

688+
void AsyncWebSocketClient::text(AsyncWebSocketMessageBuffer * buffer)
689+
{
690+
text(std::move(buffer->_buffer));
691+
delete buffer;
692+
}
693+
655694
void AsyncWebSocketClient::text(std::shared_ptr<std::vector<uint8_t>> buffer)
656695
{
657696
_queueMessage(buffer);
658697
}
659698

660699
void AsyncWebSocketClient::text(const uint8_t *message, size_t len)
661700
{
662-
text(makeBuffer(message, len));
701+
text(makeSharedBuffer(message, len));
663702
}
664703

665704
void AsyncWebSocketClient::text(const char *message, size_t len)
@@ -698,14 +737,20 @@ void AsyncWebSocketClient::text(const __FlashStringHelper *data)
698737
}
699738
}
700739

740+
void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer)
741+
{
742+
binary(std::move(buffer->_buffer));
743+
delete buffer;
744+
}
745+
701746
void AsyncWebSocketClient::binary(std::shared_ptr<std::vector<uint8_t>> buffer)
702747
{
703748
_queueMessage(buffer, WS_BINARY);
704749
}
705750

706751
void AsyncWebSocketClient::binary(const uint8_t *message, size_t len)
707752
{
708-
binary(makeBuffer(message, len));
753+
binary(makeSharedBuffer(message, len));
709754
}
710755

711756
void AsyncWebSocketClient::binary(const char *message, size_t len)
@@ -853,7 +898,7 @@ void AsyncWebSocket::pingAll(const uint8_t *data, size_t len)
853898
void AsyncWebSocket::text(uint32_t id, const uint8_t *message, size_t len)
854899
{
855900
if (AsyncWebSocketClient * c = client(id))
856-
c->text(makeBuffer(message, len));
901+
c->text(makeSharedBuffer(message, len));
857902
}
858903
void AsyncWebSocket::text(uint32_t id, const char *message, size_t len)
859904
{
@@ -889,6 +934,12 @@ void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper *data)
889934
}
890935
}
891936

937+
void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer)
938+
{
939+
textAll(std::move(buffer->_buffer));
940+
delete buffer;
941+
}
942+
892943
void AsyncWebSocket::textAll(std::shared_ptr<std::vector<uint8_t>> buffer)
893944
{
894945
for (auto &c : _clients)
@@ -897,7 +948,7 @@ void AsyncWebSocket::textAll(std::shared_ptr<std::vector<uint8_t>> buffer)
897948
}
898949
void AsyncWebSocket::textAll(const uint8_t *message, size_t len)
899950
{
900-
textAll(makeBuffer(message, len));
951+
textAll(makeSharedBuffer(message, len));
901952
}
902953
void AsyncWebSocket::textAll(const char * message, size_t len)
903954
{
@@ -935,7 +986,7 @@ void AsyncWebSocket::textAll(const __FlashStringHelper *data)
935986
void AsyncWebSocket::binary(uint32_t id, const uint8_t *message, size_t len)
936987
{
937988
if (AsyncWebSocketClient *c = client(id))
938-
c->binary(makeBuffer(message, len));
989+
c->binary(makeSharedBuffer(message, len));
939990
}
940991
void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len)
941992
{
@@ -961,6 +1012,12 @@ void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper *data, size_t
9611012
}
9621013
}
9631014

1015+
void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
1016+
{
1017+
binaryAll(std::move(buffer->_buffer));
1018+
delete buffer;
1019+
}
1020+
9641021
void AsyncWebSocket::binaryAll(std::shared_ptr<std::vector<uint8_t>> buffer)
9651022
{
9661023
for (auto &c : _clients)
@@ -970,7 +1027,7 @@ void AsyncWebSocket::binaryAll(std::shared_ptr<std::vector<uint8_t>> buffer)
9701027

9711028
void AsyncWebSocket::binaryAll(const uint8_t *message, size_t len)
9721029
{
973-
binaryAll(makeBuffer(message, len));
1030+
binaryAll(makeSharedBuffer(message, len));
9741031
}
9751032

9761033
void AsyncWebSocket::binaryAll(const char *message, size_t len)
@@ -1141,6 +1198,16 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request)
11411198
request->send(response);
11421199
}
11431200

1201+
AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size)
1202+
{
1203+
return new AsyncWebSocketMessageBuffer(size);
1204+
}
1205+
1206+
AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size)
1207+
{
1208+
return new AsyncWebSocketMessageBuffer(data, size);
1209+
}
1210+
11441211
/*
11451212
* Response to Web Socket request - sends the authorization and detaches the TCP Client from the web server
11461213
* Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480

src/AsyncWebSocket.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ typedef enum { WS_CONTINUATION, WS_TEXT, WS_BINARY, WS_DISCONNECT = 0x08, WS_PIN
8888
typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
8989
typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
9090

91+
class AsyncWebSocketMessageBuffer {
92+
friend AsyncWebSocket;
93+
friend AsyncWebSocketClient;
94+
95+
private:
96+
std::shared_ptr<std::vector<uint8_t>> _buffer;
97+
98+
public:
99+
AsyncWebSocketMessageBuffer();
100+
AsyncWebSocketMessageBuffer(size_t size);
101+
AsyncWebSocketMessageBuffer(uint8_t* data, size_t size);
102+
~AsyncWebSocketMessageBuffer();
103+
bool reserve(size_t size);
104+
uint8_t* get() { return _buffer->data(); }
105+
size_t length() const { return _buffer->size(); }
106+
};
107+
91108
class AsyncWebSocketMessage
92109
{
93110
private:
@@ -180,13 +197,15 @@ class AsyncWebSocketClient {
180197
void text(const char *message);
181198
void text(const String &message);
182199
void text(const __FlashStringHelper *message);
200+
void text(AsyncWebSocketMessageBuffer *buffer);
183201

184202
void binary(std::shared_ptr<std::vector<uint8_t>> buffer);
185203
void binary(const uint8_t *message, size_t len);
186204
void binary(const char * message, size_t len);
187205
void binary(const char * message);
188206
void binary(const String &message);
189207
void binary(const __FlashStringHelper *message, size_t len);
208+
void binary(AsyncWebSocketMessageBuffer *buffer);
190209

191210
bool canSend() const;
192211

@@ -245,6 +264,7 @@ class AsyncWebSocket: public AsyncWebHandler {
245264
void textAll(const char * message);
246265
void textAll(const String &message);
247266
void textAll(const __FlashStringHelper *message); // need to convert
267+
void textAll(AsyncWebSocketMessageBuffer *buffer);
248268

249269
void binary(uint32_t id, const uint8_t *message, size_t len);
250270
void binary(uint32_t id, const char *message, size_t len);
@@ -258,6 +278,7 @@ class AsyncWebSocket: public AsyncWebHandler {
258278
void binaryAll(const char *message);
259279
void binaryAll(const String &message);
260280
void binaryAll(const __FlashStringHelper *message, size_t len);
281+
void binaryAll(AsyncWebSocketMessageBuffer *buffer);
261282

262283
size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
263284
size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
@@ -283,6 +304,11 @@ class AsyncWebSocket: public AsyncWebHandler {
283304
virtual bool canHandle(AsyncWebServerRequest *request) override final;
284305
virtual void handleRequest(AsyncWebServerRequest *request) override final;
285306

307+
308+
// messagebuffer functions/objects.
309+
AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
310+
AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
311+
286312
const std::list<AsyncWebSocketClient> &getClients() const { return _clients; }
287313
};
288314

0 commit comments

Comments
 (0)