Skip to content

Commit 2c8ad8b

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 5b43fe3 commit 2c8ad8b

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
@@ -126,6 +126,20 @@ typedef struct {
126126
};
127127
} lwip_tcp_event_packet_t;
128128

129+
// Detail class for interacting with AsyncClient internals, but without exposing the API
130+
class AsyncTCP_detail {
131+
public:
132+
// Helper functions
133+
static void __attribute__((visibility("internal"))) handle_async_event(lwip_tcp_event_packet_t *event);
134+
135+
// LwIP TCP event callbacks that (will) require privileged access
136+
static int8_t __attribute__((visibility("internal"))) tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err);
137+
static int8_t __attribute__((visibility("internal"))) tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len);
138+
static void __attribute__((visibility("internal"))) tcp_error(void *arg, int8_t err);
139+
static int8_t __attribute__((visibility("internal"))) tcp_poll(void *arg, struct tcp_pcb *pcb);
140+
static int8_t __attribute__((visibility("internal"))) tcp_accept(void *arg, tcp_pcb *pcb, int8_t err);
141+
};
142+
129143
static QueueHandle_t _async_queue = NULL;
130144
static TaskHandle_t _async_service_task_handle = NULL;
131145

@@ -272,36 +286,36 @@ static bool _remove_events_with_arg(void *arg) {
272286
return true;
273287
}
274288

275-
static void _handle_async_event(lwip_tcp_event_packet_t *e) {
289+
void AsyncTCP_detail::handle_async_event(lwip_tcp_event_packet_t *e) {
276290
if (e->arg == NULL) {
277291
// do nothing when arg is NULL
278292
// ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb);
279293
} else if (e->event == LWIP_TCP_CLEAR) {
280294
_remove_events_with_arg(e->arg);
281295
} else if (e->event == LWIP_TCP_RECV) {
282296
// ets_printf("-R: 0x%08x\n", e->recv.pcb);
283-
AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err);
297+
reinterpret_cast<AsyncClient *>(e->arg)->_recv(e->recv.pcb, e->recv.pb, e->recv.err);
284298
} else if (e->event == LWIP_TCP_FIN) {
285299
// ets_printf("-F: 0x%08x\n", e->fin.pcb);
286-
AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err);
300+
reinterpret_cast<AsyncClient *>(e->arg)->_fin(e->fin.pcb, e->fin.err);
287301
} else if (e->event == LWIP_TCP_SENT) {
288302
// ets_printf("-S: 0x%08x\n", e->sent.pcb);
289-
AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len);
303+
reinterpret_cast<AsyncClient *>(e->arg)->_sent(e->sent.pcb, e->sent.len);
290304
} else if (e->event == LWIP_TCP_POLL) {
291305
// ets_printf("-P: 0x%08x\n", e->poll.pcb);
292-
AsyncClient::_s_poll(e->arg, e->poll.pcb);
306+
reinterpret_cast<AsyncClient *>(e->arg)->_poll(e->poll.pcb);
293307
} else if (e->event == LWIP_TCP_ERROR) {
294308
// ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err);
295-
AsyncClient::_s_error(e->arg, e->error.err);
309+
reinterpret_cast<AsyncClient *>(e->arg)->_error(e->error.err);
296310
} else if (e->event == LWIP_TCP_CONNECTED) {
297311
// ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err);
298-
AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err);
312+
reinterpret_cast<AsyncClient *>(e->arg)->_connected(e->connected.pcb, e->connected.err);
299313
} else if (e->event == LWIP_TCP_ACCEPT) {
300314
// ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client);
301-
AsyncServer::_s_accepted(e->arg, e->accept.client);
315+
reinterpret_cast<AsyncServer *>(e->arg)->_accepted(e->accept.client);
302316
} else if (e->event == LWIP_TCP_DNS) {
303317
// ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr));
304-
AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg);
318+
reinterpret_cast<AsyncClient *>(e->arg)->_dns_found(&e->dns.addr);
305319
}
306320
free((void *)(e));
307321
}
@@ -315,7 +329,7 @@ static void _async_service_task(void *pvParameters) {
315329
lwip_tcp_event_packet_t *packet = NULL;
316330
for (;;) {
317331
if (_get_async_event(&packet)) {
318-
_handle_async_event(packet);
332+
AsyncTCP_detail::handle_async_event(packet);
319333
}
320334
#if CONFIG_ASYNC_TCP_USE_WDT
321335
esp_task_wdt_reset();
@@ -403,7 +417,7 @@ static int8_t _tcp_connected(void *arg, tcp_pcb *pcb, int8_t err) {
403417
return ERR_OK;
404418
}
405419

406-
static int8_t _tcp_poll(void *arg, struct tcp_pcb *pcb) {
420+
int8_t AsyncTCP_detail::tcp_poll(void *arg, struct tcp_pcb *pcb) {
407421
// throttle polling events queueing when event queue is getting filled up, let it handle _onack's
408422
// log_d("qs:%u", uxQueueMessagesWaiting(_async_queue));
409423
if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4)) {
@@ -428,7 +442,7 @@ static int8_t _tcp_poll(void *arg, struct tcp_pcb *pcb) {
428442
return ERR_OK;
429443
}
430444

431-
static int8_t _tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err) {
445+
int8_t AsyncTCP_detail::tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err) {
432446
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
433447
if (!e) {
434448
log_e("Failed to allocate event packet");
@@ -447,7 +461,7 @@ static int8_t _tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t
447461
e->fin.pcb = pcb;
448462
e->fin.err = err;
449463
// close the PCB in LwIP thread
450-
AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err);
464+
reinterpret_cast<AsyncClient *>(arg)->_lwip_fin(e->fin.pcb, e->fin.err);
451465
}
452466
if (!_send_async_event(&e)) {
453467
free((void *)(e));
@@ -456,7 +470,7 @@ static int8_t _tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t
456470
return ERR_OK;
457471
}
458472

459-
static int8_t _tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
473+
int8_t AsyncTCP_detail::tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
460474
// ets_printf("+S: 0x%08x\n", pcb);
461475
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
462476
if (!e) {
@@ -474,16 +488,16 @@ static int8_t _tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
474488
return ERR_OK;
475489
}
476490

477-
void AsyncClient::_tcp_error(void *arg, int8_t err) {
491+
void AsyncTCP_detail::tcp_error(void *arg, int8_t err) {
478492
// ets_printf("+E: 0x%08x\n", arg);
479493
AsyncClient *client = reinterpret_cast<AsyncClient *>(arg);
480494
if (client && client->_pcb) {
481495
tcp_arg(client->_pcb, NULL);
482496
if (client->_pcb->state == LISTEN) {
483-
tcp_sent(client->_pcb, NULL);
484-
tcp_recv(client->_pcb, NULL);
485-
tcp_err(client->_pcb, NULL);
486-
tcp_poll(client->_pcb, NULL, 0);
497+
::tcp_sent(client->_pcb, NULL);
498+
::tcp_recv(client->_pcb, NULL);
499+
::tcp_err(client->_pcb, NULL);
500+
::tcp_poll(client->_pcb, NULL, 0);
487501
}
488502
client->_pcb = nullptr;
489503
client->_free_closed_slot();
@@ -523,23 +537,6 @@ static void _tcp_dns_found(const char *name, struct ip_addr *ipaddr, void *arg)
523537
}
524538
}
525539

526-
// Used to switch out from LwIP thread
527-
static int8_t _tcp_accept(void *arg, AsyncClient *client) {
528-
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
529-
if (!e) {
530-
log_e("Failed to allocate event packet");
531-
return ERR_MEM;
532-
}
533-
e->event = LWIP_TCP_ACCEPT;
534-
e->arg = arg;
535-
e->accept.client = client;
536-
if (!_prepend_async_event(&e)) {
537-
free((void *)(e));
538-
return ERR_TIMEOUT;
539-
}
540-
return ERR_OK;
541-
}
542-
543540
/*
544541
* TCP/IP API Calls
545542
* */
@@ -749,10 +746,10 @@ AsyncClient::AsyncClient(tcp_pcb *pcb)
749746
if (_pcb) {
750747
_rx_last_packet = millis();
751748
tcp_arg(_pcb, this);
752-
tcp_recv(_pcb, &_tcp_recv);
753-
tcp_sent(_pcb, &_tcp_sent);
754-
tcp_err(_pcb, &_tcp_error);
755-
tcp_poll(_pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
749+
tcp_recv(_pcb, &AsyncTCP_detail::tcp_recv);
750+
tcp_sent(_pcb, &AsyncTCP_detail::tcp_sent);
751+
tcp_err(_pcb, &AsyncTCP_detail::tcp_error);
752+
tcp_poll(_pcb, &AsyncTCP_detail::tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
756753
if (!_allocate_closed_slot()) {
757754
_close();
758755
}
@@ -846,10 +843,10 @@ bool AsyncClient::connect(ip_addr_t addr, uint16_t port) {
846843
return false;
847844
}
848845
tcp_arg(pcb, this);
849-
tcp_err(pcb, &_tcp_error);
850-
tcp_recv(pcb, &_tcp_recv);
851-
tcp_sent(pcb, &_tcp_sent);
852-
tcp_poll(pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
846+
tcp_err(pcb, &AsyncTCP_detail::tcp_error);
847+
tcp_recv(pcb, &AsyncTCP_detail::tcp_recv);
848+
tcp_sent(pcb, &AsyncTCP_detail::tcp_sent);
849+
tcp_poll(pcb, &AsyncTCP_detail::tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER);
853850
}
854851

855852
esp_err_t err = _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected);
@@ -1479,42 +1476,6 @@ const char *AsyncClient::stateToString() const {
14791476
}
14801477
}
14811478

1482-
/*
1483-
* Static Callbacks (LwIP C2C++ interconnect)
1484-
* */
1485-
1486-
void AsyncClient::_s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg) {
1487-
reinterpret_cast<AsyncClient *>(arg)->_dns_found(ipaddr);
1488-
}
1489-
1490-
int8_t AsyncClient::_s_poll(void *arg, struct tcp_pcb *pcb) {
1491-
return reinterpret_cast<AsyncClient *>(arg)->_poll(pcb);
1492-
}
1493-
1494-
int8_t AsyncClient::_s_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, int8_t err) {
1495-
return reinterpret_cast<AsyncClient *>(arg)->_recv(pcb, pb, err);
1496-
}
1497-
1498-
int8_t AsyncClient::_s_fin(void *arg, struct tcp_pcb *pcb, int8_t err) {
1499-
return reinterpret_cast<AsyncClient *>(arg)->_fin(pcb, err);
1500-
}
1501-
1502-
int8_t AsyncClient::_s_lwip_fin(void *arg, struct tcp_pcb *pcb, int8_t err) {
1503-
return reinterpret_cast<AsyncClient *>(arg)->_lwip_fin(pcb, err);
1504-
}
1505-
1506-
int8_t AsyncClient::_s_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
1507-
return reinterpret_cast<AsyncClient *>(arg)->_sent(pcb, len);
1508-
}
1509-
1510-
void AsyncClient::_s_error(void *arg, int8_t err) {
1511-
reinterpret_cast<AsyncClient *>(arg)->_error(err);
1512-
}
1513-
1514-
int8_t AsyncClient::_s_connected(void *arg, struct tcp_pcb *pcb, int8_t err) {
1515-
return reinterpret_cast<AsyncClient *>(arg)->_connected(pcb, err);
1516-
}
1517-
15181479
/*
15191480
Async TCP Server
15201481
*/
@@ -1590,7 +1551,7 @@ void AsyncServer::begin() {
15901551
}
15911552
tcp_core_guard tcg;
15921553
tcp_arg(_pcb, (void *)this);
1593-
tcp_accept(_pcb, &_s_accept);
1554+
tcp_accept(_pcb, &AsyncTCP_detail::tcp_accept);
15941555
}
15951556

15961557
void AsyncServer::end() {
@@ -1606,18 +1567,28 @@ void AsyncServer::end() {
16061567
}
16071568

16081569
// runs on LwIP thread
1609-
int8_t AsyncServer::_accept(tcp_pcb *pcb, int8_t err) {
1570+
int8_t AsyncTCP_detail::tcp_accept(void *arg, tcp_pcb *pcb, int8_t err) {
16101571
if (!pcb) {
16111572
log_e("_accept failed: pcb is NULL");
16121573
return ERR_ABRT;
16131574
}
1614-
if (_connect_cb) {
1575+
auto server = reinterpret_cast<AsyncServer *>(arg);
1576+
if (server->_connect_cb) {
16151577
AsyncClient *c = new (std::nothrow) AsyncClient(pcb);
16161578
if (c && c->pcb()) {
1617-
c->setNoDelay(_noDelay);
1618-
if (_tcp_accept(this, c) == ERR_OK) {
1619-
return ERR_OK; // success
1579+
c->setNoDelay(server->_noDelay);
1580+
1581+
lwip_tcp_event_packet_t *e = (lwip_tcp_event_packet_t *)malloc(sizeof(lwip_tcp_event_packet_t));
1582+
if (e) {
1583+
e->event = LWIP_TCP_ACCEPT;
1584+
e->arg = arg;
1585+
e->accept.client = c;
1586+
if (_prepend_async_event(&e)) {
1587+
return ERR_OK; // success
1588+
}
1589+
free((void *)(e));
16201590
}
1591+
16211592
// Couldn't allocate accept event
16221593
// 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
16231594
c->_pcb = nullptr;
@@ -1662,11 +1633,3 @@ uint8_t AsyncServer::status() const {
16621633
}
16631634
return _pcb->state;
16641635
}
1665-
1666-
int8_t AsyncServer::_s_accept(void *arg, tcp_pcb *pcb, int8_t err) {
1667-
return reinterpret_cast<AsyncServer *>(arg)->_accept(pcb, err);
1668-
}
1669-
1670-
int8_t AsyncServer::_s_accepted(void *arg, AsyncClient *client) {
1671-
return reinterpret_cast<AsyncServer *>(arg)->_accepted(client);
1672-
}

src/AsyncTCP.h

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

7575
struct tcp_pcb;
7676
struct ip_addr;
77+
class AsyncTCP_detail;
7778

7879
class AsyncClient {
7980
public:
@@ -255,23 +256,13 @@ class AsyncClient {
255256
static const char *errorToString(int8_t error);
256257
const char *stateToString() const;
257258

258-
// internal callbacks - Do NOT call any of the functions below in user code!
259-
static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb);
260-
static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err);
261-
static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
262-
static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
263-
static void _s_error(void *arg, int8_t err);
264-
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
265-
static int8_t _s_connected(void *arg, struct tcp_pcb *tpcb, int8_t err);
266-
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
267-
static void _tcp_error(void *arg, int8_t err);
268-
269259
int8_t _recv(tcp_pcb *pcb, pbuf *pb, int8_t err);
270260
tcp_pcb *pcb() {
271261
return _pcb;
272262
}
273263

274264
protected:
265+
friend class AsyncTCP_detail;
275266
friend class AsyncServer;
276267

277268
tcp_pcb *_pcb;
@@ -333,11 +324,9 @@ class AsyncServer {
333324
bool getNoDelay() const;
334325
uint8_t status() const;
335326

336-
// Do not use any of the functions below!
337-
static int8_t _s_accept(void *arg, tcp_pcb *newpcb, int8_t err);
338-
static int8_t _s_accepted(void *arg, AsyncClient *client);
339-
340327
protected:
328+
friend class AsyncTCP_detail;
329+
341330
uint16_t _port;
342331
ip_addr_t _addr;
343332
bool _noDelay;

0 commit comments

Comments
 (0)