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