extmod/modlwip: Handle case of connection closing while on accept queue.
In such a case the connection is aborted by lwIP and so must be removed from the pending accept queue.
This commit is contained in:
parent
edd0e0f93d
commit
da938a83b5
|
@ -370,6 +370,43 @@ STATIC err_t _lwip_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
|||
return ERR_OK;
|
||||
}
|
||||
|
||||
// Handle errors (eg connection aborted) on TCP PCBs that have been put on the
|
||||
// accept queue but are not yet actually accepted.
|
||||
STATIC void _lwip_tcp_err_unaccepted(void *arg, err_t err) {
|
||||
struct tcp_pcb *pcb = (struct tcp_pcb*)arg;
|
||||
|
||||
// The ->connected entry is repurposed to store the parent socket; this is safe
|
||||
// because it's only ever used by lwIP if tcp_connect is called on the TCP PCB.
|
||||
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)pcb->connected;
|
||||
|
||||
// Array is not volatile because thiss callback is executed within the lwIP context
|
||||
uint8_t alloc = socket->incoming.connection.alloc;
|
||||
struct tcp_pcb **tcp_array = (struct tcp_pcb**)lwip_socket_incoming_array(socket);
|
||||
|
||||
// Search for PCB on the accept queue of the parent socket
|
||||
struct tcp_pcb **shift_down = NULL;
|
||||
uint8_t i = socket->incoming.connection.iget;
|
||||
do {
|
||||
if (shift_down == NULL) {
|
||||
if (tcp_array[i] == pcb) {
|
||||
shift_down = &tcp_array[i];
|
||||
}
|
||||
} else {
|
||||
*shift_down = tcp_array[i];
|
||||
shift_down = &tcp_array[i];
|
||||
}
|
||||
if (++i >= alloc) {
|
||||
i = 0;
|
||||
}
|
||||
} while (i != socket->incoming.connection.iput);
|
||||
|
||||
// PCB found in queue, remove it
|
||||
if (shift_down != NULL) {
|
||||
*shift_down = NULL;
|
||||
socket->incoming.connection.iput = shift_down - tcp_array;
|
||||
}
|
||||
}
|
||||
|
||||
// By default, a child socket of listen socket is created with recv
|
||||
// handler which discards incoming pbuf's. We don't want to do that,
|
||||
// so set this handler which requests lwIP to keep pbuf's and deliver
|
||||
|
@ -409,6 +446,15 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
|
|||
// is idle.
|
||||
tcp_poll(newpcb, _lwip_tcp_accept_finished, 1);
|
||||
}
|
||||
|
||||
// Set the error callback to handle the case of a dropped connection before we
|
||||
// have a chance to take it off the accept queue.
|
||||
// The ->connected entry is repurposed to store the parent socket; this is safe
|
||||
// because it's only ever used by lwIP if tcp_connect is called on the TCP PCB.
|
||||
newpcb->connected = (void*)socket;
|
||||
tcp_arg(newpcb, newpcb);
|
||||
tcp_err(newpcb, _lwip_tcp_err_unaccepted);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue