extmod/modlwip: Rework how Python accept callback is called.

Calling it from lwIP accept callback will lead incorrect functioning
and/or packet leaks if Python callback has any networking calls, due
to lwIP non-reentrancy. So, instead schedule "poll" callback to do
that, which will be called by lwIP when it does not perform networking
activities. "Poll" callback is called infrequently though (docs say
every 0.5s by default), so for better performance, lwIP needs to be
patched to call poll callback soon after accept callback, but when
current packet is already processed.
pull/2082/head
Paul Sokolovsky 2016-05-15 22:14:12 +03:00
rodzic ca63c77073
commit afce978aca
1 zmienionych plików z 17 dodań i 1 usunięć

Wyświetl plik

@ -311,6 +311,17 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb
return ERR_BUF;
}
// "Poll" (idle) callback to be called ASAP after accept callback
// to execute Python callback function, as it can't be executed
// from accept callback itself.
STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb)
{
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
tcp_poll(pcb, NULL, 0);
exec_user_callback(socket);
return ERR_OK;
}
// Callback for incoming tcp connections.
STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
@ -323,7 +334,12 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
return ERR_BUF;
} else {
socket->incoming.connection = newpcb;
exec_user_callback(socket);
if (socket->callback != MP_OBJ_NULL) {
// Schedule accept callback to be called when lwIP is done
// with processing this incoming connection on its side and
// is idle.
tcp_poll(newpcb, _lwip_tcp_accept_finished, 1);
}
return ERR_OK;
}
}