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