@@ -22,6 +22,9 @@ LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL);
2222#include "net_private.h"
2323#include "tcp2_priv.h"
2424
25+ #define FIN_TIMEOUT_MS MSEC_PER_SEC
26+ #define FIN_TIMEOUT K_MSEC(FIN_TIMEOUT_MS)
27+
2528static int tcp_rto = CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT ;
2629static int tcp_retries = CONFIG_NET_TCP_RETRY_COUNT ;
2730static int tcp_window = NET_IPV6_MTU ;
@@ -335,6 +338,7 @@ static int tcp_conn_unref(struct tcp *conn)
335338 tcp_pkt_unref (conn -> send_data );
336339
337340 k_delayed_work_cancel (& conn -> timewait_timer );
341+ k_delayed_work_cancel (& conn -> fin_timer );
338342
339343 sys_slist_find_and_remove (& tcp_conns , & conn -> next );
340344
@@ -420,8 +424,10 @@ static void tcp_send_timer_cancel(struct tcp *conn)
420424 {
421425 struct net_pkt * pkt = tcp_slist (& conn -> send_queue , get ,
422426 struct net_pkt , next );
423- NET_DBG ("%s" , log_strdup (tcp_th (pkt )));
424- tcp_pkt_unref (pkt );
427+ if (pkt ) {
428+ NET_DBG ("%s" , log_strdup (tcp_th (pkt )));
429+ tcp_pkt_unref (pkt );
430+ }
425431 }
426432
427433 if (sys_slist_is_empty (& conn -> send_queue )) {
@@ -875,6 +881,23 @@ static void tcp_resend_data(struct k_work *work)
875881 ret = tcp_send_data (conn );
876882 if (ret == 0 ) {
877883 conn -> send_data_retries ++ ;
884+
885+ if (conn -> in_close && conn -> send_data_total == 0 ) {
886+ NET_DBG ("TCP connection in active close, "
887+ "not disposing yet (waiting %dms)" ,
888+ FIN_TIMEOUT_MS );
889+ k_delayed_work_submit (& conn -> fin_timer , FIN_TIMEOUT );
890+
891+ conn_state (conn , TCP_FIN_WAIT_1 );
892+
893+ ret = tcp_out_ext (conn , FIN | ACK , NULL ,
894+ conn -> seq + conn -> unacked_len );
895+ if (ret == 0 ) {
896+ conn_seq (conn , + 1 );
897+ }
898+
899+ goto out ;
900+ }
878901 }
879902
880903 k_delayed_work_submit (& conn -> send_data_timer , K_MSEC (tcp_rto ));
@@ -891,7 +914,19 @@ static void tcp_timewait_timeout(struct k_work *work)
891914
892915 NET_DBG ("conn: %p %s" , conn , log_strdup (tcp_conn_state (conn , NULL )));
893916
894- tcp_conn_unref (conn );
917+ /* Extra unref from net_tcp_put() */
918+ net_context_unref (conn -> context );
919+ }
920+
921+ static void tcp_fin_timeout (struct k_work * work )
922+ {
923+ struct tcp * conn = CONTAINER_OF (work , struct tcp , fin_timer );
924+
925+ NET_DBG ("Did not receive FIN in %dms" , FIN_TIMEOUT_MS );
926+ NET_DBG ("conn: %p %s" , conn , log_strdup (tcp_conn_state (conn , NULL )));
927+
928+ /* Extra unref from net_tcp_put() */
929+ net_context_unref (conn -> context );
895930}
896931
897932static void tcp_conn_ref (struct tcp * conn )
@@ -927,6 +962,7 @@ static struct tcp *tcp_conn_alloc(void)
927962 k_delayed_work_init (& conn -> send_timer , tcp_send_process );
928963
929964 k_delayed_work_init (& conn -> timewait_timer , tcp_timewait_timeout );
965+ k_delayed_work_init (& conn -> fin_timer , tcp_fin_timeout );
930966
931967 conn -> send_data = tcp_pkt_alloc (conn , 0 );
932968 k_delayed_work_init (& conn -> send_data_timer , tcp_resend_data );
@@ -1299,6 +1335,16 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
12991335 }
13001336 conn -> data_mode = TCP_DATA_MODE_SEND ;
13011337
1338+ /* We are closing the connection, send a FIN to peer */
1339+ if (conn -> in_close && conn -> send_data_total == 0 ) {
1340+ tcp_send_timer_cancel (conn );
1341+ next = TCP_FIN_WAIT_1 ;
1342+
1343+ tcp_out (conn , FIN | ACK );
1344+ conn_seq (conn , + 1 );
1345+ break ;
1346+ }
1347+
13021348 ret = tcp_send_queued_data (conn );
13031349 if (ret < 0 && ret != - ENOBUFS ) {
13041350 tcp_out (conn , RST );
@@ -1349,7 +1395,11 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
13491395 }
13501396 break ;
13511397 case TCP_FIN_WAIT_2 :
1352- if (th && FL (& fl , = = , FIN , th_seq (th ) == conn -> ack )) {
1398+ if (th && (FL (& fl , = = , FIN , th_seq (th ) == conn -> ack ) ||
1399+ FL (& fl , = = , FIN | ACK , th_seq (th ) == conn -> ack ))) {
1400+ /* Received FIN on FIN_WAIT_2, so cancel the timer */
1401+ k_delayed_work_cancel (& conn -> fin_timer );
1402+
13531403 conn_ack (conn , + 1 );
13541404 tcp_out (conn , ACK );
13551405 next = TCP_TIME_WAIT ;
@@ -1386,22 +1436,48 @@ int net_tcp_put(struct net_context *context)
13861436{
13871437 struct tcp * conn = context -> tcp ;
13881438
1439+ k_mutex_lock (& conn -> lock , K_FOREVER );
1440+
13891441 NET_DBG ("%s" , conn ? log_strdup (tcp_conn_state (conn , NULL )) : "" );
13901442 NET_DBG ("context %p %s" , context ,
13911443 log_strdup (({ const char * state = net_context_state (context );
13921444 state ? state : "<unknown>" ; })));
13931445
13941446 if (conn && conn -> state == TCP_ESTABLISHED ) {
1395- k_mutex_lock (& conn -> lock , K_FOREVER );
1447+ /* Send all remaining data if possible. */
1448+ if (conn -> send_data_total > 0 ) {
1449+ NET_DBG ("conn %p pending %u bytes" , conn ,
1450+ conn -> send_data_total );
1451+ conn -> in_close = true;
1452+
1453+ /* How long to wait until all the data has been sent?
1454+ */
1455+ k_delayed_work_submit (& conn -> send_data_timer ,
1456+ K_MSEC (tcp_rto ));
1457+ } else {
1458+ int ret ;
13961459
1397- tcp_out_ext (conn , FIN | ACK , NULL ,
1398- conn -> seq + conn -> unacked_len );
1399- conn_seq (conn , + 1 );
1400- conn_state (conn , TCP_FIN_WAIT_1 );
1460+ NET_DBG ("TCP connection in active close, not "
1461+ "disposing yet (waiting %dms)" , FIN_TIMEOUT_MS );
1462+ k_delayed_work_submit (& conn -> fin_timer , FIN_TIMEOUT );
14011463
1402- k_mutex_unlock (& conn -> lock );
1464+ ret = tcp_out_ext (conn , FIN | ACK , NULL ,
1465+ conn -> seq + conn -> unacked_len );
1466+ if (ret == 0 ) {
1467+ conn_seq (conn , + 1 );
1468+ }
1469+
1470+ conn_state (conn , TCP_FIN_WAIT_1 );
1471+ }
1472+
1473+ /* Make sure we do not delete the connection yet until we have
1474+ * sent the final ACK.
1475+ */
1476+ net_context_ref (context );
14031477 }
14041478
1479+ k_mutex_unlock (& conn -> lock );
1480+
14051481 net_context_unref (context );
14061482
14071483 return 0 ;
0 commit comments