1 /* This case tests HTTP/1.1 server establish a persistent connection with a HTTP/1.1 client. */
2 #include "tx_api.h"
3 #include "nx_api.h"
4 #include "fx_api.h"
5 #include "nx_web_http_client.h"
6 #include "nx_web_http_server.h"
7
8 extern void test_control_return(UINT);
9
10 #if !defined(NX_DISABLE_IPV4) && !defined(NX_WEB_HTTP_KEEPALIVE_DISABLE)
11
12 #include "test_device_cert.c"
13 #include "test_ca_cert.c"
14 #define ca_cert_der test_ca_cert_der
15 #define ca_cert_der_len test_ca_cert_der_len
16
17 #define DEMO_STACK_SIZE 4096
18
19 /* Set up FileX and file memory resources. */
20 static CHAR ram_disk_memory[4096];
21 static FX_MEDIA ram_disk;
22 static UCHAR media_memory[4096];
23
24 static UCHAR server_stack[16000];
25
26 /* Define device drivers. */
27 extern void _fx_ram_driver(FX_MEDIA *media_ptr);
28 extern void _nx_ram_network_driver_1024(NX_IP_DRIVER *driver_req_ptr);
29
30 /* Set up the HTTP client global variables. */
31
32 #define CLIENT_PACKET_SIZE (NX_WEB_HTTP_CLIENT_MIN_PACKET_SIZE * 2)
33
34 static TX_THREAD client_thread;
35 static NX_PACKET_POOL client_pool;
36 static NX_WEB_HTTP_CLIENT my_client;
37 static NX_IP client_ip;
38 static UINT error_counter;
39
40 /* Set up the HTTP server global variables */
41
42 #define SERVER_PACKET_SIZE (NX_WEB_HTTP_SERVER_MIN_PACKET_SIZE * 2)
43
44 static NX_WEB_HTTP_SERVER my_server;
45 static NX_PACKET_POOL server_pool;
46 static TX_THREAD server_thread;
47 static NX_IP server_ip;
48 static NXD_ADDRESS server_ip_address;
49 static UINT http_server_start = 0;
50 static UINT http_client_stop = 0;
51
52 static void thread_client_entry(ULONG thread_input);
53 static void thread_server_entry(ULONG thread_input);
54
55 #define HTTP_SERVER_ADDRESS IP_ADDRESS(1,2,3,4)
56 #define HTTP_CLIENT_ADDRESS IP_ADDRESS(1,2,3,5)
57
58 #ifdef NX_WEB_HTTPS_ENABLE
59 static UINT https_server_start = 0;
60 static UINT https_client_stop = 0;
61 static UINT loop = 2;
62 extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;
63 static CHAR crypto_metadata_server[20000 * NX_WEB_HTTP_SERVER_SESSION_MAX];
64 static CHAR crypto_metadata_client[20000 * NX_WEB_HTTP_SERVER_SESSION_MAX];
65 static UCHAR tls_packet_buffer[18500];
66 static NX_SECURE_X509_CERT certificate;
67 static NX_SECURE_X509_CERT trusted_certificate;
68 static NX_SECURE_X509_CERT remote_certificate, remote_issuer;
69 static UCHAR remote_cert_buffer[2000];
70 static UCHAR remote_issuer_buffer[2000];
71 #else
72 static UINT loop = 1;
73 #endif /* NX_WEB_HTTPS_ENABLE */
74
75 static UINT test_count;
76
77 #ifdef CTEST
test_application_define(void * first_unused_memory)78 VOID test_application_define(void *first_unused_memory)
79 #else
80 void netx_web_keep_alive_abnormal_test_application_define(void *first_unused_memory)
81 #endif
82 {
83 CHAR *pointer;
84 UINT status;
85
86
87 error_counter = 0;
88
89 /* Setup the working pointer. */
90 pointer = (CHAR *) first_unused_memory;
91
92 /* Create a helper thread for the server. */
93 tx_thread_create(&server_thread, "HTTP Server thread", thread_server_entry, 0,
94 pointer, DEMO_STACK_SIZE,
95 NX_WEB_HTTP_SERVER_PRIORITY, NX_WEB_HTTP_SERVER_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);
96
97 pointer = pointer + DEMO_STACK_SIZE;
98
99 /* Initialize the NetX system. */
100 nx_system_initialize();
101
102 /* Create the server packet pool. */
103 status = nx_packet_pool_create(&server_pool, "HTTP Server Packet Pool", SERVER_PACKET_SIZE,
104 pointer, SERVER_PACKET_SIZE*8);
105 pointer = pointer + SERVER_PACKET_SIZE * 8;
106 if (status)
107 error_counter++;
108
109 /* Create an IP instance. */
110 status = nx_ip_create(&server_ip, "HTTP Server IP", HTTP_SERVER_ADDRESS,
111 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024,
112 pointer, 4096, 1);
113 pointer = pointer + 4096;
114 if (status)
115 error_counter++;
116
117 /* Enable ARP and supply ARP cache memory for the server IP instance. */
118 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
119 pointer = pointer + 1024;
120 if (status)
121 error_counter++;
122
123
124 /* Enable TCP traffic. */
125 status = nx_tcp_enable(&server_ip);
126 if (status)
127 error_counter++;
128
129 /* Create the HTTP Client thread. */
130 status = tx_thread_create(&client_thread, "HTTP Client", thread_client_entry, 0,
131 pointer, DEMO_STACK_SIZE,
132 NX_WEB_HTTP_SERVER_PRIORITY + 2, NX_WEB_HTTP_SERVER_PRIORITY + 2, TX_NO_TIME_SLICE, TX_AUTO_START);
133 pointer = pointer + DEMO_STACK_SIZE;
134 if (status)
135 error_counter++;
136
137 /* Create the Client packet pool. */
138 status = nx_packet_pool_create(&client_pool, "HTTP Client Packet Pool", CLIENT_PACKET_SIZE,
139 pointer, CLIENT_PACKET_SIZE*8);
140 pointer = pointer + CLIENT_PACKET_SIZE * 8;
141 if (status)
142 error_counter++;
143
144 /* Create an IP instance. */
145 status = nx_ip_create(&client_ip, "HTTP Client IP", HTTP_CLIENT_ADDRESS,
146 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1024,
147 pointer, 2048, 1);
148 pointer = pointer + 2048;
149 if (status)
150 error_counter++;
151
152 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
153 pointer = pointer + 2048;
154 if (status)
155 error_counter++;
156
157 /* Enable TCP traffic. */
158 status = nx_tcp_enable(&client_ip);
159 if (status)
160 error_counter++;
161 }
162
163 #ifdef NX_WEB_HTTPS_ENABLE
164 /* Define the TLS setup callback function. */
tls_setup_callback(NX_WEB_HTTP_CLIENT * client_ptr,NX_SECURE_TLS_SESSION * tls_session)165 static UINT tls_setup_callback(NX_WEB_HTTP_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session)
166 {
167 UINT status;
168
169
170 /* Initialize and create TLS session. */
171 status = nx_secure_tls_session_create(tls_session, &nx_crypto_tls_ciphers, crypto_metadata_client, sizeof(crypto_metadata_client));
172
173 /* Check status. */
174 if (status)
175 {
176 return(status);
177 }
178
179 /* Allocate space for packet reassembly. */
180 status = nx_secure_tls_session_packet_buffer_set(&(client_ptr -> nx_web_http_client_tls_session), tls_packet_buffer, sizeof(tls_packet_buffer));
181
182 /* Check status. */
183 if (status)
184 {
185 return(status);
186 }
187
188 /* Add a CA Certificate to our trusted store for verifying incoming server certificates. */
189 nx_secure_x509_certificate_initialize(&trusted_certificate, ca_cert_der, ca_cert_der_len, NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE);
190 nx_secure_tls_trusted_certificate_add(&(client_ptr -> nx_web_http_client_tls_session), &trusted_certificate);
191
192 /* Need to allocate space for the certificate coming in from the remote host. */
193 nx_secure_tls_remote_certificate_allocate(&(client_ptr -> nx_web_http_client_tls_session), &remote_certificate, remote_cert_buffer, sizeof(remote_cert_buffer));
194 nx_secure_tls_remote_certificate_allocate(&(client_ptr -> nx_web_http_client_tls_session), &remote_issuer, remote_issuer_buffer, sizeof(remote_issuer_buffer));
195
196 return(NX_SUCCESS);
197 }
198 #endif /* NX_WEB_HTTPS_ENABLE */
199
thread_client_entry(ULONG thread_input)200 void thread_client_entry(ULONG thread_input)
201 {
202 UINT i;
203 UINT status;
204 NX_PACKET *recv_packet;
205
206
207 /* Give IP task and driver a chance to initialize the system. */
208 tx_thread_sleep(NX_IP_PERIODIC_RATE);
209
210 /* Set server IP address. */
211 server_ip_address.nxd_ip_address.v4 = HTTP_SERVER_ADDRESS;
212 server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
213
214 /* First loop test HTTP, second loop test HTTPS. */
215 for (i = 0; i < loop ; i++)
216 {
217 if (i == 0)
218 {
219
220 /* Wait HTTP server started. */
221 while(!http_server_start)
222 {
223 tx_thread_sleep(NX_IP_PERIODIC_RATE);
224 }
225 }
226 #ifdef NX_WEB_HTTPS_ENABLE
227 else
228 {
229
230 /* Wait HTTPS server started. */
231 while(!https_server_start)
232 {
233 tx_thread_sleep(NX_IP_PERIODIC_RATE);
234 }
235 }
236 #endif /* NX_WEB_HTTPS_ENABLE */
237
238 /* Create an HTTP client instance. */
239 status = nx_web_http_client_create(&my_client, "HTTP Client", &client_ip, &client_pool, 1536);
240
241 /* Check status. */
242 if (status)
243 error_counter++;
244
245 for (test_count = 0; test_count < 2; test_count++)
246 {
247
248 /* Server disconnect the connection. */
249 if (test_count == 1)
250 {
251 nx_tcp_socket_disconnect(&(my_server.nx_web_http_server_current_session_ptr -> nx_tcp_session_socket), NX_NO_WAIT);
252 }
253
254 /* Connect to server. */
255 if (i == 0)
256 {
257 status = nx_web_http_client_connect(&my_client, &server_ip_address, NX_WEB_HTTP_SERVER_PORT, NX_WAIT_FOREVER);
258
259 /* Check status. */
260 if (status)
261 error_counter++;
262 }
263 #ifdef NX_WEB_HTTPS_ENABLE
264 else
265 {
266 status = nx_web_http_client_secure_connect(&my_client, &server_ip_address, NX_WEB_HTTPS_SERVER_PORT,
267 tls_setup_callback, NX_WAIT_FOREVER);
268
269 /* Check status. */
270 if (status)
271 error_counter++;
272 }
273 #endif /* NX_WEB_HTTPS_ENABLE */
274
275 /* Initialize HTTP request. */
276 status = nx_web_http_client_request_initialize(&my_client,
277 NX_WEB_HTTP_METHOD_GET,
278 "/index.htm",
279 "www.abc.com",
280 0,
281 NX_FALSE,
282 NX_NULL,
283 NX_NULL,
284 1 * NX_IP_PERIODIC_RATE);
285
286 /* For HTTPS, if the connection is closed, the initialization should be failed. */
287 if (status)
288 {
289 error_counter++;
290 break;
291 }
292
293 /* Send GET with "connection: keep-alive", the connection should be kept alive. */
294 status = nx_web_http_client_request_header_add(&my_client, "Connection", 10, "keep-alive", 10, 1 * NX_IP_PERIODIC_RATE);
295
296 if (status)
297 error_counter++;
298
299 /* Send the request. */
300 status = nx_web_http_client_request_send(&my_client, 1 * NX_IP_PERIODIC_RATE);
301
302 if (status)
303 {
304 error_counter++;
305 break;
306 }
307
308 /* Get the response from server. */
309 while(1)
310 {
311 status = nx_web_http_client_response_body_get(&my_client, &recv_packet, 1 * NX_IP_PERIODIC_RATE);
312
313 if (status)
314 break;
315 else
316 nx_packet_release(recv_packet);
317 }
318
319 /* Check the status. */
320 if (status != NX_WEB_HTTP_GET_DONE)
321 error_counter++;
322 else
323 nx_packet_release(recv_packet);
324 }
325
326 /* Delele the client. */
327 status = nx_web_http_client_delete(&my_client);
328 if (status)
329 error_counter++;
330
331 /* Set the flag. */
332 if (i == 0)
333 {
334 http_client_stop = 1;
335 }
336 #ifdef NX_WEB_HTTPS_ENABLE
337 else
338 {
339 https_client_stop = 1;
340 }
341 #endif /* NX_WEB_HTTPS_ENABLE */
342 }
343 }
344
345 /* Define the helper HTTP server thread. */
thread_server_entry(ULONG thread_input)346 void thread_server_entry(ULONG thread_input)
347 {
348 UINT i;
349 UINT status;
350 FX_FILE my_file;
351 UINT server_port = NX_WEB_HTTP_SERVER_PORT;
352
353
354 /* Print out test information banner. */
355 printf("NetX Test: Web Keep Alive Abnormal Test..............................");
356
357 /* Check for earlier error. */
358 if(error_counter)
359 {
360 printf("ERROR!\n");
361 test_control_return(1);
362 }
363
364 fx_media_format(&ram_disk,
365 _fx_ram_driver, // Driver entry
366 ram_disk_memory, // RAM disk memory pointer
367 media_memory, // Media buffer pointer
368 sizeof(media_memory), // Media buffer size
369 "MY_RAM_DISK", // Volume Name
370 1, // Number of FATs
371 32, // Directory Entries
372 0, // Hidden sectors
373 256, // Total sectors
374 512, // Sector size
375 8, // Sectors per cluster
376 1, // Heads
377 1); // Sectors per track
378
379 /* Open the RAM disk. */
380 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, media_memory, sizeof(media_memory)) ;
381 status += fx_file_create(&ram_disk, "index.htm");
382 status += fx_file_open(&ram_disk, &my_file, "index.htm", FX_OPEN_FOR_WRITE);
383 status += fx_file_write(&my_file, "https server", 12);
384 status += fx_file_close(&my_file);
385 if(status)
386 error_counter++;
387
388 /* Give NetX a chance to initialize the system. */
389 tx_thread_sleep(NX_IP_PERIODIC_RATE);
390
391 /* First loop test HTTP, second loop test HTTPS. */
392 for (i = 0; i < loop; i++)
393 {
394
395 if (i == 1)
396 {
397 server_port = NX_WEB_HTTPS_SERVER_PORT;
398 }
399
400 /* Create the HTTP Server. */
401 status = nx_web_http_server_create(&my_server, "My HTTP Server", &server_ip, server_port, &ram_disk,
402 &server_stack, sizeof(server_stack), &server_pool,
403 NX_NULL, NX_NULL);
404 if (status)
405 error_counter++;
406
407 #ifdef NX_WEB_HTTPS_ENABLE
408 /* Set TLS for HTTPS. */
409 if (i == 1)
410 {
411 /* Initialize device certificate (used for all sessions in HTTPS server). */
412 memset(&certificate, 0, sizeof(certificate));
413 nx_secure_x509_certificate_initialize(&certificate, test_device_cert_der, test_device_cert_der_len, NX_NULL, 0, test_device_cert_key_der, test_device_cert_key_der_len, NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
414
415 /* Setup TLS session data for the TCP server. */
416 status = nx_web_http_server_secure_configure(&my_server, &nx_crypto_tls_ciphers,
417 crypto_metadata_server, sizeof(crypto_metadata_server), tls_packet_buffer, sizeof(tls_packet_buffer),
418 &certificate, NX_NULL, 0, NX_NULL, 0, NX_NULL, 0);
419 if (status)
420 error_counter++;
421 }
422 #endif /* NX_WEB_HTTPS_ENABLE */
423
424 /* OK to start the HTTP Server. */
425 status = nx_web_http_server_start(&my_server);
426 if (status)
427 error_counter++;
428
429 /* Set the flag. */
430 if (i == 0)
431 {
432 http_server_start = 1;
433
434 /* Wait HTTP test finished. */
435 while(!http_client_stop)
436 {
437 tx_thread_sleep(NX_IP_PERIODIC_RATE);
438 }
439 }
440 #ifdef NX_WEB_HTTPS_ENABLE
441 else
442 {
443 https_server_start = 1;
444
445 /* Wait HTTPS test finished. */
446 while(!https_client_stop)
447 {
448 tx_thread_sleep(NX_IP_PERIODIC_RATE);
449 }
450 }
451 #endif /* NX_WEB_HTTPS_ENABLE */
452
453 status = nx_web_http_server_delete(&my_server);
454 if (status)
455 error_counter++;
456 }
457
458 /* Check packet pool. */
459 if (server_pool.nx_packet_pool_available != server_pool.nx_packet_pool_total)
460 {
461 error_counter++;
462 }
463
464 if (client_pool.nx_packet_pool_available != client_pool.nx_packet_pool_total)
465 {
466 error_counter++;
467 }
468
469 if(error_counter)
470 {
471 printf("ERROR!\n");
472 test_control_return(1);
473 }
474 else
475 {
476 printf("SUCCESS!\n");
477 test_control_return(0);
478 }
479 }
480 #else
481
482 #ifdef CTEST
test_application_define(void * first_unused_memory)483 VOID test_application_define(void *first_unused_memory)
484 #else
485 void netx_web_keep_alive_abnormal_test_application_define(void *first_unused_memory)
486 #endif
487 {
488
489 /* Print out test information banner. */
490 printf("NetX Test: Web Keep Alive Abnormal Test..............................N/A\n");
491
492 test_control_return(3);
493 }
494 #endif
495
496