forked from me-no-dev/ESPAsyncWebServer
More crash fixes
This commit is contained in:
@ -493,7 +493,7 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
|
||||
_client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this);
|
||||
_client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this);
|
||||
_client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this);
|
||||
_server->_addClient(this);
|
||||
//_server->_addClient(this);
|
||||
_server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0);
|
||||
delete request;
|
||||
}
|
||||
@ -546,9 +546,8 @@ void AsyncWebSocketClient::_runQueue(){
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncWebSocketClient::queueIsFull(){
|
||||
if((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) ) return true;
|
||||
return false;
|
||||
bool AsyncWebSocketClient::queueIsFull() const {
|
||||
return (_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED);
|
||||
}
|
||||
|
||||
void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){
|
||||
@ -838,14 +837,14 @@ void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer)
|
||||
_queueMessage(new AsyncWebSocketMultiMessage(buffer, WS_BINARY));
|
||||
}
|
||||
|
||||
IPAddress AsyncWebSocketClient::remoteIP() {
|
||||
IPAddress AsyncWebSocketClient::remoteIP() const {
|
||||
if(!_client) {
|
||||
return IPAddress(0U);
|
||||
}
|
||||
return _client->remoteIP();
|
||||
}
|
||||
|
||||
uint16_t AsyncWebSocketClient::remotePort() {
|
||||
uint16_t AsyncWebSocketClient::remotePort() const {
|
||||
if(!_client) {
|
||||
return 0;
|
||||
}
|
||||
@ -860,7 +859,6 @@ uint16_t AsyncWebSocketClient::remotePort() {
|
||||
|
||||
AsyncWebSocket::AsyncWebSocket(const String& url)
|
||||
:_url(url)
|
||||
,_clients(LinkedList<AsyncWebSocketClient *>([](AsyncWebSocketClient *c){ delete c; }))
|
||||
,_cNextId(1)
|
||||
,_enabled(true)
|
||||
{
|
||||
@ -875,64 +873,68 @@ void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType ty
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){
|
||||
_clients.add(client);
|
||||
AsyncWebSocketClient *AsyncWebSocket::_newClient(AsyncWebServerRequest *request)
|
||||
{
|
||||
_clients.emplace_back(request, this);
|
||||
return &_clients.back();
|
||||
}
|
||||
|
||||
//void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){
|
||||
// _clients.add(client);
|
||||
//}
|
||||
|
||||
void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){
|
||||
|
||||
_clients.remove_first([=](AsyncWebSocketClient * c){
|
||||
return c->id() == client->id();
|
||||
});
|
||||
const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
|
||||
[id=client->id()](const auto &c){ return c.id() == id; });
|
||||
if (iter != std::end(_clients))
|
||||
_clients.erase(iter);
|
||||
}
|
||||
|
||||
bool AsyncWebSocket::availableForWriteAll(){
|
||||
for(const auto& c: _clients){
|
||||
if(c->queueIsFull()) return false;
|
||||
}
|
||||
return true;
|
||||
return std::none_of(std::begin(_clients), std::end(_clients),
|
||||
[](const auto &c){ return c.queueIsFull(); });
|
||||
}
|
||||
|
||||
bool AsyncWebSocket::availableForWrite(uint32_t id){
|
||||
for(const auto& c: _clients){
|
||||
if(c->queueIsFull() && (c->id() == id )) return false;
|
||||
}
|
||||
return true;
|
||||
const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
|
||||
[id](const auto &c){ return c.id() == id; });
|
||||
if (iter == std::end(_clients))
|
||||
return true; // don't know why me-no-dev decided like this?
|
||||
return !iter->queueIsFull();
|
||||
}
|
||||
|
||||
size_t AsyncWebSocket::count() const {
|
||||
return _clients.count_if([](AsyncWebSocketClient * c){
|
||||
return c->status() == WS_CONNECTED;
|
||||
});
|
||||
return std::count_if(std::begin(_clients), std::end(_clients),
|
||||
[](const auto &c){ return c.status() == WS_CONNECTED; });
|
||||
}
|
||||
|
||||
AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){
|
||||
for(const auto &c: _clients){
|
||||
if(c->id() == id && c->status() == WS_CONNECTED){
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
const auto iter = std::find_if(std::begin(_clients), std::end(_clients),
|
||||
[id](const auto &c){ return c.id() == id && c.status() == WS_CONNECTED; });
|
||||
if (iter == std::end(_clients))
|
||||
return nullptr;
|
||||
|
||||
return &(*iter);
|
||||
}
|
||||
|
||||
|
||||
void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){
|
||||
AsyncWebSocketClient * c = client(id);
|
||||
if(c)
|
||||
AsyncWebSocketClient *c = client(id);
|
||||
if (c)
|
||||
c->close(code, message);
|
||||
}
|
||||
|
||||
void AsyncWebSocket::closeAll(uint16_t code, const char * message){
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED)
|
||||
c->close(code, message);
|
||||
for(auto &c: _clients){
|
||||
if(c.status() == WS_CONNECTED)
|
||||
c.close(code, message);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncWebSocket::cleanupClients(uint16_t maxClients)
|
||||
{
|
||||
if (count() > maxClients){
|
||||
_clients.front()->close();
|
||||
_clients.front().close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -943,14 +945,14 @@ void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){
|
||||
}
|
||||
|
||||
void AsyncWebSocket::pingAll(uint8_t *data, size_t len){
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED)
|
||||
c->ping(data, len);
|
||||
for (auto &c : _clients){
|
||||
if (c.status() == WS_CONNECTED)
|
||||
c.ping(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){
|
||||
AsyncWebSocketClient * c = client(id);
|
||||
AsyncWebSocketClient *c = client(id);
|
||||
if(c)
|
||||
c->text(message, len);
|
||||
}
|
||||
@ -958,9 +960,9 @@ void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){
|
||||
void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){
|
||||
if (!buffer) return;
|
||||
buffer->lock();
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED){
|
||||
c->text(buffer);
|
||||
for(auto &c : _clients){
|
||||
if (c.status() == WS_CONNECTED){
|
||||
c.text(buffer);
|
||||
}
|
||||
}
|
||||
buffer->unlock();
|
||||
@ -988,24 +990,24 @@ void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
|
||||
{
|
||||
if (!buffer) return;
|
||||
buffer->lock();
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED)
|
||||
c->binary(buffer);
|
||||
for (auto &c : _clients){
|
||||
if (c.status() == WS_CONNECTED)
|
||||
c.binary(buffer);
|
||||
}
|
||||
buffer->unlock();
|
||||
_cleanBuffers();
|
||||
}
|
||||
|
||||
void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){
|
||||
AsyncWebSocketClient * c = client(id);
|
||||
if(c)
|
||||
AsyncWebSocketClient *c = client(id);
|
||||
if (c)
|
||||
c->message(message);
|
||||
}
|
||||
|
||||
void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED)
|
||||
c->message(message);
|
||||
for (auto &c : _clients){
|
||||
if(c.status() == WS_CONNECTED)
|
||||
c.message(message);
|
||||
}
|
||||
_cleanBuffers();
|
||||
}
|
||||
@ -1114,9 +1116,9 @@ void AsyncWebSocket::textAll(const String &message){
|
||||
textAll(message.c_str(), message.length());
|
||||
}
|
||||
void AsyncWebSocket::textAll(const __FlashStringHelper *message){
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED)
|
||||
c->text(message);
|
||||
for(auto &c : _clients){
|
||||
if(c.status() == WS_CONNECTED)
|
||||
c.text(message);
|
||||
}
|
||||
}
|
||||
void AsyncWebSocket::binary(uint32_t id, const char * message){
|
||||
@ -1149,9 +1151,9 @@ void AsyncWebSocket::binaryAll(const String &message){
|
||||
binaryAll(message.c_str(), message.length());
|
||||
}
|
||||
void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){
|
||||
for(const auto& c: _clients){
|
||||
if(c->status() == WS_CONNECTED)
|
||||
c-> binary(message, len);
|
||||
for(auto &c : _clients) {
|
||||
if(c.status() == WS_CONNECTED)
|
||||
c.binary(message, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1241,7 +1243,7 @@ void AsyncWebSocket::_cleanBuffers()
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const {
|
||||
const AsyncWebSocket::AsyncWebSocketClientLinkedList &AsyncWebSocket::getClients() const {
|
||||
return _clients;
|
||||
}
|
||||
|
||||
@ -1299,7 +1301,8 @@ void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request){
|
||||
size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){
|
||||
(void)time;
|
||||
if(len){
|
||||
new AsyncWebSocketClient(request, _server);
|
||||
//new AsyncWebSocketClient(request, _server);
|
||||
_server->_newClient(request);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,14 +183,16 @@ class AsyncWebSocketClient {
|
||||
~AsyncWebSocketClient();
|
||||
|
||||
//client id increments for the given server
|
||||
uint32_t id(){ return _clientId; }
|
||||
AwsClientStatus status(){ return _status; }
|
||||
AsyncClient* client(){ return _client; }
|
||||
AsyncWebSocket *server(){ return _server; }
|
||||
uint32_t id() const { return _clientId; }
|
||||
AwsClientStatus status() const { return _status; }
|
||||
AsyncClient* client() { return _client; }
|
||||
const AsyncClient* client() const { return _client; }
|
||||
AsyncWebSocket *server() { return _server; }
|
||||
const AsyncWebSocket *server() const { return _server; }
|
||||
AwsFrameInfo const &pinfo() const { return _pinfo; }
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
IPAddress remoteIP() const;
|
||||
uint16_t remotePort() const;
|
||||
|
||||
//control frames
|
||||
void close(uint16_t code=0, const char * message=NULL);
|
||||
@ -206,7 +208,7 @@ class AsyncWebSocketClient {
|
||||
|
||||
//data packets
|
||||
void message(AsyncWebSocketMessage *message){ _queueMessage(message); }
|
||||
bool queueIsFull();
|
||||
bool queueIsFull() const;
|
||||
|
||||
size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
#ifndef ESP32
|
||||
@ -244,7 +246,7 @@ typedef std::function<void(AsyncWebSocket * server, AsyncWebSocketClient * clien
|
||||
//WebServer Handler implementation that plays the role of a socket server
|
||||
class AsyncWebSocket: public AsyncWebHandler {
|
||||
public:
|
||||
typedef LinkedList<AsyncWebSocketClient *> AsyncWebSocketClientLinkedList;
|
||||
typedef std::list<AsyncWebSocketClient> AsyncWebSocketClientLinkedList;
|
||||
private:
|
||||
String _url;
|
||||
AsyncWebSocketClientLinkedList _clients;
|
||||
@ -320,7 +322,8 @@ class AsyncWebSocket: public AsyncWebHandler {
|
||||
|
||||
//system callbacks (do not call)
|
||||
uint32_t _getNextId(){ return _cNextId++; }
|
||||
void _addClient(AsyncWebSocketClient * client);
|
||||
AsyncWebSocketClient *_newClient(AsyncWebServerRequest *request);
|
||||
//void _addClient(AsyncWebSocketClient * client);
|
||||
void _handleDisconnect(AsyncWebSocketClient * client);
|
||||
void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
|
||||
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||
@ -333,7 +336,7 @@ class AsyncWebSocket: public AsyncWebHandler {
|
||||
std::list<AsyncWebSocketMessageBuffer> _buffers;
|
||||
void _cleanBuffers();
|
||||
|
||||
AsyncWebSocketClientLinkedList getClients() const;
|
||||
const AsyncWebSocketClientLinkedList &getClients() const;
|
||||
};
|
||||
|
||||
//WebServer response to authenticate the socket and detach the tcp client from the web server request
|
||||
|
@ -109,6 +109,9 @@ class AsyncWebHeader {
|
||||
String _value;
|
||||
|
||||
public:
|
||||
AsyncWebHeader() = default;
|
||||
AsyncWebHeader(const AsyncWebHeader &) = default;
|
||||
|
||||
AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){}
|
||||
AsyncWebHeader(const String& data): _name(), _value(){
|
||||
if(!data) return;
|
||||
@ -117,10 +120,12 @@ class AsyncWebHeader {
|
||||
_name = data.substring(0, index);
|
||||
_value = data.substring(index + 2);
|
||||
}
|
||||
~AsyncWebHeader(){}
|
||||
|
||||
AsyncWebHeader &operator=(const AsyncWebHeader &) = default;
|
||||
|
||||
const String& name() const { return _name; }
|
||||
const String& value() const { return _value; }
|
||||
String toString() const { return String(_name+": "+_value+"\r\n"); }
|
||||
String toString() const { return _name+": "+_value+"\r\n"; }
|
||||
};
|
||||
|
||||
/*
|
||||
@ -362,7 +367,7 @@ typedef enum {
|
||||
class AsyncWebServerResponse {
|
||||
protected:
|
||||
int _code;
|
||||
LinkedList<AsyncWebHeader *> _headers;
|
||||
std::list<AsyncWebHeader> _headers;
|
||||
String _contentType;
|
||||
size_t _contentLength;
|
||||
bool _sendContentLength;
|
||||
@ -444,17 +449,16 @@ class AsyncWebServer {
|
||||
};
|
||||
|
||||
class DefaultHeaders {
|
||||
using headers_t = LinkedList<AsyncWebHeader *>;
|
||||
using headers_t = std::list<AsyncWebHeader>;
|
||||
headers_t _headers;
|
||||
|
||||
DefaultHeaders()
|
||||
:_headers(headers_t([](AsyncWebHeader *h){ delete h; }))
|
||||
{}
|
||||
|
||||
public:
|
||||
using ConstIterator = headers_t::ConstIterator;
|
||||
DefaultHeaders() = default;
|
||||
|
||||
using ConstIterator = headers_t::const_iterator;
|
||||
|
||||
void addHeader(const String& name, const String& value){
|
||||
_headers.add(new AsyncWebHeader(name, value));
|
||||
_headers.emplace_back(name, value);
|
||||
}
|
||||
|
||||
ConstIterator begin() const { return _headers.begin(); }
|
||||
@ -462,6 +466,7 @@ public:
|
||||
|
||||
DefaultHeaders(DefaultHeaders const &) = delete;
|
||||
DefaultHeaders &operator=(DefaultHeaders const &) = delete;
|
||||
|
||||
static DefaultHeaders &Instance() {
|
||||
static DefaultHeaders instance;
|
||||
return instance;
|
||||
|
@ -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_ */
|
||||
|
@ -184,9 +184,7 @@ void AsyncWebServerRequest::_removeNotInterestingHeaders(){
|
||||
|
||||
for(auto iter = std::begin(_headers); iter != std::end(_headers); )
|
||||
{
|
||||
Serial.print("printing name: ");
|
||||
const auto name = iter->name();
|
||||
Serial.println(name);
|
||||
|
||||
if (std::none_of(std::begin(_interestingHeaders), std::end(_interestingHeaders),
|
||||
[&name](const String &str){ return str.equalsIgnoreCase(name); }))
|
||||
|
@ -26,7 +26,10 @@
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
|
||||
|
||||
class AsyncBasicResponse: public AsyncWebServerResponse {
|
||||
@ -122,7 +125,7 @@ class cbuf;
|
||||
|
||||
class AsyncResponseStream: public AsyncAbstractResponse, public Print {
|
||||
private:
|
||||
cbuf *_content;
|
||||
std::unique_ptr<cbuf> _content;
|
||||
public:
|
||||
AsyncResponseStream(const String& contentType, size_t bufferSize);
|
||||
~AsyncResponseStream();
|
||||
|
@ -84,7 +84,6 @@ const char* AsyncWebServerResponse::_responseCodeToString(int code) {
|
||||
|
||||
AsyncWebServerResponse::AsyncWebServerResponse()
|
||||
: _code(0)
|
||||
, _headers(LinkedList<AsyncWebHeader *>([](AsyncWebHeader *h){ delete h; }))
|
||||
, _contentType()
|
||||
, _contentLength(0)
|
||||
, _sendContentLength(true)
|
||||
@ -95,14 +94,12 @@ AsyncWebServerResponse::AsyncWebServerResponse()
|
||||
, _writtenLength(0)
|
||||
, _state(RESPONSE_SETUP)
|
||||
{
|
||||
for(auto header: DefaultHeaders::Instance()) {
|
||||
_headers.add(new AsyncWebHeader(header->name(), header->value()));
|
||||
for(const auto &header : DefaultHeaders::Instance()) {
|
||||
_headers.emplace_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWebServerResponse::~AsyncWebServerResponse(){
|
||||
_headers.free();
|
||||
}
|
||||
AsyncWebServerResponse::~AsyncWebServerResponse() = default;
|
||||
|
||||
void AsyncWebServerResponse::setCode(int code){
|
||||
if(_state == RESPONSE_SETUP)
|
||||
@ -120,7 +117,7 @@ void AsyncWebServerResponse::setContentType(const String& type){
|
||||
}
|
||||
|
||||
void AsyncWebServerResponse::addHeader(const String& name, const String& value){
|
||||
_headers.add(new AsyncWebHeader(name, value));
|
||||
_headers.emplace_back(name, value);
|
||||
}
|
||||
|
||||
String AsyncWebServerResponse::_assembleHead(uint8_t version){
|
||||
@ -145,11 +142,11 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version){
|
||||
out.concat(buf);
|
||||
}
|
||||
|
||||
for(const auto& header: _headers){
|
||||
snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str());
|
||||
for(const auto &header: _headers){
|
||||
snprintf(buf, bufSize, "%s: %s\r\n", header.name().c_str(), header.value().c_str());
|
||||
out.concat(buf);
|
||||
}
|
||||
_headers.free();
|
||||
_headers.clear();
|
||||
|
||||
out.concat("\r\n");
|
||||
_headLength = out.length();
|
||||
@ -666,16 +663,15 @@ size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){
|
||||
* Response Stream (You can print/write/printf to it, up to the contentLen bytes)
|
||||
* */
|
||||
|
||||
AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){
|
||||
AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize)
|
||||
{
|
||||
_code = 200;
|
||||
_contentLength = 0;
|
||||
_contentType = contentType;
|
||||
_content = new cbuf(bufferSize);
|
||||
_content = std::make_unique<cbuf>(bufferSize);
|
||||
}
|
||||
|
||||
AsyncResponseStream::~AsyncResponseStream(){
|
||||
delete _content;
|
||||
}
|
||||
AsyncResponseStream::~AsyncResponseStream() = default;
|
||||
|
||||
size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){
|
||||
return _content->read((char*)buf, maxLen);
|
||||
|
Reference in New Issue
Block a user