1 /* This case tests websocket delete corresponding logic. Also pay attention
2 on the influence brought by the disconnecting state on other functions */
3 #include "tx_api.h"
4 #include "nx_api.h"
5
6 extern void test_control_return(UINT);
7
8 #if !defined(NX_DISABLE_IPV4) && defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_PACKET_CHAIN)
9 #include "nx_websocket_client.h"
10 #include "netx_websocket_common_process.c"
11
12 #define DEMO_STACK_SIZE 4096
13 #define PACKET_SIZE 1536
14 #define TOTAL_SIZE DEMO_STACK_SIZE + (PACKET_SIZE * 8) + 2048 + 1024
15
16 /* Define device drivers. */
17 extern void _nx_ram_network_driver_1024(NX_IP_DRIVER *driver_req_ptr);
18
19 static UINT test_done = NX_FALSE;
20
21 static TX_THREAD client_thread;
22 static NX_PACKET_POOL client_pool;
23 static NX_TCP_SOCKET test_client;
24 static NX_IP client_ip;
25
26 static NX_TCP_SOCKET test_server;
27 static NX_PACKET_POOL server_pool;
28 static TX_THREAD server_thread;
29 static NX_IP server_ip;
30 static UINT test_server_start = 0;
31 static UINT test_client_stop = 0;
32
33 /* Set up the websocket global variables */
34 static NX_WEBSOCKET_CLIENT client_websocket;
35 static UCHAR *client_websocket_host;
36 static UINT client_websocket_host_length;
37 static UCHAR *client_websocket_uri_path;
38 static UINT client_websocket_uri_path_length;
39
40
41 static void thread_client_entry(ULONG thread_input);
42 static void thread_server_entry(ULONG thread_input);
43
44 #define TEST_SERVER_ADDRESS IP_ADDRESS(1,2,3,4)
45 #define TEST_CLIENT_ADDRESS IP_ADDRESS(1,2,3,5)
46 #define TEST_SERVER_PORT 80
47
48 #define TEST_HOST_NAME "1.2.3.4"
49 #define TEST_URI_PATH "/test"
50 #define TEST_PROTOCOL "test"
51
52 static UCHAR server_switch_101[] =
53 {
54 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x20, // HTTP1.1/
55 0x31, 0x30, 0x31, 0x20, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, // 101 Switching
56 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x0d, 0x0a, // Protocols\r\n
57 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, // Upgrade:
58 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, // WebSocket\r\n
59 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, // Connection:
60 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, // Upgrade\r\n
61 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, // Sec-WebSocket-Protocol:
62 0x74, 0x2d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x3a, 0x20,
63 0x74, 0x65, 0x73, 0x74, 0x0d, 0x0a, // test
64 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, // Sec-WebSocket-Accept:
65 0x65, 0x74, 0x2d, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
66 0x35, 0x75, 0x31, 0x6c, 0x55, 0x72, 0x32, 0x57, 0x68, 0x70, 0x34, 0x64, 0x44, 0x57, 0x6e, // 5u1lUr2Whp4dDWnskk9JcJZobO0=
67 0x73, 0x6b, 0x6b, 0x39, 0x4a, 0x63, 0x4a, 0x5a, 0x6f, 0x62, 0x4f, 0x30, 0x3d, 0x0d, 0x0a,
68 0x0d, 0x0a,
69 };
70
71 static UCHAR server_response[] =
72 {
73 0x82, 0x04, 0x01, 0x02, 0x03, 0x04,
74 0x82, 0x04, 0x01, 0x02, 0x03, 0x04, // The second frame will be on the processing packet list
75 };
76
77 static UCHAR client_test_data[] =
78 {
79 0x11, 0x22, 0x33, 0x44,
80 };
81
82 static ULONG error_counter;
83
84 extern void SET_ERROR_COUNTER(ULONG *error_counter, CHAR *filename, int line_number);
85
86 #define TEST_LOOP 2
87
88 #ifdef CTEST
test_application_define(void * first_unused_memory)89 VOID test_application_define(void *first_unused_memory)
90 #else
91 void netx_websocket_delete_test_application_define(void *first_unused_memory)
92 #endif
93 {
94 CHAR *pointer;
95 UINT status;
96
97
98 error_counter = 0;
99
100 /* Setup the working pointer. */
101 pointer = (CHAR *) first_unused_memory;
102
103 /* Create a helper thread for the server. */
104 tx_thread_create(&server_thread, "Test Server thread", thread_server_entry, 0,
105 pointer, DEMO_STACK_SIZE,
106 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
107
108 pointer = pointer + DEMO_STACK_SIZE;
109
110 /* Initialize the NetX system. */
111 nx_system_initialize();
112
113 /* Create the server packet pool. */
114 status = nx_packet_pool_create(&server_pool, "Test Server Packet Pool", PACKET_SIZE,
115 pointer, PACKET_SIZE * 8);
116 pointer = pointer + PACKET_SIZE * 8;
117 if (status)
118 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
119
120 /* Create an IP instance. */
121 status = nx_ip_create(&server_ip, "Test Server IP", TEST_SERVER_ADDRESS,
122 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024,
123 pointer, 2048, 1);
124 pointer = pointer + 2048;
125 if (status)
126 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
127
128 /* Enable ARP and supply ARP cache memory for the server IP instance. */
129 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
130 pointer = pointer + 1024;
131 if (status)
132 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
133
134 /* Enable TCP traffic. */
135 status = nx_tcp_enable(&server_ip);
136 if (status)
137 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
138
139 /* Create the Test Client thread. */
140 status = tx_thread_create(&client_thread, "Test Client", thread_client_entry, 0,
141 pointer, DEMO_STACK_SIZE,
142 6, 6, TX_NO_TIME_SLICE, TX_AUTO_START);
143 pointer = pointer + DEMO_STACK_SIZE;
144 if (status)
145 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
146
147 /* Create the Client packet pool. */
148 status = nx_packet_pool_create(&client_pool, "Test Client Packet Pool", PACKET_SIZE,
149 pointer, PACKET_SIZE * 8);
150 pointer = pointer + PACKET_SIZE * 8;
151 if (status)
152 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
153
154 /* Create an IP instance. */
155 status = nx_ip_create(&client_ip, "Test Client IP", TEST_CLIENT_ADDRESS,
156 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1024,
157 pointer, 2048, 1);
158 pointer = pointer + 2048;
159 if (status)
160 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
161
162 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
163 pointer = pointer + 1024;
164 if (status)
165 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
166
167 /* Enable TCP traffic. */
168 status = nx_tcp_enable(&client_ip);
169 if (status)
170 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
171 }
172
thread_client_entry(ULONG thread_input)173 void thread_client_entry(ULONG thread_input)
174 {
175 UINT i, status;
176 NX_PACKET *packet_ptr;
177 NX_PACKET *packet_ptr1;
178 NXD_ADDRESS server_ip_address;
179 UINT code;
180
181 /* Create client socket. */
182 status = nx_tcp_socket_create(&client_ip, &test_client, "Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY,
183 NX_IP_TIME_TO_LIVE, 1000, NX_NULL, NX_NULL);
184 if (status)
185 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
186
187 /* This test is significant only when is error checking is enabled */
188 #ifndef NX_DISABLE_ERROR_CHECKING
189 status = nx_websocket_client_delete(&client_websocket);
190 if (status != NX_PTR_ERROR || client_websocket.nx_websocket_client_mutex.tx_mutex_ownership_count != 0)
191 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
192 #endif /* NX_DISABLE_ERROR_CHECKING */
193
194 /* Create WebSocket. */
195 status = nx_websocket_client_create(&client_websocket, (UCHAR *)" ", &client_ip, &client_pool);
196
197 /* Check status. */
198 if (status)
199 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
200
201 /* Give IP task and driver a chance to initialize the system. */
202 tx_thread_sleep(NX_IP_PERIODIC_RATE);
203
204 /* Bind and connect to server. */
205 status = nx_tcp_client_socket_bind(&test_client, TEST_SERVER_PORT, NX_IP_PERIODIC_RATE);
206 if (status)
207 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
208
209 /* Wait test server started. */
210 while(!test_server_start)
211 {
212 tx_thread_sleep(NX_IP_PERIODIC_RATE);
213 }
214
215 /* Set server IP address. */
216 server_ip_address.nxd_ip_address.v4 = TEST_SERVER_ADDRESS;
217 server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
218
219 /* Connect to the server */
220 status = nxd_tcp_client_socket_connect(&test_client, &server_ip_address, TEST_SERVER_PORT, NX_WAIT_FOREVER);
221 if (status)
222 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
223
224 /* Upgrade to websocket */
225 status = nx_websocket_client_connect(&client_websocket, &test_client,
226 TEST_HOST_NAME, sizeof(TEST_HOST_NAME) - 1,
227 (UCHAR *)TEST_URI_PATH, sizeof(TEST_URI_PATH) - 1,
228 (UCHAR *)TEST_PROTOCOL, sizeof(TEST_PROTOCOL) - 1,
229 NX_WAIT_FOREVER);
230
231 if (status)
232 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
233 else
234 {
235 status = nx_packet_allocate(&client_pool, &packet_ptr, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
236 if (status)
237 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
238
239 /* Append and send data. */
240 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
241 packet_ptr -> nx_packet_length = 0;
242 status = nx_packet_data_append(packet_ptr, client_test_data, sizeof(client_test_data), &client_pool, NX_IP_PERIODIC_RATE);
243 if (status)
244 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
245 status = nx_websocket_client_send(&client_websocket, packet_ptr, NX_WEBSOCKET_OPCODE_BINARY_FRAME, NX_TRUE, NX_WAIT_FOREVER);
246 if (status)
247 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
248
249 /* Only receive and parse the first frame from server. */
250 status = nx_websocket_client_receive(&client_websocket, &packet_ptr, &code, NX_NO_WAIT);
251 if (status)
252 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
253 if (packet_ptr -> nx_packet_length != 4)
254 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
255 nx_packet_release(packet_ptr);
256
257 /* Test the delete function which shall clean up unused resources */
258 status = nx_websocket_client_delete(&client_websocket);
259 if (status || client_websocket.nx_websocket_client_mutex.tx_mutex_ownership_count != 0)
260 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
261 /* The waiting list shall be empty after calling delete */
262 if (client_websocket.nx_websocket_client_processing_packet != NX_NULL)
263 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
264 }
265
266 nx_tcp_client_socket_unbind(&test_client);
267 nx_tcp_socket_delete(&test_client);
268
269 test_done = NX_TRUE;
270 }
271
272 /* Define the helper Test server thread. */
thread_server_entry(ULONG thread_input)273 void thread_server_entry(ULONG thread_input)
274 {
275 UINT i, status;
276 NX_PACKET *packet_ptr;
277
278
279 /* Print out test information banner. */
280 printf("NetX Test: Websocket Delete Test.....................................");
281
282 /* Check for earlier error. */
283 if (error_counter)
284 {
285 printf("ERROR!\n");
286 test_control_return(1);
287 }
288
289 /* Give NetX a chance to initialize the system. */
290 tx_thread_sleep(NX_IP_PERIODIC_RATE);
291
292 status = nx_tcp_socket_create(&server_ip, &test_server, "Test Server Socket",
293 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 1000,
294 NX_NULL, NX_NULL);
295
296 status = nx_tcp_server_socket_listen(&server_ip, TEST_SERVER_PORT, &test_server, 5, NX_NULL);
297 if (status)
298 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
299
300 /* Set the flag. */
301 test_server_start = 1;
302
303 /* Accept a connection from test client. */
304 status = nx_tcp_server_socket_accept(&test_server, 5 * NX_IP_PERIODIC_RATE);
305 if (status)
306 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
307
308 for (i = 0; i < TEST_LOOP; i++)
309 {
310 /* Receive client data. */
311 status = nx_tcp_socket_receive(&test_server, &packet_ptr, 5 * NX_IP_PERIODIC_RATE);
312 if (status)
313 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
314 else
315 {
316 /* Response data. */
317 switch (i)
318 {
319 case 0:
320 /* Update the value in the field Sec-Protocol-Accept since it is calculated based on a random value */
321 _server_connect_response_process(packet_ptr);
322 memcpy(&server_switch_101[127], connect_key, 28);
323
324 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
325 packet_ptr -> nx_packet_length = 0;
326 nx_packet_data_append(packet_ptr, server_switch_101, sizeof(server_switch_101), &server_pool, NX_IP_PERIODIC_RATE);
327 status = nx_tcp_socket_send(&test_server, packet_ptr, NX_IP_PERIODIC_RATE);
328 if (status)
329 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
330 break;
331 case 1:
332 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
333 packet_ptr -> nx_packet_length = 0;
334 nx_packet_data_append(packet_ptr, server_response, sizeof(server_response), &server_pool, NX_IP_PERIODIC_RATE);
335 status = nx_tcp_socket_send(&test_server, packet_ptr, NX_IP_PERIODIC_RATE);
336 if (status)
337 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
338 break;
339 default:
340 break;
341 }
342 }
343 }
344
345 /* Wait for test done. */
346 while (test_done == NX_FALSE)
347 {
348 tx_thread_sleep(NX_IP_PERIODIC_RATE);
349 }
350
351 nx_tcp_server_socket_unlisten(&server_ip, TEST_SERVER_PORT);
352 nx_tcp_socket_delete(&test_server);
353
354 if (client_pool.nx_packet_pool_available != client_pool.nx_packet_pool_total)
355 {
356 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
357 }
358 else if (client_pool.nx_packet_pool_invalid_releases)
359 {
360 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
361 }
362
363 if (server_pool.nx_packet_pool_available != server_pool.nx_packet_pool_total)
364 {
365 SET_ERROR_COUNTER(&error_counter, __FILE__, __LINE__);
366 }
367
368 if (error_counter)
369 {
370 printf("ERROR!\n");
371 test_control_return(1);
372 }
373 else
374 {
375 printf("SUCCESS!\n");
376 test_control_return(0);
377 }
378 }
379
380 #else
381
382 #ifdef CTEST
test_application_define(void * first_unused_memory)383 VOID test_application_define(void *first_unused_memory)
384 #else
385 void netx_websocket_delete_test_application_define(void *first_unused_memory)
386 #endif
387 {
388
389 /* Print out test information banner. */
390 printf("NetX Test: Websocket Delete Test.....................................N/A\n");
391
392 test_control_return(3);
393 }
394 #endif
395
396