diff --git a/library.properties b/library.properties index 42b23fa..1a6a9b8 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=ESP AsyncTCP -version=1.2.2 +version=1.2.3 author=Me-No-Dev maintainer=Me-No-Dev -sentence=Async TCP Library for ESP8266 and ESP31B -paragraph=Async TCP Library for ESP8266 and ESP31B +sentence=Async TCP Library for ESP8266 and ESP31B and RP2040 Pico +paragraph=Async TCP Library for ESP8266 and ESP31B and RP2040 Pico category=Other url=https://github.com/me-no-dev/ESPAsyncTCP architectures=* diff --git a/src/AsyncPrinter.cpp b/src/AsyncPrinter.cpp index 8a63f20..d23e4e7 100644 --- a/src/AsyncPrinter.cpp +++ b/src/AsyncPrinter.cpp @@ -45,7 +45,11 @@ AsyncPrinter::AsyncPrinter(AsyncClient *client, size_t txBufLen) _attachCallbacks(); _tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size); if(_tx_buffer == NULL) { +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); //What should we do? +#else panic(); //What should we do? +#endif } } @@ -68,7 +72,11 @@ int AsyncPrinter::connect(IPAddress ip, uint16_t port){ return 0; _client = new (std::nothrow) AsyncClient(); if (_client == NULL) { +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); +#else panic(); +#endif } _client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this); @@ -85,7 +93,11 @@ int AsyncPrinter::connect(const char *host, uint16_t port){ return 0; _client = new (std::nothrow) AsyncClient(); if (_client == NULL) { +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); +#else panic(); +#endif } _client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this); @@ -106,7 +118,11 @@ void AsyncPrinter::_onConnect(AsyncClient *c){ } _tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size); if(_tx_buffer) { +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); +#else panic(); +#endif } _attachCallbacks(); @@ -127,7 +143,11 @@ AsyncPrinter & AsyncPrinter::operator=(const AsyncPrinter &other){ } _tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size); if(_tx_buffer == NULL) { +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); +#else panic(); +#endif } _client = other._client; @@ -179,12 +199,16 @@ size_t AsyncPrinter::_sendBuffer(){ available= sendable; char *out = new (std::nothrow) char[available]; if (out == NULL) { +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); // Connection should be aborted instead +#else panic(); // Connection should be aborted instead +#endif } _tx_buffer->read(out, available); size_t sent = _client->write(out, available); - delete out; + delete[] out; return sent; } diff --git a/src/ESPAsyncTCP.cpp b/src/ESPAsyncTCP.cpp index 7a9fdc7..510af15 100644 --- a/src/ESPAsyncTCP.cpp +++ b/src/ESPAsyncTCP.cpp @@ -703,6 +703,8 @@ void AsyncClient::_dns_found(const ip_addr *ipaddr){ if(ipaddr){ #if ASYNC_TCP_SSL_ENABLED connect(IPAddress(ipaddr->addr), _connect_port, _pcb_secure); +#elif defined(ARDUINO_ARCH_RP2040) + connect(IPAddress((const ip_addr_t*)ipaddr), _connect_port); #else connect(IPAddress(ipaddr->addr), _connect_port); #endif diff --git a/src/ESPAsyncTCPbuffer.cpp b/src/ESPAsyncTCPbuffer.cpp index d2261da..3ec130c 100644 --- a/src/ESPAsyncTCPbuffer.cpp +++ b/src/ESPAsyncTCPbuffer.cpp @@ -24,7 +24,9 @@ #include +#if !defined(ARDUINO_ARCH_RP2040) #include +#endif #include "ESPAsyncTCPbuffer.h" @@ -32,7 +34,11 @@ AsyncTCPbuffer::AsyncTCPbuffer(AsyncClient* client) { if(client == NULL) { DEBUG_ASYNC_TCP("[A-TCP] client is null!!!\n"); +#if defined(ARDUINO_ARCH_RP2040) + panic("[A-TCP] client is null!!!\n"); +#else panic(); +#endif } _client = client; @@ -116,7 +122,11 @@ size_t AsyncTCPbuffer::write(const uint8_t *data, size_t len) { if(_TXbufferWrite->full() && bytesLeft > 0) { // to less ram!!! +#if defined(ARDUINO_ARCH_RP2040) + if(rp2040.getFreeHeap() < 4096) { +#else if(ESP.getFreeHeap() < 4096) { +#endif DEBUG_ASYNC_TCP("[A-TCP] run out of Heap can not send all Data!\n"); return (len - bytesLeft); } @@ -124,7 +134,11 @@ size_t AsyncTCPbuffer::write(const uint8_t *data, size_t len) { cbuf * next = new (std::nothrow) cbuf(TCP_MSS); if(next == NULL) { DEBUG_ASYNC_TCP("[A-TCP] run out of Heap!\n"); +#if defined(ARDUINO_ARCH_RP2040) + panic("[A-TCP] run out of Heap!\n"); +#else panic(); +#endif } else { DEBUG_ASYNC_TCP("[A-TCP] new cbuf\n"); } @@ -221,7 +235,7 @@ void AsyncTCPbuffer::onDisconnect(AsyncTCPbufferDisconnectCb cb) { IPAddress AsyncTCPbuffer::remoteIP() { if(!_client) { - return IPAddress(0U); + return IPAddress((uint32_t)0); } return _client->remoteIP(); } @@ -371,11 +385,11 @@ void AsyncTCPbuffer::_sendBuffer() { if(_TXbufferRead->available() == 0 && _TXbufferRead->next != NULL) { cbuf * old = _TXbufferRead; _TXbufferRead = _TXbufferRead->next; - delete old; + delete[] old; DEBUG_ASYNC_TCP("[A-TCP] delete cbuf\n"); } - delete out; + delete[] out; } } @@ -466,8 +480,12 @@ size_t AsyncTCPbuffer::_handleRxBuffer(uint8_t *buf, size_t len) { if(BufferAvailable > 0) { uint8_t * b = new (std::nothrow) uint8_t[BufferAvailable]; if(b == NULL){ +#if defined(ARDUINO_ARCH_RP2040) + panic("OOM"); //TODO: What action should this be ? +#else panic(); //TODO: What action should this be ? - } +#endif + } _RXbuffer->peek((char *) b, BufferAvailable); r = _cbRX(b, BufferAvailable); _RXbuffer->remove(r); diff --git a/src/SyncClient.cpp b/src/SyncClient.cpp index 8335358..c4d1a99 100644 --- a/src/SyncClient.cpp +++ b/src/SyncClient.cpp @@ -22,7 +22,9 @@ #include "SyncClient.h" #include "ESPAsyncTCP.h" #include "cbuf.h" +#if !defined(ARDUINO_ARCH_RP2040) #include +#endif #define DEBUG_ESP_SYNC_CLIENT #if defined(DEBUG_ESP_SYNC_CLIENT) && !defined(SYNC_CLIENT_DEBUG) diff --git a/src/cbuf.cpp b/src/cbuf.cpp new file mode 100644 index 0000000..44b938d --- /dev/null +++ b/src/cbuf.cpp @@ -0,0 +1,184 @@ +#if defined(ARDUINO_ARCH_RP2040) +/* + cbuf.cpp - Circular buffer implementation + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include // std::nothrow +#include "cbuf.h" +//#include "c_types.h" +#undef IRAM_ATTR +#define IRAM_ATTR + +cbuf::cbuf(size_t size) : + next(NULL), _size(size), _buf(new char[size]), _bufend(_buf + size), _begin(_buf), _end(_begin) { +} + +cbuf::~cbuf() { + delete[] _buf; +} + +size_t cbuf::resizeAdd(size_t addSize) { + return resize(_size + addSize); +} + +size_t cbuf::resize(size_t newSize) { + + size_t bytes_available = available(); + + // not lose any data + // if data can be lost use remove or flush before resize + if((newSize <= bytes_available) || (newSize == _size)) { + return _size; + } + + char *newbuf = new (std::nothrow) char[newSize]; + char *oldbuf = _buf; + + if(!newbuf) { + return _size; + } + + if(_buf) { + read(newbuf, bytes_available); + memset((newbuf + bytes_available), 0x00, (newSize - bytes_available)); + } + + _begin = newbuf; + _end = newbuf + bytes_available; + _bufend = newbuf + newSize; + _size = newSize; + + _buf = newbuf; + delete[] oldbuf; + + return _size; +} + +size_t IRAM_ATTR cbuf::available() const { + if(_end >= _begin) { + return _end - _begin; + } + return _size - (_begin - _end); +} + +size_t cbuf::size() { + return _size; +} + +size_t cbuf::room() const { + if(_end >= _begin) { + return _size - (_end - _begin) - 1; + } + return _begin - _end - 1; +} + +int cbuf::peek() { + if(empty()) + return -1; + + return static_cast(*_begin); +} + +size_t cbuf::peek(char *dst, size_t size) { + size_t bytes_available = available(); + size_t size_to_read = (size < bytes_available) ? size : bytes_available; + size_t size_read = size_to_read; + char * begin = _begin; + if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) { + size_t top_size = _bufend - _begin; + memcpy(dst, _begin, top_size); + begin = _buf; + size_to_read -= top_size; + dst += top_size; + } + memcpy(dst, begin, size_to_read); + return size_read; +} + +int IRAM_ATTR cbuf::read() { + if(empty()) + return -1; + + char result = *_begin; + _begin = wrap_if_bufend(_begin + 1); + return static_cast(result); +} + +size_t cbuf::read(char* dst, size_t size) { + size_t bytes_available = available(); + size_t size_to_read = (size < bytes_available) ? size : bytes_available; + size_t size_read = size_to_read; + if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) { + size_t top_size = _bufend - _begin; + memcpy(dst, _begin, top_size); + _begin = _buf; + size_to_read -= top_size; + dst += top_size; + } + memcpy(dst, _begin, size_to_read); + _begin = wrap_if_bufend(_begin + size_to_read); + return size_read; +} + +size_t IRAM_ATTR cbuf::write(char c) { + if(full()) + return 0; + + *_end = c; + _end = wrap_if_bufend(_end + 1); + return 1; +} + +size_t cbuf::write(const char* src, size_t size) { + size_t bytes_available = room(); + size_t size_to_write = (size < bytes_available) ? size : bytes_available; + size_t size_written = size_to_write; + if(_end >= _begin && size_to_write > (size_t) (_bufend - _end)) { + size_t top_size = _bufend - _end; + memcpy(_end, src, top_size); + _end = _buf; + size_to_write -= top_size; + src += top_size; + } + memcpy(_end, src, size_to_write); + _end = wrap_if_bufend(_end + size_to_write); + return size_written; +} + +void cbuf::flush() { + _begin = _buf; + _end = _buf; +} + +size_t cbuf::remove(size_t size) { + size_t bytes_available = available(); + if(size >= bytes_available) { + flush(); + return 0; + } + size_t size_to_remove = (size < bytes_available) ? size : bytes_available; + if(_end < _begin && size_to_remove > (size_t) (_bufend - _begin)) { + size_t top_size = _bufend - _begin; + _begin = _buf; + size_to_remove -= top_size; + } + _begin = wrap_if_bufend(_begin + size_to_remove); + return available(); +} +#endif diff --git a/src/cbuf.h b/src/cbuf.h new file mode 100644 index 0000000..9c358a7 --- /dev/null +++ b/src/cbuf.h @@ -0,0 +1,75 @@ +/* + cbuf.h - Circular buffer implementation + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __cbuf_h +#define __cbuf_h + +#include +#include +#include + +class cbuf { + public: + cbuf(size_t size); + ~cbuf(); + + size_t resizeAdd(size_t addSize); + size_t resize(size_t newSize); + size_t available() const; + size_t size(); + + size_t room() const; + + inline bool empty() const { + return _begin == _end; + } + + inline bool full() const { + return wrap_if_bufend(_end + 1) == _begin; + } + + int peek(); + size_t peek(char *dst, size_t size); + + int read(); + size_t read(char* dst, size_t size); + + size_t write(char c); + size_t write(const char* src, size_t size); + + void flush(); + size_t remove(size_t size); + + cbuf *next; + + private: + inline char* wrap_if_bufend(char* ptr) const { + return (ptr == _bufend) ? _buf : ptr; + } + + size_t _size; + char* _buf; + const char* _bufend; + char* _begin; + char* _end; + +}; + +#endif//__cbuf_h