summaryrefslogtreecommitdiffstatshomepage
path: root/extmod
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-05-15 22:14:12 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-05-15 22:42:12 +0300
commitafce978aca77805e84a2442c93c26dab045784f8 (patch)
tree2fb23380f45cb717de7245f0996e554894a05356 /extmod
parentca63c770733ead7fd5de061ddc5268ffbd3c368b (diff)
downloadmicropython-afce978aca77805e84a2442c93c26dab045784f8.tar.gz
micropython-afce978aca77805e84a2442c93c26dab045784f8.zip
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.
Diffstat (limited to 'extmod')
-rw-r--r--extmod/modlwip.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index e03bdd56ff..cb7cc6596f 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -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;
}
}