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 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_tcp_socket_create                               PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function creates a TCP socket for the specified IP instance.   */
45 /*    Both client and server sockets are created by this service.         */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    ip_ptr                                IP instance pointer           */
50 /*    socket_ptr                            Pointer to new TCP socket     */
51 /*    name                                  Name of new TCP socket        */
52 /*    type_of_service                       Type of service for this TCP  */
53 /*                                            socket                      */
54 /*    fragment                              Flag to enable IP fragmenting */
55 /*    time_to_live                          Time to live value for socket */
56 /*    window_size                           Size of socket's receive      */
57 /*                                            window                      */
58 /*    tcp_urgent_data_callback              Routine to call when urgent   */
59 /*                                            data is received            */
60 /*    tcp_disconnect_callback               Routine to call when a        */
61 /*                                            disconnect occurs           */
62 /*                                                                        */
63 /*  OUTPUT                                                                */
64 /*                                                                        */
65 /*    status                                Completion status             */
66 /*                                                                        */
67 /*  CALLS                                                                 */
68 /*                                                                        */
69 /*    tx_mutex_get                          Obtain protection             */
70 /*    tx_mutex_put                          Release protection            */
71 /*                                                                        */
72 /*  CALLED BY                                                             */
73 /*                                                                        */
74 /*    Application Code                                                    */
75 /*                                                                        */
76 /*  RELEASE HISTORY                                                       */
77 /*                                                                        */
78 /*    DATE              NAME                      DESCRIPTION             */
79 /*                                                                        */
80 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
81 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
82 /*                                            resulting in version 6.1    */
83 /*                                                                        */
84 /**************************************************************************/
_nx_tcp_socket_create(NX_IP * ip_ptr,NX_TCP_SOCKET * socket_ptr,CHAR * name,ULONG type_of_service,ULONG fragment,UINT time_to_live,ULONG window_size,VOID (* tcp_urgent_data_callback)(NX_TCP_SOCKET * socket_ptr),VOID (* tcp_disconnect_callback)(NX_TCP_SOCKET * socket_ptr))85 UINT  _nx_tcp_socket_create(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, CHAR *name,
86                             ULONG type_of_service, ULONG fragment, UINT time_to_live, ULONG window_size,
87                             VOID (*tcp_urgent_data_callback)(NX_TCP_SOCKET *socket_ptr),
88                             VOID (*tcp_disconnect_callback)(NX_TCP_SOCKET *socket_ptr))
89 {
90 TX_INTERRUPT_SAVE_AREA
91 
92 NX_TCP_SOCKET *tail_ptr;
93 
94 
95     /* Initialize the TCP control block to zero.  */
96     memset((void *)socket_ptr, 0, sizeof(NX_TCP_SOCKET));
97 
98     /* Fill in the basic information in the new TCP socket structure.  */
99 
100     /* Remember the associated IP structure.  */
101     socket_ptr -> nx_tcp_socket_ip_ptr =  ip_ptr;
102 
103     /* By default, indicate the socket is a client socket.  */
104     socket_ptr -> nx_tcp_socket_client_type =  NX_TRUE;
105 
106     /* Save the TCP socket's name.  */
107     socket_ptr -> nx_tcp_socket_name =  name;
108 
109     /* Setup the counter for duplicated ACK packet.  */
110     socket_ptr -> nx_tcp_socket_duplicated_ack_received = 0;
111 
112     /* Setup this socket's maximum segment size (mss).  */
113     socket_ptr -> nx_tcp_socket_mss = 0;
114 
115     /* Setup the default receiver's maximum segment size.  */
116     socket_ptr -> nx_tcp_socket_connect_mss =  NX_TCP_MSS_SIZE;
117 
118     /* Save the type of service input parameter.  */
119     socket_ptr -> nx_tcp_socket_type_of_service =  type_of_service;
120 
121     /* Save the fragment input parameter.  */
122     socket_ptr -> nx_tcp_socket_fragment_enable =  fragment & NX_DONT_FRAGMENT;
123 
124     /* Save the time-to-live input parameter.  */
125     socket_ptr -> nx_tcp_socket_time_to_live =  time_to_live;
126 
127     /* Clear the socket bind in progress flag.  */
128     socket_ptr -> nx_tcp_socket_bind_in_progress =  NX_FALSE;
129 
130     /* Setup the delayed ACK timeout periodic rate.  */
131     socket_ptr -> nx_tcp_socket_delayed_ack_timeout =  _nx_tcp_ack_timer_rate;
132 
133     /* Setup the default transmit timeout.  */
134     socket_ptr -> nx_tcp_socket_timeout_rate =         _nx_tcp_transmit_timer_rate;
135     socket_ptr -> nx_tcp_socket_timeout_max_retries =  NX_TCP_MAXIMUM_RETRIES;
136     socket_ptr -> nx_tcp_socket_timeout_shift =        NX_TCP_RETRY_SHIFT;
137 
138     /* Setup the default maximum transmit queue depth.  */
139     socket_ptr -> nx_tcp_socket_transmit_queue_maximum_default =  NX_TCP_MAXIMUM_TX_QUEUE;
140     socket_ptr -> nx_tcp_socket_transmit_queue_maximum =          NX_TCP_MAXIMUM_TX_QUEUE;
141 
142 #ifdef NX_ENABLE_LOW_WATERMARK
143     /* Setup the default maximum receive queue depth.  */
144     socket_ptr -> nx_tcp_socket_receive_queue_maximum = NX_TCP_MAXIMUM_RX_QUEUE;
145 #endif /* NX_ENABLE_LOW_WATERMARK */
146 
147 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
148 
149     /* Window scaling feature is enabled.  Record this user-specified window size. */
150     socket_ptr -> nx_tcp_socket_rx_window_maximum = window_size;
151 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
152 
153     /* Setup the sliding window information.  */
154     socket_ptr -> nx_tcp_socket_rx_window_default =   window_size;
155     socket_ptr -> nx_tcp_socket_rx_window_current =   window_size;
156     socket_ptr -> nx_tcp_socket_tx_outstanding_bytes = 0;
157     socket_ptr -> nx_tcp_socket_tx_window_advertised = 0;
158     socket_ptr -> nx_tcp_socket_tx_window_congestion = 0;
159 
160 
161     /* Initialize the ack_n_packet counter. */
162     socket_ptr -> nx_tcp_socket_ack_n_packet_counter = 1;
163 
164     /* Save the application callback routines.  */
165     socket_ptr -> nx_tcp_urgent_data_callback = tcp_urgent_data_callback;
166     socket_ptr -> nx_tcp_disconnect_callback =  tcp_disconnect_callback;
167 
168     /* Clear the receive notify function pointer.  */
169     socket_ptr -> nx_tcp_receive_callback =  NX_NULL;
170 
171 #ifdef NX_ENABLE_TCP_KEEPALIVE
172     /* If the Keep alive feature is enabled in NetX, enable it
173        on all TCP sockets. */
174     socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_TRUE;
175 
176 #endif
177 
178     /* If trace is enabled, insert this event into the trace buffer.  */
179     NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_CLOSED, NX_TRACE_INTERNAL_EVENTS, 0, 0);
180 
181     /* Setup the initial TCP socket state.  */
182     socket_ptr -> nx_tcp_socket_state =  NX_TCP_CLOSED;
183 
184     /* If trace is enabled, register this object.  */
185     NX_TRACE_OBJECT_REGISTER(NX_TRACE_OBJECT_TYPE_TCP_SOCKET, socket_ptr, name, type_of_service, window_size);
186 
187     /* If trace is enabled, insert this event into the trace buffer.  */
188     NX_TRACE_IN_LINE_INSERT(NX_TRACE_TCP_SOCKET_CREATE, ip_ptr, socket_ptr, type_of_service, window_size, NX_TRACE_TCP_EVENTS, 0, 0);
189 
190     /* Get protection while we insert the TCP socket into the created list.  */
191     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
192 
193     /* Disable interrupts while we link the new TCP socket to the IP structure.  */
194     TX_DISABLE
195 
196     /* Load the TCP ID field in the TCP control block.  */
197     socket_ptr -> nx_tcp_socket_id =  NX_TCP_ID;
198 
199     /* Place the new TCP control block on the list of created TCP sockets for this IP.  First,
200        check for an empty list.  */
201     if (ip_ptr -> nx_ip_tcp_created_sockets_ptr)
202     {
203 
204         /* Pickup tail pointer.  */
205         tail_ptr =  (ip_ptr -> nx_ip_tcp_created_sockets_ptr) -> nx_tcp_socket_created_previous;
206 
207         /* Place the new TCP socket control block in the list.  */
208         (ip_ptr -> nx_ip_tcp_created_sockets_ptr) -> nx_tcp_socket_created_previous =  socket_ptr;
209         tail_ptr ->  nx_tcp_socket_created_next =  socket_ptr;
210 
211         /* Setup this TCP socket's created links.  */
212         socket_ptr -> nx_tcp_socket_created_previous =  tail_ptr;
213         socket_ptr -> nx_tcp_socket_created_next =      ip_ptr -> nx_ip_tcp_created_sockets_ptr;
214     }
215     else
216     {
217 
218         /* The created TCP socket list is empty.  Add TCP socket control block to empty list.  */
219         ip_ptr -> nx_ip_tcp_created_sockets_ptr =       socket_ptr;
220         socket_ptr -> nx_tcp_socket_created_previous =  socket_ptr;
221         socket_ptr -> nx_tcp_socket_created_next =      socket_ptr;
222     }
223 
224     /* Increment the created TCP socket counter.  */
225     ip_ptr -> nx_ip_tcp_created_sockets_count++;
226 
227 #ifdef FEATURE_NX_IPV6
228     socket_ptr -> nx_tcp_socket_ipv6_addr   =             NX_NULL;
229 #endif /* FEATURE_NX_IPV6 */
230 
231 
232 #ifdef NX_IPSEC_ENABLE
233     socket_ptr -> nx_tcp_socket_egress_sa = NX_NULL;
234     socket_ptr -> nx_tcp_socket_egress_sa_data_offset = 0;
235 #endif /* NX_IPSEC_ENABLE */
236     /* Restore previous interrupt posture.  */
237     TX_RESTORE
238 
239     /* Release protection.  */
240     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
241 
242     /* Return successful completion.  */
243     return(NX_SUCCESS);
244 }
245 
246