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_ip.h"
29 #include "nx_tcp.h"
30 #ifdef NX_ENABLE_HTTP_PROXY
31 #include "nx_http_proxy_client.h"
32 #endif /* NX_ENABLE_HTTP_PROXY */
33
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _nx_tcp_socket_state_established PORTABLE C */
40 /* 6.2.0 */
41 /* AUTHOR */
42 /* */
43 /* Yuxin Zhou, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function processes packets during the ESTABLISHED state, */
48 /* the state of the socket during typical TCP data sending and */
49 /* receiving. The expected packet that changes state once in the */
50 /* established state is the FIN packet. Reception of this will move */
51 /* the state for this socket to the CLOSE WAIT state. */
52 /* */
53 /* INPUT */
54 /* */
55 /* socket_ptr Pointer to owning socket */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* None */
60 /* */
61 /* CALLS */
62 /* */
63 /* _nx_tcp_packet_send_ack Send ACK message */
64 /* (nx_tcp_disconnect_callback) Application's callback */
65 /* function when disconnect */
66 /* FIN is received */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* _nx_tcp_socket_packet_process Process TCP packet for socket */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
77 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
78 /* resulting in version 6.1 */
79 /* 10-31-2022 Wenhui Xie Modified comment(s), and */
80 /* supported HTTP Proxy, */
81 /* resulting in version 6.2.0 */
82 /* */
83 /**************************************************************************/
_nx_tcp_socket_state_established(NX_TCP_SOCKET * socket_ptr)84 VOID _nx_tcp_socket_state_established(NX_TCP_SOCKET *socket_ptr)
85 {
86 #if !defined(NX_DISABLE_TCP_INFO) || defined(TX_ENABLE_EVENT_TRACE)
87 NX_IP *ip_ptr;
88
89
90 /* Setup the IP pointer. */
91 ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
92 #endif
93 /* Determine if a FIN has been previously detected in the _nx_tcp_socket_state_data_check
94 routine and if the socket's sequence number matches the expected FIN sequence number. */
95 if ((socket_ptr -> nx_tcp_socket_fin_received) &&
96 (socket_ptr -> nx_tcp_socket_fin_sequence == socket_ptr -> nx_tcp_socket_rx_sequence))
97 {
98
99 #ifndef NX_DISABLE_TCP_INFO
100 /* Increment the TCP disconnections count. */
101 ip_ptr -> nx_ip_tcp_disconnections++;
102 #endif
103
104 #ifdef NX_ENABLE_TCP_KEEPALIVE
105 /* Is the keepalive feature enabled on this socket? */
106 if (socket_ptr -> nx_tcp_socket_keepalive_enabled)
107 {
108 /* Clear the TCP Keepalive timer to disable it for this socket (only needed when
109 the socket is connected. */
110 socket_ptr -> nx_tcp_socket_keepalive_timeout = 0;
111 socket_ptr -> nx_tcp_socket_keepalive_retries = 0;
112 }
113 #endif
114
115 /* If trace is enabled, insert this event into the trace buffer. */
116 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_CLOSE_WAIT, NX_TRACE_INTERNAL_EVENTS, 0, 0);
117
118 /* The FIN bit is set, we need to go into the finished state. */
119 socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSE_WAIT;
120
121 /* Increment the received sequence. */
122 socket_ptr -> nx_tcp_socket_rx_sequence++;
123
124 /* Loop to release all threads suspended while trying to receive on the socket. */
125 while (socket_ptr -> nx_tcp_socket_receive_suspension_list)
126 {
127
128 /* Release the head of the receive suspension list. */
129 _nx_tcp_receive_cleanup(socket_ptr -> nx_tcp_socket_receive_suspension_list NX_CLEANUP_ARGUMENT);
130 }
131
132 /* Send ACK message. */
133 _nx_tcp_packet_send_ack(socket_ptr, socket_ptr -> nx_tcp_socket_tx_sequence);
134
135 #ifdef NX_ENABLE_HTTP_PROXY
136 if ((ip_ptr -> nx_ip_http_proxy_enable) &&
137 (socket_ptr -> nx_tcp_socket_http_proxy_state == NX_HTTP_PROXY_STATE_CONNECTING))
138 {
139
140 /* If received FIN before HTTP Proxy connection established, disconnect the TCP connection
141 and don't notify the application. */
142 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
143 }
144 else
145 #endif /* NX_ENABLE_HTTP_PROXY */
146 {
147
148 /* If given, call the application's disconnect callback function
149 for disconnect. */
150 if (socket_ptr -> nx_tcp_disconnect_callback)
151 {
152
153 /* Call the application's disconnect handling function. It is
154 responsible for calling the socket disconnect function. */
155 (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr);
156 }
157 }
158 }
159 }
160
161