Tue 17 Feb 2009 10:57:53 PM UTC, original submission:
I'm debugging a problem where page elements served from an lwIP-based HTTP server are frequently missing in the browser. Looking at Wireshark traces, the typical failure scenario involves incoming SYN segments which are never responded to by lwIP. When the failure occurs, tcp_input determines that there is already a pcb for the connection on the tcp_active_pcbs list and passes control to tcp_process. Unfortunately, the pcb in question is in state SYN_RCVD so tcp_process does nothing.
Looking at the incoming connection handling, however, I see a problem. At the bottom of function tcp_listen_input, two calls are made to tcp_enqueue and tcp_output but no return code checking is performed to determine if the SYN | ACK response was actually sent successfully. In the failure I am seeing, tcp_enqueue fails due to lack of memory and this leaves the new pcb on the active queue but without having sparked off the next part of the SYN/ACK handshake.
To fix this, I have reworked tcp_in.c as follows:
1. Add local variable "err_t retcode" to tcp_listen_input.
2. Replace,
tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
return tcp_output(npcb);
at line 457 of tcp_in.c (HEAD) with,
retcode = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0,
(u8_t *)&optdata, 4);
if(retcode == ERR_OK) {
retcode = tcp_output(npcb);
}
if(retcode != ERR_OK) {
tcp_abort(npcb);
return(retcode);
}
This cures my problem. The tcp_abort call attempts to send an RST but this will likely fail in the same was as our attempt to send SYN |ACK. It does, however, accomplish the task of getting the new PCB off the active list and freeing it up.
I am attaching before and after versions of the file I am using which is based on the 1.3.0 release.
|