diff options
| author | schererleander <leander@schererleander.de> | 2026-01-20 08:34:54 +0100 |
|---|---|---|
| committer | schererleander <leander@schererleander.de> | 2026-01-20 08:34:54 +0100 |
| commit | 85ea4e995a75abe061f6fc375ea0481084dddd43 (patch) | |
| tree | 7eb5d57653ecd8f041aeac4e68d7d554c1168681 /libraries/ESPAsyncTCP/src/ESPAsyncTCP.h | |
Diffstat (limited to 'libraries/ESPAsyncTCP/src/ESPAsyncTCP.h')
| -rw-r--r-- | libraries/ESPAsyncTCP/src/ESPAsyncTCP.h | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/libraries/ESPAsyncTCP/src/ESPAsyncTCP.h b/libraries/ESPAsyncTCP/src/ESPAsyncTCP.h new file mode 100644 index 0000000..2d1f768 --- /dev/null +++ b/libraries/ESPAsyncTCP/src/ESPAsyncTCP.h @@ -0,0 +1,327 @@ +/* + Asynchronous TCP library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. 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 ASYNCTCP_H_ +#define ASYNCTCP_H_ + +#include <async_config.h> +#include "IPAddress.h" +#include <functional> +#include <memory> + +extern "C" { + #include "lwip/init.h" + #include "lwip/err.h" + #include "lwip/pbuf.h" +}; + +class AsyncClient; +class AsyncServer; +class ACErrorTracker; + +#define ASYNC_MAX_ACK_TIME 5000 +#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. + +struct tcp_pcb; +struct ip_addr; +#if ASYNC_TCP_SSL_ENABLED +struct SSL_; +typedef struct SSL_ SSL; +struct SSL_CTX_; +typedef struct SSL_CTX_ SSL_CTX; +#endif + +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*, err_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; +typedef std::function<void(void*, size_t event)> AsNotifyHandler; + +enum error_events { + EE_OK = 0, + EE_ABORTED, // Callback or foreground aborted connections + EE_ERROR_CB, // Stack initiated aborts via error Callbacks. + EE_CONNECTED_CB, + EE_RECV_CB, + EE_ACCEPT_CB, + EE_MAX +}; +// DEBUG_MORE is for gathering more information on which CBs close events are +// occuring and count. +// #define DEBUG_MORE 1 +class ACErrorTracker { + private: + AsyncClient *_client; + err_t _close_error; + int _errored; +#if DEBUG_ESP_ASYNC_TCP + size_t _connectionId; +#endif +#ifdef DEBUG_MORE + AsNotifyHandler _error_event_cb; + void* _error_event_cb_arg; +#endif + + protected: + friend class AsyncClient; + friend class AsyncServer; +#ifdef DEBUG_MORE + void onErrorEvent(AsNotifyHandler cb, void *arg); +#endif +#if DEBUG_ESP_ASYNC_TCP + void setConnectionId(size_t id) { _connectionId=id;} + size_t getConnectionId(void) { return _connectionId;} +#endif + void setCloseError(err_t e); + void setErrored(size_t errorEvent); + err_t getCallbackCloseError(void); + void clearClient(void){ if (_client) _client = NULL;} + + public: + err_t getCloseError(void) const { return _close_error;} + bool hasClient(void) const { return (_client != NULL);} + ACErrorTracker(AsyncClient *c); + ~ACErrorTracker() {} +}; + +class AsyncClient { + protected: + friend class AsyncTCPbuffer; + 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 _pcb_busy; +#if ASYNC_TCP_SSL_ENABLED + bool _pcb_secure; + bool _handshake_done; +#endif + uint32_t _pcb_sent_at; + bool _close_pcb; + bool _ack_pcb; + uint32_t _tx_unacked_len; + uint32_t _tx_acked_len; + uint32_t _tx_unsent_len; + uint32_t _rx_ack_len; + uint32_t _rx_last_packet; + uint32_t _rx_since_timeout; + uint32_t _ack_timeout; + uint16_t _connect_port; + u8_t _recv_pbuf_flags; + std::shared_ptr<ACErrorTracker> _errorTracker; + + void _close(); + void _connected(std::shared_ptr<ACErrorTracker>& closeAbort, void* pcb, err_t err); + void _error(err_t err); +#if ASYNC_TCP_SSL_ENABLED + void _ssl_error(int8_t err); +#endif + void _poll(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb); + void _sent(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb, uint16_t len); +#if LWIP_VERSION_MAJOR == 1 + void _dns_found(struct ip_addr *ipaddr); +#else + void _dns_found(const ip_addr *ipaddr); +#endif + static err_t _s_poll(void *arg, struct tcp_pcb *tpcb); + static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err); + static void _s_error(void *arg, err_t err); + static err_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); + static err_t _s_connected(void* arg, void* tpcb, err_t err); +#if LWIP_VERSION_MAJOR == 1 + static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); +#else + static void _s_dns_found(const char *name, const ip_addr *ipaddr, void *arg); +#endif +#if ASYNC_TCP_SSL_ENABLED + static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len); + static void _s_handshake(void *arg, struct tcp_pcb *tcp, SSL *ssl); + static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err); +#endif + std::shared_ptr<ACErrorTracker> getACErrorTracker(void) const { return _errorTracker; }; + void setCloseError(err_t e) const { _errorTracker->setCloseError(e);} + + public: + AsyncClient* prev; + AsyncClient* next; + +#if ASYNC_TCP_SSL_ENABLED + AsyncClient(tcp_pcb* pcb = 0, SSL_CTX * ssl_ctx = NULL); +#else + AsyncClient(tcp_pcb* pcb = 0); +#endif + ~AsyncClient(); + + AsyncClient & operator=(const AsyncClient &other); + AsyncClient & operator+=(const AsyncClient &other); + + bool operator==(const AsyncClient &other); + + bool operator!=(const AsyncClient &other) { + return !(*this == other); + } +#if ASYNC_TCP_SSL_ENABLED + bool connect(IPAddress ip, uint16_t port, bool secure=false); + bool connect(const char* host, uint16_t port, bool secure=false); +#else + bool connect(IPAddress ip, uint16_t port); + bool connect(const char* host, uint16_t port); +#endif + void close(bool now = false); + void stop(); + void abort(); + bool free(); + + bool canSend();//ack is not pending + size_t space(); + size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending + bool send();//send all data added with the method above + size_t ack(size_t len); //ack data that you have not acked using the method below + void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData + bool isRecvPush(){ return !!(_recv_pbuf_flags & PBUF_FLAG_PUSH); } +#if DEBUG_ESP_ASYNC_TCP + size_t getConnectionId(void) const { return _errorTracker->getConnectionId();} +#endif +#if ASYNC_TCP_SSL_ENABLED + SSL *getSSL(); +#endif + + size_t write(const char* data); + size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true + + uint8_t state(); + bool connecting(); + bool connected(); + bool disconnecting(); + bool disconnected(); + bool freeable();//disconnected or disconnecting + + uint16_t getMss(); + uint32_t getRxTimeout(); + void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds + uint32_t getAckTimeout(); + void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds + void setNoDelay(bool nodelay); + bool getNoDelay(); + uint32_t getRemoteAddress(); + uint16_t getRemotePort(); + uint32_t getLocalAddress(); + uint16_t getLocalPort(); + + IPAddress remoteIP(); + uint16_t remotePort(); + IPAddress localIP(); + uint16_t localPort(); + + void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect + void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected + void onAck(AcAckHandler cb, void* arg = 0); //ack received + void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error + void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used) + void onPacket(AcPacketHandler cb, void* arg = 0); //data received + void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout + void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected + void ackPacket(struct pbuf * pb); + + const char * errorToString(err_t error); + const char * stateToString(); + + void _recv(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb, pbuf* pb, err_t err); + err_t getCloseError(void) const { return _errorTracker->getCloseError();} +}; + +#if ASYNC_TCP_SSL_ENABLED +typedef std::function<int(void* arg, const char *filename, uint8_t **buf)> AcSSlFileHandler; +struct pending_pcb; +#endif + + +class AsyncServer { + protected: + uint16_t _port; + IPAddress _addr; + bool _noDelay; + tcp_pcb* _pcb; + AcConnectHandler _connect_cb; + void* _connect_cb_arg; +#if ASYNC_TCP_SSL_ENABLED + struct pending_pcb * _pending; + SSL_CTX * _ssl_ctx; + AcSSlFileHandler _file_cb; + void* _file_cb_arg; +#endif +#ifdef DEBUG_MORE + int _event_count[EE_MAX]; +#endif + + public: + + AsyncServer(IPAddress addr, uint16_t port); + AsyncServer(uint16_t port); + ~AsyncServer(); + void onClient(AcConnectHandler cb, void* arg); +#if ASYNC_TCP_SSL_ENABLED + void onSslFileRequest(AcSSlFileHandler cb, void* arg); + void beginSecure(const char *cert, const char *private_key_file, const char *password); +#endif + void begin(); + void end(); + void setNoDelay(bool nodelay); + bool getNoDelay(); + uint8_t status(); +#ifdef DEBUG_MORE + int getEventCount(size_t ee) const { return _event_count[ee];} +#endif + protected: + err_t _accept(tcp_pcb* newpcb, err_t err); + static err_t _s_accept(void *arg, tcp_pcb* newpcb, err_t err); +#ifdef DEBUG_MORE + int incEventCount(size_t ee) { return ++_event_count[ee];} +#endif +#if ASYNC_TCP_SSL_ENABLED + int _cert(const char *filename, uint8_t **buf); + err_t _poll(tcp_pcb* pcb); + err_t _recv(tcp_pcb *pcb, struct pbuf *pb, err_t err); + static int _s_cert(void *arg, const char *filename, uint8_t **buf); + static err_t _s_poll(void *arg, struct tcp_pcb *tpcb); + static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err); +#endif +}; + + +#endif /* ASYNCTCP_H_ */ |
