chore: import local project into Gitea
This commit is contained in:
1612
WiFiX-Enhanced/.pio/libdeps/esp32_enhanced/AsyncTCP/src/AsyncTCP.cpp
Normal file
1612
WiFiX-Enhanced/.pio/libdeps/esp32_enhanced/AsyncTCP/src/AsyncTCP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user