1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Component */
17 /** */
18 /** Transmission Control Protocol (TCP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_api.h"
29 #include "nx_tcp.h"
30 #include "nx_packet.h"
31 #include "tx_thread.h"
32 #include "nx_ip.h"
33 #ifdef FEATURE_NX_IPV6
34 #include "nx_ipv6.h"
35 #endif /* FEATURE_NX_IPV6 */
36
37 #ifdef NX_ENABLE_TCPIP_OFFLOAD
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _nx_tcp_socket_driver_establish PORTABLE C */
43 /* 6.1.8 */
44 /* AUTHOR */
45 /* */
46 /* Yuxin Zhou, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function is invoked when a TCP connection is established. */
51 /* */
52 /* INPUT */
53 /* */
54 /* socket_ptr Pointer to owning socket */
55 /* interface_ptr Pointer to IP interface */
56 /* remote_port Pointer to remote UDP port */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* Status */
61 /* */
62 /* CALLS */
63 /* */
64 /* tx_mutex_get Obtain protection mutex */
65 /* tx_mutex_put Release protection mutex */
66 /* _nx_ip_packet_deferred_receive Defer IP packet receive */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Driver */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */
77 /* */
78 /**************************************************************************/
_nx_tcp_socket_driver_establish(NX_TCP_SOCKET * socket_ptr,NX_INTERFACE * interface_ptr,UINT remote_port)79 UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port)
80 {
81 NX_IP *ip_ptr;
82 NXD_ADDRESS ip_address;
83 UINT status;
84 UINT index;
85 UINT port;
86 struct NX_TCP_LISTEN_STRUCT *listen_ptr;
87
88 /* Setup the IP pointer. */
89 ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
90
91 /* Obtain the IP internal mutex before processing the IP event. */
92 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
93
94 /* Check socket state first. */
95 if ((socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_SENT) &&
96 (socket_ptr -> nx_tcp_socket_state != NX_TCP_LISTEN_STATE)&&
97 (socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_RECEIVED))
98 {
99
100 /* Just ignore socket not in connecting state. */
101 /* Release the IP internal mutex. */
102 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
103 return(NX_NOT_SUCCESSFUL);
104 }
105
106 if (socket_ptr -> nx_tcp_socket_client_type == NX_FALSE)
107 {
108 if (socket_ptr -> nx_tcp_socket_bound_next)
109 {
110
111 /* TCP socket is connecting on other interface. */
112 /* Release the IP internal mutex. */
113 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
114 return(NX_NOT_SUCCESSFUL);
115 }
116
117 /* For TCP server socket, the connection is not established yet. */
118 port = socket_ptr -> nx_tcp_socket_port;
119 status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr,
120 NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT,
121 NX_NULL, NX_NULL, &ip_address, port,
122 &remote_port, NX_NO_WAIT);
123
124 if (status)
125 {
126
127 /* This should not happen as a connection is pendding. */
128 /* Release the IP internal mutex. */
129 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
130 return(NX_TCPIP_OFFLOAD_ERROR);
131 }
132
133 /* Setup connection parameters. */
134 socket_ptr -> nx_tcp_socket_connect_interface = interface_ptr;
135
136 /* Save the server port and server IP address. */
137 socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version = ip_address.nxd_ip_version;
138 #ifndef NX_DISABLE_IPV4
139 if (ip_address.nxd_ip_version == NX_IP_VERSION_V4)
140 {
141 socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4;
142 socket_ptr -> nx_tcp_socket_mss =
143 (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER));
144 }
145 #endif /* !NX_DISABLE_IPV4 */
146
147 #ifdef FEATURE_NX_IPV6
148 if (ip_address.nxd_ip_version == NX_IP_VERSION_V6)
149 {
150 COPY_IPV6_ADDRESS(ip_address.nxd_ip_address.v6,
151 socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6);
152 socket_ptr -> nx_tcp_socket_mss =
153 (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER));
154 }
155 #endif /* FEATURE_NX_IPV6 */
156
157 socket_ptr -> nx_tcp_socket_connect_port = remote_port;
158
159 /* Find listen callback function. */
160 listen_ptr = ip_ptr -> nx_ip_tcp_active_listen_requests;
161 if (listen_ptr)
162 {
163 do
164 {
165 if (listen_ptr -> nx_tcp_listen_port == port)
166 {
167 if (listen_ptr -> nx_tcp_listen_callback)
168 {
169
170 /* Clear the server socket pointer in the listen request. If the
171 application wishes to honor more server connections on this port,
172 the application must call relisten with a new server socket
173 pointer. */
174 listen_ptr->nx_tcp_listen_socket_ptr = NX_NULL;
175
176 /* Call the user's listen callback function. */
177 (listen_ptr ->nx_tcp_listen_callback)(socket_ptr, listen_ptr -> nx_tcp_listen_port);
178 break;
179 }
180 }
181
182 /* Move to the next listen request. */
183 listen_ptr = listen_ptr -> nx_tcp_listen_next;
184 } while (listen_ptr != ip_ptr -> nx_ip_tcp_active_listen_requests);
185 }
186
187 /* Calculate the hash index in the TCP port array of the associated IP instance. */
188 index = (UINT)((port + (port >> 8)) & NX_TCP_PORT_TABLE_MASK);
189
190 /* Determine if the list is NULL. */
191 if (ip_ptr -> nx_ip_tcp_port_table[index])
192 {
193
194 /* There are already sockets on this list... just add this one
195 to the end. */
196 socket_ptr -> nx_tcp_socket_bound_next =
197 ip_ptr -> nx_ip_tcp_port_table[index];
198 socket_ptr -> nx_tcp_socket_bound_previous =
199 (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous;
200 ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next =
201 socket_ptr;
202 (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr;
203 }
204 else
205 {
206
207 /* Nothing is on the TCP port list. Add this TCP socket to an
208 empty list. */
209 socket_ptr -> nx_tcp_socket_bound_next = socket_ptr;
210 socket_ptr -> nx_tcp_socket_bound_previous = socket_ptr;
211 ip_ptr -> nx_ip_tcp_port_table[index] = socket_ptr;
212 }
213 }
214
215 /* Update socket state. */
216 socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED;
217
218 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
219
220 /* Is a connection completion callback registered with the TCP socket? */
221 if (socket_ptr -> nx_tcp_establish_notify)
222 {
223
224 /* Call the application's establish callback function. */
225 (socket_ptr -> nx_tcp_establish_notify)(socket_ptr);
226 }
227 #endif
228
229 /* Determine if we need to wake a thread suspended on the connection. */
230 if (socket_ptr -> nx_tcp_socket_connect_suspended_thread)
231 {
232
233 /* Resume the suspended thread. */
234 _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS);
235 }
236
237 /* Release the IP internal mutex. */
238 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
239
240 return(NX_SUCCESS);
241 }
242 #endif /* NX_ENABLE_TCPIP_OFFLOAD */
243
244