From 8bb1c704cd70dd58b318b296154a5404a1bd27d0 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Sat, 19 Dec 2020 18:57:59 +0100 Subject: [PATCH] More crash fixes --- src/AsyncWebSocket.cpp | 121 ++++++++++++++++++++-------------------- src/AsyncWebSocket.h | 23 ++++---- src/ESPAsyncWebServer.h | 25 +++++---- src/StringArray.h | 19 ------- src/WebRequest.cpp | 2 - src/WebResponseImpl.h | 5 +- src/WebResponses.cpp | 26 ++++----- 7 files changed, 105 insertions(+), 116 deletions(-) diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index fd2599f..3284d6e 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -493,7 +493,7 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async _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->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this); - _server->_addClient(this); + //_server->_addClient(this); _server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0); delete request; } @@ -546,9 +546,8 @@ void AsyncWebSocketClient::_runQueue(){ } } -bool AsyncWebSocketClient::queueIsFull(){ - if((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) ) return true; - return false; +bool AsyncWebSocketClient::queueIsFull() const { + return (_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED); } void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){ @@ -838,14 +837,14 @@ void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer) _queueMessage(new AsyncWebSocketMultiMessage(buffer, WS_BINARY)); } -IPAddress AsyncWebSocketClient::remoteIP() { +IPAddress AsyncWebSocketClient::remoteIP() const { if(!_client) { return IPAddress(0U); } return _client->remoteIP(); } -uint16_t AsyncWebSocketClient::remotePort() { +uint16_t AsyncWebSocketClient::remotePort() const { if(!_client) { return 0; } @@ -860,7 +859,6 @@ uint16_t AsyncWebSocketClient::remotePort() { AsyncWebSocket::AsyncWebSocket(const String& url) :_url(url) - ,_clients(LinkedList([](AsyncWebSocketClient *c){ delete c; })) ,_cNextId(1) ,_enabled(true) { @@ -875,64 +873,68 @@ void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType ty } } -void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){ - _clients.add(client); +AsyncWebSocketClient *AsyncWebSocket::_newClient(AsyncWebServerRequest *request) +{ + _clients.emplace_back(request, this); + return &_clients.back(); } +//void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){ +// _clients.add(client); +//} + void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){ - - _clients.remove_first([=](AsyncWebSocketClient * c){ - return c->id() == client->id(); - }); + const auto iter = std::find_if(std::begin(_clients), std::end(_clients), + [id=client->id()](const auto &c){ return c.id() == id; }); + if (iter != std::end(_clients)) + _clients.erase(iter); } bool AsyncWebSocket::availableForWriteAll(){ - for(const auto& c: _clients){ - if(c->queueIsFull()) return false; - } - return true; + return std::none_of(std::begin(_clients), std::end(_clients), + [](const auto &c){ return c.queueIsFull(); }); } bool AsyncWebSocket::availableForWrite(uint32_t id){ - for(const auto& c: _clients){ - if(c->queueIsFull() && (c->id() == id )) return false; - } - return true; + const auto iter = std::find_if(std::begin(_clients), std::end(_clients), + [id](const auto &c){ return c.id() == id; }); + if (iter == std::end(_clients)) + return true; // don't know why me-no-dev decided like this? + return !iter->queueIsFull(); } size_t AsyncWebSocket::count() const { - return _clients.count_if([](AsyncWebSocketClient * c){ - return c->status() == WS_CONNECTED; - }); + return std::count_if(std::begin(_clients), std::end(_clients), + [](const auto &c){ return c.status() == WS_CONNECTED; }); } AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){ - for(const auto &c: _clients){ - if(c->id() == id && c->status() == WS_CONNECTED){ - return c; - } - } - return nullptr; + const auto iter = std::find_if(std::begin(_clients), std::end(_clients), + [id](const auto &c){ return c.id() == id && c.status() == WS_CONNECTED; }); + if (iter == std::end(_clients)) + return nullptr; + + return &(*iter); } void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){ - AsyncWebSocketClient * c = client(id); - if(c) + AsyncWebSocketClient *c = client(id); + if (c) c->close(code, message); } void AsyncWebSocket::closeAll(uint16_t code, const char * message){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->close(code, message); + for(auto &c: _clients){ + if(c.status() == WS_CONNECTED) + c.close(code, message); } } void AsyncWebSocket::cleanupClients(uint16_t maxClients) { if (count() > maxClients){ - _clients.front()->close(); + _clients.front().close(); } } @@ -943,14 +945,14 @@ void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){ } void AsyncWebSocket::pingAll(uint8_t *data, size_t len){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->ping(data, len); + for (auto &c : _clients){ + if (c.status() == WS_CONNECTED) + c.ping(data, len); } } void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){ - AsyncWebSocketClient * c = client(id); + AsyncWebSocketClient *c = client(id); if(c) c->text(message, len); } @@ -958,9 +960,9 @@ void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){ void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){ if (!buffer) return; buffer->lock(); - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED){ - c->text(buffer); + for(auto &c : _clients){ + if (c.status() == WS_CONNECTED){ + c.text(buffer); } } buffer->unlock(); @@ -988,24 +990,24 @@ void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer) { if (!buffer) return; buffer->lock(); - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->binary(buffer); + for (auto &c : _clients){ + if (c.status() == WS_CONNECTED) + c.binary(buffer); } buffer->unlock(); _cleanBuffers(); } void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){ - AsyncWebSocketClient * c = client(id); - if(c) + AsyncWebSocketClient *c = client(id); + if (c) c->message(message); } void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->message(message); + for (auto &c : _clients){ + if(c.status() == WS_CONNECTED) + c.message(message); } _cleanBuffers(); } @@ -1114,9 +1116,9 @@ void AsyncWebSocket::textAll(const String &message){ textAll(message.c_str(), message.length()); } void AsyncWebSocket::textAll(const __FlashStringHelper *message){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c->text(message); + for(auto &c : _clients){ + if(c.status() == WS_CONNECTED) + c.text(message); } } void AsyncWebSocket::binary(uint32_t id, const char * message){ @@ -1149,9 +1151,9 @@ void AsyncWebSocket::binaryAll(const String &message){ binaryAll(message.c_str(), message.length()); } void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){ - for(const auto& c: _clients){ - if(c->status() == WS_CONNECTED) - c-> binary(message, len); + for(auto &c : _clients) { + if(c.status() == WS_CONNECTED) + c.binary(message, len); } } @@ -1241,7 +1243,7 @@ void AsyncWebSocket::_cleanBuffers() } } -AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const { +const AsyncWebSocket::AsyncWebSocketClientLinkedList &AsyncWebSocket::getClients() const { return _clients; } @@ -1299,7 +1301,8 @@ void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request){ size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ (void)time; if(len){ - new AsyncWebSocketClient(request, _server); + //new AsyncWebSocketClient(request, _server); + _server->_newClient(request); } return 0; } diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 5a439b9..79f49f5 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -183,14 +183,16 @@ class AsyncWebSocketClient { ~AsyncWebSocketClient(); //client id increments for the given server - uint32_t id(){ return _clientId; } - AwsClientStatus status(){ return _status; } - AsyncClient* client(){ return _client; } - AsyncWebSocket *server(){ return _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; } - IPAddress remoteIP(); - uint16_t remotePort(); + IPAddress remoteIP() const; + uint16_t remotePort() const; //control frames void close(uint16_t code=0, const char * message=NULL); @@ -206,7 +208,7 @@ class AsyncWebSocketClient { //data packets void message(AsyncWebSocketMessage *message){ _queueMessage(message); } - bool queueIsFull(); + bool queueIsFull() const; size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3))); #ifndef ESP32 @@ -244,7 +246,7 @@ typedef std::function AsyncWebSocketClientLinkedList; + typedef std::list AsyncWebSocketClientLinkedList; private: String _url; AsyncWebSocketClientLinkedList _clients; @@ -320,7 +322,8 @@ class AsyncWebSocket: public AsyncWebHandler { //system callbacks (do not call) uint32_t _getNextId(){ return _cNextId++; } - void _addClient(AsyncWebSocketClient * client); + AsyncWebSocketClient *_newClient(AsyncWebServerRequest *request); + //void _addClient(AsyncWebSocketClient * client); void _handleDisconnect(AsyncWebSocketClient * client); void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); virtual bool canHandle(AsyncWebServerRequest *request) override final; @@ -333,7 +336,7 @@ class AsyncWebSocket: public AsyncWebHandler { std::list _buffers; 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 diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 0948ba0..23f76a5 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -109,6 +109,9 @@ class AsyncWebHeader { String _value; public: + AsyncWebHeader() = default; + AsyncWebHeader(const AsyncWebHeader &) = default; + AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){} AsyncWebHeader(const String& data): _name(), _value(){ if(!data) return; @@ -117,10 +120,12 @@ class AsyncWebHeader { _name = data.substring(0, index); _value = data.substring(index + 2); } - ~AsyncWebHeader(){} + + AsyncWebHeader &operator=(const AsyncWebHeader &) = default; + const String& name() const { return _name; } const String& value() const { return _value; } - String toString() const { return String(_name+": "+_value+"\r\n"); } + String toString() const { return _name+": "+_value+"\r\n"; } }; /* @@ -362,7 +367,7 @@ typedef enum { class AsyncWebServerResponse { protected: int _code; - LinkedList _headers; + std::list _headers; String _contentType; size_t _contentLength; bool _sendContentLength; @@ -444,17 +449,16 @@ class AsyncWebServer { }; class DefaultHeaders { - using headers_t = LinkedList; + using headers_t = std::list; headers_t _headers; - - DefaultHeaders() - :_headers(headers_t([](AsyncWebHeader *h){ delete h; })) - {} + public: - using ConstIterator = headers_t::ConstIterator; + DefaultHeaders() = default; + + using ConstIterator = headers_t::const_iterator; void addHeader(const String& name, const String& value){ - _headers.add(new AsyncWebHeader(name, value)); + _headers.emplace_back(name, value); } ConstIterator begin() const { return _headers.begin(); } @@ -462,6 +466,7 @@ public: DefaultHeaders(DefaultHeaders const &) = delete; DefaultHeaders &operator=(DefaultHeaders const &) = delete; + static DefaultHeaders &Instance() { static DefaultHeaders instance; return instance; diff --git a/src/StringArray.h b/src/StringArray.h index 4c0aa70..d5096e6 100644 --- a/src/StringArray.h +++ b/src/StringArray.h @@ -171,23 +171,4 @@ class LinkedList { } }; - -class StringArray : public LinkedList { -public: - - StringArray() : LinkedList(nullptr) {} - - bool containsIgnoreCase(const String& str){ - for (const auto& s : *this) { - if (str.equalsIgnoreCase(s)) { - return true; - } - } - return false; - } -}; - - - - #endif /* STRINGARRAY_H_ */ diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index 9758705..d0a6d88 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -184,9 +184,7 @@ void AsyncWebServerRequest::_removeNotInterestingHeaders(){ for(auto iter = std::begin(_headers); iter != std::end(_headers); ) { - Serial.print("printing name: "); const auto name = iter->name(); - Serial.println(name); if (std::none_of(std::begin(_interestingHeaders), std::end(_interestingHeaders), [&name](const String &str){ return str.equalsIgnoreCase(name); })) diff --git a/src/WebResponseImpl.h b/src/WebResponseImpl.h index 9a64e3a..c717d91 100644 --- a/src/WebResponseImpl.h +++ b/src/WebResponseImpl.h @@ -26,7 +26,10 @@ #undef min #undef max #endif + #include +#include + // It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max. class AsyncBasicResponse: public AsyncWebServerResponse { @@ -122,7 +125,7 @@ class cbuf; class AsyncResponseStream: public AsyncAbstractResponse, public Print { private: - cbuf *_content; + std::unique_ptr _content; public: AsyncResponseStream(const String& contentType, size_t bufferSize); ~AsyncResponseStream(); diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index a22e991..8a4b37e 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp @@ -84,7 +84,6 @@ const char* AsyncWebServerResponse::_responseCodeToString(int code) { AsyncWebServerResponse::AsyncWebServerResponse() : _code(0) - , _headers(LinkedList([](AsyncWebHeader *h){ delete h; })) , _contentType() , _contentLength(0) , _sendContentLength(true) @@ -95,14 +94,12 @@ AsyncWebServerResponse::AsyncWebServerResponse() , _writtenLength(0) , _state(RESPONSE_SETUP) { - for(auto header: DefaultHeaders::Instance()) { - _headers.add(new AsyncWebHeader(header->name(), header->value())); + for(const auto &header : DefaultHeaders::Instance()) { + _headers.emplace_back(header); } } -AsyncWebServerResponse::~AsyncWebServerResponse(){ - _headers.free(); -} +AsyncWebServerResponse::~AsyncWebServerResponse() = default; void AsyncWebServerResponse::setCode(int code){ if(_state == RESPONSE_SETUP) @@ -120,7 +117,7 @@ void AsyncWebServerResponse::setContentType(const String& type){ } void AsyncWebServerResponse::addHeader(const String& name, const String& value){ - _headers.add(new AsyncWebHeader(name, value)); + _headers.emplace_back(name, value); } String AsyncWebServerResponse::_assembleHead(uint8_t version){ @@ -145,11 +142,11 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version){ out.concat(buf); } - for(const auto& header: _headers){ - snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str()); + for(const auto &header: _headers){ + snprintf(buf, bufSize, "%s: %s\r\n", header.name().c_str(), header.value().c_str()); out.concat(buf); } - _headers.free(); + _headers.clear(); out.concat("\r\n"); _headLength = out.length(); @@ -666,16 +663,15 @@ size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){ * Response Stream (You can print/write/printf to it, up to the contentLen bytes) * */ -AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){ +AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize) +{ _code = 200; _contentLength = 0; _contentType = contentType; - _content = new cbuf(bufferSize); + _content = std::make_unique(bufferSize); } -AsyncResponseStream::~AsyncResponseStream(){ - delete _content; -} +AsyncResponseStream::~AsyncResponseStream() = default; size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){ return _content->read((char*)buf, maxLen);