Compare commits
	
		
			5 Commits
		
	
	
		
			patches
			...
			feature/vo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bdb9bd3625 | |||
| 165db0f093 | |||
| afbbf372bb | |||
| 71ab0b8e8c | |||
| 4ceb5c02d0 | 
@@ -18,11 +18,15 @@
 | 
				
			|||||||
  "platforms": ["espressif8266", "espressif32"],
 | 
					  "platforms": ["espressif8266", "espressif32"],
 | 
				
			||||||
  "dependencies": [
 | 
					  "dependencies": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					      "owner": "me-no-dev",
 | 
				
			||||||
      "name": "ESPAsyncTCP",
 | 
					      "name": "ESPAsyncTCP",
 | 
				
			||||||
 | 
					      "version": "^1.2.2",
 | 
				
			||||||
      "platforms": "espressif8266"
 | 
					      "platforms": "espressif8266"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					      "owner": "me-no-dev",      
 | 
				
			||||||
      "name": "AsyncTCP",
 | 
					      "name": "AsyncTCP",
 | 
				
			||||||
 | 
					      "version": "^1.1.1",
 | 
				
			||||||
      "platforms": "espressif32"
 | 
					      "platforms": "espressif32"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -137,16 +137,17 @@ size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) {
 | 
				
			|||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This could also return void as the return value is not used.
 | 
				
			||||||
 | 
					// Leaving as-is for compatibility...
 | 
				
			||||||
size_t AsyncEventSourceMessage::send(AsyncClient *client) {
 | 
					size_t AsyncEventSourceMessage::send(AsyncClient *client) {
 | 
				
			||||||
  const size_t len = _len - _sent;
 | 
					    if (_sent >= _len) {
 | 
				
			||||||
  if(client->space() < len){
 | 
					 | 
				
			||||||
      return 0;
 | 
					      return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  size_t sent = client->add((const char *)_data, len);
 | 
					    const size_t len_to_send = _len - _sent;
 | 
				
			||||||
  if(client->canSend())
 | 
					    auto position = reinterpret_cast<const char*>(_data + _sent);
 | 
				
			||||||
    client->send();
 | 
					    const size_t sent_now = client->write(position, len_to_send);
 | 
				
			||||||
  _sent += sent;
 | 
					    _sent += sent_now;
 | 
				
			||||||
  return sent;
 | 
					    return sent_now;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Client
 | 
					// Client
 | 
				
			||||||
@@ -173,7 +174,9 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncEventSourceClient::~AsyncEventSourceClient(){
 | 
					AsyncEventSourceClient::~AsyncEventSourceClient(){
 | 
				
			||||||
 | 
					  _lockmq.lock();
 | 
				
			||||||
  _messageQueue.free();
 | 
					  _messageQueue.free();
 | 
				
			||||||
 | 
					  _lockmq.unlock();
 | 
				
			||||||
  close();
 | 
					  close();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -184,33 +187,41 @@ void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage)
 | 
				
			|||||||
    delete dataMessage;
 | 
					    delete dataMessage;
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  //length() is not thread-safe, thus acquiring the lock before this call..
 | 
				
			||||||
 | 
					  _lockmq.lock();
 | 
				
			||||||
  if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){
 | 
					  if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){
 | 
				
			||||||
      ets_printf(String(F("ERROR: Too many messages queued\n")).c_str());
 | 
					      ets_printf(String(F("ERROR: Too many messages queued\n")).c_str());
 | 
				
			||||||
      delete dataMessage;
 | 
					      delete dataMessage;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    _messageQueue.add(dataMessage);
 | 
					    _messageQueue.add(dataMessage);
 | 
				
			||||||
  }
 | 
					    // runqueue trigger when new messages added
 | 
				
			||||||
  if(_client->canSend())
 | 
					    if(_client->canSend()) {
 | 
				
			||||||
      _runQueue();
 | 
					      _runQueue();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  _lockmq.unlock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){
 | 
					void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){
 | 
				
			||||||
 | 
					  // Same here, acquiring the lock early
 | 
				
			||||||
 | 
					  _lockmq.lock();
 | 
				
			||||||
  while(len && !_messageQueue.isEmpty()){
 | 
					  while(len && !_messageQueue.isEmpty()){
 | 
				
			||||||
    len = _messageQueue.front()->ack(len, time);
 | 
					    len = _messageQueue.front()->ack(len, time);
 | 
				
			||||||
    if(_messageQueue.front()->finished())
 | 
					    if(_messageQueue.front()->finished())
 | 
				
			||||||
      _messageQueue.remove(_messageQueue.front());
 | 
					      _messageQueue.remove(_messageQueue.front());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  _runQueue();
 | 
					  _runQueue();
 | 
				
			||||||
 | 
					  _lockmq.unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSourceClient::_onPoll(){
 | 
					void AsyncEventSourceClient::_onPoll(){
 | 
				
			||||||
 | 
					  _lockmq.lock();
 | 
				
			||||||
  if(!_messageQueue.isEmpty()){
 | 
					  if(!_messageQueue.isEmpty()){
 | 
				
			||||||
    _runQueue();
 | 
					    _runQueue();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  _lockmq.unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
 | 
					void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
 | 
				
			||||||
  _client->close(true);
 | 
					  _client->close(true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -225,7 +236,7 @@ void AsyncEventSourceClient::close(){
 | 
				
			|||||||
    _client->close();
 | 
					    _client->close();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSourceClient::write(const char * message, size_t len){
 | 
					void AsyncEventSourceClient::_write(const char * message, size_t len){
 | 
				
			||||||
  _queueMessage(new AsyncEventSourceMessage(message, len));
 | 
					  _queueMessage(new AsyncEventSourceMessage(message, len));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -234,17 +245,25 @@ void AsyncEventSourceClient::send(const char *message, const char *event, uint32
 | 
				
			|||||||
  _queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length()));
 | 
					  _queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSourceClient::_runQueue(){
 | 
					size_t AsyncEventSourceClient::packetsWaiting() const {
 | 
				
			||||||
  while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){
 | 
					    size_t len;
 | 
				
			||||||
    _messageQueue.remove(_messageQueue.front());
 | 
					    _lockmq.lock();
 | 
				
			||||||
 | 
					    len = _messageQueue.length();
 | 
				
			||||||
 | 
					    _lockmq.unlock();
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for(auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i)
 | 
					void AsyncEventSourceClient::_runQueue() {
 | 
				
			||||||
  {
 | 
					  // Calls to this private method now already protected by _lockmq acquisition
 | 
				
			||||||
    if(!(*i)->sent())
 | 
					  // so no extra call of _lockmq.lock() here..
 | 
				
			||||||
 | 
					  for (auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i) {
 | 
				
			||||||
 | 
					    // If it crashes here, iterator (i) has been invalidated as _messageQueue
 | 
				
			||||||
 | 
					    // has been changed... (UL 2020-11-15: Not supposed to happen any more ;-) )
 | 
				
			||||||
 | 
					    if (!(*i)->sent()) {
 | 
				
			||||||
      (*i)->send(_client);
 | 
					      (*i)->send(_client);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Handler
 | 
					// Handler
 | 
				
			||||||
@@ -280,17 +299,22 @@ void AsyncEventSource::_addClient(AsyncEventSourceClient * client){
 | 
				
			|||||||
    client->write((const char *)temp, 2053);
 | 
					    client->write((const char *)temp, 2053);
 | 
				
			||||||
    free(temp);
 | 
					    free(temp);
 | 
				
			||||||
  }*/
 | 
					  }*/
 | 
				
			||||||
 | 
					  AsyncWebLockGuard l(_client_queue_lock);
 | 
				
			||||||
  _clients.add(client);
 | 
					  _clients.add(client);
 | 
				
			||||||
  if(_connectcb)
 | 
					  if(_connectcb)
 | 
				
			||||||
    _connectcb(client);
 | 
					    _connectcb(client);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
 | 
					void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
 | 
				
			||||||
 | 
					  AsyncWebLockGuard l(_client_queue_lock);
 | 
				
			||||||
  _clients.remove(client);
 | 
					  _clients.remove(client);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSource::close(){
 | 
					void AsyncEventSource::close(){
 | 
				
			||||||
 | 
					  // While the whole loop is not done, the linked list is locked and so the
 | 
				
			||||||
 | 
					  // iterator should remain valid even when AsyncEventSource::_handleDisconnect()
 | 
				
			||||||
 | 
					  // is called very early
 | 
				
			||||||
 | 
					  AsyncWebLockGuard l(_client_queue_lock);
 | 
				
			||||||
  for(const auto &c: _clients){
 | 
					  for(const auto &c: _clients){
 | 
				
			||||||
    if(c->connected())
 | 
					    if(c->connected())
 | 
				
			||||||
      c->close();
 | 
					      c->close();
 | 
				
			||||||
@@ -299,37 +323,39 @@ void AsyncEventSource::close(){
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// pmb fix
 | 
					// pmb fix
 | 
				
			||||||
size_t AsyncEventSource::avgPacketsWaiting() const {
 | 
					size_t AsyncEventSource::avgPacketsWaiting() const {
 | 
				
			||||||
  if(_clients.isEmpty())
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  size_t aql = 0;
 | 
					  size_t aql = 0;
 | 
				
			||||||
  uint32_t nConnectedClients = 0;
 | 
					  uint32_t nConnectedClients = 0;
 | 
				
			||||||
 | 
					  AsyncWebLockGuard l(_client_queue_lock);
 | 
				
			||||||
 | 
					  if (_clients.isEmpty()) {
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  for(const auto &c: _clients){
 | 
					  for(const auto &c: _clients){
 | 
				
			||||||
    if(c->connected()) {
 | 
					    if(c->connected()) {
 | 
				
			||||||
      aql += c->packetsWaiting();
 | 
					      aql += c->packetsWaiting();
 | 
				
			||||||
      ++nConnectedClients;
 | 
					      ++nConnectedClients;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
//  return aql / nConnectedClients;
 | 
					 | 
				
			||||||
  return ((aql) + (nConnectedClients/2)) / (nConnectedClients); // round up
 | 
					  return ((aql) + (nConnectedClients/2)) / (nConnectedClients); // round up
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){
 | 
					void AsyncEventSource::send(
 | 
				
			||||||
 | 
					    const char *message, const char *event, uint32_t id, uint32_t reconnect){
 | 
				
			||||||
 | 
					 | 
				
			||||||
  String ev = generateEventMessage(message, event, id, reconnect);
 | 
					  String ev = generateEventMessage(message, event, id, reconnect);
 | 
				
			||||||
 | 
					  AsyncWebLockGuard l(_client_queue_lock);
 | 
				
			||||||
  for(const auto &c: _clients){
 | 
					  for(const auto &c: _clients){
 | 
				
			||||||
    if(c->connected()) {
 | 
					    if(c->connected()) {
 | 
				
			||||||
      c->write(ev.c_str(), ev.length());
 | 
					      c->_write(ev.c_str(), ev.length());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t AsyncEventSource::count() const {
 | 
					size_t AsyncEventSource::count() const {
 | 
				
			||||||
  return _clients.count_if([](AsyncEventSourceClient *c){
 | 
					  size_t n_clients;
 | 
				
			||||||
 | 
					  AsyncWebLockGuard l(_client_queue_lock);
 | 
				
			||||||
 | 
					  n_clients = _clients.count_if([](AsyncEventSourceClient *c){
 | 
				
			||||||
                                    return c->connected();
 | 
					                                    return c->connected();
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
 | 
					  return n_clients;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){
 | 
					bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,6 +73,8 @@ class AsyncEventSourceClient {
 | 
				
			|||||||
    AsyncEventSource *_server;
 | 
					    AsyncEventSource *_server;
 | 
				
			||||||
    uint32_t _lastId;
 | 
					    uint32_t _lastId;
 | 
				
			||||||
    LinkedList<AsyncEventSourceMessage *> _messageQueue;
 | 
					    LinkedList<AsyncEventSourceMessage *> _messageQueue;
 | 
				
			||||||
 | 
					    // ArFi 2020-08-27 for protecting/serializing _messageQueue
 | 
				
			||||||
 | 
					    AsyncPlainLock _lockmq;
 | 
				
			||||||
    void _queueMessage(AsyncEventSourceMessage *dataMessage);
 | 
					    void _queueMessage(AsyncEventSourceMessage *dataMessage);
 | 
				
			||||||
    void _runQueue();
 | 
					    void _runQueue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,12 +85,12 @@ class AsyncEventSourceClient {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    AsyncClient* client(){ return _client; }
 | 
					    AsyncClient* client(){ return _client; }
 | 
				
			||||||
    void close();
 | 
					    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);
 | 
					    void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
 | 
				
			||||||
    bool connected() const { return (_client != NULL) && _client->connected(); }
 | 
					    bool connected() const { return (_client != NULL) && _client->connected(); }
 | 
				
			||||||
    uint32_t lastId() const { return _lastId; }
 | 
					    uint32_t lastId() const { return _lastId; }
 | 
				
			||||||
    size_t  packetsWaiting() const { return _messageQueue.length(); }
 | 
					    size_t  packetsWaiting() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void _write(const char * message, size_t len);
 | 
				
			||||||
    //system callbacks (do not call)
 | 
					    //system callbacks (do not call)
 | 
				
			||||||
    void _onAck(size_t len, uint32_t time);
 | 
					    void _onAck(size_t len, uint32_t time);
 | 
				
			||||||
    void _onPoll(); 
 | 
					    void _onPoll(); 
 | 
				
			||||||
@@ -100,6 +102,9 @@ class AsyncEventSource: public AsyncWebHandler {
 | 
				
			|||||||
  private:
 | 
					  private:
 | 
				
			||||||
    String _url;
 | 
					    String _url;
 | 
				
			||||||
    LinkedList<AsyncEventSourceClient *> _clients;
 | 
					    LinkedList<AsyncEventSourceClient *> _clients;
 | 
				
			||||||
 | 
					    // Same as for individual messages, protect mutations of _clients list
 | 
				
			||||||
 | 
					    // since simultaneous access from different tasks is possible
 | 
				
			||||||
 | 
					    AsyncWebLock _client_queue_lock;
 | 
				
			||||||
    ArEventHandlerFunction _connectcb;
 | 
					    ArEventHandlerFunction _connectcb;
 | 
				
			||||||
	ArAuthorizeConnectHandler _authorizeConnectHandler;
 | 
						ArAuthorizeConnectHandler _authorizeConnectHandler;
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
@@ -111,7 +116,7 @@ class AsyncEventSource: public AsyncWebHandler {
 | 
				
			|||||||
    void onConnect(ArEventHandlerFunction cb);
 | 
					    void onConnect(ArEventHandlerFunction cb);
 | 
				
			||||||
    void authorizeConnect(ArAuthorizeConnectHandler cb);
 | 
					    void authorizeConnect(ArAuthorizeConnectHandler cb);
 | 
				
			||||||
    void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
 | 
					    void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
 | 
				
			||||||
    size_t count() const; //number clinets connected
 | 
					    size_t count() const; //number clients connected
 | 
				
			||||||
    size_t  avgPacketsWaiting() const;
 | 
					    size_t  avgPacketsWaiting() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //system callbacks (do not call)
 | 
					    //system callbacks (do not call)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,8 +41,10 @@
 | 
				
			|||||||
#if ARDUINOJSON_VERSION_MAJOR == 5
 | 
					#if ARDUINOJSON_VERSION_MAJOR == 5
 | 
				
			||||||
  #define ARDUINOJSON_5_COMPATIBILITY
 | 
					  #define ARDUINOJSON_5_COMPATIBILITY
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					  #ifndef DYNAMIC_JSON_DOCUMENT_SIZE
 | 
				
			||||||
    #define DYNAMIC_JSON_DOCUMENT_SIZE  1024
 | 
					    #define DYNAMIC_JSON_DOCUMENT_SIZE  1024
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr const char* JSON_MIMETYPE = "application/json";
 | 
					constexpr const char* JSON_MIMETYPE = "application/json";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -24,7 +24,7 @@
 | 
				
			|||||||
#include <Arduino.h>
 | 
					#include <Arduino.h>
 | 
				
			||||||
#ifdef ESP32
 | 
					#ifdef ESP32
 | 
				
			||||||
#include <AsyncTCP.h>
 | 
					#include <AsyncTCP.h>
 | 
				
			||||||
#define WS_MAX_QUEUED_MESSAGES 32
 | 
					#define WS_MAX_QUEUED_MESSAGES 16
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#include <ESPAsyncTCP.h>
 | 
					#include <ESPAsyncTCP.h>
 | 
				
			||||||
#define WS_MAX_QUEUED_MESSAGES 8
 | 
					#define WS_MAX_QUEUED_MESSAGES 8
 | 
				
			||||||
@@ -33,6 +33,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "AsyncWebSynchronization.h"
 | 
					#include "AsyncWebSynchronization.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef ESP8266
 | 
					#ifdef ESP8266
 | 
				
			||||||
#include <Hash.h>
 | 
					#include <Hash.h>
 | 
				
			||||||
#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library
 | 
					#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library
 | 
				
			||||||
@@ -46,6 +50,8 @@
 | 
				
			|||||||
#define DEFAULT_MAX_WS_CLIENTS 4
 | 
					#define DEFAULT_MAX_WS_CLIENTS 4
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using AsyncWebSocketMessageBuffer = std::shared_ptr<std::vector<uint8_t>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AsyncWebSocket;
 | 
					class AsyncWebSocket;
 | 
				
			||||||
class AsyncWebSocketResponse;
 | 
					class AsyncWebSocketResponse;
 | 
				
			||||||
class AsyncWebSocketClient;
 | 
					class AsyncWebSocketClient;
 | 
				
			||||||
@@ -80,78 +86,26 @@ typedef enum { WS_CONTINUATION, WS_TEXT, WS_BINARY, WS_DISCONNECT = 0x08, WS_PIN
 | 
				
			|||||||
typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
 | 
					typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
 | 
				
			||||||
typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
 | 
					typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AsyncWebSocketMessageBuffer {
 | 
					
 | 
				
			||||||
 | 
					class AsyncWebSocketMessage
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    uint8_t * _data;
 | 
					    std::shared_ptr<std::vector<uint8_t>> _WSbuffer;
 | 
				
			||||||
    size_t _len;
 | 
					    uint8_t _opcode{WS_TEXT};
 | 
				
			||||||
    bool _lock;
 | 
					    bool _mask{false};
 | 
				
			||||||
    uint32_t _count;
 | 
					    AwsMessageStatus _status{WS_MSG_ERROR};
 | 
				
			||||||
 | 
					    size_t _sent{};
 | 
				
			||||||
 | 
					    size_t _ack{};
 | 
				
			||||||
 | 
					    size_t _acked{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    AsyncWebSocketMessageBuffer();
 | 
					    AsyncWebSocketMessage(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode=WS_TEXT, bool mask=false);
 | 
				
			||||||
    AsyncWebSocketMessageBuffer(size_t size);
 | 
					 | 
				
			||||||
    AsyncWebSocketMessageBuffer(uint8_t * data, size_t size);
 | 
					 | 
				
			||||||
    AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer &);
 | 
					 | 
				
			||||||
    AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer &&);
 | 
					 | 
				
			||||||
    ~AsyncWebSocketMessageBuffer();
 | 
					 | 
				
			||||||
    void operator ++(int i) { (void)i; _count++; }
 | 
					 | 
				
			||||||
    void operator --(int i) { (void)i; if (_count > 0) { _count--; } ;  }
 | 
					 | 
				
			||||||
    bool reserve(size_t size);
 | 
					 | 
				
			||||||
    void lock() { _lock = true; }
 | 
					 | 
				
			||||||
    void unlock() { _lock = false; }
 | 
					 | 
				
			||||||
    uint8_t * get() { return _data; }
 | 
					 | 
				
			||||||
    size_t length() { return _len; }
 | 
					 | 
				
			||||||
    uint32_t count() { return _count; }
 | 
					 | 
				
			||||||
    bool canDelete() { return (!_count && !_lock); }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    friend AsyncWebSocket;
 | 
					    bool finished() const { return _status != WS_MSG_SENDING; }
 | 
				
			||||||
 | 
					    bool betweenFrames() const { return _acked == _ack; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					    void ack(size_t len, uint32_t time);
 | 
				
			||||||
 | 
					    size_t send(AsyncClient *client);
 | 
				
			||||||
class AsyncWebSocketMessage {
 | 
					 | 
				
			||||||
  protected:
 | 
					 | 
				
			||||||
    uint8_t _opcode;
 | 
					 | 
				
			||||||
    bool _mask;
 | 
					 | 
				
			||||||
    AwsMessageStatus _status;
 | 
					 | 
				
			||||||
  public:
 | 
					 | 
				
			||||||
    AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){}
 | 
					 | 
				
			||||||
    virtual ~AsyncWebSocketMessage(){}
 | 
					 | 
				
			||||||
    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() const { return false; }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage {
 | 
					 | 
				
			||||||
  private:
 | 
					 | 
				
			||||||
    size_t _len;
 | 
					 | 
				
			||||||
    size_t _sent;
 | 
					 | 
				
			||||||
    size_t _ack;
 | 
					 | 
				
			||||||
    size_t _acked;
 | 
					 | 
				
			||||||
    uint8_t * _data;
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode=WS_TEXT, bool mask=false);
 | 
					 | 
				
			||||||
    AsyncWebSocketBasicMessage(uint8_t opcode=WS_TEXT, bool mask=false);
 | 
					 | 
				
			||||||
    virtual ~AsyncWebSocketBasicMessage() override;
 | 
					 | 
				
			||||||
    virtual bool betweenFrames() const override { return _acked == _ack; }
 | 
					 | 
				
			||||||
    virtual void ack(size_t len, uint32_t time) override ;
 | 
					 | 
				
			||||||
    virtual size_t send(AsyncClient *client) override ;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage {
 | 
					 | 
				
			||||||
  private:
 | 
					 | 
				
			||||||
    uint8_t * _data;
 | 
					 | 
				
			||||||
    size_t _len;
 | 
					 | 
				
			||||||
    size_t _sent;
 | 
					 | 
				
			||||||
    size_t _ack;
 | 
					 | 
				
			||||||
    size_t _acked;
 | 
					 | 
				
			||||||
    AsyncWebSocketMessageBuffer * _WSbuffer;
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode=WS_TEXT, bool mask=false);
 | 
					 | 
				
			||||||
    virtual ~AsyncWebSocketMultiMessage() override;
 | 
					 | 
				
			||||||
    virtual bool betweenFrames() const override { return _acked == _ack; }
 | 
					 | 
				
			||||||
    virtual void ack(size_t len, uint32_t time) override ;
 | 
					 | 
				
			||||||
    virtual size_t send(AsyncClient *client) override ;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AsyncWebSocketClient {
 | 
					class AsyncWebSocketClient {
 | 
				
			||||||
@@ -161,8 +115,10 @@ class AsyncWebSocketClient {
 | 
				
			|||||||
    uint32_t _clientId;
 | 
					    uint32_t _clientId;
 | 
				
			||||||
    AwsClientStatus _status;
 | 
					    AwsClientStatus _status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LinkedList<AsyncWebSocketControl *> _controlQueue;
 | 
					    AsyncWebLock _lock;
 | 
				
			||||||
    LinkedList<AsyncWebSocketMessage *> _messageQueue;
 | 
					
 | 
				
			||||||
 | 
					    std::deque<AsyncWebSocketControl> _controlQueue;
 | 
				
			||||||
 | 
					    std::deque<AsyncWebSocketMessage> _messageQueue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t _pstate;
 | 
					    uint8_t _pstate;
 | 
				
			||||||
    AwsFrameInfo _pinfo;
 | 
					    AwsFrameInfo _pinfo;
 | 
				
			||||||
@@ -170,8 +126,8 @@ class AsyncWebSocketClient {
 | 
				
			|||||||
    uint32_t _lastMessageTime;
 | 
					    uint32_t _lastMessageTime;
 | 
				
			||||||
    uint32_t _keepAlivePeriod;
 | 
					    uint32_t _keepAlivePeriod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void _queueMessage(AsyncWebSocketMessage *dataMessage);
 | 
					    void _queueControl(uint8_t opcode, const uint8_t *data=NULL, size_t len=0, bool mask=false);
 | 
				
			||||||
    void _queueControl(AsyncWebSocketControl *controlMessage);
 | 
					    void _queueMessage(std::shared_ptr<std::vector<uint8_t>> buffer, uint8_t opcode=WS_TEXT, bool mask=false);
 | 
				
			||||||
    void _runQueue();
 | 
					    void _runQueue();
 | 
				
			||||||
    void _clearQueue();
 | 
					    void _clearQueue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -182,18 +138,22 @@ class AsyncWebSocketClient {
 | 
				
			|||||||
    ~AsyncWebSocketClient();
 | 
					    ~AsyncWebSocketClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //client id increments for the given server
 | 
					    //client id increments for the given server
 | 
				
			||||||
    uint32_t id(){ return _clientId; }
 | 
					    uint32_t id() const { return _clientId; }
 | 
				
			||||||
    AwsClientStatus status(){ return _status; }
 | 
					    AwsClientStatus status() const { return _status; }
 | 
				
			||||||
    AsyncClient* client() { return _client; }
 | 
					    AsyncClient* client() { return _client; }
 | 
				
			||||||
 | 
					    const AsyncClient* client() const { return _client; }
 | 
				
			||||||
    AsyncWebSocket *server(){ return _server; }
 | 
					    AsyncWebSocket *server(){ return _server; }
 | 
				
			||||||
 | 
					    const AsyncWebSocket *server() const { return _server; }
 | 
				
			||||||
    AwsFrameInfo const &pinfo() const { return _pinfo; }
 | 
					    AwsFrameInfo const &pinfo() const { return _pinfo; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IPAddress remoteIP();
 | 
					    IPAddress remoteIP() const;
 | 
				
			||||||
    uint16_t  remotePort();
 | 
					    uint16_t  remotePort() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool shouldBeDeleted() const { return !_client; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //control frames
 | 
					    //control frames
 | 
				
			||||||
    void close(uint16_t code=0, const char * message=NULL);
 | 
					    void close(uint16_t code=0, const char * message=NULL);
 | 
				
			||||||
    void ping(uint8_t *data=NULL, size_t len=0);
 | 
					    void ping(const uint8_t *data=NULL, size_t len=0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //set auto-ping period in seconds. disabled if zero (default)
 | 
					    //set auto-ping period in seconds. disabled if zero (default)
 | 
				
			||||||
    void keepAlivePeriod(uint16_t seconds){
 | 
					    void keepAlivePeriod(uint16_t seconds){
 | 
				
			||||||
@@ -204,31 +164,49 @@ class AsyncWebSocketClient {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //data packets
 | 
					    //data packets
 | 
				
			||||||
    void message(AsyncWebSocketMessage *message){ _queueMessage(message); }
 | 
					    /**
 | 
				
			||||||
    bool queueIsFull();
 | 
					     * @brief allocate memory buffer owned by shared-pointer and copy provided data
 | 
				
			||||||
    size_t queueLen() { return _messageQueue.length() + _controlQueue.length(); }
 | 
					     * used to keep the data untill websocket send is complete for single/multiple clients
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param message 
 | 
				
			||||||
 | 
					     * @param len 
 | 
				
			||||||
 | 
					     * @return AsyncWebSocketMessageBuffer 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    AsyncWebSocketMessageBuffer makeBuffer(const uint8_t *message, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief allocate empty memory buffer owned by shared-pointer
 | 
				
			||||||
 | 
					     * used to keep the data untill websocket send is complete for single/multiple clients
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param len 
 | 
				
			||||||
 | 
					     * @return AsyncWebSocketMessageBuffer 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    inline AsyncWebSocketMessageBuffer makeBuffer(size_t len){ return std::make_shared<std::vector<uint8_t>>(len); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void message(AsyncWebSocketMessageBuffer buffer, uint8_t opcode=WS_TEXT, bool mask=false) { _queueMessage(buffer, opcode, mask); }
 | 
				
			||||||
 | 
					    bool queueIsFull() const;
 | 
				
			||||||
 | 
					    size_t queueLen() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t printf(const char *format, ...)  __attribute__ ((format (printf, 2, 3)));
 | 
					    size_t printf(const char *format, ...)  __attribute__ ((format (printf, 2, 3)));
 | 
				
			||||||
#ifndef ESP32
 | 
					#ifndef ESP32
 | 
				
			||||||
    size_t printf_P(PGM_P formatP, ...)  __attribute__ ((format (printf, 2, 3)));
 | 
					    size_t printf_P(PGM_P formatP, ...)  __attribute__ ((format (printf, 2, 3)));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    void text(const char * message, size_t len);
 | 
					 | 
				
			||||||
    void text(const char * message);
 | 
					 | 
				
			||||||
    void text(uint8_t * message, size_t len);
 | 
					 | 
				
			||||||
    void text(char * message);
 | 
					 | 
				
			||||||
    void text(const String &message);
 | 
					 | 
				
			||||||
    void text(const __FlashStringHelper *data);
 | 
					 | 
				
			||||||
    void text(AsyncWebSocketMessageBuffer *buffer);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void binary(const char * message, size_t len);
 | 
					    inline void text(AsyncWebSocketMessageBuffer buffer){ _queueMessage(buffer); };
 | 
				
			||||||
    void binary(const char * message);
 | 
					    inline void text(const uint8_t *message, size_t len){ text(makeBuffer(message, len)); };
 | 
				
			||||||
    void binary(uint8_t * message, size_t len);
 | 
					    inline void text(const char *message, size_t len){ text((const uint8_t *)message, len); };
 | 
				
			||||||
    void binary(char * message);
 | 
					    inline void text(const char *message){ text(message, strlen(message)); };
 | 
				
			||||||
    void binary(const String &message);
 | 
					    inline void text(const String &message){ text(message.c_str(), message.length()); };
 | 
				
			||||||
    void binary(const __FlashStringHelper *data, size_t len);
 | 
					    void text(const __FlashStringHelper *message);
 | 
				
			||||||
    void binary(AsyncWebSocketMessageBuffer *buffer);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool canSend() { return _messageQueue.length() < WS_MAX_QUEUED_MESSAGES; }
 | 
					    inline void binary(AsyncWebSocketMessageBuffer buffer){ _queueMessage(buffer, WS_BINARY); };
 | 
				
			||||||
 | 
					    inline void binary(const uint8_t *message, size_t len){ binary(makeBuffer(message, len)); };
 | 
				
			||||||
 | 
					    inline void binary(const char * message, size_t len){ binary((const uint8_t *)message, len); };
 | 
				
			||||||
 | 
					    inline void binary(const char * message){ binary(message, strlen(message)); };
 | 
				
			||||||
 | 
					    inline void binary(const String &message){ binary(message.c_str(), message.length()); };
 | 
				
			||||||
 | 
					    void binary(const __FlashStringHelper *message, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool canSend() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //system callbacks (do not call)
 | 
					    //system callbacks (do not call)
 | 
				
			||||||
    void _onAck(size_t len, uint32_t time);
 | 
					    void _onAck(size_t len, uint32_t time);
 | 
				
			||||||
@@ -244,11 +222,9 @@ typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * clien
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
//WebServer Handler implementation that plays the role of a socket server
 | 
					//WebServer Handler implementation that plays the role of a socket server
 | 
				
			||||||
class AsyncWebSocket: public AsyncWebHandler {
 | 
					class AsyncWebSocket: public AsyncWebHandler {
 | 
				
			||||||
  public:
 | 
					 | 
				
			||||||
    typedef LinkedList<AsyncWebSocketClient *> AsyncWebSocketClientLinkedList;
 | 
					 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
    String _url;
 | 
					    String _url;
 | 
				
			||||||
    AsyncWebSocketClientLinkedList _clients;
 | 
					    std::list<AsyncWebSocketClient> _clients;
 | 
				
			||||||
    uint32_t _cNextId;
 | 
					    uint32_t _cNextId;
 | 
				
			||||||
    AwsEventHandler _eventHandler;
 | 
					    AwsEventHandler _eventHandler;
 | 
				
			||||||
	  AwsHandshakeHandler _handshakeHandler;
 | 
						  AwsHandshakeHandler _handshakeHandler;
 | 
				
			||||||
@@ -272,41 +248,56 @@ class AsyncWebSocket: public AsyncWebHandler {
 | 
				
			|||||||
    void closeAll(uint16_t code=0, const char * message=NULL);
 | 
					    void closeAll(uint16_t code=0, const char * message=NULL);
 | 
				
			||||||
    void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
 | 
					    void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void ping(uint32_t id, uint8_t *data=NULL, size_t len=0);
 | 
					    void ping(uint32_t id, const uint8_t *data=NULL, size_t len=0);
 | 
				
			||||||
    void pingAll(uint8_t *data=NULL, size_t len=0); //  done
 | 
					    void pingAll(const uint8_t *data=NULL, size_t len=0); //  done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void text(uint32_t id, const char * message, size_t len);
 | 
					    //data packets
 | 
				
			||||||
    void text(uint32_t id, const char * message);
 | 
					    /**
 | 
				
			||||||
    void text(uint32_t id, uint8_t * message, size_t len);
 | 
					     * @brief allocate memory buffer owned by shared-pointer and copy provided data
 | 
				
			||||||
    void text(uint32_t id, char * message);
 | 
					     * used to keep the data untill websocket send is complete for single/multiple clients
 | 
				
			||||||
    void text(uint32_t id, const String &message);
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param message 
 | 
				
			||||||
 | 
					     * @param len 
 | 
				
			||||||
 | 
					     * @return AsyncWebSocketMessageBuffer 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    AsyncWebSocketMessageBuffer makeBuffer(const uint8_t *message, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @brief allocate empty memory buffer owned by shared-pointer
 | 
				
			||||||
 | 
					     * used to keep the data untill websocket send is complete for single/multiple clients
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param len 
 | 
				
			||||||
 | 
					     * @return AsyncWebSocketMessageBuffer 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    inline AsyncWebSocketMessageBuffer makeBuffer(size_t len){ return std::make_shared<std::vector<uint8_t>>(len); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void text(uint32_t id, AsyncWebSocketMessageBuffer message);
 | 
				
			||||||
 | 
					    void text(uint32_t id, const uint8_t * message, size_t len);
 | 
				
			||||||
 | 
					    inline void text(uint32_t id, const char *message, size_t len){ text(id, (const uint8_t *)message, len); };
 | 
				
			||||||
 | 
					    inline void text(uint32_t id, const char *message){ text(id, message, strlen(message)); };
 | 
				
			||||||
 | 
					    inline void text(uint32_t id, const String &message){ text(id, message.c_str(), message.length()); };
 | 
				
			||||||
    void text(uint32_t id, const __FlashStringHelper *message);
 | 
					    void text(uint32_t id, const __FlashStringHelper *message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void textAll(AsyncWebSocketMessageBuffer buffer);
 | 
				
			||||||
 | 
					    void textAll(const uint8_t *message, size_t len);
 | 
				
			||||||
    void textAll(const char * message, size_t len);
 | 
					    void textAll(const char * message, size_t len);
 | 
				
			||||||
    void textAll(const char * message);
 | 
					    void textAll(const char * message);
 | 
				
			||||||
    void textAll(uint8_t * message, size_t len);
 | 
					 | 
				
			||||||
    void textAll(char * message);
 | 
					 | 
				
			||||||
    void textAll(const String &message);
 | 
					    void textAll(const String &message);
 | 
				
			||||||
    void textAll(const __FlashStringHelper *message); //  need to convert
 | 
					    void textAll(const __FlashStringHelper *message); //  need to convert
 | 
				
			||||||
    void textAll(AsyncWebSocketMessageBuffer * buffer);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void binary(uint32_t id, AsyncWebSocketMessageBuffer message);
 | 
				
			||||||
 | 
					    void binary(uint32_t id, const uint8_t *message, size_t len);
 | 
				
			||||||
    void binary(uint32_t id, const char *message, size_t len);
 | 
					    void binary(uint32_t id, const char *message, size_t len);
 | 
				
			||||||
    void binary(uint32_t id, const char *message);
 | 
					    void binary(uint32_t id, const char *message);
 | 
				
			||||||
    void binary(uint32_t id, uint8_t * message, size_t len);
 | 
					 | 
				
			||||||
    void binary(uint32_t id, char * message);
 | 
					 | 
				
			||||||
    void binary(uint32_t id, const String &message);
 | 
					    void binary(uint32_t id, const String &message);
 | 
				
			||||||
    void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
 | 
					    void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void binaryAll(AsyncWebSocketMessageBuffer buffer);
 | 
				
			||||||
 | 
					    void binaryAll(const uint8_t *message, size_t len);
 | 
				
			||||||
    void binaryAll(const char *message, size_t len);
 | 
					    void binaryAll(const char *message, size_t len);
 | 
				
			||||||
    void binaryAll(const char *message);
 | 
					    void binaryAll(const char *message);
 | 
				
			||||||
    void binaryAll(uint8_t * message, size_t len);
 | 
					 | 
				
			||||||
    void binaryAll(char * message);
 | 
					 | 
				
			||||||
    void binaryAll(const String &message);
 | 
					    void binaryAll(const String &message);
 | 
				
			||||||
    void binaryAll(const __FlashStringHelper *message, size_t len);
 | 
					    void binaryAll(const __FlashStringHelper *message, size_t len);
 | 
				
			||||||
    void binaryAll(AsyncWebSocketMessageBuffer * buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void message(uint32_t id, AsyncWebSocketMessage *message);
 | 
					 | 
				
			||||||
    void messageAll(AsyncWebSocketMultiMessage *message);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t printf(uint32_t id, const char *format, ...)  __attribute__ ((format (printf, 3, 4)));
 | 
					    size_t printf(uint32_t id, const char *format, ...)  __attribute__ ((format (printf, 3, 4)));
 | 
				
			||||||
    size_t printfAll(const char *format, ...)  __attribute__ ((format (printf, 2, 3)));
 | 
					    size_t printfAll(const char *format, ...)  __attribute__ ((format (printf, 2, 3)));
 | 
				
			||||||
@@ -327,20 +318,12 @@ class AsyncWebSocket: public AsyncWebHandler {
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
    //system callbacks (do not call)
 | 
					    //system callbacks (do not call)
 | 
				
			||||||
    uint32_t _getNextId(){ return _cNextId++; }
 | 
					    uint32_t _getNextId(){ return _cNextId++; }
 | 
				
			||||||
    void _addClient(AsyncWebSocketClient * client);
 | 
					    AsyncWebSocketClient *_newClient(AsyncWebServerRequest *request);
 | 
				
			||||||
    void _handleDisconnect(AsyncWebSocketClient * client);
 | 
					 | 
				
			||||||
    void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
 | 
					    void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
 | 
				
			||||||
    virtual bool canHandle(AsyncWebServerRequest *request) override final;
 | 
					    virtual bool canHandle(AsyncWebServerRequest *request) override final;
 | 
				
			||||||
    virtual void handleRequest(AsyncWebServerRequest *request) override final;
 | 
					    virtual void handleRequest(AsyncWebServerRequest *request) override final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::list<AsyncWebSocketClient> &getClients() const { return _clients; }
 | 
				
			||||||
    //  messagebuffer functions/objects.
 | 
					 | 
				
			||||||
    AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
 | 
					 | 
				
			||||||
    AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
 | 
					 | 
				
			||||||
    LinkedList<AsyncWebSocketMessageBuffer *> _buffers;
 | 
					 | 
				
			||||||
    void _cleanBuffers();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    AsyncWebSocketClientLinkedList getClients() const;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//WebServer response to authenticate the socket and detach the tcp client from the web server request
 | 
					//WebServer response to authenticate the socket and detach the tcp client from the web server request
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,16 +7,52 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef ESP32
 | 
					#ifdef ESP32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore
 | 
				
			||||||
 | 
					// Modified 'AsyncWebLock' to just only use mutex since pxCurrentTCB is not
 | 
				
			||||||
 | 
					// always available. According to example by Arjan Filius, changed name,
 | 
				
			||||||
 | 
					// added unimplemented version for ESP8266
 | 
				
			||||||
 | 
					class AsyncPlainLock
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  SemaphoreHandle_t _lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  AsyncPlainLock() {
 | 
				
			||||||
 | 
					    _lock = xSemaphoreCreateBinary();
 | 
				
			||||||
 | 
					    // In this fails, the system is likely that much out of memory that
 | 
				
			||||||
 | 
					    // we should abort anyways. If assertions are disabled, nothing is lost..
 | 
				
			||||||
 | 
					    assert(_lock);
 | 
				
			||||||
 | 
					    xSemaphoreGive(_lock);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ~AsyncPlainLock() {
 | 
				
			||||||
 | 
					    vSemaphoreDelete(_lock);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool lock() const {
 | 
				
			||||||
 | 
					      xSemaphoreTake(_lock, portMAX_DELAY);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void unlock() const {
 | 
				
			||||||
 | 
					    xSemaphoreGive(_lock);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore
 | 
					// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore
 | 
				
			||||||
class AsyncWebLock
 | 
					class AsyncWebLock
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    SemaphoreHandle_t _lock;
 | 
					    SemaphoreHandle_t _lock;
 | 
				
			||||||
  mutable void *_lockedBy;
 | 
					    mutable TaskHandle_t _lockedBy{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  AsyncWebLock() {
 | 
					    AsyncWebLock()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        _lock = xSemaphoreCreateBinary();
 | 
					        _lock = xSemaphoreCreateBinary();
 | 
				
			||||||
 | 
					        // In this fails, the system is likely that much out of memory that
 | 
				
			||||||
 | 
					        // we should abort anyways. If assertions are disabled, nothing is lost..
 | 
				
			||||||
 | 
					        assert(_lock);
 | 
				
			||||||
        _lockedBy = NULL;
 | 
					        _lockedBy = NULL;
 | 
				
			||||||
        xSemaphoreGive(_lock);
 | 
					        xSemaphoreGive(_lock);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -26,10 +62,10 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool lock() const {
 | 
					    bool lock() const {
 | 
				
			||||||
    extern void *pxCurrentTCB;
 | 
					        const auto currentTask = xTaskGetCurrentTaskHandle();
 | 
				
			||||||
    if (_lockedBy != pxCurrentTCB) {
 | 
					        if (_lockedBy != currentTask) {
 | 
				
			||||||
            xSemaphoreTake(_lock, portMAX_DELAY);
 | 
					            xSemaphoreTake(_lock, portMAX_DELAY);
 | 
				
			||||||
      _lockedBy = pxCurrentTCB;
 | 
					            _lockedBy = currentTask;
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
@@ -61,6 +97,10 @@ public:
 | 
				
			|||||||
  void unlock() const {
 | 
					  void unlock() const {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Same for AsyncPlainLock, for ESP8266 this is just the unimplemented version above. 
 | 
				
			||||||
 | 
					using AsyncPlainLock = AsyncWebLock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AsyncWebLockGuard
 | 
					class AsyncWebLockGuard
 | 
				
			||||||
@@ -82,6 +122,13 @@ public:
 | 
				
			|||||||
      _lock->unlock();
 | 
					      _lock->unlock();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void unlock() {
 | 
				
			||||||
 | 
					    if (_lock) {
 | 
				
			||||||
 | 
					      _lock->unlock();
 | 
				
			||||||
 | 
					      _lock = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // ASYNCWEBSYNCHRONIZATION_H_
 | 
					#endif // ASYNCWEBSYNCHRONIZATION_H_
 | 
				
			||||||
@@ -24,6 +24,8 @@
 | 
				
			|||||||
#include "Arduino.h"
 | 
					#include "Arduino.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
#include "FS.h"
 | 
					#include "FS.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "StringArray.h"
 | 
					#include "StringArray.h"
 | 
				
			||||||
@@ -59,22 +61,14 @@ class AsyncResponseStream;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifndef WEBSERVER_H
 | 
					#ifndef WEBSERVER_H
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
  HTTP_GET       = 0b0000000000000001,
 | 
					  HTTP_GET     = 0b00000001,
 | 
				
			||||||
  HTTP_POST      = 0b0000000000000010,
 | 
					  HTTP_POST    = 0b00000010,
 | 
				
			||||||
  HTTP_DELETE    = 0b0000000000000100,
 | 
					  HTTP_DELETE  = 0b00000100,
 | 
				
			||||||
  HTTP_PUT       = 0b0000000000001000,
 | 
					  HTTP_PUT     = 0b00001000,
 | 
				
			||||||
  HTTP_PATCH     = 0b0000000000010000,
 | 
					  HTTP_PATCH   = 0b00010000,
 | 
				
			||||||
  HTTP_HEAD      = 0b0000000000100000,
 | 
					  HTTP_HEAD    = 0b00100000,
 | 
				
			||||||
  HTTP_OPTIONS   = 0b0000000001000000,
 | 
					  HTTP_OPTIONS = 0b01000000,
 | 
				
			||||||
  HTTP_PROPFIND  = 0b0000000010000000,
 | 
					  HTTP_ANY     = 0b01111111,
 | 
				
			||||||
  HTTP_LOCK      = 0b0000000100000000,
 | 
					 | 
				
			||||||
  HTTP_UNLOCK    = 0b0000001000000000,
 | 
					 | 
				
			||||||
  HTTP_PROPPATCH = 0b0000010000000000,
 | 
					 | 
				
			||||||
  HTTP_MKCOL     = 0b0000100000000000,
 | 
					 | 
				
			||||||
  HTTP_MOVE      = 0b0001000000000000,
 | 
					 | 
				
			||||||
  HTTP_COPY      = 0b0010000000000000,
 | 
					 | 
				
			||||||
  HTTP_RESERVED  = 0b0100000000000000,
 | 
					 | 
				
			||||||
  HTTP_ANY       = 0b0111111111111111,
 | 
					 | 
				
			||||||
} WebRequestMethod;
 | 
					} WebRequestMethod;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -94,7 +88,7 @@ namespace fs {
 | 
				
			|||||||
//if this value is returned when asked for data, packet will not be sent and you will be asked for data again
 | 
					//if this value is returned when asked for data, packet will not be sent and you will be asked for data again
 | 
				
			||||||
#define RESPONSE_TRY_AGAIN 0xFFFFFFFF
 | 
					#define RESPONSE_TRY_AGAIN 0xFFFFFFFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef uint16_t WebRequestMethodComposite;
 | 
					typedef uint8_t WebRequestMethodComposite;
 | 
				
			||||||
typedef std::function<void(void)> ArDisconnectHandler;
 | 
					typedef std::function<void(void)> ArDisconnectHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -129,6 +123,9 @@ class AsyncWebHeader {
 | 
				
			|||||||
    String _value;
 | 
					    String _value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
 | 
					    AsyncWebHeader() = default;
 | 
				
			||||||
 | 
					    AsyncWebHeader(const AsyncWebHeader &) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){}
 | 
					    AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){}
 | 
				
			||||||
    AsyncWebHeader(const String& data): _name(), _value(){
 | 
					    AsyncWebHeader(const String& data): _name(), _value(){
 | 
				
			||||||
      if(!data) return;
 | 
					      if(!data) return;
 | 
				
			||||||
@@ -137,10 +134,12 @@ class AsyncWebHeader {
 | 
				
			|||||||
      _name = data.substring(0, index);
 | 
					      _name = data.substring(0, index);
 | 
				
			||||||
      _value = data.substring(index + 2);
 | 
					      _value = data.substring(index + 2);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ~AsyncWebHeader(){}
 | 
					
 | 
				
			||||||
 | 
					    AsyncWebHeader &operator=(const AsyncWebHeader &) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const String& name() const { return _name; }
 | 
					    const String& name() const { return _name; }
 | 
				
			||||||
    const String& value() const { return _value; }
 | 
					    const String& value() const { return _value; }
 | 
				
			||||||
    String toString() const { return String(_name + F(": ") + _value + F("\r\n")); }
 | 
					    String toString() const { return _name + F(": ") + _value + F("\r\n"); }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -162,7 +161,7 @@ class AsyncWebServerRequest {
 | 
				
			|||||||
    AsyncWebServer* _server;
 | 
					    AsyncWebServer* _server;
 | 
				
			||||||
    AsyncWebHandler* _handler;
 | 
					    AsyncWebHandler* _handler;
 | 
				
			||||||
    AsyncWebServerResponse* _response;
 | 
					    AsyncWebServerResponse* _response;
 | 
				
			||||||
    StringArray _interestingHeaders;
 | 
					    std::vector<String> _interestingHeaders;
 | 
				
			||||||
    ArDisconnectHandler _onDisconnectfn;
 | 
					    ArDisconnectHandler _onDisconnectfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    String _temp;
 | 
					    String _temp;
 | 
				
			||||||
@@ -184,9 +183,9 @@ class AsyncWebServerRequest {
 | 
				
			|||||||
    size_t _contentLength;
 | 
					    size_t _contentLength;
 | 
				
			||||||
    size_t _parsedLength;
 | 
					    size_t _parsedLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LinkedList<AsyncWebHeader *> _headers;
 | 
					    std::list<AsyncWebHeader> _headers;
 | 
				
			||||||
    LinkedList<AsyncWebParameter *> _params;
 | 
					    LinkedList<AsyncWebParameter *> _params;
 | 
				
			||||||
    LinkedList<String *> _pathParams;
 | 
					    std::vector<String> _pathParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t _multiParseState;
 | 
					    uint8_t _multiParseState;
 | 
				
			||||||
    uint8_t _boundaryPosition;
 | 
					    uint8_t _boundaryPosition;
 | 
				
			||||||
@@ -278,9 +277,12 @@ class AsyncWebServerRequest {
 | 
				
			|||||||
    bool hasHeader(const String& name) const;   // check if header exists
 | 
					    bool hasHeader(const String& name) const;   // check if header exists
 | 
				
			||||||
    bool hasHeader(const __FlashStringHelper * data) const;   // check if header exists
 | 
					    bool hasHeader(const __FlashStringHelper * data) const;   // check if header exists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AsyncWebHeader* getHeader(const String& name) const;
 | 
					    AsyncWebHeader* getHeader(const String& name);
 | 
				
			||||||
    AsyncWebHeader* getHeader(const __FlashStringHelper * data) const;
 | 
					    const AsyncWebHeader* getHeader(const String& name) const;
 | 
				
			||||||
    AsyncWebHeader* getHeader(size_t num) const;
 | 
					    AsyncWebHeader* getHeader(const __FlashStringHelper * data);
 | 
				
			||||||
 | 
					    const AsyncWebHeader* getHeader(const __FlashStringHelper * data) const;
 | 
				
			||||||
 | 
					    AsyncWebHeader* getHeader(size_t num);
 | 
				
			||||||
 | 
					    const AsyncWebHeader* getHeader(size_t num) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t params() const;                      // get arguments count
 | 
					    size_t params() const;                      // get arguments count
 | 
				
			||||||
    bool hasParam(const String& name, bool post=false, bool file=false) const;
 | 
					    bool hasParam(const String& name, bool post=false, bool file=false) const;
 | 
				
			||||||
@@ -379,7 +381,7 @@ typedef enum {
 | 
				
			|||||||
class AsyncWebServerResponse {
 | 
					class AsyncWebServerResponse {
 | 
				
			||||||
  protected:
 | 
					  protected:
 | 
				
			||||||
    int _code;
 | 
					    int _code;
 | 
				
			||||||
    LinkedList<AsyncWebHeader *> _headers;
 | 
					    std::list<AsyncWebHeader> _headers;
 | 
				
			||||||
    String _contentType;
 | 
					    String _contentType;
 | 
				
			||||||
    size_t _contentLength;
 | 
					    size_t _contentLength;
 | 
				
			||||||
    bool _sendContentLength;
 | 
					    bool _sendContentLength;
 | 
				
			||||||
@@ -462,17 +464,16 @@ class AsyncWebServer {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DefaultHeaders {
 | 
					class DefaultHeaders {
 | 
				
			||||||
  using headers_t = LinkedList<AsyncWebHeader *>;
 | 
					  using headers_t = std::list<AsyncWebHeader>;
 | 
				
			||||||
  headers_t _headers;
 | 
					  headers_t _headers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DefaultHeaders()
 | 
					 | 
				
			||||||
  :_headers(headers_t([](AsyncWebHeader *h){ delete h; }))
 | 
					 | 
				
			||||||
  {}
 | 
					 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  using ConstIterator = headers_t::ConstIterator;
 | 
					  DefaultHeaders() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  using ConstIterator = headers_t::const_iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void addHeader(const String& name, const String& value){
 | 
					  void addHeader(const String& name, const String& value){
 | 
				
			||||||
    _headers.add(new AsyncWebHeader(name, value));
 | 
					    _headers.emplace_back(name, value);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ConstIterator begin() const { return _headers.begin(); }
 | 
					  ConstIterator begin() const { return _headers.begin(); }
 | 
				
			||||||
@@ -480,6 +481,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  DefaultHeaders(DefaultHeaders const &) = delete;
 | 
					  DefaultHeaders(DefaultHeaders const &) = delete;
 | 
				
			||||||
  DefaultHeaders &operator=(DefaultHeaders const &) = delete;
 | 
					  DefaultHeaders &operator=(DefaultHeaders const &) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static DefaultHeaders &Instance() {
 | 
					  static DefaultHeaders &Instance() {
 | 
				
			||||||
    static DefaultHeaders instance;
 | 
					    static DefaultHeaders instance;
 | 
				
			||||||
    return instance;
 | 
					    return instance;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -171,23 +171,4 @@ class LinkedList {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
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_ */
 | 
					#endif /* STRINGARRAY_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,9 +77,9 @@ static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or mo
 | 
				
			|||||||
  memset(_buf, 0x00, 16);
 | 
					  memset(_buf, 0x00, 16);
 | 
				
			||||||
#ifdef ESP32
 | 
					#ifdef ESP32
 | 
				
			||||||
  mbedtls_md5_init(&_ctx);
 | 
					  mbedtls_md5_init(&_ctx);
 | 
				
			||||||
  mbedtls_md5_starts(&_ctx);
 | 
					  mbedtls_md5_starts_ret(&_ctx);
 | 
				
			||||||
  mbedtls_md5_update(&_ctx, data, len);
 | 
					  mbedtls_md5_update_ret(&_ctx, data, len);
 | 
				
			||||||
  mbedtls_md5_finish(&_ctx, _buf);
 | 
					  mbedtls_md5_finish_ret(&_ctx, _buf);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  MD5Init(&_ctx);
 | 
					  MD5Init(&_ctx);
 | 
				
			||||||
  MD5Update(&_ctx, data, len);
 | 
					  MD5Update(&_ctx, data, len);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,9 +51,7 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
 | 
				
			|||||||
  , _expectingContinue(false)
 | 
					  , _expectingContinue(false)
 | 
				
			||||||
  , _contentLength(0)
 | 
					  , _contentLength(0)
 | 
				
			||||||
  , _parsedLength(0)
 | 
					  , _parsedLength(0)
 | 
				
			||||||
  , _headers(LinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
 | 
					 | 
				
			||||||
  , _params(LinkedList<AsyncWebParameter *>([](AsyncWebParameter *p){ delete p; }))
 | 
					  , _params(LinkedList<AsyncWebParameter *>([](AsyncWebParameter *p){ delete p; }))
 | 
				
			||||||
  , _pathParams(LinkedList<String *>([](String *p){ delete p; }))
 | 
					 | 
				
			||||||
  , _multiParseState(0)
 | 
					  , _multiParseState(0)
 | 
				
			||||||
  , _boundaryPosition(0)
 | 
					  , _boundaryPosition(0)
 | 
				
			||||||
  , _itemStartIndex(0)
 | 
					  , _itemStartIndex(0)
 | 
				
			||||||
@@ -76,12 +74,12 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncWebServerRequest::~AsyncWebServerRequest(){
 | 
					AsyncWebServerRequest::~AsyncWebServerRequest(){
 | 
				
			||||||
  _headers.free();
 | 
					  _headers.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _params.free();
 | 
					  _params.free();
 | 
				
			||||||
  _pathParams.free();
 | 
					  _pathParams.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _interestingHeaders.free();
 | 
					  _interestingHeaders.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(_response != NULL){
 | 
					  if(_response != NULL){
 | 
				
			||||||
    delete _response;
 | 
					    delete _response;
 | 
				
			||||||
@@ -182,11 +180,19 @@ void AsyncWebServerRequest::_onData(void *buf, size_t len){
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerRequest::_removeNotInterestingHeaders(){
 | 
					void AsyncWebServerRequest::_removeNotInterestingHeaders(){
 | 
				
			||||||
  if (_interestingHeaders.containsIgnoreCase(F("ANY"))) return; // nothing to do
 | 
					  if (std::any_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
 | 
				
			||||||
  for(const auto& header: _headers){
 | 
					      [](const String &str){ return str.equalsIgnoreCase(F("ANY")); }))
 | 
				
			||||||
      if(!_interestingHeaders.containsIgnoreCase(header->name().c_str())){
 | 
					      return; // nothing to do
 | 
				
			||||||
        _headers.remove(header);
 | 
					
 | 
				
			||||||
      }
 | 
					  for(auto iter = std::begin(_headers); iter != std::end(_headers); )
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					      const auto name = iter->name();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (std::none_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
 | 
				
			||||||
 | 
					                       [&name](const String &str){ return str.equalsIgnoreCase(name); }))
 | 
				
			||||||
 | 
					          iter = _headers.erase(iter);
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					          iter++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -247,7 +253,7 @@ void AsyncWebServerRequest::_addParam(AsyncWebParameter *p){
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerRequest::_addPathParam(const char *p){
 | 
					void AsyncWebServerRequest::_addPathParam(const char *p){
 | 
				
			||||||
  _pathParams.add(new String(p));
 | 
					  _pathParams.emplace_back(p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerRequest::_addGetParams(const String& params){
 | 
					void AsyncWebServerRequest::_addGetParams(const String& params){
 | 
				
			||||||
@@ -286,24 +292,6 @@ bool AsyncWebServerRequest::_parseReqHead(){
 | 
				
			|||||||
    _method = HTTP_HEAD;
 | 
					    _method = HTTP_HEAD;
 | 
				
			||||||
  } else if(m == F("OPTIONS")){
 | 
					  } else if(m == F("OPTIONS")){
 | 
				
			||||||
    _method = HTTP_OPTIONS;
 | 
					    _method = HTTP_OPTIONS;
 | 
				
			||||||
  } else if(m == F("PROPFIND")){
 | 
					 | 
				
			||||||
    _method = HTTP_PROPFIND;
 | 
					 | 
				
			||||||
  } else if(m == F("LOCK")){
 | 
					 | 
				
			||||||
    _method = HTTP_LOCK;
 | 
					 | 
				
			||||||
  } else if(m == F("UNLOCK")){
 | 
					 | 
				
			||||||
    _method = HTTP_UNLOCK;
 | 
					 | 
				
			||||||
  } else if(m == F("PROPPATCH")){
 | 
					 | 
				
			||||||
    _method = HTTP_PROPPATCH;
 | 
					 | 
				
			||||||
  } else if(m == F("MKCOL")){
 | 
					 | 
				
			||||||
    _method = HTTP_MKCOL;
 | 
					 | 
				
			||||||
  } else if(m == F("MOVE")){
 | 
					 | 
				
			||||||
    _method = HTTP_MOVE;
 | 
					 | 
				
			||||||
  } else if(m == F("COPY")){
 | 
					 | 
				
			||||||
    _method = HTTP_COPY;
 | 
					 | 
				
			||||||
  } else if(m == F("RESERVED")){
 | 
					 | 
				
			||||||
    _method = HTTP_RESERVED;
 | 
					 | 
				
			||||||
  } else if(m == F("ANY")){
 | 
					 | 
				
			||||||
    _method = HTTP_ANY;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  String g;
 | 
					  String g;
 | 
				
			||||||
@@ -379,7 +367,7 @@ bool AsyncWebServerRequest::_parseReqHeader(){
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    _headers.add(new AsyncWebHeader(name, value));
 | 
					    _headers.emplace_back(name, value);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _temp = String();
 | 
					  _temp = String();
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
@@ -620,12 +608,12 @@ void AsyncWebServerRequest::_parseLine(){
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t AsyncWebServerRequest::headers() const{
 | 
					size_t AsyncWebServerRequest::headers() const{
 | 
				
			||||||
  return _headers.length();
 | 
					  return _headers.size();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool AsyncWebServerRequest::hasHeader(const String& name) const {
 | 
					bool AsyncWebServerRequest::hasHeader(const String& name) const {
 | 
				
			||||||
  for(const auto& h: _headers){
 | 
					  for(const auto& h: _headers){
 | 
				
			||||||
    if(h->name().equalsIgnoreCase(name)){
 | 
					    if(h.name().equalsIgnoreCase(name)){
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -636,22 +624,64 @@ bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper * data) const {
 | 
				
			|||||||
  return hasHeader(String(data));
 | 
					  return hasHeader(String(data));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const {
 | 
					AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) {
 | 
				
			||||||
  for(const auto& h: _headers){
 | 
					  auto iter = std::find_if(std::begin(_headers), std::end(_headers),
 | 
				
			||||||
    if(h->name().equalsIgnoreCase(name)){
 | 
					                           [&name](const AsyncWebHeader &header){ return header.name().equalsIgnoreCase(name); });
 | 
				
			||||||
      return h;
 | 
					
 | 
				
			||||||
 | 
					  if (iter == std::end(_headers))
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &(*iter);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const {
 | 
				
			||||||
 | 
					  auto iter = std::find_if(std::begin(_headers), std::end(_headers),
 | 
				
			||||||
 | 
					                           [&name](const AsyncWebHeader &header){ return header.name().equalsIgnoreCase(name); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (iter == std::end(_headers))
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &(*iter);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) {
 | 
				
			||||||
 | 
					  PGM_P p = reinterpret_cast<PGM_P>(data);
 | 
				
			||||||
 | 
					  size_t n = strlen_P(p);
 | 
				
			||||||
 | 
					  char * name = (char*) malloc(n+1);
 | 
				
			||||||
 | 
					  if (name) {
 | 
				
			||||||
 | 
					    strcpy_P(name, p);
 | 
				
			||||||
 | 
					    AsyncWebHeader* result = getHeader( String(name));
 | 
				
			||||||
 | 
					    free(name);
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const {
 | 
					 | 
				
			||||||
  return getHeader(String(data));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const {
 | 
					const AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const {
 | 
				
			||||||
  auto header = _headers.nth(num);
 | 
					  PGM_P p = reinterpret_cast<PGM_P>(data);
 | 
				
			||||||
  return header ? *header : nullptr;
 | 
					  size_t n = strlen_P(p);
 | 
				
			||||||
 | 
					  char * name = (char*) malloc(n+1);
 | 
				
			||||||
 | 
					  if (name) {
 | 
				
			||||||
 | 
					    strcpy_P(name, p);
 | 
				
			||||||
 | 
					    const AsyncWebHeader* result = getHeader( String(name));
 | 
				
			||||||
 | 
					    free(name);
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    return nullptr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) {
 | 
				
			||||||
 | 
					  if (num >= _headers.size())
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					  return &(*std::next(std::begin(_headers), num));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const {
 | 
				
			||||||
 | 
					  if (num >= _headers.size())
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					  return &(*std::next(std::begin(_headers), num));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t AsyncWebServerRequest::params() const {
 | 
					size_t AsyncWebServerRequest::params() const {
 | 
				
			||||||
@@ -690,8 +720,9 @@ AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerRequest::addInterestingHeader(const String& name){
 | 
					void AsyncWebServerRequest::addInterestingHeader(const String& name){
 | 
				
			||||||
  if(!_interestingHeaders.containsIgnoreCase(name))
 | 
					  if(std::none_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
 | 
				
			||||||
    _interestingHeaders.add(name);
 | 
					                  [&name](const String &str){ return str.equalsIgnoreCase(name); }))
 | 
				
			||||||
 | 
					    _interestingHeaders.push_back(name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
 | 
					void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
 | 
				
			||||||
@@ -883,12 +914,11 @@ const String& AsyncWebServerRequest::argName(size_t i) const {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String& AsyncWebServerRequest::pathArg(size_t i) const {
 | 
					const String& AsyncWebServerRequest::pathArg(size_t i) const {
 | 
				
			||||||
  auto param = _pathParams.nth(i);
 | 
					  return i < _pathParams.size() ? _pathParams[i] : emptyString;
 | 
				
			||||||
  return param ? **param : emptyString;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String& AsyncWebServerRequest::header(const char* name) const {
 | 
					const String& AsyncWebServerRequest::header(const char* name) const {
 | 
				
			||||||
  AsyncWebHeader* h = getHeader(String(name));
 | 
					  const AsyncWebHeader* h = getHeader(String(name));
 | 
				
			||||||
  return h ? h->value() : emptyString;
 | 
					  return h ? h->value() : emptyString;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -898,12 +928,12 @@ const String& AsyncWebServerRequest::header(const __FlashStringHelper * data) co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String& AsyncWebServerRequest::header(size_t i) const {
 | 
					const String& AsyncWebServerRequest::header(size_t i) const {
 | 
				
			||||||
  AsyncWebHeader* h = getHeader(i);
 | 
					  const AsyncWebHeader* h = getHeader(i);
 | 
				
			||||||
  return h ?  h->value() : emptyString;
 | 
					  return h ?  h->value() : emptyString;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String& AsyncWebServerRequest::headerName(size_t i) const {
 | 
					const String& AsyncWebServerRequest::headerName(size_t i) const {
 | 
				
			||||||
  AsyncWebHeader* h = getHeader(i);
 | 
					  const AsyncWebHeader* h = getHeader(i);
 | 
				
			||||||
  return h ? h->name() : emptyString;
 | 
					  return h ? h->name() : emptyString;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -940,14 +970,6 @@ const __FlashStringHelper *AsyncWebServerRequest::methodToString() const {
 | 
				
			|||||||
  else if(_method & HTTP_PATCH) return F("PATCH");
 | 
					  else if(_method & HTTP_PATCH) return F("PATCH");
 | 
				
			||||||
  else if(_method & HTTP_HEAD) return F("HEAD");
 | 
					  else if(_method & HTTP_HEAD) return F("HEAD");
 | 
				
			||||||
  else if(_method & HTTP_OPTIONS) return F("OPTIONS");
 | 
					  else if(_method & HTTP_OPTIONS) return F("OPTIONS");
 | 
				
			||||||
  else if(_method & HTTP_PROPFIND) return F("PROPFIND");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_LOCK) return F("LOCK");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_UNLOCK) return F("UNLOCK");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_PROPPATCH) return F("PROPPATCH");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_MKCOL) return F("MKCOL");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_MOVE) return F("MOVE");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_COPY) return F("COPY");
 | 
					 | 
				
			||||||
  else if(_method & HTTP_RESERVED) return F("RESERVED");
 | 
					 | 
				
			||||||
  return F("UNKNOWN");
 | 
					  return F("UNKNOWN");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,8 @@
 | 
				
			|||||||
#undef max
 | 
					#undef max
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
 | 
					// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AsyncBasicResponse: public AsyncWebServerResponse {
 | 
					class AsyncBasicResponse: public AsyncWebServerResponse {
 | 
				
			||||||
@@ -122,7 +124,7 @@ class cbuf;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class AsyncResponseStream: public AsyncAbstractResponse, public Print {
 | 
					class AsyncResponseStream: public AsyncAbstractResponse, public Print {
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
    cbuf *_content;
 | 
					    std::unique_ptr<cbuf> _content;
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
    AsyncResponseStream(const String& contentType, size_t bufferSize);
 | 
					    AsyncResponseStream(const String& contentType, size_t bufferSize);
 | 
				
			||||||
    ~AsyncResponseStream();
 | 
					    ~AsyncResponseStream();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,7 +88,6 @@ const __FlashStringHelper *AsyncWebServerResponse::responseCodeToString(int code
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
AsyncWebServerResponse::AsyncWebServerResponse()
 | 
					AsyncWebServerResponse::AsyncWebServerResponse()
 | 
				
			||||||
  : _code(0)
 | 
					  : _code(0)
 | 
				
			||||||
  , _headers(LinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
 | 
					 | 
				
			||||||
  , _contentType()
 | 
					  , _contentType()
 | 
				
			||||||
  , _contentLength(0)
 | 
					  , _contentLength(0)
 | 
				
			||||||
  , _sendContentLength(true)
 | 
					  , _sendContentLength(true)
 | 
				
			||||||
@@ -99,14 +98,12 @@ AsyncWebServerResponse::AsyncWebServerResponse()
 | 
				
			|||||||
  , _writtenLength(0)
 | 
					  , _writtenLength(0)
 | 
				
			||||||
  , _state(RESPONSE_SETUP)
 | 
					  , _state(RESPONSE_SETUP)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  for(auto header: DefaultHeaders::Instance()) {
 | 
					  for(const auto &header: DefaultHeaders::Instance()) {
 | 
				
			||||||
    _headers.add(new AsyncWebHeader(header->name(), header->value()));
 | 
					    _headers.emplace_back(header);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncWebServerResponse::~AsyncWebServerResponse(){
 | 
					AsyncWebServerResponse::~AsyncWebServerResponse() = default;
 | 
				
			||||||
  _headers.free();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerResponse::setCode(int code){
 | 
					void AsyncWebServerResponse::setCode(int code){
 | 
				
			||||||
  if(_state == RESPONSE_SETUP)
 | 
					  if(_state == RESPONSE_SETUP)
 | 
				
			||||||
@@ -124,7 +121,7 @@ void AsyncWebServerResponse::setContentType(const String& type){
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AsyncWebServerResponse::addHeader(const String& name, const String& value){
 | 
					void AsyncWebServerResponse::addHeader(const String& name, const String& value){
 | 
				
			||||||
  _headers.add(new AsyncWebHeader(name, value));
 | 
					  _headers.emplace_back(name, value);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String AsyncWebServerResponse::_assembleHead(uint8_t version){
 | 
					String AsyncWebServerResponse::_assembleHead(uint8_t version){
 | 
				
			||||||
@@ -150,10 +147,10 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version){
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for(const auto& header: _headers){
 | 
					  for(const auto& header: _headers){
 | 
				
			||||||
    snprintf_P(buf, bufSize, PSTR("%s: %s\r\n"), header->name().c_str(), header->value().c_str());
 | 
					    snprintf_P(buf, bufSize, PSTR("%s: %s\r\n"), header.name().c_str(), header.value().c_str());
 | 
				
			||||||
    out.concat(buf);
 | 
					    out.concat(buf);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _headers.free();
 | 
					  _headers.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  out.concat(F("\r\n"));
 | 
					  out.concat(F("\r\n"));
 | 
				
			||||||
  _headLength = out.length();
 | 
					  _headLength = out.length();
 | 
				
			||||||
@@ -675,16 +672,15 @@ size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){
 | 
				
			|||||||
 * Response Stream (You can print/write/printf to it, up to the contentLen bytes)
 | 
					 * Response Stream (You can print/write/printf to it, up to the contentLen bytes)
 | 
				
			||||||
 * */
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){
 | 
					AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
  _code = 200;
 | 
					  _code = 200;
 | 
				
			||||||
  _contentLength = 0;
 | 
					  _contentLength = 0;
 | 
				
			||||||
  _contentType = contentType;
 | 
					  _contentType = contentType;
 | 
				
			||||||
  _content = new cbuf(bufferSize);
 | 
					  _content = std::unique_ptr<cbuf>(new cbuf(bufferSize)); //std::make_unique<cbuf>(bufferSize);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AsyncResponseStream::~AsyncResponseStream(){
 | 
					AsyncResponseStream::~AsyncResponseStream() = default;
 | 
				
			||||||
  delete _content;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){
 | 
					size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){
 | 
				
			||||||
  return _content->read((char*)buf, maxLen);
 | 
					  return _content->read((char*)buf, maxLen);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user