Skip to content

Commit 7d57037

Browse files
committed
extmod/modlwip: Add ability to run callback on "recv" and "accept" events.
To use: .setsockopt(SOL_SOCKET, 20, lambda sock: print(sock)). There's a single underlying callback slot. For normal sockets, it serves as data received callback, for listening sockets - connection arrived callback.
1 parent 67ece47 commit 7d57037

1 file changed

Lines changed: 27 additions & 1 deletion

File tree

extmod/modlwip.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ typedef struct _lwip_socket_obj_t {
234234
struct pbuf *pbuf;
235235
struct tcp_pcb *connection;
236236
} incoming;
237+
mp_obj_t callback;
237238
byte peer[4];
238239
mp_uint_t peer_port;
239240
mp_uint_t timeout;
@@ -261,6 +262,12 @@ static inline void poll_sockets(void) {
261262
/*******************************************************************************/
262263
// Callback functions for the lwIP raw API.
263264

265+
static inline void exec_user_callback(lwip_socket_obj_t *socket) {
266+
if (socket->callback != MP_OBJ_NULL) {
267+
mp_call_function_1(socket->callback, socket);
268+
}
269+
}
270+
264271
// Callback for incoming UDP packets. We simply stash the packet and the source address,
265272
// in case we need it for recvfrom.
266273
STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port) {
@@ -315,6 +322,7 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
315322
return ERR_BUF;
316323
} else {
317324
socket->incoming.connection = newpcb;
325+
exec_user_callback(socket);
318326
return ERR_OK;
319327
}
320328
}
@@ -327,12 +335,16 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
327335
// Other side has closed connection.
328336
DEBUG_printf("_lwip_tcp_recv[%p]: other side closed connection\n", socket);
329337
socket->state = STATE_PEER_CLOSED;
338+
exec_user_callback(socket);
330339
return ERR_OK;
331340
} else if (socket->incoming.pbuf != NULL) {
332341
// No room in the inn, let LWIP know it's still responsible for delivery later
333342
return ERR_BUF;
334343
}
335344
socket->incoming.pbuf = p;
345+
346+
exec_user_callback(socket);
347+
336348
return ERR_OK;
337349
}
338350

@@ -542,6 +554,7 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args
542554
socket->base.type = (mp_obj_t)&lwip_socket_type;
543555
socket->domain = MOD_NETWORK_AF_INET;
544556
socket->type = MOD_NETWORK_SOCK_STREAM;
557+
socket->callback = MP_OBJ_NULL;
545558
if (n_args >= 1) {
546559
socket->domain = mp_obj_get_int(args[0]);
547560
if (n_args >= 2) {
@@ -717,6 +730,7 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
717730
socket2->timeout = socket->timeout;
718731
socket2->state = STATE_CONNECTED;
719732
socket2->leftover_count = 0;
733+
socket2->callback = MP_OBJ_NULL;
720734
tcp_arg(socket2->pcb.tcp, (void*)socket2);
721735
tcp_err(socket2->pcb.tcp, _lwip_tcp_error);
722736
tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv);
@@ -978,8 +992,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_setblocking_obj, lwip_socket_setblo
978992
STATIC mp_obj_t lwip_socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
979993
(void)n_args; // always 4
980994
lwip_socket_obj_t *socket = args[0];
995+
996+
int opt = mp_obj_get_int(args[2]);
997+
if (opt == 20) {
998+
if (args[3] == mp_const_none) {
999+
socket->callback = MP_OBJ_NULL;
1000+
} else {
1001+
socket->callback = args[3];
1002+
}
1003+
return mp_const_none;
1004+
}
1005+
1006+
// Integer options
9811007
mp_int_t val = mp_obj_get_int(args[3]);
982-
switch (mp_obj_get_int(args[2])) {
1008+
switch (opt) {
9831009
case SOF_REUSEADDR:
9841010
// Options are common for UDP and TCP pcb's.
9851011
if (val) {

0 commit comments

Comments
 (0)