Template container instead of direct pointer manipulation. (#95)

* using Container instead ofdirect pointers list manipulation

* fixed different type of virtual methods.

* Fixed typo in conditional

* Renamed ListArray to LinkedList

* Const reference to String as method parameters to prevent additional copy and memory allocation when String passed by value

* fix 'min' redefinition

* removed #include <iterator>
begin/end methods it's enough for 'for( : )' loop
count() renamed to length()
spacing fixing

* Const reference to String as method parameters to prevent additional copy and memory allocation when String passed by value

* Fixed unused params warnings
This commit is contained in:
Max Lunin 2016-11-27 17:42:09 +02:00 committed by Me No Dev
parent 3e6e890808
commit a7c4dfb04f
17 changed files with 478 additions and 659 deletions

View File

@ -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);

View File

@ -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 *>([](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);
}

View File

@ -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<AsyncEventSourceClient *> _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 {

View File

@ -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){

View File

@ -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 *>([](AsyncWebSocketControl *c){ delete c; }))
, _messageQueue(LinkedList<AsyncWebSocketMessage *>([](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 *>([](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);

View File

@ -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<AsyncWebSocketControl *> _controlQueue;
LinkedList<AsyncWebSocketMessage *> _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<void(AsyncWebSocket * server, AsyncWebSocketClient * clien
class AsyncWebSocket: public AsyncWebHandler {
private:
String _url;
AsyncWebSocketClient * _clients;
LinkedList<AsyncWebSocketClient *> _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; }

View File

@ -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<AsyncWebHeader *> _headers;
LinkedList<AsyncWebParameter *> _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<bool(AsyncWebServerRequest *request)> 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<AsyncWebHeader *> _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<void(AsyncWebServerRequest *request)> ArRequestHandlerFunction;
typedef std::function<void(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final)> ArUploadHandlerFunction;
typedef std::function<void(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final)> ArUploadHandlerFunction;
typedef std::function<void(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)> ArBodyHandlerFunction;
class AsyncWebServer {
protected:
AsyncServer _server;
AsyncWebRewrite* _rewrites;
AsyncWebHandler* _handlers;
LinkedList<AsyncWebRewrite*> _rewrites;
LinkedList<AsyncWebHandler*> _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);

View File

@ -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;

View File

@ -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

View File

@ -24,88 +24,110 @@
#include "stddef.h"
#include "WString.h"
class StringArrayItem;
class StringArrayItem {
private:
String _string;
template <typename T>
class LinkedListNode {
T _value;
public:
StringArrayItem *next;
StringArrayItem(String str):_string(str), next(NULL){}
~StringArrayItem(){}
String string(){ return _string; }
LinkedListNode<T>* 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 <typename T, template<typename> 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<T> ItemType;
typedef std::function<void(const T&)> OnRemove;
typedef std::function<bool(const T&)> 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<String> {
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_ */

View File

@ -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 "";

View File

@ -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);
}

View File

@ -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;

View File

@ -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 *>([](AsyncWebHeader *h){ delete h; }))
, _params(LinkedList<AsyncWebParameter *>([](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";

View File

@ -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;

View File

@ -73,7 +73,7 @@ const char* AsyncWebServerResponse::_responseCodeToString(int code) {
AsyncWebServerResponse::AsyncWebServerResponse()
: _code(0)
, _headers(NULL)
, _headers(LinkedList<AsyncWebHeader *>([](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;

View File

@ -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*>([](AsyncWebRewrite* r){ delete r; }))
, _handlers(LinkedList<AsyncWebHandler*>([](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);