@alteriom/painlessmesh 1.6.1 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CHANGELOG.md +435 -144
  2. package/LICENSE +674 -674
  3. package/README.md +491 -434
  4. package/RELEASE_GUIDE.md +504 -418
  5. package/docs/DOCUMENTATION_MIGRATION_PLAN.md +175 -175
  6. package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +1062 -0
  7. package/docs/MESH_TOPOLOGY_GUIDE.md +992 -0
  8. package/docs/MESH_TOPOLOGY_PROGRESS.md +422 -0
  9. package/docs/MQTT_BRIDGE_COMMANDS.md +894 -0
  10. package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +324 -0
  11. package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +576 -0
  12. package/docs/MQTT_SCHEMA_COMPLIANCE.md +285 -0
  13. package/docs/MQTT_SCHEMA_PROPOSALS.md +446 -0
  14. package/docs/MQTT_SCHEMA_REVIEW.md +690 -0
  15. package/docs/OTA_COMMANDS_REFERENCE.md +554 -0
  16. package/docs/PHASE1_GUIDE.md +349 -0
  17. package/docs/PHASE2_GUIDE.md +543 -0
  18. package/docs/README.md +130 -71
  19. package/docs/SCHEMA_VALIDATION_CHECKLIST.md +222 -0
  20. package/docs/alteriom/overview.md +507 -507
  21. package/docs/api/core-api.md +606 -606
  22. package/docs/architecture/mesh-architecture.md +378 -378
  23. package/docs/architecture/plugin-system.md +516 -516
  24. package/docs/archive/DOCUSAURUS_DEPLOYMENT.md +166 -0
  25. package/docs/archive/FEATURE_PROPOSALS.md +337 -0
  26. package/docs/archive/LIBRARY_JSON_FIX.md +98 -0
  27. package/docs/archive/LIBRARY_STRUCTURE_FIX.md +215 -0
  28. package/docs/archive/PHASE1_IMPLEMENTATION.md +325 -0
  29. package/docs/archive/PHASE2_IMPLEMENTATION.md +567 -0
  30. package/docs/archive/RELEASE_SUMMARY.md +173 -0
  31. package/docs/archive/SCONS_BUILD_FIX.md +313 -0
  32. package/docs/archive/TRIGGER_RELEASE.md +280 -0
  33. package/docs/archive/VECTOR_INCLUDE_FIX.md +129 -0
  34. package/docs/archive/ota-and-status-enhancements.md +911 -0
  35. package/docs/archive/ota-status-architecture-diagrams.md +658 -0
  36. package/docs/archive/ota-status-quick-reference.md +284 -0
  37. package/docs/development/ARDUINO_COMPLIANCE_SUMMARY.md +71 -0
  38. package/docs/development/CODE_REFACTORING_RECOMMENDATIONS.md +1011 -0
  39. package/docs/development/DOCKER_TESTING.md +196 -0
  40. package/docs/development/PLATFORMIO_USAGE.md +180 -0
  41. package/docs/development/TESTING_SUMMARY.md +126 -0
  42. package/docs/development/contributing.md +301 -0
  43. package/docs/development/documentation.md +583 -0
  44. package/docs/getting-started/first-mesh.md +409 -409
  45. package/docs/getting-started/installation.md +274 -274
  46. package/docs/getting-started/quickstart.md +157 -157
  47. package/docs/improvements/FUTURE_PROPOSALS.md +1016 -0
  48. package/docs/improvements/IMPLEMENTATION_HISTORY.md +1091 -0
  49. package/docs/improvements/OTA_STATUS_ENHANCEMENTS.md +709 -0
  50. package/docs/improvements/README.md +212 -69
  51. package/docs/platformio-publishing.md +255 -0
  52. package/docs/platformio-setup-summary.md +121 -0
  53. package/docs/releases/FEATURE_HISTORY.md +543 -0
  54. package/docs/releases/PATCH_v1.7.3.md +262 -0
  55. package/docs/releases/PHASE1_SUMMARY.md +246 -0
  56. package/docs/releases/PHASE2_SUMMARY.md +499 -0
  57. package/docs/releases/RELEASE_NOTES_1.7.0.md +539 -0
  58. package/docs/troubleshooting/common-issues.md +520 -520
  59. package/docs/troubleshooting/debugging.md +455 -0
  60. package/docs/troubleshooting/faq.md +472 -472
  61. package/docs/tutorials/basic-examples.md +717 -717
  62. package/docs/wiki/API-Reference.md +245 -245
  63. package/docs/wiki/Complete-Documentation.md +122 -122
  64. package/examples/alteriom/README.md +139 -81
  65. package/examples/alteriom/alteriom.ino +186 -185
  66. package/examples/alteriom/alteriom_sensor_package.hpp +240 -127
  67. package/examples/alteriom/platformio.ini +24 -24
  68. package/examples/alteriomImproved/alteriom_sensor_package.hpp +224 -0
  69. package/examples/{alteriom → alteriomImproved}/improved_sensor_node.ino +245 -245
  70. package/examples/alteriomImproved/platformio.ini +25 -0
  71. package/examples/alteriomPhase1/alteriom_sensor_package.hpp +224 -0
  72. package/examples/alteriomPhase1/phase1_features.ino +242 -0
  73. package/examples/alteriomPhase1/platformio.ini +25 -0
  74. package/examples/alteriomPhase2/alteriom_sensor_package.hpp +224 -0
  75. package/examples/alteriomPhase2/phase2_features.ino +186 -0
  76. package/examples/alteriomPhase2/platformio.ini +25 -0
  77. package/examples/{alteriom → alteriomSensorNode}/alteriom_sensor_node.ino +183 -183
  78. package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +224 -0
  79. package/examples/alteriomSensorNode/platformio.ini +25 -0
  80. package/examples/basic/basic.ino +66 -66
  81. package/examples/basic/platformio.ini +25 -25
  82. package/examples/bridge/bridge.ino +51 -51
  83. package/examples/bridge/mesh_event_publisher.hpp +253 -0
  84. package/examples/bridge/mesh_topology_reporter.hpp +303 -0
  85. package/examples/bridge/mqtt_command_bridge.hpp +459 -0
  86. package/examples/bridge/mqtt_status_bridge.hpp +519 -0
  87. package/examples/bridge/platformio.ini +25 -25
  88. package/examples/echoNode/echoNode.ino +33 -33
  89. package/examples/echoNode/platformio.ini +25 -25
  90. package/examples/logClient/logClient.ino +109 -109
  91. package/examples/logClient/platformio.ini +25 -25
  92. package/examples/logServer/logServer.ino +81 -81
  93. package/examples/logServer/platformio.ini +25 -25
  94. package/examples/meshCommandNode/alteriom_sensor_package.hpp +235 -0
  95. package/examples/meshCommandNode/meshCommandNode.ino +263 -0
  96. package/examples/meshCommandNode/platformio.ini +25 -0
  97. package/examples/mqttBridge/mqttBridge.ino +118 -118
  98. package/examples/mqttBridge/platformio.ini +26 -26
  99. package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +235 -0
  100. package/examples/mqttCommandBridge/mesh_event_publisher.hpp +253 -0
  101. package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +303 -0
  102. package/examples/mqttCommandBridge/mqttCommandBridge.ino +252 -0
  103. package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +459 -0
  104. package/examples/mqttCommandBridge/platformio.ini +26 -0
  105. package/examples/mqttStatusBridge/mqttStatusBridge.ino +216 -0
  106. package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +522 -0
  107. package/examples/mqttStatusBridge/platformio.ini +26 -0
  108. package/examples/mqttTopologyTest/README.md +467 -0
  109. package/examples/mqttTopologyTest/mqttTopologyTest.ino +748 -0
  110. package/examples/mqttTopologyTest/platformio.ini +26 -0
  111. package/examples/namedMesh/namedMesh.ino +97 -97
  112. package/examples/namedMesh/platformio.ini +25 -25
  113. package/examples/otaReceiver/otaReceiver.ino +79 -79
  114. package/examples/otaReceiver/platformio.ini +25 -25
  115. package/examples/otaSender/otaSender.ino +160 -151
  116. package/examples/otaSender/platformio.ini +25 -25
  117. package/examples/startHere/platformio.ini +25 -25
  118. package/examples/startHere/startHere.ino +159 -159
  119. package/examples/webServer/platformio.ini +27 -27
  120. package/examples/webServer/webServer.ino +89 -89
  121. package/keywords.txt +48 -48
  122. package/library.json +55 -34
  123. package/library.properties +10 -10
  124. package/package.json +86 -78
  125. package/src/AlteriomPainlessMesh.h +97 -97
  126. package/src/arduino/wifi.hpp +365 -365
  127. package/src/boost/asynctcp.hpp +279 -279
  128. package/src/painlessMesh.h +70 -70
  129. package/src/painlessMeshSTA.cpp +236 -236
  130. package/src/painlessMeshSTA.h +58 -58
  131. package/src/painlessTaskOptions.h +4 -4
  132. package/src/painlessmesh/base64.hpp +111 -111
  133. package/src/painlessmesh/buffer.hpp +229 -229
  134. package/src/painlessmesh/callback.hpp +91 -91
  135. package/src/painlessmesh/configuration.hpp +77 -77
  136. package/src/painlessmesh/connection.hpp +192 -192
  137. package/src/painlessmesh/layout.hpp +188 -188
  138. package/src/painlessmesh/logger.hpp +158 -158
  139. package/src/painlessmesh/memory.hpp +119 -119
  140. package/src/painlessmesh/mesh.hpp +761 -560
  141. package/src/painlessmesh/metrics.hpp +322 -322
  142. package/src/painlessmesh/ntp.hpp +263 -263
  143. package/src/painlessmesh/ota.hpp +582 -553
  144. package/src/painlessmesh/plugin.hpp +188 -188
  145. package/src/painlessmesh/protocol.hpp +813 -813
  146. package/src/painlessmesh/router.hpp +338 -322
  147. package/src/painlessmesh/tcp.hpp +71 -71
  148. package/src/painlessmesh/validation.hpp +238 -238
  149. package/src/plugin/performance.hpp +214 -214
  150. package/src/plugin/remote.hpp +64 -64
  151. package/src/scheduler.cpp +10 -10
  152. package/src/wifi.cpp +2 -2
@@ -1,279 +1,279 @@
1
- #ifndef _BOOST_ASYNCTCP_HPP_
2
- #define _BOOST_ASYNCTCP_HPP_
3
-
4
- #include <boost/array.hpp>
5
- #include <boost/asio.hpp>
6
- #include <iostream>
7
-
8
- #ifndef TCP_MSS
9
- #define TCP_MSS 1024
10
- #endif
11
-
12
- using boost::asio::ip::tcp;
13
-
14
- #define ASYNC_WRITE_FLAG_COPY 0x01
15
-
16
- class AsyncClient;
17
-
18
- typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
19
- typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)>
20
- AcAckHandler;
21
- typedef std::function<void(void*, AsyncClient*, int8_t error)> AcErrorHandler;
22
- typedef std::function<void(void*, AsyncClient*, void* data, size_t len)>
23
- AcDataHandler;
24
- // typedef std::function<void(void*, AsyncClient*, struct pbuf* pb)>
25
- // AcPacketHandler;
26
- typedef std::function<void(void*, AsyncClient*, uint32_t time)>
27
- AcTimeoutHandler;
28
-
29
- typedef boost::asio::ip::address IPAddress;
30
-
31
- class AsyncClient {
32
- public:
33
- AsyncClient(boost::asio::io_context& io_service)
34
- : _io_service(io_service), mSocket(_io_service) {}
35
-
36
- bool connect(IPAddress ipaddress, uint16_t port) {
37
- namespace ip = boost::asio::ip;
38
- auto endpoint = ip::tcp::endpoint(ipaddress, port);
39
-
40
- mSocket.async_connect(endpoint, [&](auto& ec) { this->handleConnect(ec); });
41
- return true;
42
- }
43
-
44
- void initRead() {
45
- mSocket.async_read_some(
46
- boost::asio::buffer(mInputBuffer, TCP_MSS),
47
- [&](auto& ec, auto len) { this->handleData(ec, len); });
48
- }
49
-
50
- size_t write(const void* data, size_t len,
51
- size_t copy = ASYNC_WRITE_FLAG_COPY) {
52
- if (writing) return 0;
53
- writing = true;
54
- if (copy == ASYNC_WRITE_FLAG_COPY) {
55
- memcpy(mWriteBuffer, data, len);
56
- mSocket.async_send(
57
- boost::asio::buffer(mWriteBuffer, len),
58
- [&](auto& ec, auto len) { this->handleWrite(ec, len); });
59
- } else {
60
- mSocket.async_send(
61
- boost::asio::buffer(data, len),
62
- [&](auto& ec, auto len) { this->handleWrite(ec, len); });
63
- }
64
- return len;
65
- }
66
-
67
- // Dummy functions for compatibility with ESPAsycnTCP
68
- void send() {}
69
- void setNoDelay(bool value = true) {}
70
- void setRxTimeout(uint32_t timeout) {}
71
- const char* errorToString(int8_t error) { return ""; }
72
-
73
- // TODO: check if there is a better one
74
- void abort() { this->close(true); }
75
-
76
- void onConnect(AcConnectHandler cb, void* arg = 0) {
77
- _connect_cb = cb;
78
- _connect_cb_arg = arg;
79
- }
80
-
81
- void onDisconnect(AcConnectHandler cb, void* arg = 0) {
82
- _discard_cb = cb;
83
- _discard_cb_arg = arg;
84
- }
85
-
86
- void onAck(AcAckHandler cb, void* arg = 0) {
87
- _sent_cb = cb;
88
- _sent_cb_arg = arg;
89
- }
90
-
91
- void onError(AcErrorHandler cb, void* arg = 0) {
92
- _error_cb = cb;
93
- _error_cb_arg = arg;
94
- }
95
-
96
- void onData(AcDataHandler cb, void* arg = 0) {
97
- _recv_cb = cb;
98
- _recv_cb_arg = arg;
99
- }
100
-
101
- void onTimeout(AcTimeoutHandler cb, void* arg = 0) {
102
- _timeout_cb = cb;
103
- _timeout_cb_arg = arg;
104
- }
105
-
106
- void onPoll(AcConnectHandler cb, void* arg = 0) {
107
- _poll_cb = cb;
108
- _poll_cb_arg = arg;
109
- }
110
-
111
- bool connected() { return mSocket.is_open(); }
112
-
113
- bool freeable() { return !this->connected(); }
114
-
115
- void close(bool now = true) {
116
- if (this->connected()) {
117
- mSocket.close();
118
- }
119
- if (!disconnectCalled) {
120
- disconnectCalled = true;
121
- if (_discard_cb) {
122
- _discard_cb(_discard_cb_arg, this);
123
- }
124
- }
125
- }
126
-
127
- ~AsyncClient() { close(true); }
128
-
129
- size_t space() {
130
- // This could be more intelligent, but simple and safe for now
131
- if (writing) return 0;
132
- return TCP_MSS;
133
- }
134
-
135
- bool canSend() { return this->space() > 0; }
136
-
137
- size_t ack(size_t len) {
138
- // Currently assumes that len is actually the size of the data that was sent
139
- // Otherwise it will break
140
- initRead();
141
- return len;
142
- }
143
-
144
- tcp::socket& socket() { return mSocket; }
145
-
146
- protected:
147
- boost::asio::io_context& _io_service;
148
- tcp::socket mSocket;
149
-
150
- char mInputBuffer[TCP_MSS];
151
- char mWriteBuffer[TCP_MSS];
152
- bool writing = false;
153
-
154
- bool disconnectCalled = false;
155
-
156
- AcConnectHandler _connect_cb = 0;
157
- void* _connect_cb_arg = 0;
158
- AcConnectHandler _discard_cb = 0;
159
- void* _discard_cb_arg = 0;
160
- AcAckHandler _sent_cb = 0;
161
- void* _sent_cb_arg = 0;
162
- AcErrorHandler _error_cb = 0;
163
- void* _error_cb_arg = 0;
164
- AcDataHandler _recv_cb = 0;
165
- void* _recv_cb_arg = 0;
166
- AcTimeoutHandler _timeout_cb = 0;
167
- void* _timeout_cb_arg = 0;
168
- AcConnectHandler _poll_cb = 0;
169
- void* _poll_cb_arg = 0;
170
-
171
- void handleConnect(const boost::system::error_code& ec) {
172
- if (!ec) {
173
- if (_connect_cb) _connect_cb(_connect_cb_arg, this);
174
-
175
- initRead();
176
- } else {
177
- handleError(ec);
178
- if (this->connected()) close(true);
179
- }
180
- }
181
-
182
- void handleData(const boost::system::error_code& ec, size_t len) {
183
- if (disconnectCalled) return;
184
-
185
- if (!ec) {
186
- if (_recv_cb) {
187
- _recv_cb(_recv_cb_arg, this, (void*)mInputBuffer, len);
188
- }
189
- } else {
190
- handleError(ec);
191
- close(true);
192
- }
193
- }
194
-
195
- void handleWrite(const boost::system::error_code& ec, size_t len) {
196
- if (disconnectCalled) return;
197
-
198
- if (!ec) {
199
- if (_sent_cb) {
200
- // TODO send actual time
201
- _sent_cb(_sent_cb_arg, this, len, 0);
202
- }
203
- writing = false;
204
- } else {
205
- handleError(ec);
206
- close(true);
207
- }
208
- }
209
-
210
- void handleError(const boost::system::error_code& ec) {
211
- if (ec != boost::asio::error::eof && _error_cb) {
212
- _error_cb(_error_cb_arg, this, ec.value());
213
- }
214
- }
215
- };
216
-
217
- class AsyncServer {
218
- public:
219
- AsyncServer(boost::asio::io_context& io_service, uint16_t port)
220
- : _io_service(io_service),
221
- // mSocket(io_service),
222
- _port(port),
223
- mAcceptor(io_service) {}
224
-
225
- ~AsyncServer() { this->end(); }
226
-
227
- void onClient(AcConnectHandler cb, void* arg = 0) {
228
- _connect_cb = cb;
229
- _connect_cb_arg = arg;
230
- }
231
-
232
- // begin() should do start_accept (see server2):w
233
- void begin() {
234
- mAcceptor.open(tcp::v4());
235
- int one = 1;
236
- setsockopt(mAcceptor.native_handle(), SOL_SOCKET,
237
- SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one));
238
- boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), _port);
239
- mAcceptor.set_option(boost::asio::socket_base::reuse_address(true));
240
- mAcceptor.set_option(boost::asio::ip::tcp::no_delay(true));
241
- mAcceptor.set_option(boost::asio::socket_base::send_buffer_size(65536));
242
- mAcceptor.set_option(boost::asio::socket_base::receive_buffer_size(65536));
243
- mAcceptor.bind(endpoint);
244
- mAcceptor.listen();
245
- initAccept();
246
- }
247
-
248
- // Acceptor stop?
249
- void end() { mAcceptor.close(); }
250
-
251
- // Dummy function for compatibility with ESPAsycnTCP
252
- void setNoDelay(bool value = true) {}
253
-
254
- protected:
255
- boost::asio::io_context& _io_service;
256
- uint16_t _port;
257
- tcp::acceptor mAcceptor;
258
- AcConnectHandler _connect_cb = 0;
259
- void* _connect_cb_arg = 0;
260
-
261
- void initAccept() {
262
- #if BOOST_VERSION >= 107000
263
- AsyncClient* client = new AsyncClient(_io_service);
264
- #else
265
- AsyncClient* client = new AsyncClient(mAcceptor.get_io_service());
266
- #endif
267
- mAcceptor.async_accept(
268
- client->socket(), [this, client](const boost::system::error_code& e) {
269
- if (!e && this->_connect_cb) {
270
- this->_connect_cb(this->_connect_cb_arg, client);
271
- this->initAccept();
272
- client->initRead();
273
- } else
274
- std::cout << "Error: " << e.message() << std::endl;
275
- });
276
- }
277
- };
278
-
279
- #endif
1
+ #ifndef _BOOST_ASYNCTCP_HPP_
2
+ #define _BOOST_ASYNCTCP_HPP_
3
+
4
+ #include <boost/array.hpp>
5
+ #include <boost/asio.hpp>
6
+ #include <iostream>
7
+
8
+ #ifndef TCP_MSS
9
+ #define TCP_MSS 1024
10
+ #endif
11
+
12
+ using boost::asio::ip::tcp;
13
+
14
+ #define ASYNC_WRITE_FLAG_COPY 0x01
15
+
16
+ class AsyncClient;
17
+
18
+ typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
19
+ typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)>
20
+ AcAckHandler;
21
+ typedef std::function<void(void*, AsyncClient*, int8_t error)> AcErrorHandler;
22
+ typedef std::function<void(void*, AsyncClient*, void* data, size_t len)>
23
+ AcDataHandler;
24
+ // typedef std::function<void(void*, AsyncClient*, struct pbuf* pb)>
25
+ // AcPacketHandler;
26
+ typedef std::function<void(void*, AsyncClient*, uint32_t time)>
27
+ AcTimeoutHandler;
28
+
29
+ typedef boost::asio::ip::address IPAddress;
30
+
31
+ class AsyncClient {
32
+ public:
33
+ AsyncClient(boost::asio::io_context& io_service)
34
+ : _io_service(io_service), mSocket(_io_service) {}
35
+
36
+ bool connect(IPAddress ipaddress, uint16_t port) {
37
+ namespace ip = boost::asio::ip;
38
+ auto endpoint = ip::tcp::endpoint(ipaddress, port);
39
+
40
+ mSocket.async_connect(endpoint, [&](auto& ec) { this->handleConnect(ec); });
41
+ return true;
42
+ }
43
+
44
+ void initRead() {
45
+ mSocket.async_read_some(
46
+ boost::asio::buffer(mInputBuffer, TCP_MSS),
47
+ [&](auto& ec, auto len) { this->handleData(ec, len); });
48
+ }
49
+
50
+ size_t write(const void* data, size_t len,
51
+ size_t copy = ASYNC_WRITE_FLAG_COPY) {
52
+ if (writing) return 0;
53
+ writing = true;
54
+ if (copy == ASYNC_WRITE_FLAG_COPY) {
55
+ memcpy(mWriteBuffer, data, len);
56
+ mSocket.async_send(
57
+ boost::asio::buffer(mWriteBuffer, len),
58
+ [&](auto& ec, auto len) { this->handleWrite(ec, len); });
59
+ } else {
60
+ mSocket.async_send(
61
+ boost::asio::buffer(data, len),
62
+ [&](auto& ec, auto len) { this->handleWrite(ec, len); });
63
+ }
64
+ return len;
65
+ }
66
+
67
+ // Dummy functions for compatibility with ESPAsycnTCP
68
+ void send() {}
69
+ void setNoDelay(bool value = true) {}
70
+ void setRxTimeout(uint32_t timeout) {}
71
+ const char* errorToString(int8_t error) { return ""; }
72
+
73
+ // TODO: check if there is a better one
74
+ void abort() { this->close(true); }
75
+
76
+ void onConnect(AcConnectHandler cb, void* arg = 0) {
77
+ _connect_cb = cb;
78
+ _connect_cb_arg = arg;
79
+ }
80
+
81
+ void onDisconnect(AcConnectHandler cb, void* arg = 0) {
82
+ _discard_cb = cb;
83
+ _discard_cb_arg = arg;
84
+ }
85
+
86
+ void onAck(AcAckHandler cb, void* arg = 0) {
87
+ _sent_cb = cb;
88
+ _sent_cb_arg = arg;
89
+ }
90
+
91
+ void onError(AcErrorHandler cb, void* arg = 0) {
92
+ _error_cb = cb;
93
+ _error_cb_arg = arg;
94
+ }
95
+
96
+ void onData(AcDataHandler cb, void* arg = 0) {
97
+ _recv_cb = cb;
98
+ _recv_cb_arg = arg;
99
+ }
100
+
101
+ void onTimeout(AcTimeoutHandler cb, void* arg = 0) {
102
+ _timeout_cb = cb;
103
+ _timeout_cb_arg = arg;
104
+ }
105
+
106
+ void onPoll(AcConnectHandler cb, void* arg = 0) {
107
+ _poll_cb = cb;
108
+ _poll_cb_arg = arg;
109
+ }
110
+
111
+ bool connected() { return mSocket.is_open(); }
112
+
113
+ bool freeable() { return !this->connected(); }
114
+
115
+ void close(bool now = true) {
116
+ if (this->connected()) {
117
+ mSocket.close();
118
+ }
119
+ if (!disconnectCalled) {
120
+ disconnectCalled = true;
121
+ if (_discard_cb) {
122
+ _discard_cb(_discard_cb_arg, this);
123
+ }
124
+ }
125
+ }
126
+
127
+ ~AsyncClient() { close(true); }
128
+
129
+ size_t space() {
130
+ // This could be more intelligent, but simple and safe for now
131
+ if (writing) return 0;
132
+ return TCP_MSS;
133
+ }
134
+
135
+ bool canSend() { return this->space() > 0; }
136
+
137
+ size_t ack(size_t len) {
138
+ // Currently assumes that len is actually the size of the data that was sent
139
+ // Otherwise it will break
140
+ initRead();
141
+ return len;
142
+ }
143
+
144
+ tcp::socket& socket() { return mSocket; }
145
+
146
+ protected:
147
+ boost::asio::io_context& _io_service;
148
+ tcp::socket mSocket;
149
+
150
+ char mInputBuffer[TCP_MSS];
151
+ char mWriteBuffer[TCP_MSS];
152
+ bool writing = false;
153
+
154
+ bool disconnectCalled = false;
155
+
156
+ AcConnectHandler _connect_cb = 0;
157
+ void* _connect_cb_arg = 0;
158
+ AcConnectHandler _discard_cb = 0;
159
+ void* _discard_cb_arg = 0;
160
+ AcAckHandler _sent_cb = 0;
161
+ void* _sent_cb_arg = 0;
162
+ AcErrorHandler _error_cb = 0;
163
+ void* _error_cb_arg = 0;
164
+ AcDataHandler _recv_cb = 0;
165
+ void* _recv_cb_arg = 0;
166
+ AcTimeoutHandler _timeout_cb = 0;
167
+ void* _timeout_cb_arg = 0;
168
+ AcConnectHandler _poll_cb = 0;
169
+ void* _poll_cb_arg = 0;
170
+
171
+ void handleConnect(const boost::system::error_code& ec) {
172
+ if (!ec) {
173
+ if (_connect_cb) _connect_cb(_connect_cb_arg, this);
174
+
175
+ initRead();
176
+ } else {
177
+ handleError(ec);
178
+ if (this->connected()) close(true);
179
+ }
180
+ }
181
+
182
+ void handleData(const boost::system::error_code& ec, size_t len) {
183
+ if (disconnectCalled) return;
184
+
185
+ if (!ec) {
186
+ if (_recv_cb) {
187
+ _recv_cb(_recv_cb_arg, this, (void*)mInputBuffer, len);
188
+ }
189
+ } else {
190
+ handleError(ec);
191
+ close(true);
192
+ }
193
+ }
194
+
195
+ void handleWrite(const boost::system::error_code& ec, size_t len) {
196
+ if (disconnectCalled) return;
197
+
198
+ if (!ec) {
199
+ if (_sent_cb) {
200
+ // TODO send actual time
201
+ _sent_cb(_sent_cb_arg, this, len, 0);
202
+ }
203
+ writing = false;
204
+ } else {
205
+ handleError(ec);
206
+ close(true);
207
+ }
208
+ }
209
+
210
+ void handleError(const boost::system::error_code& ec) {
211
+ if (ec != boost::asio::error::eof && _error_cb) {
212
+ _error_cb(_error_cb_arg, this, ec.value());
213
+ }
214
+ }
215
+ };
216
+
217
+ class AsyncServer {
218
+ public:
219
+ AsyncServer(boost::asio::io_context& io_service, uint16_t port)
220
+ : _io_service(io_service),
221
+ // mSocket(io_service),
222
+ _port(port),
223
+ mAcceptor(io_service) {}
224
+
225
+ ~AsyncServer() { this->end(); }
226
+
227
+ void onClient(AcConnectHandler cb, void* arg = 0) {
228
+ _connect_cb = cb;
229
+ _connect_cb_arg = arg;
230
+ }
231
+
232
+ // begin() should do start_accept (see server2):w
233
+ void begin() {
234
+ mAcceptor.open(tcp::v4());
235
+ int one = 1;
236
+ setsockopt(mAcceptor.native_handle(), SOL_SOCKET,
237
+ SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one));
238
+ boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), _port);
239
+ mAcceptor.set_option(boost::asio::socket_base::reuse_address(true));
240
+ mAcceptor.set_option(boost::asio::ip::tcp::no_delay(true));
241
+ mAcceptor.set_option(boost::asio::socket_base::send_buffer_size(65536));
242
+ mAcceptor.set_option(boost::asio::socket_base::receive_buffer_size(65536));
243
+ mAcceptor.bind(endpoint);
244
+ mAcceptor.listen();
245
+ initAccept();
246
+ }
247
+
248
+ // Acceptor stop?
249
+ void end() { mAcceptor.close(); }
250
+
251
+ // Dummy function for compatibility with ESPAsycnTCP
252
+ void setNoDelay(bool value = true) {}
253
+
254
+ protected:
255
+ boost::asio::io_context& _io_service;
256
+ uint16_t _port;
257
+ tcp::acceptor mAcceptor;
258
+ AcConnectHandler _connect_cb = 0;
259
+ void* _connect_cb_arg = 0;
260
+
261
+ void initAccept() {
262
+ #if BOOST_VERSION >= 107000
263
+ AsyncClient* client = new AsyncClient(_io_service);
264
+ #else
265
+ AsyncClient* client = new AsyncClient(mAcceptor.get_io_service());
266
+ #endif
267
+ mAcceptor.async_accept(
268
+ client->socket(), [this, client](const boost::system::error_code& e) {
269
+ if (!e && this->_connect_cb) {
270
+ this->_connect_cb(this->_connect_cb_arg, client);
271
+ this->initAccept();
272
+ client->initRead();
273
+ } else
274
+ std::cout << "Error: " << e.message() << std::endl;
275
+ });
276
+ }
277
+ };
278
+
279
+ #endif