More crash fixes

This commit is contained in:
2020-12-19 18:57:59 +01:00
parent 2183addab0
commit 8bb1c704cd
7 changed files with 105 additions and 116 deletions

View File

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

View File

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

View File

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

View File

@ -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_ */

View File

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

View File

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

View File

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