mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
add module license
This commit is contained in:
@@ -89,8 +89,8 @@ typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
|
||||
typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
|
||||
|
||||
class AsyncWebSocketMessageBuffer {
|
||||
friend AsyncWebSocket;
|
||||
friend AsyncWebSocketClient;
|
||||
friend AsyncWebSocket;
|
||||
friend AsyncWebSocketClient;
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::vector<uint8_t>> _buffer;
|
||||
@@ -98,114 +98,165 @@ class AsyncWebSocketMessageBuffer {
|
||||
public:
|
||||
AsyncWebSocketMessageBuffer();
|
||||
AsyncWebSocketMessageBuffer(size_t size);
|
||||
AsyncWebSocketMessageBuffer(uint8_t* data, size_t size);
|
||||
AsyncWebSocketMessageBuffer(uint8_t * data, size_t size);
|
||||
~AsyncWebSocketMessageBuffer();
|
||||
bool reserve(size_t size);
|
||||
uint8_t* get() { return _buffer->data(); }
|
||||
size_t length() const { return _buffer->size(); }
|
||||
bool reserve(size_t size);
|
||||
uint8_t * get() {
|
||||
return _buffer->data();
|
||||
}
|
||||
size_t length() const {
|
||||
return _buffer->size();
|
||||
}
|
||||
};
|
||||
|
||||
class AsyncWebSocketMessage
|
||||
{
|
||||
private:
|
||||
class AsyncWebSocketMessage {
|
||||
private:
|
||||
std::shared_ptr<std::vector<uint8_t>> _WSbuffer;
|
||||
uint8_t _opcode{WS_TEXT};
|
||||
bool _mask{false};
|
||||
AwsMessageStatus _status{WS_MSG_ERROR};
|
||||
size_t _sent{};
|
||||
size_t _ack{};
|
||||
size_t _acked{};
|
||||
uint8_t _opcode{WS_TEXT};
|
||||
bool _mask{false};
|
||||
AwsMessageStatus _status{WS_MSG_ERROR};
|
||||
size_t _sent{};
|
||||
size_t _ack{};
|
||||
size_t _acked{};
|
||||
|
||||
public:
|
||||
AsyncWebSocketMessage(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode=WS_TEXT, bool mask=false);
|
||||
public:
|
||||
AsyncWebSocketMessage(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode = WS_TEXT, bool mask = false);
|
||||
|
||||
bool finished() const { return _status != WS_MSG_SENDING; }
|
||||
bool betweenFrames() const { return _acked == _ack; }
|
||||
bool finished() const {
|
||||
return _status != WS_MSG_SENDING;
|
||||
}
|
||||
bool betweenFrames() const {
|
||||
return _acked == _ack;
|
||||
}
|
||||
|
||||
void ack(size_t len, uint32_t time);
|
||||
size_t send(AsyncClient *client);
|
||||
void ack(size_t len, uint32_t time);
|
||||
size_t send(AsyncClient * client);
|
||||
};
|
||||
|
||||
class AsyncWebSocketClient {
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
AsyncWebSocket *_server;
|
||||
uint32_t _clientId;
|
||||
AwsClientStatus _status;
|
||||
AsyncClient * _client;
|
||||
AsyncWebSocket * _server;
|
||||
uint32_t _clientId;
|
||||
AwsClientStatus _status;
|
||||
|
||||
AsyncWebLock _lock;
|
||||
|
||||
std::deque<AsyncWebSocketControl> _controlQueue;
|
||||
std::deque<AsyncWebSocketMessage> _messageQueue;
|
||||
bool closeWhenFull = true;
|
||||
|
||||
uint8_t _pstate;
|
||||
uint8_t _pstate;
|
||||
AwsFrameInfo _pinfo;
|
||||
|
||||
uint32_t _lastMessageTime;
|
||||
uint32_t _keepAlivePeriod;
|
||||
|
||||
void _queueControl(uint8_t opcode, const uint8_t *data=NULL, size_t len=0, bool mask=false);
|
||||
void _queueMessage(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode=WS_TEXT, bool mask=false);
|
||||
void _queueControl(uint8_t opcode, const uint8_t * data = NULL, size_t len = 0, bool mask = false);
|
||||
void _queueMessage(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode = WS_TEXT, bool mask = false);
|
||||
void _runQueue();
|
||||
void _clearQueue();
|
||||
|
||||
public:
|
||||
void *_tempObject;
|
||||
void * _tempObject;
|
||||
|
||||
AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server);
|
||||
AsyncWebSocketClient(AsyncWebServerRequest * request, AsyncWebSocket * server);
|
||||
~AsyncWebSocketClient();
|
||||
|
||||
//client id increments for the given server
|
||||
uint32_t id() const { return _clientId; }
|
||||
AwsClientStatus status() const { return _status; }
|
||||
AsyncClient* client() { return _client; }
|
||||
const AsyncClient* client() const { return _client; }
|
||||
AsyncWebSocket *server(){ return _server; }
|
||||
const AsyncWebSocket *server() const { return _server; }
|
||||
AwsFrameInfo const &pinfo() const { return _pinfo; }
|
||||
uint32_t id() const {
|
||||
return _clientId;
|
||||
}
|
||||
AwsClientStatus status() const {
|
||||
return _status;
|
||||
}
|
||||
AsyncClient * client() {
|
||||
return _client;
|
||||
}
|
||||
const AsyncClient * client() const {
|
||||
return _client;
|
||||
}
|
||||
AsyncWebSocket * server() {
|
||||
return _server;
|
||||
}
|
||||
const AsyncWebSocket * server() const {
|
||||
return _server;
|
||||
}
|
||||
AwsFrameInfo const & pinfo() const {
|
||||
return _pinfo;
|
||||
}
|
||||
|
||||
// - If "true" (default), the connection will be closed if the message queue is full.
|
||||
// This is the default behavior in yubox-node-org, which is not silently discarding messages but instead closes the connection.
|
||||
// The big issue with this behavior is that is can cause the UI to automatically re-create a new WS connection, which can be filled again,
|
||||
// and so on, causing a resource exhaustion.
|
||||
//
|
||||
// - If "false", the incoming message will be discarded if the queue is full.
|
||||
// This is the default behavior in the original ESPAsyncWebServer library from me-no-dev.
|
||||
// This behavior allows the best performance at the expense of unreliable message delivery in case the queue is full (some messages may be lost).
|
||||
//
|
||||
// - In any case, when the queue is full, a message is logged.
|
||||
// - IT is recommended to use the methods queueIsFull(), availableForWriteAll(), availableForWrite(clientId) to check if the queue is full before sending a message.
|
||||
//
|
||||
// Usage:
|
||||
// - can be set in the onEvent listener when connecting (event type is: WS_EVT_CONNECT)
|
||||
//
|
||||
// Use cases:,
|
||||
// - if using websocket to send logging messages, maybe some loss is acceptable.
|
||||
// - But if using websocket to send UI update messages, maybe the connection should be closed and the UI redrawn.
|
||||
void setCloseClientOnQueueFull(bool close) {
|
||||
closeWhenFull = close;
|
||||
}
|
||||
bool willCloseClientOnQueueFull() const {
|
||||
return closeWhenFull;
|
||||
}
|
||||
|
||||
IPAddress remoteIP() const;
|
||||
uint16_t remotePort() const;
|
||||
|
||||
bool shouldBeDeleted() const { return !_client; }
|
||||
bool shouldBeDeleted() const {
|
||||
return !_client;
|
||||
}
|
||||
|
||||
//control frames
|
||||
void close(uint16_t code=0, const char * message=NULL);
|
||||
void ping(const uint8_t *data=NULL, size_t len=0);
|
||||
void close(uint16_t code = 0, const char * message = NULL);
|
||||
void ping(const uint8_t * data = NULL, size_t len = 0);
|
||||
|
||||
//set auto-ping period in seconds. disabled if zero (default)
|
||||
void keepAlivePeriod(uint16_t seconds){
|
||||
_keepAlivePeriod = seconds * 1000;
|
||||
void keepAlivePeriod(uint16_t seconds) {
|
||||
_keepAlivePeriod = seconds * 1000;
|
||||
}
|
||||
uint16_t keepAlivePeriod(){
|
||||
return (uint16_t)(_keepAlivePeriod / 1000);
|
||||
uint16_t keepAlivePeriod() {
|
||||
return (uint16_t)(_keepAlivePeriod / 1000);
|
||||
}
|
||||
|
||||
//data packets
|
||||
void message(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode=WS_TEXT, bool mask=false) { _queueMessage(buffer, opcode, mask); }
|
||||
bool queueIsFull() const;
|
||||
void message(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode = WS_TEXT, bool mask = false) {
|
||||
_queueMessage(buffer, opcode, mask);
|
||||
}
|
||||
bool queueIsFull() const;
|
||||
size_t queueLen() const;
|
||||
|
||||
size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
size_t printf(const char * format, ...) __attribute__((format(printf, 2, 3)));
|
||||
#ifndef ESP32
|
||||
size_t printf_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
size_t printf_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
|
||||
#endif
|
||||
|
||||
void text(std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
void text(const uint8_t *message, size_t len);
|
||||
void text(const char *message, size_t len);
|
||||
void text(const char *message);
|
||||
void text(const String &message);
|
||||
void text(const __FlashStringHelper *message);
|
||||
void text(AsyncWebSocketMessageBuffer *buffer);
|
||||
void text(const uint8_t * message, size_t len);
|
||||
void text(const char * message, size_t len);
|
||||
void text(const char * message);
|
||||
void text(const String & message);
|
||||
void text(const __FlashStringHelper * message);
|
||||
void text(AsyncWebSocketMessageBuffer * buffer);
|
||||
|
||||
void binary(std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
void binary(const uint8_t *message, size_t len);
|
||||
void binary(const uint8_t * message, size_t len);
|
||||
void binary(const char * message, size_t len);
|
||||
void binary(const char * message);
|
||||
void binary(const String &message);
|
||||
void binary(const __FlashStringHelper *message, size_t len);
|
||||
void binary(AsyncWebSocketMessageBuffer *buffer);
|
||||
void binary(const String & message);
|
||||
void binary(const __FlashStringHelper * message, size_t len);
|
||||
void binary(AsyncWebSocketMessageBuffer * buffer);
|
||||
|
||||
bool canSend() const;
|
||||
|
||||
@@ -215,114 +266,133 @@ class AsyncWebSocketClient {
|
||||
void _onPoll();
|
||||
void _onTimeout(uint32_t time);
|
||||
void _onDisconnect();
|
||||
void _onData(void *pbuf, size_t plen);
|
||||
void _onData(void * pbuf, size_t plen);
|
||||
};
|
||||
|
||||
typedef std::function<bool(AsyncWebServerRequest *request)> AwsHandshakeHandler;
|
||||
typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)> AwsEventHandler;
|
||||
typedef std::function<bool(AsyncWebServerRequest * request)> AwsHandshakeHandler;
|
||||
typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len)> AwsEventHandler;
|
||||
|
||||
//WebServer Handler implementation that plays the role of a socket server
|
||||
class AsyncWebSocket: public AsyncWebHandler {
|
||||
class AsyncWebSocket : public AsyncWebHandler {
|
||||
private:
|
||||
String _url;
|
||||
String _url;
|
||||
std::list<AsyncWebSocketClient> _clients;
|
||||
uint32_t _cNextId;
|
||||
AwsEventHandler _eventHandler;
|
||||
AwsHandshakeHandler _handshakeHandler;
|
||||
bool _enabled;
|
||||
AsyncWebLock _lock;
|
||||
uint32_t _cNextId;
|
||||
AwsEventHandler _eventHandler;
|
||||
AwsHandshakeHandler _handshakeHandler;
|
||||
bool _enabled;
|
||||
AsyncWebLock _lock;
|
||||
|
||||
public:
|
||||
AsyncWebSocket(const String& url);
|
||||
AsyncWebSocket(const String & url);
|
||||
~AsyncWebSocket();
|
||||
const char * url() const { return _url.c_str(); }
|
||||
void enable(bool e){ _enabled = e; }
|
||||
bool enabled() const { return _enabled; }
|
||||
const char * url() const {
|
||||
return _url.c_str();
|
||||
}
|
||||
void enable(bool e) {
|
||||
_enabled = e;
|
||||
}
|
||||
bool enabled() const {
|
||||
return _enabled;
|
||||
}
|
||||
bool availableForWriteAll();
|
||||
bool availableForWrite(uint32_t id);
|
||||
|
||||
size_t count() const;
|
||||
size_t count() const;
|
||||
AsyncWebSocketClient * client(uint32_t id);
|
||||
bool hasClient(uint32_t id){ return client(id) != NULL; }
|
||||
bool hasClient(uint32_t id) {
|
||||
return client(id) != NULL;
|
||||
}
|
||||
|
||||
void close(uint32_t id, uint16_t code=0, const char * message=NULL);
|
||||
void closeAll(uint16_t code=0, const char * message=NULL);
|
||||
void close(uint32_t id, uint16_t code = 0, const char * message = NULL);
|
||||
void closeAll(uint16_t code = 0, const char * message = NULL);
|
||||
void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
|
||||
|
||||
void ping(uint32_t id, const uint8_t *data=NULL, size_t len=0);
|
||||
void pingAll(const uint8_t *data=NULL, size_t len=0); // done
|
||||
void ping(uint32_t id, const uint8_t * data = NULL, size_t len = 0);
|
||||
void pingAll(const uint8_t * data = NULL, size_t len = 0); // done
|
||||
|
||||
void text(uint32_t id, const uint8_t * message, size_t len);
|
||||
void text(uint32_t id, const char *message, size_t len);
|
||||
void text(uint32_t id, const char *message);
|
||||
void text(uint32_t id, const String &message);
|
||||
void text(uint32_t id, const __FlashStringHelper *message);
|
||||
void text(uint32_t id, const char * message, size_t len);
|
||||
void text(uint32_t id, const char * message);
|
||||
void text(uint32_t id, const String & message);
|
||||
void text(uint32_t id, const __FlashStringHelper * message);
|
||||
void text(uint32_t id, AsyncWebSocketMessageBuffer * buffer);
|
||||
void text(uint32_t id, std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
|
||||
void textAll(std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
void textAll(const uint8_t *message, size_t len);
|
||||
void textAll(const uint8_t * message, size_t len);
|
||||
void textAll(const char * message, size_t len);
|
||||
void textAll(const char * message);
|
||||
void textAll(const String &message);
|
||||
void textAll(const __FlashStringHelper *message); // need to convert
|
||||
void textAll(AsyncWebSocketMessageBuffer *buffer);
|
||||
void textAll(const String & message);
|
||||
void textAll(const __FlashStringHelper * message);
|
||||
void textAll(AsyncWebSocketMessageBuffer * buffer);
|
||||
void textAll(std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
|
||||
void binary(uint32_t id, const uint8_t *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 String &message);
|
||||
void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
|
||||
void binary(uint32_t id, const uint8_t * 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 String & message);
|
||||
void binary(uint32_t id, const __FlashStringHelper * message, size_t len);
|
||||
void binary(uint32_t id, AsyncWebSocketMessageBuffer * buffer);
|
||||
void binary(uint32_t id, std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
|
||||
void binaryAll(const uint8_t * message, size_t len);
|
||||
void binaryAll(const char * message, size_t len);
|
||||
void binaryAll(const char * message);
|
||||
void binaryAll(const String & message);
|
||||
void binaryAll(const __FlashStringHelper * message, size_t len);
|
||||
void binaryAll(AsyncWebSocketMessageBuffer * buffer);
|
||||
void binaryAll(std::shared_ptr<std::vector<uint8_t>> buffer);
|
||||
void binaryAll(const uint8_t *message, size_t len);
|
||||
void binaryAll(const char *message, size_t len);
|
||||
void binaryAll(const char *message);
|
||||
void binaryAll(const String &message);
|
||||
void binaryAll(const __FlashStringHelper *message, size_t len);
|
||||
void binaryAll(AsyncWebSocketMessageBuffer *buffer);
|
||||
|
||||
size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
size_t printf(uint32_t id, const char * format, ...) __attribute__((format(printf, 3, 4)));
|
||||
size_t printfAll(const char * format, ...) __attribute__((format(printf, 2, 3)));
|
||||
#ifndef ESP32
|
||||
size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__((format(printf, 3, 4)));
|
||||
#endif
|
||||
size_t printfAll_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
size_t printfAll_P(PGM_P formatP, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
//event listener
|
||||
void onEvent(AwsEventHandler handler){
|
||||
_eventHandler = handler;
|
||||
void onEvent(AwsEventHandler handler) {
|
||||
_eventHandler = handler;
|
||||
}
|
||||
|
||||
// Handshake Handler
|
||||
void handleHandshake(AwsHandshakeHandler handler){
|
||||
_handshakeHandler = handler;
|
||||
void handleHandshake(AwsHandshakeHandler handler) {
|
||||
_handshakeHandler = handler;
|
||||
}
|
||||
|
||||
|
||||
//system callbacks (do not call)
|
||||
uint32_t _getNextId(){ return _cNextId++; }
|
||||
AsyncWebSocketClient *_newClient(AsyncWebServerRequest *request);
|
||||
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
|
||||
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||
virtual void handleRequest(AsyncWebServerRequest *request) override final;
|
||||
uint32_t _getNextId() {
|
||||
return _cNextId++;
|
||||
}
|
||||
AsyncWebSocketClient * _newClient(AsyncWebServerRequest * request);
|
||||
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t * data, size_t len);
|
||||
virtual bool canHandle(AsyncWebServerRequest * request) override final;
|
||||
virtual void handleRequest(AsyncWebServerRequest * request) override final;
|
||||
|
||||
|
||||
// messagebuffer functions/objects.
|
||||
AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
|
||||
AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
|
||||
// messagebuffer functions/objects.
|
||||
AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
|
||||
AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
|
||||
|
||||
const std::list<AsyncWebSocketClient> &getClients() const { return _clients; }
|
||||
const std::list<AsyncWebSocketClient> & getClients() const {
|
||||
return _clients;
|
||||
}
|
||||
};
|
||||
|
||||
//WebServer response to authenticate the socket and detach the tcp client from the web server request
|
||||
class AsyncWebSocketResponse: public AsyncWebServerResponse {
|
||||
class AsyncWebSocketResponse : public AsyncWebServerResponse {
|
||||
private:
|
||||
String _content;
|
||||
AsyncWebSocket *_server;
|
||||
String _content;
|
||||
AsyncWebSocket * _server;
|
||||
|
||||
public:
|
||||
AsyncWebSocketResponse(const String& key, AsyncWebSocket *server);
|
||||
void _respond(AsyncWebServerRequest *request);
|
||||
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
|
||||
bool _sourceValid() const { return true; }
|
||||
AsyncWebSocketResponse(const String & key, AsyncWebSocket * server);
|
||||
void _respond(AsyncWebServerRequest * request);
|
||||
size_t _ack(AsyncWebServerRequest * request, size_t len, uint32_t time);
|
||||
bool _sourceValid() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* ASYNCWEBSOCKET_H_ */
|
||||
#endif /* ASYNCWEBSOCKET_H_ */
|
||||
Reference in New Issue
Block a user