Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LWIP TCP socket close - disconnecting fix #10476

Merged
merged 1 commit into from May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 15 additions & 2 deletions features/lwipstack/LWIPStack.cpp
Expand Up @@ -50,9 +50,12 @@ void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
}

LWIP &lwip = LWIP::get_instance();

lwip.adaptation.lock();

if (eh == NETCONN_EVT_RCVPLUS && nc->state == NETCONN_NONE) {
lwip._event_flag.set(TCP_CLOSED_FLAG);
}

for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
if (lwip.arena[i].in_use
&& lwip.arena[i].conn == nc
Expand Down Expand Up @@ -292,7 +295,17 @@ nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
nsapi_error_t LWIP::socket_close(nsapi_socket_t handle)
{
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;

#if LWIP_TCP
/* Check if TCP FSM is in ESTABLISHED state.
* Then give extra time for connection close handshaking until TIME_WAIT state.
* The purpose is to prevent eth/wifi driver stop and FIN ACK corrupt.
* This may happend if network interface disconnect follows immediately after socket_close.*/
if (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_TCP && s->conn->pcb.tcp->state == ESTABLISHED) {
_event_flag.clear(TCP_CLOSED_FLAG);
netconn_shutdown(s->conn, false, true);
_event_flag.wait_any(TCP_CLOSED_FLAG, TCP_CLOSE_TIMEOUT);
}
#endif
netbuf_delete(s->buf);
err_t err = netconn_delete(s->conn);
arena_dealloc(s);
Expand Down
2 changes: 2 additions & 0 deletions features/lwipstack/LWIPStack.h
Expand Up @@ -587,6 +587,8 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
LWIPMemoryManager memory_manager;
osThreadId tcpip_thread_id;
rtos::Mutex adaptation;
rtos::EventFlags _event_flag;
static const int TCP_CLOSED_FLAG = 0x4u;
};

#endif /* LWIPSTACK_H_ */
5 changes: 5 additions & 0 deletions features/lwipstack/lwipopts.h
Expand Up @@ -244,6 +244,11 @@
#define LWIP_TCP 1
#define TCP_OVERSIZE 0
#define LWIP_TCP_KEEPALIVE 1
#ifdef MBED_CONF_TCP_CLOSE_TIMEOUT
#define TCP_CLOSE_TIMEOUT MBED_CONF_TCP_CLOSE_TIMEOUT
#else
#define TCP_CLOSE_TIMEOUT 1000
#endif
#else
#define LWIP_TCP 0
#endif
Expand Down
4 changes: 4 additions & 0 deletions features/lwipstack/mbed_lib.json
Expand Up @@ -100,6 +100,10 @@
"help": "Maximum number of retransmissions of SYN segments. Current default (used if null here) is set to 6 in opt.h",
"value": null
},
"tcp-close-timeout": {
"help": "Maximum timeout (ms) for TCP close handshaking timeout",
"value": 1000
},
"pbuf-pool-size": {
"help": "Number of pbufs in pool - usually used for received packets, so this determines how much data can be buffered between reception and the application reading. If a driver uses PBUF_RAM for reception, less pool may be needed. Current default (used if null here) is set to 5 in lwipopts.h, unless overridden by target Ethernet drivers.",
"value": null
Expand Down