mirror of
https://github.com/apache/nuttx.git
synced 2026-08-09 14:35:08 +00:00
net/tcp: support recv packet in the TCP_FIN_WAIT_1/2 state
shutdown should send TCP_FIN packet.
close should send TCP_RST packet when the data in readahead has not been
read and NEW_DATA has arrived.
send TCP_FIN packet when in other cases.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
parent
0588d08d75
commit
2ad01e2aab
14 changed files with 92 additions and 95 deletions
|
|
@ -78,11 +78,11 @@ NuttX today.
|
|||
* - FIN-WAIT-1
|
||||
- ``TCP_FIN_WAIT_1``
|
||||
- Yes
|
||||
- Entered on active close (local FIN sent). However, it is currently unable to continue receiving data in this state
|
||||
- Entered on active close (local FIN sent).
|
||||
* - FIN-WAIT-2
|
||||
- ``TCP_FIN_WAIT_2``
|
||||
- Yes
|
||||
- Entered after ACK for local FIN (when peer hasn't closed yet). However, it is currently unable to continue receiving data in this state
|
||||
- Entered after ACK for local FIN (when peer hasn't closed yet).
|
||||
* - CLOSE-WAIT
|
||||
- Not implemented
|
||||
- Yes
|
||||
|
|
@ -243,8 +243,7 @@ TCP_FIN_WAIT_1
|
|||
|
||||
* Data received in FIN_WAIT_1:
|
||||
|
||||
* Current behavior is to send a RST and force ``TCP_CLOSED``.
|
||||
* The implementation notes this as a TODO to improve shutdown behavior.
|
||||
* Can continue receiving data until close or peer FIN.
|
||||
|
||||
TCP_FIN_WAIT_2
|
||||
--------------
|
||||
|
|
@ -257,7 +256,7 @@ TCP_FIN_WAIT_2
|
|||
|
||||
* Data received in FIN_WAIT_2:
|
||||
|
||||
* Current behavior is to send a RST and force ``TCP_CLOSED``.
|
||||
* Can continue receiving data until close or peer FIN.
|
||||
|
||||
TCP_CLOSING
|
||||
-----------
|
||||
|
|
@ -311,8 +310,6 @@ Deviations and Notable Simplifications
|
|||
======================================
|
||||
|
||||
* LISTEN is not an explicit TCP state; it is represented by listener table entries.
|
||||
* FIN_WAIT_* data handling is currently strict: received payload data in
|
||||
FIN_WAIT_1/2 results in sending RST and closing the connection.
|
||||
* RST processing is intentionally simple (accept RST and close).
|
||||
|
||||
Where to Look in the Code
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@
|
|||
* OUT: Not used
|
||||
*/
|
||||
|
||||
/* Bits 0-9: Connection specific event bits */
|
||||
/* Bits 0-11: Connection specific event bits */
|
||||
|
||||
#define TCP_ACKDATA (1 << 0)
|
||||
#define TCP_NEWDATA (1 << 1)
|
||||
|
|
@ -192,8 +192,7 @@
|
|||
#define TCP_CONNECTED (1 << 8)
|
||||
#define TCP_TIMEDOUT (1 << 9)
|
||||
#define TCP_WAITALL (1 << 10)
|
||||
|
||||
/* Bits 10-11: Unused, available */
|
||||
#define TCP_TXCLOSE (1 << 11)
|
||||
|
||||
/* Bit 12: Device specific event bits */
|
||||
|
||||
|
|
@ -216,7 +215,8 @@
|
|||
/* The set of events that and implications to the TCP connection state */
|
||||
|
||||
#define TCP_CONN_EVENTS \
|
||||
(TCP_CLOSE | TCP_ABORT | TCP_CONNECTED | TCP_TIMEDOUT | NETDEV_DOWN)
|
||||
(TCP_CLOSE | TCP_ABORT | TCP_CONNECTED | TCP_TIMEDOUT | NETDEV_DOWN | \
|
||||
TCP_TXCLOSE)
|
||||
|
||||
#define TCP_DISCONN_EVENTS \
|
||||
(TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT | NETDEV_DOWN)
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ struct tcp_conn_s
|
|||
* When an callback is executed from 'list', the input flags are normally
|
||||
* returned, however, the implementation may set one of the following:
|
||||
*
|
||||
* TCP_CLOSE - Gracefully close the current connection
|
||||
* TCP_TXCLOSE - Gracefully close the current connection (TX)
|
||||
* TCP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents TCP_CLOSE from working.
|
||||
*
|
||||
|
|
@ -220,6 +220,8 @@ struct tcp_conn_s
|
|||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
uint8_t domain; /* IP domain: PF_INET or PF_INET6 */
|
||||
#endif
|
||||
uint8_t shutdown; /* Whether the connection is shutdown, SHUT_RD and
|
||||
* SHUT_WR */
|
||||
uint8_t sa; /* Retransmission time-out calculation state
|
||||
* variable */
|
||||
uint8_t sv; /* Retransmission time-out calculation state
|
||||
|
|
|
|||
|
|
@ -190,9 +190,9 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
|||
tcp_send(dev, conn, TCP_RST | TCP_ACK, hdrlen);
|
||||
}
|
||||
|
||||
/* Check for connection closed */
|
||||
/* Check for connection tx closed */
|
||||
|
||||
else if ((result & TCP_CLOSE) != 0)
|
||||
else if ((result & TCP_TXCLOSE) != 0)
|
||||
{
|
||||
conn->tcpstateflags = conn->tcpstateflags == TCP_CLOSE_WAIT ?
|
||||
TCP_LAST_ACK : TCP_FIN_WAIT_1;
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Preserve the TCP_ACKDATA, TCP_CLOSE, and TCP_ABORT in the response.
|
||||
/* Preserve the TCP_ACKDATA, TCP_TXCLOSE, and TCP_ABORT in the response.
|
||||
* These is needed by the network to handle responses and buffer state.
|
||||
* The TCP_NEWDATA indication will trigger the ACK response, but must be
|
||||
* explicitly set in the callback.
|
||||
|
|
@ -283,7 +283,7 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
|
|||
* 'list', the input flags are normally returned, however, the
|
||||
* implementation may set one of the following:
|
||||
*
|
||||
* TCP_CLOSE - Gracefully close the current connection
|
||||
* TCP_TXCLOSE - Gracefully close the current connection (TX)
|
||||
* TCP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents TCP_CLOSE from working.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ static void tcp_close_work(FAR void *param)
|
|||
/* Stop the network monitor for all sockets */
|
||||
|
||||
conn_dev_lock(&conn->sconn, conn->dev);
|
||||
tcp_stop_monitor(conn, TCP_CLOSE);
|
||||
tcp_stop_monitor(conn, TCP_TXCLOSE);
|
||||
conn_dev_unlock(&conn->sconn, conn->dev);
|
||||
tcp_free(conn);
|
||||
}
|
||||
|
|
@ -78,22 +78,16 @@ static uint16_t tcp_close_eventhandler(FAR struct net_driver_s *dev,
|
|||
ninfo("flags: %04x\n", flags);
|
||||
|
||||
/* TCP_DISCONN_EVENTS:
|
||||
* TCP_CLOSE: The remote host has closed the connection
|
||||
* TCP_ABORT: The remote host has aborted the connection
|
||||
* TCP_TIMEDOUT: The remote did not respond, the connection timed out
|
||||
* NETDEV_DOWN: The network device went down
|
||||
*/
|
||||
|
||||
if ((flags & TCP_DISCONN_EVENTS) != 0)
|
||||
if ((flags & (TCP_TXCLOSE | TCP_DISCONN_EVENTS)) != 0)
|
||||
{
|
||||
/* The disconnection is complete. Wake up the waiting thread with an
|
||||
* appropriate result. Success is returned in these cases:
|
||||
*
|
||||
* * TCP_CLOSE indicates normal successful closure. The TCP_CLOSE
|
||||
* event is sent when the remote ACKs the outgoing FIN in the
|
||||
* FIN_WAIT_1 state. That is the appropriate time for the
|
||||
* application to close the socket.
|
||||
*
|
||||
* NOTE: The underlying connection, however, will persist, waiting
|
||||
* for the FIN to be returned by the remote in the TIME_WAIT state.
|
||||
*
|
||||
|
|
@ -128,7 +122,7 @@ static uint16_t tcp_close_eventhandler(FAR struct net_driver_s *dev,
|
|||
)
|
||||
{
|
||||
/* No... we are still waiting for ACKs. Drop any received data, but
|
||||
* do not yet report TCP_CLOSE in the response.
|
||||
* do not yet report TCP_TXCLOSE in the response.
|
||||
*/
|
||||
|
||||
dev->d_len = 0;
|
||||
|
|
@ -139,23 +133,20 @@ static uint16_t tcp_close_eventhandler(FAR struct net_driver_s *dev,
|
|||
{
|
||||
/* Note: the following state shouldn't reach here because
|
||||
*
|
||||
* FIN_WAIT_1, CLOSING, LAST_ACK
|
||||
* CLOSING, LAST_ACK
|
||||
* should have tx_unacked != 0, already handled above
|
||||
*
|
||||
* CLOSED, TIME_WAIT
|
||||
* a TCP_CLOSE callback should have already cleared this callback
|
||||
* a TCP_TXCLOSE callback should have already cleared this callback
|
||||
* when transitioning to these states.
|
||||
*
|
||||
* FIN_WAIT_2
|
||||
* new data is dropped by tcp_input without invoking tcp_callback.
|
||||
* timer is handled by tcp_timer without invoking tcp_callback.
|
||||
* TCP_CLOSE is handled above.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(conn->tcpstateflags == TCP_ESTABLISHED ||
|
||||
conn->tcpstateflags == TCP_CLOSE_WAIT);
|
||||
conn->tcpstateflags == TCP_CLOSE_WAIT ||
|
||||
conn->tcpstateflags == TCP_FIN_WAIT_1 ||
|
||||
conn->tcpstateflags == TCP_FIN_WAIT_2);
|
||||
|
||||
/* Drop data received in this state and make sure that TCP_CLOSE
|
||||
/* Drop data received in this state and make sure that TCP_TXCLOSE
|
||||
* is set in the response
|
||||
*/
|
||||
|
||||
|
|
@ -174,7 +165,30 @@ static uint16_t tcp_close_eventhandler(FAR struct net_driver_s *dev,
|
|||
#endif
|
||||
|
||||
dev->d_len = 0;
|
||||
flags = (flags & ~TCP_NEWDATA) | TCP_CLOSE;
|
||||
if (conn->readahead != NULL || (flags & TCP_NEWDATA) != 0)
|
||||
{
|
||||
/* We need to send RST when read-ahead buffer data is not consumed
|
||||
* or new data is coming.
|
||||
* Set TCP_ABORT flag to trigger sending RST.
|
||||
*/
|
||||
|
||||
flags = flags & ~TCP_NEWDATA;
|
||||
flags |= TCP_ABORT;
|
||||
|
||||
/* Free rx buffers of the connection immediately */
|
||||
|
||||
tcp_free_rx_buffers(conn);
|
||||
|
||||
goto end_wait;
|
||||
}
|
||||
else if ((conn->shutdown & SHUT_WR) == 0)
|
||||
{
|
||||
flags |= TCP_TXCLOSE;
|
||||
|
||||
/* Avoid sending multiple FIN */
|
||||
|
||||
conn->shutdown |= SHUT_WR;
|
||||
}
|
||||
}
|
||||
|
||||
UNUSED(conn); /* May not be used */
|
||||
|
|
@ -236,18 +250,16 @@ static inline int tcp_close_disconnect(FAR struct socket *psock)
|
|||
*/
|
||||
|
||||
if ((conn->tcpstateflags == TCP_ESTABLISHED ||
|
||||
conn->tcpstateflags == TCP_FIN_WAIT_1 ||
|
||||
conn->tcpstateflags == TCP_FIN_WAIT_2 ||
|
||||
conn->tcpstateflags == TCP_LAST_ACK ||
|
||||
conn->tcpstateflags == TCP_CLOSE_WAIT) &&
|
||||
(conn->clscb = tcp_callback_alloc(conn)) != NULL)
|
||||
{
|
||||
/* Free rx buffers of the connection immediately */
|
||||
|
||||
tcp_free_rx_buffers(conn);
|
||||
|
||||
/* Set up to receive TCP data event callbacks */
|
||||
|
||||
conn->clscb->flags = TCP_NEWDATA | TCP_ACKDATA |
|
||||
TCP_POLL | TCP_DISCONN_EVENTS;
|
||||
TCP_POLL | TCP_TXCLOSE | TCP_DISCONN_EVENTS;
|
||||
conn->clscb->event = tcp_close_eventhandler;
|
||||
conn->clscb->priv = conn; /* reference for event handler to free cb */
|
||||
|
||||
|
|
@ -284,7 +296,7 @@ static inline int tcp_close_disconnect(FAR struct socket *psock)
|
|||
{
|
||||
/* Stop the network monitor for all sockets */
|
||||
|
||||
tcp_stop_monitor(conn, TCP_CLOSE);
|
||||
tcp_stop_monitor(conn, TCP_TXCLOSE);
|
||||
conn_dev_unlock(&conn->sconn, conn->dev);
|
||||
|
||||
/* Free network resources */
|
||||
|
|
|
|||
|
|
@ -791,7 +791,7 @@ void tcp_free(FAR struct tcp_conn_s *conn)
|
|||
/* Make sure monitor is stopped. */
|
||||
|
||||
conn_dev_lock(&conn->sconn, conn->dev);
|
||||
tcp_stop_monitor(conn, TCP_CLOSE);
|
||||
tcp_stop_monitor(conn, TCP_TXCLOSE);
|
||||
|
||||
/* Free remaining callbacks, actually there should be only the send
|
||||
* callback for CONFIG_NET_TCP_WRITE_BUFFERS is left.
|
||||
|
|
|
|||
|
|
@ -111,7 +111,9 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
|
|||
/* Verify that the connection is established. */
|
||||
|
||||
if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED ||
|
||||
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_CLOSE_WAIT)
|
||||
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_CLOSE_WAIT ||
|
||||
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_FIN_WAIT_1 ||
|
||||
(conn->tcpstateflags & TCP_STATE_MASK) == TCP_FIN_WAIT_2)
|
||||
{
|
||||
/* Set up for the callback. We can't know in advance if the
|
||||
* application is going to send a IPv4 or an IPv6 packet, so this
|
||||
|
|
|
|||
|
|
@ -1112,7 +1112,8 @@ found:
|
|||
/* Check if no packet need to retransmission, clear timer. */
|
||||
|
||||
if (conn->tx_unacked == 0 && (conn->tcpstateflags == TCP_ESTABLISHED ||
|
||||
conn->tcpstateflags == TCP_CLOSE_WAIT))
|
||||
conn->tcpstateflags == TCP_CLOSE_WAIT ||
|
||||
conn->tcpstateflags == TCP_FIN_WAIT_1))
|
||||
{
|
||||
timeout = 0;
|
||||
}
|
||||
|
|
@ -1183,18 +1184,15 @@ found:
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if ((conn->tcpstateflags & TCP_STATE_MASK) <= TCP_ESTABLISHED)
|
||||
else if ((conn->tcpstateflags & TCP_STATE_MASK) <= TCP_FIN_WAIT_2)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
|
||||
/* Queue out-of-order segments. */
|
||||
|
||||
tcp_input_ofosegs(dev, conn, iplen);
|
||||
#endif
|
||||
if ((conn->tcpstateflags & TCP_STATE_MASK) <= TCP_ESTABLISHED)
|
||||
{
|
||||
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
||||
return;
|
||||
}
|
||||
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1553,7 +1551,7 @@ found:
|
|||
conn->tcpstateflags = TCP_CLOSED;
|
||||
ninfo("TCP_LAST_ACK TCP state: TCP_CLOSED\n");
|
||||
|
||||
tcp_callback(dev, conn, TCP_CLOSE);
|
||||
tcp_callback(dev, conn, TCP_TXCLOSE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1563,11 +1561,6 @@ found:
|
|||
* until we receive a FIN from the remote.
|
||||
*/
|
||||
|
||||
if (dev->d_len > 0)
|
||||
{
|
||||
net_incr32(conn->rcvseq, dev->d_len);
|
||||
}
|
||||
|
||||
if ((tcp->flags & TCP_FIN) != 0)
|
||||
{
|
||||
if ((flags & TCP_ACKDATA) != 0 && conn->tx_unacked == 0)
|
||||
|
|
@ -1592,36 +1585,18 @@ found:
|
|||
{
|
||||
conn->tcpstateflags = TCP_FIN_WAIT_2;
|
||||
ninfo("TCP state: TCP_FIN_WAIT_2\n");
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (dev->d_len > 0)
|
||||
{
|
||||
/* Due to RFC 2525, Section 2.17, we SHOULD send RST if we can no
|
||||
* longer read any received data. Also set state into TCP_CLOSED
|
||||
* because the peer will not send FIN after RST received.
|
||||
*
|
||||
* TODO: Modify shutdown behavior to allow read in FIN_WAIT.
|
||||
*/
|
||||
|
||||
conn->tcpstateflags = TCP_CLOSED;
|
||||
|
||||
/* In the TCP_FIN_WAIT_1, we need call tcp_close_eventhandler to
|
||||
* release nofosegs, that we received in this state.
|
||||
*/
|
||||
|
||||
tcp_callback(dev, conn, TCP_CLOSE);
|
||||
tcp_reset(dev, conn);
|
||||
result = tcp_callback(dev, conn, TCP_NEWDATA);
|
||||
tcp_appsend(dev, conn, result);
|
||||
return;
|
||||
}
|
||||
|
||||
goto drop;
|
||||
|
||||
case TCP_FIN_WAIT_2:
|
||||
if (dev->d_len > 0)
|
||||
{
|
||||
net_incr32(conn->rcvseq, dev->d_len);
|
||||
}
|
||||
|
||||
if ((tcp->flags & TCP_FIN) != 0)
|
||||
{
|
||||
|
|
@ -1638,19 +1613,8 @@ found:
|
|||
|
||||
if (dev->d_len > 0)
|
||||
{
|
||||
/* Due to RFC 2525, Section 2.17, we SHOULD send RST if we can no
|
||||
* longer read any received data. Also set state into TCP_CLOSED
|
||||
* because the peer will not send FIN after RST received.
|
||||
*/
|
||||
|
||||
conn->tcpstateflags = TCP_CLOSED;
|
||||
|
||||
/* In the TCP_FIN_WAIT_2, we need call tcp_close_eventhandler to
|
||||
* release nofosegs, that we received in this state.
|
||||
*/
|
||||
|
||||
tcp_callback(dev, conn, TCP_CLOSE);
|
||||
tcp_reset(dev, conn);
|
||||
result = tcp_callback(dev, conn, TCP_NEWDATA);
|
||||
tcp_appsend(dev, conn, result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ static uint16_t tcp_monitor_event(FAR struct net_driver_s *dev,
|
|||
*
|
||||
* Input Parameters:
|
||||
* conn - The TCP connection of interest
|
||||
* flags - Indicates the type of shutdown. TCP_CLOSE or TCP_ABORT
|
||||
* flags - Indicates the type of shutdown. TCP_TXCLOSE or TCP_ABORT
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
|
|
|
|||
|
|
@ -1361,6 +1361,13 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||
goto errout;
|
||||
}
|
||||
|
||||
if ((conn->shutdown & SHUT_WR) != 0)
|
||||
{
|
||||
nerr("ERROR: Connection is shutdown\n");
|
||||
ret = -EPIPE;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Make sure that we have the IP address mapping */
|
||||
|
||||
#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR)
|
||||
|
|
@ -1443,7 +1450,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
|||
/* Set up the callback in the connection */
|
||||
|
||||
conn->sndcb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_POLL |
|
||||
TCP_DISCONN_EVENTS);
|
||||
TCP_DISCONN_EVENTS | TCP_TXCLOSE);
|
||||
conn->sndcb->priv = (FAR void *)conn;
|
||||
conn->sndcb->event = psock_send_eventhandler;
|
||||
|
||||
|
|
|
|||
|
|
@ -511,6 +511,13 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
|
|||
goto errout;
|
||||
}
|
||||
|
||||
if ((conn->shutdown & SHUT_WR) != 0)
|
||||
{
|
||||
nerr("ERROR: Connection is shutdown\n");
|
||||
ret = -EPIPE;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Make sure that we have the IP address mapping */
|
||||
|
||||
#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR)
|
||||
|
|
@ -591,7 +598,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
|
|||
/* Set up the callback in the connection */
|
||||
|
||||
state.snd_cb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_POLL |
|
||||
TCP_DISCONN_EVENTS);
|
||||
TCP_DISCONN_EVENTS | TCP_TXCLOSE);
|
||||
state.snd_cb->priv = (FAR void *)&state;
|
||||
state.snd_cb->event = tcpsend_eventhandler;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ static uint16_t tcp_shutdown_eventhandler(FAR struct net_driver_s *dev,
|
|||
#endif
|
||||
|
||||
dev->d_len = 0;
|
||||
flags = (flags & ~TCP_NEWDATA) | TCP_CLOSE;
|
||||
flags |= TCP_TXCLOSE;
|
||||
|
||||
if (conn->shdcb != NULL)
|
||||
{
|
||||
|
|
@ -160,11 +160,18 @@ out:
|
|||
|
||||
int tcp_shutdown(FAR struct socket *psock, int how)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn;
|
||||
|
||||
conn = psock->s_conn;
|
||||
DEBUGASSERT(conn != NULL);
|
||||
|
||||
if (!(how & SHUT_WR))
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
conn->shutdown |= how;
|
||||
|
||||
tcp_unlisten(psock->s_conn); /* No longer accepting connections */
|
||||
|
||||
return tcp_send_fin(psock);
|
||||
|
|
|
|||
|
|
@ -473,8 +473,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
|
|||
* out.
|
||||
*/
|
||||
|
||||
if (conn->tcpstateflags == TCP_TIME_WAIT ||
|
||||
conn->tcpstateflags == TCP_FIN_WAIT_2)
|
||||
if (conn->tcpstateflags == TCP_TIME_WAIT)
|
||||
{
|
||||
/* Check if the timer exceeds the timeout value */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue