1 /* This case tests server getting content. */
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_DISABLE_PACKET_CHAIN)
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 authentication_check(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
76 CHAR *resource, CHAR **name, CHAR **password, CHAR **realm);
77 static UINT server_request_callback(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr);
78
79 static UINT test_count;
80
81 /* POST AAAAAAAAAA*/
82 static char pkt[] = {
83 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 /* AAAAAAAAAA */
84 };
85
86 #ifdef CTEST
test_application_define(void * first_unused_memory)87 VOID test_application_define(void *first_unused_memory)
88 #else
89 void netx_web_server_content_process_test_application_define(void *first_unused_memory)
90 #endif
91 {
92 CHAR *pointer;
93 UINT status;
94
95
96 error_counter = 0;
97
98 /* Setup the working pointer. */
99 pointer = (CHAR *) first_unused_memory;
100
101 /* Create a helper thread for the server. */
102 tx_thread_create(&server_thread, "HTTP Server thread", thread_server_entry, 0,
103 pointer, DEMO_STACK_SIZE,
104 NX_WEB_HTTP_SERVER_PRIORITY, NX_WEB_HTTP_SERVER_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);
105
106 pointer = pointer + DEMO_STACK_SIZE;
107
108 /* Initialize the NetX system. */
109 nx_system_initialize();
110
111 /* Create the server packet pool. */
112 status = nx_packet_pool_create(&server_pool, "HTTP Server Packet Pool", SERVER_PACKET_SIZE,
113 pointer, SERVER_PACKET_SIZE*16);
114 pointer = pointer + SERVER_PACKET_SIZE * 16;
115 if (status)
116 error_counter++;
117
118 /* Create an IP instance. */
119 status = nx_ip_create(&server_ip, "HTTP Server IP", HTTP_SERVER_ADDRESS,
120 0xFFFFFF00UL, &server_pool, _nx_ram_network_driver_1024,
121 pointer, 4096, 1);
122 pointer = pointer + 4096;
123 if (status)
124 error_counter++;
125
126 /* Enable ARP and supply ARP cache memory for the server IP instance. */
127 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
128 pointer = pointer + 1024;
129 if (status)
130 error_counter++;
131
132 /* Enable TCP traffic. */
133 status = nx_tcp_enable(&server_ip);
134 if (status)
135 error_counter++;
136
137 /* Create the HTTP Client thread. */
138 status = tx_thread_create(&client_thread, "HTTP Client", thread_client_entry, 0,
139 pointer, DEMO_STACK_SIZE,
140 NX_WEB_HTTP_SERVER_PRIORITY + 2, NX_WEB_HTTP_SERVER_PRIORITY + 2, TX_NO_TIME_SLICE, TX_AUTO_START);
141 pointer = pointer + DEMO_STACK_SIZE;
142 if (status)
143 error_counter++;
144
145 /* Create the Client packet pool. */
146 status = nx_packet_pool_create(&client_pool, "HTTP Client Packet Pool", CLIENT_PACKET_SIZE,
147 pointer, CLIENT_PACKET_SIZE*16);
148 pointer = pointer + CLIENT_PACKET_SIZE * 16;
149 if (status)
150 error_counter++;
151
152 /* Create an IP instance. */
153 status = nx_ip_create(&client_ip, "HTTP Client IP", HTTP_CLIENT_ADDRESS,
154 0xFFFFFF00UL, &client_pool, _nx_ram_network_driver_1024,
155 pointer, 2048, 1);
156 pointer = pointer + 2048;
157 if (status)
158 error_counter++;
159
160 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
161 pointer = pointer + 2048;
162 if (status)
163 error_counter++;
164
165 /* Enable TCP traffic. */
166 status = nx_tcp_enable(&client_ip);
167 if (status)
168 error_counter++;
169 }
170
171 #ifdef NX_WEB_HTTPS_ENABLE
172 /* Define the TLS setup callback function. */
tls_setup_callback(NX_WEB_HTTP_CLIENT * client_ptr,NX_SECURE_TLS_SESSION * tls_session)173 static UINT tls_setup_callback(NX_WEB_HTTP_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session)
174 {
175 UINT status;
176
177
178 /* Initialize and create TLS session. */
179 status = nx_secure_tls_session_create(tls_session, &nx_crypto_tls_ciphers, crypto_metadata_client, sizeof(crypto_metadata_client));
180
181 /* Check status. */
182 if (status)
183 {
184 return(status);
185 }
186
187 /* Allocate space for packet reassembly. */
188 status = nx_secure_tls_session_packet_buffer_set(&(client_ptr -> nx_web_http_client_tls_session), tls_packet_buffer, sizeof(tls_packet_buffer));
189
190 /* Check status. */
191 if (status)
192 {
193 return(status);
194 }
195
196 /* Add a CA Certificate to our trusted store for verifying incoming server certificates. */
197 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);
198 nx_secure_tls_trusted_certificate_add(&(client_ptr -> nx_web_http_client_tls_session), &trusted_certificate);
199
200 /* Need to allocate space for the certificate coming in from the remote host. */
201 nx_secure_tls_remote_certificate_allocate(&(client_ptr -> nx_web_http_client_tls_session), &remote_certificate, remote_cert_buffer, sizeof(remote_cert_buffer));
202 nx_secure_tls_remote_certificate_allocate(&(client_ptr -> nx_web_http_client_tls_session), &remote_issuer, remote_issuer_buffer, sizeof(remote_issuer_buffer));
203
204 return(NX_SUCCESS);
205 }
206 #endif /* NX_WEB_HTTPS_ENABLE */
207
thread_client_entry(ULONG thread_input)208 void thread_client_entry(ULONG thread_input)
209 {
210 UINT i;
211 UINT status;
212 NX_PACKET *send_packet;
213 NX_PACKET *recv_packet;
214
215
216 /* Give IP task and driver a chance to initialize the system. */
217 tx_thread_sleep(NX_IP_PERIODIC_RATE);
218
219 /* Set server IP address. */
220 server_ip_address.nxd_ip_address.v4 = HTTP_SERVER_ADDRESS;
221 server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
222
223 /* First loop test HTTP, second loop test HTTPS. */
224 for (i = 0; i < loop ; i++)
225 {
226 if (i == 0)
227 {
228
229 /* Wait HTTP server started. */
230 while(!http_server_start)
231 {
232 tx_thread_sleep(NX_IP_PERIODIC_RATE);
233 }
234 }
235 #ifdef NX_WEB_HTTPS_ENABLE
236 else
237 {
238
239 /* Wait HTTPS server started. */
240 while(!https_server_start)
241 {
242 tx_thread_sleep(NX_IP_PERIODIC_RATE);
243 }
244 }
245 #endif /* NX_WEB_HTTPS_ENABLE */
246
247 for (test_count = 0; test_count < 2; test_count++)
248 {
249
250 /* Create an HTTP client instance. */
251 status = nx_web_http_client_create(&my_client, "HTTP Client", &client_ip, &client_pool, 1536);
252
253 /* Check status. */
254 if (status)
255 error_counter++;
256
257 /* Send POST request. */
258 if (i == 0)
259 {
260 status = nx_web_http_client_post_start(&my_client, &server_ip_address,
261 NX_WEB_HTTP_SERVER_PORT, "/test.txt?ad",
262 "www.abc.com", "name", "password", sizeof(pkt), NX_WAIT_FOREVER);
263 }
264 #ifdef NX_WEB_HTTPS_ENABLE
265 else
266 {
267 status = nx_web_http_client_secure_connect(&my_client, &server_ip_address, NX_WEB_HTTPS_SERVER_PORT,
268 tls_setup_callback, NX_WAIT_FOREVER);
269 if (status)
270 {
271 printf("Error in nx_web_http_client_secure_connect: 0x%x\n", status);
272 error_counter++;
273 }
274
275 status = nx_web_http_client_request_initialize(&my_client,
276 NX_WEB_HTTP_METHOD_POST, /* GET, PUT, DELETE, POST, HEAD */
277 "/test.txt;12",
278 "www.abc.com",
279 sizeof(pkt), /* Used by PUT and POST */
280 NX_FALSE, /* If true, input_size is ignored. */
281 "name",
282 "password",
283 NX_WAIT_FOREVER);
284 if (status)
285 {
286 printf("Error in nx_web_http_client_request_initialize: 0x%x\n", status);
287 error_counter++;
288 }
289
290 status = nx_web_http_client_request_send(&my_client, NX_WAIT_FOREVER);
291 if (status)
292 {
293 printf("Error in nx_web_http_client_request_send: 0x%x\n", status);
294 error_counter++;
295 }
296 }
297 #endif /* NX_WEB_HTTPS_ENABLE */
298
299 /* Allocate a packet. */
300 status = nx_web_http_client_request_packet_allocate(&my_client, &send_packet, NX_WAIT_FOREVER);
301
302 /* Check status. */
303 if (status)
304 error_counter++;
305
306 /* Write test data into the packet payload. */
307 nx_packet_data_append(send_packet, pkt, sizeof(pkt), &client_pool, NX_WAIT_FOREVER);
308
309 /* Send the POST data. */
310 status = nx_web_http_client_put_packet(&my_client, send_packet, 1 * NX_IP_PERIODIC_RATE);
311 if (status)
312 {
313 nx_packet_release(send_packet);
314 error_counter++;
315 }
316
317 /* Get response from server. */
318 while (1)
319 {
320 status = nx_web_http_client_response_body_get(&my_client, &recv_packet, NX_WAIT_FOREVER);
321
322 if (status)
323 break;
324 else
325 nx_packet_release(recv_packet);
326 }
327
328 /* Check status. */
329 if (status != NX_WEB_HTTP_GET_DONE)
330 error_counter++;
331 else
332 {
333 if (memcmp(recv_packet -> nx_packet_prepend_ptr, pkt, sizeof(pkt)) != 0)
334 {
335 error_counter++;
336 }
337 nx_packet_release(recv_packet);
338 }
339
340 status = nx_web_http_client_delete(&my_client);
341 if (status)
342 error_counter++;
343 }
344
345 /* Set the flag. */
346 if (i == 0)
347 {
348 http_client_stop = 1;
349 }
350 #ifdef NX_WEB_HTTPS_ENABLE
351 else
352 {
353 https_client_stop = 1;
354 }
355 #endif /* NX_WEB_HTTPS_ENABLE */
356 }
357
358 if (server_pool.nx_packet_pool_available != server_pool.nx_packet_pool_total)
359 {
360 error_counter++;
361 }
362 }
363
364
365 /* Define the helper HTTP server thread. */
thread_server_entry(ULONG thread_input)366 void thread_server_entry(ULONG thread_input)
367 {
368 UINT i;
369 UINT status;
370 FX_FILE my_file;
371 UINT server_port = NX_WEB_HTTP_SERVER_PORT;
372
373
374 /* Print out test information banner. */
375 printf("NetX Test: Web Server Content Process Test...........................");
376
377 /* Check for earlier error. */
378 if(error_counter)
379 {
380 printf("ERROR!\n");
381 test_control_return(1);
382 }
383
384 fx_media_format(&ram_disk,
385 _fx_ram_driver, // Driver entry
386 ram_disk_memory, // RAM disk memory pointer
387 media_memory, // Media buffer pointer
388 sizeof(media_memory), // Media buffer size
389 "MY_RAM_DISK", // Volume Name
390 1, // Number of FATs
391 32, // Directory Entries
392 0, // Hidden sectors
393 256, // Total sectors
394 512, // Sector size
395 8, // Sectors per cluster
396 1, // Heads
397 1); // Sectors per track
398
399 /* Open the RAM disk. */
400 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, media_memory, sizeof(media_memory)) ;
401 status += fx_file_create(&ram_disk, "index.htm");
402 status += fx_file_open(&ram_disk, &my_file, "index.htm", FX_OPEN_FOR_WRITE);
403 status += fx_file_write(&my_file, "https server", 12);
404 status += fx_file_close(&my_file);
405 if(status)
406 error_counter++;
407
408 /* Give NetX a chance to initialize the system. */
409 tx_thread_sleep(NX_IP_PERIODIC_RATE);
410
411 /* First loop test HTTP, second loop test HTTPS. */
412 for (i = 0; i < loop; i++)
413 {
414
415 if (i == 1)
416 {
417 server_port = NX_WEB_HTTPS_SERVER_PORT;
418 }
419
420 /* Create the HTTP Server. */
421 status = nx_web_http_server_create(&my_server, "My HTTP Server", &server_ip, server_port, &ram_disk,
422 &server_stack, sizeof(server_stack), &server_pool,
423 authentication_check, server_request_callback);
424 if (status)
425 error_counter++;
426
427 #ifdef NX_WEB_HTTPS_ENABLE
428 /* Set TLS for HTTPS. */
429 if (i == 1)
430 {
431 /* Initialize device certificate (used for all sessions in HTTPS server). */
432 memset(&certificate, 0, sizeof(certificate));
433 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);
434
435 /* Setup TLS session data for the TCP server. */
436 status = nx_web_http_server_secure_configure(&my_server, &nx_crypto_tls_ciphers,
437 crypto_metadata_server, sizeof(crypto_metadata_server), tls_packet_buffer, sizeof(tls_packet_buffer),
438 &certificate, NX_NULL, 0, NX_NULL, 0, NX_NULL, 0);
439 if (status)
440 error_counter++;
441 }
442 #endif /* NX_WEB_HTTPS_ENABLE */
443
444 /* OK to start the HTTP Server. */
445 status = nx_web_http_server_start(&my_server);
446 if (status)
447 error_counter++;
448
449 /* Set the flag. */
450 if (i == 0)
451 {
452 http_server_start = 1;
453
454 /* Wait HTTP test finished. */
455 while(!http_client_stop)
456 {
457 tx_thread_sleep(NX_IP_PERIODIC_RATE);
458 }
459 }
460 #ifdef NX_WEB_HTTPS_ENABLE
461 else
462 {
463 https_server_start = 1;
464
465 /* Wait HTTPS test finished. */
466 while(!https_client_stop)
467 {
468 tx_thread_sleep(NX_IP_PERIODIC_RATE);
469 }
470 }
471 #endif /* NX_WEB_HTTPS_ENABLE */
472
473 status = nx_web_http_server_delete(&my_server);
474 if (status)
475 error_counter++;
476 }
477
478 /* Check packet pool. */
479 if (server_pool.nx_packet_pool_available != server_pool.nx_packet_pool_total)
480 {
481 error_counter++;
482 }
483
484 if (client_pool.nx_packet_pool_available != client_pool.nx_packet_pool_total)
485 {
486 error_counter++;
487 }
488
489 if(error_counter)
490 {
491 printf("ERROR!\n");
492 test_control_return(1);
493 }
494 else
495 {
496 printf("SUCCESS!\n");
497 test_control_return(0);
498 }
499 }
500
501
502 /* Define the application's authentication check. This is called by
503 the HTTP server whenever a new request is received. */
authentication_check(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,CHAR ** password,CHAR ** realm)504 static UINT authentication_check(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
505 CHAR *resource, CHAR **name, CHAR **password, CHAR **realm)
506 {
507
508 /* Just use a simple name, password, and realm for all
509 requests and resources. */
510 *name = "name";
511 *password = "password";
512 *realm = "NetX Duo HTTP demo";
513
514 /* Request basic authentication. */
515 return(NX_WEB_HTTP_BASIC_AUTHENTICATE);
516 }
517
518 /* Define the server request callback function. */
server_request_callback(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,NX_PACKET * packet_ptr)519 static UINT server_request_callback(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr)
520 {
521 UINT length;
522 NX_PACKET *response_pkt;
523 UCHAR buffer[4000];
524 CHAR param[10];
525 UINT param_size;
526 ULONG content_length;
527 UINT status;
528
529
530 memset(buffer, 0, sizeof(buffer));
531 length = 0;
532
533 /* Process content. */
534 if (request_type == NX_WEB_HTTP_SERVER_POST_REQUEST)
535 {
536
537 /* Get the content data location. */
538 if (test_count == 0)
539 {
540 status = nx_web_http_server_content_get(server_ptr, packet_ptr, 0, buffer, sizeof(buffer), &length);
541 }
542 else
543 {
544 status = nx_web_http_server_content_get_extended(server_ptr, packet_ptr, 0, buffer, sizeof(buffer), &length);
545 }
546
547 if (status)
548 {
549 return(status);
550 }
551
552 /* FIXME: HACK! The parameter and query parsing won't parse past the other symbol (e.g. ';' or '?')
553 so check queries with HTTP and params with HTTPS. */
554
555 #ifdef NX_WEB_HTTPS_ENABLE
556 if(!server_ptr->nx_web_http_is_https_server)
557 {
558 #endif
559 /* Look for queries and parameters. */
560 status = nx_web_http_server_query_get(packet_ptr, 0, param, ¶m_size, sizeof(param));
561
562 if(status != NX_SUCCESS || strncmp(param, "ad", 2) != 0)
563 {
564 error_counter++;
565 }
566 #ifdef NX_WEB_HTTPS_ENABLE
567 }
568 else
569 {
570 /* HTTPS, check params. */
571 status = nx_web_http_server_param_get(packet_ptr, 0, param, ¶m_size, sizeof(param));
572
573 if(status != NX_SUCCESS || strncmp(param, "12", 2) != 0)
574 {
575 error_counter++;
576 }
577 }
578 #endif
579
580 status = nx_web_http_server_packet_content_find(server_ptr, &packet_ptr, &content_length);
581
582 /* Release the received content packet. */
583 nx_packet_release(packet_ptr);
584
585 if(status != NX_SUCCESS || content_length != sizeof(pkt))
586 {
587 error_counter++;
588 }
589
590 if (length != sizeof(pkt))
591 {
592 error_counter++;
593 }
594
595 if (memcmp(buffer, pkt, length) != 0)
596 {
597 error_counter++;
598 }
599
600 /* make sure we don't overwrite our buffer! */
601 if(length > sizeof(buffer))
602 {
603 length = sizeof(buffer);
604 }
605
606 /* Send HTTP header. */
607 status = nx_web_http_server_callback_response_send(server_ptr, NX_WEB_HTTP_STATUS_OK, buffer, NX_NULL);
608
609 if(status)
610 {
611 return(status);
612 }
613
614 status = nx_web_http_server_response_packet_allocate(server_ptr, &response_pkt, NX_IP_PERIODIC_RATE);
615
616 if(status)
617 {
618 return(status);
619 }
620
621 if(length > 0)
622 {
623 /* Only send what is in the buffer. */
624 status = nx_packet_data_append(response_pkt, buffer, length, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
625 }
626
627 if(status == NX_SUCCESS)
628 {
629 if(nx_web_http_server_callback_packet_send(server_ptr, response_pkt) != NX_SUCCESS)
630 {
631 nx_packet_release(response_pkt);
632 }
633 }
634 }
635 else
636 {
637 /* Indicate we have not processed the response to client yet. */
638 return(NX_SUCCESS);
639 }
640
641 /* Indicate the response to client is transmitted. */
642 return(NX_WEB_HTTP_CALLBACK_COMPLETED);
643 }
644
645 #else
646
647 #ifdef CTEST
test_application_define(void * first_unused_memory)648 VOID test_application_define(void *first_unused_memory)
649 #else
650 void netx_web_server_content_process_test_application_define(void *first_unused_memory)
651 #endif
652 {
653
654 /* Print out test information banner. */
655 printf("NetX Test: Web Server Content Process Test...........................N/A\n");
656
657 test_control_return(3);
658 }
659 #endif
660