diff --git a/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino b/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino index 9d8597f..b350dc3 100644 --- a/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino +++ b/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino @@ -189,7 +189,7 @@ void setup(){ request->send(404); }); - server.onFileUpload([](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ + server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ if(!index) Serial.printf("UploadStart: %s\n", filename.c_str()); Serial.printf("%s", (const char*)data); diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index 5e65e26..7b8cdca 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -110,7 +110,6 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A _client = request->client(); _server = server; _lastId = 0; - next = NULL; if(request->hasHeader("Last-Event-ID")) _lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str()); @@ -119,7 +118,7 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A _client->onAck(NULL, NULL); _client->onPoll(NULL, NULL); _client->onData(NULL, NULL); - _client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this); + _client->onTimeout([](void *r, AsyncClient* c __attribute__((unused)), uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this); _client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this); _server->_addClient(this); delete request; @@ -129,7 +128,7 @@ AsyncEventSourceClient::~AsyncEventSourceClient(){ close(); } -void AsyncEventSourceClient::_onTimeout(uint32_t time){ +void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){ _client->close(true); } @@ -161,9 +160,9 @@ void AsyncEventSourceClient::send(const char *message, const char *event, uint32 // Handler -AsyncEventSource::AsyncEventSource(String url) +AsyncEventSource::AsyncEventSource(const String& url) : _url(url) - , _clients(NULL) + , _clients(LinkedList([](AsyncEventSourceClient *c){ delete c; })) , _connectcb(NULL) {} @@ -188,68 +187,38 @@ void AsyncEventSource::_addClient(AsyncEventSourceClient * client){ client->write((const char *)temp, 2053); free(temp); }*/ - if(_clients == NULL){ - _clients = client; - if(_connectcb) - _connectcb(client); - return; - } - AsyncEventSourceClient * c = _clients; - while(c->next != NULL) c = c->next; - c->next = client; + + _clients.add(client); if(_connectcb) _connectcb(client); } void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){ - if(_clients == NULL){ - return; - } - if(_clients == client){ - _clients = client->next; - delete client; - return; - } - AsyncEventSourceClient * c = _clients; - while(c->next != NULL && c->next != client) c = c->next; - if(c->next == NULL){ - return; - } - c->next = client->next; - delete client; + _clients.remove(client); } void AsyncEventSource::close(){ - AsyncEventSourceClient * c = _clients; - while(c != NULL){ + for(const auto &c: _clients){ if(c->connected()) c->close(); - c = c->next; } } void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){ - if(_clients == NULL) + if(_clients.isEmpty()) return; String ev = generateEventMessage(message, event, id, reconnect); - AsyncEventSourceClient * c = _clients; - while(c != NULL){ + for(const auto &c: _clients){ if(c->connected()) c->write(ev.c_str(), ev.length()); - c = c->next; } } -size_t AsyncEventSource::count(){ - size_t i = 0; - AsyncEventSourceClient * c = _clients; - while(c != NULL){ - if(c->connected()) - i++; - c = c->next; - } - return i; +size_t AsyncEventSource::count() const { + return _clients.count_if([](AsyncEventSourceClient *c){ + return c->connected(); + }); } bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){ @@ -280,7 +249,7 @@ void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_WAIT_ACK; } -size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ +size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused))){ if(len){ new AsyncEventSourceClient(request, _server); } diff --git a/src/AsyncEventSource.h b/src/AsyncEventSource.h index 94c1e85..6754694 100644 --- a/src/AsyncEventSource.h +++ b/src/AsyncEventSource.h @@ -36,7 +36,6 @@ class AsyncEventSourceClient { uint32_t _lastId; public: - AsyncEventSourceClient * next; AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server); ~AsyncEventSourceClient(); @@ -45,8 +44,8 @@ class AsyncEventSourceClient { void close(); void write(const char * message, size_t len); void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); - bool connected(){ return (_client != NULL) && _client->connected(); } - uint32_t lastId(){ return _lastId; } + bool connected() const { return (_client != NULL) && _client->connected(); } + uint32_t lastId() const { return _lastId; } //system callbacks (do not call) void _onTimeout(uint32_t time); @@ -56,23 +55,23 @@ class AsyncEventSourceClient { class AsyncEventSource: public AsyncWebHandler { private: String _url; - AsyncEventSourceClient * _clients; + LinkedList _clients; ArEventHandlerFunction _connectcb; public: - AsyncEventSource(String url); + AsyncEventSource(const String& url); ~AsyncEventSource(); - const char * url(){ return _url.c_str(); } + const char * url() const { return _url.c_str(); } void close(); void onConnect(ArEventHandlerFunction cb); void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); - size_t count(); //number clinets connected + size_t count() const; //number clinets connected //system callbacks (do not call) void _addClient(AsyncEventSourceClient * client); void _handleDisconnect(AsyncEventSourceClient * client); - bool canHandle(AsyncWebServerRequest *request); - void handleRequest(AsyncWebServerRequest *request); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; }; class AsyncEventSourceResponse: public AsyncWebServerResponse { diff --git a/src/AsyncJson.h b/src/AsyncJson.h index 4ff1ff6..a1d3772 100644 --- a/src/AsyncJson.h +++ b/src/AsyncJson.h @@ -69,7 +69,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse { size_t setLength() { _contentLength = _root.measureLength(); if (_contentLength) { _isValid = true; } - return _contentLength; + return _contentLength; } size_t _fillBuffer(uint8_t *data, size_t len){ diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index 8d38de0..56c7bb2 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -133,13 +133,12 @@ class AsyncWebSocketControl { bool _mask; bool _finished; public: - AsyncWebSocketControl * next; AsyncWebSocketControl(uint8_t opcode, uint8_t *data=NULL, size_t len=0, bool mask=false) :_opcode(opcode) ,_len(len) ,_mask(len && mask) ,_finished(false) - ,next(NULL){ + { if(data == NULL) _len = 0; if(_len){ @@ -151,11 +150,11 @@ class AsyncWebSocketControl { else memcpy(_data, data, len); } else _data = NULL; } - ~AsyncWebSocketControl(){ + virtual ~AsyncWebSocketControl(){ if(_data != NULL) free(_data); } - bool finished(){ return _finished; } + virtual bool finished(){ return _finished; } uint8_t opcode(){ return _opcode; } uint8_t len(){ return _len + 2; } size_t send(AsyncClient *client){ @@ -195,18 +194,18 @@ class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage { _data[_len] = 0; } } - virtual ~AsyncWebSocketBasicMessage(){ + virtual ~AsyncWebSocketBasicMessage() override { if(_data != NULL) free(_data); } - virtual bool betweenFrames(){ return _acked == _ack; } - virtual void ack(size_t len, uint32_t time){ + virtual bool betweenFrames() const override { return _acked == _ack; } + virtual void ack(size_t len, uint32_t time) override { _acked += len; if(_sent == _len && _acked == _ack){ _status = WS_MSG_SENT; } } - virtual size_t send(AsyncClient *client){ + virtual size_t send(AsyncClient *client) override { if(_status != WS_MSG_SENDING) return 0; if(_acked < _ack){ @@ -239,17 +238,17 @@ class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage { const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING"; const size_t AWSC_PING_PAYLOAD_LEN = 22; -AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server){ +AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server) + : _controlQueue(LinkedList([](AsyncWebSocketControl *c){ delete c; })) + , _messageQueue(LinkedList([](AsyncWebSocketMessage *m){ delete m; })) +{ _client = request->client(); _server = server; _clientId = _server->_getNextId(); _status = WS_CONNECTED; - _controlQueue = NULL; - _messageQueue = NULL; _pstate = 0; _lastMessageTime = millis(); _keepAlivePeriod = 0; - next = NULL; _client->setRxTimeout(0); _client->onError([](void *r, AsyncClient* c, int8_t error){ ((AsyncWebSocketClient*)(r))->_onError(error); }, this); _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this); @@ -263,61 +262,49 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async } AsyncWebSocketClient::~AsyncWebSocketClient(){ - while(_messageQueue != NULL){ - AsyncWebSocketMessage * m = _messageQueue; - _messageQueue = _messageQueue->next; - delete(m); - } - while(_controlQueue != NULL){ - AsyncWebSocketControl * c = _controlQueue; - _controlQueue = _controlQueue->next; - delete(c); - } + _messageQueue.free(); + _controlQueue.free(); _server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0); } void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){ _lastMessageTime = millis(); - if(_controlQueue != NULL){ - AsyncWebSocketControl *controlMessage = _controlQueue; - if(controlMessage->finished()){ - _controlQueue = _controlQueue->next; - len -= controlMessage->len(); - if(_status == WS_DISCONNECTING && controlMessage->opcode() == WS_DISCONNECT){ - delete controlMessage; + if(!_controlQueue.isEmpty()){ + auto head = _controlQueue.front(); + if(head->finished()){ + len -= head->len(); + if(_status == WS_DISCONNECTING && head->opcode() == WS_DISCONNECT){ + _controlQueue.remove(head); _status = WS_DISCONNECTED; _client->close(true); return; } - delete controlMessage; + _controlQueue.remove(head); } } - if(len && _messageQueue != NULL){ - _messageQueue->ack(len, time); + if(len && !_messageQueue.isEmpty()){ + _messageQueue.front()->ack(len, time); } _runQueue(); } void AsyncWebSocketClient::_onPoll(){ - if(_client->canSend() && (_controlQueue != NULL || _messageQueue != NULL)){ + if(_client->canSend() && (!_controlQueue.isEmpty() || !_messageQueue.isEmpty())){ _runQueue(); - } else if(_keepAlivePeriod > 0 && _controlQueue == NULL && _messageQueue == NULL && (millis() - _lastMessageTime) >= _keepAlivePeriod){ + } else if(_keepAlivePeriod > 0 && _controlQueue.isEmpty() && _messageQueue.isEmpty() && (millis() - _lastMessageTime) >= _keepAlivePeriod){ ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN); } } void AsyncWebSocketClient::_runQueue(){ - while(_messageQueue != NULL && _messageQueue->finished()){ - AsyncWebSocketMessage * m = _messageQueue; - _messageQueue = _messageQueue->next; - delete(m); + while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){ + _messageQueue.remove(_messageQueue.front()); } - if(_controlQueue != NULL && (_messageQueue == NULL || _messageQueue->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue->len() - 1)){ - AsyncWebSocketControl *control = _controlQueue; - control->send(_client); - } else if(_messageQueue != NULL && _messageQueue->betweenFrames() && webSocketSendFrameWindow(_client)){ - _messageQueue->send(_client); + if(!_controlQueue.isEmpty() && (_messageQueue.isEmpty() || _messageQueue.front()->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front()->len() - 1)){ + _controlQueue.front()->send(_client); + } else if(!_messageQueue.isEmpty() && _messageQueue.front()->betweenFrames() && webSocketSendFrameWindow(_client)){ + _messageQueue.front()->send(_client); } } @@ -328,13 +315,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){ delete dataMessage; return; } - if(_messageQueue == NULL){ - _messageQueue = dataMessage; - } else { - AsyncWebSocketMessage * m = _messageQueue; - while(m->next != NULL) m = m->next; - m->next = dataMessage; - } + _messageQueue.add(dataMessage); if(_client->canSend()) _runQueue(); } @@ -342,13 +323,7 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){ void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage){ if(controlMessage == NULL) return; - if(_controlQueue == NULL){ - _controlQueue = controlMessage; - } else { - AsyncWebSocketControl * m = _controlQueue; - while(m->next != NULL) m = m->next; - m->next = controlMessage; - } + _controlQueue.add(controlMessage); if(_client->canSend()) _runQueue(); } @@ -604,9 +579,9 @@ uint16_t AsyncWebSocketClient::remotePort() { * Async Web Socket - Each separate socket location */ -AsyncWebSocket::AsyncWebSocket(String url) +AsyncWebSocket::AsyncWebSocket(const String& url) :_url(url) - ,_clients(NULL) + ,_clients(LinkedList([](AsyncWebSocketClient *c){ delete c; })) ,_cNextId(1) ,_enabled(true) { @@ -622,133 +597,100 @@ void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType ty } void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){ - if(_clients == NULL){ - _clients = client; - return; - } - AsyncWebSocketClient * c = _clients; - while(c->next != NULL) c = c->next; - c->next = client; + _clients.add(client); } void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){ - if(_clients == NULL){ - return; - } - if(_clients->id() == client->id()){ - _clients = client->next; - delete client; - return; - } - AsyncWebSocketClient * c = _clients; - while(c->next != NULL && c->next->id() != client->id()) c = c->next; - if(c->next == NULL){ - return; - } - c->next = client->next; - delete client; + + _clients.remove_first([=](AsyncWebSocketClient * c){ + return c->id() == client->id(); + }); } -size_t AsyncWebSocket::count(){ - size_t i = 0; - AsyncWebSocketClient * c = _clients; - while(c != NULL){ - if(c->status() == WS_CONNECTED) - i++; - c = c->next; - } - return i; +size_t AsyncWebSocket::count() const { + return _clients.count_if([](AsyncWebSocketClient * c){ + return c->status() == WS_CONNECTED; + }); } AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){ - AsyncWebSocketClient * c = _clients; - while(c != NULL && c->id() != id) - c = c->next; - if(c != NULL && c->status() == WS_CONNECTED) - return c; - return NULL; + for(const auto &c: _clients){ + if(c->id() == id && c->status() == WS_CONNECTED){ + return c; + } + } + return nullptr; } void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){ AsyncWebSocketClient * c = client(id); - if(c != NULL) + if(c) c->close(code, message); } void AsyncWebSocket::closeAll(uint16_t code, const char * message){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c->close(code, message); - c = c->next; } } void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){ AsyncWebSocketClient * c = client(id); - if(c != NULL) + if(c) c->ping(data, len); } void AsyncWebSocket::pingAll(uint8_t *data, size_t len){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c->ping(data, len); - c = c->next; } - } void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){ AsyncWebSocketClient * c = client(id); - if(c != NULL) + if(c) c->text(message, len); } void AsyncWebSocket::textAll(const char * message, size_t len){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c->text(message, len); - c = c->next; } } void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len){ AsyncWebSocketClient * c = client(id); - if(c != NULL) + if(c) c->binary(message, len); } void AsyncWebSocket::binaryAll(const char * message, size_t len){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c->binary(message, len); - c = c->next; } } void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){ AsyncWebSocketClient * c = client(id); - if(c != NULL) + if(c) c->message(message); } void AsyncWebSocket::messageAll(AsyncWebSocketMessage *message){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c->message(message); - c = c->next; } } size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){ AsyncWebSocketClient * c = client(id); - if(c != NULL){ + if(c){ va_list arg; va_start(arg, format); size_t len = c->printf(format, arg); @@ -854,11 +796,9 @@ void AsyncWebSocket::textAll(const String &message){ textAll(message.c_str(), message.length()); } void AsyncWebSocket::textAll(const __FlashStringHelper *message){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c->text(message); - c = c->next; } } void AsyncWebSocket::binary(uint32_t id, const char * message){ @@ -891,11 +831,9 @@ void AsyncWebSocket::binaryAll(const String &message){ binaryAll(message.c_str(), message.length()); } void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){ - AsyncWebSocketClient * c = _clients; - while(c != NULL){ + for(const auto& c: _clients){ if(c->status() == WS_CONNECTED) c-> binary(message, len); - c = c->next; } } @@ -952,7 +890,7 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){ * Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480 */ -AsyncWebSocketResponse::AsyncWebSocketResponse(String key, AsyncWebSocket *server){ +AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket *server){ _server = server; _code = 101; uint8_t * hash = (uint8_t*)malloc(20); diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index d5b06a5..1ef7d7b 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -52,13 +52,12 @@ class AsyncWebSocketMessage { bool _mask; AwsMessageStatus _status; public: - AsyncWebSocketMessage * next; - AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR),next(NULL){} + AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){} virtual ~AsyncWebSocketMessage(){} - virtual void ack(size_t len, uint32_t time){} - virtual size_t send(AsyncClient *client){ return 0; } + virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))){} + virtual size_t send(AsyncClient *client __attribute__((unused))){ return 0; } virtual bool finished(){ return _status != WS_MSG_SENDING; } - virtual bool betweenFrames(){ return false; } + virtual bool betweenFrames() const { return false; } }; class AsyncWebSocketClient { @@ -68,8 +67,8 @@ class AsyncWebSocketClient { uint32_t _clientId; AwsClientStatus _status; - AsyncWebSocketControl * _controlQueue; - AsyncWebSocketMessage * _messageQueue; + LinkedList _controlQueue; + LinkedList _messageQueue; uint8_t _pstate; AwsFrameInfo _pinfo; @@ -82,8 +81,6 @@ class AsyncWebSocketClient { void _runQueue(); public: - AsyncWebSocketClient * next; - AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server); ~AsyncWebSocketClient(); @@ -142,18 +139,18 @@ typedef std::function _clients; uint32_t _cNextId; AwsEventHandler _eventHandler; bool _enabled; public: - AsyncWebSocket(String url); + AsyncWebSocket(const String& url); ~AsyncWebSocket(); - const char * url(){ return _url.c_str(); } + const char * url() const { return _url.c_str(); } void enable(bool e){ _enabled = e; } - bool enabled() { return _enabled; } + bool enabled() const { return _enabled; } - size_t count(); + size_t count() const; AsyncWebSocketClient * client(uint32_t id); bool hasClient(uint32_t id){ return client(id) != NULL; } @@ -209,8 +206,8 @@ class AsyncWebSocket: public AsyncWebHandler { void _addClient(AsyncWebSocketClient * client); void _handleDisconnect(AsyncWebSocketClient * client); void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); - bool canHandle(AsyncWebServerRequest *request); - void handleRequest(AsyncWebServerRequest *request); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; }; //WebServer response to authenticate the socket and detach the tcp client from the web server request @@ -219,7 +216,7 @@ class AsyncWebSocketResponse: public AsyncWebServerResponse { String _content; AsyncWebSocket *_server; public: - AsyncWebSocketResponse(String key, AsyncWebSocket *server); + AsyncWebSocketResponse(const String& key, AsyncWebSocket *server); void _respond(AsyncWebServerRequest *request); size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); bool _sourceValid(){ return true; } diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 8e44899..535e387 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -76,14 +76,13 @@ class AsyncWebParameter { bool _isFile; public: - AsyncWebParameter *next; - AsyncWebParameter(String name, String value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file), next(NULL){} - String name(){ return _name; } - String value(){ return _value; } - size_t size(){ return _size; } - bool isPost(){ return _isForm; } - bool isFile(){ return _isFile; } + AsyncWebParameter(const String& name, const String& value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file){} + const String& name() const { return _name; } + const String& value() const { return _value; } + size_t size() const { return _size; } + bool isPost() const { return _isForm; } + bool isFile() const { return _isFile; } }; /* @@ -96,10 +95,8 @@ class AsyncWebHeader { String _value; public: - AsyncWebHeader *next; - - AsyncWebHeader(String name, String value): _name(name), _value(value), next(NULL){} - AsyncWebHeader(String data): _name(), _value(), next(NULL){ + AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){} + AsyncWebHeader(const String& data): _name(), _value(){ if(!data) return; int index = data.indexOf(':'); if (index < 0) return; @@ -107,9 +104,9 @@ class AsyncWebHeader { _value = data.substring(index + 2); } ~AsyncWebHeader(){} - String name(){ return _name; } - String value(){ return _value; } - String toString(){ return String(_name+": "+_value+"\r\n"); } + const String& name() const { return _name; } + const String& value() const { return _value; } + String toString() const { return String(_name+": "+_value+"\r\n"); } }; /* @@ -125,7 +122,7 @@ class AsyncWebServerRequest { AsyncWebServer* _server; AsyncWebHandler* _handler; AsyncWebServerResponse* _response; - StringArray* _interestingHeaders; + StringArray _interestingHeaders; String _temp; uint8_t _parseState; @@ -144,8 +141,8 @@ class AsyncWebServerRequest { size_t _contentLength; size_t _parsedLength; - AsyncWebHeader *_headers; - AsyncWebParameter *_params; + LinkedList _headers; + LinkedList _params; uint8_t _multiParseState; uint8_t _boundaryPosition; @@ -173,7 +170,7 @@ class AsyncWebServerRequest { void _parseLine(); void _parsePlainPostChar(uint8_t data); void _parseMultipartPostByte(uint8_t data, bool last); - void _addGetParams(String params); + void _addGetParams(const String& params); void _handleUploadStart(); void _handleUploadByte(uint8_t data, bool last); @@ -182,20 +179,19 @@ class AsyncWebServerRequest { public: File _tempFile; void *_tempObject; - AsyncWebServerRequest *next; AsyncWebServerRequest(AsyncWebServer*, AsyncClient*); ~AsyncWebServerRequest(); AsyncClient* client(){ return _client; } - uint8_t version(){ return _version; } - WebRequestMethodComposite method(){ return _method; } - String url(){ return _url; } - String host(){ return _host; } - String contentType(){ return _contentType; } - size_t contentLength(){ return _contentLength; } - bool multipart(){ return _isMultipart; } - const char * methodToString(); + uint8_t version() const { return _version; } + WebRequestMethodComposite method() const { return _method; } + const String& url() const { return _url; } + const String& host() const { return _host; } + const String& contentType() const { return _contentType; } + size_t contentLength() const { return _contentLength; } + bool multipart() const { return _isMultipart; } + const char * methodToString() const; //hash is the string representation of: @@ -206,52 +202,50 @@ class AsyncWebServerRequest { void requestAuthentication(const char * realm = NULL, bool isDigest = true); void setHandler(AsyncWebHandler *handler){ _handler = handler; } - void addInterestingHeader(String name); + void addInterestingHeader(const String& name); - void redirect(String url); + void redirect(const String& url); void send(AsyncWebServerResponse *response); - void send(int code, String contentType=String(), String content=String()); - void send(FS &fs, String path, String contentType=String(), bool download=false); - void send(File content, String path, String contentType=String(), bool download=false); - void send(Stream &stream, String contentType, size_t len); - void send(String contentType, size_t len, AwsResponseFiller callback); - void sendChunked(String contentType, AwsResponseFiller callback); - void send_P(int code, String contentType, const uint8_t * content, size_t len); - void send_P(int code, String contentType, PGM_P content); + void send(int code, const String& contentType=String(), const String& content=String()); + void send(FS &fs, const String& path, const String& contentType=String(), bool download=false); + void send(File content, const String& path, const String& contentType=String(), bool download=false); + void send(Stream &stream, const String& contentType, size_t len); + void send(const String& contentType, size_t len, AwsResponseFiller callback); + void sendChunked(const String& contentType, AwsResponseFiller callback); + void send_P(int code, const String& contentType, const uint8_t * content, size_t len); + void send_P(int code, const String& contentType, PGM_P content); - AsyncWebServerResponse *beginResponse(int code, String contentType=String(), String content=String()); - AsyncWebServerResponse *beginResponse(FS &fs, String path, String contentType=String(), bool download=false); - AsyncWebServerResponse *beginResponse(File content, String path, String contentType=String(), bool download=false); - AsyncWebServerResponse *beginResponse(Stream &stream, String contentType, size_t len); - AsyncWebServerResponse *beginResponse(String contentType, size_t len, AwsResponseFiller callback); - AsyncWebServerResponse *beginChunkedResponse(String contentType, AwsResponseFiller callback); - AsyncResponseStream *beginResponseStream(String contentType, size_t bufferSize=1460); - AsyncWebServerResponse *beginResponse_P(int code, String contentType, const uint8_t * content, size_t len); - AsyncWebServerResponse *beginResponse_P(int code, String contentType, PGM_P content); + AsyncWebServerResponse *beginResponse(int code, const String& contentType=String(), const String& content=String()); + AsyncWebServerResponse *beginResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false); + AsyncWebServerResponse *beginResponse(File content, const String& path, const String& contentType=String(), bool download=false); + AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len); + AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback); + AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback); + AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460); + AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len); + AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content); - int headers(); // get header count - bool hasHeader(String name); - AsyncWebHeader* getHeader(String name); - AsyncWebHeader* getHeader(int num); + size_t headers() const; // get header count + bool hasHeader(const String& name) const; // check if header exists + AsyncWebHeader* getHeader(const String& name) const; + AsyncWebHeader* getHeader(size_t num) const; - int params(); // get arguments count - bool hasParam(String name, bool post=false, bool file=false); - AsyncWebParameter* getParam(String name, bool post=false, bool file=false); - AsyncWebParameter* getParam(int num); + size_t params() const; // get arguments count + bool hasParam(const String& name, bool post=false, bool file=false) const; + AsyncWebParameter* getParam(const String& name, bool post=false, bool file=false) const; + AsyncWebParameter* getParam(size_t num) const; - int args(){ return params(); } // get arguments count - String arg(const char* name); // get request argument value by name - String arg(int i); // get request argument value by number - String argName(int i); // get request argument name by number - bool hasArg(const char* name); // check if argument exists + size_t args() const { return params(); } // get arguments count + const String& arg(const String& name) const; // get request argument value by name + const String& arg(size_t i) const; // get request argument value by number + const String& argName(size_t i) const; // get request argument name by number + bool hasArg(const char* name) const; // check if argument exists - String header(const char* name); // get request header value by name - String header(int i); // get request header value by number - String headerName(int i); // get request header name by number - bool hasHeader(const char* name); // check if header exists - - String urlDecode(const String& text); + const String& header(const char* name) const;// get request header value by name + const String& header(size_t i) const; // get request header value by number + const String& headerName(size_t i) const; // get request header name by number + String urlDecode(const String& text) const; }; /* @@ -260,13 +254,9 @@ class AsyncWebServerRequest { typedef std::function ArRequestFilterFunction; -static bool ON_STA_FILTER(AsyncWebServerRequest *request) { - return WiFi.localIP() == request->client()->localIP(); -} +bool ON_STA_FILTER(AsyncWebServerRequest *request); -static bool ON_AP_FILTER(AsyncWebServerRequest *request) { - return WiFi.localIP() != request->client()->localIP(); -} +bool ON_AP_FILTER(AsyncWebServerRequest *request); /* * REWRITE :: One instance can be handle any Request (done by the Server) @@ -279,8 +269,7 @@ class AsyncWebRewrite { String _params; ArRequestFilterFunction _filter; public: - AsyncWebRewrite* next; - AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL), next(NULL){ + AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL){ int index = _toUrl.indexOf('?'); if (index > 0) { _params = _toUrl.substring(index +1); @@ -288,10 +277,10 @@ class AsyncWebRewrite { } } AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } - bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); } - String from(void) { return _from; } - String toUrl(void) { return _toUrl; } - String params(void) { return _params; } + bool filter(AsyncWebServerRequest *request) const { return _filter == NULL || _filter(request); } + const String& from(void) const { return _from; } + const String& toUrl(void) const { return _toUrl; } + const String& params(void) const { return _params; } }; /* @@ -302,15 +291,16 @@ class AsyncWebHandler { protected: ArRequestFilterFunction _filter; public: - AsyncWebHandler* next; - AsyncWebHandler(): next(NULL){} + AsyncWebHandler(){} AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; } bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); } virtual ~AsyncWebHandler(){} - virtual bool canHandle(AsyncWebServerRequest *request){ return false; } - virtual void handleRequest(AsyncWebServerRequest *request){} - virtual void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){} - virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){} + virtual bool canHandle(AsyncWebServerRequest *request __attribute__((unused))){ + return false; + } + virtual void handleRequest(AsyncWebServerRequest *request __attribute__((unused))){} + virtual void handleUpload(AsyncWebServerRequest *request __attribute__((unused)), const String& filename __attribute__((unused)), size_t index __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), bool final __attribute__((unused))){} + virtual void handleBody(AsyncWebServerRequest *request __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), size_t index __attribute__((unused)), size_t total __attribute__((unused))){} }; /* @@ -324,7 +314,7 @@ typedef enum { class AsyncWebServerResponse { protected: int _code; - AsyncWebHeader *_headers; + LinkedList _headers; String _contentType; size_t _contentLength; bool _sendContentLength; @@ -341,13 +331,13 @@ class AsyncWebServerResponse { virtual ~AsyncWebServerResponse(); virtual void setCode(int code); virtual void setContentLength(size_t len); - virtual void setContentType(String type); - virtual void addHeader(String name, String value); + virtual void setContentType(const String& type); + virtual void addHeader(const String& name, const String& value); virtual String _assembleHead(uint8_t version); - virtual bool _started(); - virtual bool _finished(); - virtual bool _failed(); - virtual bool _sourceValid(); + virtual bool _started() const; + virtual bool _finished() const; + virtual bool _failed() const; + virtual bool _sourceValid() const; virtual void _respond(AsyncWebServerRequest *request); virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); }; @@ -357,14 +347,14 @@ class AsyncWebServerResponse { * */ typedef std::function ArRequestHandlerFunction; -typedef std::function ArUploadHandlerFunction; +typedef std::function ArUploadHandlerFunction; typedef std::function ArBodyHandlerFunction; class AsyncWebServer { protected: AsyncServer _server; - AsyncWebRewrite* _rewrites; - AsyncWebHandler* _handlers; + LinkedList _rewrites; + LinkedList _handlers; AsyncWebHandler* _catchAllHandler; public: @@ -380,7 +370,6 @@ class AsyncWebServer { AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite); bool removeRewrite(AsyncWebRewrite* rewrite); - AsyncWebRewrite& rewrite(const char* from, const char* to); AsyncWebHandler& addHandler(AsyncWebHandler* handler); diff --git a/src/SPIFFSEditor.cpp b/src/SPIFFSEditor.cpp index 612ba65..63935f1 100644 --- a/src/SPIFFSEditor.cpp +++ b/src/SPIFFSEditor.cpp @@ -317,7 +317,7 @@ const uint8_t edit_htm_gz[] PROGMEM = { // WEB HANDLER IMPLEMENTATION -SPIFFSEditor::SPIFFSEditor(String username, String password) +SPIFFSEditor::SPIFFSEditor(const String& username, const String& password) :_username(username) ,_password(password) ,_authenticated(false) @@ -418,7 +418,7 @@ void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request){ } } -void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ +void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ if(!index){ if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){ _authenticated = true; diff --git a/src/SPIFFSEditor.h b/src/SPIFFSEditor.h index 26ab884..e1c0d94 100644 --- a/src/SPIFFSEditor.h +++ b/src/SPIFFSEditor.h @@ -9,10 +9,10 @@ class SPIFFSEditor: public AsyncWebHandler { bool _authenticated; uint32_t _startTime; public: - SPIFFSEditor(String username=String(), String password=String()); - bool canHandle(AsyncWebServerRequest *request); - void handleRequest(AsyncWebServerRequest *request); - void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final); + SPIFFSEditor(const String& username=String(), const String& password=String()); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; + virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final; }; #endif diff --git a/src/StringArray.h b/src/StringArray.h index 8173b04..4c0aa70 100644 --- a/src/StringArray.h +++ b/src/StringArray.h @@ -24,88 +24,110 @@ #include "stddef.h" #include "WString.h" -class StringArrayItem; -class StringArrayItem { - private: - String _string; +template +class LinkedListNode { + T _value; public: - StringArrayItem *next; - StringArrayItem(String str):_string(str), next(NULL){} - ~StringArrayItem(){} - String string(){ return _string; } + LinkedListNode* next; + LinkedListNode(const T val): _value(val), next(nullptr) {} + ~LinkedListNode(){} + const T& value() const { return _value; }; + T& value(){ return _value; } }; -class StringArray { - private: - StringArrayItem *_items; +template class Item = LinkedListNode> +class LinkedList { public: - StringArray():_items(NULL){} - StringArray(StringArrayItem *items):_items(items){} - ~StringArray(){} - StringArrayItem *items(){ - return _items; - } - void add(String str){ - StringArrayItem *it = new StringArrayItem(str); - if(_items == NULL){ - _items = it; + typedef Item ItemType; + typedef std::function OnRemove; + typedef std::function Predicate; + private: + ItemType* _root; + OnRemove _onRemove; + + class Iterator { + ItemType* _node; + public: + Iterator(ItemType* current = nullptr) : _node(current) {} + Iterator(const Iterator& i) : _node(i._node) {} + Iterator& operator ++() { _node = _node->next; return *this; } + bool operator != (const Iterator& i) const { return _node != i._node; } + const T& operator * () const { return _node->value(); } + const T* operator -> () const { return &_node->value(); } + }; + + public: + typedef const Iterator ConstIterator; + ConstIterator begin() const { return ConstIterator(_root); } + ConstIterator end() const { return ConstIterator(nullptr); } + + LinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {} + ~LinkedList(){} + void add(const T& t){ + auto it = new ItemType(t); + if(!_root){ + _root = it; } else { - StringArrayItem *i = _items; - while(i->next != NULL) i = i->next; + auto i = _root; + while(i->next) i = i->next; i->next = it; } } - size_t length(){ + T& front() const { + return _root->value(); + } + + bool isEmpty() const { + return _root == nullptr; + } + size_t length() const { size_t i = 0; - StringArrayItem *it = _items; - while(it != NULL){ + auto it = _root; + while(it){ i++; it = it->next; } return i; } - bool contains(String str){ - StringArrayItem *it = _items; - while(it != NULL){ - if(it->string() == str) - return true; - it = it->next; - } - return false; - } - bool containsIgnoreCase(String str){ - StringArrayItem *it = _items; - while(it != NULL){ - if(it->string().equalsIgnoreCase(str)) - return true; - it = it->next; - } - return false; - } - String get(size_t index){ + size_t count_if(Predicate predicate) const { size_t i = 0; - StringArrayItem *it = _items; - while(it != NULL){ - if(i++ == index) - return it->string(); + auto it = _root; + while(it){ + if (!predicate){ + i++; + } + else if (predicate(it->value())) { + i++; + } it = it->next; } - return String(); + return i; } - bool remove(size_t index){ - StringArrayItem *it = _items; - if(!index){ - if(_items == NULL) - return false; - _items = _items->next; - delete it; - return true; - } + const T* nth(size_t N) const { size_t i = 0; - StringArrayItem *pit = _items; - while(it != NULL){ - if(i++ == index){ - pit->next = it->next; + auto it = _root; + while(it){ + if(i++ == N) + return &(it->value()); + it = it->next; + } + return nullptr; + } + bool remove(const T& t){ + auto it = _root; + auto pit = _root; + while(it){ + if(it->value() == t){ + if(it == _root){ + _root = _root->next; + } else { + pit->next = it->next; + } + + if (_onRemove) { + _onRemove(it->value()); + } + delete it; return true; } @@ -114,16 +136,19 @@ class StringArray { } return false; } - bool remove(String str){ - StringArrayItem *it = _items; - StringArrayItem *pit = _items; - while(it != NULL){ - if(it->string() == str){ - if(it == _items){ - _items = _items->next; + bool remove_first(Predicate predicate){ + auto it = _root; + auto pit = _root; + while(it){ + if(predicate(it->value())){ + if(it == _root){ + _root = _root->next; } else { pit->next = it->next; } + if (_onRemove) { + _onRemove(it->value()); + } delete it; return true; } @@ -132,16 +157,37 @@ class StringArray { } return false; } + void free(){ - StringArrayItem *it; - while(_items != NULL){ - it = _items; - _items = _items->next; + while(_root != nullptr){ + auto it = _root; + _root = _root->next; + if (_onRemove) { + _onRemove(it->value()); + } delete it; } + _root = nullptr; } }; +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/WebAuthentication.cpp b/src/WebAuthentication.cpp index 91b831c..5ca41ed 100644 --- a/src/WebAuthentication.cpp +++ b/src/WebAuthentication.cpp @@ -84,7 +84,7 @@ static String genRandomMD5(){ return res; } -static String stringMD5(String in){ +static String stringMD5(const String& in){ char * out = (char*)malloc(33); if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out)) return ""; diff --git a/src/WebHandlerImpl.h b/src/WebHandlerImpl.h index 5c1dda3..58e6b82 100644 --- a/src/WebHandlerImpl.h +++ b/src/WebHandlerImpl.h @@ -28,8 +28,8 @@ class AsyncStaticWebHandler: public AsyncWebHandler { private: bool _getFile(AsyncWebServerRequest *request); - bool _fileExists(AsyncWebServerRequest *request, const String path); - uint8_t _countBits(const uint8_t value); + bool _fileExists(AsyncWebServerRequest *request, const String& path); + uint8_t _countBits(const uint8_t value) const; protected: FS _fs; String _uri; @@ -42,8 +42,8 @@ class AsyncStaticWebHandler: public AsyncWebHandler { uint8_t _gzipStats; public: AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control); - bool canHandle(AsyncWebServerRequest *request); - void handleRequest(AsyncWebServerRequest *request); + virtual bool canHandle(AsyncWebServerRequest *request) override final; + virtual void handleRequest(AsyncWebServerRequest *request) override final; AsyncStaticWebHandler& setIsDir(bool isDir); AsyncStaticWebHandler& setDefaultFile(const char* filename); AsyncStaticWebHandler& setCacheControl(const char* cache_control); @@ -65,13 +65,14 @@ class AsyncCallbackWebHandler: public AsyncWebHandler { ArBodyHandlerFunction _onBody; public: AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL){} - void setUri(String uri){ _uri = uri; } + void setUri(const String& uri){ _uri = uri; } void setMethod(WebRequestMethodComposite method){ _method = method; } void onRequest(ArRequestHandlerFunction fn){ _onRequest = fn; } void onUpload(ArUploadHandlerFunction fn){ _onUpload = fn; } void onBody(ArBodyHandlerFunction fn){ _onBody = fn; } - bool canHandle(AsyncWebServerRequest *request){ + virtual bool canHandle(AsyncWebServerRequest *request) override final{ + if(!_onRequest) return false; @@ -84,17 +85,18 @@ class AsyncCallbackWebHandler: public AsyncWebHandler { request->addInterestingHeader("ANY"); return true; } - void handleRequest(AsyncWebServerRequest *request){ + + virtual void handleRequest(AsyncWebServerRequest *request) override final { if(_onRequest) _onRequest(request); else request->send(500); } - void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ + virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final { if(_onUpload) _onUpload(request, filename, index, data, len, final); } - void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ + virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final { if(_onBody) _onBody(request, data, len, index, total); } diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index dd1967f..2326664 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -79,8 +79,7 @@ AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(){ return setLastModified(last_modified); } #endif -bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request) -{ +bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request){ if (request->method() == HTTP_GET && request->url().startsWith(_uri) && _getFile(request)) { @@ -125,7 +124,7 @@ bool AsyncStaticWebHandler::_getFile(AsyncWebServerRequest *request) return _fileExists(request, path); } -bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String path) +bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String& path) { bool fileFound = false; bool gzipFound = false; @@ -167,7 +166,7 @@ bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const St return found; } -uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) +uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const { uint8_t w = value; uint8_t n; diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index 83d07c2..1b5163b 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -26,6 +26,8 @@ #define os_strlen strlen #endif +static const String SharedEmptyString = String(); + #define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '=')) enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL }; @@ -35,7 +37,6 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c) , _server(s) , _handler(NULL) , _response(NULL) - , _interestingHeaders(new StringArray()) , _temp() , _parseState(0) , _version(0) @@ -51,8 +52,8 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c) , _expectingContinue(false) , _contentLength(0) , _parsedLength(0) - , _headers(NULL) - , _params(NULL) + , _headers(LinkedList([](AsyncWebHeader *h){ delete h; })) + , _params(LinkedList([](AsyncWebParameter *p){ delete p; })) , _multiParseState(0) , _boundaryPosition(0) , _itemStartIndex(0) @@ -65,7 +66,6 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c) , _itemBufferIndex(0) , _itemIsFile(false) , _tempObject(NULL) - , next(NULL) { c->onError([](void *r, AsyncClient* c, int8_t error){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this); c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this); @@ -76,20 +76,11 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c) } AsyncWebServerRequest::~AsyncWebServerRequest(){ - while(_headers != NULL){ - AsyncWebHeader *h = _headers; - _headers = h->next; - delete h; - } + _headers.free(); - while(_params != NULL){ - AsyncWebParameter *p = _params; - _params = p->next; - delete p; - } + _params.free(); - _interestingHeaders->free(); - delete _interestingHeaders; + _interestingHeaders.free(); if(_response != NULL){ delete _response; @@ -199,18 +190,10 @@ void AsyncWebServerRequest::_onDisconnect(){ } void AsyncWebServerRequest::_addParam(AsyncWebParameter *p){ - if(p == NULL) - return; - if(_params == NULL) - _params = p; - else { - AsyncWebParameter *ps = _params; - while(ps->next != NULL) ps = ps->next; - ps->next = p; - } + _params.add(p); } -void AsyncWebServerRequest::_addGetParams(String params){ +void AsyncWebServerRequest::_addGetParams(const String& params){ size_t start = 0; while (start < params.length()){ int end = params.indexOf('&', start); @@ -294,15 +277,8 @@ bool AsyncWebServerRequest::_parseReqHeader(){ _authorization = value.substring(7); } } else { - if(_interestingHeaders->containsIgnoreCase(name) || _interestingHeaders->containsIgnoreCase("ANY")){ - AsyncWebHeader *h = new AsyncWebHeader(name, value); - if(_headers == NULL) - _headers = h; - else { - AsyncWebHeader *hs = _headers; - while(hs->next != NULL) hs = hs->next; - hs->next = h; - } + if(_interestingHeaders.containsIgnoreCase(name) || _interestingHeaders.containsIgnoreCase("ANY")){ + _headers.add(new AsyncWebHeader(name, value)); } } } @@ -541,89 +517,63 @@ void AsyncWebServerRequest::_parseLine(){ } } - -int AsyncWebServerRequest::headers(){ - int i = 0; - AsyncWebHeader* h = _headers; - while(h != NULL){ - i++; h = h->next; - } - return i; +size_t AsyncWebServerRequest::headers() const{ + return _headers.length(); } -bool AsyncWebServerRequest::hasHeader(String name){ - AsyncWebHeader* h = _headers; - while(h != NULL){ - if(h->name().equalsIgnoreCase(name)) +bool AsyncWebServerRequest::hasHeader(const String& name) const { + for(const auto& h: _headers){ + if(h->name().equalsIgnoreCase(name)){ return true; - h = h->next; + } } return false; } -AsyncWebHeader* AsyncWebServerRequest::getHeader(String name){ - AsyncWebHeader* h = _headers; - while(h != NULL){ - if(h->name().equalsIgnoreCase(name)) +AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const { + for(const auto& h: _headers){ + if(h->name().equalsIgnoreCase(name)){ return h; - h = h->next; + } } - return NULL; + return nullptr; } -AsyncWebHeader* AsyncWebServerRequest::getHeader(int num){ - int i = 0; - AsyncWebHeader* h = _headers; - while(h != NULL){ - if(num == i++) - return h; - h = h->next; - } - return NULL; +AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const { + auto header = _headers.nth(num); + return header ? *header : nullptr; } -int AsyncWebServerRequest::params(){ - int i = 0; - AsyncWebParameter* h = _params; - while(h != NULL){ - i++; h = h->next; - } - return i; +size_t AsyncWebServerRequest::params() const { + return _params.length(); } -bool AsyncWebServerRequest::hasParam(String name, bool post, bool file){ - AsyncWebParameter* h = _params; - while(h != NULL){ - if(h->name() == name && h->isPost() == post && h->isFile() == file) +bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const { + for(const auto& p: _params){ + if(p->name() == name && p->isPost() == post && p->isFile() == file){ return true; - h = h->next; + } } return false; } -AsyncWebParameter* AsyncWebServerRequest::getParam(String name, bool post, bool file){ - AsyncWebParameter* h = _params; - while(h != NULL){ - if(h->name() == name && h->isPost() == post && h->isFile() == file) - return h; - h = h->next; +AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const { + for(const auto& p: _params){ + if(p->name() == name && p->isPost() == post && p->isFile() == file){ + return p; + } } - return NULL; + return nullptr; } -AsyncWebParameter* AsyncWebServerRequest::getParam(int num){ - int i = 0; - AsyncWebParameter* h = _params; - while(h != NULL){ - if(num == i++) - return h; - h = h->next; - } - return NULL; +AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const { + auto param = _params.nth(num); + return param ? *param : nullptr; } -void AsyncWebServerRequest::addInterestingHeader(String name){ - if(!_interestingHeaders->containsIgnoreCase(name)) _interestingHeaders->add(name); +void AsyncWebServerRequest::addInterestingHeader(const String& name){ + if(!_interestingHeaders.containsIgnoreCase(name)) + _interestingHeaders.add(name); } void AsyncWebServerRequest::send(AsyncWebServerResponse *response){ @@ -642,85 +592,85 @@ void AsyncWebServerRequest::send(AsyncWebServerResponse *response){ _response->_respond(this); } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, String contentType, String content){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content){ return new AsyncBasicResponse(code, contentType, content); } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, String path, String contentType, bool download){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, const String& path, const String& contentType, bool download){ if(fs.exists(path) || (!download && fs.exists(path+".gz"))) return new AsyncFileResponse(fs, path, contentType, download); return NULL; } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, String path, String contentType, bool download){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download){ if(content == true) return new AsyncFileResponse(content, path, contentType, download); return NULL; } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, String contentType, size_t len){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len){ return new AsyncStreamResponse(stream, contentType, len); } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(String contentType, size_t len, AwsResponseFiller callback){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback){ return new AsyncCallbackResponse(contentType, len, callback); } -AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(String contentType, AwsResponseFiller callback){ +AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback){ if(_version) return new AsyncChunkedResponse(contentType, callback); return new AsyncCallbackResponse(contentType, 0, callback); } -AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(String contentType, size_t bufferSize){ +AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize){ return new AsyncResponseStream(contentType, bufferSize); } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, String contentType, const uint8_t * content, size_t len){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len){ return new AsyncProgmemResponse(code, contentType, content, len); } -AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, String contentType, PGM_P content){ +AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, PGM_P content){ return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content)); } -void AsyncWebServerRequest::send(int code, String contentType, String content){ +void AsyncWebServerRequest::send(int code, const String& contentType, const String& content){ send(beginResponse(code, contentType, content)); } -void AsyncWebServerRequest::send(FS &fs, String path, String contentType, bool download){ +void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download){ if(fs.exists(path) || (!download && fs.exists(path+".gz"))){ send(beginResponse(fs, path, contentType, download)); } else send(404); } -void AsyncWebServerRequest::send(File content, String path, String contentType, bool download){ +void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download){ if(content == true){ send(beginResponse(content, path, contentType, download)); } else send(404); } -void AsyncWebServerRequest::send(Stream &stream, String contentType, size_t len){ +void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len){ send(beginResponse(stream, contentType, len)); } -void AsyncWebServerRequest::send(String contentType, size_t len, AwsResponseFiller callback){ +void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback){ send(beginResponse(contentType, len, callback)); } -void AsyncWebServerRequest::sendChunked(String contentType, AwsResponseFiller callback){ +void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback){ send(beginChunkedResponse(contentType, callback)); } -void AsyncWebServerRequest::send_P(int code, String contentType, const uint8_t * content, size_t len){ +void AsyncWebServerRequest::send_P(int code, const String& contentType, const uint8_t * content, size_t len){ send(beginResponse_P(code, contentType, content, len)); } -void AsyncWebServerRequest::send_P(int code, String contentType, PGM_P content){ +void AsyncWebServerRequest::send_P(int code, const String& contentType, PGM_P content){ send(beginResponse_P(code, contentType, content)); } -void AsyncWebServerRequest::redirect(String url){ +void AsyncWebServerRequest::redirect(const String& url){ AsyncWebServerResponse * response = beginResponse(302); response->addHeader("Location",url); send(response); @@ -777,61 +727,48 @@ void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDig send(r); } -bool AsyncWebServerRequest::hasArg(const char* name){ - AsyncWebParameter* h = _params; - while(h != NULL){ - if(h->name() == String(name)) +bool AsyncWebServerRequest::hasArg(const char* name) const { + for(const auto& arg: _params){ + if(arg->name() == name){ return true; - h = h->next; + } } return false; } -String AsyncWebServerRequest::arg(const char* name){ - AsyncWebParameter* h = _params; - while(h != NULL){ - if(h->name() == String(name)) - return h->value(); - h = h->next; +const String& AsyncWebServerRequest::arg(const String& name) const { + for(const auto& arg: _params){ + if(arg->name() == name){ + return arg->value(); + } } - return String(); + return SharedEmptyString; } -String AsyncWebServerRequest::arg(int i){ +const String& AsyncWebServerRequest::arg(size_t i) const { return getParam(i)->value(); } -String AsyncWebServerRequest::argName(int i){ +const String& AsyncWebServerRequest::argName(size_t i) const { return getParam(i)->name(); } -String AsyncWebServerRequest::header(const char* name){ +const String& AsyncWebServerRequest::header(const char* name) const { AsyncWebHeader* h = getHeader(String(name)); - if(h) - return h->value(); - return String(); + return h ? h->value() : SharedEmptyString; } -String AsyncWebServerRequest::header(int i){ +const String& AsyncWebServerRequest::header(size_t i) const { AsyncWebHeader* h = getHeader(i); - if(h) - return h->value(); - return String(); + return h ? h->value() : SharedEmptyString; } -String AsyncWebServerRequest::headerName(int i){ +const String& AsyncWebServerRequest::headerName(size_t i) const { AsyncWebHeader* h = getHeader(i); - if(h) - return h->name(); - return String(); + return h ? h->name() : SharedEmptyString; } -bool AsyncWebServerRequest::hasHeader(const char* name){ - return hasHeader(String(name)); -} - - -String AsyncWebServerRequest::urlDecode(const String& text){ +String AsyncWebServerRequest::urlDecode(const String& text) const { char temp[] = "0x00"; unsigned int len = text.length(); unsigned int i = 0; @@ -855,7 +792,7 @@ String AsyncWebServerRequest::urlDecode(const String& text){ } -const char * AsyncWebServerRequest::methodToString(){ +const char * AsyncWebServerRequest::methodToString() const { if(_method == HTTP_ANY) return "ANY"; else if(_method & HTTP_GET) return "GET"; else if(_method & HTTP_POST) return "POST"; diff --git a/src/WebResponseImpl.h b/src/WebResponseImpl.h index 6e3b1a4..e0f4403 100644 --- a/src/WebResponseImpl.h +++ b/src/WebResponseImpl.h @@ -25,10 +25,10 @@ class AsyncBasicResponse: public AsyncWebServerResponse { private: String _content; public: - AsyncBasicResponse(int code, String contentType=String(), String content=String()); + AsyncBasicResponse(int code, const String& contentType=String(), const String& content=String()); void _respond(AsyncWebServerRequest *request); size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); - bool _sourceValid(){ return true; } + bool _sourceValid() const { return true; } }; class AsyncAbstractResponse: public AsyncWebServerResponse { @@ -37,57 +37,57 @@ class AsyncAbstractResponse: public AsyncWebServerResponse { public: void _respond(AsyncWebServerRequest *request); size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time); - bool _sourceValid(){ return false; } - virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen){ return 0; } + bool _sourceValid() const { return false; } + virtual size_t _fillBuffer(uint8_t *buf __attribute__((unused)), size_t maxLen __attribute__((unused))) { return 0; } }; class AsyncFileResponse: public AsyncAbstractResponse { private: File _content; String _path; - void _setContentType(String path); + void _setContentType(const String& path); public: - AsyncFileResponse(FS &fs, String path, String contentType=String(), bool download=false); - AsyncFileResponse(File content, String path, String contentType=String(), bool download=false); + AsyncFileResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false); + AsyncFileResponse(File content, const String& path, const String& contentType=String(), bool download=false); ~AsyncFileResponse(); - bool _sourceValid(){ return !!(_content); } - size_t _fillBuffer(uint8_t *buf, size_t maxLen); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; }; class AsyncStreamResponse: public AsyncAbstractResponse { private: Stream *_content; public: - AsyncStreamResponse(Stream &stream, String contentType, size_t len); - bool _sourceValid(){ return !!(_content); } - size_t _fillBuffer(uint8_t *buf, size_t maxLen); + AsyncStreamResponse(Stream &stream, const String& contentType, size_t len); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; }; class AsyncCallbackResponse: public AsyncAbstractResponse { private: AwsResponseFiller _content; public: - AsyncCallbackResponse(String contentType, size_t len, AwsResponseFiller callback); - bool _sourceValid(){ return !!(_content); } - size_t _fillBuffer(uint8_t *buf, size_t maxLen); + AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; }; class AsyncChunkedResponse: public AsyncAbstractResponse { private: AwsResponseFiller _content; public: - AsyncChunkedResponse(String contentType, AwsResponseFiller callback); - bool _sourceValid(){ return !!(_content); } - size_t _fillBuffer(uint8_t *buf, size_t maxLen); + AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback); + bool _sourceValid() const { return !!(_content); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; }; class AsyncProgmemResponse: public AsyncAbstractResponse { private: const uint8_t * _content; public: - AsyncProgmemResponse(int code, String contentType, const uint8_t * content, size_t len); - bool _sourceValid(){ return true; } - size_t _fillBuffer(uint8_t *buf, size_t maxLen); + AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len); + bool _sourceValid() const { return true; } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; }; class cbuf; @@ -96,10 +96,10 @@ class AsyncResponseStream: public AsyncAbstractResponse, public Print { private: cbuf *_content; public: - AsyncResponseStream(String contentType, size_t bufferSize); + AsyncResponseStream(const String& contentType, size_t bufferSize); ~AsyncResponseStream(); - bool _sourceValid(){ return (_state < RESPONSE_END); } - size_t _fillBuffer(uint8_t *buf, size_t maxLen); + bool _sourceValid() const { return (_state < RESPONSE_END); } + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; size_t write(const uint8_t *data, size_t len); size_t write(uint8_t data); using Print::write; diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index eacef6e..c0f60c8 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp @@ -73,7 +73,7 @@ const char* AsyncWebServerResponse::_responseCodeToString(int code) { AsyncWebServerResponse::AsyncWebServerResponse() : _code(0) - , _headers(NULL) + , _headers(LinkedList([](AsyncWebHeader *h){ delete h; })) , _contentType() , _contentLength(0) , _sendContentLength(true) @@ -86,11 +86,7 @@ AsyncWebServerResponse::AsyncWebServerResponse() {} AsyncWebServerResponse::~AsyncWebServerResponse(){ - while(_headers != NULL){ - AsyncWebHeader *h = _headers; - _headers = h->next; - delete h; - } + _headers.free(); } void AsyncWebServerResponse::setCode(int code){ @@ -103,20 +99,13 @@ void AsyncWebServerResponse::setContentLength(size_t len){ _contentLength = len; } -void AsyncWebServerResponse::setContentType(String type){ +void AsyncWebServerResponse::setContentType(const String& type){ if(_state == RESPONSE_SETUP) _contentType = type; } -void AsyncWebServerResponse::addHeader(String name, String value){ - AsyncWebHeader *header = new AsyncWebHeader(name, value); - if(_headers == NULL){ - _headers = header; - } else { - AsyncWebHeader *h = _headers; - while(h->next != NULL) h = h->next; - h->next = header; - } +void AsyncWebServerResponse::addHeader(const String& name, const String& value){ + _headers.add(new AsyncWebHeader(name, value)); } String AsyncWebServerResponse::_assembleHead(uint8_t version){ @@ -141,30 +130,28 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version){ out.concat(buf); } - AsyncWebHeader *h; - while(_headers != NULL){ - h = _headers; - _headers = _headers->next; - snprintf(buf, bufSize, "%s: %s\r\n", h->name().c_str(), h->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); - delete h; } + _headers.free(); + out.concat("\r\n"); _headLength = out.length(); return out; } -bool AsyncWebServerResponse::_started(){ return _state > RESPONSE_SETUP; } -bool AsyncWebServerResponse::_finished(){ return _state > RESPONSE_WAIT_ACK; } -bool AsyncWebServerResponse::_failed(){ return _state == RESPONSE_FAILED; } -bool AsyncWebServerResponse::_sourceValid(){ return false; } +bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; } +bool AsyncWebServerResponse::_finished() const { return _state > RESPONSE_WAIT_ACK; } +bool AsyncWebServerResponse::_failed() const { return _state == RESPONSE_FAILED; } +bool AsyncWebServerResponse::_sourceValid() const { return false; } void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_END; request->client()->close(); } size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ return 0; } /* * String/Code Response * */ -AsyncBasicResponse::AsyncBasicResponse(int code, String contentType, String content){ +AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const String& content){ _code = code; _content = content; _contentType = contentType; @@ -343,7 +330,7 @@ AsyncFileResponse::~AsyncFileResponse(){ _content.close(); } -void AsyncFileResponse::_setContentType(String path){ +void AsyncFileResponse::_setContentType(const String& path){ if (path.endsWith(".html")) _contentType = "text/html"; else if (path.endsWith(".htm")) _contentType = "text/html"; else if (path.endsWith(".css")) _contentType = "text/css"; @@ -365,7 +352,7 @@ void AsyncFileResponse::_setContentType(String path){ else _contentType = "text/plain"; } -AsyncFileResponse::AsyncFileResponse(FS &fs, String path, String contentType, bool download){ +AsyncFileResponse::AsyncFileResponse(FS &fs, const String& path, const String& contentType, bool download){ _code = 200; _path = path; @@ -397,7 +384,7 @@ AsyncFileResponse::AsyncFileResponse(FS &fs, String path, String contentType, bo } -AsyncFileResponse::AsyncFileResponse(File content, String path, String contentType, bool download){ +AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download){ _code = 200; _path = path; _content = content; @@ -432,7 +419,7 @@ size_t AsyncFileResponse::_fillBuffer(uint8_t *data, size_t len){ * Stream Response * */ -AsyncStreamResponse::AsyncStreamResponse(Stream &stream, String contentType, size_t len){ +AsyncStreamResponse::AsyncStreamResponse(Stream &stream, const String& contentType, size_t len){ _code = 200; _content = &stream; _contentLength = len; @@ -452,7 +439,7 @@ size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len){ * Callback Response * */ -AsyncCallbackResponse::AsyncCallbackResponse(String contentType, size_t len, AwsResponseFiller callback){ +AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback){ _code = 200; _content = callback; _contentLength = len; @@ -469,7 +456,7 @@ size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len){ * Chunked Response * */ -AsyncChunkedResponse::AsyncChunkedResponse(String contentType, AwsResponseFiller callback){ +AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback){ _code = 200; _content = callback; _contentLength = 0; @@ -486,7 +473,7 @@ size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len){ * Progmem Response * */ -AsyncProgmemResponse::AsyncProgmemResponse(int code, String contentType, const uint8_t * content, size_t len){ +AsyncProgmemResponse::AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len){ _code = code; _content = content; _contentType = contentType; @@ -508,7 +495,7 @@ 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(String contentType, size_t bufferSize){ +AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){ _code = 200; _contentLength = 0; _contentType = contentType; diff --git a/src/WebServer.cpp b/src/WebServer.cpp index 9875f22..f2538e8 100644 --- a/src/WebServer.cpp +++ b/src/WebServer.cpp @@ -21,8 +21,20 @@ #include "ESPAsyncWebServer.h" #include "WebHandlerImpl.h" +bool ON_STA_FILTER(AsyncWebServerRequest *request) { + return WiFi.localIP() == request->client()->localIP(); +} -AsyncWebServer::AsyncWebServer(uint16_t port):_server(port), _rewrites(0), _handlers(0){ +bool ON_AP_FILTER(AsyncWebServerRequest *request) { + return WiFi.localIP() != request->client()->localIP(); +} + + +AsyncWebServer::AsyncWebServer(uint16_t port) + : _server(port) + , _rewrites(LinkedList([](AsyncWebRewrite* r){ delete r; })) + , _handlers(LinkedList([](AsyncWebHandler* h){ delete h; })) +{ _catchAllHandler = new AsyncCallbackWebHandler(); if(_catchAllHandler == NULL) return; @@ -45,32 +57,12 @@ AsyncWebServer::~AsyncWebServer(){ } AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){ - if (_rewrites == NULL){ - _rewrites = rewrite; - } else { - AsyncWebRewrite *r = _rewrites; - while(r->next != NULL) r = r->next; - r->next = rewrite; - } + _rewrites.add(rewrite); return *rewrite; } bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite){ - if(rewrite == _rewrites){ - _rewrites = _rewrites->next; - return true; - } - AsyncWebRewrite *r = _rewrites; - while(r != NULL){ - if(rewrite == r->next){ - AsyncWebRewrite *d = r->next; - r->next = d->next; - delete d; - return true; - } - r = r->next; - } - return false; + return _rewrites.remove(rewrite); } AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){ @@ -78,32 +70,12 @@ AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){ } AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler){ - if(_handlers == NULL){ - _handlers = handler; - } else { - AsyncWebHandler* h = _handlers; - while(h->next != NULL) h = h->next; - h->next = handler; - } + _handlers.add(handler); return *handler; } bool AsyncWebServer::removeHandler(AsyncWebHandler *handler){ - if(handler == _handlers){ - _handlers = _handlers->next; - return true; - } - AsyncWebHandler *h = _handlers; - while(h != NULL){ - if(handler == h->next){ - AsyncWebHandler *d = h->next; - h->next = d->next; - delete d; - return true; - } - h = h->next; - } - return false; + return _handlers.remove(handler); } void AsyncWebServer::begin(){ @@ -125,27 +97,22 @@ void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request){ } void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request){ - AsyncWebRewrite *r = _rewrites; - while(r){ + for(const auto& r: _rewrites){ if (r->from() == request->_url && r->filter(request)){ request->_url = r->toUrl(); request->_addGetParams(r->params()); } - r = r->next; } } void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request){ - if(_handlers){ - AsyncWebHandler* h = _handlers; - while(h){ - if (h->filter(request) && h->canHandle(request)){ - request->setHandler(h); - return; - } - h = h->next; + for(const auto& h: _handlers){ + if (h->filter(request) && h->canHandle(request)){ + request->setHandler(h); + return; } } + request->addInterestingHeader("ANY"); request->setHandler(_catchAllHandler); } @@ -208,19 +175,8 @@ void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn){ } void AsyncWebServer::reset(){ - while(_rewrites != NULL){ - AsyncWebRewrite *r = _rewrites; - _rewrites = r->next; - delete r; - } - _rewrites = NULL; - - while(_handlers != NULL){ - AsyncWebHandler *h = _handlers; - _handlers = h->next; - delete h; - } - _handlers = NULL; + _rewrites.free(); + _handlers.free(); if (_catchAllHandler != NULL){ ((AsyncCallbackWebHandler*)_catchAllHandler)->onRequest(NULL);