Skip to content

Commit 0592be6

Browse files
committed
Remove private callbacks from public scope
Use a friend class to ensure that private callbacks are not exposed to client code.
1 parent 7828031 commit 0592be6

File tree

2 files changed

+61
-109
lines changed

2 files changed

+61
-109
lines changed

src/AsyncTCP.cpp

Lines changed: 57 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,20 @@ typedef struct {
111111
};
112112
} lwip_tcp_event_packet_t;
113113

114+
// Detail class for interacting with AsyncClient internals, but without exposing the API
115+
class AsyncTCP_detail {
116+
public:
117+
// Helper functions
118+
static void __attribute__((visibility("internal"))) handle_async_event(lwip_tcp_event_packet_t *event);
119+
120+
// LwIP TCP event callbacks that (will) require privileged access
121+
static int8_t __attribute__((visibility("internal"))) tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err);
122+
static int8_t __attribute__((visibility("internal"))) tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len);
123+
static void __attribute__((visibility("internal"))) tcp_error(void *arg, int8_t err);
124+
static int8_t __attribute__((visibility("internal"))) tcp_poll(void *arg, struct tcp_pcb *pcb);
125+
static int8_t __attribute__((visibility("internal"))) tcp_accept(void *arg, tcp_pcb *pcb, int8_t err);
126+
};
127+
114128
static QueueHandle_t _async_queue = NULL;
115129
static TaskHandle_t _async_service_task_handle = NULL;
116130

@@ -257,36 +271,36 @@ static bool _remove_events_with_arg(void *arg) {
257271
return true;
258272
}
259273

260-
static void _handle_async_event(lwip_tcp_event_packet_t *e) {
274+
void AsyncTCP_detail::handle_async_event(lwip_tcp_event_packet_t *e) {
261275
if (e->arg == NULL) {
262276
// do nothing when arg is NULL
263277
// ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb);
264278
} else if (e->event == LWIP_TCP_CLEAR) {
265279
_remove_events_with_arg(e->arg);
266280
} else if (e->event == LWIP_TCP_RECV) {
267281
// ets_printf("-R: 0x%08x\n", e->recv.pcb);
268-
AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err);
282+
reinterpret_cast<AsyncClient *>(e->arg)->_recv(e->recv.pcb, e->recv.pb, e->recv.err);
269283
} else if (e->event == LWIP_TCP_FIN) {
270284
// ets_printf("-F: 0x%08x\n", e->fin.pcb);
271-
AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err);
285+
reinterpret_cast<AsyncClient *>(e->arg)->_fin(e->fin.pcb, e->fin.err);
272286
} else if (e->event == LWIP_TCP_SENT) {
273287
// ets_printf("-S: 0x%08x\n", e->sent.pcb);
274-
AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len);
288+
reinterpret_cast<AsyncClient *>(e->arg)->_sent(e->sent.pcb, e->sent.len);
275289
} else if (e->event == LWIP_TCP_POLL) {
276290
// ets_printf("-P: 0x%08x\n", e->poll.pcb);
277-
AsyncClient::_s_poll(e->arg, e->poll.pcb);
291+
reinterpret_cast<AsyncClient *>(e->arg)->_poll(e->poll.pcb);
278292
} else if (e->event == LWIP_TCP_ERROR) {
279293
// ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err);
280-
AsyncClient::_s_error(e->arg, e->error.err);
294+
reinterpret_cast<AsyncClient *>(e->arg)->_error(e->error.err);
281295
} else if (e->event == LWIP_TCP_CONNECTED) {
282296
// ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err);
283-
AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err);
297+
reinterpret_cast<AsyncClient *>(e->arg)->_connected(e->connected.pcb, e->connected.err);
284298
} else if (e->event == LWIP_TCP_ACCEPT) {
285299
// ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client);
286-
AsyncServer::_s_accepted(e->arg, e->accept.client);
300+
reinterpret_cast<AsyncServer *>(e->arg)->_accepted(e->accept.client);
287301
} else if (e->event == LWIP_TCP_DNS) {
288302
// ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr));
289-
AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg);
303+
reinterpret_cast<AsyncClient *>(e->arg)->_dns_found(&e->dns.addr);
290304
}
291305
free((void *)(e));
292306
}
@@ -300,7 +314,7 @@ static void _async_service_task(void *pvParameters) {
300314
lwip_tcp_event_packet_t *packet = NULL;
301315
for (;;) {
302316
if (_get_async_event(&packet)) {
303-
_handle_async_event(packet);
317+
AsyncTCP_detail::handle_async_event(packet);
304318
}
305319
#if CONFIG_ASYNC_TCP_USE_WDT
306320
esp_task_wdt_reset();
@@ -388,7 +402,7 @@ static int8_t _tcp_connected(void *arg, tcp_pcb *pcb, int8_t err) {
388402
return ERR_OK;
389403
}
390404

391-
static int8_t _tcp_poll(void *arg, struct tcp_pcb *pcb) {
405+
int8_t AsyncTCP_detail::tcp_poll(void *arg, struct tcp_pcb *pcb) {
392406
// throttle polling events queueing when event queue is getting filled up, let it handle _onack's
393407
// log_d("qs:%u", uxQueueMessagesWaiting(_async_queue));
394408
if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4)) {
@@ -413,7 +427,7 @@ static int8_t _tcp_poll(void *arg, struct tcp_pcb *pcb) {
413427
return ERR_OK;
414428
}
415429

416-
static int8_t _tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err) {
430+
int8_t AsyncTCP_detail::tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err) {
417431
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
418432
if (!e) {
419433
log_e("Failed to allocate event packet");
@@ -432,7 +446,7 @@ static int8_t _tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t
432446
e->fin.pcb = pcb;
433447
e->fin.err = err;
434448
// close the PCB in LwIP thread
435-
AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err);
449+
reinterpret_cast<AsyncClient *>(arg)->_lwip_fin(e->fin.pcb, e->fin.err);
436450
}
437451
if (!_send_async_event(&e)) {
438452
free((void *)(e));
@@ -441,7 +455,7 @@ static int8_t _tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t
441455
return ERR_OK;
442456
}
443457

444-
static int8_t _tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
458+
int8_t AsyncTCP_detail::tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
445459
// ets_printf("+S: 0x%08x\n", pcb);
446460
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
447461
if (!e) {
@@ -459,16 +473,16 @@ static int8_t _tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
459473
return ERR_OK;
460474
}
461475

462-
void AsyncClient::_tcp_error(void *arg, int8_t err) {
476+
void AsyncTCP_detail::tcp_error(void *arg, int8_t err) {
463477
// ets_printf("+E: 0x%08x\n", arg);
464478
AsyncClient *client = reinterpret_cast<AsyncClient *>(arg);
465479
if (client && client->_pcb) {
466480
tcp_arg(client->_pcb, NULL);
467481
if (client->_pcb->state == LISTEN) {
468-
tcp_sent(client->_pcb, NULL);
469-
tcp_recv(client->_pcb, NULL);
470-
tcp_err(client->_pcb, NULL);
471-
tcp_poll(client->_pcb, NULL, 0);
482+
::tcp_sent(client->_pcb, NULL);
483+
::tcp_recv(client->_pcb, NULL);
484+
::tcp_err(client->_pcb, NULL);
485+
::tcp_poll(client->_pcb, NULL, 0);
472486
}
473487
client->_pcb = nullptr;
474488
client->_free_closed_slot();
@@ -508,23 +522,6 @@ static void _tcp_dns_found(const char *name, struct ip_addr *ipaddr, void *arg)
508522
}
509523
}
510524

511-
// Used to switch out from LwIP thread
512-
static int8_t _tcp_accept(void *arg, AsyncClient *client) {
513-
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
514-
if (!e) {
515-
log_e("Failed to allocate event packet");
516-
return ERR_MEM;
517-
}
518-
e->event = LWIP_TCP_ACCEPT;
519-
e->arg = arg;
520-
e->accept.client = client;
521-
if (!_prepend_async_event(&e)) {
522-
free((void *)(e));
523-
return ERR_TIMEOUT;
524-
}
525-
return ERR_OK;
526-
}
527-
528525
/*
529526
* TCP/IP API Calls
530527
* */
@@ -734,10 +731,10 @@ AsyncClient::AsyncClient(tcp_pcb *pcb)
734731
if (_pcb) {
735732
_rx_last_packet = millis();
736733
tcp_arg(_pcb, this);
737-
tcp_recv(_pcb, &_tcp_recv);
738-
tcp_sent(_pcb, &_tcp_sent);
739-
tcp_err(_pcb, &_tcp_error);
740-
tcp_poll(_pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
734+
tcp_recv(_pcb, &AsyncTCP_detail::tcp_recv);
735+
tcp_sent(_pcb, &AsyncTCP_detail::tcp_sent);
736+
tcp_err(_pcb, &AsyncTCP_detail::tcp_error);
737+
tcp_poll(_pcb, &AsyncTCP_detail::tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
741738
if (!_allocate_closed_slot()) {
742739
_close();
743740
}
@@ -831,10 +828,10 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) {
831828
return false;
832829
}
833830
tcp_arg(pcb, this);
834-
tcp_err(pcb, &_tcp_error);
835-
tcp_recv(pcb, &_tcp_recv);
836-
tcp_sent(pcb, &_tcp_sent);
837-
tcp_poll(pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
831+
tcp_err(pcb, &AsyncTCP_detail::tcp_error);
832+
tcp_recv(pcb, &AsyncTCP_detail::tcp_recv);
833+
tcp_sent(pcb, &AsyncTCP_detail::tcp_sent);
834+
tcp_poll(pcb, &AsyncTCP_detail::tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
838835
}
839836

840837
esp_err_t err = _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected);
@@ -1455,42 +1452,6 @@ const char *AsyncClient::stateToString() const {
14551452
}
14561453
}
14571454

1458-
/*
1459-
* Static Callbacks (LwIP C2C++ interconnect)
1460-
* */
1461-
1462-
void AsyncClient::_s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg) {
1463-
reinterpret_cast<AsyncClient *>(arg)->_dns_found(ipaddr);
1464-
}
1465-
1466-
int8_t AsyncClient::_s_poll(void *arg, struct tcp_pcb *pcb) {
1467-
return reinterpret_cast<AsyncClient *>(arg)->_poll(pcb);
1468-
}
1469-
1470-
int8_t AsyncClient::_s_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err) {
1471-
return reinterpret_cast<AsyncClient *>(arg)->_recv(pcb, pb, err);
1472-
}
1473-
1474-
int8_t AsyncClient::_s_fin(void *arg, struct tcp_pcb *pcb, int8_t err) {
1475-
return reinterpret_cast<AsyncClient *>(arg)->_fin(pcb, err);
1476-
}
1477-
1478-
int8_t AsyncClient::_s_lwip_fin(void *arg, struct tcp_pcb *pcb, int8_t err) {
1479-
return reinterpret_cast<AsyncClient *>(arg)->_lwip_fin(pcb, err);
1480-
}
1481-
1482-
int8_t AsyncClient::_s_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
1483-
return reinterpret_cast<AsyncClient *>(arg)->_sent(pcb, len);
1484-
}
1485-
1486-
void AsyncClient::_s_error(void *arg, int8_t err) {
1487-
reinterpret_cast<AsyncClient *>(arg)->_error(err);
1488-
}
1489-
1490-
int8_t AsyncClient::_s_connected(void *arg, struct tcp_pcb *pcb, int8_t err) {
1491-
return reinterpret_cast<AsyncClient *>(arg)->_connected(pcb, err);
1492-
}
1493-
14941455
/*
14951456
Async TCP Server
14961457
*/
@@ -1580,7 +1541,7 @@ void AsyncServer::begin() {
15801541
}
15811542
tcp_core_guard tcg;
15821543
tcp_arg(_pcb, (void *)this);
1583-
tcp_accept(_pcb, &_s_accept);
1544+
tcp_accept(_pcb, &AsyncTCP_detail::tcp_accept);
15841545
}
15851546

15861547
void AsyncServer::end() {
@@ -1596,18 +1557,28 @@ void AsyncServer::end() {
15961557
}
15971558

15981559
// runs on LwIP thread
1599-
int8_t AsyncServer::_accept(tcp_pcb *pcb, int8_t err) {
1560+
int8_t AsyncTCP_detail::tcp_accept(void *arg, tcp_pcb *pcb, int8_t err) {
16001561
if (!pcb) {
16011562
log_e("_accept failed: pcb is NULL");
16021563
return ERR_ABRT;
16031564
}
1604-
if (_connect_cb) {
1565+
auto server = reinterpret_cast<AsyncServer *>(arg);
1566+
if (server->_connect_cb) {
16051567
AsyncClient *c = new (std::nothrow) AsyncClient(pcb);
16061568
if (c && c->pcb()) {
1607-
c->setNoDelay(_noDelay);
1608-
if (_tcp_accept(this, c) == ERR_OK) {
1609-
return ERR_OK; // success
1569+
c->setNoDelay(server->_noDelay);
1570+
1571+
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
1572+
if (e) {
1573+
e->event = LWIP_TCP_ACCEPT;
1574+
e->arg = arg;
1575+
e->accept.client = c;
1576+
if (_prepend_async_event(&e)) {
1577+
return ERR_OK; // success
1578+
}
1579+
free((void *)(e));
16101580
}
1581+
16111582
// Couldn't allocate accept event
16121583
// We can't let the client object call in to close, as we're on the LWIP thread; it could deadlock trying to RPC to itself
16131584
c->_pcb = nullptr;
@@ -1652,11 +1623,3 @@ uint8_t AsyncServer::status() const {
16521623
}
16531624
return _pcb->state;
16541625
}
1655-
1656-
int8_t AsyncServer::_s_accept(void *arg, tcp_pcb *pcb, int8_t err) {
1657-
return reinterpret_cast<AsyncServer *>(arg)->_accept(pcb, err);
1658-
}
1659-
1660-
int8_t AsyncServer::_s_accepted(void *arg, AsyncClient *client) {
1661-
return reinterpret_cast<AsyncServer *>(arg)->_accepted(client);
1662-
}

src/AsyncTCP.h

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ typedef std::function<void(void *, AsyncClient *, uint32_t time)> AcTimeoutHandl
6969

7070
struct tcp_pcb;
7171
struct ip_addr;
72+
class AsyncTCP_detail;
7273

7374
class AsyncClient {
7475
public:
@@ -235,23 +236,13 @@ class AsyncClient {
235236
static const char *errorToString(int8_t error);
236237
const char *stateToString() const;
237238

238-
// internal callbacks - Do NOT call any of the functions below in user code!
239-
static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb);
240-
static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err);
241-
static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
242-
static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
243-
static void _s_error(void *arg, int8_t err);
244-
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
245-
static int8_t _s_connected(void *arg, struct tcp_pcb *tpcb, int8_t err);
246-
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
247-
static void _tcp_error(void *arg, int8_t err);
248-
249239
int8_t _recv(tcp_pcb *pcb, pbuf *pb, int8_t err);
250240
tcp_pcb *pcb() {
251241
return _pcb;
252242
}
253243

254244
protected:
245+
friend class AsyncTCP_detail;
255246
friend class AsyncServer;
256247

257248
bool _connect(ip_addr_t addr, uint16_t port);
@@ -312,11 +303,9 @@ class AsyncServer {
312303
bool getNoDelay() const;
313304
uint8_t status() const;
314305

315-
// Do not use any of the functions below!
316-
static int8_t _s_accept(void *arg, tcp_pcb *newpcb, int8_t err);
317-
static int8_t _s_accepted(void *arg, AsyncClient *client);
318-
319306
protected:
307+
friend class AsyncTCP_detail;
308+
320309
uint16_t _port;
321310
bool _bind4 = false;
322311
bool _bind6 = false;

0 commit comments

Comments
 (0)