Skip to content

Commit

Permalink
Fixed TCP connection close.
Browse files Browse the repository at this point in the history
If TCP FSM is in ESTABLISHED state,  waits  for TCP close handshaking until TIME_WAIT
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.
  • Loading branch information
tymoteuszblochmobica committed May 10, 2019
1 parent b21c278 commit 1806702
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 2 deletions.
18 changes: 16 additions & 2 deletions features/lwipstack/LWIPStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "nsapi.h"
#include "mbed_interface.h"
#include "mbed_assert.h"
#include "rtos/ThisThread.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
Expand Down Expand Up @@ -50,9 +51,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 +296,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 number of 1ms intervals 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

0 comments on commit 1806702

Please sign in to comment.