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_ip.h"
30 #include "nx_tcp.h"
31 #include "tx_thread.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _nx_tcp_server_socket_accept                        PORTABLE C      */
39 /*                                                           6.1          */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Yuxin Zhou, Microsoft Corporation                                   */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function sets up the server socket after an active connection  */
47 /*    request was received.                                               */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    socket_ptr                            Pointer to new TCP socket     */
52 /*    wait_option                           Suspension option             */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    status                                Completion status             */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _nx_tcp_packet_send_syn               Send SYN message              */
61 /*    _nx_tcp_socket_thread_suspend         Suspend thread for connection */
62 /*    tx_mutex_get                          Obtain a protection mutex     */
63 /*    tx_mutex_put                          Release a protection mutex    */
64 /*    NX_RAND                               Random number for sequence    */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    Application Code                                                    */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
75 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*                                                                        */
78 /**************************************************************************/
_nx_tcp_server_socket_accept(NX_TCP_SOCKET * socket_ptr,ULONG wait_option)79 UINT  _nx_tcp_server_socket_accept(NX_TCP_SOCKET *socket_ptr, ULONG wait_option)
80 {
81 
82 NX_IP *ip_ptr;
83 
84 
85     /* Pickup the associated IP structure.  */
86     ip_ptr =  socket_ptr -> nx_tcp_socket_ip_ptr;
87 
88     /* If trace is enabled, insert this event into the trace buffer.  */
89     NX_TRACE_IN_LINE_INSERT(NX_TRACE_TCP_SERVER_SOCKET_ACCEPT, ip_ptr, socket_ptr, wait_option, socket_ptr -> nx_tcp_socket_state, NX_TRACE_TCP_EVENTS, 0, 0);
90 
91     /* Check if the socket has already made a connection, return successful outcome to accept(). */
92     if (socket_ptr -> nx_tcp_socket_state == NX_TCP_ESTABLISHED)
93     {
94         return(NX_SUCCESS);
95     }
96 
97     /* Determine if the socket is still in the listen state or has sent a SYN packet out already
98        from a previous accept() call on this socket.  */
99     if ((socket_ptr -> nx_tcp_socket_state != NX_TCP_LISTEN_STATE) && (socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_RECEIVED))
100     {
101 
102         /* Socket has either been closed or in the process of closing*/
103         return(NX_NOT_LISTEN_STATE);
104     }
105 
106 
107     /* Obtain the IP mutex so we can initiate accept processing for this socket.  */
108     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
109 
110     if (socket_ptr -> nx_tcp_socket_state == NX_TCP_LISTEN_STATE)
111     {
112 
113         /* Setup the initial sequence number.  */
114         if (socket_ptr -> nx_tcp_socket_tx_sequence == 0)
115         {
116             socket_ptr -> nx_tcp_socket_tx_sequence =  (((ULONG)NX_RAND()) << NX_SHIFT_BY_16) & 0xFFFFFFFF;
117             socket_ptr -> nx_tcp_socket_tx_sequence |= (ULONG)NX_RAND();
118         }
119         else
120         {
121             socket_ptr -> nx_tcp_socket_tx_sequence =  socket_ptr -> nx_tcp_socket_tx_sequence + ((ULONG)(((ULONG)0x10000))) + ((ULONG)NX_RAND());
122         }
123 
124         /* Ensure the rx window size logic is reset.  */
125         socket_ptr -> nx_tcp_socket_rx_window_current =    socket_ptr -> nx_tcp_socket_rx_window_default;
126         socket_ptr -> nx_tcp_socket_rx_window_last_sent =  socket_ptr -> nx_tcp_socket_rx_window_default;
127 
128         /* If trace is enabled, insert this event into the trace buffer.  */
129         NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_SYN_RECEIVED, NX_TRACE_INTERNAL_EVENTS, 0, 0);
130 
131         /* Move the TCP state to Sequence Received, the next state of a passive open.  */
132         socket_ptr -> nx_tcp_socket_state =  NX_TCP_SYN_RECEIVED;
133 
134         /* Clear the FIN received flag.  */
135         socket_ptr -> nx_tcp_socket_fin_received =  NX_FALSE;
136         socket_ptr -> nx_tcp_socket_fin_acked =  NX_FALSE;
137 
138         /* Determine if the listen command has completed.  This can be detected by checking
139            to see if the socket is bound.  If it is bound and still in the listen state, then
140            we know that this service is being called after a client connection request was
141            received.  */
142         if (socket_ptr -> nx_tcp_socket_bound_next)
143         {
144 
145             /* Send a SYN message back to establish the connection, but increment the ACK first.  */
146             socket_ptr -> nx_tcp_socket_rx_sequence++;
147 
148             /* Increment the sequence number.  */
149             socket_ptr -> nx_tcp_socket_tx_sequence++;
150 
151             /* Setup a timeout so the connection attempt can be sent again.  */
152 
153             socket_ptr -> nx_tcp_socket_timeout =          socket_ptr -> nx_tcp_socket_timeout_rate;
154             socket_ptr -> nx_tcp_socket_timeout_retries =  0;
155 
156             /* CLEANUP: Clean up any existing socket data before making a new connection. */
157             socket_ptr -> nx_tcp_socket_tx_window_congestion = 0;
158             socket_ptr -> nx_tcp_socket_tx_outstanding_bytes = 0;
159             socket_ptr -> nx_tcp_socket_packets_sent = 0;
160             socket_ptr -> nx_tcp_socket_bytes_sent = 0;
161             socket_ptr -> nx_tcp_socket_packets_received = 0;
162             socket_ptr -> nx_tcp_socket_bytes_received = 0;
163             socket_ptr -> nx_tcp_socket_retransmit_packets = 0;
164             socket_ptr -> nx_tcp_socket_checksum_errors = 0;
165             socket_ptr -> nx_tcp_socket_transmit_sent_head  =  NX_NULL;
166             socket_ptr -> nx_tcp_socket_transmit_sent_tail  =  NX_NULL;
167             socket_ptr -> nx_tcp_socket_transmit_sent_count =  0;
168             socket_ptr -> nx_tcp_socket_receive_queue_count =  0;
169             socket_ptr -> nx_tcp_socket_receive_queue_head  =  NX_NULL;
170             socket_ptr -> nx_tcp_socket_receive_queue_tail  =  NX_NULL;
171 
172             /* Send the SYN+ACK message.  */
173             _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1));
174         }
175         else
176         {
177             socket_ptr -> nx_tcp_socket_timeout = 0;
178         }
179     }
180 
181     /* Determine if the wait option is specified.  If so, suspend the calling thread.
182        Otherwise, return an in progress status.  */
183     if ((wait_option) && (_tx_thread_current_ptr != &(ip_ptr -> nx_ip_thread)))
184     {
185 
186         /* Suspend the thread on this socket's receive queue.  */
187         _nx_tcp_socket_thread_suspend(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), _nx_tcp_connect_cleanup,
188                                       socket_ptr, &(ip_ptr -> nx_ip_protection), wait_option);
189 
190         /* Check if the socket connection has failed.  */
191         if (_tx_thread_current_ptr -> tx_thread_suspend_status)
192         {
193 
194             /* If trace is enabled, insert this event into the trace buffer.  */
195             NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_LISTEN_STATE, NX_TRACE_INTERNAL_EVENTS, 0, 0);
196 
197             /* Yes, socket connection has failed.  Return to the
198                listen state so it can be tried again.  */
199             socket_ptr -> nx_tcp_socket_state =  NX_TCP_LISTEN_STATE;
200 
201             /* Socket is not active. Clear the timeout. */
202             socket_ptr -> nx_tcp_socket_timeout =  0;
203         }
204 
205         /* If not, just return the status.  */
206         return(_tx_thread_current_ptr -> tx_thread_suspend_status);
207     }
208     else
209     {
210 
211         /* No suspension is request, just release protection and return to the caller.  */
212 
213         /* Release the IP protection.  */
214         tx_mutex_put(&(ip_ptr -> nx_ip_protection));
215 
216         /* Return in-progress completion status.  */
217         return(NX_IN_PROGRESS);
218     }
219 }
220 
221