Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
// SPDX-License-Identifier: LGPL-3.0-or-later
2
// Copyright 2016-2026 Hristo Gochkov, Mathieu Carbou, Emil Muratov, Will Miles
3
 
4
#ifndef ASYNCTCP_H_
5
#define ASYNCTCP_H_
6
 
7
#include "AsyncTCPVersion.h"
8
#define ASYNCTCP_FORK_ESP32Async
9
 
10
#ifdef ARDUINO
11
#include "IPAddress.h"
12
#if __has_include(<IPv6Address.h>)
13
#include "IPv6Address.h"
14
#endif
15
#endif
16
 
17
#include "lwip/ip6_addr.h"
18
#include "lwip/ip_addr.h"
19
#include <functional>
20
 
21
#ifndef LIBRETINY
22
#include "sdkconfig.h"
23
extern "C" {
24
#include "freertos/semphr.h"
25
#include "lwip/pbuf.h"
26
}
27
#else
28
extern "C" {
29
#include <lwip/pbuf.h>
30
#include <FreeRTOS.h>
31
#include <semphr.h>
32
}
33
#endif
34
 
35
// If core is not defined, then we are running in Arduino or PIO
36
#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
37
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1  // any available core
38
#endif
39
 
40
// guard AsyncTCP task with watchdog
41
#ifndef CONFIG_ASYNC_TCP_USE_WDT
42
#define CONFIG_ASYNC_TCP_USE_WDT 1
43
#endif
44
 
45
#ifndef CONFIG_ASYNC_TCP_STACK_SIZE
46
#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2
47
#endif
48
 
49
#ifndef CONFIG_ASYNC_TCP_PRIORITY
50
#define CONFIG_ASYNC_TCP_PRIORITY 10
51
#endif
52
 
53
#ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE
54
#define CONFIG_ASYNC_TCP_QUEUE_SIZE 64
55
#endif
56
 
57
#ifndef CONFIG_ASYNC_TCP_MAX_ACK_TIME
58
#define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000
59
#endif
60
 
61
class AsyncClient;
62
 
63
#define ASYNC_WRITE_FLAG_COPY 0x01  // will allocate new buffer to hold the data while sending (else will hold reference to the data given)
64
#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.
65
 
66
typedef std::function<void(void *, AsyncClient *)> AcConnectHandler;
67
typedef std::function<void(void *, AsyncClient *, size_t len, uint32_t time)> AcAckHandler;
68
typedef std::function<void(void *, AsyncClient *, int8_t error)> AcErrorHandler;
69
typedef std::function<void(void *, AsyncClient *, void *data, size_t len)> AcDataHandler;
70
typedef std::function<void(void *, AsyncClient *, struct pbuf *pb)> AcPacketHandler;
71
typedef std::function<void(void *, AsyncClient *, uint32_t time)> AcTimeoutHandler;
72
 
73
struct tcp_pcb;
74
class AsyncTCP_detail;
75
 
76
class AsyncClient {
77
public:
78
  AsyncClient(tcp_pcb *pcb = 0);
79
  ~AsyncClient();
80
 
81
  // Noncopyable
82
  AsyncClient(const AsyncClient &) = delete;
83
  AsyncClient &operator=(const AsyncClient &) = delete;
84
 
85
  // Nonmovable
86
  AsyncClient(AsyncClient &&) = delete;
87
  AsyncClient &operator=(AsyncClient &&) = delete;
88
 
89
  bool operator==(const AsyncClient &other) const;
90
 
91
  bool operator!=(const AsyncClient &other) const {
92
    return !(*this == other);
93
  }
94
  bool connect(ip_addr_t addr, uint16_t port);
95
#ifdef ARDUINO
96
  bool connect(const IPAddress &ip, uint16_t port);
97
#if __has_include(<IPv6Address.h>)
98
  bool connect(const IPv6Address &ip, uint16_t port);
99
#endif
100
#endif
101
  bool connect(const char *host, uint16_t port);
102
 
103
  /**
104
     * @brief close connection
105
     *
106
     * @param now - ignored
107
     */
108
  [[deprecated("Use AsyncClient::close() instead")]]
109
  void close(bool now) {
110
    close();
111
  }
112
  [[deprecated("Use AsyncClient::close() instead")]]
113
  void stop() {
114
    close();
115
  };
116
 
117
  /**
118
     * @brief close connection
119
     */
120
  void close();
121
 
122
  int8_t abort();
123
  bool free();
124
 
125
  // ack is not pending
126
  bool canSend() const;
127
  // TCP buffer space available
128
  size_t space() const;
129
 
130
  /**
131
     * @brief add data to be send (but do not send yet)
132
     * @note add() would call lwip's tcp_write()
133
        By default apiflags=ASYNC_WRITE_FLAG_COPY
134
        You could try to use apiflags with this flag unset to pass data by reference and avoid copy to socket buffer,
135
        but looks like it does not work for Arduino's lwip in ESP32/IDF at least
136
        it is enforced in https://github.com/espressif/esp-lwip/blob/0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9/src/core/tcp_out.c#L422C5-L422C30
137
        if LWIP_NETIF_TX_SINGLE_PBUF is set, and it is set indeed in IDF
138
        https://github.com/espressif/esp-idf/blob/a0f798cfc4bbd624aab52b2c194d219e242d80c1/components/lwip/port/include/lwipopts.h#L744
139
     *
140
     * @param data
141
     * @param size
142
     * @param apiflags
143
     * @return size_t amount of data that has been copied
144
     */
145
  size_t add(const char *data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY);
146
 
147
  /**
148
     * @brief send data previously add()'ed
149
     *
150
     * @return true on success
151
     * @return false on error
152
     */
153
  bool send();
154
 
155
  /**
156
     * @brief add and enqueue data for sending
157
     * @note it is same as add() + send()
158
     * @note only make sense when canSend() == true
159
     *
160
     * @param data
161
     * @param size
162
     * @param apiflags
163
     * @return size_t
164
     */
165
  size_t write(const char *data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY);
166
 
167
  /**
168
     * @brief add and enqueue data for sending
169
     * @note treats data as null-terminated string
170
     *
171
     * @param data
172
     * @return size_t
173
     */
174
  size_t write(const char *data) {
175
    return data == NULL ? 0 : write(data, strlen(data));
176
  };
177
 
178
  uint8_t state() const;
179
  bool connecting() const;
180
  bool connected() const;
181
  bool disconnecting() const;
182
  bool disconnected() const;
183
 
184
  // disconnected or disconnecting
185
  bool freeable() const;
186
 
187
  uint16_t getMss() const;
188
 
189
  uint32_t getRxTimeout() const;
190
  // no RX data timeout for the connection in seconds
191
  void setRxTimeout(uint32_t timeout);
192
 
193
  uint32_t getAckTimeout() const;
194
  // no ACK timeout for the last sent packet in milliseconds
195
  void setAckTimeout(uint32_t timeout);
196
 
197
  void setNoDelay(bool nodelay) const;
198
  bool getNoDelay();
199
 
200
  void setKeepAlive(uint32_t ms, uint8_t cnt);
201
 
202
  uint32_t getRemoteAddress() const;
203
  uint16_t getRemotePort() const;
204
  uint16_t remotePort() const {
205
    return getRemotePort();
206
  }
207
 
208
  uint32_t getLocalAddress() const;
209
  uint16_t getLocalPort() const;
210
  uint16_t localPort() const {
211
    return getLocalPort();
212
  }
213
 
214
  ip4_addr_t getRemoteAddress4() const;
215
  ip4_addr_t getLocalAddress4() const;
216
 
217
#if LWIP_IPV6
218
  ip6_addr_t getRemoteAddress6() const;
219
  ip6_addr_t getLocalAddress6() const;
220
#ifdef ARDUINO
221
#if __has_include(<IPv6Address.h>)
222
  IPv6Address remoteIP6() const;
223
  IPv6Address localIP6() const;
224
#else
225
  IPAddress remoteIP6() const;
226
  IPAddress localIP6() const;
227
#endif
228
#endif
229
#endif
230
 
231
#ifdef ARDUINO
232
  IPAddress remoteIP() const;
233
  IPAddress localIP() const;
234
#endif
235
 
236
  // set callback - on successful connect
237
  void onConnect(AcConnectHandler cb, void *arg = 0);
238
  // set callback - disconnected
239
  void onDisconnect(AcConnectHandler cb, void *arg = 0);
240
  // set callback - ack received
241
  void onAck(AcAckHandler cb, void *arg = 0);
242
  // set callback - unsuccessful connect or error
243
  void onError(AcErrorHandler cb, void *arg = 0);
244
  // set callback - data received (called if onPacket is not used)
245
  void onData(AcDataHandler cb, void *arg = 0);
246
  // set callback - data received
247
  // !!! You MUST call ackPacket() or free the pbuf yourself to prevent memory leaks
248
  void onPacket(AcPacketHandler cb, void *arg = 0);
249
  // set callback - ack timeout
250
  void onTimeout(AcTimeoutHandler cb, void *arg = 0);
251
  // set callback - every 125ms when connected
252
  void onPoll(AcConnectHandler cb, void *arg = 0);
253
 
254
  // ack pbuf from onPacket
255
  void ackPacket(struct pbuf *pb);
256
  // ack data that you have not acked using the method below
257
  size_t ack(size_t len);
258
  // will not ack the current packet. Call from onData
259
  void ackLater() {
260
    _ack_pcb = false;
261
  }
262
 
263
  static const char *errorToString(int8_t error);
264
  const char *stateToString() const;
265
 
266
  int8_t _recv(tcp_pcb *pcb, pbuf *pb, int8_t err);
267
  tcp_pcb *pcb() {
268
    return _pcb;
269
  }
270
 
271
protected:
272
  friend class AsyncTCP_detail;
273
  friend class AsyncServer;
274
 
275
  tcp_pcb *_pcb;
276
 
277
  AcConnectHandler _connect_cb;
278
  void *_connect_cb_arg;
279
  AcConnectHandler _discard_cb;
280
  void *_discard_cb_arg;
281
  AcAckHandler _sent_cb;
282
  void *_sent_cb_arg;
283
  AcErrorHandler _error_cb;
284
  void *_error_cb_arg;
285
  AcDataHandler _recv_cb;
286
  void *_recv_cb_arg;
287
  AcPacketHandler _pb_cb;
288
  void *_pb_cb_arg;
289
  AcTimeoutHandler _timeout_cb;
290
  void *_timeout_cb_arg;
291
  AcConnectHandler _poll_cb;
292
  void *_poll_cb_arg;
293
 
294
  bool _ack_pcb;
295
  uint32_t _tx_last_packet;
296
  uint32_t _rx_ack_len;
297
  uint32_t _rx_last_packet;
298
  uint32_t _rx_timeout;
299
  uint32_t _rx_last_ack;
300
  uint32_t _ack_timeout;
301
  uint16_t _connect_port;
302
 
303
  int8_t _close();
304
  int8_t _connected(tcp_pcb *pcb, int8_t err);
305
  void _error(int8_t err);
306
  int8_t _poll(tcp_pcb *pcb);
307
  int8_t _sent(tcp_pcb *pcb, uint16_t len);
308
  int8_t _fin(tcp_pcb *pcb, int8_t err);
309
  int8_t _lwip_fin(tcp_pcb *pcb, int8_t err);
310
  void _dns_found(ip_addr_t *ipaddr);
311
};
312
 
313
class AsyncServer {
314
public:
315
  AsyncServer(ip_addr_t addr, uint16_t port);
316
#ifdef ARDUINO
317
  AsyncServer(IPAddress addr, uint16_t port);
318
#if __has_include(<IPv6Address.h>)
319
  AsyncServer(IPv6Address addr, uint16_t port);
320
#endif
321
#endif
322
  AsyncServer(uint16_t port);
323
  ~AsyncServer();
324
  void onClient(AcConnectHandler cb, void *arg);
325
  void begin();
326
  void end();
327
  void setNoDelay(bool nodelay);
328
  bool getNoDelay() const;
329
  uint8_t status() const;
330
 
331
protected:
332
  friend class AsyncTCP_detail;
333
 
334
  uint16_t _port;
335
  ip_addr_t _addr;
336
  bool _noDelay;
337
  tcp_pcb *_pcb;
338
  AcConnectHandler _connect_cb;
339
  void *_connect_cb_arg;
340
 
341
  int8_t _accept(tcp_pcb *newpcb, int8_t err);
342
  int8_t _accepted(AsyncClient *client);
343
};
344
 
345
#endif /* ASYNCTCP_H_ */