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