mirror of
https://github.com/me-no-dev/ESPAsyncWebServer.git
synced 2025-09-28 07:11:01 +02:00
Replace use of LinkedList<T> with std::list for AsyncWebServer clients
Fraction of commit 8bb1c704cd70dd58b318b296154a5404a1bd27d0 of dumbfixes branch of 0xFEEDC0DE64 fork of ESPAsyncWebServer. Const-ify a few methods of AsyncWebServer. Instead of using the new operator to create the AsyncWebSocketClient and then discarding it while adding the pointer to the client list, just create the client inside the standard list container. Workarounds for lack of auto parameter support in lambdas used by original patch.
This commit is contained in:
@@ -540,7 +540,6 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
|
|||||||
_client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this);
|
_client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this);
|
||||||
_client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this);
|
_client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this);
|
||||||
_client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this);
|
_client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this);
|
||||||
_server->_addClient(this);
|
|
||||||
_server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0);
|
_server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0);
|
||||||
delete request;
|
delete request;
|
||||||
memset(&_pinfo,0,sizeof(_pinfo));
|
memset(&_pinfo,0,sizeof(_pinfo));
|
||||||
@@ -614,9 +613,8 @@ void AsyncWebSocketClient::_runQueue(){
|
|||||||
_clearQueue();
|
_clearQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncWebSocketClient::queueIsFull(){
|
bool AsyncWebSocketClient::queueIsFull() const {
|
||||||
if((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) ) return true;
|
return (_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){
|
void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){
|
||||||
@@ -909,14 +907,14 @@ void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer)
|
|||||||
_queueMessage(new AsyncWebSocketMultiMessage(buffer, WS_BINARY));
|
_queueMessage(new AsyncWebSocketMultiMessage(buffer, WS_BINARY));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress AsyncWebSocketClient::remoteIP() {
|
IPAddress AsyncWebSocketClient::remoteIP() const {
|
||||||
if(!_client) {
|
if(!_client) {
|
||||||
return IPAddress(0U);
|
return IPAddress(0U);
|
||||||
}
|
}
|
||||||
return _client->remoteIP();
|
return _client->remoteIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t AsyncWebSocketClient::remotePort() {
|
uint16_t AsyncWebSocketClient::remotePort() const {
|
||||||
if(!_client) {
|
if(!_client) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -931,7 +929,6 @@ uint16_t AsyncWebSocketClient::remotePort() {
|
|||||||
|
|
||||||
AsyncWebSocket::AsyncWebSocket(const String& url)
|
AsyncWebSocket::AsyncWebSocket(const String& url)
|
||||||
:_url(url)
|
:_url(url)
|
||||||
,_clients(LinkedList<AsyncWebSocketClient *>([](AsyncWebSocketClient *c){ delete c; }))
|
|
||||||
,_cNextId(1)
|
,_cNextId(1)
|
||||||
,_enabled(true)
|
,_enabled(true)
|
||||||
{
|
{
|
||||||
@@ -946,44 +943,45 @@ void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType ty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){
|
AsyncWebSocketClient *AsyncWebSocket::_newClient(AsyncWebServerRequest *request)
|
||||||
_clients.add(client);
|
{
|
||||||
|
_clients.emplace_back(request, this);
|
||||||
|
return &_clients.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){
|
void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){
|
||||||
|
const auto client_id = client->id();
|
||||||
_clients.remove_first([=](AsyncWebSocketClient * c){
|
const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
|
||||||
return c->id() == client->id();
|
[client_id](const AsyncWebSocketClient &c){ return c.id() == client_id; });
|
||||||
});
|
if (iter != std::end(_clients))
|
||||||
|
_clients.erase(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncWebSocket::availableForWriteAll(){
|
bool AsyncWebSocket::availableForWriteAll(){
|
||||||
for(const auto& c: _clients){
|
return std::none_of(std::begin(_clients), std::end(_clients),
|
||||||
if(c->queueIsFull()) return false;
|
[](const AsyncWebSocketClient &c){ return c.queueIsFull(); });
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncWebSocket::availableForWrite(uint32_t id){
|
bool AsyncWebSocket::availableForWrite(uint32_t id){
|
||||||
for(const auto& c: _clients){
|
const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
|
||||||
if(c->queueIsFull() && (c->id() == id )) return false;
|
[id](const AsyncWebSocketClient &c){ return c.id() == id; });
|
||||||
}
|
if (iter == std::end(_clients))
|
||||||
return true;
|
return true; // don't know why me-no-dev decided like this?
|
||||||
|
return !iter->queueIsFull();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AsyncWebSocket::count() const {
|
size_t AsyncWebSocket::count() const {
|
||||||
return _clients.count_if([](AsyncWebSocketClient * c){
|
return std::count_if(std::begin(_clients), std::end(_clients),
|
||||||
return c->status() == WS_CONNECTED;
|
[](const AsyncWebSocketClient &c){ return c.status() == WS_CONNECTED; });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){
|
AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){
|
||||||
for(const auto &c: _clients){
|
const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
|
||||||
if(c->id() == id && c->status() == WS_CONNECTED){
|
[id](const AsyncWebSocketClient &c){ return c.id() == id && c.status() == WS_CONNECTED; });
|
||||||
return c;
|
if (iter == std::end(_clients))
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
return &(*iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -994,16 +992,16 @@ void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocket::closeAll(uint16_t code, const char * message){
|
void AsyncWebSocket::closeAll(uint16_t code, const char * message){
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED)
|
if(c.status() == WS_CONNECTED)
|
||||||
c->close(code, message);
|
c.close(code, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocket::cleanupClients(uint16_t maxClients)
|
void AsyncWebSocket::cleanupClients(uint16_t maxClients)
|
||||||
{
|
{
|
||||||
if (count() > maxClients){
|
if (count() > maxClients){
|
||||||
_clients.front()->close();
|
_clients.front().close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1014,9 +1012,9 @@ void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocket::pingAll(uint8_t *data, size_t len){
|
void AsyncWebSocket::pingAll(uint8_t *data, size_t len){
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED)
|
if(c.status() == WS_CONNECTED)
|
||||||
c->ping(data, len);
|
c.ping(data, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1029,9 +1027,9 @@ void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){
|
|||||||
void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){
|
void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){
|
||||||
if (!buffer) return;
|
if (!buffer) return;
|
||||||
buffer->lock();
|
buffer->lock();
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED){
|
if(c.status() == WS_CONNECTED){
|
||||||
c->text(buffer);
|
c.text(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer->unlock();
|
buffer->unlock();
|
||||||
@@ -1060,9 +1058,9 @@ void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
|
|||||||
{
|
{
|
||||||
if (!buffer) return;
|
if (!buffer) return;
|
||||||
buffer->lock();
|
buffer->lock();
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED)
|
if(c.status() == WS_CONNECTED)
|
||||||
c->binary(buffer);
|
c.binary(buffer);
|
||||||
}
|
}
|
||||||
buffer->unlock();
|
buffer->unlock();
|
||||||
_cleanBuffers();
|
_cleanBuffers();
|
||||||
@@ -1075,9 +1073,9 @@ void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){
|
void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED)
|
if(c.status() == WS_CONNECTED)
|
||||||
c->message(message);
|
c.message(message);
|
||||||
}
|
}
|
||||||
_cleanBuffers();
|
_cleanBuffers();
|
||||||
}
|
}
|
||||||
@@ -1186,9 +1184,9 @@ void AsyncWebSocket::textAll(const String &message){
|
|||||||
textAll(message.c_str(), message.length());
|
textAll(message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
void AsyncWebSocket::textAll(const __FlashStringHelper *message){
|
void AsyncWebSocket::textAll(const __FlashStringHelper *message){
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED)
|
if(c.status() == WS_CONNECTED)
|
||||||
c->text(message);
|
c.text(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void AsyncWebSocket::binary(uint32_t id, const char * message){
|
void AsyncWebSocket::binary(uint32_t id, const char * message){
|
||||||
@@ -1221,9 +1219,9 @@ void AsyncWebSocket::binaryAll(const String &message){
|
|||||||
binaryAll(message.c_str(), message.length());
|
binaryAll(message.c_str(), message.length());
|
||||||
}
|
}
|
||||||
void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){
|
void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){
|
||||||
for(const auto& c: _clients){
|
for(auto& c: _clients){
|
||||||
if(c->status() == WS_CONNECTED)
|
if(c.status() == WS_CONNECTED)
|
||||||
c-> binary(message, len);
|
c.binary(message, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1333,7 +1331,7 @@ void AsyncWebSocket::_cleanBuffers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const {
|
const AsyncWebSocket::AsyncWebSocketClientLinkedList &AsyncWebSocket::getClients() const {
|
||||||
return _clients;
|
return _clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1391,7 +1389,7 @@ void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request){
|
|||||||
size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){
|
size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){
|
||||||
(void)time;
|
(void)time;
|
||||||
if(len){
|
if(len){
|
||||||
new AsyncWebSocketClient(request, _server);
|
_server->_newClient(request);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -184,14 +184,16 @@ class AsyncWebSocketClient {
|
|||||||
~AsyncWebSocketClient();
|
~AsyncWebSocketClient();
|
||||||
|
|
||||||
//client id increments for the given server
|
//client id increments for the given server
|
||||||
uint32_t id(){ return _clientId; }
|
uint32_t id() const { return _clientId; }
|
||||||
AwsClientStatus status(){ return _status; }
|
AwsClientStatus status() const { return _status; }
|
||||||
AsyncClient* client() { return _client; }
|
AsyncClient* client() { return _client; }
|
||||||
|
const AsyncClient* client() const { return _client; }
|
||||||
AsyncWebSocket *server(){ return _server; }
|
AsyncWebSocket *server(){ return _server; }
|
||||||
|
const AsyncWebSocket *server() const { return _server; }
|
||||||
AwsFrameInfo const &pinfo() const { return _pinfo; }
|
AwsFrameInfo const &pinfo() const { return _pinfo; }
|
||||||
|
|
||||||
IPAddress remoteIP();
|
IPAddress remoteIP() const;
|
||||||
uint16_t remotePort();
|
uint16_t remotePort() const;
|
||||||
|
|
||||||
//control frames
|
//control frames
|
||||||
void close(uint16_t code=0, const char * message=NULL);
|
void close(uint16_t code=0, const char * message=NULL);
|
||||||
@@ -207,7 +209,7 @@ class AsyncWebSocketClient {
|
|||||||
|
|
||||||
//data packets
|
//data packets
|
||||||
void message(AsyncWebSocketMessage *message){ _queueMessage(message); }
|
void message(AsyncWebSocketMessage *message){ _queueMessage(message); }
|
||||||
bool queueIsFull();
|
bool queueIsFull() const;
|
||||||
size_t queueLen() { return _messageQueue.length() + _controlQueue.length(); }
|
size_t queueLen() { return _messageQueue.length() + _controlQueue.length(); }
|
||||||
|
|
||||||
size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
@@ -247,7 +249,7 @@ typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * clien
|
|||||||
//WebServer Handler implementation that plays the role of a socket server
|
//WebServer Handler implementation that plays the role of a socket server
|
||||||
class AsyncWebSocket: public AsyncWebHandler {
|
class AsyncWebSocket: public AsyncWebHandler {
|
||||||
public:
|
public:
|
||||||
typedef LinkedList<AsyncWebSocketClient *> AsyncWebSocketClientLinkedList;
|
typedef std::list<AsyncWebSocketClient> AsyncWebSocketClientLinkedList;
|
||||||
private:
|
private:
|
||||||
String _url;
|
String _url;
|
||||||
AsyncWebSocketClientLinkedList _clients;
|
AsyncWebSocketClientLinkedList _clients;
|
||||||
@@ -329,7 +331,7 @@ class AsyncWebSocket: public AsyncWebHandler {
|
|||||||
|
|
||||||
//system callbacks (do not call)
|
//system callbacks (do not call)
|
||||||
uint32_t _getNextId(){ return _cNextId++; }
|
uint32_t _getNextId(){ return _cNextId++; }
|
||||||
void _addClient(AsyncWebSocketClient * client);
|
AsyncWebSocketClient *_newClient(AsyncWebServerRequest *request);
|
||||||
void _handleDisconnect(AsyncWebSocketClient * client);
|
void _handleDisconnect(AsyncWebSocketClient * client);
|
||||||
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
|
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
|
||||||
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||||
@@ -342,7 +344,7 @@ class AsyncWebSocket: public AsyncWebHandler {
|
|||||||
std::list<AsyncWebSocketMessageBuffer> _buffers;
|
std::list<AsyncWebSocketMessageBuffer> _buffers;
|
||||||
void _cleanBuffers();
|
void _cleanBuffers();
|
||||||
|
|
||||||
AsyncWebSocketClientLinkedList getClients() const;
|
const AsyncWebSocketClientLinkedList &getClients() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//WebServer response to authenticate the socket and detach the tcp client from the web server request
|
//WebServer response to authenticate the socket and detach the tcp client from the web server request
|
||||||
|
Reference in New Issue
Block a user