chore: import local project into Gitea

This commit is contained in:
2026-05-20 10:03:16 -07:00
commit 7bd88d29b5
4043 changed files with 1056916 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,335 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
#ifndef ASYNCTCP_H_
#define ASYNCTCP_H_
#include "AsyncTCPVersion.h"
#define ASYNCTCP_FORK_ESP32Async
#ifdef ARDUINO
#include "IPAddress.h"
#if __has_include(<IPv6Address.h>)
#include "IPv6Address.h"
#endif
#endif
#include "lwip/ip6_addr.h"
#include "lwip/ip_addr.h"
#include <functional>
#ifndef LIBRETINY
#include "sdkconfig.h"
extern "C" {
#include "freertos/semphr.h"
#include "lwip/pbuf.h"
}
#else
extern "C" {
#include <lwip/pbuf.h>
#include <FreeRTOS.h>
#include <semphr.h>
}
#endif
// If core is not defined, then we are running in Arduino or PIO
#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 // any available core
#endif
// guard AsyncTCP task with watchdog
#ifndef CONFIG_ASYNC_TCP_USE_WDT
#define CONFIG_ASYNC_TCP_USE_WDT 1
#endif
#ifndef CONFIG_ASYNC_TCP_STACK_SIZE
#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2
#endif
#ifndef CONFIG_ASYNC_TCP_PRIORITY
#define CONFIG_ASYNC_TCP_PRIORITY 10
#endif
#ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE
#define CONFIG_ASYNC_TCP_QUEUE_SIZE 64
#endif
#ifndef CONFIG_ASYNC_TCP_MAX_ACK_TIME
#define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000
#endif
class AsyncClient;
#define ASYNC_WRITE_FLAG_COPY 0x01 // will allocate new buffer to hold the data while sending (else will hold reference to the data given)
#define ASYNC_WRITE_FLAG_MORE 0x02 // will not send PSH flag, meaning that there should be more data to be sent before the application should react.
typedef std::function<void(void *, AsyncClient *)> AcConnectHandler;
typedef std::function<void(void *, AsyncClient *, size_t len, uint32_t time)> AcAckHandler;
typedef std::function<void(void *, AsyncClient *, int8_t error)> AcErrorHandler;
typedef std::function<void(void *, AsyncClient *, void *data, size_t len)> AcDataHandler;
typedef std::function<void(void *, AsyncClient *, struct pbuf *pb)> AcPacketHandler;
typedef std::function<void(void *, AsyncClient *, uint32_t time)> AcTimeoutHandler;
struct tcp_pcb;
class AsyncTCP_detail;
class AsyncClient {
public:
AsyncClient(tcp_pcb *pcb = 0);
~AsyncClient();
// Noncopyable
AsyncClient(const AsyncClient &) = delete;
AsyncClient &operator=(const AsyncClient &) = delete;
// Nonmovable
AsyncClient(AsyncClient &&) = delete;
AsyncClient &operator=(AsyncClient &&) = delete;
bool operator==(const AsyncClient &other) const;
bool operator!=(const AsyncClient &other) const {
return !(*this == other);
}
bool connect(ip_addr_t addr, uint16_t port);
#ifdef ARDUINO
bool connect(const IPAddress &ip, uint16_t port);
#if __has_include(<IPv6Address.h>)
bool connect(const IPv6Address &ip, uint16_t port);
#endif
#endif
bool connect(const char *host, uint16_t port);
/**
* @brief close connection
*
* @param now - ignored
*/
void close(bool now = false);
// same as close()
void stop() {
close(false);
};
int8_t abort();
bool free();
// ack is not pending
bool canSend() const;
// TCP buffer space available
size_t space() const;
/**
* @brief add data to be send (but do not send yet)
* @note add() would call lwip's tcp_write()
By default apiflags=ASYNC_WRITE_FLAG_COPY
You could try to use apiflags with this flag unset to pass data by reference and avoid copy to socket buffer,
but looks like it does not work for Arduino's lwip in ESP32/IDF at least
it is enforced in https://github.com/espressif/esp-lwip/blob/0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9/src/core/tcp_out.c#L422C5-L422C30
if LWIP_NETIF_TX_SINGLE_PBUF is set, and it is set indeed in IDF
https://github.com/espressif/esp-idf/blob/a0f798cfc4bbd624aab52b2c194d219e242d80c1/components/lwip/port/include/lwipopts.h#L744
*
* @param data
* @param size
* @param apiflags
* @return size_t amount of data that has been copied
*/
size_t add(const char *data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY);
/**
* @brief send data previously add()'ed
*
* @return true on success
* @return false on error
*/
bool send();
/**
* @brief add and enqueue data for sending
* @note it is same as add() + send()
* @note only make sense when canSend() == true
*
* @param data
* @param size
* @param apiflags
* @return size_t
*/
size_t write(const char *data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY);
/**
* @brief add and enqueue data for sending
* @note treats data as null-terminated string
*
* @param data
* @return size_t
*/
size_t write(const char *data) {
return data == NULL ? 0 : write(data, strlen(data));
};
uint8_t state() const;
bool connecting() const;
bool connected() const;
bool disconnecting() const;
bool disconnected() const;
// disconnected or disconnecting
bool freeable() const;
uint16_t getMss() const;
uint32_t getRxTimeout() const;
// no RX data timeout for the connection in seconds
void setRxTimeout(uint32_t timeout);
uint32_t getAckTimeout() const;
// no ACK timeout for the last sent packet in milliseconds
void setAckTimeout(uint32_t timeout);
void setNoDelay(bool nodelay) const;
bool getNoDelay();
void setKeepAlive(uint32_t ms, uint8_t cnt);
uint32_t getRemoteAddress() const;
uint16_t getRemotePort() const;
uint16_t remotePort() const {
return getRemotePort();
}
uint32_t getLocalAddress() const;
uint16_t getLocalPort() const;
uint16_t localPort() const {
return getLocalPort();
}
ip4_addr_t getRemoteAddress4() const;
ip4_addr_t getLocalAddress4() const;
#if LWIP_IPV6
ip6_addr_t getRemoteAddress6() const;
ip6_addr_t getLocalAddress6() const;
#ifdef ARDUINO
#if __has_include(<IPv6Address.h>)
IPv6Address remoteIP6() const;
IPv6Address localIP6() const;
#else
IPAddress remoteIP6() const;
IPAddress localIP6() const;
#endif
#endif
#endif
#ifdef ARDUINO
IPAddress remoteIP() const;
IPAddress localIP() const;
#endif
// set callback - on successful connect
void onConnect(AcConnectHandler cb, void *arg = 0);
// set callback - disconnected
void onDisconnect(AcConnectHandler cb, void *arg = 0);
// set callback - ack received
void onAck(AcAckHandler cb, void *arg = 0);
// set callback - unsuccessful connect or error
void onError(AcErrorHandler cb, void *arg = 0);
// set callback - data received (called if onPacket is not used)
void onData(AcDataHandler cb, void *arg = 0);
// set callback - data received
// !!! You MUST call ackPacket() or free the pbuf yourself to prevent memory leaks
void onPacket(AcPacketHandler cb, void *arg = 0);
// set callback - ack timeout
void onTimeout(AcTimeoutHandler cb, void *arg = 0);
// set callback - every 125ms when connected
void onPoll(AcConnectHandler cb, void *arg = 0);
// ack pbuf from onPacket
void ackPacket(struct pbuf *pb);
// ack data that you have not acked using the method below
size_t ack(size_t len);
// will not ack the current packet. Call from onData
void ackLater() {
_ack_pcb = false;
}
static const char *errorToString(int8_t error);
const char *stateToString() const;
int8_t _recv(tcp_pcb *pcb, pbuf *pb, int8_t err);
tcp_pcb *pcb() {
return _pcb;
}
protected:
friend class AsyncTCP_detail;
friend class AsyncServer;
tcp_pcb *_pcb;
AcConnectHandler _connect_cb;
void *_connect_cb_arg;
AcConnectHandler _discard_cb;
void *_discard_cb_arg;
AcAckHandler _sent_cb;
void *_sent_cb_arg;
AcErrorHandler _error_cb;
void *_error_cb_arg;
AcDataHandler _recv_cb;
void *_recv_cb_arg;
AcPacketHandler _pb_cb;
void *_pb_cb_arg;
AcTimeoutHandler _timeout_cb;
void *_timeout_cb_arg;
AcConnectHandler _poll_cb;
void *_poll_cb_arg;
bool _ack_pcb;
uint32_t _tx_last_packet;
uint32_t _rx_ack_len;
uint32_t _rx_last_packet;
uint32_t _rx_timeout;
uint32_t _rx_last_ack;
uint32_t _ack_timeout;
uint16_t _connect_port;
int8_t _close();
int8_t _connected(tcp_pcb *pcb, int8_t err);
void _error(int8_t err);
int8_t _poll(tcp_pcb *pcb);
int8_t _sent(tcp_pcb *pcb, uint16_t len);
int8_t _fin(tcp_pcb *pcb, int8_t err);
int8_t _lwip_fin(tcp_pcb *pcb, int8_t err);
void _dns_found(ip_addr_t *ipaddr);
};
class AsyncServer {
public:
AsyncServer(ip_addr_t addr, uint16_t port);
#ifdef ARDUINO
AsyncServer(IPAddress addr, uint16_t port);
#if __has_include(<IPv6Address.h>)
AsyncServer(IPv6Address addr, uint16_t port);
#endif
#endif
AsyncServer(uint16_t port);
~AsyncServer();
void onClient(AcConnectHandler cb, void *arg);
void begin();
void end();
void setNoDelay(bool nodelay);
bool getNoDelay() const;
uint8_t status() const;
protected:
friend class AsyncTCP_detail;
uint16_t _port;
ip_addr_t _addr;
bool _noDelay;
tcp_pcb *_pcb;
AcConnectHandler _connect_cb;
void *_connect_cb_arg;
int8_t _accept(tcp_pcb *newpcb, int8_t err);
int8_t _accepted(AsyncClient *client);
};
#endif /* ASYNCTCP_H_ */

View File

@@ -0,0 +1,66 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
#pragma once
#ifdef CONFIG_ASYNC_TCP_LOG_CUSTOM
// The user must provide the following macros in AsyncTCPLoggingCustom.h:
// async_tcp_log_e, async_tcp_log_w, async_tcp_log_i, async_tcp_log_d, async_tcp_log_v
#include <AsyncTCPLoggingCustom.h>
#elif defined(CONFIG_ASYNC_TCP_DEBUG)
// Local Debug logging
#include <HardwareSerial.h>
#define async_tcp_log_e(format, ...) Serial.printf("E async_tcp %s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define async_tcp_log_w(format, ...) Serial.printf("W async_tcp %s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define async_tcp_log_i(format, ...) Serial.printf("I async_tcp %s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define async_tcp_log_d(format, ...) Serial.printf("D async_tcp %s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define async_tcp_log_v(format, ...) Serial.printf("V async_tcp %s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
// Framework-based logging
/**
* LibreTiny specific configurations
*/
#if defined(LIBRETINY)
#include <Arduino.h>
#define async_tcp_log_e(format, ...) log_e(format, ##__VA_ARGS__)
#define async_tcp_log_w(format, ...) log_w(format, ##__VA_ARGS__)
#define async_tcp_log_i(format, ...) log_i(format, ##__VA_ARGS__)
#define async_tcp_log_d(format, ...) log_d(format, ##__VA_ARGS__)
#define async_tcp_log_v(format, ...) log_v(format, ##__VA_ARGS__)
/**
* Arduino specific configurations
*/
#elif defined(ARDUINO)
#if defined(USE_ESP_IDF_LOG)
#include <esp_log.h>
#define async_tcp_log_e(format, ...) ESP_LOGE("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_w(format, ...) ESP_LOGW("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_i(format, ...) ESP_LOGI("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_d(format, ...) ESP_LOGD("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_v(format, ...) ESP_LOGV("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#include <esp32-hal-log.h>
#define async_tcp_log_e(format, ...) log_e(format, ##__VA_ARGS__)
#define async_tcp_log_w(format, ...) log_w(format, ##__VA_ARGS__)
#define async_tcp_log_i(format, ...) log_i(format, ##__VA_ARGS__)
#define async_tcp_log_d(format, ...) log_d(format, ##__VA_ARGS__)
#define async_tcp_log_v(format, ...) log_v(format, ##__VA_ARGS__)
#endif // USE_ESP_IDF_LOG
/**
* ESP-IDF specific configurations
*/
#else
#include <esp_log.h>
#define async_tcp_log_e(format, ...) ESP_LOGE("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_w(format, ...) ESP_LOGW("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_i(format, ...) ESP_LOGI("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_d(format, ...) ESP_LOGD("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define async_tcp_log_v(format, ...) ESP_LOGV("async_tcp", "%s() %d: " format, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif // !LIBRETINY && !ARDUINO
#endif // CONFIG_ASYNC_TCP_LOG_CUSTOM

View File

@@ -0,0 +1,134 @@
// Simple intrusive list class
#pragma once
template<typename T> class SimpleIntrusiveList {
static_assert(std::is_same<decltype(std::declval<T>().next), T *>::value, "Template type must have public 'T* next' member");
public:
typedef T value_type;
typedef value_type *value_ptr_type;
typedef value_ptr_type *value_ptr_ptr_type;
// Static utility methods
static size_t list_size(value_ptr_type chain) {
size_t count = 0;
for (auto c = chain; c != nullptr; c = c->next) {
++count;
}
return count;
}
static void delete_list(value_ptr_type chain) {
while (chain) {
auto t = chain;
chain = chain->next;
delete t;
}
}
public:
// Object methods
SimpleIntrusiveList() : _head(nullptr), _tail(&_head) {}
~SimpleIntrusiveList() {
clear();
}
// Noncopyable, nonmovable
SimpleIntrusiveList(const SimpleIntrusiveList<T> &) = delete;
SimpleIntrusiveList(SimpleIntrusiveList<T> &&) = delete;
SimpleIntrusiveList<T> &operator=(const SimpleIntrusiveList<T> &) = delete;
SimpleIntrusiveList<T> &operator=(SimpleIntrusiveList<T> &&) = delete;
inline void push_back(value_ptr_type obj) {
if (obj) {
*_tail = obj;
_tail = &obj->next;
++_size;
}
}
inline void push_front(value_ptr_type obj) {
if (obj) {
if (_head == nullptr) {
_tail = &obj->next;
}
obj->next = _head;
_head = obj;
++_size;
}
}
inline value_ptr_type pop_front() {
auto rv = _head;
if (_head) {
if (_tail == &_head->next) {
_tail = &_head;
}
_head = _head->next;
--_size;
}
return rv;
}
inline void clear() {
// Assumes all elements were allocated with "new"
delete_list(_head);
_head = nullptr;
_tail = &_head;
_size = 0;
}
inline size_t size() const {
return _size;
}
template<typename function_type> inline value_ptr_type remove_if(const function_type &condition) {
value_ptr_type removed = nullptr;
value_ptr_ptr_type current_ptr = &_head;
while (*current_ptr != nullptr) {
value_ptr_type current = *current_ptr;
if (condition(*current)) {
// Remove this item from the list by moving the next item in
*current_ptr = current->next;
// If we were the last item, reset tail
if (current->next == nullptr) {
_tail = current_ptr;
}
--_size;
// Prepend this item to the removed list
current->next = removed;
removed = current;
// do not advance current_ptr
} else {
// advance current_ptr
current_ptr = &(*current_ptr)->next;
}
}
// Return the removed entries
return removed;
}
inline value_ptr_type begin() const {
return _head;
}
bool validate_tail() const {
if (_head == nullptr) {
return (_tail == &_head);
}
auto p = _head;
while (p->next != nullptr) {
p = p->next;
}
return _tail == &p->next;
}
private:
// Data members
value_ptr_type _head;
value_ptr_ptr_type _tail;
size_t _size;
}; // class simple_intrusive_list

View File

@@ -0,0 +1,40 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** Major version number (X.x.x) */
#define ASYNCTCP_VERSION_MAJOR 3
/** Minor version number (x.X.x) */
#define ASYNCTCP_VERSION_MINOR 4
/** Patch version number (x.x.X) */
#define ASYNCTCP_VERSION_PATCH 9
/**
* Macro to convert version number into an integer
*
* To be used in comparisons, such as ASYNCTCP_VERSION >= ASYNCTCP_VERSION_VAL(2, 0, 0)
*/
#define ASYNCTCP_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
/**
* Current version, as an integer
*
* To be used in comparisons, such as ASYNCTCP_VERSION_NUM >= ASYNCTCP_VERSION_VAL(2, 0, 0)
*/
#define ASYNCTCP_VERSION_NUM ASYNCTCP_VERSION_VAL(ASYNCTCP_VERSION_MAJOR, ASYNCTCP_VERSION_MINOR, ASYNCTCP_VERSION_PATCH)
/**
* Current version, as string
*/
#define df2xstr(s) #s
#define df2str(s) df2xstr(s)
#define ASYNCTCP_VERSION df2str(ASYNCTCP_VERSION_MAJOR) "." df2str(ASYNCTCP_VERSION_MINOR) "." df2str(ASYNCTCP_VERSION_PATCH)
#ifdef __cplusplus
}
#endif