1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Transmission Control Protocol (TCP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_tcp.h"
29 #include "nx_ipv6.h"
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _nx_tcp_socket_state_closing PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Yuxin Zhou, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function processes packets during the CLOSING state, */
44 /* which is the state at the end of an active, simultaneous */
45 /* disconnect. If a valid ACK is present, set the socket state */
46 /* to TIMED WAIT. */
47 /* */
48 /* INPUT */
49 /* */
50 /* socket_ptr Pointer to owning socket */
51 /* tcp_header_ptr Pointer to packet header */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* None */
56 /* */
57 /* CALLS */
58 /* */
59 /* _nx_tcp_packet_send_ack Send ACK message */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* _nx_tcp_socket_packet_process Process TCP packet for socket */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
70 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
71 /* resulting in version 6.1 */
72 /* */
73 /**************************************************************************/
_nx_tcp_socket_state_closing(NX_TCP_SOCKET * socket_ptr,NX_TCP_HEADER * tcp_header_ptr)74 VOID _nx_tcp_socket_state_closing(NX_TCP_SOCKET *socket_ptr, NX_TCP_HEADER *tcp_header_ptr)
75 {
76
77
78 /* Determine if the incoming message is an ACK message. */
79 if (tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_ACK_BIT)
80 {
81
82 /* If it is proper, finish the disconnect. */
83 if ((tcp_header_ptr -> nx_tcp_acknowledgment_number == socket_ptr -> nx_tcp_socket_tx_sequence) &&
84 (tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence))
85 {
86
87 /* Return to the proper socket state. */
88
89 /* Yes, return the socket to the TIMED WAIT state. */
90
91 /* If trace is enabled, insert this event into the trace buffer. */
92 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, socket_ptr -> nx_tcp_socket_ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_TIMED_WAIT, NX_TRACE_INTERNAL_EVENTS, 0, 0);
93
94 /* Set the socket state to TIMED WAIT now. */
95 socket_ptr -> nx_tcp_socket_state = NX_TCP_TIMED_WAIT;
96
97 /* Set the timeout as 2MSL (Maximum Segment Lifetime). */
98 socket_ptr -> nx_tcp_socket_timeout = _nx_tcp_2MSL_timer_rate;
99
100 /* Determine if we need to wake a thread suspended on the connection. */
101 if (socket_ptr -> nx_tcp_socket_disconnect_suspended_thread)
102 {
103
104 /* Resume the thread suspended for the disconnect. */
105 _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_disconnect_suspended_thread), NX_SUCCESS);
106 }
107
108 /* If given, call the application's disconnect callback function
109 for disconnect. */
110 if (socket_ptr -> nx_tcp_disconnect_callback)
111 {
112
113 /* Call the application's disconnect handling function. It is
114 responsible for calling the socket disconnect function. */
115 (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr);
116 }
117
118 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
119
120 /* Is a timed wait callback registered for this socket? */
121 if (socket_ptr -> nx_tcp_timed_wait_callback)
122 {
123
124 /* Call the timed wait callback for this socket to let the host
125 know the socket can now be put in the timed wait state (if
126 the RE-USE ADDRESS socket option is not enabled). */
127 (socket_ptr -> nx_tcp_timed_wait_callback)(socket_ptr);
128 }
129
130 /* Is a disconnect complete callback registered with the TCP socket? */
131 if (socket_ptr -> nx_tcp_disconnect_complete_notify)
132 {
133
134 /* Call the application's disconnect_complete callback function. */
135 (socket_ptr -> nx_tcp_disconnect_complete_notify)(socket_ptr);
136 }
137 #endif
138 }
139
140 /* Ignore the segment. According to RFC 793, Section 3.9, Page 73. */
141 }
142 }
143
144