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 Web Component */
17 /** */
18 /** Hypertext Transfer Protocol (HTTP) */
19 /** Hypertext Transfer Protocol Secure (HTTPS using TLS) */
20 /** */
21 /**************************************************************************/
22 /**************************************************************************/
23
24 #define NX_WEB_HTTP_SERVER_SOURCE_CODE
25
26
27 /* Force error checking to be disabled in this module */
28
29 #ifndef NX_DISABLE_ERROR_CHECKING
30 #define NX_DISABLE_ERROR_CHECKING
31 #endif
32
33 /* Include necessary system files. */
34
35 #include "nx_api.h"
36 #include "nx_ip.h"
37 #include "nx_web_http_server.h"
38
39 #include "stdio.h"
40 #include "string.h"
41 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
42 #include "nx_md5.h"
43 #endif
44
45 #if defined(NX_WEB_HTTP_SERVER_OMIT_CONTENT_LENGTH) && !defined(NX_WEB_HTTP_KEEPALIVE_DISABLE)
46 #error "Content length needed when keepalive is enabled"
47 #endif /* NX_WEB_HTTP_SERVER_OMIT_CONTENT_LENGTH */
48
49 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
50
51 /* Use for mapping random nonces to printable characters. */
52 static CHAR _nx_web_http_server_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
53 #endif
54
55 /* Define date strings. */
56 const CHAR _nx_web_http_server_weekday[][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
57 const CHAR _nx_web_http_server_month[][3] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
58
59 /* Define basic MIME maps. */
60 static NX_WEB_HTTP_SERVER_MIME_MAP _nx_web_http_server_mime_maps[] =
61 {
62 {"html", "text/html"},
63 {"htm", "text/html"},
64 {"txt", "text/plain"},
65 {"gif", "image/gif"},
66 {"jpg", "image/jpeg"},
67 {"ico", "image/x-icon"},
68 };
69
70
71 /* Create two arrays to hold encoded and decoded username/password data. */
72 static CHAR authorization_request[NX_WEB_HTTP_MAX_STRING + 1];
73 static CHAR authorization_decoded[NX_WEB_HTTP_MAX_NAME + NX_WEB_HTTP_MAX_PASSWORD + 2];
74
75 /* Bring in externs for caller checking code. */
76
77 NX_CALLER_CHECKING_EXTERNS
78
79
80 /**************************************************************************/
81 /* */
82 /* FUNCTION RELEASE */
83 /* */
84 /* _nxe_web_http_server_content_get PORTABLE C */
85 /* 6.1 */
86 /* AUTHOR */
87 /* */
88 /* Yuxin Zhou, Microsoft Corporation */
89 /* */
90 /* DESCRIPTION */
91 /* */
92 /* This function checks for errors in the HTTP content get call. */
93 /* */
94 /* */
95 /* INPUT */
96 /* */
97 /* server_ptr Pointer to HTTP server */
98 /* packet_ptr Pointer to HTTP request packet*/
99 /* byte_offset Byte offset into content */
100 /* destination_ptr Pointer to content destination*/
101 /* destination_size Maximum size of destination */
102 /* actual_size Actual amount of content */
103 /* */
104 /* OUTPUT */
105 /* */
106 /* status Completion status */
107 /* */
108 /* CALLS */
109 /* */
110 /* _nx_web_http_server_content_get Actual server content get call*/
111 /* */
112 /* CALLED BY */
113 /* */
114 /* Application Code */
115 /* */
116 /* RELEASE HISTORY */
117 /* */
118 /* DATE NAME DESCRIPTION */
119 /* */
120 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
121 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
122 /* resulting in version 6.1 */
123 /* */
124 /**************************************************************************/
_nxe_web_http_server_content_get(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)125 UINT _nxe_web_http_server_content_get(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset, CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
126 {
127
128 UINT status;
129
130
131 /* Check for invalid input pointers. */
132 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
133 (packet_ptr == NX_NULL) || (destination_ptr == NX_NULL) || (actual_size == NX_NULL))
134 return(NX_PTR_ERROR);
135
136 /* Check for appropriate caller. */
137 NX_THREADS_ONLY_CALLER_CHECKING
138
139 /* Call actual server content get function. */
140 status = _nx_web_http_server_content_get(server_ptr, packet_ptr, byte_offset, destination_ptr, destination_size, actual_size);
141
142 /* Return completion status. */
143 return(status);
144 }
145
146
147 /**************************************************************************/
148 /* */
149 /* FUNCTION RELEASE */
150 /* */
151 /* _nx_web_http_server_content_get PORTABLE C */
152 /* 6.1 */
153 /* AUTHOR */
154 /* */
155 /* Yuxin Zhou, Microsoft Corporation */
156 /* */
157 /* DESCRIPTION */
158 /* */
159 /* This function returns the user's specified portion of the HTTP */
160 /* content. Content is typically included in POST and PUT requests */
161 /* from the client. This routine is designed to be called from the */
162 /* application's request notify callback. */
163 /* */
164 /* */
165 /* INPUT */
166 /* */
167 /* server_ptr Pointer to HTTP server */
168 /* packet_ptr Pointer to HTTP request packet*/
169 /* byte_offset Byte offset into content */
170 /* destination_ptr Pointer to content destination*/
171 /* destination_size Maximum size of destination */
172 /* actual_size Actual amount of content */
173 /* */
174 /* OUTPUT */
175 /* */
176 /* status Completion status */
177 /* */
178 /* CALLS */
179 /* */
180 /* _nx_web_http_server_content_get_extended */
181 /* Get content data */
182 /* */
183 /* CALLED BY */
184 /* */
185 /* Application Code */
186 /* */
187 /* RELEASE HISTORY */
188 /* */
189 /* DATE NAME DESCRIPTION */
190 /* */
191 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
192 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
193 /* resulting in version 6.1 */
194 /* */
195 /**************************************************************************/
_nx_web_http_server_content_get(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)196 UINT _nx_web_http_server_content_get(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset, CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
197 {
198 UINT status;
199
200 /* Get content data. */
201 status = _nx_web_http_server_content_get_extended(server_ptr, packet_ptr, byte_offset, destination_ptr, destination_size, actual_size);
202
203 return(status);
204 }
205
206
207 /**************************************************************************/
208 /* */
209 /* FUNCTION RELEASE */
210 /* */
211 /* _nxe_web_http_server_packet_content_find PORTABLE C */
212 /* 6.1 */
213 /* AUTHOR */
214 /* */
215 /* Yuxin Zhou, Microsoft Corporation */
216 /* */
217 /* DESCRIPTION */
218 /* */
219 /* This function checks for errors in the HTTP packet content find */
220 /* call. */
221 /* */
222 /* */
223 /* INPUT */
224 /* */
225 /* server_ptr Pointer to HTTP server */
226 /* packet_ptr Pointer to pointer to the */
227 /* packet that contains the */
228 /* HTTP header */
229 /* content_length Pointer to content length */
230 /* */
231 /* OUTPUT */
232 /* */
233 /* status Completion status */
234 /* */
235 /* CALLS */
236 /* */
237 /* _nx_web_http_server_packet_content_find */
238 /* Actual server packet content */
239 /* find call */
240 /* */
241 /* CALLED BY */
242 /* */
243 /* Application Code */
244 /* */
245 /* RELEASE HISTORY */
246 /* */
247 /* DATE NAME DESCRIPTION */
248 /* */
249 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
250 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
251 /* resulting in version 6.1 */
252 /* */
253 /**************************************************************************/
_nxe_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,ULONG * content_length)254 UINT _nxe_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG *content_length)
255 {
256
257
258 /* Check for invalid packet pointer. */
259 if((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
260 (packet_ptr == NX_NULL) || (*packet_ptr == NX_NULL) || (content_length == NX_NULL))
261 return(NX_PTR_ERROR);
262
263 /* Call actual server content length get function. */
264 return(_nx_web_http_server_packet_content_find(server_ptr, packet_ptr, content_length));
265
266 }
267
268 /**************************************************************************/
269 /* */
270 /* FUNCTION RELEASE */
271 /* */
272 /* _nx_web_http_server_packet_content_find PORTABLE C */
273 /* 6.1.7 */
274 /* AUTHOR */
275 /* */
276 /* Yuxin Zhou, Microsoft Corporation */
277 /* */
278 /* DESCRIPTION */
279 /* */
280 /* This function finds the content length specified in the HTTP */
281 /* header, and move the nx_packet_prepend_ptr to the beginning of */
282 /* the content. If the beginning of the content is not in the packet, */
283 /* this function attempts to read the HTTP server socket for the */
284 /* next packet. */
285 /* */
286 /* */
287 /* INPUT */
288 /* */
289 /* server_ptr Pointer to HTTP server */
290 /* packet_ptr Pointer to pointer to the */
291 /* packet that contains the */
292 /* HTTP header */
293 /* content_length Pointer to content length */
294 /* */
295 /* OUTPUT */
296 /* */
297 /* status Completion status */
298 /* */
299 /* CALLS */
300 /* */
301 /* _nx_web_http_server_content_length_get */
302 /* Get content length */
303 /* _nx_web_http_server_packet_get Receive another packet */
304 /* _nx_web_http_server_calculate_content_offset */
305 /* Pickup content offset */
306 /* nx_packet_allocate Allocate a new packet */
307 /* nx_packet_release Release the packet */
308 /* */
309 /* CALLED BY */
310 /* */
311 /* Application Code */
312 /* */
313 /* RELEASE HISTORY */
314 /* */
315 /* DATE NAME DESCRIPTION */
316 /* */
317 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
318 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
319 /* resulting in version 6.1 */
320 /* 06-02-2021 Yuxin Zhou Modified comment(s), */
321 /* fixed compiler warnings, */
322 /* resulting in version 6.1.7 */
323 /* */
324 /**************************************************************************/
_nx_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,ULONG * content_length)325 UINT _nx_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG *content_length)
326 {
327
328 ULONG get_offset;
329 UINT status;
330 ULONG length = 0;
331 UINT packet_chunked;
332 NX_PACKET *header_packet_ptr;
333 NX_PACKET *new_packet_ptr;
334 ULONG temp_offset;
335
336 /* Check if the packet is chunked. */
337 packet_chunked = _nx_web_http_server_chunked_check(*packet_ptr);
338
339 /* If the packet isn't chunked. */
340 if (!packet_chunked)
341 {
342
343 /* Get the content length header information. */
344 status = _nx_web_http_server_content_length_get(*packet_ptr, &length);
345
346 if (status != NX_SUCCESS)
347 {
348 return(status);
349 }
350 }
351
352 /* Get the content offset. */
353 get_offset = (ULONG)_nx_web_http_server_calculate_content_offset(*packet_ptr);
354
355 /* Check packet length. */
356 if((*packet_ptr) -> nx_packet_length == get_offset)
357 {
358
359 /* If the packet doesn't contain any content, need to receive a new packet. */
360
361 /* If the received request packet is chunked. */
362 if (server_ptr -> nx_web_http_server_request_chunked)
363 {
364
365 /* Initialize the request packet pointer and remaining size for processing chunked packet. */
366 server_ptr -> nx_web_http_server_request_packet = NX_NULL;
367 server_ptr -> nx_web_http_server_chunked_request_remaining_size = 0;
368 }
369
370 /* Make the receive call to obtain the next packet. */
371 status = _nx_web_http_server_packet_get(server_ptr, packet_ptr);
372
373 if(status != NX_SUCCESS)
374 {
375 return(NX_WEB_HTTP_TIMEOUT);
376 }
377
378 }
379 else
380 {
381
382 /* Separate the HTTP header and content. Copy the content to a new packet. */
383
384 /* Remember the packet pointer and content offset. */
385 header_packet_ptr = *packet_ptr;
386 temp_offset = get_offset;
387
388 #ifndef NX_DISABLE_PACKET_CHAIN
389
390 /* If the packet is chained, loop to find the end of the HTTP header. */
391 while ((*packet_ptr) && (temp_offset > (ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr)))
392 {
393 temp_offset -= (ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr);
394 (*packet_ptr) = (*packet_ptr) -> nx_packet_next;
395 }
396
397 /* Chack if packet is valid. */
398 if ((*packet_ptr) == NX_NULL)
399 {
400 return(NX_WEB_HTTP_BAD_PACKET_LENGTH);
401 }
402
403 /* If this packet contain no content, set next packet as the first packet of the content. */
404 if (temp_offset == (ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr))
405 {
406 new_packet_ptr = (*packet_ptr) -> nx_packet_next;
407 }
408 else
409 {
410 #endif
411
412 /* Allocate a new packet to store content. */
413 status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
414 &new_packet_ptr, 0, NX_WAIT_FOREVER);
415 if(status)
416 {
417 return(status);
418 }
419
420 /* Copy the content part to the new packet. */
421 nx_packet_data_append(new_packet_ptr,
422 (*packet_ptr) -> nx_packet_prepend_ptr + temp_offset,
423 (ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr) - temp_offset,
424 server_ptr -> nx_web_http_server_packet_pool_ptr,
425 NX_WAIT_FOREVER);
426
427 /* Update the append pointer of the header part. */
428 (*packet_ptr) -> nx_packet_append_ptr = (*packet_ptr) -> nx_packet_prepend_ptr + temp_offset;
429
430 #ifndef NX_DISABLE_PACKET_CHAIN
431
432 /* Set the next packet of the content packet. */
433 new_packet_ptr -> nx_packet_next = (*packet_ptr) -> nx_packet_next;
434 }
435
436 /* Set the last packet of the content and header packet. */
437 new_packet_ptr -> nx_packet_last = header_packet_ptr -> nx_packet_last;
438 header_packet_ptr -> nx_packet_last = (*packet_ptr);
439 (*packet_ptr) -> nx_packet_next = NX_NULL;
440 #endif
441
442 /* Update the length of the header and content packet. */
443 new_packet_ptr -> nx_packet_length = header_packet_ptr -> nx_packet_length - get_offset;
444 header_packet_ptr -> nx_packet_length = get_offset;
445
446 /* Return the content packet. */
447 if (server_ptr -> nx_web_http_server_request_chunked)
448 {
449
450 /* If the packet is chunked, set for processing chunked packet. */
451 server_ptr -> nx_web_http_server_request_packet = new_packet_ptr;
452 server_ptr -> nx_web_http_server_chunked_request_remaining_size = new_packet_ptr -> nx_packet_length;
453
454 /* Get the processed chunked packet. Set this packet as the returned packet. */
455 status = _nx_web_http_server_packet_get(server_ptr, packet_ptr);
456 if (status)
457 {
458 return(status);
459 }
460 }
461 else
462 {
463
464 /* Set the returned packet. */
465 *packet_ptr = new_packet_ptr;
466 }
467 }
468
469 /* Determine if there is content in this HTTP request. */
470 if(content_length)
471 {
472
473 if (packet_chunked)
474 {
475
476 /* If the packet is chunked, set content length as packet length. */
477 *content_length = (*packet_ptr) -> nx_packet_length;
478 }
479 else
480 {
481
482 /* Set the content length as the length in HTTP header. */
483 *content_length = length;
484 }
485 }
486
487 return(NX_SUCCESS);
488 }
489
490
491 /**************************************************************************/
492 /* */
493 /* FUNCTION RELEASE */
494 /* */
495 /* _nxe_web_http_server_packet_get PORTABLE C */
496 /* 6.1 */
497 /* AUTHOR */
498 /* */
499 /* Yuxin Zhou, Microsoft Corporation */
500 /* */
501 /* DESCRIPTION */
502 /* */
503 /* This function checks for errors in the HTTP server packet get call. */
504 /* */
505 /* */
506 /* INPUT */
507 /* */
508 /* server_ptr Pointer to HTTP server */
509 /* packet_ptr Pointer to the packet to */
510 /* be returned. */
511 /* */
512 /* OUTPUT */
513 /* */
514 /* status Completion status */
515 /* */
516 /* CALLS */
517 /* */
518 /* _nx_web_http_server_packet_get Actual server packet get call */
519 /* */
520 /* CALLED BY */
521 /* */
522 /* Application Code */
523 /* */
524 /* RELEASE HISTORY */
525 /* */
526 /* DATE NAME DESCRIPTION */
527 /* */
528 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
529 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
530 /* resulting in version 6.1 */
531 /* */
532 /**************************************************************************/
_nxe_web_http_server_packet_get(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr)533 UINT _nxe_web_http_server_packet_get(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr)
534 {
535
536
537 /* Check for invalid packet pointer. */
538 if((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
539 (packet_ptr == NX_NULL))
540 return(NX_PTR_ERROR);
541
542 /* Call actual server packet get function. */
543 return(_nx_web_http_server_packet_get(server_ptr, packet_ptr));
544
545 }
546
547
548 /**************************************************************************/
549 /* */
550 /* FUNCTION RELEASE */
551 /* */
552 /* _nx_web_http_server_packet_get PORTABLE C */
553 /* 6.1 */
554 /* AUTHOR */
555 /* */
556 /* Yuxin Zhou, Microsoft Corporation */
557 /* */
558 /* DESCRIPTION */
559 /* */
560 /* This function obtains the next packet from the HTTP server socket. */
561 /* */
562 /* */
563 /* INPUT */
564 /* */
565 /* server_ptr Pointer to HTTP server */
566 /* packet_ptr Pointer to the packet to */
567 /* be returned. */
568 /* */
569 /* OUTPUT */
570 /* */
571 /* status Completion status */
572 /* */
573 /* CALLS */
574 /* */
575 /* _nx_web_http_server_request_chunked_get */
576 /* Get chunked request packet */
577 /* _nx_web_http_server_receive Receive another packet */
578 /* nx_packet_release Packet release */
579 /* */
580 /* CALLED BY */
581 /* */
582 /* Application Code */
583 /* */
584 /* RELEASE HISTORY */
585 /* */
586 /* DATE NAME DESCRIPTION */
587 /* */
588 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
589 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
590 /* resulting in version 6.1 */
591 /* */
592 /**************************************************************************/
_nx_web_http_server_packet_get(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr)593 UINT _nx_web_http_server_packet_get(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr)
594 {
595 NX_PACKET *new_packet_ptr;
596 UINT status;
597
598 if (server_ptr -> nx_web_http_server_request_chunked)
599 {
600
601 /* If the request packet is chunked, remove the chunk header and get the packet which contain the chunk data. */
602 status = _nx_web_http_server_request_chunked_get(server_ptr, &new_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_RECEIVE);
603 }
604 else
605 {
606
607 /* Receive another packet from client. */
608 status = _nx_web_http_server_receive(server_ptr, &new_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_RECEIVE);
609 }
610
611 /* Check the return status. */
612 if (status != NX_SUCCESS)
613 {
614
615 if (server_ptr -> nx_web_http_server_request_chunked)
616 {
617
618 /* Reset the chunked info. */
619 nx_packet_release(server_ptr -> nx_web_http_server_request_packet);
620 server_ptr -> nx_web_http_server_request_packet = NX_NULL;
621 server_ptr -> nx_web_http_server_chunked_request_remaining_size = 0;
622 server_ptr -> nx_web_http_server_request_chunked = NX_FALSE;
623 return(status);
624 }
625
626 /* Error, return to caller. */
627 return(NX_WEB_HTTP_TIMEOUT);
628 }
629
630 *packet_ptr = new_packet_ptr;
631
632 return(NX_SUCCESS);
633
634 }
635
636
637 /**************************************************************************/
638 /* */
639 /* FUNCTION RELEASE */
640 /* */
641 /* _nxe_web_http_server_content_get_extended PORTABLE C */
642 /* 6.1 */
643 /* AUTHOR */
644 /* */
645 /* Yuxin Zhou, Microsoft Corporation */
646 /* */
647 /* DESCRIPTION */
648 /* */
649 /* This function checks for errors in the HTTP extended get content */
650 /* service. */
651 /* */
652 /* */
653 /* INPUT */
654 /* */
655 /* server_ptr Pointer to HTTP server */
656 /* packet_ptr Pointer to HTTP request packet*/
657 /* byte_offset Byte offset into content */
658 /* destination_ptr Pointer to content destination*/
659 /* destination_size Maximum size of destination */
660 /* actual_size Actual amount of content */
661 /* */
662 /* OUTPUT */
663 /* */
664 /* status Completion status */
665 /* */
666 /* CALLS */
667 /* */
668 /* _nx_web_http_server_content_get_extended */
669 /* Actual extended get content */
670 /* get service */
671 /* */
672 /* CALLED BY */
673 /* */
674 /* Application Code */
675 /* */
676 /* RELEASE HISTORY */
677 /* */
678 /* DATE NAME DESCRIPTION */
679 /* */
680 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
681 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
682 /* resulting in version 6.1 */
683 /* */
684 /**************************************************************************/
_nxe_web_http_server_content_get_extended(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)685 UINT _nxe_web_http_server_content_get_extended(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset,
686 CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
687 {
688
689 UINT status;
690
691
692 /* Check for invalid input pointers. */
693 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
694 (packet_ptr == NX_NULL) || (destination_ptr == NX_NULL) || (actual_size == NX_NULL))
695 return(NX_PTR_ERROR);
696
697 /* Check for appropriate caller. */
698 NX_THREADS_ONLY_CALLER_CHECKING
699
700 /* Call actual server content get function. */
701 status = _nx_web_http_server_content_get_extended(server_ptr, packet_ptr, byte_offset, destination_ptr, destination_size, actual_size);
702
703 /* Return completion status. */
704 return(status);
705 }
706
707
708 /**************************************************************************/
709 /* */
710 /* FUNCTION RELEASE */
711 /* */
712 /* _nx_web_http_server_content_get_extended PORTABLE C */
713 /* 6.1 */
714 /* AUTHOR */
715 /* */
716 /* Yuxin Zhou, Microsoft Corporation */
717 /* */
718 /* DESCRIPTION */
719 /* */
720 /* This function returns the user's specified portion of the HTTP */
721 /* content. Content is typically included in POST and PUT requests */
722 /* from the client. This routine is designed to be called from the */
723 /* application's request notify callback. */
724 /* */
725 /* INPUT */
726 /* */
727 /* server_ptr Pointer to HTTP server */
728 /* packet_ptr Pointer to HTTP request packet*/
729 /* byte_offset Byte offset into content */
730 /* destination_ptr Pointer to content destination*/
731 /* destination_size Maximum size of destination */
732 /* actual_size Actual amount of content */
733 /* */
734 /* OUTPUT */
735 /* */
736 /* status Completion status */
737 /* */
738 /* CALLS */
739 /* */
740 /* _nx_web_http_server_chunked_check Check if the packet is chunked*/
741 /* _nx_web_http_server_packet_get Receive another packet */
742 /* _nx_web_http_server_content_length_get */
743 /* Get content length with error */
744 /* status returned separately */
745 /* content length value. */
746 /* _nx_web_http_server_calculate_content_offset */
747 /* Pickup content offset */
748 /* _nx_web_http_server_packet_content_find */
749 /* Get the content packet */
750 /* */
751 /* CALLED BY */
752 /* */
753 /* Application Code */
754 /* */
755 /* RELEASE HISTORY */
756 /* */
757 /* DATE NAME DESCRIPTION */
758 /* */
759 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
760 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
761 /* resulting in version 6.1 */
762 /* */
763 /**************************************************************************/
_nx_web_http_server_content_get_extended(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)764 UINT _nx_web_http_server_content_get_extended(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset,
765 CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
766 {
767
768 ULONG content_length;
769 ULONG offset;
770 UINT status;
771 UINT remaining_bytes;
772 NX_PACKET *new_packet_ptr;
773 CHAR *buffer_ptr;
774 #ifndef NX_DISABLE_PACKET_CHAIN
775 NX_PACKET *header_packet_ptr = NX_NULL;
776 #endif
777
778 /* Default the actual size to zero. */
779 *actual_size = 0;
780
781 if (_nx_web_http_server_chunked_check(packet_ptr) == NX_FALSE)
782 {
783
784 /* Determine if there is content in this HTTP request. */
785 status = _nx_web_http_server_content_length_get(packet_ptr, &content_length);
786
787 if (status != NX_SUCCESS)
788 {
789 return status;
790 }
791
792 /* Make sure the content length is at least greater than the byte offset supplied. */
793 if (content_length <= byte_offset)
794 {
795
796 /* No more data in this buffer. */
797 return(NX_WEB_HTTP_DATA_END);
798 }
799
800 /* Determine if the destination size is greater than the content length. */
801 if (destination_size > content_length)
802 {
803
804 /* Yes, make the destination size equal to the content length. */
805 destination_size = content_length;
806 }
807
808 /* Add the byte offset with content offset. */
809 byte_offset += ((ULONG) _nx_web_http_server_calculate_content_offset(packet_ptr));
810 }
811 else
812 {
813 #ifdef NX_DISABLE_PACKET_CHAIN
814
815 NX_PARAMETER_NOT_USED(server_ptr);
816
817 return NX_WEB_HTTP_ERROR;
818 #else
819
820 /* If never processed the chunked packet, need to separate the HTTP header and content. */
821 if (!server_ptr -> nx_web_http_server_expect_receive_bytes)
822 {
823
824 /* Remember the header packet. */
825 header_packet_ptr = packet_ptr;
826
827 /* Separate the HTTP header and get the first content packet. */
828 status = _nx_web_http_server_packet_content_find(server_ptr, &packet_ptr, NX_NULL);
829 if (status)
830 {
831 return(status);
832 }
833 }
834 else
835 {
836
837 /* If the HTTP header and content is already separated, process this packet as normal packet. */
838 byte_offset += ((ULONG) _nx_web_http_server_calculate_content_offset(packet_ptr));
839 }
840 #endif
841 }
842
843 /* Determine if we need to read one or more additional packets. */
844 while (byte_offset >= packet_ptr -> nx_packet_length)
845 {
846
847 #ifdef NX_DISABLE_PACKET_CHAIN
848 NX_PARAMETER_NOT_USED(server_ptr);
849
850 return NX_WEB_HTTP_ERROR;
851 #else
852 /* Read another packet because the offset reaches past the current packet
853 length. */
854 status = _nx_web_http_server_packet_get(server_ptr, &new_packet_ptr);
855
856 /* Check the return status. */
857 if (status != NX_SUCCESS)
858 {
859
860 /* Error, return to caller. */
861 return(NX_WEB_HTTP_TIMEOUT);
862 }
863
864 /* Otherwise, we have a new packet to append to the head packet. */
865
866 /* Determine if the current packet is already chained. */
867 if (packet_ptr -> nx_packet_next)
868 {
869
870 /* Yes, link the current last packet to the new packet. */
871 (packet_ptr -> nx_packet_last) -> nx_packet_next = new_packet_ptr;
872 }
873 else
874 {
875
876 /* Otherwise, this is our first chained packet. Link to the head. */
877 packet_ptr -> nx_packet_next = new_packet_ptr;
878 }
879
880 /* Is the new packet chained? */
881 if (new_packet_ptr -> nx_packet_next)
882 {
883
884 /* Yes, there is a last packet pointer. Point to this from the head packet. */
885 packet_ptr -> nx_packet_last = new_packet_ptr -> nx_packet_last;
886 }
887 else
888 {
889
890 /* No, there isn't a last packet pointer. Point to new packet from the head packet. */
891 packet_ptr -> nx_packet_last = new_packet_ptr;
892 }
893
894 /* Update the packet length. */
895 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + new_packet_ptr -> nx_packet_length;
896 #endif /* NX_DISABLE_PACKET_CHAIN */
897 }
898
899 #ifndef NX_DISABLE_PACKET_CHAIN
900 if (header_packet_ptr)
901 {
902
903 /* Append the content packet to the header packet. */
904 if (header_packet_ptr -> nx_packet_next)
905 {
906 (header_packet_ptr -> nx_packet_last) -> nx_packet_next = packet_ptr;
907 }
908 else
909 {
910 header_packet_ptr -> nx_packet_next = packet_ptr;
911 }
912
913 /* Update the last packet. */
914 if (packet_ptr -> nx_packet_next)
915 {
916 header_packet_ptr -> nx_packet_last = packet_ptr -> nx_packet_last;
917 }
918 else
919 {
920 header_packet_ptr -> nx_packet_last = packet_ptr;
921 }
922
923 /* Update the packet length. */
924 header_packet_ptr -> nx_packet_length = header_packet_ptr -> nx_packet_length + packet_ptr -> nx_packet_length;
925 }
926 #endif
927
928 /* Default the buffer pointer to NULL. */
929 buffer_ptr = NX_NULL;
930
931 /* Now find the packet that contains the offset. */
932 offset = 0;
933 new_packet_ptr = packet_ptr;
934 do
935 {
936
937 /* Determine if the get request falls into this packet. */
938 if (byte_offset < (offset + (ULONG)(new_packet_ptr -> nx_packet_append_ptr - new_packet_ptr -> nx_packet_prepend_ptr)))
939 {
940
941 /* Yes, the get offset is in this packet. */
942
943 /* Setup the starting byte pointer. */
944 buffer_ptr = ((CHAR *) new_packet_ptr -> nx_packet_prepend_ptr) + (byte_offset - offset);
945 break;
946 }
947
948 /* Otherwise update the offset. */
949 offset = offset + (ULONG)(new_packet_ptr -> nx_packet_append_ptr - new_packet_ptr -> nx_packet_prepend_ptr);
950
951 #ifdef NX_DISABLE_PACKET_CHAIN
952 new_packet_ptr = NX_NULL;
953 #else
954 /* Move to next packet in the chain. */
955 new_packet_ptr = new_packet_ptr -> nx_packet_next;
956 #endif /* NX_DISABLE_PACKET_CHAIN */
957
958 } while (new_packet_ptr);
959
960 /* Determine if an error occurred in the search. */
961 if ((buffer_ptr == (CHAR *) NX_NULL) || (new_packet_ptr == NX_NULL))
962 return(NX_WEB_HTTP_ERROR);
963
964 /* Now determine if the maximum buffer size has to be adjusted. */
965 if (destination_size > (UINT) (packet_ptr -> nx_packet_length - byte_offset))
966 {
967
968 /* Adjust the destination size downward. */
969 destination_size = (UINT) (packet_ptr -> nx_packet_length - byte_offset);
970 }
971
972 /* Initialize the remaining bytes. */
973 remaining_bytes = destination_size;
974
975 /* Otherwise copy the bytes from the offset to the end of the packet pointer. */
976 while (remaining_bytes--)
977 {
978
979 #ifndef NX_DISABLE_PACKET_CHAIN
980
981 /* If the packet is chained, copy the data in the chain. */
982 if (buffer_ptr == (CHAR *)new_packet_ptr -> nx_packet_append_ptr)
983 {
984 new_packet_ptr = new_packet_ptr -> nx_packet_next;
985 buffer_ptr = (CHAR *)new_packet_ptr -> nx_packet_prepend_ptr;
986 }
987 #endif /* NX_DISABLE_PACKET_CHAIN */
988
989 /* Copy a byte to the destination. */
990 *destination_ptr++ = *buffer_ptr++;
991 }
992
993 /* Successful completion. */
994 *actual_size = destination_size;
995 return(NX_SUCCESS);
996 }
997
998
999 /**************************************************************************/
1000 /* */
1001 /* FUNCTION RELEASE */
1002 /* */
1003 /* _nxe_web_http_server_content_length_get PORTABLE C */
1004 /* 6.1 */
1005 /* AUTHOR */
1006 /* */
1007 /* Yuxin Zhou, Microsoft Corporation */
1008 /* */
1009 /* DESCRIPTION */
1010 /* */
1011 /* This function checks for errors in the HTTP content length service. */
1012 /* */
1013 /* */
1014 /* INPUT */
1015 /* */
1016 /* packet_ptr Pointer to HTTP packet */
1017 /* content_length Pointer for returning content */
1018 /* length value */
1019 /* */
1020 /* OUTPUT */
1021 /* */
1022 /* status Completion status */
1023 /* */
1024 /* CALLS */
1025 /* */
1026 /* _nx_web_http_server_content_length_get */
1027 /* Actual get content length call*/
1028 /* */
1029 /* CALLED BY */
1030 /* */
1031 /* Application Code */
1032 /* */
1033 /* RELEASE HISTORY */
1034 /* */
1035 /* DATE NAME DESCRIPTION */
1036 /* */
1037 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1038 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1039 /* resulting in version 6.1 */
1040 /* */
1041 /**************************************************************************/
_nxe_web_http_server_content_length_get(NX_PACKET * packet_ptr,ULONG * content_length)1042 UINT _nxe_web_http_server_content_length_get(NX_PACKET *packet_ptr, ULONG *content_length)
1043 {
1044
1045 UINT status;
1046
1047
1048 /* Check for invalid input pointers. */
1049 if ((packet_ptr == NX_NULL) || (content_length == NX_NULL))
1050 return(NX_PTR_ERROR);
1051
1052 /* Call actual server content length get function. */
1053 status = _nx_web_http_server_content_length_get(packet_ptr, content_length);
1054
1055 /* Return completion status. */
1056 return status;
1057 }
1058
1059 /**************************************************************************/
1060 /* */
1061 /* FUNCTION RELEASE */
1062 /* */
1063 /* _nx_web_http_server_content_length_get PORTABLE C */
1064 /* 6.1 */
1065 /* AUTHOR */
1066 /* */
1067 /* Yuxin Zhou, Microsoft Corporation */
1068 /* */
1069 /* DESCRIPTION */
1070 /* */
1071 /* This function find a valid content length field and returns a */
1072 /* successful completion status (NX_SUCCESS) if so. Otherwise it */
1073 /* it returns an error status. A valid content length value is */
1074 /* zero or more and matches the size of the message body. */
1075 /* */
1076 /* */
1077 /* INPUT */
1078 /* */
1079 /* packet_ptr Pointer to HTTP request packet*/
1080 /* content_length Pointer to a valid Content */
1081 /* Length value */
1082 /* */
1083 /* OUTPUT */
1084 /* */
1085 /* NX_SUCCESS Content length extracted */
1086 /* status Invalid content length */
1087 /* */
1088 /* CALLS */
1089 /* */
1090 /* None */
1091 /* */
1092 /* CALLED BY */
1093 /* */
1094 /* Threads */
1095 /* */
1096 /* RELEASE HISTORY */
1097 /* */
1098 /* DATE NAME DESCRIPTION */
1099 /* */
1100 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1101 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1102 /* resulting in version 6.1 */
1103 /* */
1104 /**************************************************************************/
_nx_web_http_server_content_length_get(NX_PACKET * packet_ptr,ULONG * length)1105 UINT _nx_web_http_server_content_length_get(NX_PACKET *packet_ptr, ULONG *length)
1106 {
1107
1108 CHAR *buffer_ptr;
1109
1110
1111 /* Default the content length to no data. */
1112 *length = 0;
1113
1114 /* Setup pointer to buffer. */
1115 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
1116
1117 /* Find the "Content-length: " token first. */
1118 while (((buffer_ptr+17) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
1119 {
1120
1121 /* Check for the Content-length token. */
1122 if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) &&
1123 ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) &&
1124 ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) &&
1125 ((*(buffer_ptr+3) == 't') || (*(buffer_ptr+3) == 'T')) &&
1126 ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) &&
1127 ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) &&
1128 ((*(buffer_ptr+6) == 't') || (*(buffer_ptr+6) == 'T')) &&
1129 (*(buffer_ptr+7) == '-') &&
1130 ((*(buffer_ptr+8) == 'l') || (*(buffer_ptr+8) == 'L')) &&
1131 ((*(buffer_ptr+9) == 'e') || (*(buffer_ptr+9) == 'E')) &&
1132 ((*(buffer_ptr+10) == 'n') || (*(buffer_ptr+10) == 'N')) &&
1133 ((*(buffer_ptr+11) == 'g') || (*(buffer_ptr+11) == 'G')) &&
1134 ((*(buffer_ptr+12) == 't') || (*(buffer_ptr+12) == 'T')) &&
1135 ((*(buffer_ptr+13) == 'h') || (*(buffer_ptr+13) == 'H')) &&
1136 (*(buffer_ptr+14) == ':') &&
1137 (*(buffer_ptr+15) == ' '))
1138 {
1139
1140 /* Move the pointer up to the length token. */
1141 buffer_ptr = buffer_ptr + 16;
1142 break;
1143 }
1144
1145 /* Move the pointer up to the next character. */
1146 buffer_ptr++;
1147 }
1148
1149 /* Now convert the length into a numeric value. */
1150 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
1151 {
1152
1153 /* Update the content length. */
1154 *length = *length * 10;
1155 *length = *length + (((UINT) (*buffer_ptr)) - 0x30);
1156
1157 /* Move the buffer pointer forward. */
1158 buffer_ptr++;
1159 }
1160
1161 /* Determine if the content length was picked up properly. */
1162 if ((buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr) ||
1163 ((*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13)))
1164 {
1165
1166 /* Error, set the length to zero. */
1167 return NX_WEB_HTTP_INCOMPLETE_PUT_ERROR;
1168 }
1169
1170 /* Return successful completion status to the caller. */
1171 return NX_SUCCESS;
1172 }
1173
1174
1175 /**************************************************************************/
1176 /* */
1177 /* FUNCTION RELEASE */
1178 /* */
1179 /* _nxe_web_http_server_create PORTABLE C */
1180 /* 6.1 */
1181 /* AUTHOR */
1182 /* */
1183 /* Yuxin Zhou, Microsoft Corporation */
1184 /* */
1185 /* DESCRIPTION */
1186 /* */
1187 /* This function checks for errors in the HTTP server create call. */
1188 /* */
1189 /* */
1190 /* INPUT */
1191 /* */
1192 /* http_server_ptr Pointer to HTTP server */
1193 /* http_server_name Name of HTTP server */
1194 /* server_port Port to use for HTTP server */
1195 /* ip_ptr Pointer to IP instance */
1196 /* media_ptr Pointer to media structure */
1197 /* stack_ptr Server thread's stack pointer */
1198 /* stack_size Server thread's stack size */
1199 /* pool_ptr Pointer to packet pool */
1200 /* authentication_check Pointer to application's */
1201 /* authentication checking */
1202 /* request_notify Pointer to application's */
1203 /* request notify service */
1204 /* http_server_size Size of HTTP server */
1205 /* */
1206 /* OUTPUT */
1207 /* */
1208 /* status Completion status */
1209 /* */
1210 /* CALLS */
1211 /* */
1212 /* _nx_web_http_server_create Actual server create call */
1213 /* */
1214 /* CALLED BY */
1215 /* */
1216 /* Application Code */
1217 /* */
1218 /* RELEASE HISTORY */
1219 /* */
1220 /* DATE NAME DESCRIPTION */
1221 /* */
1222 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1223 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1224 /* resulting in version 6.1 */
1225 /* */
1226 /**************************************************************************/
_nxe_web_http_server_create(NX_WEB_HTTP_SERVER * http_server_ptr,CHAR * http_server_name,NX_IP * ip_ptr,UINT server_port,FX_MEDIA * media_ptr,VOID * stack_ptr,ULONG stack_size,NX_PACKET_POOL * pool_ptr,UINT (* authentication_check)(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,CHAR ** password,CHAR ** realm),UINT (* request_notify)(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,NX_PACKET * packet_ptr),UINT http_server_size)1227 UINT _nxe_web_http_server_create(NX_WEB_HTTP_SERVER *http_server_ptr, CHAR *http_server_name, NX_IP *ip_ptr, UINT server_port, FX_MEDIA *media_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr,
1228 UINT (*authentication_check)(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm),
1229 UINT (*request_notify)(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr), UINT http_server_size)
1230 {
1231
1232 NX_PACKET *packet_ptr;
1233 UINT status;
1234
1235
1236 /* Check for invalid input pointers. */
1237 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
1238 (http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id == NX_WEB_HTTP_SERVER_ID) ||
1239 (stack_ptr == NX_NULL) || (pool_ptr == NX_NULL) ||
1240 (http_server_size != sizeof(NX_WEB_HTTP_SERVER)))
1241 return(NX_PTR_ERROR);
1242
1243 /* Pickup a packet from the supplied packet pool. */
1244 packet_ptr = pool_ptr -> nx_packet_pool_available_list;
1245
1246 /* Determine if the packet payload is equal to or greater than the maximum HTTP header supported. */
1247 if (((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start) - NX_PHYSICAL_TRAILER)
1248 < NX_WEB_HTTP_SERVER_MIN_PACKET_SIZE)
1249 return(NX_WEB_HTTP_POOL_ERROR);
1250
1251 /* Call actual server create function. */
1252 status = _nx_web_http_server_create(http_server_ptr, http_server_name, ip_ptr, server_port, media_ptr, stack_ptr, stack_size, pool_ptr,
1253 authentication_check, request_notify);
1254
1255 /* Return completion status. */
1256 return(status);
1257 }
1258
1259
1260 /**************************************************************************/
1261 /* */
1262 /* FUNCTION RELEASE */
1263 /* */
1264 /* _nx_web_http_server_create PORTABLE C */
1265 /* 6.1 */
1266 /* AUTHOR */
1267 /* */
1268 /* Yuxin Zhou, Microsoft Corporation */
1269 /* */
1270 /* DESCRIPTION */
1271 /* */
1272 /* This function creates a HTTP server on the specified IP. In doing */
1273 /* so this function creates an TCP socket for subsequent HTTP */
1274 /* transfers and a thread for the HTTP server. */
1275 /* */
1276 /* Note: The string resource in callback functions authentication_check*/
1277 /* and request_notify is built by internal logic and always */
1278 /* NULL-terminated. */
1279 /* */
1280 /* */
1281 /* INPUT */
1282 /* */
1283 /* http_server_ptr Pointer to HTTP server */
1284 /* http_server_name Name of HTTP server */
1285 /* server_port Port for HTTP server */
1286 /* ip_ptr Pointer to IP instance */
1287 /* media_ptr Pointer to media structure */
1288 /* stack_ptr Server thread's stack pointer */
1289 /* stack_size Server thread's stack size */
1290 /* pool_ptr Pointer to packet pool */
1291 /* authentication_check Pointer to application's */
1292 /* authentication checking */
1293 /* request_notify Pointer to application's */
1294 /* request notify service */
1295 /* */
1296 /* OUTPUT */
1297 /* */
1298 /* status Completion status */
1299 /* */
1300 /* CALLS */
1301 /* */
1302 /* nx_tcp_socket_create Create HTTP server socket */
1303 /* nx_tcp_socket_delete Delete the HTTP server socket */
1304 /* tx_thread_create Create the HTTP server thread */
1305 /* */
1306 /* CALLED BY */
1307 /* */
1308 /* Application Code */
1309 /* */
1310 /* RELEASE HISTORY */
1311 /* */
1312 /* DATE NAME DESCRIPTION */
1313 /* */
1314 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1315 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1316 /* resulting in version 6.1 */
1317 /* */
1318 /**************************************************************************/
_nx_web_http_server_create(NX_WEB_HTTP_SERVER * http_server_ptr,CHAR * http_server_name,NX_IP * ip_ptr,UINT server_port,FX_MEDIA * media_ptr,VOID * stack_ptr,ULONG stack_size,NX_PACKET_POOL * pool_ptr,UINT (* authentication_check)(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,CHAR ** password,CHAR ** realm),UINT (* request_notify)(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,NX_PACKET * packet_ptr))1319 UINT _nx_web_http_server_create(NX_WEB_HTTP_SERVER *http_server_ptr,
1320 CHAR *http_server_name, NX_IP *ip_ptr,
1321 UINT server_port, FX_MEDIA *media_ptr,
1322 VOID *stack_ptr, ULONG stack_size,
1323 NX_PACKET_POOL *pool_ptr,
1324 UINT (*authentication_check)(NX_WEB_HTTP_SERVER *server_ptr,
1325 UINT request_type, CHAR *resource,
1326 CHAR **name, CHAR **password, CHAR **realm),
1327 UINT (*request_notify)(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type,
1328 CHAR *resource, NX_PACKET *packet_ptr))
1329 {
1330
1331 UINT status;
1332
1333
1334 /* Clear the HTTP server structure. */
1335 memset((void *) http_server_ptr, 0, sizeof(NX_WEB_HTTP_SERVER));
1336
1337 /* Create the Server's TCP socket. */
1338 status = nx_tcpserver_create(ip_ptr, &http_server_ptr -> nx_web_http_server_tcpserver, http_server_name,
1339 NX_WEB_HTTP_TYPE_OF_SERVICE, NX_WEB_HTTP_FRAGMENT_OPTION, NX_WEB_HTTP_TIME_TO_LIVE,
1340 NX_WEB_HTTP_SERVER_WINDOW_SIZE, NX_NULL,
1341 _nx_web_http_server_receive_data, _nx_web_http_server_connection_end,
1342 _nx_web_http_server_connection_timeout, NX_WEB_HTTP_SERVER_TIMEOUT / NX_IP_PERIODIC_RATE,
1343 stack_ptr, stack_size, http_server_ptr -> nx_web_http_server_session_buffer,
1344 NX_WEB_HTTP_SERVER_SESSION_BUFFER_SIZE, NX_WEB_HTTP_SERVER_PRIORITY, NX_WEB_HTTP_SERVER_TIMEOUT_ACCEPT);
1345
1346 /* Determine if an error occurred. */
1347 if (status != NX_SUCCESS)
1348 {
1349
1350 /* Yes, return error code. */
1351 return(status);
1352 }
1353
1354 /* Store server ptr. */
1355 http_server_ptr -> nx_web_http_server_tcpserver.nx_tcpserver_reserved = (ULONG)http_server_ptr;
1356
1357 /* Save the Server name. */
1358 http_server_ptr -> nx_web_http_server_name = http_server_name;
1359
1360 /* Save the IP pointer address. */
1361 http_server_ptr -> nx_web_http_server_ip_ptr = ip_ptr;
1362
1363 /* Save the packet pool pointer. */
1364 http_server_ptr -> nx_web_http_server_packet_pool_ptr = pool_ptr;
1365
1366 /* Save the media pointer address. */
1367 http_server_ptr -> nx_web_http_server_media_ptr = media_ptr;
1368
1369 /* Save the user-supplied routines, if specified. */
1370 http_server_ptr -> nx_web_http_server_authentication_check = authentication_check;
1371 http_server_ptr -> nx_web_http_server_request_notify = request_notify;
1372
1373 /* Set the server ID to indicate the HTTP server is ready. */
1374 http_server_ptr -> nx_web_http_server_id = NX_WEB_HTTP_SERVER_ID;
1375
1376 /* Set the port to the default HTTP listening port (80). */
1377 http_server_ptr -> nx_web_http_server_listen_port = server_port;
1378
1379 /* Return successful completion. */
1380 return(NX_SUCCESS);
1381 }
1382
1383
1384 /**************************************************************************/
1385 /* */
1386 /* FUNCTION RELEASE */
1387 /* */
1388 /* _nxe_web_http_server_delete PORTABLE C */
1389 /* 6.1 */
1390 /* AUTHOR */
1391 /* */
1392 /* Yuxin Zhou, Microsoft Corporation */
1393 /* */
1394 /* DESCRIPTION */
1395 /* */
1396 /* This function checks for errors in the HTTP server delete call. */
1397 /* */
1398 /* */
1399 /* INPUT */
1400 /* */
1401 /* http_server_ptr Pointer to HTTP server */
1402 /* */
1403 /* OUTPUT */
1404 /* */
1405 /* status Completion status */
1406 /* */
1407 /* CALLS */
1408 /* */
1409 /* _nx_web_http_server_delete Actual server delete call */
1410 /* */
1411 /* CALLED BY */
1412 /* */
1413 /* Application Code */
1414 /* */
1415 /* RELEASE HISTORY */
1416 /* */
1417 /* DATE NAME DESCRIPTION */
1418 /* */
1419 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1420 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1421 /* resulting in version 6.1 */
1422 /* */
1423 /**************************************************************************/
_nxe_web_http_server_delete(NX_WEB_HTTP_SERVER * http_server_ptr)1424 UINT _nxe_web_http_server_delete(NX_WEB_HTTP_SERVER *http_server_ptr)
1425 {
1426
1427 UINT status;
1428
1429
1430 /* Check for invalid input pointers. */
1431 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID))
1432 return(NX_PTR_ERROR);
1433
1434 /* Check for appropriate caller. */
1435 NX_THREADS_ONLY_CALLER_CHECKING
1436
1437 /* Call actual server delete function. */
1438 status = _nx_web_http_server_delete(http_server_ptr);
1439
1440 /* Return completion status. */
1441 return(status);
1442 }
1443
1444
1445 /**************************************************************************/
1446 /* */
1447 /* FUNCTION RELEASE */
1448 /* */
1449 /* _nx_web_http_server_delete PORTABLE C */
1450 /* 6.1 */
1451 /* AUTHOR */
1452 /* */
1453 /* Yuxin Zhou, Microsoft Corporation */
1454 /* */
1455 /* DESCRIPTION */
1456 /* */
1457 /* This function deletes a previously created HTTP server on the */
1458 /* specified IP. */
1459 /* */
1460 /* */
1461 /* INPUT */
1462 /* */
1463 /* http_server_ptr Pointer to HTTP server */
1464 /* */
1465 /* OUTPUT */
1466 /* */
1467 /* status Completion status */
1468 /* */
1469 /* CALLS */
1470 /* */
1471 /* nx_tcp_socket_delete Delete the HTTP server socket */
1472 /* nx_tcp_socket_disconnect Disconnect HTTP server socket */
1473 /* nx_tcp_socket_unaccept Unaccept HTTP server connect */
1474 /* nx_tcp_socket_unlisten Unlisten on the HTTP port */
1475 /* tx_thread_delete Delete the HTTP server thread */
1476 /* tx_thread_suspend Suspend the HTTP server thread*/
1477 /* tx_thread_terminate Terminate the HTTP server */
1478 /* thread */
1479 /* */
1480 /* CALLED BY */
1481 /* */
1482 /* Application Code */
1483 /* */
1484 /* RELEASE HISTORY */
1485 /* */
1486 /* DATE NAME DESCRIPTION */
1487 /* */
1488 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1489 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1490 /* resulting in version 6.1 */
1491 /* */
1492 /**************************************************************************/
_nx_web_http_server_delete(NX_WEB_HTTP_SERVER * http_server_ptr)1493 UINT _nx_web_http_server_delete(NX_WEB_HTTP_SERVER *http_server_ptr)
1494 {
1495 UINT status;
1496 NX_TCPSERVER *tcpserver_ptr = &(http_server_ptr -> nx_web_http_server_tcpserver);
1497
1498
1499 #ifdef NX_WEB_HTTPS_ENABLE
1500 UINT i;
1501
1502 /* Stop TLS session if using HTTPS. */
1503 if(http_server_ptr -> nx_web_http_is_https_server)
1504 {
1505 for(i = 0; i < tcpserver_ptr -> nx_tcpserver_sessions_count; i++)
1506 {
1507 nx_secure_tls_session_end(&(tcpserver_ptr -> nx_tcpserver_sessions[i].nx_tcp_session_tls_session), NX_WAIT_FOREVER);
1508 nx_secure_tls_session_delete(&(tcpserver_ptr -> nx_tcpserver_sessions[i].nx_tcp_session_tls_session));
1509 }
1510 }
1511
1512 #endif
1513
1514 /* Delete the TCP server. */
1515 status = nx_tcpserver_delete(tcpserver_ptr);
1516
1517 /* Clear the server ID to indicate the HTTP server is no longer ready. */
1518 http_server_ptr -> nx_web_http_server_id = 0;
1519
1520 /* Return status. */
1521 return(status);
1522 }
1523
1524
1525 /**************************************************************************/
1526 /* */
1527 /* FUNCTION RELEASE */
1528 /* */
1529 /* _nxe_web_http_server_param_get PORTABLE C */
1530 /* 6.1 */
1531 /* AUTHOR */
1532 /* */
1533 /* Yuxin Zhou, Microsoft Corporation */
1534 /* */
1535 /* DESCRIPTION */
1536 /* */
1537 /* This function checks for errors in the HTTP parameter get call. */
1538 /* */
1539 /* */
1540 /* INPUT */
1541 /* */
1542 /* packet_ptr Pointer to HTTP request packet*/
1543 /* param_number Parameter number (start at 0) */
1544 /* param_ptr Pointer to destination */
1545 /* max_param_size Maximum size of destination */
1546 /* */
1547 /* OUTPUT */
1548 /* */
1549 /* status Completion status */
1550 /* */
1551 /* CALLS */
1552 /* */
1553 /* _nx_web_http_server_param_get Actual server parameter get */
1554 /* call */
1555 /* */
1556 /* CALLED BY */
1557 /* */
1558 /* Application Code */
1559 /* */
1560 /* RELEASE HISTORY */
1561 /* */
1562 /* DATE NAME DESCRIPTION */
1563 /* */
1564 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1565 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1566 /* resulting in version 6.1 */
1567 /* */
1568 /**************************************************************************/
_nxe_web_http_server_param_get(NX_PACKET * packet_ptr,UINT param_number,CHAR * param_ptr,UINT * param_size,UINT max_param_size)1569 UINT _nxe_web_http_server_param_get(NX_PACKET *packet_ptr, UINT param_number, CHAR *param_ptr, UINT *param_size, UINT max_param_size)
1570 {
1571
1572 UINT status;
1573
1574
1575 /* Check for invalid input pointers. */
1576 if ((packet_ptr == NX_NULL) || (param_ptr == NX_NULL) || (param_size == NX_NULL))
1577 return(NX_PTR_ERROR);
1578
1579 /* Check for appropriate caller. */
1580 NX_THREADS_ONLY_CALLER_CHECKING
1581
1582 /* Call actual server parameter get function. */
1583 status = _nx_web_http_server_param_get(packet_ptr, param_number, param_ptr, param_size, max_param_size);
1584
1585 /* Return completion status. */
1586 return(status);
1587 }
1588
1589
1590 /**************************************************************************/
1591 /* */
1592 /* FUNCTION RELEASE */
1593 /* */
1594 /* _nx_web_http_server_param_get PORTABLE C */
1595 /* 6.1 */
1596 /* AUTHOR */
1597 /* */
1598 /* Yuxin Zhou, Microsoft Corporation */
1599 /* */
1600 /* DESCRIPTION */
1601 /* */
1602 /* This function returns the requested parameter specified in the URL */
1603 /* requested by the client. If the specified parameter is not present, */
1604 /* a not found error is returned to the caller. */
1605 /* */
1606 /* */
1607 /* INPUT */
1608 /* */
1609 /* packet_ptr Pointer to HTTP request packet*/
1610 /* param_number Parameter number (start at 0) */
1611 /* param_ptr Pointer to destination */
1612 /* max_param_size Maximum size of destination */
1613 /* */
1614 /* OUTPUT */
1615 /* */
1616 /* status Completion status */
1617 /* */
1618 /* CALLS */
1619 /* */
1620 /* None */
1621 /* */
1622 /* CALLED BY */
1623 /* */
1624 /* Application Code */
1625 /* */
1626 /* RELEASE HISTORY */
1627 /* */
1628 /* DATE NAME DESCRIPTION */
1629 /* */
1630 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1631 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1632 /* resulting in version 6.1 */
1633 /* */
1634 /**************************************************************************/
_nx_web_http_server_param_get(NX_PACKET * packet_ptr,UINT param_number,CHAR * param_ptr,UINT * param_size,UINT max_param_size)1635 UINT _nx_web_http_server_param_get(NX_PACKET *packet_ptr, UINT param_number, CHAR *param_ptr, UINT *param_size, UINT max_param_size)
1636 {
1637
1638 UINT i;
1639 UINT current_param;
1640 CHAR *buffer_ptr;
1641
1642
1643 /* Set the destination string to NULL. */
1644 param_ptr[0] = (CHAR) NX_NULL;
1645 *param_size = 0;
1646
1647 /* Set current parameter to 0. */
1648 current_param = 0;
1649
1650 /* Setup a pointer to the HTTP buffer. */
1651 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
1652
1653 /* Position to the start of the URL. */
1654 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != '/'))
1655 {
1656
1657 /* Move the buffer pointer. */
1658 buffer_ptr++;
1659 }
1660
1661 /* Not find URL. */
1662 if (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr)
1663 {
1664 return(NX_WEB_HTTP_NOT_FOUND);
1665 }
1666
1667 /* Loop through the buffer to search for the specified parameter. */
1668 do
1669 {
1670
1671 /* Determine if the character is a semicolon, indicating a parameter
1672 is present. */
1673 if (*buffer_ptr == ';')
1674 {
1675
1676 /* Yes, a parameter is present. */
1677
1678 /* Move the buffer pointer forward. */
1679 buffer_ptr++;
1680
1681 /* Is this the parameter requested? */
1682 if (current_param == param_number)
1683 {
1684
1685
1686 /* Yes, we have found the parameter. */
1687 for (i = 0; i < max_param_size; i++)
1688 {
1689
1690 /* Check if reach the end of the packet data. */
1691 if (buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr)
1692 {
1693 return(NX_WEB_HTTP_NOT_FOUND);
1694 }
1695
1696 /* Check for end of parameter. */
1697 if ((*buffer_ptr == ';') || (*buffer_ptr == '?') ||
1698 (*buffer_ptr == '&') || (*buffer_ptr == ' ') ||
1699 (*buffer_ptr == (CHAR) 13))
1700 {
1701
1702 /* Yes, we are finished and need to get out of the loop. */
1703 break;
1704 }
1705
1706 /* Otherwise, store the character in the destination. */
1707 param_ptr[i] = *buffer_ptr++;
1708 }
1709
1710 /* NULL terminate the parameter. */
1711 if (i < max_param_size)
1712 {
1713 param_ptr[i] = (CHAR) NX_NULL;
1714 }
1715
1716 /* Return to caller. */
1717 if (param_ptr[i] == (CHAR) NX_NULL)
1718 {
1719 *param_size = i;
1720 return(NX_SUCCESS);
1721 }
1722 else
1723 {
1724 return(NX_WEB_HTTP_IMPROPERLY_TERMINATED_PARAM);
1725 }
1726 }
1727 else
1728 {
1729
1730 /* Increment the current parameter. */
1731 current_param++;
1732 }
1733 }
1734 else
1735 {
1736
1737 /* Check for any other character that signals the end of the param list. */
1738 if ((*buffer_ptr == '?') || (*buffer_ptr == ' ') || (*buffer_ptr == '&'))
1739 break;
1740
1741 /* Update the buffer pointer. */
1742 buffer_ptr++;
1743 }
1744
1745 } while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 13));
1746
1747 /* Return a not found error. */
1748 return(NX_WEB_HTTP_NOT_FOUND);
1749 }
1750
1751
1752 /**************************************************************************/
1753 /* */
1754 /* FUNCTION RELEASE */
1755 /* */
1756 /* _nxe_web_http_server_query_get PORTABLE C */
1757 /* 6.1 */
1758 /* AUTHOR */
1759 /* */
1760 /* Yuxin Zhou, Microsoft Corporation */
1761 /* */
1762 /* DESCRIPTION */
1763 /* */
1764 /* This function checks for errors in the HTTP query get call. */
1765 /* */
1766 /* */
1767 /* INPUT */
1768 /* */
1769 /* packet_ptr Pointer to HTTP request packet*/
1770 /* query_number Query number (start at 0) */
1771 /* query_ptr Pointer to destination */
1772 /* query_size Pointer to data size return */
1773 /* max_query_size Maximum size of destination */
1774 /* */
1775 /* OUTPUT */
1776 /* */
1777 /* status Completion status */
1778 /* */
1779 /* CALLS */
1780 /* */
1781 /* _nx_web_http_server_query_get Actual server query get */
1782 /* call */
1783 /* */
1784 /* CALLED BY */
1785 /* */
1786 /* Application Code */
1787 /* */
1788 /* RELEASE HISTORY */
1789 /* */
1790 /* DATE NAME DESCRIPTION */
1791 /* */
1792 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1793 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1794 /* resulting in version 6.1 */
1795 /* */
1796 /**************************************************************************/
_nxe_web_http_server_query_get(NX_PACKET * packet_ptr,UINT query_number,CHAR * query_ptr,UINT * query_size,UINT max_query_size)1797 UINT _nxe_web_http_server_query_get(NX_PACKET *packet_ptr, UINT query_number, CHAR *query_ptr, UINT *query_size, UINT max_query_size)
1798 {
1799
1800 UINT status;
1801
1802
1803 /* Check for invalid input pointers. */
1804 if ((packet_ptr == NX_NULL) || (query_ptr == NX_NULL) || (query_size == NX_NULL))
1805 return(NX_PTR_ERROR);
1806
1807 /* Check for appropriate caller. */
1808 NX_THREADS_ONLY_CALLER_CHECKING
1809
1810 /* Call actual server query get function. */
1811 status = _nx_web_http_server_query_get(packet_ptr, query_number, query_ptr, query_size, max_query_size);
1812
1813 /* Return completion status. */
1814 return(status);
1815 }
1816
1817
1818 /**************************************************************************/
1819 /* */
1820 /* FUNCTION RELEASE */
1821 /* */
1822 /* _nx_web_http_server_query_get PORTABLE C */
1823 /* 6.1 */
1824 /* AUTHOR */
1825 /* */
1826 /* Yuxin Zhou, Microsoft Corporation */
1827 /* */
1828 /* DESCRIPTION */
1829 /* */
1830 /* This function returns the requested query specified in the URL */
1831 /* requested by the client. If the specified query is not present, */
1832 /* a not found error is returned to the caller. */
1833 /* */
1834 /* */
1835 /* INPUT */
1836 /* */
1837 /* packet_ptr Pointer to HTTP request packet*/
1838 /* query_number Query number (start at 0) */
1839 /* query_ptr Pointer to destination */
1840 /* query_size Pointer to data size return */
1841 /* max_query_size Maximum size of destination */
1842 /* */
1843 /* OUTPUT */
1844 /* */
1845 /* status Completion status */
1846 /* */
1847 /* CALLS */
1848 /* */
1849 /* None */
1850 /* */
1851 /* CALLED BY */
1852 /* */
1853 /* Application Code */
1854 /* */
1855 /* RELEASE HISTORY */
1856 /* */
1857 /* DATE NAME DESCRIPTION */
1858 /* */
1859 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1860 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1861 /* resulting in version 6.1 */
1862 /* */
1863 /**************************************************************************/
_nx_web_http_server_query_get(NX_PACKET * packet_ptr,UINT query_number,CHAR * query_ptr,UINT * query_size,UINT max_query_size)1864 UINT _nx_web_http_server_query_get(NX_PACKET *packet_ptr, UINT query_number, CHAR *query_ptr, UINT *query_size, UINT max_query_size)
1865 {
1866
1867 UINT i;
1868 UINT current_query;
1869 CHAR *buffer_ptr;
1870
1871
1872 /* Set the destination string to NULL. */
1873 query_ptr[0] = (CHAR) NX_NULL;
1874 *query_size = 0;
1875
1876 /* Set current query number to 0. */
1877 current_query = 0;
1878
1879 /* Setup a pointer to the HTTP buffer. */
1880 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
1881
1882 /* Position to the start of the URL. */
1883 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != '/'))
1884 {
1885
1886 /* Move the buffer pointer. */
1887 buffer_ptr++;
1888 }
1889
1890 /* Not find URL. */
1891 if (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr)
1892 {
1893 return(NX_WEB_HTTP_NOT_FOUND);
1894 }
1895
1896 /* Loop through the buffer to search for the specified query instance. */
1897 do
1898 {
1899
1900 /* Determine if the character is a '?' or a '&', indicating a query
1901 is present. */
1902 if (((*buffer_ptr == '?') && (current_query == 0)) ||
1903 ((*buffer_ptr == '&') && (current_query != 0)))
1904 {
1905
1906 /* Yes, a query is present. */
1907
1908 /* Move the buffer pointer forward. */
1909 buffer_ptr++;
1910
1911 /* Is this the query requested? */
1912 if (current_query == query_number)
1913 {
1914
1915
1916 /* Yes, we have found the query. */
1917 for (i = 0; i < max_query_size; i++)
1918 {
1919
1920 /* Check if reach the end of the packet data. */
1921 if (buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr)
1922 {
1923 return(NX_WEB_HTTP_NOT_FOUND);
1924 }
1925
1926 /* Check for end of query. */
1927 if ((*buffer_ptr == ';') || (*buffer_ptr == '?') ||
1928 (*buffer_ptr == '&') || (*buffer_ptr == ' ') ||
1929 (*buffer_ptr == (CHAR) 13))
1930 {
1931
1932 /* Yes, we are finished and need to get out of the loop. */
1933 break;
1934 }
1935
1936 /* Otherwise, store the character in the destination. */
1937 query_ptr[i] = *buffer_ptr++;
1938 }
1939
1940 /* NULL terminate the query. */
1941 query_ptr[i] = (CHAR) NX_NULL;
1942
1943 /* Return to caller. */
1944 if (i)
1945 {
1946 *query_size = i;
1947 return(NX_SUCCESS);
1948 }
1949 else
1950 {
1951 return(NX_WEB_HTTP_NO_QUERY_PARSED);
1952 }
1953 }
1954 else
1955 {
1956
1957 /* Increment the current query. */
1958 current_query++;
1959 }
1960 }
1961 else
1962 {
1963
1964 /* Check for any other character that signals the end of the query list. */
1965 if ((*buffer_ptr == '?') || (*buffer_ptr == ' ') || (*buffer_ptr == ';'))
1966 break;
1967
1968 /* Update the buffer pointer. */
1969 buffer_ptr++;
1970 }
1971
1972 } while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 13));
1973
1974 /* Return a not found error. */
1975 return(NX_WEB_HTTP_NOT_FOUND);
1976 }
1977
1978
1979 /**************************************************************************/
1980 /* */
1981 /* FUNCTION RELEASE */
1982 /* */
1983 /* _nxe_web_http_server_start PORTABLE C */
1984 /* 6.1 */
1985 /* AUTHOR */
1986 /* */
1987 /* Yuxin Zhou, Microsoft Corporation */
1988 /* */
1989 /* DESCRIPTION */
1990 /* */
1991 /* This function checks for errors in the HTTP server start call. */
1992 /* */
1993 /* */
1994 /* INPUT */
1995 /* */
1996 /* http_server_ptr Pointer to HTTP server */
1997 /* */
1998 /* OUTPUT */
1999 /* */
2000 /* status Completion status */
2001 /* */
2002 /* CALLS */
2003 /* */
2004 /* _nx_web_http_server_start Actual server start call */
2005 /* */
2006 /* CALLED BY */
2007 /* */
2008 /* Application Code */
2009 /* */
2010 /* RELEASE HISTORY */
2011 /* */
2012 /* DATE NAME DESCRIPTION */
2013 /* */
2014 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2015 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2016 /* resulting in version 6.1 */
2017 /* */
2018 /**************************************************************************/
_nxe_web_http_server_start(NX_WEB_HTTP_SERVER * http_server_ptr)2019 UINT _nxe_web_http_server_start(NX_WEB_HTTP_SERVER *http_server_ptr)
2020 {
2021
2022 UINT status;
2023
2024
2025 /* Check for invalid input pointers. */
2026 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID))
2027 return(NX_PTR_ERROR);
2028
2029 /* Call actual server start function. */
2030 status = _nx_web_http_server_start(http_server_ptr);
2031
2032 /* Return completion status. */
2033 return(status);
2034 }
2035
2036
2037 /**************************************************************************/
2038 /* */
2039 /* FUNCTION RELEASE */
2040 /* */
2041 /* _nx_web_http_server_start PORTABLE C */
2042 /* 6.1 */
2043 /* AUTHOR */
2044 /* */
2045 /* Yuxin Zhou, Microsoft Corporation */
2046 /* */
2047 /* DESCRIPTION */
2048 /* */
2049 /* This function starts a previously created HTTP server on the */
2050 /* specified IP. */
2051 /* */
2052 /* */
2053 /* INPUT */
2054 /* */
2055 /* http_server_ptr Pointer to HTTP server */
2056 /* */
2057 /* OUTPUT */
2058 /* */
2059 /* status Completion status */
2060 /* */
2061 /* CALLS */
2062 /* */
2063 /* nx_tcp_server_socket_listen Start listening on HTTP port */
2064 /* tx_thread_resume Resume the HTTP server thread */
2065 /* */
2066 /* CALLED BY */
2067 /* */
2068 /* Application Code */
2069 /* */
2070 /* RELEASE HISTORY */
2071 /* */
2072 /* DATE NAME DESCRIPTION */
2073 /* */
2074 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2075 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2076 /* resulting in version 6.1 */
2077 /* */
2078 /**************************************************************************/
_nx_web_http_server_start(NX_WEB_HTTP_SERVER * http_server_ptr)2079 UINT _nx_web_http_server_start(NX_WEB_HTTP_SERVER *http_server_ptr)
2080 {
2081
2082 UINT status;
2083 UINT port;
2084
2085 port = http_server_ptr -> nx_web_http_server_listen_port;
2086
2087 /* Start listening on the HTTP server port. */
2088 status = nx_tcpserver_start(&http_server_ptr -> nx_web_http_server_tcpserver, port, NX_WEB_HTTP_SERVER_MAX_PENDING);
2089
2090 /* Determine if the listen was unsuccessful. */
2091 if (status != NX_SUCCESS)
2092 {
2093 /* Just return an HTTP error. */
2094 return(status);
2095 }
2096
2097 /* Return successful completion. */
2098 return(NX_SUCCESS);
2099 }
2100
2101 #ifdef NX_WEB_HTTPS_ENABLE
2102
2103 /**************************************************************************/
2104 /* */
2105 /* FUNCTION RELEASE */
2106 /* */
2107 /* _nxe_web_http_server_secure_configure PORTABLE C */
2108 /* 6.1 */
2109 /* AUTHOR */
2110 /* */
2111 /* Yuxin Zhou, Microsoft Corporation */
2112 /* */
2113 /* DESCRIPTION */
2114 /* */
2115 /* This function checks for errors in the HTTPS configuration call. */
2116 /* */
2117 /* INPUT */
2118 /* */
2119 /* http_server_ptr Pointer to HTTP server */
2120 /* crypto_table TLS cryptographic routines */
2121 /* metadata_buffer Cryptographic metadata buffer */
2122 /* metadata_size Size of metadata buffer */
2123 /* packet_buffer TLS packet buffer */
2124 /* packet_size Size of packet buffer */
2125 /* identity_certificate TLS server certificate */
2126 /* trusted_certificates TLS trusted certificates */
2127 /* trusted_certs_num Number of trusted certs */
2128 /* remote_certificates Remote certificates array */
2129 /* remote_certs_num Number of remote certificates */
2130 /* remote_certificate_buffer Buffer for remote certs */
2131 /* remote_cert_buffer_size Size of remote cert buffer */
2132 /* */
2133 /* OUTPUT */
2134 /* */
2135 /* status Completion status */
2136 /* */
2137 /* CALLS */
2138 /* */
2139 /* _nx_web_http_server_secure_configure Actual server configure call */
2140 /* */
2141 /* CALLED BY */
2142 /* */
2143 /* Application Code */
2144 /* */
2145 /* RELEASE HISTORY */
2146 /* */
2147 /* DATE NAME DESCRIPTION */
2148 /* */
2149 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2150 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2151 /* resulting in version 6.1 */
2152 /* */
2153 /**************************************************************************/
_nxe_web_http_server_secure_configure(NX_WEB_HTTP_SERVER * http_server_ptr,const NX_SECURE_TLS_CRYPTO * crypto_table,VOID * metadata_buffer,ULONG metadata_size,UCHAR * packet_buffer,UINT packet_buffer_size,NX_SECURE_X509_CERT * identity_certificate,NX_SECURE_X509_CERT * trusted_certificates[],UINT trusted_certs_num,NX_SECURE_X509_CERT * remote_certificates[],UINT remote_certs_num,UCHAR * remote_certificate_buffer,UINT remote_cert_buffer_size)2154 UINT _nxe_web_http_server_secure_configure(NX_WEB_HTTP_SERVER *http_server_ptr, const NX_SECURE_TLS_CRYPTO *crypto_table,
2155 VOID *metadata_buffer, ULONG metadata_size,
2156 UCHAR* packet_buffer, UINT packet_buffer_size,
2157 NX_SECURE_X509_CERT *identity_certificate,
2158 NX_SECURE_X509_CERT *trusted_certificates[],
2159 UINT trusted_certs_num,
2160 NX_SECURE_X509_CERT *remote_certificates[],
2161 UINT remote_certs_num,
2162 UCHAR *remote_certificate_buffer,
2163 UINT remote_cert_buffer_size)
2164 {
2165
2166 UINT status;
2167
2168
2169 /* Check for invalid input pointers. Note that the remote certificates array and buffer
2170 * may be NX_NULL for the HTTPS server since remote certificates are optional for TLS Server.*/
2171 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
2172 crypto_table == NX_NULL || metadata_buffer == NX_NULL || packet_buffer == NX_NULL ||
2173 identity_certificate == NX_NULL)
2174 {
2175 return(NX_PTR_ERROR);
2176 }
2177
2178 /* Call actual server start function. */
2179 status = _nx_web_http_server_secure_configure(http_server_ptr, crypto_table, metadata_buffer, metadata_size,
2180 packet_buffer, packet_buffer_size, identity_certificate,
2181 trusted_certificates, trusted_certs_num,
2182 remote_certificates, remote_certs_num, remote_certificate_buffer,
2183 remote_cert_buffer_size);
2184
2185 /* Return completion status. */
2186 return(status);
2187 }
2188
2189
2190 /**************************************************************************/
2191 /* */
2192 /* FUNCTION RELEASE */
2193 /* */
2194 /* _nx_web_http_server_secure_configure PORTABLE C */
2195 /* 6.1.11 */
2196 /* AUTHOR */
2197 /* */
2198 /* Yuxin Zhou, Microsoft Corporation */
2199 /* */
2200 /* DESCRIPTION */
2201 /* */
2202 /* This function configures a previously created NetX Web HTTP server */
2203 /* instance to use TLS for secure HTTPS communications. The parameters */
2204 /* are used to configure all the possible TLS sessions with identical */
2205 /* state so that each incoming HTTPS client experiences consistent */
2206 /* behavior. The number of TLS sessions is controlled using the macro */
2207 /* NX_WEB_HTTP_SERVER_SESSION_MAX. */
2208 /* */
2209 /* The cryptographic routine table (ciphersuite table) is shared */
2210 /* between all TLS sessions as it just contains function pointers. */
2211 /* */
2212 /* The metadata buffer and packet reassembly buffer are divided */
2213 /* equally between all TLS sessions. If the buffer size is not evenly */
2214 /* divisible by the number of sessions the remainder will be unused. */
2215 /* */
2216 /* The passed-in identity certificate is used by all sessions. During */
2217 /* TLS operation the server identity certificate is only read from so */
2218 /* copies are not needed for each session. */
2219 /* */
2220 /* The trusted certificates are added to the trusted store for each */
2221 /* TLS session in the server. This is used for client certificate */
2222 /* verification which is enabled if remote certificates are provided. */
2223 /* */
2224 /* The remote certificate array and buffer is shared by default */
2225 /* between all TLS sessions. This does mean that some sessions may */
2226 /* block during certificate validation. */
2227 /* */
2228 /* INPUT */
2229 /* */
2230 /* http_server_ptr Pointer to HTTP server */
2231 /* crypto_table TLS cryptographic routines */
2232 /* metadata_buffer Cryptographic metadata buffer */
2233 /* metadata_size Size of metadata buffer */
2234 /* packet_buffer TLS packet buffer */
2235 /* packet_size Size of packet buffer */
2236 /* identity_certificate TLS server certificate */
2237 /* trusted_certificates TLS trusted certificates */
2238 /* trusted_certs_num Number of trusted certs */
2239 /* remote_certificates Remote certificates array */
2240 /* remote_certs_num Number of remote certificates */
2241 /* remote_certificate_buffer Buffer for remote certs */
2242 /* remote_cert_buffer_size Size of remote cert buffer */
2243 /* */
2244 /* OUTPUT */
2245 /* */
2246 /* status Completion status */
2247 /* */
2248 /* CALLS */
2249 /* */
2250 /* nx_tcpserver_tls_setup Socket server TLS configure */
2251 /* */
2252 /* CALLED BY */
2253 /* */
2254 /* Application Code */
2255 /* */
2256 /* RELEASE HISTORY */
2257 /* */
2258 /* DATE NAME DESCRIPTION */
2259 /* */
2260 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2261 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2262 /* resulting in version 6.1 */
2263 /* 04-25-2022 Yuxin Zhou Modified comment(s), */
2264 /* resulting in version 6.1.11 */
2265 /* */
2266 /**************************************************************************/
_nx_web_http_server_secure_configure(NX_WEB_HTTP_SERVER * http_server_ptr,const NX_SECURE_TLS_CRYPTO * crypto_table,VOID * metadata_buffer,ULONG metadata_size,UCHAR * packet_buffer,UINT packet_buffer_size,NX_SECURE_X509_CERT * identity_certificate,NX_SECURE_X509_CERT * trusted_certificates[],UINT trusted_certs_num,NX_SECURE_X509_CERT * remote_certificates[],UINT remote_certs_num,UCHAR * remote_certificate_buffer,UINT remote_cert_buffer_size)2267 UINT _nx_web_http_server_secure_configure(NX_WEB_HTTP_SERVER *http_server_ptr, const NX_SECURE_TLS_CRYPTO *crypto_table,
2268 VOID *metadata_buffer, ULONG metadata_size,
2269 UCHAR* packet_buffer, UINT packet_buffer_size,
2270 NX_SECURE_X509_CERT *identity_certificate,
2271 NX_SECURE_X509_CERT *trusted_certificates[],
2272 UINT trusted_certs_num,
2273 NX_SECURE_X509_CERT *remote_certificates[],
2274 UINT remote_certs_num,
2275 UCHAR *remote_certificate_buffer,
2276 UINT remote_cert_buffer_size)
2277 {
2278
2279 UINT status;
2280
2281 /* This is a secure HTTP server, so set HTTPS flag. */
2282 http_server_ptr -> nx_web_http_is_https_server = NX_TRUE;
2283
2284 /* Configure TLS for the socket server. */
2285 status = nx_tcpserver_tls_setup(&http_server_ptr->nx_web_http_server_tcpserver,
2286 crypto_table, metadata_buffer, metadata_size,
2287 packet_buffer, packet_buffer_size, identity_certificate,
2288 trusted_certificates, trusted_certs_num,
2289 remote_certificates, remote_certs_num,
2290 remote_certificate_buffer,remote_cert_buffer_size);
2291
2292 /* Return result of TLS setup. */
2293 return(status);
2294 }
2295
2296 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
2297 /**************************************************************************/
2298 /* */
2299 /* FUNCTION RELEASE */
2300 /* */
2301 /* _nxe_web_http_server_secure_ecc_configure PORTABLE C */
2302 /* 6.1.11 */
2303 /* AUTHOR */
2304 /* */
2305 /* Yuxin Zhou, Microsoft Corporation */
2306 /* */
2307 /* DESCRIPTION */
2308 /* */
2309 /* This function checks for errors in the HTTPS ECC configuration call.*/
2310 /* */
2311 /* INPUT */
2312 /* */
2313 /* http_server_ptr Pointer to HTTP server */
2314 /* supported_groups List of supported groups */
2315 /* supported_group_count Number of supported groups */
2316 /* curves List of curve methods */
2317 /* */
2318 /* OUTPUT */
2319 /* */
2320 /* status Completion status */
2321 /* */
2322 /* CALLS */
2323 /* */
2324 /* _nx_web_http_server_secure_ecc_configure */
2325 /* Actual ECC configuration call */
2326 /* */
2327 /* CALLED BY */
2328 /* */
2329 /* Application Code */
2330 /* */
2331 /* RELEASE HISTORY */
2332 /* */
2333 /* DATE NAME DESCRIPTION */
2334 /* */
2335 /* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */
2336 /* */
2337 /**************************************************************************/
_nxe_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER * http_server_ptr,const USHORT * supported_groups,USHORT supported_group_count,const NX_CRYPTO_METHOD ** curves)2338 UINT _nxe_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr,
2339 const USHORT *supported_groups, USHORT supported_group_count,
2340 const NX_CRYPTO_METHOD **curves)
2341 {
2342 UINT status;
2343
2344 /* Check for invalid input pointers. */
2345 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
2346 (supported_groups == NX_NULL) || (supported_group_count == 0) || (curves == NX_NULL))
2347 {
2348 return(NX_PTR_ERROR);
2349 }
2350
2351 /* Call actual ECC configuration function. */
2352 status = _nx_web_http_server_secure_ecc_configure(http_server_ptr, supported_groups, supported_group_count, curves);
2353 return(status);
2354 }
2355
2356 /**************************************************************************/
2357 /* */
2358 /* FUNCTION RELEASE */
2359 /* */
2360 /* _nx_web_http_server_secure_ecc_configure PORTABLE C */
2361 /* 6.1.11 */
2362 /* AUTHOR */
2363 /* */
2364 /* Yuxin Zhou, Microsoft Corporation */
2365 /* */
2366 /* DESCRIPTION */
2367 /* */
2368 /* This function configures supported curve lists for NetX Web HTTP */
2369 /* server instance using TLS. */
2370 /* */
2371 /* INPUT */
2372 /* */
2373 /* http_server_ptr Pointer to HTTP server */
2374 /* supported_groups List of supported groups */
2375 /* supported_group_count Number of supported groups */
2376 /* curves List of curve methods */
2377 /* */
2378 /* OUTPUT */
2379 /* */
2380 /* status Completion status */
2381 /* */
2382 /* CALLS */
2383 /* */
2384 /* nx_tcpserver_tls_ecc_setup Socket server ECC configure */
2385 /* */
2386 /* CALLED BY */
2387 /* */
2388 /* Application Code */
2389 /* */
2390 /* RELEASE HISTORY */
2391 /* */
2392 /* DATE NAME DESCRIPTION */
2393 /* */
2394 /* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */
2395 /* */
2396 /**************************************************************************/
_nx_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER * http_server_ptr,const USHORT * supported_groups,USHORT supported_group_count,const NX_CRYPTO_METHOD ** curves)2397 UINT _nx_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr,
2398 const USHORT *supported_groups, USHORT supported_group_count,
2399 const NX_CRYPTO_METHOD **curves)
2400 {
2401 UINT status;
2402
2403 /* Configure TLS ECC for the socket server. */
2404 status = nx_tcpserver_tls_ecc_setup(&http_server_ptr -> nx_web_http_server_tcpserver,
2405 supported_groups, supported_group_count, curves);
2406 return(status);
2407 }
2408 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
2409
2410 #endif /* NX_WEB_HTTPS_ENABLE */
2411
2412 /**************************************************************************/
2413 /* */
2414 /* FUNCTION RELEASE */
2415 /* */
2416 /* _nxe_web_http_server_stop PORTABLE C */
2417 /* 6.1 */
2418 /* AUTHOR */
2419 /* */
2420 /* Yuxin Zhou, Microsoft Corporation */
2421 /* */
2422 /* DESCRIPTION */
2423 /* */
2424 /* This function checks for errors in the HTTP server stop call. */
2425 /* */
2426 /* */
2427 /* INPUT */
2428 /* */
2429 /* http_server_ptr Pointer to HTTP server */
2430 /* */
2431 /* OUTPUT */
2432 /* */
2433 /* status Completion status */
2434 /* */
2435 /* CALLS */
2436 /* */
2437 /* _nx_web_http_server_stop Actual server stop call */
2438 /* */
2439 /* CALLED BY */
2440 /* */
2441 /* Application Code */
2442 /* */
2443 /* RELEASE HISTORY */
2444 /* */
2445 /* DATE NAME DESCRIPTION */
2446 /* */
2447 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2448 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2449 /* resulting in version 6.1 */
2450 /* */
2451 /**************************************************************************/
_nxe_web_http_server_stop(NX_WEB_HTTP_SERVER * http_server_ptr)2452 UINT _nxe_web_http_server_stop(NX_WEB_HTTP_SERVER *http_server_ptr)
2453 {
2454
2455 UINT status;
2456
2457
2458 /* Check for invalid input pointers. */
2459 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID))
2460 return(NX_PTR_ERROR);
2461
2462 /* Check for appropriate caller. */
2463 NX_THREADS_ONLY_CALLER_CHECKING
2464
2465 /* Call actual server stop function. */
2466 status = _nx_web_http_server_stop(http_server_ptr);
2467
2468 /* Return completion status. */
2469 return(status);
2470 }
2471
2472
2473 /**************************************************************************/
2474 /* */
2475 /* FUNCTION RELEASE */
2476 /* */
2477 /* _nx_web_http_server_stop PORTABLE C */
2478 /* 6.1 */
2479 /* AUTHOR */
2480 /* */
2481 /* Yuxin Zhou, Microsoft Corporation */
2482 /* */
2483 /* DESCRIPTION */
2484 /* */
2485 /* This function stops a previously started HTTP server on the */
2486 /* specified IP. */
2487 /* */
2488 /* */
2489 /* INPUT */
2490 /* */
2491 /* http_server_ptr Pointer to HTTP server */
2492 /* */
2493 /* OUTPUT */
2494 /* */
2495 /* status Completion status */
2496 /* */
2497 /* CALLS */
2498 /* */
2499 /* nx_tcpserver_stop Suspend the HTTP server thread*/
2500 /* */
2501 /* CALLED BY */
2502 /* */
2503 /* Application Code */
2504 /* */
2505 /* RELEASE HISTORY */
2506 /* */
2507 /* DATE NAME DESCRIPTION */
2508 /* */
2509 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2510 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2511 /* resulting in version 6.1 */
2512 /* */
2513 /**************************************************************************/
_nx_web_http_server_stop(NX_WEB_HTTP_SERVER * http_server_ptr)2514 UINT _nx_web_http_server_stop(NX_WEB_HTTP_SERVER *http_server_ptr)
2515 {
2516 UINT status;
2517 NX_TCPSERVER *tcpserver_ptr = &(http_server_ptr -> nx_web_http_server_tcpserver);
2518
2519 #ifdef NX_WEB_HTTPS_ENABLE
2520 UINT i;
2521
2522 /* Stop TLS session if using HTTPS. */
2523 if(http_server_ptr -> nx_web_http_is_https_server)
2524 {
2525 for(i = 0; i < tcpserver_ptr -> nx_tcpserver_sessions_count; i++)
2526 {
2527 nx_secure_tls_session_end(&(tcpserver_ptr -> nx_tcpserver_sessions[i].nx_tcp_session_tls_session), NX_WAIT_FOREVER);
2528 }
2529 }
2530 #endif
2531
2532 /* Suspend the HTTP server thread. */
2533 status = nx_tcpserver_stop(tcpserver_ptr);
2534
2535 /* Return status. */
2536 return(status);
2537 }
2538
2539
2540 /**************************************************************************/
2541 /* */
2542 /* FUNCTION RELEASE */
2543 /* */
2544 /* _nxe_web_http_server_callback_data_send PORTABLE C */
2545 /* 6.1 */
2546 /* AUTHOR */
2547 /* */
2548 /* Yuxin Zhou, Microsoft Corporation */
2549 /* */
2550 /* DESCRIPTION */
2551 /* */
2552 /* This function checks for errors in the data send call. */
2553 /* */
2554 /* */
2555 /* INPUT */
2556 /* */
2557 /* http_server_ptr Pointer to HTTP server */
2558 /* data_ptr Pointer to data to send */
2559 /* data_length Length of data to send */
2560 /* */
2561 /* OUTPUT */
2562 /* */
2563 /* status Completion status */
2564 /* */
2565 /* CALLS */
2566 /* */
2567 /* _nx_web_http_server_callback_data_send */
2568 /* Actual function call */
2569 /* */
2570 /* CALLED BY */
2571 /* */
2572 /* Application Code */
2573 /* */
2574 /* RELEASE HISTORY */
2575 /* */
2576 /* DATE NAME DESCRIPTION */
2577 /* */
2578 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2579 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2580 /* resulting in version 6.1 */
2581 /* */
2582 /**************************************************************************/
_nxe_web_http_server_callback_data_send(NX_WEB_HTTP_SERVER * server_ptr,VOID * data_ptr,ULONG data_length)2583 UINT _nxe_web_http_server_callback_data_send(NX_WEB_HTTP_SERVER *server_ptr, VOID *data_ptr, ULONG data_length)
2584 {
2585 UINT status;
2586
2587 /* Check pointers. */
2588 if(server_ptr == NX_NULL || data_ptr == NX_NULL || server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID)
2589 {
2590 return(NX_PTR_ERROR);
2591 }
2592
2593 /* Actual function call. */
2594 status = _nx_web_http_server_callback_data_send(server_ptr, data_ptr, data_length);
2595
2596 /* Return completion status. */
2597 return(status);
2598 }
2599
2600
2601 /**************************************************************************/
2602 /* */
2603 /* FUNCTION RELEASE */
2604 /* */
2605 /* _nx_web_http_server_callback_data_send PORTABLE C */
2606 /* 6.1 */
2607 /* AUTHOR */
2608 /* */
2609 /* Yuxin Zhou, Microsoft Corporation */
2610 /* */
2611 /* DESCRIPTION */
2612 /* */
2613 /* This function sends data to the client from the application */
2614 /* callback function. This is typically done to satisfy a GET or */
2615 /* POST request that is processed completely by the application */
2616 /* callback function. */
2617 /* */
2618 /* */
2619 /* INPUT */
2620 /* */
2621 /* http_server_ptr Pointer to HTTP server */
2622 /* data_ptr Pointer to data to send */
2623 /* data_length Length of data to send */
2624 /* */
2625 /* OUTPUT */
2626 /* */
2627 /* status Completion status */
2628 /* */
2629 /* CALLS */
2630 /* */
2631 /* _nx_web_http_server_response_packet_allocate */
2632 /* Allocate a resonse packet */
2633 /* nx_packet_data_append Append data to packet */
2634 /* nx_tcp_socket_send Send TCP data */
2635 /* */
2636 /* CALLED BY */
2637 /* */
2638 /* Application Code */
2639 /* */
2640 /* RELEASE HISTORY */
2641 /* */
2642 /* DATE NAME DESCRIPTION */
2643 /* */
2644 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2645 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2646 /* resulting in version 6.1 */
2647 /* */
2648 /**************************************************************************/
_nx_web_http_server_callback_data_send(NX_WEB_HTTP_SERVER * server_ptr,VOID * data_ptr,ULONG data_length)2649 UINT _nx_web_http_server_callback_data_send(NX_WEB_HTTP_SERVER *server_ptr, VOID *data_ptr, ULONG data_length)
2650 {
2651
2652 NX_PACKET *new_packet_ptr;
2653 UINT status;
2654
2655
2656 /* Allocate a new packet for data. */
2657 status = _nx_web_http_server_response_packet_allocate(server_ptr, &new_packet_ptr, NX_WAIT_FOREVER);
2658
2659 /* Determine if an error is present. */
2660 if (status != NX_SUCCESS)
2661 {
2662
2663 /* Indicate an allocation error occurred. */
2664 server_ptr -> nx_web_http_server_allocation_errors++;
2665
2666 /* Error, return to caller. */
2667 return(NX_WEB_HTTP_ERROR);
2668 }
2669
2670 /* Now append the data to the packet. */
2671 status = nx_packet_data_append(new_packet_ptr, data_ptr, data_length,
2672 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
2673
2674 /* Determine if an error is present. */
2675 if (status != NX_SUCCESS)
2676 {
2677
2678 /* Indicate an allocation error occurred. */
2679 server_ptr -> nx_web_http_server_allocation_errors++;
2680
2681 /* Release the initial packet. */
2682 nx_packet_release(new_packet_ptr);
2683
2684 /* Error, return to caller. */
2685 return(status);
2686 }
2687
2688 /* Send the data back to the client. */
2689 status = _nx_web_http_server_send(server_ptr, new_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
2690
2691 /* Determine if this is successful. */
2692 if (status != NX_SUCCESS)
2693 {
2694 /* Release the packet. */
2695 nx_packet_release(new_packet_ptr);
2696 }
2697
2698 /* Return completion status. */
2699 return(status);
2700 }
2701
2702
2703 /**************************************************************************/
2704 /* */
2705 /* FUNCTION RELEASE */
2706 /* */
2707 /* _nxe_web_http_server_callback_response_send PORTABLE C */
2708 /* 6.1 */
2709 /* AUTHOR */
2710 /* */
2711 /* Yuxin Zhou, Microsoft Corporation */
2712 /* */
2713 /* DESCRIPTION */
2714 /* */
2715 /* This function checks for errors in the response send call. */
2716 /* */
2717 /* */
2718 /* INPUT */
2719 /* */
2720 /* http_server_ptr Pointer to HTTP server */
2721 /* status_code Status-code and reason-phrase */
2722 /* information Pointer to HTTP info string */
2723 /* additional_information Pointer to additional HTTP */
2724 /* information */
2725 /* */
2726 /* OUTPUT */
2727 /* */
2728 /* status Completion status */
2729 /* */
2730 /* CALLS */
2731 /* */
2732 /* _nxe_web_http_server_callback_response_send */
2733 /* Actual function call */
2734 /* */
2735 /* CALLED BY */
2736 /* */
2737 /* Application Code */
2738 /* */
2739 /* RELEASE HISTORY */
2740 /* */
2741 /* DATE NAME DESCRIPTION */
2742 /* */
2743 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2744 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2745 /* resulting in version 6.1 */
2746 /* */
2747 /**************************************************************************/
_nxe_web_http_server_callback_response_send(NX_WEB_HTTP_SERVER * server_ptr,CHAR * status_code,CHAR * information,CHAR * additional_info)2748 UINT _nxe_web_http_server_callback_response_send(NX_WEB_HTTP_SERVER *server_ptr, CHAR *status_code, CHAR *information, CHAR *additional_info)
2749 {
2750 UINT status;
2751
2752 if(server_ptr == NX_NULL || status_code == NX_NULL)
2753 {
2754 return(NX_PTR_ERROR);
2755 }
2756
2757 /* Check for appropriate caller. */
2758 NX_THREADS_ONLY_CALLER_CHECKING
2759
2760 /* Actual function call. */
2761 status = _nx_web_http_server_callback_response_send(server_ptr, status_code, information, additional_info);
2762
2763 /* Return successful completion. */
2764 return(status);
2765 }
2766
2767
2768 /**************************************************************************/
2769 /* */
2770 /* FUNCTION RELEASE */
2771 /* */
2772 /* _nx_web_http_server_callback_response_send PORTABLE C */
2773 /* 6.1 */
2774 /* AUTHOR */
2775 /* */
2776 /* Yuxin Zhou, Microsoft Corporation */
2777 /* */
2778 /* DESCRIPTION */
2779 /* */
2780 /* This function sends the completion response to the client from the */
2781 /* application callback function. This is typically done to satisfy a */
2782 /* GET or POST request that is processed completely by the application */
2783 /* callback function. */
2784 /* */
2785 /* */
2786 /* INPUT */
2787 /* */
2788 /* http_server_ptr Pointer to HTTP server */
2789 /* status_code Status-code and reason-phrase */
2790 /* information Pointer to HTTP info string */
2791 /* additional_information Pointer to additional HTTP */
2792 /* information */
2793 /* */
2794 /* OUTPUT */
2795 /* */
2796 /* status Completion status */
2797 /* */
2798 /* CALLS */
2799 /* */
2800 /* _nx_web_http_server_response_send Send HTTP response */
2801 /* _nx_utility_string_length_check Check string length */
2802 /* */
2803 /* CALLED BY */
2804 /* */
2805 /* Application Code */
2806 /* */
2807 /* RELEASE HISTORY */
2808 /* */
2809 /* DATE NAME DESCRIPTION */
2810 /* */
2811 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2812 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2813 /* resulting in version 6.1 */
2814 /* */
2815 /**************************************************************************/
_nx_web_http_server_callback_response_send(NX_WEB_HTTP_SERVER * server_ptr,CHAR * status_code,CHAR * information,CHAR * additional_info)2816 UINT _nx_web_http_server_callback_response_send(NX_WEB_HTTP_SERVER *server_ptr, CHAR *status_code, CHAR *information, CHAR *additional_info)
2817 {
2818
2819 UINT status_code_length = 0;
2820 UINT information_length = 0;
2821 UINT additional_info_length = 0;
2822 UINT status;
2823
2824
2825 /* Check length of header, information and additional information. */
2826 if (_nx_utility_string_length_check(status_code, &status_code_length, NX_MAX_STRING_LENGTH) ||
2827 (information && _nx_utility_string_length_check(information, &information_length, NX_MAX_STRING_LENGTH)) ||
2828 (additional_info && _nx_utility_string_length_check(additional_info, &additional_info_length, NX_MAX_STRING_LENGTH)))
2829 {
2830 return(NX_WEB_HTTP_ERROR);
2831 }
2832
2833 /* Call the internal HTTP response send function. */
2834 status = _nx_web_http_server_response_send(server_ptr, status_code, status_code_length, information,
2835 information_length, additional_info, additional_info_length);
2836
2837 /* Return status. */
2838 return(status);
2839 }
2840
2841 /**************************************************************************/
2842 /* */
2843 /* FUNCTION RELEASE */
2844 /* */
2845 /* _nxe_web_http_server_callback_response_send_extended */
2846 /* PORTABLE C */
2847 /* 6.1 */
2848 /* AUTHOR */
2849 /* */
2850 /* Yuxin Zhou, Microsoft Corporation */
2851 /* */
2852 /* DESCRIPTION */
2853 /* */
2854 /* This function checks for errors in the response send call. */
2855 /* */
2856 /* */
2857 /* INPUT */
2858 /* */
2859 /* http_server_ptr Pointer to HTTP server */
2860 /* status_code Status-code and reason-phrase */
2861 /* status_code_length Length of status-code */
2862 /* information Pointer to HTTP info string */
2863 /* information_length Length of information */
2864 /* additional_information Pointer to additional HTTP */
2865 /* information */
2866 /* additional_information_length Length of additional */
2867 /* information */
2868 /* */
2869 /* OUTPUT */
2870 /* */
2871 /* status Completion status */
2872 /* */
2873 /* CALLS */
2874 /* */
2875 /* _nxe_web_http_server_callback_response_send_extended */
2876 /* Actual function call */
2877 /* */
2878 /* CALLED BY */
2879 /* */
2880 /* Application Code */
2881 /* */
2882 /* RELEASE HISTORY */
2883 /* */
2884 /* DATE NAME DESCRIPTION */
2885 /* */
2886 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2887 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2888 /* resulting in version 6.1 */
2889 /* */
2890 /**************************************************************************/
_nxe_web_http_server_callback_response_send_extended(NX_WEB_HTTP_SERVER * server_ptr,CHAR * status_code,UINT status_code_length,CHAR * information,UINT information_length,CHAR * additional_info,UINT additional_information_length)2891 UINT _nxe_web_http_server_callback_response_send_extended(NX_WEB_HTTP_SERVER *server_ptr, CHAR *status_code,
2892 UINT status_code_length, CHAR *information,
2893 UINT information_length, CHAR *additional_info,
2894 UINT additional_information_length)
2895 {
2896 UINT status;
2897
2898 if(server_ptr == NX_NULL || status_code == NX_NULL)
2899 {
2900 return(NX_PTR_ERROR);
2901 }
2902
2903 /* Check for appropriate caller. */
2904 NX_THREADS_ONLY_CALLER_CHECKING
2905
2906 /* Actual function call. */
2907 status = _nx_web_http_server_callback_response_send_extended(server_ptr, status_code, status_code_length,
2908 information, information_length,
2909 additional_info, additional_information_length);
2910
2911 /* Return successful completion. */
2912 return(status);
2913 }
2914
2915
2916 /**************************************************************************/
2917 /* */
2918 /* FUNCTION RELEASE */
2919 /* */
2920 /* _nx_web_http_server_callback_response_send_extended PORTABLE C */
2921 /* 6.1 */
2922 /* AUTHOR */
2923 /* */
2924 /* Yuxin Zhou, Microsoft Corporation */
2925 /* */
2926 /* DESCRIPTION */
2927 /* */
2928 /* This function sends the completion response to the client from the */
2929 /* application callback function. This is typically done to satisfy a */
2930 /* GET or POST request that is processed completely by the application */
2931 /* callback function. */
2932 /* */
2933 /* Note: The strings of status_code, information and */
2934 /* additional_information must be NULL-terminated and length of each */
2935 /* string matches the length specified in the argument list. */
2936 /* */
2937 /* */
2938 /* INPUT */
2939 /* */
2940 /* http_server_ptr Pointer to HTTP server */
2941 /* status_code Status-code and reason-phrase */
2942 /* status_code_length Length of status-code */
2943 /* information Pointer to HTTP info string */
2944 /* information_length Length of information */
2945 /* additional_information Pointer to additional HTTP */
2946 /* information */
2947 /* additional_information_length Length of additional */
2948 /* information */
2949 /* */
2950 /* OUTPUT */
2951 /* */
2952 /* status Completion status */
2953 /* */
2954 /* CALLS */
2955 /* */
2956 /* _nx_web_http_server_response_send Send HTTP response */
2957 /* _nx_utility_string_length_check Check string length */
2958 /* */
2959 /* CALLED BY */
2960 /* */
2961 /* Application Code */
2962 /* */
2963 /* RELEASE HISTORY */
2964 /* */
2965 /* DATE NAME DESCRIPTION */
2966 /* */
2967 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2968 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2969 /* resulting in version 6.1 */
2970 /* */
2971 /**************************************************************************/
_nx_web_http_server_callback_response_send_extended(NX_WEB_HTTP_SERVER * server_ptr,CHAR * status_code,UINT status_code_length,CHAR * information,UINT information_length,CHAR * additional_info,UINT additional_info_length)2972 UINT _nx_web_http_server_callback_response_send_extended(NX_WEB_HTTP_SERVER *server_ptr, CHAR *status_code,
2973 UINT status_code_length, CHAR *information,
2974 UINT information_length, CHAR *additional_info,
2975 UINT additional_info_length)
2976 {
2977 UINT temp_status_code_length = 0;
2978 UINT temp_information_length = 0;
2979 UINT temp_additional_info_length = 0;
2980
2981 /* Check length of status_code, information and additional information. */
2982 if (_nx_utility_string_length_check(status_code, &temp_status_code_length, NX_MAX_STRING_LENGTH) ||
2983 (information && _nx_utility_string_length_check(information, &temp_information_length, NX_MAX_STRING_LENGTH)) ||
2984 (additional_info && _nx_utility_string_length_check(additional_info, &temp_additional_info_length, NX_MAX_STRING_LENGTH)))
2985 {
2986 return(NX_WEB_HTTP_ERROR);
2987 }
2988
2989 /* Validate string length. */
2990 if ((temp_status_code_length != status_code_length) ||
2991 (information && (temp_information_length != information_length)) ||
2992 (additional_info && (temp_additional_info_length != additional_info_length)))
2993 {
2994 return(NX_WEB_HTTP_ERROR);
2995 }
2996
2997 /* Call the internal HTTP response send function. */
2998 return(_nx_web_http_server_response_send(server_ptr, status_code, status_code_length, information,
2999 information_length, additional_info, additional_info_length));
3000 }
3001
3002 /**************************************************************************/
3003 /* */
3004 /* FUNCTION RELEASE */
3005 /* */
3006 /* _nx_web_http_server_connection_end PORTABLE C */
3007 /* 6.1 */
3008 /* AUTHOR */
3009 /* */
3010 /* Yuxin Zhou, Microsoft Corporation */
3011 /* */
3012 /* DESCRIPTION */
3013 /* */
3014 /* This function is an internal callback used by the TCP server when a */
3015 /* TCP connection is ready to close. */
3016 /* */
3017 /* */
3018 /* INPUT */
3019 /* */
3020 /* tcpserver_ptr Pointer to TCP server */
3021 /* session_ptr Pointer to TCP session */
3022 /* */
3023 /* OUTPUT */
3024 /* */
3025 /* None */
3026 /* */
3027 /* CALLS */
3028 /* */
3029 /* _nx_web_http_server_connection_disconnect */
3030 /* Disconnect TCP or TLS */
3031 /* */
3032 /* CALLED BY */
3033 /* */
3034 /* NetX Duo */
3035 /* */
3036 /* RELEASE HISTORY */
3037 /* */
3038 /* DATE NAME DESCRIPTION */
3039 /* */
3040 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3041 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3042 /* resulting in version 6.1 */
3043 /* */
3044 /**************************************************************************/
_nx_web_http_server_connection_end(NX_TCPSERVER * tcpserver_ptr,NX_TCP_SESSION * session_ptr)3045 VOID _nx_web_http_server_connection_end(NX_TCPSERVER *tcpserver_ptr, NX_TCP_SESSION *session_ptr)
3046 {
3047 NX_WEB_HTTP_SERVER *server_ptr;
3048
3049
3050 /* Get the HTTP server pointer. */
3051 server_ptr = (NX_WEB_HTTP_SERVER *) tcpserver_ptr -> nx_tcpserver_reserved;
3052
3053 /* Disconnect the TCP server (and end TLS if used). */
3054 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
3055 }
3056
3057
3058 /**************************************************************************/
3059 /* */
3060 /* FUNCTION RELEASE */
3061 /* */
3062 /* _nx_web_http_server_connection_timeout PORTABLE C */
3063 /* 6.1 */
3064 /* AUTHOR */
3065 /* */
3066 /* Yuxin Zhou, Microsoft Corporation */
3067 /* */
3068 /* DESCRIPTION */
3069 /* */
3070 /* This function is an internal callback used by the TCP server when a */
3071 /* TCP connection times out. */
3072 /* */
3073 /* */
3074 /* INPUT */
3075 /* */
3076 /* tcpserver_ptr Pointer to TCP server */
3077 /* session_ptr Pointer to TCP session */
3078 /* */
3079 /* OUTPUT */
3080 /* */
3081 /* None */
3082 /* */
3083 /* CALLS */
3084 /* */
3085 /* _nx_web_http_server_connection_disconnect */
3086 /* Disconnect TCP or TLS */
3087 /* */
3088 /* CALLED BY */
3089 /* */
3090 /* NetX Duo */
3091 /* */
3092 /* RELEASE HISTORY */
3093 /* */
3094 /* DATE NAME DESCRIPTION */
3095 /* */
3096 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3097 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3098 /* resulting in version 6.1 */
3099 /* */
3100 /**************************************************************************/
_nx_web_http_server_connection_timeout(NX_TCPSERVER * tcpserver_ptr,NX_TCP_SESSION * session_ptr)3101 VOID _nx_web_http_server_connection_timeout(NX_TCPSERVER *tcpserver_ptr, NX_TCP_SESSION *session_ptr)
3102 {
3103 NX_WEB_HTTP_SERVER *server_ptr;
3104
3105
3106 /* Get the HTTP server pointer. */
3107 server_ptr = (NX_WEB_HTTP_SERVER *) tcpserver_ptr -> nx_tcpserver_reserved;
3108
3109 /* Disconnect the TCP server (and end TLS if used). */
3110 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
3111 }
3112
3113
3114 /**************************************************************************/
3115 /* */
3116 /* FUNCTION RELEASE */
3117 /* */
3118 /* _nx_web_http_server_receive_data PORTABLE C */
3119 /* 6.1 */
3120 /* AUTHOR */
3121 /* */
3122 /* Yuxin Zhou, Microsoft Corporation */
3123 /* */
3124 /* DESCRIPTION */
3125 /* */
3126 /* This function is the callback function executed whenever a client */
3127 /* connection appears on the HTTP Server port. It is responsible for */
3128 /* waking up the HTTP Server thread. */
3129 /* */
3130 /* */
3131 /* INPUT */
3132 /* */
3133 /* socket_ptr Pointer to HTTP Server socket */
3134 /* port HTTP Server port */
3135 /* */
3136 /* OUTPUT */
3137 /* */
3138 /* None */
3139 /* */
3140 /* CALLS */
3141 /* */
3142 /* _nx_web_http_server_get_client_request */
3143 /* Get request from client */
3144 /* _nx_web_http_server_connection_disconnect */
3145 /* Disconnect connection */
3146 /* _nx_web_http_server_get_client_keepalive */
3147 /* Get keepalive flag */
3148 /* _nx_web_http_server_chunked_check Check if the packet is chunked*/
3149 /* _nx_web_http_server_get_process Process GET request */
3150 /* _nx_web_http_server_put_process Process PUT request */
3151 /* _nx_web_http_server_delete_process Process DELETE request */
3152 /* _nx_web_http_server_response_packet_allocate */
3153 /* Allocate a response packet */
3154 /* */
3155 /* CALLED BY */
3156 /* */
3157 /* NetX */
3158 /* */
3159 /* RELEASE HISTORY */
3160 /* */
3161 /* DATE NAME DESCRIPTION */
3162 /* */
3163 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3164 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3165 /* resulting in version 6.1 */
3166 /* */
3167 /**************************************************************************/
_nx_web_http_server_receive_data(NX_TCPSERVER * tcpserver_ptr,NX_TCP_SESSION * session_ptr)3168 VOID _nx_web_http_server_receive_data(NX_TCPSERVER *tcpserver_ptr, NX_TCP_SESSION *session_ptr)
3169 {
3170
3171 NX_WEB_HTTP_SERVER *server_ptr;
3172 NX_PACKET *packet_ptr;
3173 UCHAR *buffer_ptr;
3174 UINT status;
3175 NX_PACKET *response_pkt;
3176
3177
3178 /* Set the HTTP server pointer. */
3179 server_ptr = (NX_WEB_HTTP_SERVER *) tcpserver_ptr -> nx_tcpserver_reserved;
3180
3181 /* Store the current session. */
3182 server_ptr -> nx_web_http_server_current_session_ptr = session_ptr;
3183
3184 /* Get the complete HTTP client request. */
3185 status = _nx_web_http_server_get_client_request(server_ptr, &packet_ptr);
3186
3187 /* Check if the HTTP request is valid. */
3188 if (status == NX_SUCCESS)
3189 {
3190 if (packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr < 7)
3191 {
3192 nx_packet_release(packet_ptr);
3193 status = NX_WEB_HTTP_ERROR;
3194 }
3195 }
3196
3197 /* Determine if it was successful. */
3198 if (status != NX_SUCCESS)
3199 {
3200
3201 if(status != NX_NO_PACKET)
3202 {
3203
3204 /* Increment the number of invalid HTTP requests. */
3205 server_ptr -> nx_web_http_server_invalid_http_headers++;
3206 }
3207
3208 /* Disconnect from the current connection. */
3209 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
3210
3211 /* Return. */
3212 return;
3213 }
3214
3215 #ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
3216 /* Check whether keepalive is necessary. */
3217 _nx_web_http_server_get_client_keepalive(server_ptr, packet_ptr);
3218 #endif /* NX_WEB_HTTP_KEEPALIVE_DISABLE */
3219
3220 /* Check if the packet is chunked. */
3221 server_ptr -> nx_web_http_server_request_chunked = (UCHAR)_nx_web_http_server_chunked_check(packet_ptr);
3222 server_ptr -> nx_web_http_server_expect_receive_bytes = 0;
3223 server_ptr -> nx_web_http_server_actual_bytes_received = 0;
3224
3225 /* Otherwise, we have received an HTTP client request successfully. */
3226
3227 /* Setup a pointer to packet buffer area. */
3228 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3229
3230 /* Determine what type of request is present. */
3231
3232 /* Check for a GET request. */
3233 if ((buffer_ptr[0] == 'G') && (buffer_ptr[1] == 'E') && (buffer_ptr[2] == 'T') && (buffer_ptr[3] == ' '))
3234 {
3235
3236 /* We have a HTTP GET request to get a resource from this HTTP Server. */
3237 server_ptr -> nx_web_http_server_request_type = NX_WEB_HTTP_SERVER_GET_REQUEST;
3238
3239 /* Increment the number of GET requests. */
3240 server_ptr -> nx_web_http_server_get_requests++;
3241
3242 /* Process the GET request. */
3243 _nx_web_http_server_get_process(server_ptr, NX_WEB_HTTP_SERVER_GET_REQUEST, packet_ptr);
3244 }
3245
3246 /* Check for a PUT request. */
3247 else if ((buffer_ptr[0] == 'P') && (buffer_ptr[1] == 'U') && (buffer_ptr[2] == 'T') && (buffer_ptr[3] == ' '))
3248 {
3249
3250 /* We have a HTTP PUT request to store a resource on this HTTP Server. */
3251 server_ptr -> nx_web_http_server_request_type = NX_WEB_HTTP_SERVER_PUT_REQUEST;
3252
3253 /* Increment the number of PUT requests. */
3254 server_ptr -> nx_web_http_server_put_requests++;
3255
3256 /* Process the PUT request. */
3257 _nx_web_http_server_put_process(server_ptr, packet_ptr);
3258 }
3259
3260 /* Check for a DELETE request. */
3261 else if ((buffer_ptr[0] == 'D') && (buffer_ptr[1] == 'E') && (buffer_ptr[2] == 'L') && (buffer_ptr[3] == 'E') &&
3262 (buffer_ptr[4] == 'T') && (buffer_ptr[5] == 'E') && (buffer_ptr[6] == ' '))
3263 {
3264
3265 /* We have a HTTP DELETE request to delete a resource from this HTTP Server. */
3266 server_ptr -> nx_web_http_server_request_type = NX_WEB_HTTP_SERVER_DELETE_REQUEST;
3267
3268 /* Increment the number of DELETE requests. */
3269 server_ptr -> nx_web_http_server_delete_requests++;
3270
3271 /* Process the Delete request. */
3272 _nx_web_http_server_delete_process(server_ptr, packet_ptr);
3273 }
3274
3275 /* Check for a POST request. */
3276 else if ((buffer_ptr[0] == 'P') && (buffer_ptr[1] == 'O') && (buffer_ptr[2] == 'S') &&
3277 (buffer_ptr[3] == 'T') && (buffer_ptr[4] == ' '))
3278 {
3279
3280 /* We have a HTTP POST request to send data to this HTTP Server for processing. Note that the POST
3281 request is nearly identical to the GET request, except the parameter/query data is found in the
3282 content rather than as part of the URL (resource). */
3283 server_ptr -> nx_web_http_server_request_type = NX_WEB_HTTP_SERVER_POST_REQUEST;
3284
3285 /* Increment the number of POST requests. */
3286 server_ptr -> nx_web_http_server_post_requests++;
3287
3288 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
3289
3290 /* Reset last received multipart packet. */
3291 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = NX_NULL;
3292 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
3293
3294 /* Process the POST request. */
3295 _nx_web_http_server_get_process(server_ptr, NX_WEB_HTTP_SERVER_POST_REQUEST, packet_ptr);
3296
3297 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
3298 /* Restore the packet to release. */
3299 if (server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet)
3300 packet_ptr = server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet;
3301 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
3302 }
3303
3304 /* Check for a HEAD request. */
3305 else if ((buffer_ptr[0] == 'H') && (buffer_ptr[1] == 'E') && (buffer_ptr[2] == 'A') &&
3306 (buffer_ptr[3] == 'D') && (buffer_ptr[4] == ' '))
3307 {
3308
3309 /* We have a HTTP HEAD request to get a resource header from this HTTP Server. Note that the HEAD
3310 request is nearly identical to the GET request, except the requested content is not returned to
3311 the client. */
3312 server_ptr -> nx_web_http_server_request_type = NX_WEB_HTTP_SERVER_HEAD_REQUEST;
3313
3314 /* Increment the number of HEAD requests. */
3315 server_ptr -> nx_web_http_server_head_requests++;
3316
3317 /* Process the HEAD request. */
3318 _nx_web_http_server_get_process(server_ptr, NX_WEB_HTTP_SERVER_HEAD_REQUEST, packet_ptr);
3319 }
3320
3321 /* Unhandled request. */
3322 else
3323 {
3324
3325 /* We have an unhandled HTTP request. */
3326 server_ptr -> nx_web_http_server_request_type = NX_WEB_HTTP_SERVER_UNKNOWN_REQUEST;
3327
3328 /* Send response back to HTTP Client. */
3329 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_NOT_IMPLEMENTED,
3330 sizeof(NX_WEB_HTTP_STATUS_NOT_IMPLEMENTED) - 1,
3331 "NetX HTTP Request Not Implemented",
3332 sizeof("NetX HTTP Request Not Implemented") - 1, NX_NULL, 0);
3333
3334 /* Increment the number of unhandled requests. */
3335 server_ptr -> nx_web_http_server_unknown_requests++;
3336 }
3337
3338 /* Release the packet. */
3339 nx_packet_release(packet_ptr);
3340
3341 /* Release the unprocessed packet. */
3342 if (server_ptr -> nx_web_http_server_request_packet)
3343 {
3344 nx_packet_release(server_ptr -> nx_web_http_server_request_packet);
3345 server_ptr -> nx_web_http_server_request_packet = NX_NULL;
3346 }
3347
3348 /* If there are no more data to send, append the last chunk. */
3349 if (server_ptr -> nx_web_http_server_response_chunked)
3350 {
3351
3352 /* Allocate a packet to send the chunk end. */
3353 status = _nx_web_http_server_response_packet_allocate(server_ptr, &response_pkt, NX_WAIT_FOREVER);
3354 if (status)
3355 {
3356
3357 /* Disconnect from the current connection. */
3358 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
3359 return;
3360 }
3361
3362 nx_packet_data_append(response_pkt, "0\r\n\r\n", 5, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
3363
3364 /* Send internal. */
3365 status = _nx_web_http_server_send(server_ptr, response_pkt, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
3366 if (status)
3367 {
3368
3369 /* Disconnect from the current connection. */
3370 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
3371
3372 nx_packet_release(response_pkt);
3373 return;
3374 }
3375
3376 server_ptr -> nx_web_http_server_response_chunked = NX_FALSE;
3377 }
3378
3379 #ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
3380 if(server_ptr -> nx_web_http_server_keepalive == NX_FALSE)
3381 {
3382 #endif
3383 /* Disconnect from the current connection. */
3384 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
3385
3386 #ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
3387 }
3388 #endif
3389
3390 return;
3391 }
3392
3393
3394 /**************************************************************************/
3395 /* */
3396 /* FUNCTION RELEASE */
3397 /* */
3398 /* _nx_web_http_server_get_client_request PORTABLE C */
3399 /* 6.1 */
3400 /* AUTHOR */
3401 /* */
3402 /* Yuxin Zhou, Microsoft Corporation */
3403 /* */
3404 /* DESCRIPTION */
3405 /* */
3406 /* This function retrieves the complete HTTP client request in a single*/
3407 /* packet. Doing this makes the other parsing and searching */
3408 /* routines simple. */
3409 /* */
3410 /* */
3411 /* INPUT */
3412 /* */
3413 /* server_ptr HTTP Server pointer */
3414 /* packet_ptr Destination for request */
3415 /* packet pointer */
3416 /* */
3417 /* OUTPUT */
3418 /* */
3419 /* status Completion status */
3420 /* */
3421 /* CALLS */
3422 /* */
3423 /* nx_packet_copy Copy packet */
3424 /* nx_packet_data_append Move data into packet */
3425 /* nx_packet_release Release packet */
3426 /* nx_tcp_socket_receive Receive an HTTP request packet*/
3427 /* */
3428 /* CALLED BY */
3429 /* _nx_web_http_server_receive_data */
3430 /* */
3431 /* RELEASE HISTORY */
3432 /* */
3433 /* DATE NAME DESCRIPTION */
3434 /* */
3435 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3436 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3437 /* resulting in version 6.1 */
3438 /* */
3439 /**************************************************************************/
_nx_web_http_server_get_client_request(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr)3440 UINT _nx_web_http_server_get_client_request(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr)
3441 {
3442
3443 NX_PACKET *head_packet_ptr;
3444 NX_PACKET *new_packet_ptr;
3445 CHAR *buffer_ptr;
3446 UINT status;
3447 NX_PACKET *work_ptr;
3448 UINT crlf_found = 0;
3449 NX_PACKET *tmp_ptr;
3450
3451
3452 /* Default the return packet pointer to NULL. */
3453 *packet_ptr = NX_NULL;
3454
3455 /* Wait for a request on the HTTP TCP well known port 80, or if encryption is enabled 443. */
3456 status = _nx_web_http_server_receive(server_ptr, &head_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_RECEIVE);
3457
3458 /* At this point, the server has a connection with an HTTP Client */
3459
3460 /* Check the return status. */
3461 if (status != NX_SUCCESS)
3462 {
3463
3464 /* Return an error condition. */
3465 return(status);
3466 }
3467
3468 /* Setup pointer to start of buffer. */
3469 buffer_ptr = (CHAR *) head_packet_ptr -> nx_packet_prepend_ptr;
3470
3471 /* Determine if the packet is an HTTP request. */
3472 if ((buffer_ptr[0] != 'G') && (buffer_ptr[0] != 'g') && (buffer_ptr[0] != 'P') && (buffer_ptr[0] != 'p') &&
3473 (buffer_ptr[0] != 'D') && (buffer_ptr[0] != 'd') && (buffer_ptr[0] != 'H') && (buffer_ptr[0] != 'h') &&
3474 (buffer_ptr[0] != 'T') && (buffer_ptr[0] != 't'))
3475 {
3476
3477 /* Invalid first packet for HTTP request. */
3478
3479 /* Release the packet. */
3480 nx_packet_release(head_packet_ptr);
3481
3482 /* Return an error. */
3483 return(NX_WEB_HTTP_ERROR);
3484 }
3485
3486 crlf_found = 0;
3487 work_ptr = head_packet_ptr;
3488
3489 /* Build a pointer to the buffer area. */
3490 buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr;
3491
3492 do
3493 {
3494
3495 /* See if there is a blank line present in the buffer. */
3496 /* Search the buffer for a cr/lf pair. */
3497 while (buffer_ptr < (CHAR *) work_ptr -> nx_packet_append_ptr)
3498 {
3499 if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13))
3500 {
3501
3502 /* Found CR. */
3503 crlf_found++;
3504 }
3505 else if((crlf_found & 1) && (*buffer_ptr == (CHAR)10))
3506 {
3507
3508 /* Found LF. */
3509 crlf_found++;
3510 }
3511 else
3512 {
3513
3514 /* Reset the CRLF marker. */
3515 crlf_found = 0;
3516 }
3517
3518 if (crlf_found == 4)
3519 {
3520
3521 /* Yes, we have found the end of the HTTP request header. */
3522
3523 /* Set the return packet pointer. */
3524 *packet_ptr = head_packet_ptr;
3525
3526 /* Return a successful completion. */
3527 return(NX_SUCCESS);
3528 }
3529
3530 /* Move the buffer pointer up. */
3531 buffer_ptr++;
3532 }
3533
3534 /* Determine if the packet has already overflowed into another packet. */
3535
3536 #ifndef NX_DISABLE_PACKET_CHAIN
3537
3538 if (work_ptr -> nx_packet_next != NX_NULL)
3539 {
3540 /* Get the next packet in the chain. */
3541 work_ptr = work_ptr -> nx_packet_next;
3542 buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr;
3543 }
3544 else
3545
3546 #endif
3547 {
3548 /* Receive another packet from the HTTP server port. */
3549 status = _nx_web_http_server_receive(server_ptr, &new_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_RECEIVE);
3550
3551 /* Check the return status. */
3552 if (status != NX_SUCCESS)
3553 {
3554
3555 /* Release the current head packet. */
3556 nx_packet_release(head_packet_ptr);
3557
3558 /* Return an error condition. */
3559 return(status);
3560 }
3561
3562 /* Successfully received another packet. Its contents now need to be placed in the head packet. */
3563 tmp_ptr = new_packet_ptr;
3564 #ifndef NX_DISABLE_PACKET_CHAIN
3565 while (tmp_ptr)
3566 {
3567 #endif /* NX_DISABLE_PACKET_CHAIN */
3568
3569 /* Copy the contents of the current packet into the head packet. */
3570 status = nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr,
3571 (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr),
3572 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WEB_HTTP_SERVER_TIMEOUT);
3573
3574 /* Determine if an error occurred. */
3575 if (status != NX_SUCCESS)
3576 {
3577
3578 /* Yes, an error is present. */
3579
3580 /* Release both packets. */
3581 nx_packet_release(head_packet_ptr);
3582 nx_packet_release(new_packet_ptr);
3583
3584 /* Return an error condition. */
3585 return(status);
3586 }
3587
3588 #ifndef NX_DISABLE_PACKET_CHAIN
3589 tmp_ptr = tmp_ptr -> nx_packet_next;
3590 }
3591 #endif /* NX_DISABLE_PACKET_CHAIN */
3592
3593 /* Release the new packet. */
3594 nx_packet_release(new_packet_ptr);
3595 }
3596
3597 } while (status == NX_SUCCESS);
3598
3599 /* Release the packet. */
3600 nx_packet_release(head_packet_ptr);
3601
3602 return NX_WEB_HTTP_ERROR;
3603 }
3604
3605
3606 /**************************************************************************/
3607 /* */
3608 /* FUNCTION RELEASE */
3609 /* */
3610 /* _nx_web_http_server_get_process PORTABLE C */
3611 /* 6.1 */
3612 /* AUTHOR */
3613 /* */
3614 /* Yuxin Zhou, Microsoft Corporation */
3615 /* */
3616 /* DESCRIPTION */
3617 /* */
3618 /* This function processes the GET, POST, and HEAD HTTP client */
3619 /* requests. */
3620 /* */
3621 /* */
3622 /* INPUT */
3623 /* */
3624 /* server_ptr HTTP Server pointer */
3625 /* request_type Type of request (GET, POST, */
3626 /* or HEAD) */
3627 /* packet_ptr Request packet pointer */
3628 /* */
3629 /* OUTPUT */
3630 /* */
3631 /* None */
3632 /* */
3633 /* CALLS */
3634 /* */
3635 /* _nx_web_http_server_basic_authenticate */
3636 /* Process basic authentication */
3637 /* _nx_web_http_server_digest_authenticate */
3638 /* Process digest authentication */
3639 /* _nx_web_http_server_calculate_content_offset */
3640 /* Retrieve content offset */
3641 /* _nx_web_http_server_content_length_get */
3642 /* Retrieve content length */
3643 /* _nx_web_http_server_response_send Send response back to client */
3644 /* _nx_web_http_server_retrieve_resource Retrieve resource from request*/
3645 /* _nx_web_http_server_type_get_extended Derive file type */
3646 /* _nx_web_http_server_packet_get Receive another packet */
3647 /* _nx_web_http_server_field_value_get Get field value */
3648 /* nx_tcp_socket_transmit_configure Configure the server socket */
3649 /* fx_directory_information_get Get length of resource file */
3650 /* fx_file_close Close resource file */
3651 /* fx_file_open Open resource file */
3652 /* fx_file_read Read data from resource file */
3653 /* _nx_web_http_server_reponse_packet_allocate */
3654 /* Allocate a response packet */
3655 /* nx_packet_release Release packet */
3656 /* _nx_utility_string_length_check Check string length */
3657 /* */
3658 /* CALLED BY */
3659 /* */
3660 /* _nx_web_http_server_receive_data HTTP receive processing */
3661 /* */
3662 /* RELEASE HISTORY */
3663 /* */
3664 /* DATE NAME DESCRIPTION */
3665 /* */
3666 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3667 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3668 /* resulting in version 6.1 */
3669 /* */
3670 /**************************************************************************/
_nx_web_http_server_get_process(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,NX_PACKET * packet_ptr)3671 VOID _nx_web_http_server_get_process(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, NX_PACKET *packet_ptr)
3672 {
3673
3674 ULONG length = 0;
3675 UINT file_type_length;
3676 UINT status;
3677 NX_PACKET *new_packet_ptr;
3678 CHAR *name_ptr;
3679 CHAR *password_ptr;
3680 CHAR *realm_ptr;
3681 ULONG temp;
3682 CHAR temp_string[30];
3683 UINT auth_request_present = NX_FALSE;
3684 NX_TCP_SOCKET *socket_ptr = &server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket;
3685 UINT offset = 0;
3686 UINT resource_length;
3687 UINT name_length = 0;
3688 UINT password_length = 0;
3689 UINT realm_length = 0;
3690 UINT temp_name_length = 0;
3691 UINT temp_password_length = 0;
3692 UINT temp_realm_length = 0;
3693
3694
3695 /* Pickup the URL (resource) from the request. */
3696 status = _nx_web_http_server_retrieve_resource(server_ptr, packet_ptr, server_ptr -> nx_web_http_server_request_resource, NX_WEB_HTTP_MAX_RESOURCE + 1);
3697
3698 /* Determine if the resource was extracted successfully. */
3699 if (status != NX_SUCCESS)
3700 {
3701
3702 /* Send response back to HTTP Client. */
3703 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
3704 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
3705 "NetX HTTP URL Bad", sizeof("NetX HTTP URL Bad") - 1, NX_NULL, 0);
3706
3707 /* Error, return to caller. */
3708 return;
3709 }
3710
3711 /* Determine if a POST is present. */
3712 if (request_type == NX_WEB_HTTP_SERVER_POST_REQUEST)
3713 {
3714
3715 if (!server_ptr -> nx_web_http_server_request_chunked)
3716 {
3717
3718 /* It is. Check for a valid content-length field. */
3719 status = _nx_web_http_server_content_length_get(packet_ptr, &length);
3720
3721 /* Check for errors. */
3722 if ( status != NX_SUCCESS)
3723 {
3724
3725 /* Send response back to HTTP Client. */
3726 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
3727 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
3728 "NetX HTTP Invalid Content Length",
3729 sizeof("NetX HTTP Invalid Content Length") - 1, NX_NULL, 0);
3730
3731 /* Error, return to caller. */
3732 return;
3733 }
3734 }
3735
3736 /* Check for an invalid content offset . */
3737 offset = _nx_web_http_server_calculate_content_offset(packet_ptr);
3738 if (offset == 0)
3739 {
3740
3741 /* Send response back to HTTP Client. */
3742 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
3743 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
3744 "NetX HTTP Invalid Content Offset",
3745 sizeof("NetX HTTP Invalid Content Offset") - 1, NX_NULL, 0);
3746
3747 /* Error, return to caller. */
3748 return;
3749 }
3750
3751 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
3752 /* Cleanup the multipart field. */
3753 memset(&server_ptr -> nx_web_http_server_multipart, 0, sizeof(NX_WEB_HTTP_SERVER_MULTIPART));
3754 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
3755 }
3756
3757 /* Determine if the application has specified an authentication function for this server. */
3758 if (server_ptr -> nx_web_http_server_authentication_check ||
3759 server_ptr -> nx_web_http_server_authentication_check_extended)
3760 {
3761
3762 /* Determine if authentication is required for the specified resource. */
3763 if (server_ptr -> nx_web_http_server_authentication_check_extended)
3764 {
3765 status = (server_ptr -> nx_web_http_server_authentication_check_extended)(server_ptr, request_type, server_ptr -> nx_web_http_server_request_resource,
3766 &name_ptr, &name_length, &password_ptr, &password_length, &realm_ptr, &realm_length);
3767 }
3768 else
3769 {
3770 status = (server_ptr -> nx_web_http_server_authentication_check)(server_ptr, request_type, server_ptr -> nx_web_http_server_request_resource,
3771 &name_ptr, &password_ptr, &realm_ptr);
3772 }
3773
3774 if ((status == NX_WEB_HTTP_BASIC_AUTHENTICATE) ||
3775 (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE))
3776 {
3777
3778 /* Check name, password and realm string. */
3779 if (_nx_utility_string_length_check(name_ptr, &temp_name_length, NX_WEB_HTTP_MAX_NAME) ||
3780 _nx_utility_string_length_check(password_ptr, &temp_password_length, NX_WEB_HTTP_MAX_PASSWORD) ||
3781 _nx_utility_string_length_check(realm_ptr, &temp_realm_length, NX_MAX_STRING_LENGTH))
3782 {
3783
3784 /* Error, return to caller. */
3785 return;
3786 }
3787
3788 /* Validate string length. */
3789 if (server_ptr -> nx_web_http_server_authentication_check_extended &&
3790 ((realm_length != temp_realm_length) ||
3791 (name_length != temp_name_length) ||
3792 (password_length != temp_password_length)))
3793 {
3794 return;
3795 }
3796 }
3797
3798 /* Determine what kind - if any - authentication is requested for this resource. */
3799 if (status == NX_WEB_HTTP_BASIC_AUTHENTICATE)
3800 {
3801
3802 /* Process basic authentication request. */
3803 status = _nx_web_http_server_basic_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, &auth_request_present);
3804 }
3805 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
3806 else if (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE)
3807 {
3808
3809 /* Process digest authentication request. */
3810 status = _nx_web_http_server_digest_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, &auth_request_present);
3811 }
3812 #endif
3813
3814 /* Determine if the authentication failed. */
3815 if ((status != NX_WEB_HTTP_DONT_AUTHENTICATE) && (status != NX_SUCCESS))
3816 {
3817
3818 /* Yes it did. Inform the HTTP server application about the failed authentication. */
3819 if (server_ptr -> nx_web_http_server_invalid_username_password_callback && auth_request_present)
3820 {
3821 NXD_ADDRESS client_nxd_address;
3822 ULONG client_port;
3823
3824 /* Get the IP address of the client: */
3825 status = nxd_tcp_socket_peer_info_get(socket_ptr, &client_nxd_address , &client_port);
3826
3827 if (status == NX_SUCCESS)
3828 {
3829 /* Send this information to the host application. */
3830 (server_ptr -> nx_web_http_server_invalid_username_password_callback)(server_ptr -> nx_web_http_server_request_resource, &client_nxd_address, request_type);
3831 }
3832 }
3833
3834 return;
3835 }
3836 }
3837
3838 /* Check whether a full response is necessary. */
3839 if((server_ptr -> nx_web_http_server_cache_info_get) &&
3840 (server_ptr -> nx_web_http_server_request_type == NX_WEB_HTTP_SERVER_GET_REQUEST))
3841 {
3842
3843 /* Searching for "If-Modified-Since" header. */
3844 if(_nx_web_http_server_field_value_get(packet_ptr, (UCHAR *)"if-modified-since", 17, (UCHAR *)temp_string, sizeof(temp_string)) == NX_SUCCESS)
3845 {
3846 UINT max_age;
3847 NX_WEB_HTTP_SERVER_DATE date;
3848 CHAR date_string[30];
3849
3850 /* Get last modified date of this resource. */
3851 if(server_ptr -> nx_web_http_server_cache_info_get(server_ptr -> nx_web_http_server_request_resource, &max_age, &date) == NX_TRUE)
3852 {
3853
3854 /* Convert date to string, the return length is always 29. */
3855 temp = _nx_web_http_server_date_to_string(&date, date_string);
3856 date_string[temp] = 0;
3857
3858 /* Check the last modified date with if-modified-since. */
3859 if(memcmp(temp_string, date_string, temp + 1) == 0)
3860 {
3861
3862 /* Send not modified. */
3863 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_NOT_MODIFIED,
3864 sizeof(NX_WEB_HTTP_STATUS_NOT_MODIFIED) - 1,
3865 NX_NULL, 0, NX_NULL, 0);
3866
3867 /* Return to caller. */
3868 return;
3869 }
3870 }
3871 }
3872 }
3873
3874 /* Setup the server socket with a specific packet transmit retry logic. */
3875 nx_tcp_socket_transmit_configure(socket_ptr,
3876 NX_WEB_HTTP_SERVER_TRANSMIT_QUEUE_DEPTH,
3877 NX_WEB_HTTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
3878 NX_WEB_HTTP_SERVER_RETRY_MAX,
3879 NX_WEB_HTTP_SERVER_RETRY_SHIFT);
3880
3881 /* At this point, either there isn't any required authentication for this resource or the authentication is
3882 complete. */
3883
3884 /* If the HTTP server receives an empty POST request (no message body, content length = 0, it is the
3885 responsibility of the request notify callback to send a response (if any) to the HTTP Client.
3886 The HTTP server will process the request no further. */
3887
3888 /* Determine if a user supplied get function has been specified. */
3889 if (server_ptr -> nx_web_http_server_request_notify)
3890 {
3891
3892 /* Call the user supplied function to notify the user of the get request. */
3893 status = (server_ptr -> nx_web_http_server_request_notify)(server_ptr, request_type, server_ptr -> nx_web_http_server_request_resource, packet_ptr);
3894
3895 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
3896 /* Release the packet that is not processed by callback function. */
3897 if(server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_next_packet)
3898 nx_packet_release(server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_next_packet);
3899 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
3900
3901 /* Determine if the user supplied routine is requesting the get should be aborted. */
3902 if (status != NX_SUCCESS)
3903 {
3904
3905 /* Determine if the user callback routine successfully completed the request processing. */
3906 if (status == NX_WEB_HTTP_CALLBACK_COMPLETED)
3907 {
3908
3909 /* User callback routine already sent success response back to HTTP Client. */
3910 return;
3911 }
3912
3913 /* Send response back to HTTP Client. */
3914 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
3915 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
3916 "NetX HTTP Request Aborted",
3917 sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
3918
3919 /* Yes, error was detected. Abort the remainder of the get processing. */
3920 return;
3921 }
3922 }
3923
3924 /* If it's POST request, process the message body. */
3925 if (request_type == NX_WEB_HTTP_SERVER_POST_REQUEST)
3926 {
3927
3928 /* Was there a message body in the request? */
3929 if (server_ptr -> nx_web_http_server_request_chunked)
3930 {
3931
3932 /* Find the first chunk of the content. */
3933 status = _nx_web_http_server_packet_content_find(server_ptr, &packet_ptr, NX_NULL);
3934 if (status)
3935 {
3936
3937 /* No. Regardless if a reply was sent via the request notify callback, we are done with this packet. */
3938 return;
3939 }
3940
3941 nx_packet_release(packet_ptr);
3942 }
3943 else
3944 {
3945 if (length == 0)
3946 {
3947
3948 /* No. Regardless if a reply was sent via the request notify callback, we are done with this packet. */
3949 return;
3950 }
3951
3952 length -= (ULONG)(packet_ptr -> nx_packet_length - offset);
3953 }
3954
3955 /* If necessary, receive more packets from the TCP socket. */
3956 while (length || server_ptr -> nx_web_http_server_request_chunked)
3957 {
3958
3959 /* Wait for more packets. */
3960 status = _nx_web_http_server_packet_get(server_ptr, &new_packet_ptr);
3961
3962 /* Check the return status. */
3963 if (status != NX_SUCCESS)
3964 {
3965
3966 if (status == NX_WEB_HTTP_GET_DONE)
3967 {
3968 break;
3969 }
3970
3971 /* Send response back to HTTP Client. */
3972 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
3973 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
3974 "NetX HTTP Receive Timeout",
3975 sizeof("NetX HTTP Receive Timeout") - 1, NX_NULL, 0);
3976
3977 /* Error, return to caller. */
3978 return;
3979 }
3980
3981 /* Update the length. */
3982 if (!server_ptr -> nx_web_http_server_request_chunked)
3983 {
3984 length -= new_packet_ptr -> nx_packet_length;
3985 }
3986
3987 nx_packet_release(new_packet_ptr);
3988 }
3989 }
3990
3991
3992 /* Get the length of request resource. */
3993 if (_nx_utility_string_length_check(server_ptr -> nx_web_http_server_request_resource, &resource_length,
3994 sizeof(server_ptr -> nx_web_http_server_request_resource) - 1))
3995 {
3996 return;
3997 }
3998
3999 /* Open the specified file for reading. */
4000 status = fx_file_open(server_ptr -> nx_web_http_server_media_ptr, &(server_ptr -> nx_web_http_server_file), server_ptr -> nx_web_http_server_request_resource, FX_OPEN_FOR_READ);
4001
4002 /* Check for error condition. */
4003 if (status != NX_SUCCESS)
4004 {
4005
4006 /* Send response back to HTTP Client. */
4007 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_NOT_FOUND,
4008 sizeof(NX_WEB_HTTP_STATUS_NOT_FOUND) - 1,
4009 "NetX HTTP Server unable to find file: ",
4010 sizeof("NetX HTTP Server unable to find file: ") - 1,
4011 server_ptr -> nx_web_http_server_request_resource,
4012 resource_length);
4013
4014 /* Error, return to caller. */
4015 return;
4016 }
4017
4018 /* Calculate the size of the file. */
4019 length = 0;
4020 fx_directory_information_get(server_ptr -> nx_web_http_server_media_ptr, server_ptr -> nx_web_http_server_request_resource, FX_NULL,
4021 &length, FX_NULL, FX_NULL, FX_NULL, FX_NULL, FX_NULL, FX_NULL);
4022
4023 /* Derive the file type. We use whatever value is returned since if there is no
4024 match this function will return a default value. */
4025 _nx_web_http_server_type_get_extended(server_ptr, server_ptr -> nx_web_http_server_request_resource, resource_length, temp_string, sizeof(temp_string), &file_type_length);
4026
4027 temp = file_type_length;
4028 temp_string[temp] = 0;
4029
4030 /* Now build a response header. */
4031 status = _nx_web_http_server_generate_response_header(server_ptr, &new_packet_ptr, NX_WEB_HTTP_STATUS_OK,
4032 sizeof(NX_WEB_HTTP_STATUS_OK) - 1, length, temp_string,
4033 file_type_length, NX_NULL, 0);
4034 if(status)
4035 {
4036
4037 /* Send response back to HTTP Client. */
4038 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4039 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4040 "NetX HTTP Request Aborted",
4041 sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
4042
4043 /* Close the file. */
4044 fx_file_close(&(server_ptr -> nx_web_http_server_file));
4045
4046 /* Error, return to caller. */
4047 return;
4048 }
4049
4050 /* Check to see if only a response is required. */
4051 if ((!length) || (request_type == NX_WEB_HTTP_SERVER_HEAD_REQUEST))
4052 {
4053
4054 /* Yes, only a response is required... send it! */
4055 status = _nx_web_http_server_send(server_ptr, new_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
4056
4057 /* Determine if this is successful. */
4058 if (status != NX_SUCCESS)
4059 {
4060
4061 /* Release the packet. */
4062 nx_packet_release(new_packet_ptr);
4063
4064 /* Force zero length. */
4065 length = 0;
4066 }
4067 }
4068
4069 /* Get length of packet */
4070 temp = new_packet_ptr -> nx_packet_length;
4071
4072 /* Now, loop to send the data contents. If the request type is "HEAD", skip this loop to output the
4073 file contents. */
4074 while ((length) && (request_type != NX_WEB_HTTP_SERVER_HEAD_REQUEST))
4075 {
4076
4077 /* Determine if we need to allocate a new packet for data. */
4078 if (!temp)
4079 {
4080
4081 /* Yes, allocate a new packet. */
4082 status = _nx_web_http_server_response_packet_allocate(server_ptr, &new_packet_ptr, NX_WAIT_FOREVER);
4083
4084 /* Determine if an error is present. */
4085 if (status != NX_SUCCESS)
4086 {
4087
4088 /* Indicate an allocation error occurred. */
4089 server_ptr -> nx_web_http_server_allocation_errors++;
4090
4091 /* Error, return to caller. */
4092 break;
4093 }
4094 }
4095
4096 /* Calculate the maximum length. */
4097 temp = ((ULONG) (new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_append_ptr)) - NX_PHYSICAL_TRAILER;
4098
4099 /* Determine if this exceeds the MSS of the peer. */
4100 if (temp > socket_ptr -> nx_tcp_socket_connect_mss)
4101 {
4102
4103 /* Yes, reduce the maximum size to the mss size. */
4104 temp = socket_ptr -> nx_tcp_socket_connect_mss;
4105 }
4106
4107 /* Read data from the file. */
4108 status = fx_file_read(&(server_ptr -> nx_web_http_server_file), new_packet_ptr -> nx_packet_append_ptr,
4109 temp, &temp);
4110
4111 /* Check for an error. */
4112 if (status != NX_SUCCESS)
4113 {
4114
4115 /* Release the packet. */
4116 nx_packet_release(new_packet_ptr);
4117
4118 /* Error, return. */
4119 break;
4120 }
4121
4122 /* Update the packet information with the data read. */
4123 new_packet_ptr -> nx_packet_length = new_packet_ptr -> nx_packet_length + temp;
4124 new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_append_ptr + temp;
4125
4126 /* Send the packet out. */
4127 status = _nx_web_http_server_send(server_ptr, new_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
4128
4129 /* Check for success. */
4130 if (status != NX_SUCCESS)
4131 {
4132
4133 /* Release the packet. */
4134 nx_packet_release(new_packet_ptr);
4135
4136 /* Return to caller. */
4137 break;
4138 }
4139
4140 /* Increment the bytes sent count. */
4141 server_ptr -> nx_web_http_server_total_bytes_sent = server_ptr -> nx_web_http_server_total_bytes_sent + temp;
4142
4143 /* Adjust the file length based on what we have sent. */
4144 length = length - temp;
4145
4146 /* Indicate new packet needed */
4147 temp = 0;
4148 }
4149
4150 /* Close the file. */
4151 fx_file_close(&(server_ptr -> nx_web_http_server_file));
4152 }
4153
4154
4155 /**************************************************************************/
4156 /* */
4157 /* FUNCTION RELEASE */
4158 /* */
4159 /* _nx_web_http_server_put_process PORTABLE C */
4160 /* 6.1 */
4161 /* AUTHOR */
4162 /* */
4163 /* Yuxin Zhou, Microsoft Corporation */
4164 /* */
4165 /* DESCRIPTION */
4166 /* */
4167 /* This function processes the PUT HTTP client requests. */
4168 /* */
4169 /* */
4170 /* INPUT */
4171 /* */
4172 /* server_ptr HTTP Server pointer */
4173 /* packet_ptr Request packet pointer */
4174 /* */
4175 /* OUTPUT */
4176 /* */
4177 /* None */
4178 /* */
4179 /* CALLS */
4180 /* */
4181 /* _nx_web_http_server_basic_authenticate */
4182 /* Process basic authentication */
4183 /* _nx_web_http_server_digest_authenticate */
4184 /* Process digest authentication */
4185 /* _nx_web_http_server_calculate_content_offset */
4186 /* Retrieve content offset */
4187 /* _nx_web_http_server_content_length_get */
4188 /* Retrieve content length */
4189 /* _nx_web_http_server_response_send Send response back to client */
4190 /* _nx_web_http_server_retrieve_resource Retrieve resource from request*/
4191 /* _nx_web_http_server_packet_get Receive another packet */
4192 /* fx_file_close Close resource file */
4193 /* fx_file_create Create resource file */
4194 /* fx_file_open Open resource file */
4195 /* fx_file_write Write data to resource file */
4196 /* nx_packet_release Release packet */
4197 /* _nx_utility_string_length_check Check string length */
4198 /* */
4199 /* CALLED BY */
4200 /* */
4201 /* _nx_web_http_server_content_get Content get processing */
4202 /* _nx_web_http_server_get_process GET request processing */
4203 /* _nx_web_http_server_put_process PUT request processing */
4204 /* */
4205 /* RELEASE HISTORY */
4206 /* */
4207 /* DATE NAME DESCRIPTION */
4208 /* */
4209 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4210 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4211 /* resulting in version 6.1 */
4212 /* */
4213 /**************************************************************************/
_nx_web_http_server_put_process(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)4214 VOID _nx_web_http_server_put_process(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
4215 {
4216
4217 UINT status;
4218 ULONG length = 0;
4219 UINT offset;
4220 CHAR *name_ptr;
4221 CHAR *password_ptr;
4222 CHAR *realm_ptr;
4223 NX_PACKET *data_packet_ptr;
4224 NX_PACKET *next_packet_ptr;
4225 UINT auth_request_present = NX_FALSE;
4226 NX_TCP_SOCKET *socket_ptr = &server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket;
4227 UINT name_length = 0;
4228 UINT password_length = 0;
4229 UINT realm_length = 0;
4230 UINT temp_name_length = 0;
4231 UINT temp_password_length = 0;
4232 UINT temp_realm_length = 0;
4233
4234
4235 /* Pickup the URL (resource) from the request. */
4236 status = _nx_web_http_server_retrieve_resource(server_ptr, packet_ptr, server_ptr -> nx_web_http_server_request_resource, NX_WEB_HTTP_MAX_RESOURCE + 1);
4237
4238 /* Determine if the resource was extracted successfully. */
4239 if (status != NX_SUCCESS)
4240 {
4241
4242 /* Send response back to HTTP Client. */
4243 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
4244 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
4245 "NetX HTTP URL Bad",
4246 sizeof("NetX HTTP URL Bad") - 1, NX_NULL, 0);
4247
4248 /* Error, return to caller. */
4249 return;
4250 }
4251
4252 if (!server_ptr -> nx_web_http_server_request_chunked)
4253 {
4254
4255 /* Calculate the content length from the request. */
4256 status = _nx_web_http_server_content_length_get(packet_ptr, &length);
4257
4258 /* Determine if the content length is valid. */
4259 if (status != NX_SUCCESS)
4260 {
4261
4262 /* Send response back to HTTP Client. */
4263 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
4264 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
4265 "NetX HTTP Invalid Content Length",
4266 sizeof("NetX HTTP Invalid Content Length") - 1, NX_NULL, 0);
4267
4268 /* Error, return to caller. */
4269 return;
4270 }
4271 }
4272
4273 /* Calculate the offset to the content (the two Cr LF tokens) in the request. */
4274 offset = _nx_web_http_server_calculate_content_offset(packet_ptr);
4275
4276 /* Determine if the offset to the content is valid. */
4277 if (offset == 0)
4278 {
4279
4280 /* Send response back to HTTP Client. */
4281 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
4282 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
4283 "NetX HTTP Invalid Content Offset",
4284 sizeof("NetX HTTP Invalid Content Offset") - 1, NX_NULL, 0);
4285
4286 /* Error, return to caller. */
4287 return;
4288 }
4289
4290 /* Determine if the application has specified an authentication function for this server. */
4291 if (server_ptr -> nx_web_http_server_authentication_check ||
4292 server_ptr -> nx_web_http_server_authentication_check_extended)
4293 {
4294
4295 /* Determine if authentication is required for the specified resource. */
4296 if (server_ptr -> nx_web_http_server_authentication_check_extended)
4297 {
4298 status = (server_ptr -> nx_web_http_server_authentication_check_extended)(server_ptr, NX_WEB_HTTP_SERVER_PUT_REQUEST, server_ptr -> nx_web_http_server_request_resource,
4299 &name_ptr, &name_length, &password_ptr, &password_length, &realm_ptr, &realm_length);
4300 }
4301 else
4302 {
4303 status = (server_ptr -> nx_web_http_server_authentication_check)(server_ptr, NX_WEB_HTTP_SERVER_PUT_REQUEST, server_ptr -> nx_web_http_server_request_resource,
4304 &name_ptr, &password_ptr, &realm_ptr);
4305 }
4306
4307 if ((status == NX_WEB_HTTP_BASIC_AUTHENTICATE) ||
4308 (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE))
4309 {
4310
4311 /* Check name, password and realm string. */
4312 if (_nx_utility_string_length_check(name_ptr, &temp_name_length, NX_WEB_HTTP_MAX_NAME) ||
4313 _nx_utility_string_length_check(password_ptr, &temp_password_length, NX_WEB_HTTP_MAX_PASSWORD) ||
4314 _nx_utility_string_length_check(realm_ptr, &temp_realm_length, NX_MAX_STRING_LENGTH))
4315 {
4316
4317 /* Error, return to caller. */
4318 return;
4319 }
4320
4321 /* Validate string length. */
4322 if (server_ptr -> nx_web_http_server_authentication_check_extended &&
4323 ((realm_length != temp_realm_length) ||
4324 (name_length != temp_name_length) ||
4325 (password_length != temp_password_length)))
4326 {
4327 return;
4328 }
4329 }
4330
4331 /* Determine what kind - if any - authentication is requested for this resource. */
4332 if (status == NX_WEB_HTTP_BASIC_AUTHENTICATE)
4333 {
4334
4335 /* Process basic authentication request. */
4336 status = _nx_web_http_server_basic_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, &auth_request_present);
4337 }
4338 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
4339 else if (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE)
4340 {
4341
4342 /* Process digest authentication request. */
4343 status = _nx_web_http_server_digest_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, &auth_request_present);
4344 }
4345 #endif
4346
4347 /* Determine if the authentication is currently in progress. */
4348 if ((status != NX_WEB_HTTP_DONT_AUTHENTICATE) && (status != NX_SUCCESS))
4349 {
4350
4351 /* Yes, authentication is in progress. The HTTP 401 has already been sent. */
4352 if (server_ptr -> nx_web_http_server_invalid_username_password_callback && auth_request_present)
4353 {
4354 NXD_ADDRESS client_nxd_address;
4355 ULONG client_port;
4356
4357 /* Get the IP address of the client: */
4358 status = nxd_tcp_socket_peer_info_get(socket_ptr, &client_nxd_address , &client_port);
4359
4360 if (status == NX_SUCCESS)
4361 {
4362 /* Send this information to the host application. */
4363 (server_ptr -> nx_web_http_server_invalid_username_password_callback)(server_ptr -> nx_web_http_server_request_resource, &client_nxd_address, NX_WEB_HTTP_SERVER_PUT_REQUEST);
4364 }
4365 }
4366
4367 return;
4368 }
4369 }
4370
4371 /* At this point, either there isn't any required authentication for this resource or the authentication is
4372 complete. */
4373
4374 /* If the request is empty (content-length = 0) the request notify callback is where a response is generated
4375 to return to the Client. NetX HTTP Server will not process an empty request further. */
4376
4377 /* Determine if a user supplied get function has been specified. */
4378 if (server_ptr -> nx_web_http_server_request_notify)
4379 {
4380
4381 /* Call the user supplied function to notify the user of the put request. */
4382 status = (server_ptr -> nx_web_http_server_request_notify)(server_ptr, NX_WEB_HTTP_SERVER_PUT_REQUEST, server_ptr -> nx_web_http_server_request_resource, packet_ptr);
4383
4384 /* Determine if the user supplied routine is requesting the put should be aborted. */
4385 if (status != NX_SUCCESS)
4386 {
4387
4388 /* Determine if the user callback routine successfully completed the request processing. */
4389 if (status == NX_WEB_HTTP_CALLBACK_COMPLETED)
4390 {
4391
4392 /* Send success response back to HTTP Client. */
4393 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_OK,
4394 sizeof(NX_WEB_HTTP_STATUS_OK) - 1, NX_NULL, 0, NX_NULL, 0);
4395 return;
4396 }
4397
4398 /* No, an error was detected. Abort the remainder of the get processing. */
4399 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4400 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4401 "NetX HTTP Request Aborted",
4402 sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
4403 return;
4404 }
4405 }
4406
4407 /* Was there a message body in the request? */
4408 if (server_ptr -> nx_web_http_server_request_chunked)
4409 {
4410
4411 /* Find the first chunk of the content. */
4412 status = _nx_web_http_server_packet_content_find(server_ptr, &packet_ptr, NX_NULL);
4413 if (status)
4414 {
4415
4416 /* No. Regardless if a reply was sent via the request notify callback, we are done with this packet. */
4417 return;
4418 }
4419
4420 offset = 0;
4421 length = packet_ptr -> nx_packet_length;
4422 }
4423 else if (length == 0)
4424 {
4425
4426 /* No. Regardless if a reply was sent via the request notify callback, we are done with this packet. */
4427 return;
4428 }
4429
4430 /* Otherwise, everything is okay... complete the request. */
4431
4432 /* Create the specified file. */
4433 status = fx_file_create(server_ptr -> nx_web_http_server_media_ptr, server_ptr -> nx_web_http_server_request_resource);
4434
4435
4436 if (status != NX_SUCCESS)
4437 {
4438
4439 /* Send response back to HTTP Client. */
4440 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4441 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4442 "NetX HTTP File Create Failed",
4443 sizeof("NetX HTTP File Create Failed") - 1, NX_NULL, 0);
4444
4445 /* Release first chunked packet. */
4446 if (server_ptr -> nx_web_http_server_request_chunked)
4447 {
4448 nx_packet_release(packet_ptr);
4449 }
4450
4451 /* Error, return to caller. */
4452 return;
4453 }
4454
4455 /* Open the specified file for writing. */
4456 status = fx_file_open(server_ptr -> nx_web_http_server_media_ptr, &(server_ptr -> nx_web_http_server_file), server_ptr -> nx_web_http_server_request_resource, FX_OPEN_FOR_WRITE);
4457
4458 /* Check for error condition. */
4459 if (status != NX_SUCCESS)
4460 {
4461
4462 /* Send response back to HTTP Client. */
4463 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4464 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4465 "NetX HTTP File Open Failed",
4466 sizeof("NetX HTTP File Open Failed") - 1, NX_NULL, 0);
4467
4468 /* Release first chunked packet. */
4469 if (server_ptr -> nx_web_http_server_request_chunked)
4470 {
4471 nx_packet_release(packet_ptr);
4472 }
4473
4474 /* Error, return to caller. */
4475 return;
4476 }
4477
4478 /* Determine if there is any content in the first packet. */
4479 if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > offset)
4480 {
4481
4482 /* Write the content found in this packet. */
4483 status = fx_file_write(&(server_ptr -> nx_web_http_server_file), (packet_ptr -> nx_packet_prepend_ptr + offset),
4484 ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - offset));
4485
4486 /* Check the status. */
4487 if (status != NX_SUCCESS)
4488 {
4489
4490 /* Send response back to HTTP Client. */
4491 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4492 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4493 "NetX HTTP File Write Failed",
4494 sizeof("NetX HTTP File Write Failed") - 1, NX_NULL, 0);
4495
4496 /* Release first chunked packet. */
4497 if (server_ptr -> nx_web_http_server_request_chunked)
4498 {
4499 nx_packet_release(packet_ptr);
4500 }
4501
4502 /* Error, return to caller. */
4503 return;
4504 }
4505
4506 /* Update the length. */
4507 length = length - ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - offset);
4508
4509 /* Increment the bytes received count. */
4510 server_ptr -> nx_web_http_server_total_bytes_received = server_ptr -> nx_web_http_server_total_bytes_received +
4511 ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - offset);
4512 }
4513
4514 #ifndef NX_DISABLE_PACKET_CHAIN
4515 /* Loop to write chained packets out to the file. */
4516 next_packet_ptr = packet_ptr -> nx_packet_next;
4517 while ((length) && (next_packet_ptr))
4518 {
4519
4520 /* Write the content of the next packet. */
4521 status = fx_file_write(&(server_ptr -> nx_web_http_server_file), next_packet_ptr -> nx_packet_prepend_ptr,
4522 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr));
4523
4524 /* Check the status. */
4525 if (status != NX_SUCCESS)
4526 {
4527
4528 /* Send response back to HTTP Client. */
4529 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4530 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4531 "NetX HTTP File Write Failed",
4532 sizeof("NetX HTTP File Write Failed") - 1, NX_NULL, 0);
4533
4534 /* Release first chunked packet. */
4535 if (server_ptr -> nx_web_http_server_request_chunked)
4536 {
4537 nx_packet_release(packet_ptr);
4538 }
4539
4540 /* Error, return to caller. */
4541 return;
4542 }
4543
4544 /* Update the length. */
4545 length = length - (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4546
4547 /* Increment the bytes received count. */
4548 server_ptr -> nx_web_http_server_total_bytes_received = server_ptr -> nx_web_http_server_total_bytes_received +
4549 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4550
4551 /* Move to the next pointer. */
4552 next_packet_ptr = next_packet_ptr -> nx_packet_next;
4553 }
4554 #endif /* NX_DISABLE_PACKET_CHAIN */
4555
4556 /* Release first chunked packet. */
4557 if (server_ptr -> nx_web_http_server_request_chunked)
4558 {
4559 nx_packet_release(packet_ptr);
4560 }
4561
4562 /* If necessary, receive more packets from the TCP socket to complete the write request. */
4563 while (length || server_ptr -> nx_web_http_server_request_chunked)
4564 {
4565
4566 /* Wait for a request. */
4567 status = _nx_web_http_server_packet_get(server_ptr, &data_packet_ptr);
4568
4569 /* Check the return status. */
4570 if (status != NX_SUCCESS)
4571 {
4572
4573 if (status == NX_WEB_HTTP_GET_DONE)
4574 {
4575 break;
4576 }
4577
4578 /* Send response back to HTTP Client. */
4579 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4580 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4581 "NetX HTTP Receive Timeout",
4582 sizeof("NetX HTTP Receive Timeout") - 1, NX_NULL, 0);
4583
4584 /* Error, return to caller. */
4585 return;
4586 }
4587
4588 if (server_ptr -> nx_web_http_server_request_chunked)
4589 {
4590 length = data_packet_ptr -> nx_packet_length;
4591 }
4592
4593 /* Loop to write the packet chain out to the file. */
4594 next_packet_ptr = data_packet_ptr;
4595 do
4596 {
4597
4598 /* Write the content of this packet. */
4599 status = fx_file_write(&(server_ptr -> nx_web_http_server_file), next_packet_ptr -> nx_packet_prepend_ptr,
4600 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr));
4601
4602 /* Check the status. */
4603 if (status != NX_SUCCESS)
4604 {
4605
4606 /* Send response back to HTTP Client. */
4607 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4608 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4609 "NetX HTTP File Write Failed",
4610 sizeof("NetX HTTP File Write Failed") - 1, NX_NULL, 0);
4611
4612 /* Release the previous data packet. */
4613 nx_packet_release(data_packet_ptr);
4614
4615 /* Error, return to caller. */
4616 return;
4617 }
4618
4619 /* Update the length. */
4620 length = length - (UINT)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4621
4622 /* Increment the bytes received count. */
4623 server_ptr -> nx_web_http_server_total_bytes_received = server_ptr -> nx_web_http_server_total_bytes_received +
4624 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4625
4626 #ifdef NX_DISABLE_PACKET_CHAIN
4627 next_packet_ptr = NX_NULL;
4628 #else
4629 /* Move to the next pointer. */
4630 next_packet_ptr = next_packet_ptr -> nx_packet_next;
4631 #endif /* NX_DISABLE_PACKET_CHAIN */
4632
4633 } while ((length) && (next_packet_ptr));
4634
4635 /* Release the previous data packet. */
4636 nx_packet_release(data_packet_ptr);
4637 }
4638
4639 /* Success, at this point close the file and prepare a successful response for the client. */
4640 fx_file_close(&(server_ptr -> nx_web_http_server_file));
4641
4642
4643 /* Now build a response header. */
4644 status = _nx_web_http_server_generate_response_header(server_ptr, &data_packet_ptr, NX_WEB_HTTP_STATUS_OK,
4645 sizeof(NX_WEB_HTTP_STATUS_OK) - 1, 0,
4646 NX_NULL, 0, NX_NULL, 0);
4647 if (status == NX_SUCCESS)
4648 {
4649
4650 /* Send the response back to the client. */
4651 status = _nx_web_http_server_send(server_ptr, data_packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
4652
4653 /* Check for an error. */
4654 if (status != NX_SUCCESS)
4655 {
4656
4657 /* Just release the packet. */
4658 nx_packet_release(data_packet_ptr);
4659 }
4660 }
4661
4662 }
4663
4664
4665 /**************************************************************************/
4666 /* */
4667 /* FUNCTION RELEASE */
4668 /* */
4669 /* _nx_web_http_server_delete_process PORTABLE C */
4670 /* 6.1 */
4671 /* AUTHOR */
4672 /* */
4673 /* Yuxin Zhou, Microsoft Corporation */
4674 /* */
4675 /* DESCRIPTION */
4676 /* */
4677 /* This function processes the DELETE HTTP client requests. */
4678 /* */
4679 /* INPUT */
4680 /* */
4681 /* server_ptr HTTP Server pointer */
4682 /* packet_ptr Request packet pointer */
4683 /* */
4684 /* OUTPUT */
4685 /* */
4686 /* None */
4687 /* */
4688 /* CALLS */
4689 /* */
4690 /* _nx_web_http_server_basic_authenticate */
4691 /* Process basic authentication */
4692 /* _nx_web_http_server_digest_authenticate */
4693 /* Process digest authentication */
4694 /* _nx_web_http_server_response_send Send response back to client */
4695 /* _nx_web_http_server_retrieve_resource Retrieve resource from request*/
4696 /* fx_file_delete Delete resource file */
4697 /* nx_packet_release Release packet */
4698 /* _nx_web_http_server_send Send packet to client */
4699 /* _nx_utility_string_length_check Check string length */
4700 /* */
4701 /* CALLED BY */
4702 /* */
4703 /* _nx_web_http_server_receive_data HTTP Server receive processing*/
4704 /* */
4705 /* RELEASE HISTORY */
4706 /* */
4707 /* DATE NAME DESCRIPTION */
4708 /* */
4709 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4710 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4711 /* resulting in version 6.1 */
4712 /* */
4713 /**************************************************************************/
_nx_web_http_server_delete_process(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)4714 VOID _nx_web_http_server_delete_process(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
4715 {
4716
4717 UINT status;
4718 CHAR *name_ptr;
4719 CHAR *password_ptr;
4720 CHAR *realm_ptr;
4721 NX_PACKET *response_ptr;
4722 UINT auth_request_present = NX_FALSE;
4723 NX_TCP_SOCKET *socket_ptr = &server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket;
4724 UINT name_length = 0;
4725 UINT password_length = 0;
4726 UINT realm_length = 0;
4727 UINT temp_name_length = 0;
4728 UINT temp_password_length = 0;
4729 UINT temp_realm_length = 0;
4730
4731
4732 /* Pickup the URL (resource) from the request. */
4733 status = _nx_web_http_server_retrieve_resource(server_ptr, packet_ptr, server_ptr -> nx_web_http_server_request_resource, NX_WEB_HTTP_MAX_RESOURCE + 1);
4734
4735 /* Determine if the resource was extracted successfully. */
4736 if (status != NX_SUCCESS)
4737 {
4738
4739 /* Send response back to HTTP Client. */
4740 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_BAD_REQUEST,
4741 sizeof(NX_WEB_HTTP_STATUS_BAD_REQUEST) - 1,
4742 "NetX HTTP URL Bad",
4743 sizeof("NetX HTTP URL Bad") - 1, NX_NULL, 0);
4744
4745 /* Error, return to caller. */
4746 return;
4747 }
4748
4749 /* Determine if the application has specified an authentication function for this server. */
4750 if (server_ptr -> nx_web_http_server_authentication_check ||
4751 server_ptr -> nx_web_http_server_authentication_check_extended)
4752 {
4753
4754 /* Determine if authentication is required for the specified resource. */
4755 if (server_ptr -> nx_web_http_server_authentication_check_extended)
4756 {
4757 status = (server_ptr -> nx_web_http_server_authentication_check_extended)(server_ptr, NX_WEB_HTTP_SERVER_DELETE_REQUEST, server_ptr -> nx_web_http_server_request_resource,
4758 &name_ptr, &name_length, &password_ptr, &password_length, &realm_ptr, &realm_length);
4759 }
4760 else
4761 {
4762 status = (server_ptr -> nx_web_http_server_authentication_check)(server_ptr, NX_WEB_HTTP_SERVER_DELETE_REQUEST, server_ptr -> nx_web_http_server_request_resource,
4763 &name_ptr, &password_ptr, &realm_ptr);
4764 }
4765
4766 if ((status == NX_WEB_HTTP_BASIC_AUTHENTICATE) ||
4767 (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE))
4768 {
4769
4770 /* Check name, password and realm string. */
4771 if (_nx_utility_string_length_check(name_ptr, &temp_name_length, NX_WEB_HTTP_MAX_NAME) ||
4772 _nx_utility_string_length_check(password_ptr, &temp_password_length, NX_WEB_HTTP_MAX_PASSWORD) ||
4773 _nx_utility_string_length_check(realm_ptr, &temp_realm_length, NX_MAX_STRING_LENGTH))
4774 {
4775
4776 /* Error, return to caller. */
4777 return;
4778 }
4779
4780 /* Validate string length. */
4781 if (server_ptr -> nx_web_http_server_authentication_check_extended &&
4782 ((realm_length != temp_realm_length) ||
4783 (name_length != temp_name_length) ||
4784 (password_length != temp_password_length)))
4785 {
4786 return;
4787 }
4788 }
4789
4790 /* Determine what kind - if any - authentication is requested for this resource. */
4791 if (status == NX_WEB_HTTP_BASIC_AUTHENTICATE)
4792 {
4793
4794 /* Process basic authentication request. */
4795 status = _nx_web_http_server_basic_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, &auth_request_present);
4796 }
4797 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
4798 else if (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE)
4799 {
4800
4801 /* Process digest authentication request. */
4802 status = _nx_web_http_server_digest_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, &auth_request_present);
4803 }
4804 #endif
4805
4806 /* Determine if the authentication is currently in progress. */
4807 if ((status != NX_WEB_HTTP_DONT_AUTHENTICATE) && (status != NX_SUCCESS))
4808 {
4809
4810 /* Yes, authentication is in progress. The HTTP 401 has already been sent. */
4811 if (server_ptr -> nx_web_http_server_invalid_username_password_callback && auth_request_present)
4812 {
4813 NXD_ADDRESS client_nxd_address;
4814 ULONG client_port;
4815
4816 /* Get the IP address of the client: */
4817 status = nxd_tcp_socket_peer_info_get(socket_ptr, &client_nxd_address , &client_port);
4818
4819 if (status == NX_SUCCESS)
4820 {
4821 /* Send this information to the host application. */
4822 (server_ptr -> nx_web_http_server_invalid_username_password_callback)(server_ptr -> nx_web_http_server_request_resource, &client_nxd_address, NX_WEB_HTTP_SERVER_DELETE_REQUEST);
4823 }
4824 }
4825
4826 return;
4827 }
4828 }
4829
4830 /* Determine if a user supplied notify function has been specified. */
4831 if (server_ptr -> nx_web_http_server_request_notify)
4832 {
4833
4834 /* Call the user supplied function to notify the user of the delete request. */
4835 status = (server_ptr -> nx_web_http_server_request_notify)(server_ptr, NX_WEB_HTTP_SERVER_DELETE_REQUEST, server_ptr -> nx_web_http_server_request_resource, packet_ptr);
4836
4837 /* Determine if the user supplied routine is requesting the delete should be aborted. */
4838 if (status != NX_SUCCESS)
4839 {
4840
4841 /* Determine if the user callback routine successfully completed the request processing. */
4842 if (status == NX_WEB_HTTP_CALLBACK_COMPLETED)
4843 {
4844
4845 /* Send success response back to HTTP Client. */
4846 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_OK,
4847 sizeof(NX_WEB_HTTP_STATUS_OK) - 1, NX_NULL, 0, NX_NULL, 0);
4848 return;
4849 }
4850
4851 /* Send response back to HTTP Client. */
4852 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4853 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4854 "NetX HTTP Request Aborted",
4855 sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
4856
4857 /* Yes, error was detected. Abort the remainder of the delete processing. */
4858 return;
4859 }
4860 }
4861
4862 /* Otherwise, everything is okay... complete the request. */
4863
4864 /* Delete the specified file. */
4865 status = fx_file_delete(server_ptr -> nx_web_http_server_media_ptr, server_ptr -> nx_web_http_server_request_resource);
4866
4867 /* Check for error condition. */
4868 if (status != NX_SUCCESS)
4869 {
4870
4871 /* Send response back to HTTP Client. */
4872 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR,
4873 sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
4874 "NetX HTTP File Delete Failed",
4875 sizeof("NetX HTTP File Delete Failed") - 1, NX_NULL, 0);
4876
4877 /* Error, return to caller. */
4878 return;
4879 }
4880
4881 /* Now build a response header. */
4882 status = _nx_web_http_server_generate_response_header(server_ptr, &response_ptr, NX_WEB_HTTP_STATUS_OK,
4883 sizeof(NX_WEB_HTTP_STATUS_OK) - 1, 0, NX_NULL, 0, NX_NULL, 0);
4884 if (status == NX_SUCCESS)
4885 {
4886
4887 /* Send the response back to the client. */
4888 status = _nx_web_http_server_send(server_ptr, response_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
4889
4890 /* Check for an error. */
4891 if (status != NX_SUCCESS)
4892 {
4893
4894 /* Just release the packet. */
4895 nx_packet_release(response_ptr);
4896 }
4897 }
4898 }
4899
4900
4901 /**************************************************************************/
4902 /* */
4903 /* FUNCTION RELEASE */
4904 /* */
4905 /* _nxe_web_http_server_invalid_userpassword_notify_set */
4906 /* PORTABLE C */
4907 /* 6.1 */
4908 /* AUTHOR */
4909 /* */
4910 /* Yuxin Zhou, Microsoft Corporation */
4911 /* */
4912 /* DESCRIPTION */
4913 /* */
4914 /* This function performs error checking for service to set invalid */
4915 /* username password callback function. */
4916 /* */
4917 /* INPUT */
4918 /* */
4919 /* http_server_ptr Pointer to HTTP server */
4920 /* invalid_username_password_callback Pointer to application's */
4921 /* invalid username password */
4922 /* callback function */
4923 /* */
4924 /* OUTPUT */
4925 /* */
4926 /* status Completion status */
4927 /* */
4928 /* CALLED BY */
4929 /* */
4930 /* Application Code */
4931 /* */
4932 /* RELEASE HISTORY */
4933 /* */
4934 /* DATE NAME DESCRIPTION */
4935 /* */
4936 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4937 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4938 /* resulting in version 6.1 */
4939 /* */
4940 /**************************************************************************/
_nxe_web_http_server_invalid_userpassword_notify_set(NX_WEB_HTTP_SERVER * http_server_ptr,UINT (* invalid_username_password_callback)(CHAR * resource,NXD_ADDRESS * client_nxd_address,UINT request_type))4941 UINT _nxe_web_http_server_invalid_userpassword_notify_set(NX_WEB_HTTP_SERVER *http_server_ptr,
4942 UINT (*invalid_username_password_callback)(CHAR *resource, NXD_ADDRESS *client_nxd_address, UINT request_type))
4943 {
4944
4945 UINT status;
4946
4947
4948 if ((http_server_ptr == NX_NULL) || (invalid_username_password_callback == NX_NULL))
4949 {
4950 return NX_PTR_ERROR;
4951 }
4952
4953 status = _nx_web_http_server_invalid_userpassword_notify_set(http_server_ptr, invalid_username_password_callback);
4954
4955 return status;
4956 }
4957
4958
4959 /**************************************************************************/
4960 /* */
4961 /* FUNCTION RELEASE */
4962 /* */
4963 /* _nx_web_http_server_invalid_userpassword_notify_set PORTABLE C */
4964 /* 6.1 */
4965 /* AUTHOR */
4966 /* */
4967 /* Yuxin Zhou, Microsoft Corporation */
4968 /* */
4969 /* DESCRIPTION */
4970 /* */
4971 /* This function sets invalid username password callback function */
4972 /* */
4973 /* Note: The string resource in callback function */
4974 /* invalid_username_password_callback is built by internal logic and */
4975 /* always NULL-terminated. */
4976 /* */
4977 /* */
4978 /* INPUT */
4979 /* */
4980 /* http_server_ptr Pointer to HTTP server */
4981 /* invalid_username_password_callback Pointer to application's */
4982 /* invalid username password */
4983 /* callback function */
4984 /* */
4985 /* OUTPUT */
4986 /* */
4987 /* status Completion status */
4988 /* */
4989 /* CALLED BY */
4990 /* */
4991 /* Application Code */
4992 /* */
4993 /* RELEASE HISTORY */
4994 /* */
4995 /* DATE NAME DESCRIPTION */
4996 /* */
4997 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4998 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4999 /* resulting in version 6.1 */
5000 /* */
5001 /**************************************************************************/
_nx_web_http_server_invalid_userpassword_notify_set(NX_WEB_HTTP_SERVER * http_server_ptr,UINT (* invalid_username_password_callback)(CHAR * resource,NXD_ADDRESS * client_nxd_address,UINT request_type))5002 UINT _nx_web_http_server_invalid_userpassword_notify_set(NX_WEB_HTTP_SERVER *http_server_ptr,
5003 UINT (*invalid_username_password_callback)(CHAR *resource, NXD_ADDRESS *client_nxd_address, UINT request_type))
5004 {
5005
5006 http_server_ptr -> nx_web_http_server_invalid_username_password_callback = invalid_username_password_callback;
5007
5008 return NX_SUCCESS;
5009 }
5010
5011
5012 /**************************************************************************/
5013 /* */
5014 /* FUNCTION RELEASE */
5015 /* */
5016 /* _nx_web_http_server_response_send PORTABLE C */
5017 /* 6.1 */
5018 /* AUTHOR */
5019 /* */
5020 /* Yuxin Zhou, Microsoft Corporation */
5021 /* */
5022 /* DESCRIPTION */
5023 /* */
5024 /* This function sends the specified Server response to the requesting */
5025 /* HTTP client. */
5026 /* */
5027 /* */
5028 /* INPUT */
5029 /* */
5030 /* server_ptr HTTP Server pointer */
5031 /* status_code Status-code and reason-phrase */
5032 /* status_code_length Length of status-code */
5033 /* information Pointer to HTTP info string */
5034 /* information_length Length of information */
5035 /* additional_information Pointer to additional HTTP */
5036 /* information */
5037 /* additional_information_length Length of additional */
5038 /* information */
5039 /* */
5040 /* OUTPUT */
5041 /* */
5042 /* status Completion status */
5043 /* */
5044 /* CALLS */
5045 /* */
5046 /* _nx_web_http_server_generate_response_header */
5047 /* Generate response header */
5048 /* nx_packet_data_append Append information to response*/
5049 /* nx_packet_release Release packet */
5050 /* _nx_web_http_server_send Send HTTP Server response */
5051 /* */
5052 /* CALLED BY */
5053 /* */
5054 /* _nx_web_http_server_receive HTTP receive processing */
5055 /* _nx_web_http_server_get_process Process GET request */
5056 /* _nx_web_http_server_put_process Process PUT request */
5057 /* _nx_web_http_server_delete_process Process DELETE request */
5058 /* */
5059 /* RELEASE HISTORY */
5060 /* */
5061 /* DATE NAME DESCRIPTION */
5062 /* */
5063 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5064 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5065 /* resulting in version 6.1 */
5066 /* */
5067 /**************************************************************************/
_nx_web_http_server_response_send(NX_WEB_HTTP_SERVER * server_ptr,CHAR * status_code,UINT status_code_length,CHAR * information,UINT information_length,CHAR * additional_information,UINT additional_information_length)5068 UINT _nx_web_http_server_response_send(NX_WEB_HTTP_SERVER *server_ptr, CHAR *status_code,
5069 UINT status_code_length, CHAR *information,
5070 UINT information_length, CHAR *additional_information,
5071 UINT additional_information_length)
5072 {
5073
5074 UINT status;
5075 UINT length;
5076 NX_PACKET *packet_ptr;
5077
5078 /* Determine if there is additional information. */
5079 if(information)
5080 {
5081
5082 /* Calculate the size of the information field. */
5083 length = information_length;
5084
5085 /* Determine if there is additional information. */
5086 if (additional_information)
5087 {
5088
5089 /* Update the length with it as well. */
5090 length = length + additional_information_length;
5091 }
5092 }
5093 else
5094 length = 0;
5095
5096 /* Generate response header. */
5097 status = _nx_web_http_server_generate_response_header(server_ptr, &packet_ptr, status_code,
5098 status_code_length, length, NX_NULL, 0, NX_NULL, 0);
5099
5100 /* Determine if an error occurred. */
5101 if (status != NX_SUCCESS)
5102 {
5103
5104 /* Just return. */
5105 return(status);
5106 }
5107
5108 /* Determine if there is additional information. */
5109 if (information)
5110 {
5111
5112 /* Place the first informational field. */
5113 status = nx_packet_data_append(packet_ptr, information, information_length,
5114 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5115
5116 /* If there is additional information, place it in the buffer as well. */
5117 if (additional_information)
5118 {
5119
5120 /* Now, place the additional informational field. */
5121 status += nx_packet_data_append(packet_ptr, additional_information, additional_information_length,
5122 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5123 }
5124 }
5125
5126 /* Check for an error. */
5127 if (status != NX_SUCCESS)
5128 {
5129
5130 /* Just release the packet and return. */
5131 nx_packet_release(packet_ptr);
5132 return(status);
5133 }
5134
5135 /* Send the response back to the client. */
5136 status = _nx_web_http_server_send(server_ptr, packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
5137
5138 /* Check for an error. */
5139 if (status != NX_SUCCESS)
5140 {
5141
5142 /* Just release the packet. */
5143 nx_packet_release(packet_ptr);
5144 }
5145
5146 return(status);
5147 }
5148
5149
5150 /**************************************************************************/
5151 /* */
5152 /* FUNCTION RELEASE */
5153 /* */
5154 /* _nx_web_http_server_basic_authenticate PORTABLE C */
5155 /* 6.2.0 */
5156 /* AUTHOR */
5157 /* */
5158 /* Yuxin Zhou, Microsoft Corporation */
5159 /* */
5160 /* DESCRIPTION */
5161 /* */
5162 /* This function checks for basic (name & password) authentication. */
5163 /* If found and correct, it returns a success. Otherwise, it returns */
5164 /* an authentication request to the requesting client. */
5165 /* */
5166 /* */
5167 /* INPUT */
5168 /* */
5169 /* server_ptr HTTP Server pointer */
5170 /* packet_ptr Request packet pointer */
5171 /* name_ptr Pointer to name string */
5172 /* password_ptr Pointer to password string */
5173 /* realm_ptr Pointer to realm string */
5174 /* auth_request_present Indicate if authentication */
5175 /* must be performed */
5176 /* */
5177 /* OUTPUT */
5178 /* */
5179 /* status Completion status */
5180 /* */
5181 /* CALLS */
5182 /* */
5183 /* _nx_web_http_server_retrieve_basic_authorization */
5184 /* Pickup authorization */
5185 /* _nx_web_http_base64_decode Decode authorization */
5186 /* _nx_web_http_server_response_packet_allocate */
5187 /* Allocate a response packet */
5188 /* nx_packet_data_append Append information to response*/
5189 /* nx_packet_release Release packet */
5190 /* _nx_web_http_server_send Send HTTP Server response */
5191 /* _nx_utility_string_length_check Check string length */
5192 /* */
5193 /* CALLED BY */
5194 /* */
5195 /* _nx_web_http_server_get_process Process GET request */
5196 /* _nx_web_http_server_put_process Process PUT request */
5197 /* _nx_web_http_server_delete_process Process DELETE request */
5198 /* */
5199 /* RELEASE HISTORY */
5200 /* */
5201 /* DATE NAME DESCRIPTION */
5202 /* */
5203 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5204 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5205 /* resulting in version 6.1 */
5206 /* 04-02-2021 Yuxin Zhou Modified comment(s), and */
5207 /* improved the logic of */
5208 /* parsing base64, */
5209 /* resulting in version 6.1.6 */
5210 /* 10-31-2022 Yuxin Zhou Modified comment(s), fixed */
5211 /* the issue of processing */
5212 /* empty password, */
5213 /* resulting in version 6.2.0 */
5214 /* */
5215 /**************************************************************************/
_nx_web_http_server_basic_authenticate(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * name_ptr,CHAR * password_ptr,CHAR * realm_ptr,UINT * auth_request_present)5216 UINT _nx_web_http_server_basic_authenticate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT *auth_request_present)
5217 {
5218
5219 UINT i, j;
5220 UINT status, status1;
5221 CHAR quote[2] = {0x22, 0};
5222 CHAR crlf[2] = {13,10};
5223 UINT match;
5224 UINT realm_length;
5225 UINT length;
5226 UINT authorization_decoded_size;
5227
5228 /* Default to no authentication request detected. */
5229 *auth_request_present = NX_FALSE;
5230
5231 /* Default the status to authenticate. */
5232 status = NX_WEB_HTTP_BASIC_AUTHENTICATE;
5233
5234 memset(&authorization_request[0], 0, sizeof(authorization_request));
5235
5236 memset(&authorization_decoded[0], 0, sizeof(authorization_decoded));
5237
5238 /* Is the authorization request present? */
5239 length = _nx_web_http_server_retrieve_basic_authorization(packet_ptr, authorization_request);
5240 if (length)
5241 {
5242
5243 /* Yes, an authorization request is present. */
5244 *auth_request_present = NX_TRUE;
5245
5246 /* Convert the request from Base64 representation to ASCII. */
5247 _nx_utility_base64_decode((UCHAR *)authorization_request, length, (UCHAR *)authorization_decoded, sizeof(authorization_decoded), &authorization_decoded_size);
5248
5249 /* See if it is valid. */
5250
5251 /* Compare the name. */
5252 i = 0;
5253 match = NX_TRUE;
5254 while (name_ptr[i] && (i < authorization_decoded_size))
5255 {
5256
5257 /* Is there a mismatch? */
5258 if (name_ptr[i] != authorization_decoded[i])
5259 {
5260
5261 /* Name mismatch. Continue to avoid timing attack. */
5262 match = NX_FALSE;
5263 }
5264
5265 /* Move to next character. */
5266 i++;
5267 }
5268
5269 /* Determine if everything matches. */
5270 if (match && (i < authorization_decoded_size) && (authorization_decoded[i] == ':'))
5271 {
5272
5273 /* Move the authorization index past the semicolon. */
5274 i++;
5275
5276 /* Now compare the passwords. */
5277 j = 0;
5278 match = NX_TRUE;
5279 while (password_ptr[j] && (i < authorization_decoded_size))
5280 {
5281
5282 /* Is there a mismatch? */
5283 if (password_ptr[j] != authorization_decoded[i])
5284 {
5285
5286 /* Password mismatch. Continue to avoid timing attack. */
5287 match = NX_FALSE;
5288 }
5289
5290 /* Move to next character. */
5291 i++;
5292 j++;
5293 }
5294
5295 /* Determine if we have a match. */
5296 if (match && (i == authorization_decoded_size) &&
5297 (authorization_decoded[i] == (CHAR) NX_NULL) &&
5298 (password_ptr[j] == (CHAR) NX_NULL))
5299 {
5300
5301 /* Yes, we have successful authorization!! */
5302 status = NX_SUCCESS;
5303 }
5304 }
5305 }
5306
5307 /* Determine if we need to send back an unauthorized request. */
5308 if (status == NX_WEB_HTTP_BASIC_AUTHENTICATE)
5309 {
5310
5311 /* We need authorization so build the HTTP 401 Unauthorized message to send to the server. */
5312
5313 if (_nx_utility_string_length_check(realm_ptr, &realm_length, NX_MAX_STRING_LENGTH))
5314 {
5315 return(NX_WEB_HTTP_ERROR);
5316 }
5317
5318 /* Allocate a packet for sending the response back. */
5319 status1 = _nx_web_http_server_response_packet_allocate(server_ptr, &packet_ptr, NX_WAIT_FOREVER);
5320
5321 /* Determine if an error occurred in the packet allocation. */
5322 if (status1 != NX_SUCCESS)
5323 {
5324
5325 /* Indicate an allocation error occurred. */
5326 server_ptr -> nx_web_http_server_allocation_errors++;
5327
5328 /* Just return. */
5329 return(status1);
5330 }
5331
5332 /* Insert the response header. */
5333 nx_packet_data_append(packet_ptr, NX_WEB_HTTP_VERSION, sizeof(NX_WEB_HTTP_VERSION) - 1,
5334 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5335 nx_packet_data_append(packet_ptr, " ", 1, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5336 nx_packet_data_append(packet_ptr, NX_WEB_HTTP_STATUS_UNAUTHORIZED, sizeof(NX_WEB_HTTP_STATUS_UNAUTHORIZED) - 1,
5337 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5338
5339 /* Place the <cr,lf> into the buffer. */
5340 nx_packet_data_append(packet_ptr, crlf, 2,
5341 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5342
5343 /* Insert the type of authentication requested. */
5344 nx_packet_data_append(packet_ptr, "WWW-Authenticate: Basic realm=", 30,
5345 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5346
5347 /* Insert the double quote. */
5348 nx_packet_data_append(packet_ptr, quote, 1,
5349 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5350
5351 /* Place the realm string into the buffer. */
5352 nx_packet_data_append(packet_ptr, realm_ptr, realm_length,
5353 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5354
5355 /* Insert the double quote. */
5356 nx_packet_data_append(packet_ptr, quote, 1,
5357 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5358
5359 /* Place the <cr,lf> into the buffer. */
5360 nx_packet_data_append(packet_ptr, crlf, 2,
5361 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5362
5363 /* Place another <cr,lf> into the buffer to signal end of FULL HTTP response. */
5364 nx_packet_data_append(packet_ptr, crlf, 2,
5365 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
5366
5367 /* Send the response back to the client. */
5368 status1 = _nx_web_http_server_send(server_ptr, packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
5369
5370 /* Check for an error. */
5371 if (status1)
5372 {
5373
5374 /* Return the internal NetX error. */
5375 status = status1;
5376
5377 /* Just release the packet. */
5378 nx_packet_release(packet_ptr);
5379 }
5380 }
5381
5382 /* Return the result of the authentication request. */
5383 return(status);
5384 }
5385
5386
5387 /**************************************************************************/
5388 /* */
5389 /* FUNCTION RELEASE */
5390 /* */
5391 /* _nx_web_http_server_retrieve_basic_authorization PORTABLE C */
5392 /* 6.1.10 */
5393 /* AUTHOR */
5394 /* */
5395 /* Yuxin Zhou, Microsoft Corporation */
5396 /* */
5397 /* DESCRIPTION */
5398 /* */
5399 /* This function retrieves basic authentication information from the */
5400 /* HTTP request packet. */
5401 /* */
5402 /* */
5403 /* INPUT */
5404 /* */
5405 /* packet_ptr Request packet pointer */
5406 /* authorization_request_ptr Pointer to destination for */
5407 /* authorization string */
5408 /* */
5409 /* OUTPUT */
5410 /* */
5411 /* status Completion status */
5412 /* */
5413 /* CALLS */
5414 /* */
5415 /* None */
5416 /* */
5417 /* CALLED BY */
5418 /* */
5419 /* _nx_web_http_server_basic_authenticate */
5420 /* Basic authenticate processing */
5421 /* */
5422 /* RELEASE HISTORY */
5423 /* */
5424 /* DATE NAME DESCRIPTION */
5425 /* */
5426 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5427 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5428 /* resulting in version 6.1 */
5429 /* 01-31-2022 Yuxin Zhou Modified comment(s), fixed */
5430 /* the HTTP Server state issue */
5431 /* with basic authorization, */
5432 /* resulting in version 6.1.10 */
5433 /* */
5434 /**************************************************************************/
_nx_web_http_server_retrieve_basic_authorization(NX_PACKET * packet_ptr,CHAR * authorization_request_ptr)5435 UINT _nx_web_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr)
5436 {
5437
5438 UINT length;
5439 UINT found;
5440 CHAR *buffer_ptr;
5441
5442
5443 /* Set the found flag to false. */
5444 found = NX_FALSE;
5445
5446 /* Default the authorization request to zero. */
5447 length = 0;
5448
5449 /* Set the authorization request string to NULL. */
5450 authorization_request_ptr[0] = NX_NULL;
5451
5452 /* Setup pointer to buffer. */
5453 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5454
5455
5456 /* Find the "Authorization: " token first. */
5457 while (((buffer_ptr+15) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
5458 {
5459
5460 /* Check for the Authorization: token. */
5461 if (((*buffer_ptr == 'a') || (*buffer_ptr == 'A')) &&
5462 ((*(buffer_ptr+1) == 'u') || (*(buffer_ptr+1) == 'U')) &&
5463 ((*(buffer_ptr+2) == 't') || (*(buffer_ptr+2) == 'T')) &&
5464 ((*(buffer_ptr+3) == 'h') || (*(buffer_ptr+3) == 'H')) &&
5465 ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) &&
5466 ((*(buffer_ptr+5) == 'r') || (*(buffer_ptr+5) == 'R')) &&
5467 ((*(buffer_ptr+6) == 'i') || (*(buffer_ptr+6) == 'I')) &&
5468 ((*(buffer_ptr+7) == 'z') || (*(buffer_ptr+7) == 'Z')) &&
5469 ((*(buffer_ptr+8) == 'a') || (*(buffer_ptr+8) == 'A')) &&
5470 ((*(buffer_ptr+9) == 't') || (*(buffer_ptr+9) == 'T')) &&
5471 ((*(buffer_ptr+10) == 'i') || (*(buffer_ptr+10) == 'I')) &&
5472 ((*(buffer_ptr+11) == 'o') || (*(buffer_ptr+11) == 'O')) &&
5473 ((*(buffer_ptr+12) == 'n') || (*(buffer_ptr+12) == 'N')) &&
5474 (*(buffer_ptr+13) == ':') &&
5475 (*(buffer_ptr+14) == ' '))
5476 {
5477
5478 /* Move the pointer up to the length token. */
5479 buffer_ptr = buffer_ptr + 15;
5480
5481 /* Set the found flag. */
5482 found = NX_TRUE;
5483 break;
5484 }
5485
5486 /* Move the pointer up to the next character. */
5487 buffer_ptr++;
5488 }
5489
5490 /* Determine if the first token was found. */
5491 if (!found)
5492 {
5493
5494 /* No, authorization is not present. Return a zero length. */
5495 return(length);
5496 }
5497
5498 /* Set the found flag back to false. */
5499 found = NX_FALSE;
5500
5501 /* Now remove any extra blanks. */
5502 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
5503 {
5504
5505 /* Move the pointer up one character. */
5506 buffer_ptr++;
5507 }
5508
5509 /* Now check for the "Basic " token. */
5510 while (((buffer_ptr+6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
5511 {
5512
5513 /* Check for the Basic token. */
5514 if (((*buffer_ptr == 'b') || (*buffer_ptr == 'B')) &&
5515 ((*(buffer_ptr+1) == 'a') || (*(buffer_ptr+1) == 'A')) &&
5516 ((*(buffer_ptr+2) == 's') || (*(buffer_ptr+2) == 'S')) &&
5517 ((*(buffer_ptr+3) == 'i') || (*(buffer_ptr+3) == 'I')) &&
5518 ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+4) == 'C')) &&
5519 (*(buffer_ptr+5) == ' '))
5520 {
5521
5522 /* Move the pointer up to the actual authorization string. */
5523 buffer_ptr = buffer_ptr + 6;
5524
5525 /* Set the found flag. */
5526 found = NX_TRUE;
5527 break;
5528 }
5529
5530 /* Move the pointer up to the next character. */
5531 buffer_ptr++;
5532 }
5533
5534 /* Determine if the first token was found. */
5535 if (!found)
5536 {
5537
5538 /* No, authorization is not present. Return a zero length. */
5539 return(length);
5540 }
5541
5542 /* Now remove any extra blanks. */
5543 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
5544 {
5545
5546 /* Move the pointer up one character. */
5547 buffer_ptr++;
5548 }
5549
5550 /* Now pickup the authorization string. */
5551 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_WEB_HTTP_MAX_STRING))
5552 {
5553
5554 /* Copy a character of the authorization string into the destination. */
5555 authorization_request_ptr[length] = *buffer_ptr++;
5556 length++;
5557 }
5558
5559 /* Return the length to the caller. */
5560 return(length);
5561 }
5562
5563
5564 /**************************************************************************/
5565 /* */
5566 /* FUNCTION RELEASE */
5567 /* */
5568 /* _nx_web_http_server_retrieve_resource PORTABLE C */
5569 /* 6.1 */
5570 /* AUTHOR */
5571 /* */
5572 /* Yuxin Zhou, Microsoft Corporation */
5573 /* */
5574 /* DESCRIPTION */
5575 /* */
5576 /* This function retrieves the resource (URL) portion of the request */
5577 /* and places it in the destination. */
5578 /* */
5579 /* */
5580 /* INPUT */
5581 /* */
5582 /* server_ptr HTTP Server pointer */
5583 /* packet_ptr Request packet pointer */
5584 /* destination Destination for resource */
5585 /* max_size Maximum size of destination */
5586 /* */
5587 /* OUTPUT */
5588 /* */
5589 /* Status Completion status */
5590 /* */
5591 /* CALLS */
5592 /* */
5593 /* None */
5594 /* */
5595 /* CALLED BY */
5596 /* */
5597 /* _nx_web_http_server_get_process Process GET request */
5598 /* _nx_web_http_server_put_process Process PUT request */
5599 /* _nx_web_http_server_delete_process Process DELETE request */
5600 /* */
5601 /* RELEASE HISTORY */
5602 /* */
5603 /* DATE NAME DESCRIPTION */
5604 /* */
5605 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5606 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5607 /* resulting in version 6.1 */
5608 /* */
5609 /**************************************************************************/
_nx_web_http_server_retrieve_resource(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * destination,UINT max_size)5610 UINT _nx_web_http_server_retrieve_resource(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *destination, UINT max_size)
5611 {
5612
5613 UINT i;
5614 CHAR *buffer_ptr;
5615
5616 #ifndef NX_WEB_HTTPS_ENABLE
5617 NX_PARAMETER_NOT_USED(server_ptr);
5618 #endif /* NX_WEB_HTTPS_ENABLE */
5619
5620 /* Set the destination to NULL. */
5621 destination[0] = (CHAR) 0;
5622
5623 /* Setup pointer to buffer. */
5624 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5625
5626 /* Find the first space which is the start position of URI. */
5627 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != ' '))
5628 {
5629
5630 /* Move the pointer up to the next character. */
5631 buffer_ptr++;
5632 }
5633
5634 /* Check for an error condition. */
5635 if (*buffer_ptr != ' ')
5636 return(NX_WEB_HTTP_ERROR);
5637
5638 buffer_ptr++;
5639
5640 #ifdef NX_WEB_HTTPS_ENABLE
5641
5642 if (server_ptr -> nx_web_http_is_https_server)
5643 {
5644 if ((buffer_ptr + 8 < (CHAR *)packet_ptr->nx_packet_append_ptr) && (*buffer_ptr != '/'))
5645 {
5646
5647 /* Check whether it is an absoluteURI*/
5648 if (((*buffer_ptr == 'h') || (*buffer_ptr == 'H')) &&
5649 ((*(buffer_ptr + 1) == 't') || (*(buffer_ptr + 1) == 'T')) &&
5650 ((*(buffer_ptr + 2) == 't') || (*(buffer_ptr + 2) == 'T')) &&
5651 ((*(buffer_ptr + 3) == 'p') || (*(buffer_ptr + 3) == 'P')) &&
5652 ((*(buffer_ptr + 4) == 's') || (*(buffer_ptr + 4) == 'S')) &&
5653 (*(buffer_ptr + 5) == ':') &&
5654 (*(buffer_ptr + 6) == '/') &&
5655 (*(buffer_ptr + 7) == '/'))
5656 {
5657
5658 /* Yes it is. Find the absolute path. */
5659 buffer_ptr += 8;
5660
5661 /* Find the first slash character. The first slash marks the beginning of the URL. */
5662 while ((buffer_ptr < (CHAR *)packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR)0) && (*buffer_ptr != '/'))
5663 {
5664
5665 /* Move the pointer up to the next character. */
5666 buffer_ptr++;
5667 }
5668 }
5669 }
5670
5671 }
5672 else
5673 #endif
5674 {
5675 if ((buffer_ptr + 7 < (CHAR *)packet_ptr->nx_packet_append_ptr) && (*buffer_ptr != '/'))
5676 {
5677
5678 /* Check whether it is an absoluteURI*/
5679 if (((*buffer_ptr == 'h') || (*buffer_ptr == 'H')) &&
5680 ((*(buffer_ptr + 1) == 't') || (*(buffer_ptr + 1) == 'T')) &&
5681 ((*(buffer_ptr + 2) == 't') || (*(buffer_ptr + 2) == 'T')) &&
5682 ((*(buffer_ptr + 3) == 'p') || (*(buffer_ptr + 3) == 'P')) &&
5683 (*(buffer_ptr + 4) == ':') &&
5684 (*(buffer_ptr + 5) == '/') &&
5685 (*(buffer_ptr + 6) == '/'))
5686 {
5687
5688 /* Yes it is. Find the absolute path. */
5689 buffer_ptr += 7;
5690
5691 /* Find the first slash character. The first slash marks the beginning of the URL. */
5692 while ((buffer_ptr < (CHAR *)packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR)0) && (*buffer_ptr != '/'))
5693 {
5694
5695 /* Move the pointer up to the next character. */
5696 buffer_ptr++;
5697 }
5698 }
5699 }
5700 }
5701
5702 /* Check for an error condition. */
5703 if ((buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr) || (*buffer_ptr != '/'))
5704 return(NX_WEB_HTTP_ERROR);
5705
5706 /* Copy the rest of the resource to the destination. Space, semicolon, and question mark characters signal the
5707 end of the resource. */
5708 i = 0;
5709 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != ' ') && (*buffer_ptr != ';') && (*buffer_ptr != '?') && (i < (max_size-1)))
5710 {
5711
5712 /* Check escape characters. */
5713 if(*buffer_ptr == '%')
5714 {
5715
5716 /* It is an escape character. */
5717 if((buffer_ptr + 2) < (CHAR *)packet_ptr -> nx_packet_append_ptr)
5718 {
5719
5720 /* Convert the HEX number. */
5721 buffer_ptr++;
5722 if((*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
5723 destination[i] = (CHAR)(*buffer_ptr - '0');
5724 else if((*buffer_ptr >= 'a') && (*buffer_ptr <= 'f'))
5725 destination[i] = (CHAR)(*buffer_ptr - 'a' + 10);
5726 else if((*buffer_ptr >= 'A') && (*buffer_ptr <= 'F'))
5727 destination[i] = (CHAR)(*buffer_ptr - 'A' + 10);
5728 else
5729 {
5730
5731 /* Error picking up the resource. */
5732 destination[0] = (CHAR) 0;
5733 return(NX_WEB_HTTP_ERROR);
5734 }
5735 destination[i] = (CHAR)(destination[i] << 4);
5736
5737 /* Convert the HEX number. */
5738 buffer_ptr++;
5739 if((*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
5740 destination[i] = (CHAR)(destination[i] + (*buffer_ptr - '0'));
5741 else if((*buffer_ptr >= 'a') && (*buffer_ptr <= 'f'))
5742 destination[i] = (CHAR)(destination[i] + (*buffer_ptr - 'a' + 10));
5743 else if((*buffer_ptr >= 'A') && (*buffer_ptr <= 'F'))
5744 destination[i] = (CHAR)(destination[i] + (*buffer_ptr - 'A' + 10));
5745 else
5746 {
5747
5748 /* Error picking up the resource. */
5749 destination[0] = (CHAR) 0;
5750 return(NX_WEB_HTTP_ERROR);
5751 }
5752
5753 /* Move to the next byte. */
5754 i++;
5755 buffer_ptr++;
5756 }
5757 else
5758 {
5759
5760 /* Error picking up the resource. */
5761 destination[0] = (CHAR) 0;
5762 return(NX_WEB_HTTP_ERROR);
5763 }
5764 }
5765 else
5766 {
5767
5768 /* Copy the URL name into the destination. */
5769 destination[i++] = *buffer_ptr++;
5770 }
5771 }
5772
5773 /* Determine if the resource was retrieved. */
5774 if ((destination[0] == (CHAR) 0) || (buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr) || ((*buffer_ptr != ' ') && (*buffer_ptr != '?') && (*buffer_ptr != ';')))
5775 {
5776
5777 /* Error picking up the resource. */
5778 destination[0] = (CHAR) 0;
5779 return(NX_WEB_HTTP_ERROR);
5780 }
5781
5782 /* Everything is okay, place a NULL at the end of the resource. */
5783 destination[i] = (CHAR) 0;
5784
5785 /* Return success. */
5786 return(NX_SUCCESS);
5787 }
5788
5789
5790 /**************************************************************************/
5791 /* */
5792 /* FUNCTION RELEASE */
5793 /* */
5794 /* _nx_web_http_server_calculate_content_offset PORTABLE C */
5795 /* 6.1 */
5796 /* AUTHOR */
5797 /* */
5798 /* Yuxin Zhou, Microsoft Corporation */
5799 /* */
5800 /* DESCRIPTION */
5801 /* */
5802 /* This function calculates the byte offset to the start of the */
5803 /* HTTP request content area. This area immediately follows the HTTP */
5804 /* request header (which ends with a blank line). */
5805 /* */
5806 /* */
5807 /* INPUT */
5808 /* */
5809 /* packet_ptr Pointer to request packet */
5810 /* */
5811 /* OUTPUT */
5812 /* */
5813 /* Byte Offset (0 implies no content) */
5814 /* */
5815 /* CALLS */
5816 /* */
5817 /* None */
5818 /* */
5819 /* CALLED BY */
5820 /* */
5821 /* _nx_web_http_server_content_get Application content get */
5822 /* _nx_web_http_server_get_process Process GET request */
5823 /* _nx_web_http_server_put_process Process PUT request */
5824 /* */
5825 /* RELEASE HISTORY */
5826 /* */
5827 /* DATE NAME DESCRIPTION */
5828 /* */
5829 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5830 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5831 /* resulting in version 6.1 */
5832 /* */
5833 /**************************************************************************/
_nx_web_http_server_calculate_content_offset(NX_PACKET * packet_ptr)5834 UINT _nx_web_http_server_calculate_content_offset(NX_PACKET *packet_ptr)
5835 {
5836
5837 UINT offset;
5838 CHAR *buffer_ptr;
5839 UINT crlf_found = 0;
5840
5841
5842 /* Default the content offset to zero. */
5843 offset = 0;
5844
5845 /* Find the "cr,lf,cr,lf" token. */
5846 #ifndef NX_DISABLE_PACKET_CHAIN
5847 while(packet_ptr)
5848 {
5849 #endif
5850
5851 /* Setup pointer to buffer. */
5852 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5853
5854 while(buffer_ptr < (CHAR *)packet_ptr -> nx_packet_append_ptr)
5855 {
5856 if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13))
5857 {
5858
5859 /* Found CR. */
5860 crlf_found++;
5861 }
5862 else if ((crlf_found & 1) && (*buffer_ptr == (CHAR)10))
5863 {
5864
5865 /* Found LF. */
5866 crlf_found++;
5867 }
5868 else
5869 {
5870
5871 /* Reset the CRLF marker. */
5872 crlf_found = 0;
5873 }
5874
5875 offset++;
5876 buffer_ptr++;
5877
5878 if (crlf_found == 4)
5879 {
5880
5881 /* Return the offset to the caller. */
5882 return(offset);
5883 }
5884 }
5885
5886 #ifndef NX_DISABLE_PACKET_CHAIN
5887 packet_ptr = packet_ptr -> nx_packet_next;
5888 }
5889 #endif
5890
5891 /* Not found the "cr,lf,cr,lf". */
5892 return(0);
5893 }
5894
5895
5896 /**************************************************************************/
5897 /* */
5898 /* FUNCTION RELEASE */
5899 /* */
5900 /* _nxe_web_http_server_type_get PORTABLE C */
5901 /* 6.1 */
5902 /* AUTHOR */
5903 /* */
5904 /* Yuxin Zhou, Microsoft Corporation */
5905 /* */
5906 /* DESCRIPTION */
5907 /* */
5908 /* This function checks error for deriving the type of the resource. */
5909 /* */
5910 /* INPUT */
5911 /* */
5912 /* server_ptr HTTP Server pointer */
5913 /* name Name string */
5914 /* http_type_string Destination HTTP type string */
5915 /* string_size Return HTTP type string size */
5916 /* */
5917 /* OUTPUT */
5918 /* */
5919 /* Size Number of bytes in string */
5920 /* */
5921 /* CALLS */
5922 /* */
5923 /* _nx_web_http_server_type_get */
5924 /* */
5925 /* CALLED BY */
5926 /* */
5927 /* Application Code */
5928 /* */
5929 /* RELEASE HISTORY */
5930 /* */
5931 /* DATE NAME DESCRIPTION */
5932 /* */
5933 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5934 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5935 /* resulting in version 6.1 */
5936 /* */
5937 /**************************************************************************/
_nxe_web_http_server_type_get(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name,CHAR * http_type_string,UINT * string_size)5938 UINT _nxe_web_http_server_type_get(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string, UINT *string_size)
5939 {
5940 UINT status;
5941
5942
5943 /* Check for invalid input pointers. */
5944 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
5945 (name == NX_NULL) || (http_type_string == NX_NULL) || (string_size == NX_NULL))
5946 {
5947 return(NX_PTR_ERROR);
5948 }
5949
5950 status = _nx_web_http_server_type_get(server_ptr, name, http_type_string, string_size);
5951
5952 return(status);
5953 }
5954
5955
5956 /**************************************************************************/
5957 /* */
5958 /* FUNCTION RELEASE */
5959 /* */
5960 /* _nx_web_http_server_type_get PORTABLE C */
5961 /* 6.1 */
5962 /* AUTHOR */
5963 /* */
5964 /* Yuxin Zhou, Microsoft Corporation */
5965 /* */
5966 /* DESCRIPTION */
5967 /* */
5968 /* This function derives the type of the resource. */
5969 /* */
5970 /* INPUT */
5971 /* */
5972 /* server_ptr HTTP Server pointer */
5973 /* name Name string */
5974 /* http_type_string Destination HTTP type string */
5975 /* string_size Return HTTP type string size */
5976 /* */
5977 /* OUTPUT */
5978 /* */
5979 /* Size Number of bytes in string */
5980 /* */
5981 /* CALLS */
5982 /* */
5983 /* _nx_web_http_server_memicmp */
5984 /* _nx_utility_string_length_check */
5985 /* */
5986 /* CALLED BY */
5987 /* */
5988 /* _nx_web_http_server_type_get_extended Get MIME type */
5989 /* */
5990 /* RELEASE HISTORY */
5991 /* */
5992 /* DATE NAME DESCRIPTION */
5993 /* */
5994 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5995 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5996 /* resulting in version 6.1 */
5997 /* */
5998 /**************************************************************************/
_nx_web_http_server_type_get(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name,CHAR * http_type_string,UINT * string_size)5999 UINT _nx_web_http_server_type_get(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string, UINT *string_size)
6000 {
6001 UINT temp_name_length;
6002
6003 /* Check name length. */
6004 if (_nx_utility_string_length_check(name, &temp_name_length, NX_MAX_STRING_LENGTH))
6005 {
6006 return(NX_WEB_HTTP_ERROR);
6007 }
6008
6009 /* Call actual service type get function. */
6010 return(_nx_web_http_server_type_get_extended(server_ptr, name, temp_name_length,
6011 http_type_string, NX_MAX_STRING_LENGTH + 1,
6012 string_size));
6013 }
6014
6015
6016 /**************************************************************************/
6017 /* */
6018 /* FUNCTION RELEASE */
6019 /* */
6020 /* _nxe_web_http_server_type_get_extended PORTABLE C */
6021 /* 6.1 */
6022 /* AUTHOR */
6023 /* */
6024 /* Yuxin Zhou, Microsoft Corporation */
6025 /* */
6026 /* DESCRIPTION */
6027 /* */
6028 /* This function checks error for deriving the type of the resource. */
6029 /* */
6030 /* INPUT */
6031 /* */
6032 /* server_ptr HTTP Server pointer */
6033 /* name Name string */
6034 /* name_length Length of name string */
6035 /* http_type_string Destination HTTP type string */
6036 /* http_type_string_max_size Size of the destination string*/
6037 /* string_size Return HTTP type string size */
6038 /* */
6039 /* OUTPUT */
6040 /* */
6041 /* Status Web HTTP status code */
6042 /* */
6043 /* CALLS */
6044 /* */
6045 /* _nx_web_http_server_type_get_extended Get MIME type */
6046 /* */
6047 /* CALLED BY */
6048 /* */
6049 /* Application Code */
6050 /* */
6051 /* RELEASE HISTORY */
6052 /* */
6053 /* DATE NAME DESCRIPTION */
6054 /* */
6055 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6056 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6057 /* resulting in version 6.1 */
6058 /* */
6059 /**************************************************************************/
_nxe_web_http_server_type_get_extended(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name,UINT name_length,CHAR * http_type_string,UINT http_type_string_max_size,UINT * string_size)6060 UINT _nxe_web_http_server_type_get_extended(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length,
6061 CHAR *http_type_string, UINT http_type_string_max_size,
6062 UINT *string_size)
6063 {
6064 UINT status;
6065
6066
6067 /* Check for invalid input pointers. */
6068 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
6069 (name == NX_NULL) || (http_type_string == NX_NULL) || (string_size == NX_NULL))
6070 {
6071 return(NX_PTR_ERROR);
6072 }
6073
6074 /* Check for appropriate caller. */
6075 NX_THREADS_ONLY_CALLER_CHECKING
6076
6077 status = _nx_web_http_server_type_get_extended(server_ptr, name, name_length, http_type_string,
6078 http_type_string_max_size, string_size);
6079
6080 return(status);
6081 }
6082
6083
6084 /**************************************************************************/
6085 /* */
6086 /* FUNCTION RELEASE */
6087 /* */
6088 /* _nx_web_http_server_type_get_extended PORTABLE C */
6089 /* 6.1 */
6090 /* AUTHOR */
6091 /* */
6092 /* Yuxin Zhou, Microsoft Corporation */
6093 /* */
6094 /* DESCRIPTION */
6095 /* */
6096 /* This function derives the type of the resource. */
6097 /* */
6098 /* Note: The string of name must be NULL-terminated and length of each */
6099 /* string matches the length specified in the argument list. */
6100 /* */
6101 /* INPUT */
6102 /* */
6103 /* server_ptr HTTP Server pointer */
6104 /* name Name string */
6105 /* name_length Length of name string */
6106 /* http_type_string Destination HTTP type string */
6107 /* http_type_string_max_size Size of the destination string*/
6108 /* string_size Return HTTP type string size */
6109 /* */
6110 /* OUTPUT */
6111 /* */
6112 /* Status Web HTTP status code */
6113 /* */
6114 /* CALLS */
6115 /* */
6116 /* _nx_web_http_server_memicmp Compare ignore case */
6117 /* _nx_utility_string_length_check String length check */
6118 /* memcpy Copy memory data */
6119 /* */
6120 /* CALLED BY */
6121 /* */
6122 /* _nx_web_http_server_get_process Process GET request */
6123 /* Application Code */
6124 /* */
6125 /* RELEASE HISTORY */
6126 /* */
6127 /* DATE NAME DESCRIPTION */
6128 /* */
6129 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6130 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6131 /* verified memcpy use cases, */
6132 /* resulting in version 6.1 */
6133 /* */
6134 /**************************************************************************/
_nx_web_http_server_type_get_extended(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name,UINT name_length,CHAR * http_type_string,UINT http_type_string_max_size,UINT * string_size)6135 UINT _nx_web_http_server_type_get_extended(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length,
6136 CHAR *http_type_string, UINT http_type_string_max_size,
6137 UINT *string_size)
6138 {
6139
6140 UINT i;
6141 CHAR *ch;
6142 UINT ext_length;
6143 UINT map_ext_length;
6144 UINT map_type_length;
6145 UINT temp_name_length;
6146
6147 /* Check name length. */
6148 if (_nx_utility_string_length_check(name, &temp_name_length, name_length))
6149 {
6150 return(NX_WEB_HTTP_ERROR);
6151 }
6152
6153 /* Validate string length. */
6154 if (name_length != temp_name_length)
6155 {
6156 return(NX_WEB_HTTP_ERROR);
6157 }
6158
6159 /* First find the end of the string. */
6160 ch = name + name_length;
6161
6162 /* Now look backwards to find the last period that signals the
6163 file extension. */
6164 ext_length = 0;
6165 while ((ch >= name) && (*ch != '.') &&(*ch != '/'))
6166 {
6167 ch--;
6168 ext_length++;
6169 }
6170
6171 if(*ch != '.')
6172 {
6173
6174 /* No extension is found. Return the default mime type. */
6175 if(http_type_string_max_size < (sizeof(NX_WEB_HTTP_SERVER_DEFAULT_MIME)))
6176 {
6177 /* NX_HTTP_SERVER_DEFAULT_MIME does not fit into
6178 the caller-supplied http_type_string. */
6179 return (NX_WEB_HTTP_ERROR);
6180 }
6181
6182
6183 /* No extension is found. Return the default mime type. */
6184 memcpy(http_type_string, NX_WEB_HTTP_SERVER_DEFAULT_MIME, sizeof(NX_WEB_HTTP_SERVER_DEFAULT_MIME)); /* Use case of memcpy is verified. */
6185 *string_size = sizeof(NX_WEB_HTTP_SERVER_DEFAULT_MIME) - 1;
6186 return(NX_WEB_HTTP_EXTENSION_MIME_DEFAULT);
6187 }
6188
6189 /* Position forward again, past the period. */
6190 ch++;
6191 ext_length--;
6192
6193 /* Now see what HTTP file type to return. */
6194 /* Search user defined MIME maps first. */
6195 if(server_ptr -> nx_web_http_server_mime_maps_additional &&
6196 (server_ptr -> nx_web_http_server_mime_maps_additional_num > 0))
6197 {
6198 for(i = 0; i < server_ptr -> nx_web_http_server_mime_maps_additional_num; i++)
6199 {
6200
6201 /* Check map extension and type length. */
6202 if (_nx_utility_string_length_check(server_ptr -> nx_web_http_server_mime_maps_additional[i].nx_web_http_server_mime_map_extension,
6203 &map_ext_length, ext_length) ||
6204 _nx_utility_string_length_check(server_ptr -> nx_web_http_server_mime_maps_additional[i].nx_web_http_server_mime_map_type,
6205 &map_type_length, http_type_string_max_size - 1))
6206 {
6207 continue;
6208 }
6209
6210 if(_nx_web_http_server_memicmp((UCHAR *)ch, ext_length,
6211 (UCHAR *)server_ptr -> nx_web_http_server_mime_maps_additional[i].nx_web_http_server_mime_map_extension,
6212 map_ext_length) == NX_SUCCESS)
6213 {
6214
6215 /* Find the extension. Return the mapped MIME type. */
6216 memcpy(http_type_string, server_ptr -> nx_web_http_server_mime_maps_additional[i].nx_web_http_server_mime_map_type, map_type_length + 1); /* Use case of memcpy is verified. */
6217 *string_size = map_type_length;
6218 return(NX_SUCCESS);
6219 }
6220 }
6221 }
6222
6223 /* Search default MIME maps. */
6224 for(i = 0; i < sizeof(_nx_web_http_server_mime_maps) / sizeof(NX_WEB_HTTP_SERVER_MIME_MAP); i++)
6225 {
6226
6227 /* Check map extension and type length. */
6228 if (_nx_utility_string_length_check(_nx_web_http_server_mime_maps[i].nx_web_http_server_mime_map_extension,
6229 &map_ext_length, ext_length) ||
6230 _nx_utility_string_length_check(_nx_web_http_server_mime_maps[i].nx_web_http_server_mime_map_type,
6231 &map_type_length, http_type_string_max_size - 1))
6232 {
6233 continue;
6234 }
6235
6236 if(_nx_web_http_server_memicmp((UCHAR *)ch, ext_length,
6237 (UCHAR *)_nx_web_http_server_mime_maps[i].nx_web_http_server_mime_map_extension,
6238 map_ext_length) == NX_SUCCESS)
6239 {
6240
6241 /* Find the extension. Return the mapped MIME type. */
6242 memcpy(http_type_string, _nx_web_http_server_mime_maps[i].nx_web_http_server_mime_map_type, map_type_length + 1); /* Use case of memcpy is verified. */
6243 *string_size = map_type_length;
6244 return(NX_SUCCESS);
6245 }
6246 }
6247
6248 /* No extension matches. Return the default mime type. */
6249
6250 if(http_type_string_max_size < (sizeof(NX_WEB_HTTP_SERVER_DEFAULT_MIME)))
6251 {
6252 /* NX_HTTP_SERVER_DEFAULT_MIME does not fit into
6253 the caller-supplied http_type_string. */
6254 return (NX_WEB_HTTP_ERROR);
6255 }
6256
6257 memcpy(http_type_string, NX_WEB_HTTP_SERVER_DEFAULT_MIME, sizeof(NX_WEB_HTTP_SERVER_DEFAULT_MIME)); /* Use case of memcpy is verified. */
6258 *string_size = sizeof(NX_WEB_HTTP_SERVER_DEFAULT_MIME) - 1;
6259 return(NX_WEB_HTTP_EXTENSION_MIME_DEFAULT);
6260 }
6261
6262
6263 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
6264
6265 /**************************************************************************/
6266 /* */
6267 /* FUNCTION RELEASE */
6268 /* */
6269 /* _nx_web_http_server_nonce_allocate PORTABLE C */
6270 /* 6.2.0 */
6271 /* AUTHOR */
6272 /* */
6273 /* Yuxin Zhou, Microsoft Corporation */
6274 /* */
6275 /* DESCRIPTION */
6276 /* */
6277 /* This function allocate a new nonce for digest authentication. */
6278 /* */
6279 /* INPUT */
6280 /* */
6281 /* server_ptr HTTP Server pointer */
6282 /* nonce_ptr Allocated nonce pointer */
6283 /* */
6284 /* OUTPUT */
6285 /* */
6286 /* None */
6287 /* */
6288 /* CALLS */
6289 /* */
6290 /* tx_time_get Get system time */
6291 /* */
6292 /* CALLED BY */
6293 /* */
6294 /* _nx_web_http_server_digest_authenticate */
6295 /* Digest authentication */
6296 /* */
6297 /* RELEASE HISTORY */
6298 /* */
6299 /* DATE NAME DESCRIPTION */
6300 /* */
6301 /* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */
6302 /* */
6303 /**************************************************************************/
_nx_web_http_server_nonce_allocate(NX_WEB_HTTP_SERVER * server_ptr,NX_WEB_HTTP_SERVER_NONCE ** nonce_ptr)6304 UINT _nx_web_http_server_nonce_allocate(NX_WEB_HTTP_SERVER *server_ptr, NX_WEB_HTTP_SERVER_NONCE **nonce_ptr)
6305 {
6306 UINT i;
6307 UCHAR random_value;
6308 NX_WEB_HTTP_SERVER_NONCE *nonces_list = server_ptr -> nx_web_http_server_nonces;
6309
6310
6311 /* Search if there is free entry for new nonce. */
6312 for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++)
6313 {
6314 if (nonces_list[i].nonce_state == NX_WEB_HTTP_SERVER_NONCE_INVALID)
6315 {
6316 *nonce_ptr = &(nonces_list[i]);
6317 break;
6318 }
6319 }
6320
6321 if (i == NX_WEB_HTTP_SERVER_NONCE_MAX)
6322 {
6323
6324 /* If no free entry, check the timeout of allocated nonces. */
6325 for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++)
6326 {
6327 if (nonces_list[i].nonce_state == NX_WEB_HTTP_SERVER_NONCE_VALID)
6328 {
6329 if (tx_time_get() > nonces_list[i].nonce_timestamp + NX_WEB_HTTP_SERVER_NONCE_TIMEOUT)
6330 {
6331
6332 /* If this nonce is timed out, free up this entry for new nonce. */
6333 *nonce_ptr = &(nonces_list[i]);
6334 break;
6335 }
6336 }
6337 }
6338
6339 /* If no entry can be allocated, return error. */
6340 if (i == NX_WEB_HTTP_SERVER_NONCE_MAX)
6341 {
6342 return(NX_NOT_FOUND);
6343 }
6344 }
6345
6346 /* Generate new nonce for digest authentication. */
6347 for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_SIZE; i++)
6348 {
6349 random_value = (UCHAR)NX_RAND() % (sizeof(_nx_web_http_server_base64_array) - 1);
6350 (*nonce_ptr) -> nonce_buffer[i] = (UCHAR)_nx_web_http_server_base64_array[random_value];
6351 }
6352
6353 /* Reset the timestamp and state for the new nonce. */
6354 (*nonce_ptr) -> nonce_timestamp = tx_time_get();
6355 (*nonce_ptr) -> nonce_state = NX_WEB_HTTP_SERVER_NONCE_VALID;
6356
6357 return(NX_SUCCESS);
6358 }
6359
6360 /**************************************************************************/
6361 /* */
6362 /* FUNCTION RELEASE */
6363 /* */
6364 /* _nx_web_http_server_digest_authenticate PORTABLE C */
6365 /* 6.2.0 */
6366 /* AUTHOR */
6367 /* */
6368 /* Yuxin Zhou, Microsoft Corporation */
6369 /* */
6370 /* DESCRIPTION */
6371 /* */
6372 /* This function checks for digest (MD5 only) authentication. */
6373 /* If the digest is correct, it returns a success. Otherwise, it */
6374 /* returns an authentication request to the requesting client. */
6375 /* */
6376 /* */
6377 /* INPUT */
6378 /* */
6379 /* server_ptr HTTP Server pointer */
6380 /* packet_ptr Request packet pointer */
6381 /* name_ptr Pointer to name string */
6382 /* password_ptr Pointer to password string */
6383 /* realm_ptr Pointer to realm string */
6384 /* auth_request_present Indicate if authentication */
6385 /* must be performed */
6386 /* */
6387 /* OUTPUT */
6388 /* */
6389 /* status Completion status */
6390 /* */
6391 /* CALLS */
6392 /* */
6393 /* _nx_web_http_server_retrieve_digest_authorization */
6394 /* Pickup authorization */
6395 /* _nx_web_http_server_digest_response_calculate */
6396 /* Calculate the digest */
6397 /* _nx_web_http_server_response_packet_allocate */
6398 /* Allocate a response packet */
6399 /* nx_packet_data_append Append information to response*/
6400 /* nx_packet_release Release packet */
6401 /* _nx_web_http_server_send Send HTTP Server response */
6402 /* _nx_utility_string_length_check Check string length */
6403 /* */
6404 /* CALLED BY */
6405 /* */
6406 /* _nx_web_http_server_get_process Process GET request */
6407 /* _nx_web_http_server_put_process Process PUT request */
6408 /* _nx_web_http_server_delete_process Process DELETE request */
6409 /* */
6410 /* RELEASE HISTORY */
6411 /* */
6412 /* DATE NAME DESCRIPTION */
6413 /* */
6414 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6415 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6416 /* resulting in version 6.1 */
6417 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
6418 /* supported random nonce, */
6419 /* resulting in version 6.2.0 */
6420 /* */
6421 /**************************************************************************/
_nx_web_http_server_digest_authenticate(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * name_ptr,CHAR * password_ptr,CHAR * realm_ptr,UINT * auth_request_present)6422 UINT _nx_web_http_server_digest_authenticate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT *auth_request_present)
6423 {
6424
6425 CHAR authorization_response[NX_WEB_HTTP_MAX_ASCII_MD5 + 1];
6426 CHAR calculated_response[NX_WEB_HTTP_MAX_ASCII_MD5 + 1];
6427 CHAR authorization_uri[NX_WEB_HTTP_MAX_RESOURCE + 1];
6428 CHAR method[8];
6429 CHAR quote[2] = {0x22, 0};
6430 CHAR *buffer_ptr;
6431 UINT i;
6432 UINT status, status1, callback_status;
6433 CHAR crlf[2] = {13,10};
6434 CHAR authorization_nc[NX_WEB_HTTP_MAX_RESOURCE + 1];
6435 CHAR authorization_cnonce[NX_WEB_HTTP_MAX_RESOURCE + 1];
6436 UINT realm_length;
6437 NX_WEB_HTTP_SERVER_NONCE *nonce_ptr = NX_NULL;
6438
6439 /* Default to no authentication request detected. */
6440 *auth_request_present = NX_FALSE;
6441
6442 /* Default the status to authenticate. */
6443 status = NX_WEB_HTTP_DIGEST_AUTHENTICATE;
6444
6445 /* Is the authorization request present? */
6446 if (_nx_web_http_server_retrieve_digest_authorization(server_ptr, packet_ptr, authorization_response, authorization_uri, authorization_nc, authorization_cnonce, &nonce_ptr))
6447 {
6448
6449 /* Yes, an authorization request is present. */
6450 *auth_request_present = NX_TRUE;
6451
6452 /* Pickup method from the packet. */
6453 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
6454 i = 0;
6455 while (((buffer_ptr + i) < (CHAR *)packet_ptr -> nx_packet_append_ptr) && (buffer_ptr[i] != ' ') && (i < (sizeof(method) - 1)))
6456 {
6457
6458 /* Copy bytes of method. */
6459 method[i] = buffer_ptr[i];
6460 i++;
6461 }
6462
6463 /* Null terminate method. */
6464 method[i] = (CHAR) NX_NULL;
6465
6466 /* If the digest authenticate callback function is set, invoke the callback function. */
6467 if(server_ptr -> nx_web_http_server_digest_authenticate_callback)
6468 {
6469 callback_status = (server_ptr -> nx_web_http_server_digest_authenticate_callback)(server_ptr, name_ptr, realm_ptr, password_ptr, method, authorization_uri, authorization_nc, authorization_cnonce);
6470 }
6471 else
6472 {
6473
6474 /* If the digest authenticate callback is not set, assume it is success, for backward
6475 compatibility reasons. */
6476 callback_status = NX_SUCCESS;
6477 }
6478
6479 /* Calculate what the MD5 should be. */
6480 _nx_web_http_server_digest_response_calculate(server_ptr, name_ptr, realm_ptr, password_ptr, (CHAR *)(nonce_ptr -> nonce_buffer), method, authorization_uri, authorization_nc, authorization_cnonce, calculated_response);
6481
6482 /* Determine if the calculated response is the same as the received response. */
6483 i = 0;
6484 status = NX_SUCCESS;
6485 while (i < NX_WEB_HTTP_MAX_ASCII_MD5 + 1)
6486 {
6487 /* Is there a mismatch? */
6488 if (calculated_response[i] != authorization_response[i])
6489 {
6490
6491 /* Authorization mismatch. Continue to avoid timing attack. */
6492 status = NX_WEB_HTTP_DIGEST_AUTHENTICATE;
6493 }
6494
6495 /* Otherwise, look at next character. */
6496 i++;
6497 }
6498
6499 /* If the response is authenticated, mark the nonce as accepted. */
6500 if (status == NX_SUCCESS)
6501 {
6502
6503 /* If another session uses the same nonce, don't accept it. */
6504 if (nonce_ptr -> nonce_state == NX_WEB_HTTP_SERVER_NONCE_ACCEPTED)
6505 {
6506 if (nonce_ptr -> nonce_session_ptr != server_ptr -> nx_web_http_server_current_session_ptr)
6507 {
6508 status = NX_WEB_HTTP_DIGEST_AUTHENTICATE;
6509 }
6510 }
6511 else
6512 {
6513
6514 /* Update nonce state and set the session pointer for mapping in disconnection. */
6515 nonce_ptr -> nonce_state = NX_WEB_HTTP_SERVER_NONCE_ACCEPTED;
6516 nonce_ptr -> nonce_session_ptr = server_ptr -> nx_web_http_server_current_session_ptr;
6517 }
6518 }
6519 else
6520 {
6521 nonce_ptr -> nonce_state = NX_WEB_HTTP_SERVER_NONCE_INVALID;
6522 }
6523
6524 /* If digest authenticate callback function returns non-success value, the request is
6525 considered unauthenticated. */
6526 if(callback_status != NX_SUCCESS)
6527 status = NX_WEB_HTTP_DIGEST_AUTHENTICATE;
6528 }
6529
6530 /* Determine if we need to send back an unauthorized request. */
6531 if (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE)
6532 {
6533
6534 /* Allocate a new nonce for digest authentication. */
6535 status1 = _nx_web_http_server_nonce_allocate(server_ptr, &nonce_ptr);
6536
6537 /* Determine if an error occurred in the packet allocation. */
6538 if (status1)
6539 {
6540
6541 /* Send response back to HTTP Client. */
6542 _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1,
6543 "NetX HTTP Server Internal Error", sizeof("NetX HTTP Server Internal Error") - 1, NX_NULL, 0);
6544
6545 /* Indicate an allocation error occurred. */
6546 server_ptr -> nx_web_http_server_allocation_errors++;
6547
6548 /* Return the internal NetX error. */
6549 return(status1);
6550 }
6551
6552 /* We need authorization so build the HTTP 401 Unauthorized message to send to the server. */
6553
6554 /* Check string length. */
6555 if (_nx_utility_string_length_check(realm_ptr, &realm_length, NX_MAX_STRING_LENGTH))
6556 {
6557 return(NX_WEB_HTTP_ERROR);
6558 }
6559
6560 /* Allocate a packet for sending the response back. */
6561 status1 = _nx_web_http_server_response_packet_allocate(server_ptr, &packet_ptr, NX_WAIT_FOREVER);
6562
6563 /* Determine if an error occurred in the packet allocation. */
6564 if (status1 != NX_SUCCESS)
6565 {
6566
6567 /* Indicate an allocation error occurred. */
6568 server_ptr -> nx_web_http_server_allocation_errors++;
6569
6570 /* Return the internal NetX error. */
6571 return(status1);
6572 }
6573
6574 /* Insert the response header. */
6575 nx_packet_data_append(packet_ptr, NX_WEB_HTTP_VERSION, sizeof(NX_WEB_HTTP_VERSION) - 1,
6576 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6577 nx_packet_data_append(packet_ptr, " ", 1, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6578 nx_packet_data_append(packet_ptr, NX_WEB_HTTP_STATUS_UNAUTHORIZED, sizeof(NX_WEB_HTTP_STATUS_UNAUTHORIZED) - 1,
6579 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6580
6581 /* Place the <cr,lf> into the buffer. */
6582 nx_packet_data_append(packet_ptr, crlf, 2,
6583 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6584
6585 /* Insert the type of authentication requested. */
6586 nx_packet_data_append(packet_ptr, "WWW-Authenticate: Digest realm=", 31,
6587 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6588
6589 /* Insert the double quote. */
6590 nx_packet_data_append(packet_ptr, quote, 1,
6591 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6592
6593 /* Place the realm string into the buffer. */
6594 nx_packet_data_append(packet_ptr, realm_ptr, realm_length,
6595 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6596
6597 /* Insert the double quote. */
6598 nx_packet_data_append(packet_ptr, quote, 1,
6599 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6600
6601 /* Place a comma into the buffer. */
6602 nx_packet_data_append(packet_ptr, ",", 1,
6603 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6604
6605 /* Insert the algorithm into the buffer. */
6606 nx_packet_data_append(packet_ptr, " algorithm=", 11,
6607 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6608
6609 /* Insert the double quote. */
6610 nx_packet_data_append(packet_ptr, quote, 1,
6611 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6612
6613 /* Insert the md5 tag into the buffer. */
6614 nx_packet_data_append(packet_ptr, "md5", 3,
6615 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6616
6617 /* Insert the double quote. */
6618 nx_packet_data_append(packet_ptr, quote, 1,
6619 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6620
6621 /* Place a comma into the buffer. */
6622 nx_packet_data_append(packet_ptr, ",", 1,
6623 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6624
6625 /* Insert the nonce into the buffer. */
6626 nx_packet_data_append(packet_ptr, " nonce=", 7,
6627 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6628
6629 /* Insert the double quote. */
6630 nx_packet_data_append(packet_ptr, quote, 1,
6631 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6632
6633 /* Place the nonce string into the buffer. */
6634 nx_packet_data_append(packet_ptr, nonce_ptr -> nonce_buffer, NX_WEB_HTTP_SERVER_NONCE_SIZE,
6635 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6636
6637 /* Insert the double quote. */
6638 nx_packet_data_append(packet_ptr, quote, 1,
6639 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6640
6641 /* Place the qop="auth" parameter string into the buffer. */
6642 nx_packet_data_append(packet_ptr, ", qop=\"auth\"", 12,
6643 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6644
6645 /* Place the <cr,lf> into the buffer. */
6646 nx_packet_data_append(packet_ptr, crlf, 2,
6647 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6648
6649 /* Set Content-Length as 0. */
6650 nx_packet_data_append(packet_ptr, "Content-Length: 0", 17,
6651 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6652
6653 /* Place the <cr,lf> into the buffer. */
6654 nx_packet_data_append(packet_ptr, crlf, 2,
6655 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6656
6657 /* Place another <cr,lf> into the buffer to signal end of FULL HTTP response. */
6658 nx_packet_data_append(packet_ptr, crlf, 2,
6659 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6660
6661 /* Send the response back to the client. */
6662 status1 = _nx_web_http_server_send(server_ptr, packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
6663
6664 /* Check for an error. */
6665 if (status1)
6666 {
6667
6668 /* Set the internal NetX error as the status return. */
6669 status = status1;
6670
6671 /* Just release the packet. */
6672 nx_packet_release(packet_ptr);
6673 }
6674 }
6675
6676 /* Return the result of the authentication request. */
6677 return(status);
6678 }
6679
6680
6681 /**************************************************************************/
6682 /* */
6683 /* FUNCTION RELEASE */
6684 /* */
6685 /* _nx_web_http_server_digest_response_calculate PORTABLE C */
6686 /* 6.2.0 */
6687 /* AUTHOR */
6688 /* */
6689 /* Yuxin Zhou, Microsoft Corporation */
6690 /* */
6691 /* DESCRIPTION */
6692 /* */
6693 /* This function computes the MD5 digest based on the supplied input */
6694 /* parameters. */
6695 /* */
6696 /* INPUT */
6697 /* */
6698 /* server_ptr HTTP Server pointer */
6699 /* username Username string */
6700 /* realm Realm string */
6701 /* password Password string */
6702 /* nonce Authentication nonce string */
6703 /* method Request method string */
6704 /* uri Resource request string */
6705 /* nc Nonce count string */
6706 /* cnonce Client nonce string */
6707 /* result Computed digest string */
6708 /* */
6709 /* OUTPUT */
6710 /* */
6711 /* None */
6712 /* */
6713 /* CALLS */
6714 /* */
6715 /* _nx_web_http_server_hex_ascii_convert Convert hex to ASCII */
6716 /* _nx_md5_initialize Initialize MD5 algorithm */
6717 /* _nx_md5_update Update MD5 digest */
6718 /* _nx_md5_digest_calculate Complete the MD5 algorithm */
6719 /* _nx_utility_string_length_check Check string length */
6720 /* */
6721 /* CALLED BY */
6722 /* */
6723 /* _nx_web_http_server_digest_authenticate */
6724 /* Digest authentication */
6725 /* */
6726 /* RELEASE HISTORY */
6727 /* */
6728 /* DATE NAME DESCRIPTION */
6729 /* */
6730 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6731 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6732 /* resulting in version 6.1 */
6733 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
6734 /* supported random nonce, */
6735 /* resulting in version 6.2.0 */
6736 /* */
6737 /**************************************************************************/
_nx_web_http_server_digest_response_calculate(NX_WEB_HTTP_SERVER * server_ptr,CHAR * username,CHAR * realm,CHAR * password,CHAR * nonce,CHAR * method,CHAR * uri,CHAR * nc,CHAR * cnonce,CHAR * result)6738 VOID _nx_web_http_server_digest_response_calculate(NX_WEB_HTTP_SERVER *server_ptr, CHAR *username, CHAR *realm, CHAR *password, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result)
6739 {
6740
6741 CHAR md5_binary[NX_WEB_HTTP_MAX_BINARY_MD5];
6742 CHAR ha1_string[NX_WEB_HTTP_MAX_ASCII_MD5 + 1];
6743 CHAR ha2_string[NX_WEB_HTTP_MAX_ASCII_MD5 + 1];
6744 UINT username_length;
6745 UINT password_length;
6746 UINT realm_length;
6747 UINT method_length;
6748 UINT uri_length;
6749 UINT nc_length;
6750 UINT cnonce_length;
6751
6752 /* Check string length. */
6753 if (_nx_utility_string_length_check(username, &username_length, NX_WEB_HTTP_MAX_NAME) ||
6754 _nx_utility_string_length_check(password, &password_length, NX_WEB_HTTP_MAX_PASSWORD) ||
6755 _nx_utility_string_length_check(realm, &realm_length, NX_MAX_STRING_LENGTH) ||
6756 _nx_utility_string_length_check(method, &method_length, 7) ||
6757 _nx_utility_string_length_check(uri, &uri_length, NX_WEB_HTTP_MAX_RESOURCE) ||
6758 _nx_utility_string_length_check(nc, &nc_length, NX_WEB_HTTP_MAX_RESOURCE) ||
6759 _nx_utility_string_length_check(cnonce, &cnonce_length, NX_WEB_HTTP_MAX_RESOURCE))
6760 {
6761 return;
6762 }
6763
6764
6765 /* Calculate the H(A1) portion of the digest. */
6766 _nx_md5_initialize(&(server_ptr -> nx_web_http_server_md5data));
6767 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) username, username_length);
6768 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6769 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) realm, realm_length);
6770 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6771 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) password, password_length);
6772 _nx_md5_digest_calculate(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) md5_binary);
6773
6774 /* Convert this H(A1) portion to ASCII Hex representation. */
6775 _nx_web_http_server_hex_ascii_convert(md5_binary, NX_WEB_HTTP_MAX_BINARY_MD5, ha1_string);
6776
6777 /* Make the H(A2) portion of the digest. */
6778 _nx_md5_initialize(&(server_ptr -> nx_web_http_server_md5data));
6779 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) method, method_length);
6780 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6781 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) uri, uri_length);
6782 _nx_md5_digest_calculate(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) md5_binary);
6783
6784 /* Convert this H(A2) portion to ASCII Hex representation. */
6785 _nx_web_http_server_hex_ascii_convert(md5_binary, NX_WEB_HTTP_MAX_BINARY_MD5, ha2_string);
6786
6787 /* Now make the final MD5 digest. */
6788 _nx_md5_initialize(&(server_ptr -> nx_web_http_server_md5data));
6789 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ha1_string, sizeof(ha1_string) - 1);
6790 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6791 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) nonce, NX_WEB_HTTP_SERVER_NONCE_SIZE);
6792
6793 /* Start of Internet Explorer bug work-around. */
6794 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6795 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) nc, nc_length);
6796 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6797 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) cnonce, cnonce_length);
6798 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":auth", 5);
6799 /* End of Internet Explorer bug work-around. */
6800
6801 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1);
6802 _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ha2_string, sizeof(ha2_string) - 1);
6803 _nx_md5_digest_calculate(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) md5_binary);
6804
6805 /* Finally, convert the response back to an ASCII string and place in
6806 the destination. */
6807 _nx_web_http_server_hex_ascii_convert(md5_binary, NX_WEB_HTTP_MAX_BINARY_MD5, result);
6808 }
6809
6810
6811 /**************************************************************************/
6812 /* */
6813 /* FUNCTION RELEASE */
6814 /* */
6815 /* _nx_web_http_server_retrieve_digest_authorization PORTABLE C */
6816 /* 6.2.0 */
6817 /* AUTHOR */
6818 /* */
6819 /* Yuxin Zhou, Microsoft Corporation */
6820 /* */
6821 /* DESCRIPTION */
6822 /* */
6823 /* This function retrieves the MD5 digest parameters from the */
6824 /* supplied request packet. */
6825 /* */
6826 /* INPUT */
6827 /* */
6828 /* server_ptr HTTP Server pointer */
6829 /* packet_ptr Request packet pointer */
6830 /* response Digest response pointer */
6831 /* uri URI from response pointer */
6832 /* nc Nonce count string */
6833 /* cnonce Client nonce string */
6834 /* nonce_ptr Server nonce pointer */
6835 /* */
6836 /* OUTPUT */
6837 /* */
6838 /* length Length of response (should be */
6839 /* 32). A value of 0 indicates */
6840 /* an error is present */
6841 /* */
6842 /* CALLS */
6843 /* */
6844 /* None */
6845 /* */
6846 /* CALLED BY */
6847 /* */
6848 /* _nx_web_http_server_digest_authenticate */
6849 /* Digest authentication */
6850 /* */
6851 /* RELEASE HISTORY */
6852 /* */
6853 /* DATE NAME DESCRIPTION */
6854 /* */
6855 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6856 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6857 /* resulting in version 6.1 */
6858 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
6859 /* supported random nonce, */
6860 /* resulting in version 6.2.0 */
6861 /* */
6862 /**************************************************************************/
_nx_web_http_server_retrieve_digest_authorization(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * response,CHAR * uri,CHAR * nc,CHAR * cnonce,NX_WEB_HTTP_SERVER_NONCE ** nonce_ptr)6863 UINT _nx_web_http_server_retrieve_digest_authorization(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce, NX_WEB_HTTP_SERVER_NONCE **nonce_ptr)
6864 {
6865
6866 UINT length;
6867 UINT found;
6868 CHAR *buffer_ptr;
6869 CHAR *saved_buffer_ptr;
6870 UCHAR *nonce_buffer;
6871 UINT i;
6872
6873
6874 /* Set the found flag to false. */
6875 found = NX_FALSE;
6876
6877 /* Default the authorization request to zero. */
6878 length = 0;
6879
6880 /* Set the response and uri strings to NULL. */
6881 response[0] = NX_NULL;
6882 uri[0] = NX_NULL;
6883
6884 /* Internet Explorer bug work-around. */
6885 nc[0] = NX_NULL;
6886 cnonce[0] = NX_NULL;
6887
6888 /* Setup pointer to buffer. */
6889 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
6890
6891 /* Find the "Authorization: " token first. */
6892 while (((buffer_ptr+15) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6893 {
6894
6895 /* Check for the Authorization: token. */
6896 if (((*buffer_ptr == 'a') || (*buffer_ptr == 'A')) &&
6897 ((*(buffer_ptr+1) == 'u') || (*(buffer_ptr+1) == 'U')) &&
6898 ((*(buffer_ptr+2) == 't') || (*(buffer_ptr+2) == 'T')) &&
6899 ((*(buffer_ptr+3) == 'h') || (*(buffer_ptr+3) == 'H')) &&
6900 ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) &&
6901 ((*(buffer_ptr+5) == 'r') || (*(buffer_ptr+5) == 'R')) &&
6902 ((*(buffer_ptr+6) == 'i') || (*(buffer_ptr+6) == 'I')) &&
6903 ((*(buffer_ptr+7) == 'z') || (*(buffer_ptr+7) == 'Z')) &&
6904 ((*(buffer_ptr+8) == 'a') || (*(buffer_ptr+8) == 'A')) &&
6905 ((*(buffer_ptr+9) == 't') || (*(buffer_ptr+9) == 'T')) &&
6906 ((*(buffer_ptr+10) == 'i') || (*(buffer_ptr+10) == 'I')) &&
6907 ((*(buffer_ptr+11) == 'o') || (*(buffer_ptr+11) == 'O')) &&
6908 ((*(buffer_ptr+12) == 'n') || (*(buffer_ptr+12) == 'N')) &&
6909 (*(buffer_ptr+13) == ':') &&
6910 (*(buffer_ptr+14) == ' '))
6911 {
6912
6913 /* Move the pointer up to the length token. */
6914 buffer_ptr = buffer_ptr + 15;
6915
6916 /* Set the found flag. */
6917 found = NX_TRUE;
6918 break;
6919 }
6920
6921 /* Move the pointer up to the next character. */
6922 buffer_ptr++;
6923 }
6924
6925 /* Determine if the first token was found. */
6926 if (!found)
6927 {
6928
6929 /* No, authorization is not present. Return a zero length. */
6930 return(length);
6931 }
6932
6933 /* Set the found flag back to false. */
6934 found = NX_FALSE;
6935
6936 /* Now remove any extra blanks. */
6937 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
6938 {
6939
6940 /* Move the pointer up one character. */
6941 buffer_ptr++;
6942 }
6943
6944 /* Now check for the "Digest " token. */
6945 while (((buffer_ptr+7) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6946 {
6947
6948 /* Check for the Digest token. */
6949 if (((*buffer_ptr == 'd') || (*buffer_ptr == 'D')) &&
6950 ((*(buffer_ptr+1) == 'i') || (*(buffer_ptr+1) == 'I')) &&
6951 ((*(buffer_ptr+2) == 'g') || (*(buffer_ptr+2) == 'G')) &&
6952 ((*(buffer_ptr+3) == 'e') || (*(buffer_ptr+3) == 'E')) &&
6953 ((*(buffer_ptr+4) == 's') || (*(buffer_ptr+4) == 'S')) &&
6954 ((*(buffer_ptr+5) == 't') || (*(buffer_ptr+5) == 'T')) &&
6955 (*(buffer_ptr+6) == ' '))
6956 {
6957
6958 /* Move the pointer up to the actual authorization string. */
6959 buffer_ptr = buffer_ptr + 7;
6960
6961 /* Set the found flag. */
6962 found = NX_TRUE;
6963 break;
6964 }
6965
6966 /* Move the pointer up to the next character. */
6967 buffer_ptr++;
6968 }
6969
6970 /* Determine if the second token was found. */
6971 if (!found)
6972 {
6973
6974 /* No, digest is not present. Return a zero length. */
6975 return(length);
6976 }
6977
6978 /* Now remove any extra blanks. */
6979 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
6980 {
6981
6982 /* Move the pointer up one character. */
6983 buffer_ptr++;
6984 }
6985
6986 /* Start of Internet Explorer bug work-around (Parses nc and cnonce parameters). */
6987
6988 /* Save current buffer pointer, so each parameter search always starts from here. */
6989 saved_buffer_ptr = buffer_ptr;
6990
6991 while (((buffer_ptr + 6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6992 {
6993
6994 /* Check for the uri token. */
6995 if (((*(buffer_ptr) == 'n') || (*(buffer_ptr) == 'N')) &&
6996 ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) &&
6997 ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) &&
6998 ((*(buffer_ptr+3) == 'c') || (*(buffer_ptr+3) == 'C')) &&
6999 ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) &&
7000 (*(buffer_ptr+5) == '='))
7001 {
7002
7003 /* Move the pointer up to the actual nonce string. */
7004 buffer_ptr = buffer_ptr + 6;
7005 found = NX_TRUE;
7006
7007 break;
7008 }
7009
7010 /* Move the pointer up to the next character. */
7011 buffer_ptr++;
7012 }
7013
7014 /* Check if nonce is found. */
7015 if (!found)
7016 {
7017 return(0);
7018 }
7019
7020 /* Now remove any extra blanks and quotes. */
7021 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
7022 {
7023
7024 /* Move the pointer up one character. */
7025 buffer_ptr++;
7026 }
7027
7028 /* Now pickup the nonce string. */
7029 length = 0;
7030 nonce_buffer = (UCHAR *)buffer_ptr;
7031 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13))
7032 {
7033
7034 /* Determine if the ending quote is present. */
7035 if (*buffer_ptr == (CHAR) 0x22)
7036 {
7037 break;
7038 }
7039
7040 /* Increase the length. */
7041 length++;
7042 buffer_ptr++;
7043 }
7044
7045 /* Check the nonce size. */
7046 if (length != NX_WEB_HTTP_SERVER_NONCE_SIZE)
7047 {
7048 return(0);
7049 }
7050
7051 /* Check if the nonce is valid. */
7052 for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++)
7053 {
7054 if ((server_ptr -> nx_web_http_server_nonces[i].nonce_state != NX_WEB_HTTP_SERVER_NONCE_INVALID) &&
7055 (memcmp(server_ptr -> nx_web_http_server_nonces[i].nonce_buffer, nonce_buffer, NX_WEB_HTTP_SERVER_NONCE_SIZE) == 0)) /* Use case of memcmp is verified. */
7056 {
7057 *nonce_ptr = &(server_ptr -> nx_web_http_server_nonces[i]);
7058 break;
7059 }
7060 }
7061
7062 /* If the nonca is invalid, just return. */
7063 if (i == NX_WEB_HTTP_SERVER_NONCE_MAX)
7064 {
7065 return(0);
7066 }
7067
7068 /* Get saved buffer pointer. */
7069 buffer_ptr = saved_buffer_ptr;
7070
7071 /* Now look for the nc in the digest response. */
7072 while (((buffer_ptr+3) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
7073 {
7074
7075 /* Check for the nc token. */
7076 if (((*buffer_ptr == 'n') || (*buffer_ptr == 'N')) &&
7077 ((*(buffer_ptr+1) == 'c') || (*(buffer_ptr+1) == 'C')) &&
7078 (*(buffer_ptr+2) == '='))
7079 {
7080
7081 /* Move the pointer up to the actual authorization string. */
7082 buffer_ptr = buffer_ptr + 3;
7083
7084 break;
7085 }
7086
7087 /* Move the pointer up to the next character. */
7088 buffer_ptr++;
7089 }
7090
7091 /* Now remove any extra blanks and quotes (should be no starting quote). */
7092 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
7093 {
7094
7095 /* Move the pointer up one character. */
7096 buffer_ptr++;
7097 }
7098
7099 /* Now pickup the nc string (should be 8 hex characters; should not be quoted). */
7100 length = 0;
7101 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_WEB_HTTP_MAX_RESOURCE))
7102 {
7103
7104 /* Determine if the ending quote or comma is present (should be no ending quote). */
7105 if ((*buffer_ptr == (CHAR) 0x22) || (*buffer_ptr == ','))
7106 {
7107
7108 break;
7109 }
7110
7111 /* Copy a character of the authorization string into the destination. */
7112 nc[length++] = *buffer_ptr++;
7113 }
7114
7115 /* Null terminate the NC. */
7116 nc[length] = (CHAR) NX_NULL;
7117
7118
7119 /* Get saved buffer pointer. */
7120 buffer_ptr = saved_buffer_ptr;
7121
7122 /* Now look for the cnonce in the digest response. */
7123 while (((buffer_ptr+7) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
7124 {
7125
7126 /* Check for the uri token. */
7127 if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) &&
7128 ((*(buffer_ptr+1) == 'n') || (*(buffer_ptr+1) == 'N')) &&
7129 ((*(buffer_ptr+2) == 'o') || (*(buffer_ptr+2) == 'O')) &&
7130 ((*(buffer_ptr+3) == 'n') || (*(buffer_ptr+3) == 'N')) &&
7131 ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+4) == 'C')) &&
7132 ((*(buffer_ptr+5) == 'e') || (*(buffer_ptr+5) == 'E')) &&
7133 (*(buffer_ptr+6) == '='))
7134 {
7135
7136 /* Move the pointer up to the actual authorization string. */
7137 buffer_ptr = buffer_ptr + 7;
7138
7139 break;
7140 }
7141
7142 /* Move the pointer up to the next character. */
7143 buffer_ptr++;
7144 }
7145
7146 /* Now remove any extra blanks and quotes. */
7147 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
7148 {
7149
7150 /* Move the pointer up one character. */
7151 buffer_ptr++;
7152 }
7153
7154 /* Now pickup the cnonce string. */
7155 length = 0;
7156 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_WEB_HTTP_MAX_RESOURCE))
7157 {
7158
7159 /* Determine if the ending quote is present. */
7160 if (*buffer_ptr == (CHAR) 0x22)
7161 {
7162
7163 break;
7164 }
7165
7166 /* Copy a character of the authorization string into the destination. */
7167 cnonce[length++] = *buffer_ptr++;
7168 }
7169
7170 /* Null terminate the CNONCE. */
7171 cnonce[length] = (CHAR) NX_NULL;
7172
7173 /* End of Internet Explorer bug work-around. */
7174
7175 /* Get saved buffer pointer. */
7176 buffer_ptr = saved_buffer_ptr;
7177
7178 /* Now look for the uri in the digest response. */
7179 while (((buffer_ptr+4) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
7180 {
7181
7182 /* Check for the uri token. */
7183 if (((*buffer_ptr == 'u') || (*buffer_ptr == 'U')) &&
7184 ((*(buffer_ptr+1) == 'r') || (*(buffer_ptr+1) == 'R')) &&
7185 ((*(buffer_ptr+2) == 'i') || (*(buffer_ptr+2) == 'I')) &&
7186 (*(buffer_ptr+3) == '='))
7187 {
7188
7189 /* Move the pointer up to the actual authorization string. */
7190 buffer_ptr = buffer_ptr + 4;
7191
7192 break;
7193 }
7194
7195 /* Move the pointer up to the next character. */
7196 buffer_ptr++;
7197 }
7198
7199 /* Now remove any extra blanks and quotes. */
7200 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
7201 {
7202
7203 /* Move the pointer up one character. */
7204 buffer_ptr++;
7205 }
7206
7207 /* Now pickup the uri string. */
7208 length = 0;
7209 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_WEB_HTTP_MAX_RESOURCE))
7210 {
7211
7212 /* Determine if the ending quote is present. */
7213 if (*buffer_ptr == (CHAR) 0x22)
7214 {
7215
7216 break;
7217 }
7218
7219 /* Copy a character of the authorization string into the destination. */
7220 uri[length++] = *buffer_ptr++;
7221 }
7222
7223 /* Null terminate the URI. */
7224 uri[length] = (CHAR) NX_NULL;
7225
7226 /* Get saved buffer pointer. */
7227 buffer_ptr = saved_buffer_ptr;
7228
7229 /* Now look for the digest response. */
7230 while (((buffer_ptr+9) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
7231 {
7232
7233 /* Check for the uri token. */
7234 if (((*buffer_ptr == 'r') || (*buffer_ptr == 'R')) &&
7235 ((*(buffer_ptr+1) == 'e') || (*(buffer_ptr+1) == 'E')) &&
7236 ((*(buffer_ptr+2) == 's') || (*(buffer_ptr+2) == 'S')) &&
7237 ((*(buffer_ptr+3) == 'p') || (*(buffer_ptr+3) == 'P')) &&
7238 ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) &&
7239 ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) &&
7240 ((*(buffer_ptr+6) == 's') || (*(buffer_ptr+6) == 'S')) &&
7241 ((*(buffer_ptr+7) == 'e') || (*(buffer_ptr+7) == 'E')) &&
7242 (*(buffer_ptr+8) == '='))
7243 {
7244
7245 /* Move the pointer up to the actual authorization string. */
7246 buffer_ptr = buffer_ptr + 9;
7247
7248 break;
7249 }
7250
7251 /* Move the pointer up to the next character. */
7252 buffer_ptr++;
7253 }
7254
7255 /* Now remove any extra blanks and leading quote. */
7256 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
7257 {
7258
7259 /* Move the pointer up one character. */
7260 buffer_ptr++;
7261 }
7262
7263 /* Finally, pickup the response. */
7264 length = 0;
7265 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (*buffer_ptr != (CHAR) 0x3A) && (length < NX_WEB_HTTP_MAX_ASCII_MD5))
7266 {
7267
7268 /* Determine if the ending quote is present. */
7269 if (*buffer_ptr == (CHAR) 0x22)
7270 {
7271
7272 break;
7273 }
7274
7275 /* Copy a character of the response string into the destination. */
7276 response[length++] = *buffer_ptr++;
7277 }
7278
7279 /* Null terminate response. */
7280 response[length] = (CHAR) NX_NULL;
7281
7282 /* Check for an error. */
7283 if ((length != 32) || (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr) || (*buffer_ptr != (CHAR) 0x22))
7284 {
7285
7286 /* Error, clear the length and the response string. */
7287 length = 0;
7288 response[0] = (CHAR) NX_NULL;
7289 }
7290
7291 /* Return the length to the caller. */
7292 return(length);
7293 }
7294
7295
7296 /**************************************************************************/
7297 /* */
7298 /* FUNCTION RELEASE */
7299 /* */
7300 /* _nx_web_http_server_hex_ascii_convert PORTABLE C */
7301 /* 6.1 */
7302 /* AUTHOR */
7303 /* */
7304 /* Yuxin Zhou, Microsoft Corporation */
7305 /* */
7306 /* DESCRIPTION */
7307 /* */
7308 /* This function converts hexadecimal characters into an ASCII string. */
7309 /* */
7310 /* INPUT */
7311 /* */
7312 /* source Source hex string */
7313 /* source_length Length of source string */
7314 /* destination Pointer to destination string */
7315 /* */
7316 /* OUTPUT */
7317 /* */
7318 /* None */
7319 /* */
7320 /* CALLS */
7321 /* */
7322 /* None */
7323 /* */
7324 /* CALLED BY */
7325 /* */
7326 /* _nx_web_http_server_digest_response_calculate */
7327 /* Digest authentication */
7328 /* */
7329 /* RELEASE HISTORY */
7330 /* */
7331 /* DATE NAME DESCRIPTION */
7332 /* */
7333 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7334 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7335 /* resulting in version 6.1 */
7336 /* */
7337 /**************************************************************************/
_nx_web_http_server_hex_ascii_convert(CHAR * source,UINT source_length,CHAR * destination)7338 VOID _nx_web_http_server_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination)
7339 {
7340
7341 UINT i,j;
7342 CHAR digit;
7343
7344
7345 /* Setup destination index. */
7346 j = 0;
7347
7348 /* Loop to process the entire source string. */
7349 for (i = 0; i < source_length; i++)
7350 {
7351
7352 /* Pickup the first nibble. */
7353 digit = (source[i] >> 4) & 0xF;
7354
7355 /* Convert to ASCII and store. */
7356 if (digit <= 9)
7357 destination[j++] = (CHAR)(digit + '0');
7358 else
7359 destination[j++] = (CHAR)(digit + 'a' - 10);
7360
7361 /* Pickup the second nibble. */
7362 digit = source[i] & 0xF;
7363
7364 /* Convert to ASCII and store. */
7365 if (digit <= 9)
7366 destination[j++] = (CHAR)(digit + '0');
7367 else
7368 destination[j++] = (CHAR)(digit + 'a' - 10);
7369 }
7370
7371 /* Finally, place a NULL in the destination string. */
7372 destination[j] = (CHAR) NX_NULL;
7373 }
7374 #endif
7375
7376
7377 /**************************************************************************/
7378 /* */
7379 /* FUNCTION RELEASE */
7380 /* */
7381 /* _nxe_web_http_server_get_entity_header PORTABLE C */
7382 /* 6.1 */
7383 /* AUTHOR */
7384 /* */
7385 /* Yuxin Zhou, Microsoft Corporation */
7386 /* */
7387 /* DESCRIPTION */
7388 /* */
7389 /* This function checks error for getting the entity header. */
7390 /* */
7391 /* INPUT */
7392 /* */
7393 /* server_ptr Pointer to HTTP server */
7394 /* packet_pptr Pointer to packet */
7395 /* entity_header_buffer Buffer to get entity header */
7396 /* buffer_size Size of buffer */
7397 /* */
7398 /* OUTPUT */
7399 /* */
7400 /* status Completion status */
7401 /* */
7402 /* CALLS */
7403 /* */
7404 /* _nx_web_http_server_get_entity_header */
7405 /* */
7406 /* CALLED BY */
7407 /* */
7408 /* Application Code */
7409 /* */
7410 /* RELEASE HISTORY */
7411 /* */
7412 /* DATE NAME DESCRIPTION */
7413 /* */
7414 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7415 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7416 /* resulting in version 6.1 */
7417 /* */
7418 /**************************************************************************/
_nxe_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,UCHAR * entity_header_buffer,ULONG buffer_size)7419 UINT _nxe_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, UCHAR *entity_header_buffer, ULONG buffer_size)
7420 {
7421
7422 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
7423 /* Check for invalid input pointers. */
7424 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
7425 (packet_pptr == NX_NULL) || (entity_header_buffer == NX_NULL))
7426 return NX_PTR_ERROR;
7427
7428 /* Check for appropriate caller. */
7429 NX_THREADS_ONLY_CALLER_CHECKING
7430
7431 return _nx_web_http_server_get_entity_header(server_ptr, packet_pptr, entity_header_buffer, buffer_size);
7432 #else
7433 NX_PARAMETER_NOT_USED(server_ptr);
7434 NX_PARAMETER_NOT_USED(packet_pptr);
7435 NX_PARAMETER_NOT_USED(entity_header_buffer);
7436 NX_PARAMETER_NOT_USED(buffer_size);
7437
7438 return NX_WEB_HTTP_ERROR;
7439 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
7440 }
7441
7442
7443 /**************************************************************************/
7444 /* */
7445 /* FUNCTION RELEASE */
7446 /* */
7447 /* _nx_web_http_server_get_entity_header PORTABLE C */
7448 /* 6.1.11 */
7449 /* AUTHOR */
7450 /* */
7451 /* Yuxin Zhou, Microsoft Corporation */
7452 /* */
7453 /* DESCRIPTION */
7454 /* */
7455 /* This function gets the entity header and skip header. */
7456 /* */
7457 /* INPUT */
7458 /* */
7459 /* server_ptr Pointer to HTTP server */
7460 /* packet_pptr Pointer to packet */
7461 /* entity_header_buffer Buffer to get entity header */
7462 /* buffer_size Size of buffer */
7463 /* */
7464 /* OUTPUT */
7465 /* */
7466 /* status Completion status */
7467 /* */
7468 /* CALLS */
7469 /* */
7470 /* _nx_web_http_server_field_value_get */
7471 /* _nx_web_http_server_memicmp */
7472 /* _nx_web_http_server_boundary_find */
7473 /* nx_packet_release */
7474 /* nx_tcp_socket_receive */
7475 /* _nx_utility_string_length_check */
7476 /* memmove */
7477 /* */
7478 /* CALLED BY */
7479 /* */
7480 /* Application Code */
7481 /* */
7482 /* RELEASE HISTORY */
7483 /* */
7484 /* DATE NAME DESCRIPTION */
7485 /* */
7486 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7487 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
7488 /* fixed write underflow, */
7489 /* resulting in version 6.1 */
7490 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
7491 /* verified memmove use cases, */
7492 /* resulting in version 6.1.11 */
7493 /* */
7494 /**************************************************************************/
_nx_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,UCHAR * entity_header_buffer,ULONG buffer_size)7495 UINT _nx_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, UCHAR *entity_header_buffer, ULONG buffer_size)
7496 {
7497
7498 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
7499 NX_WEB_HTTP_SERVER_MULTIPART *multipart_ptr;
7500 UINT status;
7501 UINT offset;
7502 NX_PACKET *available_packet;
7503 UINT crlf_match_count = 0;
7504 UINT end_boundary_count = 2;
7505 UINT skip_count = 2;
7506 UCHAR *ch;
7507 UINT index;
7508
7509 /* Get multipart context. */
7510 multipart_ptr = &server_ptr -> nx_web_http_server_multipart;
7511
7512 /* Is the multipart context initialized? */
7513 if(multipart_ptr -> nx_web_http_server_multipart_boundary[0] == 0)
7514 {
7515 ULONG field_length;
7516 UINT quotation_index;
7517 UINT i;
7518
7519 /* No, it is not initialized. */
7520
7521 /* Get content type. */
7522 status = _nx_web_http_server_field_value_get(*packet_pptr, (UCHAR *)"content-type", 12,
7523 multipart_ptr -> nx_web_http_server_multipart_boundary, NX_WEB_HTTP_MAX_HEADER_FIELD + 1);
7524 if(status)
7525 return status;
7526
7527 /* Is the content type "multipart"? */
7528 /* Check the length. The length of "multipart/" is 10. */
7529 if (_nx_utility_string_length_check((CHAR *)multipart_ptr -> nx_web_http_server_multipart_boundary, (UINT *)&field_length, NX_WEB_HTTP_MAX_HEADER_FIELD))
7530 return NX_WEB_HTTP_ERROR;
7531 if(field_length < 10)
7532 return NX_WEB_HTTP_NOT_FOUND;
7533
7534 /* Check the data. */
7535 if(_nx_web_http_server_memicmp(multipart_ptr -> nx_web_http_server_multipart_boundary, 10,
7536 (UCHAR *)"multipart/", 10) != NX_SUCCESS)
7537 return NX_WEB_HTTP_NOT_FOUND;
7538
7539 /* Find the boundary. The length of "boundary=" is 9. */
7540 index = 0;
7541 while((index + 9) < field_length)
7542 {
7543 if(_nx_web_http_server_memicmp(&multipart_ptr -> nx_web_http_server_multipart_boundary[index], 9,
7544 (UCHAR *)"boundary=", 9) == NX_SUCCESS)
7545 {
7546
7547 break;
7548 }
7549
7550 /* Move the pointer up to the next character. */
7551 index++;
7552 }
7553
7554 /* Move the pointer up to the boundary value. */
7555 index += 9;
7556
7557 /* Is boundary string found? */
7558 if((field_length - index) <= 1)
7559 {
7560
7561 /* Boundary not found or no boundary value. */
7562 return NX_WEB_HTTP_NOT_FOUND;
7563 }
7564
7565 /* Boundary is started with "CRLF--". */
7566 multipart_ptr -> nx_web_http_server_multipart_boundary[0] = 13;
7567 multipart_ptr -> nx_web_http_server_multipart_boundary[1] = 10;
7568 multipart_ptr -> nx_web_http_server_multipart_boundary[2] = '-';
7569 multipart_ptr -> nx_web_http_server_multipart_boundary[3] = '-';
7570
7571 /* Remove quotation. */
7572 if(multipart_ptr -> nx_web_http_server_multipart_boundary[index] == '"')
7573 {
7574
7575 /* Find the right quotation. */
7576 index++;
7577 for(quotation_index = field_length; quotation_index > index; quotation_index--)
7578 {
7579 if(multipart_ptr -> nx_web_http_server_multipart_boundary[quotation_index] == '"')
7580 break;
7581 }
7582
7583 /* Is the right quotation found? */
7584 if(quotation_index > index)
7585 multipart_ptr -> nx_web_http_server_multipart_boundary[quotation_index] = 0;
7586 else
7587 {
7588
7589 /* Boundary not valid. */
7590 return NX_WEB_HTTP_NOT_FOUND;
7591 }
7592
7593 /* Leave boundary string only. */
7594 memmove(&multipart_ptr -> nx_web_http_server_multipart_boundary[4],
7595 &multipart_ptr -> nx_web_http_server_multipart_boundary[index],
7596 quotation_index - index + 1); /* Use case of memmove is verified. */
7597 }
7598 else
7599 {
7600
7601 /* Directly copy boundary string to the head field. */
7602 i = 4;
7603 index -= 4;
7604 do
7605 {
7606 multipart_ptr -> nx_web_http_server_multipart_boundary[i] = multipart_ptr -> nx_web_http_server_multipart_boundary[index + i];
7607 i++;
7608 }while((multipart_ptr -> nx_web_http_server_multipart_boundary[i - 1] != 0) &&
7609 (multipart_ptr -> nx_web_http_server_multipart_boundary[i - 1] != ' '));
7610
7611 /* Set the terminal character. */
7612 multipart_ptr -> nx_web_http_server_multipart_boundary[i - 1] = 0;
7613 }
7614 }
7615
7616 /* If the received request is chunked. */
7617 if (server_ptr -> nx_web_http_server_request_chunked)
7618 {
7619
7620 /* If never processed the chunked packet, need to separate the HTTP header and content. */
7621 if (!server_ptr -> nx_web_http_server_expect_receive_bytes)
7622 {
7623
7624 available_packet = *packet_pptr;
7625
7626 /* Separate the HTTP header and get the first content packet. */
7627 status = _nx_web_http_server_packet_content_find(server_ptr, &available_packet, NX_NULL);
7628 if (status)
7629 {
7630 return(status);
7631 }
7632
7633 /* Append '\r\n' to the start of the packet. */
7634 available_packet -> nx_packet_prepend_ptr -= 2;
7635 available_packet -> nx_packet_prepend_ptr[0] = 13;
7636 available_packet -> nx_packet_prepend_ptr[1] = 10;
7637
7638 /* Update packet length. */
7639 available_packet -> nx_packet_length += 2;
7640
7641 /* Store the packet. */
7642 nx_packet_release(*packet_pptr);
7643 *packet_pptr = available_packet;
7644 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = available_packet;
7645
7646 /* Reset the offset. */
7647 multipart_ptr -> nx_web_http_server_multipart_available_offset = 0;
7648 }
7649 }
7650
7651 /* Find the boundary. */
7652 while(multipart_ptr -> nx_web_http_server_multipart_boundary_find == NX_FALSE)
7653 {
7654 if(_nx_web_http_server_boundary_find(server_ptr, packet_pptr) != NX_SUCCESS)
7655 break;
7656 }
7657
7658 /* Whether the boundary is found? */
7659 if(multipart_ptr -> nx_web_http_server_multipart_boundary_find == NX_FALSE)
7660 return NX_WEB_HTTP_NOT_FOUND;
7661
7662 /* Update the packet and offset. */
7663 _nx_web_http_server_boundary_find(server_ptr, packet_pptr);
7664
7665 /* Get offset of available data in the packet. */
7666 offset = multipart_ptr -> nx_web_http_server_multipart_available_offset;
7667
7668 /* Skip data that are not header. */
7669 available_packet = *packet_pptr;
7670
7671 if(offset >= available_packet -> nx_packet_length)
7672 {
7673
7674 /* Release the packet that has been processed. */
7675 nx_packet_release(*packet_pptr);
7676
7677 /* All data has been processed. Get a new packet. */
7678 if(_nx_web_http_server_packet_get(server_ptr, &available_packet) != NX_SUCCESS)
7679 {
7680
7681 /* Error, return to caller. */
7682 return(NX_WEB_HTTP_TIMEOUT);
7683 }
7684
7685 /* Store the packet. */
7686 *packet_pptr = available_packet;
7687 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = available_packet;
7688 }
7689 #ifndef NX_DISABLE_PACKET_CHAIN
7690 else
7691 {
7692 while((UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr) <= offset)
7693 {
7694 offset -= (UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr);
7695
7696 /* Get next packet. */
7697 available_packet = available_packet -> nx_packet_next;
7698 }
7699 }
7700 #endif /* NX_DISABLE_PACKET_CHAIN */
7701
7702 /* Get entity header. */
7703 ch = available_packet -> nx_packet_prepend_ptr + offset;
7704 index = 0;
7705 while((entity_header_buffer == NX_NULL) || (index < buffer_size))
7706 {
7707
7708 /* Calculate valid CRLF. */
7709 if((*ch == 13) && ((crlf_match_count & 1) == 0))
7710 crlf_match_count++;
7711 else if((*ch == 10) && ((crlf_match_count & 1) == 1))
7712 crlf_match_count++;
7713 else if(*ch == '-')
7714 {
7715
7716 /* Check whether the last boundary is found. */
7717 if(end_boundary_count < 3)
7718 end_boundary_count--;
7719
7720 if(end_boundary_count == 0)
7721 break;
7722 }
7723 else
7724 {
7725 end_boundary_count = 0xFF;
7726 crlf_match_count = 0;
7727 }
7728
7729 /* Copy data to buffer. */
7730 if(skip_count >0)
7731 skip_count--;
7732 else
7733 {
7734 if(entity_header_buffer)
7735 entity_header_buffer[index] = *ch;
7736 index++;
7737 }
7738 multipart_ptr -> nx_web_http_server_multipart_available_offset++;
7739
7740 /* Check whether two CRLFs are found. */
7741 if(crlf_match_count == 4)
7742 break;
7743
7744 /* Get next character. */
7745 if((ch + 1) >= available_packet -> nx_packet_append_ptr)
7746 {
7747
7748 /* ch points to the end of this packet. */
7749 #ifndef NX_DISABLE_PACKET_CHAIN
7750 if(available_packet -> nx_packet_next)
7751 {
7752
7753 /* Copy data from next packet. */
7754 available_packet = available_packet -> nx_packet_next;
7755 }
7756 else
7757 #endif /* NX_DISABLE_PACKET_CHAIN */
7758 {
7759
7760 /* Release the packet that has been processed. */
7761 nx_packet_release(*packet_pptr);
7762
7763 /* Get a new packet and copy data from it. */
7764 status = _nx_web_http_server_packet_get(server_ptr, &available_packet);
7765
7766 /* Check the return status. */
7767 if (status != NX_SUCCESS)
7768 {
7769
7770 /* Error, return to caller. */
7771 return(NX_WEB_HTTP_TIMEOUT);
7772 }
7773
7774 /* Store the packet. */
7775 *packet_pptr = available_packet;
7776 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = available_packet;
7777
7778 /* Reset the offset. */
7779 multipart_ptr -> nx_web_http_server_multipart_available_offset = 0;
7780 }
7781
7782 ch = available_packet -> nx_packet_prepend_ptr;
7783 }
7784 else
7785 ch++;
7786
7787 }
7788
7789 /* Check whether two CRLFs are found. */
7790 if(crlf_match_count == 4)
7791 {
7792
7793 /* Set terminal 0. */
7794 if(entity_header_buffer)
7795 {
7796 if (index >= 4)
7797 {
7798 entity_header_buffer[index - 4] = 0;
7799 }
7800 else
7801 {
7802 entity_header_buffer[0] = 0;
7803 }
7804 }
7805 return NX_SUCCESS;
7806 }
7807 else
7808 return NX_WEB_HTTP_NOT_FOUND;
7809 #else
7810 NX_PARAMETER_NOT_USED(server_ptr);
7811 NX_PARAMETER_NOT_USED(packet_pptr);
7812 NX_PARAMETER_NOT_USED(entity_header_buffer);
7813 NX_PARAMETER_NOT_USED(buffer_size);
7814
7815 return NX_WEB_HTTP_ERROR;
7816 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
7817 }
7818
7819
7820 /**************************************************************************/
7821 /* */
7822 /* FUNCTION RELEASE */
7823 /* */
7824 /* _nxe_web_http_server_get_entity_content PORTABLE C */
7825 /* 6.1 */
7826 /* AUTHOR */
7827 /* */
7828 /* Yuxin Zhou, Microsoft Corporation */
7829 /* */
7830 /* DESCRIPTION */
7831 /* */
7832 /* This function checks error for getting the entity content. */
7833 /* */
7834 /* INPUT */
7835 /* */
7836 /* server_ptr Pointer to HTTP server */
7837 /* packet_pptr Pointer to packet */
7838 /* available_offset Return the offset */
7839 /* available_length Return the length */
7840 /* */
7841 /* OUTPUT */
7842 /* */
7843 /* status Completion status */
7844 /* */
7845 /* CALLS */
7846 /* */
7847 /* _nx_web_http_server_get_entity_content */
7848 /* */
7849 /* CALLED BY */
7850 /* */
7851 /* Application Code */
7852 /* */
7853 /* RELEASE HISTORY */
7854 /* */
7855 /* DATE NAME DESCRIPTION */
7856 /* */
7857 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7858 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7859 /* resulting in version 6.1 */
7860 /* */
7861 /**************************************************************************/
_nxe_web_http_server_get_entity_content(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,ULONG * available_offset,ULONG * available_length)7862 UINT _nxe_web_http_server_get_entity_content(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, ULONG *available_offset, ULONG *available_length)
7863 {
7864
7865 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
7866 /* Check for invalid input pointers. */
7867 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
7868 (packet_pptr == NX_NULL) || (available_offset == NX_NULL) || (available_length == NX_NULL))
7869 return(NX_PTR_ERROR);
7870
7871 /* Check whether boundary is found. */
7872 if(server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_boundary[0] == 0)
7873 return(NX_WEB_HTTP_ERROR);
7874
7875 return _nx_web_http_server_get_entity_content(server_ptr, packet_pptr, available_offset, available_length);
7876 #else
7877 NX_PARAMETER_NOT_USED(server_ptr);
7878 NX_PARAMETER_NOT_USED(packet_pptr);
7879 NX_PARAMETER_NOT_USED(available_offset);
7880 NX_PARAMETER_NOT_USED(available_length);
7881
7882 return NX_WEB_HTTP_ERROR;
7883 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
7884 }
7885
7886
7887 /**************************************************************************/
7888 /* */
7889 /* FUNCTION RELEASE */
7890 /* */
7891 /* _nx_web_http_server_get_entity_content PORTABLE C */
7892 /* 6.1 */
7893 /* AUTHOR */
7894 /* */
7895 /* Yuxin Zhou, Microsoft Corporation */
7896 /* */
7897 /* DESCRIPTION */
7898 /* */
7899 /* This function gets the entity content. */
7900 /* */
7901 /* INPUT */
7902 /* */
7903 /* server_ptr Pointer to HTTP server */
7904 /* packet_pptr Pointer to packet */
7905 /* available_offset Return the offset */
7906 /* available_length Return the length */
7907 /* */
7908 /* OUTPUT */
7909 /* */
7910 /* status Completion status */
7911 /* */
7912 /* CALLS */
7913 /* */
7914 /* _nx_web_http_server_boundary_find */
7915 /* */
7916 /* CALLED BY */
7917 /* */
7918 /* Application Code */
7919 /* */
7920 /* RELEASE HISTORY */
7921 /* */
7922 /* DATE NAME DESCRIPTION */
7923 /* */
7924 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7925 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7926 /* resulting in version 6.1 */
7927 /* */
7928 /**************************************************************************/
_nx_web_http_server_get_entity_content(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,ULONG * available_offset,ULONG * available_length)7929 UINT _nx_web_http_server_get_entity_content(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, ULONG *available_offset, ULONG *available_length)
7930 {
7931
7932 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
7933 UINT status;
7934
7935 /* Whether the boundary is found? */
7936 if(server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_boundary_find == NX_TRUE)
7937 return NX_WEB_HTTP_BOUNDARY_ALREADY_FOUND;
7938
7939 status = _nx_web_http_server_boundary_find(server_ptr, packet_pptr);
7940 if(status)
7941 return status;
7942
7943 /* Set the offset and length. */
7944 *available_offset = server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_available_offset;
7945 *available_length = server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_available_length;
7946
7947 return NX_SUCCESS;
7948 #else
7949 NX_PARAMETER_NOT_USED(server_ptr);
7950 NX_PARAMETER_NOT_USED(packet_pptr);
7951 NX_PARAMETER_NOT_USED(available_offset);
7952 NX_PARAMETER_NOT_USED(available_length);
7953
7954 return NX_WEB_HTTP_ERROR;
7955 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
7956 }
7957
7958
7959 #ifdef NX_WEB_HTTP_MULTIPART_ENABLE
7960 /**************************************************************************/
7961 /* */
7962 /* FUNCTION RELEASE */
7963 /* */
7964 /* _nx_web_http_server_boundary_find PORTABLE C */
7965 /* 6.1 */
7966 /* AUTHOR */
7967 /* */
7968 /* Yuxin Zhou, Microsoft Corporation */
7969 /* */
7970 /* DESCRIPTION */
7971 /* */
7972 /* This function finds boundary in packet even if it is chained. */
7973 /* */
7974 /* INPUT */
7975 /* */
7976 /* server_ptr Pointer to HTTP server */
7977 /* packet_pptr Pointer to packet */
7978 /* */
7979 /* OUTPUT */
7980 /* */
7981 /* status Completion status */
7982 /* */
7983 /* CALLS */
7984 /* */
7985 /* nx_packet_release */
7986 /* nx_tcp_socket_receive */
7987 /* _nx_web_http_server_match_string */
7988 /* _nx_utility_string_length_check */
7989 /* */
7990 /* CALLED BY */
7991 /* */
7992 /* _nx_web_http_server_get_entity_header */
7993 /* _nx_web_http_server_get_entity_content */
7994 /* */
7995 /* RELEASE HISTORY */
7996 /* */
7997 /* DATE NAME DESCRIPTION */
7998 /* */
7999 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8000 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8001 /* resulting in version 6.1 */
8002 /* */
8003 /**************************************************************************/
_nx_web_http_server_boundary_find(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr)8004 UINT _nx_web_http_server_boundary_find(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr)
8005 {
8006
8007 NX_WEB_HTTP_SERVER_MULTIPART *multipart_ptr;
8008 NX_PACKET *available_packet;
8009 UINT offset;
8010 ULONG match_count = 0;
8011 UCHAR *match_end_ptr;
8012 UINT boundary_length;
8013
8014 /* Get multipart context. */
8015 multipart_ptr = &server_ptr -> nx_web_http_server_multipart;
8016
8017 /* Is boundary already found? */
8018 if(multipart_ptr -> nx_web_http_server_multipart_boundary_find == NX_TRUE)
8019 {
8020
8021 /* Yes. Update the packet and offset. */
8022 if(multipart_ptr -> nx_web_http_server_multipart_next_packet != NX_NULL)
8023 {
8024 nx_packet_release(*packet_pptr);
8025 *packet_pptr = multipart_ptr -> nx_web_http_server_multipart_next_packet;
8026 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = multipart_ptr -> nx_web_http_server_multipart_next_packet;
8027 }
8028
8029 multipart_ptr -> nx_web_http_server_multipart_available_offset = multipart_ptr -> nx_web_http_server_multipart_next_available_offset;
8030
8031 /* Reset next packet and available offset. */
8032 multipart_ptr -> nx_web_http_server_multipart_next_packet = NX_NULL;
8033 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = 0;
8034
8035 /* Reset boundary find. */
8036 multipart_ptr -> nx_web_http_server_multipart_boundary_find = NX_FALSE;
8037
8038 return NX_SUCCESS;
8039 }
8040
8041 /* Is the boundary in the next packet? */
8042 if(multipart_ptr -> nx_web_http_server_multipart_next_packet)
8043 {
8044
8045 /* Yes, we're done with this packet. */
8046 nx_packet_release(*packet_pptr);
8047
8048 /* Update the packet and multipart offset. */
8049 *packet_pptr = multipart_ptr -> nx_web_http_server_multipart_next_packet;
8050 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = multipart_ptr -> nx_web_http_server_multipart_next_packet;
8051 multipart_ptr -> nx_web_http_server_multipart_available_offset = 0;
8052 }
8053 else if(multipart_ptr -> nx_web_http_server_multipart_next_available_offset)
8054 {
8055
8056 /* Find boundary in this packet. */
8057 /* Update the offset. */
8058 multipart_ptr -> nx_web_http_server_multipart_available_offset = multipart_ptr -> nx_web_http_server_multipart_next_available_offset;
8059 }
8060 else
8061 {
8062
8063 /* Find boundary from this packet. */
8064 /* Initialize the offset. */
8065 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = multipart_ptr -> nx_web_http_server_multipart_available_offset;
8066 }
8067
8068 /* Reset next packet. */
8069 multipart_ptr -> nx_web_http_server_multipart_next_packet = NX_NULL;
8070
8071 /* Reset boundary find. */
8072 multipart_ptr -> nx_web_http_server_multipart_boundary_find = NX_FALSE;
8073
8074
8075 /* Get offset of available data in the packet. */
8076 offset = multipart_ptr -> nx_web_http_server_multipart_available_offset;
8077
8078 /* Skip data that are not header. */
8079 available_packet = *packet_pptr;
8080
8081 if(offset >= available_packet -> nx_packet_length)
8082 {
8083
8084 /* Release the packet that has been processed. */
8085 nx_packet_release(*packet_pptr);
8086
8087 /* All data has been processed. Get a new packet. */
8088 if(_nx_web_http_server_packet_get(server_ptr, &available_packet) != NX_SUCCESS)
8089 {
8090
8091 /* Error, return to caller. */
8092 return(NX_WEB_HTTP_TIMEOUT);
8093 }
8094
8095 /* Store the packet. */
8096 *packet_pptr = available_packet;
8097 server_ptr -> nx_web_http_server_multipart.nx_web_http_server_multipart_last_packet = available_packet;
8098
8099 /* Reset the offset. */
8100 multipart_ptr -> nx_web_http_server_multipart_available_offset = 0;
8101 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = 0;
8102 offset = 0;
8103 }
8104 else
8105 {
8106 #ifndef NX_DISABLE_PACKET_CHAIN
8107 while((UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr) <= offset)
8108 {
8109 offset -= (UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr);
8110
8111 /* Get next packet. */
8112 available_packet = available_packet -> nx_packet_next;
8113 }
8114 #endif /* NX_DISABLE_PACKET_CHAIN */
8115 }
8116
8117 /* Check boundary length. */
8118 if (_nx_utility_string_length_check((CHAR *)multipart_ptr -> nx_web_http_server_multipart_boundary, &boundary_length, NX_WEB_HTTP_MAX_HEADER_FIELD))
8119 {
8120 return(NX_WEB_HTTP_ERROR);
8121 }
8122
8123 /* Look for the boundary string in the (next) packet. */
8124 while(_nx_web_http_server_match_string(available_packet -> nx_packet_prepend_ptr + offset,
8125 available_packet -> nx_packet_append_ptr,
8126 multipart_ptr -> nx_web_http_server_multipart_boundary,
8127 boundary_length,
8128 &match_count, &match_end_ptr) != NX_SUCCESS)
8129 {
8130
8131 /* Match string in the next packet. */
8132 #ifndef NX_DISABLE_PACKET_CHAIN
8133 if(available_packet -> nx_packet_next)
8134 {
8135 multipart_ptr -> nx_web_http_server_multipart_next_available_offset += (UINT)((UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr) - offset);
8136 available_packet = available_packet -> nx_packet_next;
8137 offset = 0;
8138 }
8139 else
8140 #endif /* NX_DISABLE_PACKET_CHAIN */
8141 break;
8142 }
8143
8144 /* Is boundary matched? */
8145 if(match_end_ptr)
8146 {
8147
8148 /* Yes. Found a match. */
8149 multipart_ptr -> nx_web_http_server_multipart_next_available_offset += (UINT)((UINT)(match_end_ptr - available_packet -> nx_packet_prepend_ptr) - offset);
8150 multipart_ptr -> nx_web_http_server_multipart_available_length = multipart_ptr -> nx_web_http_server_multipart_next_available_offset - multipart_ptr -> nx_web_http_server_multipart_available_offset - match_count;
8151 multipart_ptr -> nx_web_http_server_multipart_boundary_find = NX_TRUE;
8152
8153 }
8154 else if(match_count)
8155 {
8156
8157 /* Set the available length to all remaining data. */
8158 multipart_ptr -> nx_web_http_server_multipart_available_length = (*packet_pptr) -> nx_packet_length - multipart_ptr -> nx_web_http_server_multipart_available_offset;
8159
8160 /* Partial match. Get another packet. */
8161 if(_nx_web_http_server_packet_get(server_ptr, &available_packet) != NX_SUCCESS)
8162 {
8163
8164 /* Error, return to caller. */
8165 return(NX_WEB_HTTP_TIMEOUT);
8166 }
8167
8168 /* Match the boundary again. */
8169 if(_nx_web_http_server_match_string(available_packet -> nx_packet_prepend_ptr,
8170 available_packet -> nx_packet_append_ptr,
8171 multipart_ptr -> nx_web_http_server_multipart_boundary,
8172 boundary_length,
8173 &match_count, &match_end_ptr) == NX_SUCCESS)
8174 {
8175
8176 /* Yes. Find a match. */
8177 if((ULONG)(match_end_ptr - available_packet -> nx_packet_prepend_ptr) < match_count)
8178 {
8179
8180 /* The boundary is between two packets. */
8181 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = (UINT)(match_end_ptr - available_packet -> nx_packet_prepend_ptr);
8182 multipart_ptr -> nx_web_http_server_multipart_available_length -= boundary_length - multipart_ptr -> nx_web_http_server_multipart_next_available_offset;
8183 multipart_ptr -> nx_web_http_server_multipart_boundary_find = NX_TRUE;
8184 }
8185 else
8186 {
8187
8188 /* The boundary is in the next packet. */
8189 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = 0;
8190 }
8191 }
8192 else
8193 {
8194
8195 /* The boundary is not found. */
8196 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = 0;
8197 }
8198
8199 /* Store the packet. */
8200 multipart_ptr -> nx_web_http_server_multipart_next_packet = available_packet;
8201
8202 }
8203 else
8204 {
8205
8206 /* Set the available length to all remaining data. */
8207 multipart_ptr -> nx_web_http_server_multipart_available_length = (*packet_pptr) -> nx_packet_length - multipart_ptr -> nx_web_http_server_multipart_available_offset;
8208 multipart_ptr -> nx_web_http_server_multipart_next_available_offset = (*packet_pptr) -> nx_packet_length;
8209 }
8210
8211 return NX_SUCCESS;
8212 }
8213 #endif /* NX_WEB_HTTP_MULTIPART_ENABLE */
8214
8215
8216 /**************************************************************************/
8217 /* */
8218 /* FUNCTION RELEASE */
8219 /* */
8220 /* _nx_web_http_server_match_string PORTABLE C */
8221 /* 6.1 */
8222 /* AUTHOR */
8223 /* */
8224 /* Yuxin Zhou, Microsoft Corporation */
8225 /* */
8226 /* DESCRIPTION */
8227 /* */
8228 /* This function compares a target string in specified memory area. */
8229 /* */
8230 /* INPUT */
8231 /* */
8232 /* src_start Pointer to start of source */
8233 /* src_end Pointer to end of source */
8234 /* target Pointer to target */
8235 /* target_length Length to target */
8236 /* match_count Return the match count */
8237 /* match_end_ptr Return the end match position */
8238 /* */
8239 /* OUTPUT */
8240 /* */
8241 /* status Completion status */
8242 /* */
8243 /* CALLS */
8244 /* */
8245 /* memcmp Compare memory data */
8246 /* */
8247 /* CALLED BY */
8248 /* */
8249 /* _nx_web_http_server_boundary_find */
8250 /* */
8251 /* RELEASE HISTORY */
8252 /* */
8253 /* DATE NAME DESCRIPTION */
8254 /* */
8255 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8256 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8257 /* resulting in version 6.1 */
8258 /* */
8259 /**************************************************************************/
_nx_web_http_server_match_string(UCHAR * src_start,UCHAR * src_end,UCHAR * target,ULONG target_length,ULONG * match_count,UCHAR ** match_end_ptr)8260 UINT _nx_web_http_server_match_string(UCHAR *src_start, UCHAR *src_end, UCHAR *target, ULONG target_length, ULONG *match_count, UCHAR **match_end_ptr)
8261 {
8262
8263 UCHAR *ch;
8264 ULONG pre_match = *match_count;
8265 ULONG remain_match;
8266
8267 /* Initialize. */
8268 *match_end_ptr = NX_NULL;
8269
8270 /* Process part match. */
8271 while(pre_match)
8272 {
8273
8274 /* Compare pre-match. */
8275 if(memcmp(target, target + (*match_count - pre_match), pre_match) == 0)
8276 {
8277
8278 /* Calculate the remain match. */
8279 remain_match = target_length - pre_match;
8280
8281 /* The pre-match is the same. */
8282 if((ULONG)(src_end - src_start) < remain_match)
8283 remain_match = (ULONG)(src_end - src_start);
8284
8285 if(memcmp(target + pre_match, src_start, remain_match) == 0)
8286 {
8287
8288 /* Remain part matches. */
8289 *match_count = pre_match + remain_match;
8290
8291 if(*match_count < target_length)
8292 {
8293
8294 /* Part match. */
8295 return NX_WEB_HTTP_NOT_FOUND;
8296 }
8297
8298 /* Full match. */
8299 *match_end_ptr = src_start + remain_match;
8300 return NX_SUCCESS;
8301 }
8302 }
8303
8304 pre_match--;
8305 }
8306
8307 ch = src_start;
8308
8309 /* Perform full match. */
8310 *match_count = target_length;
8311 while(ch + *match_count <= src_end)
8312 {
8313 if(memcmp(ch, target, *match_count) == 0)
8314 {
8315
8316 /* Find a match. */
8317 *match_end_ptr = ch + *match_count;
8318 return NX_SUCCESS;
8319 }
8320
8321 ch++;
8322 }
8323
8324 /* Perform part match. */
8325 for(*match_count = target_length - 1; *match_count > 0; *match_count = *match_count - 1)
8326 {
8327 if(ch + *match_count <= src_end)
8328 {
8329 if(memcmp(ch, target, *match_count) == 0)
8330 {
8331
8332 /* Find a match. */
8333 return NX_WEB_HTTP_NOT_FOUND;
8334 }
8335
8336 ch++;
8337 }
8338 }
8339
8340 return NX_WEB_HTTP_NOT_FOUND;
8341 }
8342
8343
8344 /**************************************************************************/
8345 /* */
8346 /* FUNCTION RELEASE */
8347 /* */
8348 /* _nx_web_http_server_field_value_get PORTABLE C */
8349 /* 6.1 */
8350 /* AUTHOR */
8351 /* */
8352 /* Yuxin Zhou, Microsoft Corporation */
8353 /* */
8354 /* DESCRIPTION */
8355 /* */
8356 /* This function gets field value by field name from HTTP header. */
8357 /* */
8358 /* INPUT */
8359 /* */
8360 /* packet_ptr Pointer to packet */
8361 /* field_name Name of field in header */
8362 /* name_length Length of name field */
8363 /* field_value Return of field value */
8364 /* field_value_size Size of field value */
8365 /* */
8366 /* OUTPUT */
8367 /* */
8368 /* status Completion status */
8369 /* */
8370 /* CALLS */
8371 /* */
8372 /* _nx_web_http_server_memicmp Compare ignore case */
8373 /* */
8374 /* CALLED BY */
8375 /* */
8376 /* _nx_web_http_server_get_process */
8377 /* _nx_web_http_server_get_entity_header */
8378 /* */
8379 /* RELEASE HISTORY */
8380 /* */
8381 /* DATE NAME DESCRIPTION */
8382 /* */
8383 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8384 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8385 /* resulting in version 6.1 */
8386 /* */
8387 /**************************************************************************/
_nx_web_http_server_field_value_get(NX_PACKET * packet_ptr,UCHAR * field_name,ULONG name_length,UCHAR * field_value,ULONG field_value_size)8388 UINT _nx_web_http_server_field_value_get(NX_PACKET *packet_ptr, UCHAR *field_name, ULONG name_length, UCHAR *field_value, ULONG field_value_size)
8389 {
8390
8391 UCHAR *ch;
8392 UINT index;
8393
8394
8395 /* Initialize. */
8396 ch = packet_ptr -> nx_packet_prepend_ptr;
8397
8398 /* Loop to find field name. */
8399 while(ch + name_length < packet_ptr -> nx_packet_append_ptr)
8400 {
8401 if(_nx_web_http_server_memicmp(ch, name_length, field_name, name_length) == NX_SUCCESS)
8402 {
8403
8404 /* Field name found. */
8405 break;
8406 }
8407
8408 /* Move the pointer up to the next character. */
8409 ch++;
8410 }
8411
8412 /* Skip field name and ':'. */
8413 ch += name_length + 1;
8414
8415 /* Is field name found? */
8416 if(ch >= packet_ptr -> nx_packet_append_ptr)
8417 return NX_WEB_HTTP_NOT_FOUND;
8418
8419 /* Skip white spaces. */
8420 while(*ch == ' ')
8421 {
8422 if(ch >= packet_ptr -> nx_packet_append_ptr)
8423 return NX_WEB_HTTP_NOT_FOUND;
8424
8425 /* Get next character. */
8426 ch++;
8427 }
8428
8429 /* Copy field value. */
8430 index = 0;
8431 while(index < field_value_size)
8432 {
8433
8434 /* Whether the end of line CRLF is not found? */
8435 if(ch + 2 > packet_ptr -> nx_packet_append_ptr)
8436 return NX_WEB_HTTP_NOT_FOUND;
8437
8438 /* Compare CRLF. */
8439 if((*ch == 13) && (*(ch + 1) == 10))
8440 break;
8441
8442 /* Copy data. */
8443 field_value[index++] = *ch++;
8444 }
8445
8446 /* Buffer overflow? */
8447 if(index == field_value_size)
8448 return NX_WEB_HTTP_NOT_FOUND;
8449
8450 /* Trim white spaces. */
8451 while((index > 0) && (field_value[index - 1] == ' '))
8452 index--;
8453
8454 /* Append terminal 0. */
8455 field_value[index] = 0;
8456
8457
8458 return NX_SUCCESS;
8459 }
8460
8461
8462 /**************************************************************************/
8463 /* */
8464 /* FUNCTION RELEASE */
8465 /* */
8466 /* _nx_web_http_server_memicmp PORTABLE C */
8467 /* 6.1 */
8468 /* AUTHOR */
8469 /* */
8470 /* Yuxin Zhou, Microsoft Corporation */
8471 /* */
8472 /* DESCRIPTION */
8473 /* */
8474 /* This function compares two pieces of memory case insensitive. */
8475 /* */
8476 /* INPUT */
8477 /* */
8478 /* src Pointer to source */
8479 /* src_length Length of source */
8480 /* dest Pointer to destination */
8481 /* dest_length Length of destination */
8482 /* */
8483 /* OUTPUT */
8484 /* */
8485 /* status Completion status */
8486 /* */
8487 /* CALLS */
8488 /* */
8489 /* */
8490 /* CALLED BY */
8491 /* */
8492 /* _nx_web_http_server_get_entity_header */
8493 /* _nx_web_http_server_field_value_get */
8494 /* */
8495 /* RELEASE HISTORY */
8496 /* */
8497 /* DATE NAME DESCRIPTION */
8498 /* */
8499 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8500 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8501 /* resulting in version 6.1 */
8502 /* */
8503 /**************************************************************************/
_nx_web_http_server_memicmp(UCHAR * src,ULONG src_length,UCHAR * dest,ULONG dest_length)8504 UINT _nx_web_http_server_memicmp(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length)
8505 {
8506 UCHAR ch;
8507
8508 /* Compare the length. */
8509 if(src_length != dest_length)
8510 return NX_WEB_HTTP_FAILED;
8511
8512 while(src_length)
8513 {
8514
8515 /* Is src lowercase? */
8516 if((*src >= 'a') && (*src <= 'z'))
8517 ch = (UCHAR)(*src - 'a' + 'A');
8518
8519 /* Is src uppercase? */
8520 else if((*src >= 'A') && (*src <= 'Z'))
8521 ch = (UCHAR)(*src - 'A' + 'a');
8522 else
8523 ch = *src;
8524
8525 /* Compare case insensitive. */
8526 if((*src != *dest) && (ch != *dest))
8527 return NX_WEB_HTTP_FAILED;
8528
8529 /* Pickup next character. */
8530 src_length--;
8531 src++;
8532 dest++;
8533 }
8534
8535 return NX_SUCCESS;
8536 }
8537
8538
8539 /**************************************************************************/
8540 /* */
8541 /* FUNCTION RELEASE */
8542 /* */
8543 /* _nx_web_http_server_generate_response_header PORTABLE C */
8544 /* 6.1.8 */
8545 /* AUTHOR */
8546 /* */
8547 /* Yuxin Zhou, Microsoft Corporation */
8548 /* */
8549 /* DESCRIPTION */
8550 /* */
8551 /* This function generates HTTP response header. */
8552 /* */
8553 /* INPUT */
8554 /* */
8555 /* server_ptr Pointer to HTTP server */
8556 /* packet_pptr Pointer to packet */
8557 /* status_code Status-code and reason-phrase */
8558 /* status_code_length Length of status-code */
8559 /* content_length Length of content */
8560 /* content_type Type of content */
8561 /* content_type_length Length of content type */
8562 /* additional_header Other HTTP headers */
8563 /* additional_header_length Length of other HTTP headers */
8564 /* */
8565 /* OUTPUT */
8566 /* */
8567 /* status Completion status */
8568 /* */
8569 /* CALLS */
8570 /* */
8571 /* _nx_web_http_server_response_packet_allocate */
8572 /* Allocate response packet */
8573 /* nx_packet_data_append Append packet data */
8574 /* memcmp Compare string */
8575 /* _nx_utility_uint_to_string Convert number to ASCII */
8576 /* _nx_web_http_server_date_to_string Convert data to string */
8577 /* nx_packet_release Release packet */
8578 /* */
8579 /* CALLED BY */
8580 /* */
8581 /* _nx_web_http_server_get_process */
8582 /* _nx_web_http_server_put_process */
8583 /* _nx_web_http_server_delete_process */
8584 /* _nx_web_http_server_response_send */
8585 /* _nx_web_http_server_callback_generate_response_header */
8586 /* */
8587 /* RELEASE HISTORY */
8588 /* */
8589 /* DATE NAME DESCRIPTION */
8590 /* */
8591 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8592 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8593 /* resulting in version 6.1 */
8594 /* 08-02-2021 Yuxin Zhou Modified comment(s), */
8595 /* improved the logic of */
8596 /* converting number to string,*/
8597 /* resulting in version 6.1.8 */
8598 /* */
8599 /**************************************************************************/
_nx_web_http_server_generate_response_header(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT status_code_length,UINT content_length,CHAR * content_type,UINT content_type_length,CHAR * additional_header,UINT additional_header_length)8600 UINT _nx_web_http_server_generate_response_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr,
8601 CHAR *status_code, UINT status_code_length,
8602 UINT content_length, CHAR *content_type,
8603 UINT content_type_length, CHAR* additional_header,
8604 UINT additional_header_length)
8605 {
8606
8607 UINT status;
8608 UINT temp;
8609 CHAR temp_string[30];
8610 CHAR crlf[2] = {13,10};
8611 NX_PACKET *packet_ptr;
8612 CHAR status_code_ok;
8613 CHAR status_code_not_modified;
8614
8615
8616 /* Allocate a packet for sending the response back. */
8617 status = _nx_web_http_server_response_packet_allocate(server_ptr, packet_pptr, NX_WAIT_FOREVER);
8618
8619 /* Determine if an error occurred in the packet allocation. */
8620 if(status != NX_SUCCESS)
8621 {
8622
8623 /* Indicate an allocation error occurred. */
8624 server_ptr -> nx_web_http_server_allocation_errors++;
8625
8626 /* Just return. */
8627 return status;
8628 }
8629 else
8630 packet_ptr = *packet_pptr;
8631
8632 /* Check status code. */
8633 if(memcmp(status_code, NX_WEB_HTTP_STATUS_OK, sizeof(NX_WEB_HTTP_STATUS_OK)) == 0)
8634 status_code_ok = NX_TRUE;
8635 else
8636 status_code_ok = NX_FALSE;
8637
8638 if(memcmp(status_code, NX_WEB_HTTP_STATUS_NOT_MODIFIED, sizeof(NX_WEB_HTTP_STATUS_NOT_MODIFIED)) == 0)
8639 status_code_not_modified = NX_TRUE;
8640 else
8641 status_code_not_modified = NX_FALSE;
8642
8643 /* Insert the status line. */
8644 /* Place HTTP-Version. */
8645 status = nx_packet_data_append(packet_ptr, NX_WEB_HTTP_VERSION, sizeof(NX_WEB_HTTP_VERSION) - 1, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8646
8647 /* Insert space. */
8648 status += nx_packet_data_append(packet_ptr, " ", 1, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8649
8650 status += nx_packet_data_append(packet_ptr, status_code, status_code_length, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8651
8652 /* Place the <cr,lf> into the buffer. */
8653 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8654
8655 /* Determine if there is content_type. */
8656 if(content_type)
8657 {
8658
8659 /* Insert the content type. */
8660 status += nx_packet_data_append(packet_ptr, "Content-Type: ", 14, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8661 status += nx_packet_data_append(packet_ptr, content_type, content_type_length, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8662
8663 /* Place the <cr,lf> into the buffer. */
8664 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8665 }
8666
8667 #ifndef NX_WEB_HTTP_SERVER_OMIT_CONTENT_LENGTH
8668 /* Determine if there is content_length. */
8669 if(content_length || (status_code_not_modified == NX_TRUE))
8670 {
8671 #ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
8672
8673 /* Place the "Connection" field in the header. */
8674 if(server_ptr -> nx_web_http_server_keepalive == NX_TRUE)
8675 {
8676
8677 /* Keepalive. */
8678 status += nx_packet_data_append(packet_ptr, "Connection: keep-alive", 22,
8679 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8680 }
8681 else
8682 #endif /* NX_WEB_HTTP_KEEPALIVE_DISABLE */
8683 {
8684
8685 /* Close. */
8686 status += nx_packet_data_append(packet_ptr, "Connection: Close", 17,
8687 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8688 }
8689
8690 /* Place the <cr,lf> into the buffer. */
8691 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8692
8693 if(content_length)
8694 {
8695
8696 /* Convert the content_length to ASCII representation. */
8697 temp = _nx_utility_uint_to_string(content_length, 10, temp_string, sizeof(temp_string));
8698
8699 /* Place the "Content-Length" field in the header. */
8700 status += nx_packet_data_append(packet_ptr, "Content-Length: ", 16,
8701 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8702 status += nx_packet_data_append(packet_ptr, temp_string, temp,
8703 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8704
8705 /* Place the <cr,lf> into the buffer. */
8706 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8707 }
8708
8709 }
8710 else
8711 #endif /* NX_WEB_HTTP_SERVER_OMIT_CONTENT_LENGTH */
8712 {
8713
8714 /* Place the "Connection" field in the header. */
8715
8716 /* Force close the connection since there's no content-length. */
8717 status += nx_packet_data_append(packet_ptr, "Connection: Close", 17,
8718 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8719
8720 #ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
8721 server_ptr -> nx_web_http_server_keepalive = NX_FALSE;
8722 #endif /* NX_WEB_HTTP_KEEPALIVE_DISABLE */
8723
8724 /* Place the <cr,lf> into the buffer. */
8725 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8726 }
8727
8728 /* Insert Date header if callback function is set. */
8729 if(server_ptr -> nx_web_http_server_gmt_get)
8730 {
8731 NX_WEB_HTTP_SERVER_DATE date;
8732
8733 /* Get current date. */
8734 server_ptr -> nx_web_http_server_gmt_get(&date);
8735
8736 /* Convert date to string. */
8737 temp = _nx_web_http_server_date_to_string(&date, temp_string);
8738
8739 /* Place the "Date" field in the header. */
8740 status += nx_packet_data_append(packet_ptr, "Date: ", 6,
8741 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8742
8743 /* Insert date. */
8744 status += nx_packet_data_append(packet_ptr, temp_string, temp, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8745
8746 /* Place the <cr,lf> into the buffer. */
8747 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8748
8749 /* Set Cache Control if callback function is set. */
8750 if((server_ptr -> nx_web_http_server_cache_info_get) &&
8751 ((status_code_ok == NX_TRUE) || (status_code_not_modified == NX_TRUE)) &&
8752 (server_ptr -> nx_web_http_server_request_type == NX_WEB_HTTP_SERVER_GET_REQUEST))
8753 {
8754 UINT max_age;
8755
8756 /* Get cache infomation. */
8757 if(server_ptr -> nx_web_http_server_cache_info_get(server_ptr -> nx_web_http_server_request_resource, &max_age, &date) == NX_TRUE)
8758 {
8759
8760 /* Place "Cache-control" header. */
8761 status += nx_packet_data_append(packet_ptr, "Cache-Control: max-age=", 23,
8762 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8763
8764 /* Convert the max-age to ASCII representation. */
8765 temp = _nx_utility_uint_to_string(max_age, 10, temp_string, sizeof(temp_string));
8766 status += nx_packet_data_append(packet_ptr, temp_string, temp,
8767 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8768
8769 /* Place the <cr,lf> into the buffer. */
8770 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8771
8772 if(status_code_ok == NX_TRUE)
8773 {
8774
8775 /* Convert date to string. */
8776 temp = _nx_web_http_server_date_to_string(&date, temp_string);
8777
8778 /* Place the "Last-Modified" field in the header. */
8779 status += nx_packet_data_append(packet_ptr, "Last-Modified: ", 15,
8780 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8781
8782 /* Insert date. */
8783 status += nx_packet_data_append(packet_ptr, temp_string, temp, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8784
8785 /* Place the <cr,lf> into the buffer. */
8786 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8787 }
8788 }
8789 }
8790 }
8791
8792 /* Insert additional header. */
8793 if(additional_header)
8794 {
8795 status += nx_packet_data_append(packet_ptr, additional_header, additional_header_length,
8796 server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8797 }
8798
8799 /* Place the <cr,lf> into the buffer. */
8800 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8801
8802 if (status != NX_SUCCESS)
8803 {
8804
8805 /* Just release the packet. */
8806 nx_packet_release(packet_ptr);
8807 }
8808
8809 return status;
8810 }
8811
8812 /**************************************************************************/
8813 /* */
8814 /* FUNCTION RELEASE */
8815 /* */
8816 /* _nx_web_http_server_request_read PORTABLE C */
8817 /* 6.1 */
8818 /* AUTHOR */
8819 /* */
8820 /* Yuxin Zhou, Microsoft Corporation */
8821 /* */
8822 /* DESCRIPTION */
8823 /* */
8824 /* This function gets the next data in byte. */
8825 /* */
8826 /* INPUT */
8827 /* */
8828 /* Server_ptr Pointer to HTTP server */
8829 /* data Returned data */
8830 /* wait_option Suspension option */
8831 /* current_packet_pptr Pointer to the packet being */
8832 /* processed */
8833 /* current_data_ptr Pointer to the data will be */
8834 /* processed */
8835 /* */
8836 /* OUTPUT */
8837 /* */
8838 /* status Completion status */
8839 /* */
8840 /* CALLS */
8841 /* */
8842 /* _nx_web_http_server_receive Receive another packet */
8843 /* */
8844 /* CALLED BY */
8845 /* */
8846 /* _nx_web_http_server_request_byte_expect */
8847 /* Checks next byte is expected */
8848 /* _nx_web_http_server_chunked_size_get Gets chunk size of request */
8849 /* packet chunk */
8850 /* */
8851 /* RELEASE HISTORY */
8852 /* */
8853 /* DATE NAME DESCRIPTION */
8854 /* */
8855 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8856 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8857 /* resulting in version 6.1 */
8858 /* */
8859 /**************************************************************************/
_nx_web_http_server_request_read(NX_WEB_HTTP_SERVER * server_ptr,UCHAR * data,ULONG wait_option,NX_PACKET ** current_packet_pptr,UCHAR ** current_data_pptr)8860 UINT _nx_web_http_server_request_read(NX_WEB_HTTP_SERVER *server_ptr, UCHAR *data, ULONG wait_option,
8861 NX_PACKET **current_packet_pptr, UCHAR **current_data_pptr)
8862 {
8863 UINT status;
8864
8865 /* If there is no remaining data. */
8866 while (server_ptr -> nx_web_http_server_chunked_request_remaining_size == 0)
8867 {
8868
8869 /* Release the previous received packet. */
8870 if (server_ptr -> nx_web_http_server_request_packet)
8871 {
8872 nx_packet_release(server_ptr -> nx_web_http_server_request_packet);
8873 server_ptr -> nx_web_http_server_request_packet = NX_NULL;
8874 }
8875
8876 /* Receive another packet. */
8877 status = _nx_web_http_server_receive(server_ptr, &(server_ptr -> nx_web_http_server_request_packet), wait_option);
8878 if (status)
8879 {
8880 return(status);
8881 }
8882
8883 /* Update the packet pointer, data pointer and remaining size. */
8884 (*current_packet_pptr) = server_ptr -> nx_web_http_server_request_packet;
8885 (*current_data_pptr) = server_ptr -> nx_web_http_server_request_packet -> nx_packet_prepend_ptr;
8886 server_ptr -> nx_web_http_server_chunked_request_remaining_size = server_ptr -> nx_web_http_server_request_packet -> nx_packet_length;
8887 }
8888
8889 /* Process the packet chain. */
8890 if ((*current_data_pptr) == (*current_packet_pptr) -> nx_packet_append_ptr)
8891 {
8892 #ifndef NX_DISABLE_PACKET_CHAIN
8893 if ((*current_packet_pptr) -> nx_packet_next == NX_NULL)
8894 {
8895 return(NX_INVALID_PACKET);
8896 }
8897
8898 (*current_packet_pptr) = (*current_packet_pptr) -> nx_packet_next;
8899 (*current_data_pptr) = (*current_packet_pptr) -> nx_packet_prepend_ptr;
8900
8901 /* Release the processed packet in the packet chain. */
8902 if (server_ptr -> nx_web_http_server_request_packet)
8903 {
8904 server_ptr -> nx_web_http_server_request_packet -> nx_packet_next = NX_NULL;
8905 nx_packet_release(server_ptr -> nx_web_http_server_request_packet);
8906 server_ptr -> nx_web_http_server_request_packet = (*current_packet_pptr);
8907 }
8908 #else
8909 return(NX_INVALID_PACKET);
8910 #endif /* NX_DISABLE_PACKET_CHAIN */
8911 }
8912
8913 /* Set the returned data. */
8914 *data = *(*current_data_pptr);
8915
8916 /* Update the data pointer and remaining size. */
8917 (*current_data_pptr)++;
8918 server_ptr -> nx_web_http_server_chunked_request_remaining_size--;
8919
8920 return(NX_SUCCESS);
8921 }
8922
8923 /**************************************************************************/
8924 /* */
8925 /* FUNCTION RELEASE */
8926 /* */
8927 /* _nx_web_http_server_request_byte_expect PORTABLE C */
8928 /* 6.1 */
8929 /* AUTHOR */
8930 /* */
8931 /* Yuxin Zhou, Microsoft Corporation */
8932 /* */
8933 /* DESCRIPTION */
8934 /* */
8935 /* This function checks if next byte is the expected data. */
8936 /* */
8937 /* INPUT */
8938 /* */
8939 /* server_ptr Pointer to HTTP server */
8940 /* data Expected data */
8941 /* wait_option Suspension option */
8942 /* current_packet_pptr Pointer to the packet being */
8943 /* processed */
8944 /* current_data_ptr Pointer to the data will be */
8945 /* processed */
8946 /* */
8947 /* OUTPUT */
8948 /* */
8949 /* status Compare result */
8950 /* */
8951 /* CALLS */
8952 /* */
8953 /* _nx_web_http_server_request_read Get next data */
8954 /* */
8955 /* CALLED BY */
8956 /* */
8957 /* _nx_web_http_server_chunked_size_get Gets chunk size of request */
8958 /* _nx_web_http_server_request_chunked_get */
8959 /* Get chunk data from request */
8960 /* */
8961 /* RELEASE HISTORY */
8962 /* */
8963 /* DATE NAME DESCRIPTION */
8964 /* */
8965 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8966 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8967 /* resulting in version 6.1 */
8968 /* */
8969 /**************************************************************************/
_nx_web_http_server_request_byte_expect(NX_WEB_HTTP_SERVER * server_ptr,UCHAR data,ULONG wait_option,NX_PACKET ** current_packet_pptr,UCHAR ** current_data_pptr)8970 UINT _nx_web_http_server_request_byte_expect(NX_WEB_HTTP_SERVER *server_ptr, UCHAR data, ULONG wait_option,
8971 NX_PACKET **current_packet_pptr, UCHAR **current_data_pptr)
8972 {
8973 UINT status;
8974 UCHAR tmp;
8975
8976 /* Get next data. */
8977 status = _nx_web_http_server_request_read(server_ptr, &tmp, wait_option, current_packet_pptr, current_data_pptr);
8978
8979 if (status)
8980 {
8981 return(status);
8982 }
8983
8984 /* Return the compare result. */
8985 if (tmp != data)
8986 {
8987 return(NX_NOT_FOUND);
8988 }
8989
8990 return(NX_SUCCESS);
8991 }
8992
8993 /**************************************************************************/
8994 /* */
8995 /* FUNCTION RELEASE */
8996 /* */
8997 /* _nx_web_http_server_chunked_size_get PORTABLE C */
8998 /* 6.1 */
8999 /* AUTHOR */
9000 /* */
9001 /* Yuxin Zhou, Microsoft Corporation */
9002 /* */
9003 /* DESCRIPTION */
9004 /* */
9005 /* This function gets the chunk size of the request packet chunk. */
9006 /* */
9007 /* */
9008 /* INPUT */
9009 /* */
9010 /* server_ptr Pointer to HTTP server */
9011 /* chunk_size Returned chunk size */
9012 /* wait_option Suspension option */
9013 /* current_packet_pptr Pointer to the packet being */
9014 /* processed */
9015 /* current_data_ptr Pointer to the data will be */
9016 /* processed */
9017 /* */
9018 /* OUTPUT */
9019 /* */
9020 /* status Completion status */
9021 /* */
9022 /* CALLS */
9023 /* */
9024 /* _nx_web_http_server_chunked_size_get Get chunk size */
9025 /* _nx_web_http_server_request_byte_expect */
9026 /* Check if next byte is expected*/
9027 /* nx_packet_release Release packet */
9028 /* nx_packet_append Append packet data */
9029 /* */
9030 /* CALLED BY */
9031 /* */
9032 /* Application Code */
9033 /* */
9034 /* RELEASE HISTORY */
9035 /* */
9036 /* DATE NAME DESCRIPTION */
9037 /* */
9038 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9039 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9040 /* resulting in version 6.1 */
9041 /* */
9042 /**************************************************************************/
_nx_web_http_server_chunked_size_get(NX_WEB_HTTP_SERVER * server_ptr,UINT * chunk_size,ULONG wait_option,NX_PACKET ** current_packet_pptr,UCHAR ** current_data_pptr)9043 UINT _nx_web_http_server_chunked_size_get(NX_WEB_HTTP_SERVER *server_ptr, UINT *chunk_size, ULONG wait_option,
9044 NX_PACKET **current_packet_pptr, UCHAR **current_data_pptr)
9045 {
9046 UINT status;
9047 UINT size = 0;
9048 UCHAR tmp;
9049 UINT chunk_extension = 0;
9050
9051 if (server_ptr -> nx_web_http_server_actual_bytes_received < server_ptr -> nx_web_http_server_expect_receive_bytes)
9052 {
9053
9054 /* If there are bytes need to receive, set the size need to receive as chunk size. */
9055 *chunk_size = server_ptr -> nx_web_http_server_expect_receive_bytes - server_ptr -> nx_web_http_server_actual_bytes_received;
9056 }
9057 else
9058 {
9059
9060 /* Get the chunk size. */
9061 while (1)
9062 {
9063
9064 /* Read next byte from request packet. */
9065 status = _nx_web_http_server_request_read(server_ptr, &tmp, wait_option, current_packet_pptr, current_data_pptr);
9066 if (status)
9067 {
9068 return(status);
9069 }
9070
9071 /* Skip the chunk extension. */
9072 if (chunk_extension && (tmp != '\r'))
9073 {
9074 continue;
9075 }
9076
9077 /* Calculate the size. */
9078 if ((tmp >= 'a') && (tmp <= 'f'))
9079 {
9080 size = (size << 4) + 10 + (UINT)(tmp - 'a');
9081 }
9082 else if ((tmp >= 'A') && (tmp <= 'F'))
9083 {
9084 size = (size << 4) + 10 + (UINT)(tmp - 'A');
9085 }
9086 else if ((tmp >= '0') && (tmp <= '9'))
9087 {
9088 size = (size << 4) + (UINT)(tmp - '0');
9089 }
9090 else if (tmp == '\r')
9091 {
9092
9093 /* Find the end of chunk header. */
9094 break;
9095 }
9096 else if (tmp == ';')
9097 {
9098
9099 /* Find chunk extension. */
9100 chunk_extension = 1;
9101 }
9102 else
9103 {
9104 return(NX_NOT_FOUND);
9105 }
9106 }
9107
9108 /* Expect '\n'. */
9109 status = _nx_web_http_server_request_byte_expect(server_ptr, '\n', wait_option, current_packet_pptr, current_data_pptr);
9110 if (status)
9111 {
9112 return(status);
9113 }
9114
9115 *chunk_size = size;
9116 }
9117
9118 /* If there is no remaining data, receive another packet. */
9119 while (server_ptr -> nx_web_http_server_chunked_request_remaining_size == 0)
9120 {
9121 if (server_ptr -> nx_web_http_server_request_packet)
9122 {
9123 nx_packet_release(server_ptr -> nx_web_http_server_request_packet);
9124 }
9125
9126 status = _nx_web_http_server_receive(server_ptr, &(server_ptr -> nx_web_http_server_request_packet), wait_option);
9127 if (status)
9128 {
9129 return(status);
9130 }
9131
9132 /* Update the current request packet, data pointer and remaining size. */
9133 (*current_packet_pptr) = server_ptr -> nx_web_http_server_request_packet;
9134 (*current_data_pptr) = server_ptr -> nx_web_http_server_request_packet -> nx_packet_prepend_ptr;
9135 server_ptr -> nx_web_http_server_chunked_request_remaining_size = server_ptr -> nx_web_http_server_request_packet -> nx_packet_length;
9136 }
9137
9138 return(NX_SUCCESS);
9139 }
9140
9141 /**************************************************************************/
9142 /* */
9143 /* FUNCTION RELEASE */
9144 /* */
9145 /* _nx_web_http_server_request_chunked_get PORTABLE C */
9146 /* 6.1 */
9147 /* AUTHOR */
9148 /* */
9149 /* Yuxin Zhou, Microsoft Corporation */
9150 /* */
9151 /* DESCRIPTION */
9152 /* */
9153 /* This function gets the chunk data from chunked request. */
9154 /* */
9155 /* INPUT */
9156 /* */
9157 /* server_ptr Pointer to HTTP server */
9158 /* packet_pptr Pointer to the packet */
9159 /* wait_option Suspension option */
9160 /* */
9161 /* OUTPUT */
9162 /* */
9163 /* status Completion status */
9164 /* */
9165 /* CALLS */
9166 /* */
9167 /* _nx_web_http_server_chunked_size_get Get chunk size */
9168 /* _nx_web_http_server_request_byte_expect */
9169 /* Check if next byte is expected*/
9170 /* nx_packet_allocate Allocate packet */
9171 /* nx_packet_append Append packet data */
9172 /* */
9173 /* CALLED BY */
9174 /* */
9175 /* _nx_web_http_server_packet_get Get next packet from HTTP */
9176 /* server socket */
9177 /* */
9178 /* RELEASE HISTORY */
9179 /* */
9180 /* DATE NAME DESCRIPTION */
9181 /* */
9182 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9183 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9184 /* resulting in version 6.1 */
9185 /* */
9186 /**************************************************************************/
_nx_web_http_server_request_chunked_get(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,ULONG wait_option)9187 UINT _nx_web_http_server_request_chunked_get(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, ULONG wait_option)
9188 {
9189 UINT status;
9190 UINT chunk_size = 0, length = 0, temp_size = 0;
9191 UINT remaining_size = 0;
9192 NX_PACKET *packet_ptr;
9193 NX_PACKET *current_packet_ptr = NX_NULL;
9194 UCHAR *current_data_ptr = NX_NULL;
9195
9196 /* Set pointer for processing packet data. */
9197 current_packet_ptr = server_ptr -> nx_web_http_server_request_packet;
9198
9199 if (current_packet_ptr)
9200 {
9201
9202 /* Set current data pointer. */
9203 current_data_ptr = current_packet_ptr -> nx_packet_prepend_ptr;
9204 }
9205
9206 /* Get chunk size. */
9207 status = _nx_web_http_server_chunked_size_get(server_ptr, &chunk_size, wait_option, ¤t_packet_ptr, ¤t_data_ptr);
9208 if (status)
9209 {
9210 return(status);
9211 }
9212
9213 /* Check if it's the end. */
9214 if (chunk_size == 0)
9215 {
9216
9217 /* Read CRLF. */
9218 status = _nx_web_http_server_request_byte_expect(server_ptr, '\r', wait_option, ¤t_packet_ptr, ¤t_data_ptr);
9219 if (status)
9220 {
9221 return(status);
9222 }
9223
9224 status = _nx_web_http_server_request_byte_expect(server_ptr, '\n', wait_option, ¤t_packet_ptr, ¤t_data_ptr);
9225 if (status)
9226 {
9227 return(status);
9228 }
9229
9230 *packet_pptr = NX_NULL;
9231
9232 return(NX_WEB_HTTP_GET_DONE);
9233 }
9234
9235 /* Set the return packet. */
9236 *packet_pptr = server_ptr -> nx_web_http_server_request_packet;
9237 server_ptr -> nx_web_http_server_request_packet = NX_NULL;
9238 packet_ptr = *packet_pptr;
9239 packet_ptr -> nx_packet_prepend_ptr = current_data_ptr;
9240 remaining_size = server_ptr -> nx_web_http_server_chunked_request_remaining_size;
9241
9242 /* Process the chunk data. */
9243 if (chunk_size <= remaining_size)
9244 {
9245
9246 /* One or more chunk in the remaining data. */
9247 temp_size = chunk_size;
9248
9249 /* Check if the chunk data is all in this packet. */
9250 while (temp_size > (UINT)(current_packet_ptr -> nx_packet_append_ptr - current_data_ptr))
9251 {
9252
9253 #ifndef NX_DISABLE_PACKET_CHAIN
9254 if (current_packet_ptr -> nx_packet_next == NX_NULL)
9255 {
9256 return(NX_INVALID_PACKET);
9257 }
9258
9259 temp_size -= (UINT)(current_packet_ptr -> nx_packet_append_ptr - current_data_ptr);
9260 current_packet_ptr = current_packet_ptr -> nx_packet_next;
9261 current_data_ptr = current_packet_ptr -> nx_packet_prepend_ptr;
9262 #else
9263 return(NX_INVALID_PACKET);
9264 #endif /* NX_DISABLE_PACKET_CHAIN */
9265 }
9266
9267 /* Skip the chunk data. */
9268 current_data_ptr += temp_size;
9269 server_ptr -> nx_web_http_server_chunked_request_remaining_size -= chunk_size;
9270 length = chunk_size;
9271
9272 /* Read CRLF. */
9273 status = _nx_web_http_server_request_byte_expect(server_ptr, '\r', wait_option, ¤t_packet_ptr, ¤t_data_ptr);
9274 if (status)
9275 {
9276 return(status);
9277 }
9278
9279 status = _nx_web_http_server_request_byte_expect(server_ptr, '\n', wait_option, ¤t_packet_ptr, ¤t_data_ptr);
9280 if (status)
9281 {
9282 return(status);
9283 }
9284
9285 /* Check the remaining data. */
9286 if (server_ptr -> nx_web_http_server_chunked_request_remaining_size)
9287 {
9288 if (server_ptr -> nx_web_http_server_request_packet)
9289 {
9290
9291 /* If received new packet, adjust the prepend pointer of this packet. */
9292 server_ptr -> nx_web_http_server_request_packet -> nx_packet_prepend_ptr = current_data_ptr;
9293 }
9294 else
9295 {
9296
9297 /* Copy the remaining data to a new packet. */
9298 /* Allocate a packet. */
9299 status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
9300 &(server_ptr -> nx_web_http_server_request_packet),
9301 0, wait_option);
9302 if (status)
9303 {
9304 return(status);
9305 }
9306
9307 /* Copy the remaining data in current packet to the new packet. */
9308 temp_size = (UINT)(current_packet_ptr -> nx_packet_append_ptr - current_data_ptr);
9309 status = nx_packet_data_append(server_ptr -> nx_web_http_server_request_packet,
9310 current_data_ptr,
9311 temp_size,
9312 server_ptr -> nx_web_http_server_packet_pool_ptr,
9313 wait_option);
9314 if (status)
9315 {
9316 return(status);
9317 }
9318
9319 /* Check if any remaining data not in current packet. */
9320 if (server_ptr -> nx_web_http_server_chunked_request_remaining_size > temp_size)
9321 {
9322 #ifndef NX_DISABLE_PACKET_CHAIN
9323
9324 /* If there are chained packets, append the packets to the new packet. */
9325 if (current_packet_ptr -> nx_packet_next)
9326 {
9327 server_ptr -> nx_web_http_server_request_packet -> nx_packet_next = current_packet_ptr -> nx_packet_next;
9328 server_ptr -> nx_web_http_server_request_packet -> nx_packet_last = current_packet_ptr -> nx_packet_last;
9329 current_packet_ptr -> nx_packet_next = NX_NULL;
9330 }
9331 else
9332 #endif /* NX_DISABLE_PACKET_CHAIN */
9333 {
9334 return(NX_INVALID_PACKET);
9335 }
9336 }
9337 }
9338
9339 /* Update the packet length. */
9340 server_ptr -> nx_web_http_server_request_packet -> nx_packet_length = server_ptr -> nx_web_http_server_chunked_request_remaining_size;
9341 }
9342 }
9343 else
9344 {
9345
9346 /* All the remaining data is in this chunk. */
9347 server_ptr -> nx_web_http_server_chunked_request_remaining_size = 0;
9348 length = remaining_size;
9349 }
9350
9351 /* Set the received bytes. */
9352 server_ptr -> nx_web_http_server_expect_receive_bytes = chunk_size;
9353 server_ptr -> nx_web_http_server_actual_bytes_received = length;
9354
9355 #ifndef NX_DISABLE_PACKET_CHAIN
9356 /* Set length of the packet chain header. */
9357 (*packet_pptr) -> nx_packet_length = length;
9358
9359 /* Find the last packet. */
9360 while (packet_ptr -> nx_packet_next &&
9361 (length > (UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr)))
9362 {
9363 length -= (UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr);
9364 packet_ptr = packet_ptr -> nx_packet_next;
9365 }
9366
9367 /* Set the last packet. */
9368 (*packet_pptr) -> nx_packet_last = packet_ptr;
9369
9370 /* Maybe the '\r\n' is in another packet, release this packet. */
9371 if (packet_ptr -> nx_packet_next)
9372 {
9373 nx_packet_release(packet_ptr -> nx_packet_next);
9374 packet_ptr -> nx_packet_next = NX_NULL;
9375 }
9376 #endif /* NX_DISABLE_PACKET_CHAIN */
9377
9378 /* Set packet length and append pointer. */
9379 /* If the packet is chained, set the length and append pointer of the last packet. */
9380 packet_ptr -> nx_packet_length = length;
9381 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + length;
9382
9383 return(NX_SUCCESS);
9384 }
9385
9386 /**************************************************************************/
9387 /* */
9388 /* FUNCTION RELEASE */
9389 /* */
9390 /* _nxe_web_http_server_response_chunked_set PORTABLE C */
9391 /* 6.1 */
9392 /* AUTHOR */
9393 /* */
9394 /* Yuxin Zhou, Microsoft Corporation */
9395 /* */
9396 /* DESCRIPTION */
9397 /* */
9398 /* This function checks for errors in the HTTP response chunked set */
9399 /* API call. */
9400 /* */
9401 /* INPUT */
9402 /* */
9403 /* */
9404 /* server_ptr Pointer to HTTP server */
9405 /* chunk_size Size of the chunk */
9406 /* packet_ptr Pointer to the packet */
9407 /* */
9408 /* OUTPUT */
9409 /* */
9410 /* status Completion status */
9411 /* */
9412 /* CALLS */
9413 /* */
9414 /* _nx_web_http_server_response_chunked_set */
9415 /* Actual response chunked set */
9416 /* */
9417 /* CALLED BY */
9418 /* */
9419 /* Application Code */
9420 /* */
9421 /* RELEASE HISTORY */
9422 /* */
9423 /* DATE NAME DESCRIPTION */
9424 /* */
9425 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9426 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9427 /* resulting in version 6.1 */
9428 /* */
9429 /**************************************************************************/
_nxe_web_http_server_response_chunked_set(NX_WEB_HTTP_SERVER * server_ptr,UINT chunk_size,NX_PACKET * packet_ptr)9430 UINT _nxe_web_http_server_response_chunked_set(NX_WEB_HTTP_SERVER *server_ptr, UINT chunk_size, NX_PACKET *packet_ptr)
9431 {
9432 UINT status;
9433
9434 /* Make sure the client instance makes sense. */
9435 if ((server_ptr == NX_NULL) || (packet_ptr == NX_NULL))
9436 {
9437 return(NX_PTR_ERROR);
9438 }
9439
9440 /* Call actual response chunked set function. */
9441 status = _nx_web_http_server_response_chunked_set(server_ptr, chunk_size, packet_ptr);
9442
9443 /* Return success to the caller. */
9444 return(status);
9445 }
9446
9447
9448 /**************************************************************************/
9449 /* */
9450 /* FUNCTION RELEASE */
9451 /* */
9452 /* _nx_web_http_server_response_chunked_set PORTABLE C */
9453 /* 6.1 */
9454 /* AUTHOR */
9455 /* */
9456 /* Yuxin Zhou, Microsoft Corporation */
9457 /* */
9458 /* DESCRIPTION */
9459 /* */
9460 /* This function sets the chunked information of chunked response. */
9461 /* */
9462 /* */
9463 /* INPUT */
9464 /* */
9465 /* server_ptr Pointer to HTTP server */
9466 /* chunk_size Size of the chunk */
9467 /* packet_ptr Pointer to the packet */
9468 /* */
9469 /* OUTPUT */
9470 /* */
9471 /* status Completion status */
9472 /* */
9473 /* CALLS */
9474 /* */
9475 /* nx_packet_data_append Append the packet data */
9476 /* */
9477 /* CALLED BY */
9478 /* */
9479 /* Application Code */
9480 /* */
9481 /* RELEASE HISTORY */
9482 /* */
9483 /* DATE NAME DESCRIPTION */
9484 /* */
9485 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9486 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9487 /* resulting in version 6.1 */
9488 /* */
9489 /**************************************************************************/
_nx_web_http_server_response_chunked_set(NX_WEB_HTTP_SERVER * server_ptr,UINT chunk_size,NX_PACKET * packet_ptr)9490 UINT _nx_web_http_server_response_chunked_set(NX_WEB_HTTP_SERVER *server_ptr, UINT chunk_size, NX_PACKET *packet_ptr)
9491 {
9492 UINT status;
9493 UINT temp_size, i, j;
9494 CHAR temp_string[10];
9495 CHAR crlf[2] = {13,10};
9496
9497 /* Covert the size to ASCII. */
9498 temp_size = chunk_size;
9499 i = 0;
9500
9501 while (temp_size)
9502 {
9503
9504 for (j = i; j > 0; j--)
9505 {
9506 temp_string[j] = temp_string[j - 1];
9507 }
9508
9509 if ((temp_size & 0x0F) < 10)
9510 {
9511 temp_string[0] = (CHAR)((temp_size & 0x0F) + '0');
9512 }
9513 else
9514 {
9515 temp_string[0] = (CHAR)((temp_size & 0x0F) - 10 + 'a');
9516 }
9517 temp_size = temp_size >> 4;
9518 i++;
9519 }
9520
9521 if (i == 0)
9522 {
9523 temp_string[i++] = '0';
9524 }
9525
9526 /* Place the chunk size in the packet. */
9527 status = nx_packet_data_append(packet_ptr, temp_string, i, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
9528 if (status)
9529 {
9530 return(status);
9531 }
9532
9533 /* Place the CRLF to signal the end of the chunk size. */
9534 status = nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
9535 if (status)
9536 {
9537 return(status);
9538 }
9539
9540 /* Set the request chunked flag. */
9541 server_ptr -> nx_web_http_server_response_chunked = NX_TRUE;
9542
9543 /* The total bytes need to transfer is chunk size plus chunk header length. */
9544 server_ptr -> nx_web_http_server_expect_transfer_bytes = chunk_size + i + 2;
9545 server_ptr -> nx_web_http_server_actual_bytes_transferred = 0;
9546
9547 return(NX_SUCCESS);
9548 }
9549
9550
9551 /**************************************************************************/
9552 /* */
9553 /* FUNCTION RELEASE */
9554 /* */
9555 /* _nx_web_http_server_chunked_check PORTABLE C */
9556 /* 6.1 */
9557 /* AUTHOR */
9558 /* */
9559 /* Yuxin Zhou, Microsoft Corporation */
9560 /* */
9561 /* DESCRIPTION */
9562 /* */
9563 /* This function checks if the packet is chunked. */
9564 /* */
9565 /* */
9566 /* INPUT */
9567 /* */
9568 /* server_ptr Pointer to HTTP server */
9569 /* packet_ptr Pointer to the packet */
9570 /* */
9571 /* OUTPUT */
9572 /* */
9573 /* status The packet is chunked or not */
9574 /* */
9575 /* CALLS */
9576 /* */
9577 /* _nx_web_http_server_field_value_get Get filed value */
9578 /* _nx_web_http_server_memicmp Compare two strings */
9579 /* _nx_utility_string_length_check Check string length */
9580 /* */
9581 /* CALLED BY */
9582 /* */
9583 /* _nx_web_http_server_packet_content_find */
9584 /* Find content length in the */
9585 /* HTTP header */
9586 /* _nx_web_http_server_content_get_extended */
9587 /* Get user specified portion of */
9588 /* HTTP header */
9589 /* _nx_web_http_server_receive_data HTTP Server receive processing*/
9590 /* */
9591 /* RELEASE HISTORY */
9592 /* */
9593 /* DATE NAME DESCRIPTION */
9594 /* */
9595 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9596 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9597 /* resulting in version 6.1 */
9598 /* */
9599 /**************************************************************************/
_nx_web_http_server_chunked_check(NX_PACKET * packet_ptr)9600 UINT _nx_web_http_server_chunked_check(NX_PACKET *packet_ptr)
9601 {
9602 UINT status;
9603 CHAR temp_string[20];
9604 UINT temp_string_length;
9605
9606 /* Check if the packet is chunked. */
9607 status = _nx_web_http_server_field_value_get(packet_ptr, (UCHAR *)"Transfer-Encoding", 17, (UCHAR *)temp_string, sizeof(temp_string));
9608
9609 if ((status == NX_SUCCESS) &&
9610 (_nx_utility_string_length_check(temp_string, &temp_string_length, sizeof(temp_string) - 1) == NX_SUCCESS) &&
9611 (_nx_web_http_server_memicmp((UCHAR *)temp_string, temp_string_length, (UCHAR *)"chunked", 7) == 0))
9612 {
9613 return(NX_TRUE);
9614 }
9615
9616 return(NX_FALSE);
9617 }
9618
9619
9620 /**************************************************************************/
9621 /* */
9622 /* FUNCTION RELEASE */
9623 /* */
9624 /* _nxe_web_http_server_response_packet_allocate PORTABLE C */
9625 /* 6.1 */
9626 /* AUTHOR */
9627 /* */
9628 /* Yuxin Zhou, Microsoft Corporation */
9629 /* */
9630 /* DESCRIPTION */
9631 /* */
9632 /* This function checks for errors in the call to allocate packets for */
9633 /* an HTTP(S) server session, as used for PUT and POST operations. */
9634 /* */
9635 /* */
9636 /* INPUT */
9637 /* */
9638 /* server_ptr Pointer to HTTP client */
9639 /* packet_ptr Pointer to allocated packet */
9640 /* wait_option Suspension option */
9641 /* */
9642 /* OUTPUT */
9643 /* */
9644 /* status Completion status */
9645 /* */
9646 /* CALLS */
9647 /* */
9648 /* _nxe_web_http_server_response_packet_allocate */
9649 /* Actual packet allocation call */
9650 /* */
9651 /* CALLED BY */
9652 /* */
9653 /* Application Code */
9654 /* */
9655 /* RELEASE HISTORY */
9656 /* */
9657 /* DATE NAME DESCRIPTION */
9658 /* */
9659 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9660 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9661 /* resulting in version 6.1 */
9662 /* */
9663 /**************************************************************************/
_nxe_web_http_server_response_packet_allocate(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,UINT wait_option)9664 UINT _nxe_web_http_server_response_packet_allocate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr,
9665 UINT wait_option)
9666 {
9667 UINT status;
9668
9669 /* Check our pointers. */
9670 if(server_ptr == NX_NULL || packet_ptr == NX_NULL)
9671 {
9672 return(NX_PTR_ERROR);
9673 }
9674
9675 /* Call the actual function. */
9676 status = _nx_web_http_server_response_packet_allocate(server_ptr, packet_ptr, wait_option);
9677
9678 return(status);
9679 }
9680
9681
9682 /**************************************************************************/
9683 /* */
9684 /* FUNCTION RELEASE */
9685 /* */
9686 /* _nx_web_http_server_response_packet_allocate PORTABLE C */
9687 /* 6.1 */
9688 /* AUTHOR */
9689 /* */
9690 /* Yuxin Zhou, Microsoft Corporation */
9691 /* */
9692 /* DESCRIPTION */
9693 /* */
9694 /* This function allocates a packet for Server HTTP(S) responses so */
9695 /* that servers needing to send large amounts of data (such as for */
9696 /* multi-part file upload) can allocated the needed. */
9697 /* */
9698 /* */
9699 /* INPUT */
9700 /* */
9701 /* server_ptr Pointer to HTTP server */
9702 /* packet_ptr Pointer to allocated packet */
9703 /* wait_option Suspension option */
9704 /* */
9705 /* OUTPUT */
9706 /* */
9707 /* status Completion status */
9708 /* */
9709 /* CALLS */
9710 /* */
9711 /* nx_secure_tls_packet_allocate Allocate a TLS packet */
9712 /* nx_packet_allocate Allocate a TCP packet */
9713 /* */
9714 /* CALLED BY */
9715 /* */
9716 /* Application Code */
9717 /* */
9718 /* RELEASE HISTORY */
9719 /* */
9720 /* DATE NAME DESCRIPTION */
9721 /* */
9722 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9723 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9724 /* resulting in version 6.1 */
9725 /* */
9726 /**************************************************************************/
_nx_web_http_server_response_packet_allocate(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,UINT wait_option)9727 UINT _nx_web_http_server_response_packet_allocate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr,
9728 UINT wait_option)
9729 {
9730 UINT status;
9731
9732 /* Allocate a packet. */
9733 #ifdef NX_WEB_HTTPS_ENABLE
9734 if(server_ptr -> nx_web_http_is_https_server)
9735 {
9736 status = nx_secure_tls_packet_allocate(&(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_tls_session),
9737 server_ptr -> nx_web_http_server_packet_pool_ptr,
9738 packet_ptr, wait_option);
9739 }
9740 else
9741 #endif
9742 {
9743 status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr,
9744 packet_ptr,
9745 NX_TCP_PACKET, wait_option);
9746 }
9747
9748 return(status);
9749 }
9750
9751
9752 /**************************************************************************/
9753 /* */
9754 /* FUNCTION RELEASE */
9755 /* */
9756 /* _nxe_web_http_server_callback_generate_response_header */
9757 /* PORTABLE C */
9758 /* 6.1 */
9759 /* AUTHOR */
9760 /* */
9761 /* Yuxin Zhou, Microsoft Corporation */
9762 /* */
9763 /* DESCRIPTION */
9764 /* */
9765 /* This function checks error for generating HTTP response header. */
9766 /* */
9767 /* INPUT */
9768 /* */
9769 /* server_ptr Pointer to HTTP server */
9770 /* packet_pptr Pointer to packet */
9771 /* status_code Status-code and reason-phrase */
9772 /* content_length Length of content */
9773 /* content_type Type of content */
9774 /* additional_header Other HTTP headers */
9775 /* */
9776 /* OUTPUT */
9777 /* */
9778 /* status Completion status */
9779 /* */
9780 /* CALLS */
9781 /* */
9782 /* _nx_web_http_server_callback_generate_response_header */
9783 /* */
9784 /* CALLED BY */
9785 /* */
9786 /* Application Code */
9787 /* */
9788 /* RELEASE HISTORY */
9789 /* */
9790 /* DATE NAME DESCRIPTION */
9791 /* */
9792 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9793 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9794 /* resulting in version 6.1 */
9795 /* */
9796 /**************************************************************************/
_nxe_web_http_server_callback_generate_response_header(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT content_length,CHAR * content_type,CHAR * additional_header)9797 UINT _nxe_web_http_server_callback_generate_response_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr,
9798 CHAR *status_code, UINT content_length, CHAR *content_type,
9799 CHAR* additional_header)
9800 {
9801
9802 /* Check for invalid input pointers. */
9803 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
9804 (packet_pptr == NX_NULL) || (status_code == NX_NULL))
9805 return(NX_PTR_ERROR);
9806
9807 return _nx_web_http_server_callback_generate_response_header(server_ptr, packet_pptr, status_code, content_length, content_type, additional_header);
9808 }
9809
9810
9811 /**************************************************************************/
9812 /* */
9813 /* FUNCTION RELEASE */
9814 /* */
9815 /* _nx_web_http_server_callback_generate_response_header */
9816 /* PORTABLE C */
9817 /* 6.1 */
9818 /* AUTHOR */
9819 /* */
9820 /* Yuxin Zhou, Microsoft Corporation */
9821 /* */
9822 /* DESCRIPTION */
9823 /* */
9824 /* This function is used in callback function to generate HTTP */
9825 /* response header. */
9826 /* */
9827 /* INPUT */
9828 /* */
9829 /* server_ptr Pointer to HTTP server */
9830 /* packet_pptr Pointer to packet */
9831 /* status_code Status-code and reason-phrase */
9832 /* content_length Length of content */
9833 /* content_type Type of content */
9834 /* additional_header Other HTTP headers */
9835 /* */
9836 /* OUTPUT */
9837 /* */
9838 /* status Completion status */
9839 /* */
9840 /* CALLS */
9841 /* */
9842 /* _nx_web_http_server_generate_response_header */
9843 /* Generate response header */
9844 /* _nx_utility_string_length_check Check string length */
9845 /* */
9846 /* CALLED BY */
9847 /* */
9848 /* Application Code */
9849 /* */
9850 /* RELEASE HISTORY */
9851 /* */
9852 /* DATE NAME DESCRIPTION */
9853 /* */
9854 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9855 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9856 /* resulting in version 6.1 */
9857 /* */
9858 /**************************************************************************/
_nx_web_http_server_callback_generate_response_header(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT content_length,CHAR * content_type,CHAR * additional_header)9859 UINT _nx_web_http_server_callback_generate_response_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr,
9860 CHAR *status_code, UINT content_length, CHAR *content_type,
9861 CHAR* additional_header)
9862 {
9863 UINT status_code_length = 0;
9864 UINT content_type_length = 0;
9865 UINT additional_header_length = 0;
9866
9867 /* Check status code, content type and additional header length. */
9868 if (_nx_utility_string_length_check(status_code, &status_code_length, NX_MAX_STRING_LENGTH) ||
9869 (content_type && _nx_utility_string_length_check(content_type, &content_type_length, NX_MAX_STRING_LENGTH)) ||
9870 (additional_header && _nx_utility_string_length_check(additional_header, &additional_header_length, NX_MAX_STRING_LENGTH)))
9871 {
9872 return(NX_WEB_HTTP_ERROR);
9873 }
9874
9875 /* Call the internal HTTP response send function. */
9876 return _nx_web_http_server_generate_response_header(server_ptr, packet_pptr, status_code,
9877 status_code_length, content_length,
9878 content_type, content_type_length,
9879 additional_header, additional_header_length);
9880 }
9881
9882
9883 /**************************************************************************/
9884 /* */
9885 /* FUNCTION RELEASE */
9886 /* */
9887 /* _nxe_web_http_server_callback_generate_response_header_extended */
9888 /* PORTABLE C */
9889 /* 6.1 */
9890 /* AUTHOR */
9891 /* */
9892 /* Yuxin Zhou, Microsoft Corporation */
9893 /* */
9894 /* DESCRIPTION */
9895 /* */
9896 /* This function checks error for generating HTTP response header. */
9897 /* */
9898 /* INPUT */
9899 /* */
9900 /* server_ptr Pointer to HTTP server */
9901 /* packet_pptr Pointer to packet */
9902 /* status_code Status-code and reason-phrase */
9903 /* status_code_length Length of status-code */
9904 /* content_length Length of content */
9905 /* content_type Type of content */
9906 /* content_type_length Length of content type */
9907 /* additional_header Other HTTP headers */
9908 /* additional_header_length Length of other HTTP headers */
9909 /* */
9910 /* OUTPUT */
9911 /* */
9912 /* status Completion status */
9913 /* */
9914 /* CALLS */
9915 /* */
9916 /* _nx_web_http_server_callback_generate_response_header_extended */
9917 /* Actual generate header */
9918 /* */
9919 /* CALLED BY */
9920 /* */
9921 /* Application Code */
9922 /* */
9923 /* RELEASE HISTORY */
9924 /* */
9925 /* DATE NAME DESCRIPTION */
9926 /* */
9927 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9928 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9929 /* resulting in version 6.1 */
9930 /* */
9931 /**************************************************************************/
_nxe_web_http_server_callback_generate_response_header_extended(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT status_code_length,UINT content_length,CHAR * content_type,UINT content_type_length,CHAR * additional_header,UINT additional_header_length)9932 UINT _nxe_web_http_server_callback_generate_response_header_extended(NX_WEB_HTTP_SERVER *server_ptr,
9933 NX_PACKET **packet_pptr, CHAR *status_code,
9934 UINT status_code_length, UINT content_length,
9935 CHAR *content_type, UINT content_type_length,
9936 CHAR *additional_header, UINT additional_header_length)
9937 {
9938
9939 /* Check for invalid input pointers. */
9940 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) ||
9941 (packet_pptr == NX_NULL) || (status_code == NX_NULL))
9942 return(NX_PTR_ERROR);
9943
9944 /* Check for appropriate caller. */
9945 NX_THREADS_ONLY_CALLER_CHECKING
9946
9947 return _nx_web_http_server_callback_generate_response_header_extended(server_ptr, packet_pptr, status_code,
9948 status_code_length, content_length,
9949 content_type, content_type_length,
9950 additional_header, additional_header_length);
9951 }
9952
9953
9954 /**************************************************************************/
9955 /* */
9956 /* FUNCTION RELEASE */
9957 /* */
9958 /* _nx_web_http_server_callback_generate_response_header_extended */
9959 /* PORTABLE C */
9960 /* 6.1 */
9961 /* AUTHOR */
9962 /* */
9963 /* Yuxin Zhou, Microsoft Corporation */
9964 /* */
9965 /* DESCRIPTION */
9966 /* */
9967 /* This function is used in callback function to generate HTTP */
9968 /* response header. */
9969 /* */
9970 /* Note: The strings of status_code, content_type and additional_header*/
9971 /* must be NULL-terminated and length of each string matches the */
9972 /* length specified in the argument list. */
9973 /* */
9974 /* INPUT */
9975 /* */
9976 /* server_ptr Pointer to HTTP server */
9977 /* packet_pptr Pointer to packet */
9978 /* status_code Status-code and reason-phrase */
9979 /* status_code_length Length of status-code */
9980 /* content_length Length of content */
9981 /* content_type Type of content */
9982 /* content_type_length Length of content type */
9983 /* additional_header Other HTTP headers */
9984 /* additional_header_length Length of other HTTP headers */
9985 /* */
9986 /* OUTPUT */
9987 /* */
9988 /* status Completion status */
9989 /* */
9990 /* CALLS */
9991 /* */
9992 /* _nx_web_http_server_generate_response_header */
9993 /* Generate response header */
9994 /* _nx_utility_string_length_check Check string length */
9995 /* */
9996 /* CALLED BY */
9997 /* */
9998 /* Application Code */
9999 /* */
10000 /* RELEASE HISTORY */
10001 /* */
10002 /* DATE NAME DESCRIPTION */
10003 /* */
10004 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10005 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10006 /* resulting in version 6.1 */
10007 /* */
10008 /**************************************************************************/
_nx_web_http_server_callback_generate_response_header_extended(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT status_code_length,UINT content_length,CHAR * content_type,UINT content_type_length,CHAR * additional_header,UINT additional_header_length)10009 UINT _nx_web_http_server_callback_generate_response_header_extended(NX_WEB_HTTP_SERVER *server_ptr,
10010 NX_PACKET **packet_pptr, CHAR *status_code,
10011 UINT status_code_length, UINT content_length,
10012 CHAR *content_type, UINT content_type_length,
10013 CHAR *additional_header, UINT additional_header_length)
10014 {
10015 UINT temp_status_code_length = 0;
10016 UINT temp_content_type_length = 0;
10017 UINT temp_add_header_length = 0;
10018
10019 /* Check status code, content type and additional header length. */
10020 if (_nx_utility_string_length_check(status_code, &temp_status_code_length, status_code_length) ||
10021 (content_type && _nx_utility_string_length_check(content_type, &temp_content_type_length, content_type_length)) ||
10022 (additional_header && _nx_utility_string_length_check(additional_header, &temp_add_header_length, additional_header_length)))
10023 {
10024 return(NX_WEB_HTTP_ERROR);
10025 }
10026
10027 /* Validate string length. */
10028 if ((status_code_length != temp_status_code_length) ||
10029 (content_type && content_type_length != temp_content_type_length) ||
10030 (additional_header && additional_header_length != temp_add_header_length))
10031 {
10032 return(NX_WEB_HTTP_ERROR);
10033 }
10034
10035 /* Call the internal HTTP response send function. */
10036 return _nx_web_http_server_generate_response_header(server_ptr, packet_pptr, status_code,
10037 status_code_length, content_length,
10038 content_type, content_type_length,
10039 additional_header, additional_header_length);
10040 }
10041
10042
10043 /**************************************************************************/
10044 /* */
10045 /* FUNCTION RELEASE */
10046 /* */
10047 /* _nxe_web_http_server_callback_packet_send PORTABLE C */
10048 /* 6.1 */
10049 /* AUTHOR */
10050 /* */
10051 /* Yuxin Zhou, Microsoft Corporation */
10052 /* */
10053 /* DESCRIPTION */
10054 /* */
10055 /* This function checks error for sending a packet. */
10056 /* */
10057 /* INPUT */
10058 /* */
10059 /* server_ptr Pointer to HTTP server */
10060 /* packet_ptr Pointer to packet */
10061 /* */
10062 /* OUTPUT */
10063 /* */
10064 /* status Completion status */
10065 /* */
10066 /* CALLS */
10067 /* */
10068 /* _nx_web_http_server_callback_packet_send */
10069 /* */
10070 /* CALLED BY */
10071 /* */
10072 /* Application Code */
10073 /* */
10074 /* RELEASE HISTORY */
10075 /* */
10076 /* DATE NAME DESCRIPTION */
10077 /* */
10078 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10079 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10080 /* resulting in version 6.1 */
10081 /* */
10082 /**************************************************************************/
_nxe_web_http_server_callback_packet_send(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)10083 UINT _nxe_web_http_server_callback_packet_send(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
10084 {
10085
10086 /* Check for invalid input pointers. */
10087 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) || (packet_ptr == NX_NULL))
10088 return(NX_PTR_ERROR);
10089
10090 return _nx_web_http_server_callback_packet_send(server_ptr, packet_ptr);
10091 }
10092
10093
10094 /**************************************************************************/
10095 /* */
10096 /* FUNCTION RELEASE */
10097 /* */
10098 /* _nx_web_http_server_callback_packet_send PORTABLE C */
10099 /* 6.1 */
10100 /* AUTHOR */
10101 /* */
10102 /* Yuxin Zhou, Microsoft Corporation */
10103 /* */
10104 /* DESCRIPTION */
10105 /* */
10106 /* This function is used in callback function to send a packet. */
10107 /* */
10108 /* INPUT */
10109 /* */
10110 /* server_ptr Pointer to HTTP server */
10111 /* packet_ptr Pointer to packet */
10112 /* */
10113 /* OUTPUT */
10114 /* */
10115 /* status Completion status */
10116 /* */
10117 /* CALLS */
10118 /* */
10119 /* _nx_web_http_server_send Send packet to client */
10120 /* nx_packet_data_append Append packet data */
10121 /* */
10122 /* CALLED BY */
10123 /* */
10124 /* Application Code */
10125 /* */
10126 /* RELEASE HISTORY */
10127 /* */
10128 /* DATE NAME DESCRIPTION */
10129 /* */
10130 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10131 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10132 /* resulting in version 6.1 */
10133 /* */
10134 /**************************************************************************/
_nx_web_http_server_callback_packet_send(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)10135 UINT _nx_web_http_server_callback_packet_send(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
10136 {
10137 UINT status;
10138 CHAR crlf[2] = {13,10};
10139 UINT length = packet_ptr -> nx_packet_length;
10140
10141 /* If the request is chunked, add CRLF at the end of the chunk. */
10142 if (server_ptr -> nx_web_http_server_response_chunked)
10143 {
10144
10145 /* Check the packet length. */
10146 if (server_ptr -> nx_web_http_server_expect_transfer_bytes < (server_ptr -> nx_web_http_server_actual_bytes_transferred + length))
10147 {
10148 return(NX_INVALID_PACKET);
10149 }
10150
10151 if (server_ptr -> nx_web_http_server_expect_transfer_bytes == (server_ptr -> nx_web_http_server_actual_bytes_transferred + length))
10152 {
10153
10154 /* Place an extra CRLF to signal the end of the chunk. */
10155 nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
10156 }
10157
10158 /* Update the transferred bytes. */
10159 server_ptr -> nx_web_http_server_actual_bytes_transferred += length;
10160 }
10161
10162 /* Send internal. */
10163 status = _nx_web_http_server_send(server_ptr, packet_ptr, NX_WEB_HTTP_SERVER_TIMEOUT_SEND);
10164 if (status)
10165 {
10166 return(status);
10167 }
10168
10169 return(NX_SUCCESS);
10170 }
10171
10172
10173 /**************************************************************************/
10174 /* */
10175 /* FUNCTION RELEASE */
10176 /* */
10177 /* _nxe_web_http_server_gmt_callback_set PORTABLE C */
10178 /* 6.1 */
10179 /* AUTHOR */
10180 /* */
10181 /* Yuxin Zhou, Microsoft Corporation */
10182 /* */
10183 /* DESCRIPTION */
10184 /* */
10185 /* This function checks error for setting gmt callback function. */
10186 /* */
10187 /* INPUT */
10188 /* */
10189 /* server_ptr Pointer to HTTP server */
10190 /* gmt_get Pointer to application's */
10191 /* GMT time function */
10192 /* */
10193 /* OUTPUT */
10194 /* */
10195 /* status Completion status */
10196 /* */
10197 /* CALLS */
10198 /* */
10199 /* _nx_web_http_server_gmt_callback_set */
10200 /* */
10201 /* CALLED BY */
10202 /* */
10203 /* Application Code */
10204 /* */
10205 /* RELEASE HISTORY */
10206 /* */
10207 /* DATE NAME DESCRIPTION */
10208 /* */
10209 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10210 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10211 /* resulting in version 6.1 */
10212 /* */
10213 /**************************************************************************/
_nxe_web_http_server_gmt_callback_set(NX_WEB_HTTP_SERVER * server_ptr,VOID (* gmt_get)(NX_WEB_HTTP_SERVER_DATE *))10214 UINT _nxe_web_http_server_gmt_callback_set(NX_WEB_HTTP_SERVER *server_ptr, VOID (*gmt_get)(NX_WEB_HTTP_SERVER_DATE *))
10215 {
10216
10217 /* Check for invalid input pointers. */
10218 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) || (gmt_get == NX_NULL))
10219 return(NX_PTR_ERROR);
10220
10221 /* Send internal. */
10222 return _nx_web_http_server_gmt_callback_set(server_ptr, gmt_get);
10223 }
10224
10225
10226 /**************************************************************************/
10227 /* */
10228 /* FUNCTION RELEASE */
10229 /* */
10230 /* _nx_web_http_server_gmt_callback_set PORTABLE C */
10231 /* 6.1 */
10232 /* AUTHOR */
10233 /* */
10234 /* Yuxin Zhou, Microsoft Corporation */
10235 /* */
10236 /* DESCRIPTION */
10237 /* */
10238 /* This function sets gmt callback function. */
10239 /* */
10240 /* INPUT */
10241 /* */
10242 /* server_ptr Pointer to HTTP server */
10243 /* gmt_get Pointer to application's */
10244 /* GMT time function */
10245 /* */
10246 /* OUTPUT */
10247 /* */
10248 /* status Completion status */
10249 /* */
10250 /* CALLS */
10251 /* */
10252 /* */
10253 /* CALLED BY */
10254 /* */
10255 /* Application Code */
10256 /* */
10257 /* RELEASE HISTORY */
10258 /* */
10259 /* DATE NAME DESCRIPTION */
10260 /* */
10261 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10262 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10263 /* resulting in version 6.1 */
10264 /* */
10265 /**************************************************************************/
_nx_web_http_server_gmt_callback_set(NX_WEB_HTTP_SERVER * server_ptr,VOID (* gmt_get)(NX_WEB_HTTP_SERVER_DATE *))10266 UINT _nx_web_http_server_gmt_callback_set(NX_WEB_HTTP_SERVER *server_ptr, VOID (*gmt_get)(NX_WEB_HTTP_SERVER_DATE *))
10267 {
10268
10269 TX_INTERRUPT_SAVE_AREA
10270
10271 /* Lockout interrupts. */
10272 TX_DISABLE
10273
10274 /* Set the function pointer. */
10275 server_ptr -> nx_web_http_server_gmt_get = gmt_get;
10276
10277 /* Restore interrupts. */
10278 TX_RESTORE
10279
10280 return NX_SUCCESS;
10281 }
10282
10283
10284 /**************************************************************************/
10285 /* */
10286 /* FUNCTION RELEASE */
10287 /* */
10288 /* _nxe_web_http_server_cache_info_callback_set PORTABLE C */
10289 /* 6.1 */
10290 /* AUTHOR */
10291 /* */
10292 /* Yuxin Zhou, Microsoft Corporation */
10293 /* */
10294 /* DESCRIPTION */
10295 /* */
10296 /* This function checks error for setting cache info callback function.*/
10297 /* */
10298 /* INPUT */
10299 /* */
10300 /* server_ptr Pointer to HTTP server */
10301 /* cache_info_get Pointer to application's */
10302 /* cache information function */
10303 /* */
10304 /* OUTPUT */
10305 /* */
10306 /* status Completion status */
10307 /* */
10308 /* CALLS */
10309 /* */
10310 /* _nx_web_http_server_cache_info_callback_set */
10311 /* */
10312 /* CALLED BY */
10313 /* */
10314 /* Application Code */
10315 /* */
10316 /* RELEASE HISTORY */
10317 /* */
10318 /* DATE NAME DESCRIPTION */
10319 /* */
10320 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10321 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10322 /* resulting in version 6.1 */
10323 /* */
10324 /**************************************************************************/
_nxe_web_http_server_cache_info_callback_set(NX_WEB_HTTP_SERVER * server_ptr,UINT (* cache_info_get)(CHAR *,UINT *,NX_WEB_HTTP_SERVER_DATE *))10325 UINT _nxe_web_http_server_cache_info_callback_set(NX_WEB_HTTP_SERVER *server_ptr, UINT (*cache_info_get)(CHAR *, UINT *, NX_WEB_HTTP_SERVER_DATE *))
10326 {
10327
10328 /* Check for invalid input pointers. */
10329 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) || (cache_info_get == NX_NULL))
10330 return(NX_PTR_ERROR);
10331
10332 /* Send internal. */
10333 return _nx_web_http_server_cache_info_callback_set(server_ptr, cache_info_get);
10334 }
10335
10336
10337 /**************************************************************************/
10338 /* */
10339 /* FUNCTION RELEASE */
10340 /* */
10341 /* _nx_web_http_server_cache_info_callback_set PORTABLE C */
10342 /* 6.1 */
10343 /* AUTHOR */
10344 /* */
10345 /* Yuxin Zhou, Microsoft Corporation */
10346 /* */
10347 /* DESCRIPTION */
10348 /* */
10349 /* This function sets cache info callback function. */
10350 /* */
10351 /* Note: The string resource in callback functions authentication_check*/
10352 /* and request_notify is built by internal logic and always */
10353 /* NULL-terminated. */
10354 /* */
10355 /* INPUT */
10356 /* */
10357 /* server_ptr Pointer to HTTP server */
10358 /* cache_info_get Pointer to application's */
10359 /* cache information function */
10360 /* */
10361 /* OUTPUT */
10362 /* */
10363 /* status Completion status */
10364 /* */
10365 /* CALLS */
10366 /* */
10367 /* None */
10368 /* */
10369 /* CALLED BY */
10370 /* */
10371 /* Application Code */
10372 /* */
10373 /* RELEASE HISTORY */
10374 /* */
10375 /* DATE NAME DESCRIPTION */
10376 /* */
10377 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10378 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10379 /* resulting in version 6.1 */
10380 /* */
10381 /**************************************************************************/
_nx_web_http_server_cache_info_callback_set(NX_WEB_HTTP_SERVER * server_ptr,UINT (* cache_info_get)(CHAR *,UINT *,NX_WEB_HTTP_SERVER_DATE *))10382 UINT _nx_web_http_server_cache_info_callback_set(NX_WEB_HTTP_SERVER *server_ptr, UINT (*cache_info_get)(CHAR *, UINT *, NX_WEB_HTTP_SERVER_DATE *))
10383 {
10384
10385 TX_INTERRUPT_SAVE_AREA
10386
10387 /* Lockout interrupts. */
10388 TX_DISABLE
10389
10390 /* Set the function pointer. */
10391 server_ptr -> nx_web_http_server_cache_info_get = cache_info_get;
10392
10393 /* Restore interrupts. */
10394 TX_RESTORE
10395
10396 return NX_SUCCESS;
10397 }
10398
10399
10400 /**************************************************************************/
10401 /* */
10402 /* FUNCTION RELEASE */
10403 /* */
10404 /* _nx_web_http_server_date_to_string PORTABLE C */
10405 /* 6.1 */
10406 /* AUTHOR */
10407 /* */
10408 /* Yuxin Zhou, Microsoft Corporation */
10409 /* */
10410 /* DESCRIPTION */
10411 /* */
10412 /* This function converts from date to string. */
10413 /* */
10414 /* INPUT */
10415 /* */
10416 /* date Pointer to HTTP date */
10417 /* string Pointer to output buffer */
10418 /* */
10419 /* OUTPUT */
10420 /* */
10421 /* status Completion status */
10422 /* */
10423 /* CALLS */
10424 /* */
10425 /* _nx_web_http_server_date_convert */
10426 /* */
10427 /* CALLED BY */
10428 /* */
10429 /* _nx_web_http_server_get_process */
10430 /* _nx_web_http_server_generate_response_header */
10431 /* */
10432 /* RELEASE HISTORY */
10433 /* */
10434 /* DATE NAME DESCRIPTION */
10435 /* */
10436 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10437 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10438 /* resulting in version 6.1 */
10439 /* */
10440 /**************************************************************************/
_nx_web_http_server_date_to_string(NX_WEB_HTTP_SERVER_DATE * date,CHAR * string)10441 UINT _nx_web_http_server_date_to_string(NX_WEB_HTTP_SERVER_DATE *date, CHAR *string)
10442 {
10443
10444 UINT index = 0;
10445
10446 /* RDC1122-date. */
10447 /* Append weekday. */
10448 string[index++] = _nx_web_http_server_weekday[date -> nx_web_http_server_weekday][0];
10449 string[index++] = _nx_web_http_server_weekday[date -> nx_web_http_server_weekday][1];
10450 string[index++] = _nx_web_http_server_weekday[date -> nx_web_http_server_weekday][2];
10451 string[index++] = ',';
10452 string[index++] = ' ';
10453
10454 /* Convert and append day. */
10455 _nx_web_http_server_date_convert(date -> nx_web_http_server_day, 2, &string[index]);
10456 index += 2;
10457 string[index++] = ' ';
10458
10459 /* Append month. */
10460 string[index++] = _nx_web_http_server_month[date -> nx_web_http_server_month][0];
10461 string[index++] = _nx_web_http_server_month[date -> nx_web_http_server_month][1];
10462 string[index++] = _nx_web_http_server_month[date -> nx_web_http_server_month][2];
10463 string[index++] = ' ';
10464
10465 /* Convert and append year. */
10466 _nx_web_http_server_date_convert(date -> nx_web_http_server_year, 4, &string[index]);
10467 index += 4;
10468 string[index++] = ' ';
10469
10470 /* Convert and append hour. */
10471 _nx_web_http_server_date_convert(date -> nx_web_http_server_hour, 2, &string[index]);
10472 index += 2;
10473 string[index++] = ':';
10474
10475 /* Convert and append minute. */
10476 _nx_web_http_server_date_convert(date -> nx_web_http_server_minute, 2, &string[index]);
10477 index += 2;
10478 string[index++] = ':';
10479
10480 /* Convert and append second. */
10481 _nx_web_http_server_date_convert(date -> nx_web_http_server_second, 2, &string[index]);
10482 index += 2;
10483 string[index++] = ' ';
10484 string[index++] = 'G';
10485 string[index++] = 'M';
10486 string[index++] = 'T';
10487
10488 return index;
10489 }
10490
10491
10492 /**************************************************************************/
10493 /* */
10494 /* FUNCTION RELEASE */
10495 /* */
10496 /* _nx_web_http_server_date_convert PORTABLE C */
10497 /* 6.1 */
10498 /* AUTHOR */
10499 /* */
10500 /* Yuxin Zhou, Microsoft Corporation */
10501 /* */
10502 /* DESCRIPTION */
10503 /* */
10504 /* This function converts a date from number to string. */
10505 /* */
10506 /* INPUT */
10507 /* */
10508 /* date The number to convert */
10509 /* count Digital count for string */
10510 /* string Pointer to output buffer */
10511 /* */
10512 /* OUTPUT */
10513 /* */
10514 /* None */
10515 /* */
10516 /* CALLS */
10517 /* */
10518 /* */
10519 /* CALLED BY */
10520 /* */
10521 /* _nx_web_http_server_date_to_string */
10522 /* */
10523 /* RELEASE HISTORY */
10524 /* */
10525 /* DATE NAME DESCRIPTION */
10526 /* */
10527 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10528 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10529 /* resulting in version 6.1 */
10530 /* */
10531 /**************************************************************************/
_nx_web_http_server_date_convert(UINT date,UINT count,CHAR * string)10532 VOID _nx_web_http_server_date_convert(UINT date, UINT count, CHAR *string)
10533 {
10534
10535 UINT digit;
10536
10537 /* Initialize all 4 bytes to digit 0. */
10538 *((ULONG*)string) = 0x30303030;
10539 string[count] = 0;
10540
10541 /* Loop to convert the number to ASCII. */
10542 while(count > 0)
10543 {
10544 count--;
10545
10546 /* Compute the next decimal digit. */
10547 digit = date % 10;
10548
10549 /* Update the input date. */
10550 date = date / 10;
10551
10552 /* Store the new digit in ASCII form. */
10553 string[count] = (CHAR) (digit + 0x30);
10554 }
10555 }
10556
10557
10558 /**************************************************************************/
10559 /* */
10560 /* FUNCTION RELEASE */
10561 /* */
10562 /* _nxe_web_http_server_mime_maps_additional_set PORTABLE C */
10563 /* 6.1 */
10564 /* AUTHOR */
10565 /* */
10566 /* Yuxin Zhou, Microsoft Corporation */
10567 /* */
10568 /* DESCRIPTION */
10569 /* */
10570 /* This function checks error for setting additional MIME maps. */
10571 /* */
10572 /* INPUT */
10573 /* */
10574 /* server_ptr Pointer to HTTP server */
10575 /* mime_maps Pointer MIME map array */
10576 /* mime_maps_num Number of MIME map array */
10577 /* */
10578 /* OUTPUT */
10579 /* */
10580 /* status Completion status */
10581 /* */
10582 /* CALLS */
10583 /* */
10584 /* _nx_web_http_server_mime_maps_additional_set */
10585 /* */
10586 /* CALLED BY */
10587 /* */
10588 /* Application Code */
10589 /* */
10590 /* RELEASE HISTORY */
10591 /* */
10592 /* DATE NAME DESCRIPTION */
10593 /* */
10594 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10595 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10596 /* resulting in version 6.1 */
10597 /* */
10598 /**************************************************************************/
_nxe_web_http_server_mime_maps_additional_set(NX_WEB_HTTP_SERVER * server_ptr,NX_WEB_HTTP_SERVER_MIME_MAP * mime_maps,UINT mime_maps_num)10599 UINT _nxe_web_http_server_mime_maps_additional_set(NX_WEB_HTTP_SERVER *server_ptr, NX_WEB_HTTP_SERVER_MIME_MAP *mime_maps, UINT mime_maps_num)
10600 {
10601
10602 /* Check for invalid input pointers. */
10603 if ((server_ptr == NX_NULL) || (server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) || (mime_maps == NX_NULL))
10604 return(NX_PTR_ERROR);
10605
10606 /* Send internal. */
10607 return _nx_web_http_server_mime_maps_additional_set(server_ptr, mime_maps, mime_maps_num);
10608 }
10609
10610
10611 /**************************************************************************/
10612 /* */
10613 /* FUNCTION RELEASE */
10614 /* */
10615 /* _nx_web_http_server_mime_maps_additional_set PORTABLE C */
10616 /* 6.1 */
10617 /* AUTHOR */
10618 /* */
10619 /* Yuxin Zhou, Microsoft Corporation */
10620 /* */
10621 /* DESCRIPTION */
10622 /* */
10623 /* This function sets additional MIME maps. */
10624 /* */
10625 /* INPUT */
10626 /* */
10627 /* server_ptr Pointer to HTTP server */
10628 /* mime_maps Pointer MIME map array */
10629 /* mime_maps_num Number of MIME map array */
10630 /* */
10631 /* OUTPUT */
10632 /* */
10633 /* status Completion status */
10634 /* */
10635 /* CALLS */
10636 /* */
10637 /* */
10638 /* CALLED BY */
10639 /* */
10640 /* Application Code */
10641 /* */
10642 /* RELEASE HISTORY */
10643 /* */
10644 /* DATE NAME DESCRIPTION */
10645 /* */
10646 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10647 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10648 /* resulting in version 6.1 */
10649 /* */
10650 /**************************************************************************/
_nx_web_http_server_mime_maps_additional_set(NX_WEB_HTTP_SERVER * server_ptr,NX_WEB_HTTP_SERVER_MIME_MAP * mime_maps,UINT mime_maps_num)10651 UINT _nx_web_http_server_mime_maps_additional_set(NX_WEB_HTTP_SERVER *server_ptr, NX_WEB_HTTP_SERVER_MIME_MAP *mime_maps, UINT mime_maps_num)
10652 {
10653
10654 TX_INTERRUPT_SAVE_AREA
10655
10656 /* Lockout interrupts. */
10657 TX_DISABLE
10658
10659 /* Set the mime maps. */
10660 server_ptr -> nx_web_http_server_mime_maps_additional = mime_maps;
10661 server_ptr -> nx_web_http_server_mime_maps_additional_num = mime_maps_num;
10662
10663 /* Restore interrupts. */
10664 TX_RESTORE
10665
10666 return NX_SUCCESS;
10667 }
10668
10669 #ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE
10670 /**************************************************************************/
10671 /* */
10672 /* FUNCTION RELEASE */
10673 /* */
10674 /* _nx_web_http_server_get_client_keepalive PORTABLE C */
10675 /* 6.1 */
10676 /* AUTHOR */
10677 /* */
10678 /* Yuxin Zhou, Microsoft Corporation */
10679 /* */
10680 /* DESCRIPTION */
10681 /* */
10682 /* This function indicates whether this connection will keep alive. */
10683 /* */
10684 /* INPUT */
10685 /* */
10686 /* server_ptr Pointer to HTTP server */
10687 /* packet_ptr Pointer to packet */
10688 /* */
10689 /* OUTPUT */
10690 /* */
10691 /* None */
10692 /* */
10693 /* CALLS */
10694 /* */
10695 /* _nx_web_http_server_field_value_get Get field value */
10696 /* _nx_web_http_server_memicmp Compare two strings */
10697 /* _nx_utility_string_length_check Check string length */
10698 /* */
10699 /* CALLED BY */
10700 /* */
10701 /* _nx_web_http_server_receive_data */
10702 /* */
10703 /* RELEASE HISTORY */
10704 /* */
10705 /* DATE NAME DESCRIPTION */
10706 /* */
10707 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10708 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10709 /* resulting in version 6.1 */
10710 /* */
10711 /**************************************************************************/
_nx_web_http_server_get_client_keepalive(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)10712 VOID _nx_web_http_server_get_client_keepalive(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
10713 {
10714 UCHAR *ch;
10715 UINT version = 0;
10716 UCHAR connection_value[16];
10717 UINT connection_value_length;
10718
10719
10720 /* Locate to HTTP version. */
10721 ch = packet_ptr -> nx_packet_prepend_ptr;
10722 while(ch + 11 < packet_ptr -> nx_packet_append_ptr)
10723 {
10724 if((*ch == ' ') &&
10725 (*(ch + 1) == 'H') &&
10726 (*(ch + 2) == 'T') &&
10727 (*(ch + 3) == 'T') &&
10728 (*(ch + 4) == 'P') &&
10729 (*(ch + 5) == '/'))
10730 {
10731
10732 /* Find the HTTP version. */
10733 ch += 6;
10734 if((*ch >= '0') &&
10735 (*ch <= '9') &&
10736 (*(ch + 1) == '.') &&
10737 (*(ch + 2) >= '0') &&
10738 (*(ch + 2) <= '9'))
10739 {
10740
10741 /* Get the version. */
10742 version = (UCHAR)((*ch - '0') << 4) | (UCHAR)(*(ch + 2) - '0');
10743 }
10744
10745 break;
10746 }
10747 else if((*ch == 13) && (*(ch + 1) == 10))
10748 {
10749
10750 /* Find the end of line. */
10751 break;
10752 }
10753
10754 /* Move to the next byte. */
10755 ch++;
10756 }
10757
10758 /* Is a valid HTTP version found? */
10759 if(version == 0)
10760 {
10761 server_ptr -> nx_web_http_server_keepalive = NX_FALSE;
10762 return;
10763 }
10764
10765 /* Initialize the keepalive flag. */
10766 if(version > 0x10)
10767 server_ptr -> nx_web_http_server_keepalive = NX_TRUE;
10768 else
10769 server_ptr -> nx_web_http_server_keepalive = NX_FALSE;
10770
10771 /* Searching for 'connection' header. */
10772 if(_nx_web_http_server_field_value_get(packet_ptr, (UCHAR *)"connection", 10, connection_value, sizeof(connection_value)) == NX_SUCCESS)
10773 {
10774 _nx_utility_string_length_check((CHAR *)connection_value, &connection_value_length, sizeof(connection_value) - 1);
10775
10776 if(_nx_web_http_server_memicmp(connection_value, connection_value_length, (UCHAR *)"keep-alive", 10) == NX_SUCCESS)
10777 server_ptr -> nx_web_http_server_keepalive = NX_TRUE;
10778 else if(_nx_web_http_server_memicmp(connection_value, connection_value_length, (UCHAR *)"close", 5) == NX_SUCCESS)
10779 server_ptr -> nx_web_http_server_keepalive = NX_FALSE;
10780 }
10781 }
10782 #endif /* NX_WEB_HTTP_KEEPALIVE_DISABLE */
10783
10784 /**************************************************************************/
10785 /* */
10786 /* FUNCTION RELEASE */
10787 /* */
10788 /* _nx_web_http_server_send PORTABLE C */
10789 /* 6.1 */
10790 /* AUTHOR */
10791 /* */
10792 /* Yuxin Zhou, Microsoft Corporation */
10793 /* */
10794 /* DESCRIPTION */
10795 /* */
10796 /* This function sends data to the remote host using either the TCP */
10797 /* socket for plain HTTP or the TLS session for HTTPS. */
10798 /* */
10799 /* */
10800 /* INPUT */
10801 /* */
10802 /* server_ptr Pointer to HTTP server */
10803 /* packet_ptr Pointer to packet to send. */
10804 /* wait_option Indicates behavior if packet */
10805 /* cannot be sent. */
10806 /* */
10807 /* OUTPUT */
10808 /* */
10809 /* status Completion status */
10810 /* */
10811 /* CALLS */
10812 /* */
10813 /* nx_secure_tls_session_send Send data using TLS session */
10814 /* nx_secure_tcp_socket_send Send data using TCP socket */
10815 /* */
10816 /* CALLED BY */
10817 /* */
10818 /* */
10819 /* */
10820 /* RELEASE HISTORY */
10821 /* */
10822 /* DATE NAME DESCRIPTION */
10823 /* */
10824 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10825 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10826 /* resulting in version 6.1 */
10827 /* */
10828 /**************************************************************************/
_nx_web_http_server_send(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG wait_option)10829 UINT _nx_web_http_server_send(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
10830 {
10831
10832 UINT status;
10833 NX_TCP_SOCKET *tcp_socket;
10834 #ifdef NX_WEB_HTTPS_ENABLE
10835 NX_SECURE_TLS_SESSION *tls_session;
10836 #endif
10837
10838 tcp_socket = &(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket);
10839
10840 #ifdef NX_WEB_HTTPS_ENABLE
10841
10842 tls_session = &(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_tls_session);
10843
10844 /* End TLS session if using HTTPS. */
10845 if(server_ptr -> nx_web_http_is_https_server)
10846 {
10847 status = nx_secure_tls_session_send(tls_session, packet_ptr, wait_option);
10848 }
10849 else
10850 #endif
10851 {
10852 status = nx_tcp_socket_send(tcp_socket, packet_ptr, wait_option);
10853 }
10854
10855 /* Return status. */
10856 return(status);
10857 }
10858
10859
10860 /**************************************************************************/
10861 /* */
10862 /* FUNCTION RELEASE */
10863 /* */
10864 /* _nx_web_http_server_receive PORTABLE C */
10865 /* 6.1 */
10866 /* AUTHOR */
10867 /* */
10868 /* Yuxin Zhou, Microsoft Corporation */
10869 /* */
10870 /* DESCRIPTION */
10871 /* */
10872 /* This function receives data from the remote host using either the */
10873 /* TCP socket for plain HTTP or the TLS session for HTTPS. */
10874 /* */
10875 /* */
10876 /* INPUT */
10877 /* */
10878 /* server_ptr Pointer to HTTP server */
10879 /* packet_ptr Pointer to packet to send. */
10880 /* wait_option Indicates behavior if packet */
10881 /* cannot be received */
10882 /* */
10883 /* OUTPUT */
10884 /* */
10885 /* status Completion status */
10886 /* */
10887 /* CALLS */
10888 /* */
10889 /* nx_secure_tls_session_receive Receive data using TLS */
10890 /* nx_secure_tcp_socket_receive Receive data using TCP */
10891 /* */
10892 /* CALLED BY */
10893 /* */
10894 /* _nx_web_http_server_packet_get Get next packet from HTTP */
10895 /* server socket. */
10896 /* _nx_web_http_server_get_client_request */
10897 /* Get complete HTTP request */
10898 /* _nx_web_http_server_request_read Get the next data in byte */
10899 /* _nx_web_http_server_chunked_size_get Get chunk size of the request */
10900 /* */
10901 /* RELEASE HISTORY */
10902 /* */
10903 /* DATE NAME DESCRIPTION */
10904 /* */
10905 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10906 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10907 /* resulting in version 6.1 */
10908 /* */
10909 /**************************************************************************/
_nx_web_http_server_receive(NX_WEB_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)10910 UINT _nx_web_http_server_receive(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
10911 {
10912
10913 UINT status;
10914 NX_TCP_SOCKET *tcp_socket;
10915 #ifdef NX_WEB_HTTPS_ENABLE
10916 NX_SECURE_TLS_SESSION *tls_session;
10917 #endif
10918
10919 tcp_socket = &(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket);
10920
10921 #ifdef NX_WEB_HTTPS_ENABLE
10922 tls_session = &(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_tls_session);
10923
10924 /* End TLS session if using HTTPS. */
10925 if(server_ptr -> nx_web_http_is_https_server)
10926 {
10927 status = nx_secure_tls_session_receive(tls_session, packet_ptr, wait_option);
10928 }
10929 else
10930 #endif
10931 {
10932 status = nx_tcp_socket_receive(tcp_socket, packet_ptr, wait_option);
10933 }
10934
10935 /* Return status. */
10936 return(status);
10937 }
10938
10939
10940 /**************************************************************************/
10941 /* */
10942 /* FUNCTION RELEASE */
10943 /* */
10944 /* _nx_web_http_server_connection_reset PORTABLE C */
10945 /* 6.1 */
10946 /* AUTHOR */
10947 /* */
10948 /* Yuxin Zhou, Microsoft Corporation */
10949 /* */
10950 /* DESCRIPTION */
10951 /* */
10952 /* This function is used whenever the HTTP server needs to close the */
10953 /* network connection and reset to receive new requests. If the server */
10954 /* is using TLS for HTTPS, then it also ends the TLS session. */
10955 /* */
10956 /* */
10957 /* INPUT */
10958 /* */
10959 /* server_ptr Pointer to HTTP server */
10960 /* session_ptr Pointer to session */
10961 /* error_number Error status in caller */
10962 /* */
10963 /* OUTPUT */
10964 /* */
10965 /* status Completion status */
10966 /* */
10967 /* CALLS */
10968 /* */
10969 /* _nx_web_http_server_connection_disconnect */
10970 /* End TLS session, and calls */
10971 /* Disconnect and unaccept on the*/
10972 /* socket */
10973 /* _nx_tcp_server_socket_relisten Reset socket to accept another*/
10974 /* connection */
10975 /* */
10976 /* CALLED BY */
10977 /* */
10978 /* Application code */
10979 /* */
10980 /* RELEASE HISTORY */
10981 /* */
10982 /* DATE NAME DESCRIPTION */
10983 /* */
10984 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10985 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10986 /* resulting in version 6.1 */
10987 /* */
10988 /**************************************************************************/
_nx_web_http_server_connection_reset(NX_WEB_HTTP_SERVER * server_ptr,NX_TCP_SESSION * session_ptr,UINT wait_option)10989 VOID _nx_web_http_server_connection_reset(NX_WEB_HTTP_SERVER *server_ptr, NX_TCP_SESSION *session_ptr, UINT wait_option)
10990 {
10991 NX_TCP_SOCKET *tcp_socket;
10992
10993
10994 tcp_socket = &(session_ptr -> nx_tcp_session_socket);
10995
10996 /* Disconnect the server connection. */
10997 _nx_web_http_server_connection_disconnect(server_ptr, session_ptr, wait_option);
10998
10999 /* Relisten on the HTTP(S) Server port. */
11000 nx_tcp_server_socket_relisten(server_ptr -> nx_web_http_server_ip_ptr, server_ptr -> nx_web_http_server_listen_port, tcp_socket);
11001
11002 }
11003
11004
11005 /**************************************************************************/
11006 /* */
11007 /* FUNCTION RELEASE */
11008 /* */
11009 /* _nx_web_http_server_connection_disconnect PORTABLE C */
11010 /* 6.2.0 */
11011 /* AUTHOR */
11012 /* */
11013 /* Yuxin Zhou, Microsoft Corporation */
11014 /* */
11015 /* DESCRIPTION */
11016 /* */
11017 /* This function is used whenever the HTTP server needs to close the */
11018 /* network connection completely. If the server is using TLS for HTTPS */
11019 /* then it also ends the TLS session. */
11020 /* */
11021 /* */
11022 /* INPUT */
11023 /* */
11024 /* server_ptr Pointer to HTTP server */
11025 /* session_ptr Pointer to session */
11026 /* wait_option Wait option for TCP socket */
11027 /* */
11028 /* OUTPUT */
11029 /* */
11030 /* status Completion status */
11031 /* */
11032 /* CALLS */
11033 /* */
11034 /* _nx_secure_tls_session_end End TLS session */
11035 /* */
11036 /* CALLED BY */
11037 /* */
11038 /* */
11039 /* */
11040 /* RELEASE HISTORY */
11041 /* */
11042 /* DATE NAME DESCRIPTION */
11043 /* */
11044 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11045 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11046 /* resulting in version 6.1 */
11047 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
11048 /* supported random nonce, */
11049 /* resulting in version 6.2.0 */
11050 /* */
11051 /**************************************************************************/
_nx_web_http_server_connection_disconnect(NX_WEB_HTTP_SERVER * server_ptr,NX_TCP_SESSION * session_ptr,UINT wait_option)11052 VOID _nx_web_http_server_connection_disconnect(NX_WEB_HTTP_SERVER *server_ptr, NX_TCP_SESSION *session_ptr, UINT wait_option)
11053 {
11054 NX_TCP_SOCKET *tcp_socket;
11055 #ifdef NX_WEB_HTTPS_ENABLE
11056 NX_SECURE_TLS_SESSION *tls_session;
11057 #endif /* NX_WEB_HTTPS_ENABLE */
11058 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
11059 UINT i;
11060 #endif /* NX_WEB_HTTP_DIGEST_ENABLE */
11061
11062 #ifndef NX_WEB_HTTPS_ENABLE
11063 NX_PARAMETER_NOT_USED(server_ptr);
11064 NX_PARAMETER_NOT_USED(wait_option);
11065 #endif /* NX_WEB_HTTPS_ENABLE */
11066
11067 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
11068
11069 /* Once the nonce has been accepted, set the state as invalid. */
11070 for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++)
11071 {
11072 if ((server_ptr -> nx_web_http_server_nonces[i].nonce_state == NX_WEB_HTTP_SERVER_NONCE_ACCEPTED) &&
11073 (server_ptr -> nx_web_http_server_nonces[i].nonce_session_ptr == session_ptr))
11074 {
11075 server_ptr -> nx_web_http_server_nonces[i].nonce_state = NX_WEB_HTTP_SERVER_NONCE_INVALID;
11076 break;
11077 }
11078 }
11079 #endif /* NX_WEB_HTTP_DIGEST_ENABLE */
11080
11081 tcp_socket = &(session_ptr -> nx_tcp_session_socket);
11082
11083 #ifdef NX_WEB_HTTPS_ENABLE
11084
11085 tls_session = &(session_ptr -> nx_tcp_session_tls_session);
11086
11087 /* End TLS session if using HTTPS. */
11088 if(server_ptr -> nx_web_http_is_https_server)
11089 {
11090 _nx_secure_tls_session_end(tls_session, wait_option);
11091 }
11092 #endif
11093
11094 /* Disconnect from the current connection. */
11095 nx_tcp_socket_disconnect(tcp_socket, NX_WEB_HTTP_SERVER_TIMEOUT_DISCONNECT);
11096
11097 /* Unaccept the connection. */
11098 nx_tcp_server_socket_unaccept(tcp_socket);
11099
11100 }
11101
11102
11103 /**************************************************************************/
11104 /* */
11105 /* FUNCTION RELEASE */
11106 /* */
11107 /* _nxe_web_http_server_digest_authenticate_notify_set PORTABLE C */
11108 /* 6.1 */
11109 /* AUTHOR */
11110 /* */
11111 /* Yuxin Zhou, Microsoft Corporation */
11112 /* */
11113 /* DESCRIPTION */
11114 /* */
11115 /* This function performs error checking for service to set digest */
11116 /* authenticate callback function. */
11117 /* */
11118 /* INPUT */
11119 /* */
11120 /* http_server_ptr Pointer to HTTP server */
11121 /* digest_authenticate_callback Pointer to application's */
11122 /* digest authenticate callback */
11123 /* function */
11124 /* */
11125 /* OUTPUT */
11126 /* */
11127 /* status Completion status */
11128 /* */
11129 /* CALLS */
11130 /* */
11131 /* _nx_web_http_server_digest_authenticate_notify_set */
11132 /* */
11133 /* CALLED BY */
11134 /* */
11135 /* Application Code */
11136 /* */
11137 /* RELEASE HISTORY */
11138 /* */
11139 /* DATE NAME DESCRIPTION */
11140 /* */
11141 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11142 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11143 /* resulting in version 6.1 */
11144 /* */
11145 /**************************************************************************/
_nxe_web_http_server_digest_authenticate_notify_set(NX_WEB_HTTP_SERVER * http_server_ptr,UINT (* digest_authenticate_callback)(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name_ptr,CHAR * realm_ptr,CHAR * password_ptr,CHAR * method,CHAR * authorization_uri,CHAR * authorization_nc,CHAR * authorization_cnonce))11146 UINT _nxe_web_http_server_digest_authenticate_notify_set(NX_WEB_HTTP_SERVER *http_server_ptr,
11147 UINT (*digest_authenticate_callback)(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name_ptr,
11148 CHAR *realm_ptr, CHAR *password_ptr, CHAR *method,
11149 CHAR *authorization_uri, CHAR *authorization_nc,
11150 CHAR *authorization_cnonce))
11151 {
11152
11153 /* Check for invalid input pointers. */
11154 if ((http_server_ptr == NX_NULL) || (digest_authenticate_callback == NX_NULL))
11155 {
11156 return(NX_PTR_ERROR);
11157 }
11158
11159 return(_nx_web_http_server_digest_authenticate_notify_set(http_server_ptr, digest_authenticate_callback));
11160 }
11161
11162
11163 /**************************************************************************/
11164 /* */
11165 /* FUNCTION RELEASE */
11166 /* */
11167 /* _nx_web_http_server_digest_authenticate_notify_set PORTABLE C */
11168 /* 6.1 */
11169 /* AUTHOR */
11170 /* */
11171 /* Yuxin Zhou, Microsoft Corporation */
11172 /* */
11173 /* DESCRIPTION */
11174 /* */
11175 /* This function sets digest authenticate callback function. */
11176 /* */
11177 /* Note: The strings name_ptr, realm_ptr, password_ptr, method, */
11178 /* authorization_uri, authorization_nc and authorization_cnonce in */
11179 /* callback function digest_authenticate_callback is built by internal */
11180 /* logic and always NULL-terminated. */
11181 /* */
11182 /* */
11183 /* INPUT */
11184 /* */
11185 /* http_server_ptr Pointer to HTTP server */
11186 /* digest_authenticate_callback Pointer to application's */
11187 /* digest authenticate callback */
11188 /* function */
11189 /* */
11190 /* OUTPUT */
11191 /* */
11192 /* status Completion status */
11193 /* */
11194 /* CALLS */
11195 /* */
11196 /* None */
11197 /* */
11198 /* CALLED BY */
11199 /* */
11200 /* Application Code */
11201 /* */
11202 /* RELEASE HISTORY */
11203 /* */
11204 /* DATE NAME DESCRIPTION */
11205 /* */
11206 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11207 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11208 /* resulting in version 6.1 */
11209 /* */
11210 /**************************************************************************/
_nx_web_http_server_digest_authenticate_notify_set(NX_WEB_HTTP_SERVER * http_server_ptr,UINT (* digest_authenticate_callback)(NX_WEB_HTTP_SERVER * server_ptr,CHAR * name_ptr,CHAR * realm_ptr,CHAR * password_ptr,CHAR * method,CHAR * authorization_uri,CHAR * authorization_nc,CHAR * authorization_cnonce))11211 UINT _nx_web_http_server_digest_authenticate_notify_set(NX_WEB_HTTP_SERVER *http_server_ptr,
11212 UINT (*digest_authenticate_callback)(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name_ptr,
11213 CHAR *realm_ptr, CHAR *password_ptr, CHAR *method,
11214 CHAR *authorization_uri, CHAR *authorization_nc,
11215 CHAR *authorization_cnonce))
11216 {
11217
11218 #ifdef NX_WEB_HTTP_DIGEST_ENABLE
11219 http_server_ptr -> nx_web_http_server_digest_authenticate_callback = digest_authenticate_callback;
11220
11221 return(NX_SUCCESS);
11222 #else
11223 NX_PARAMETER_NOT_USED(http_server_ptr);
11224 NX_PARAMETER_NOT_USED(digest_authenticate_callback);
11225
11226 return(NX_NOT_SUPPORTED);
11227 #endif
11228 }
11229
11230
11231 /**************************************************************************/
11232 /* */
11233 /* FUNCTION RELEASE */
11234 /* */
11235 /* _nxe_web_http_server_authentication_check_set PORTABLE C */
11236 /* 6.1 */
11237 /* AUTHOR */
11238 /* */
11239 /* Yuxin Zhou, Microsoft Corporation */
11240 /* */
11241 /* DESCRIPTION */
11242 /* */
11243 /* This function checks errors for setting authentication checking */
11244 /* callback function. */
11245 /* */
11246 /* */
11247 /* INPUT */
11248 /* */
11249 /* http_server_ptr Pointer to HTTP server */
11250 /* authentication_check_extended Pointer to application's */
11251 /* authentication checking */
11252 /* */
11253 /* OUTPUT */
11254 /* */
11255 /* status Completion status */
11256 /* */
11257 /* CALLS */
11258 /* */
11259 /* _nx_http_server_authentication_check_set */
11260 /* Set authentication callback */
11261 /* */
11262 /* CALLED BY */
11263 /* */
11264 /* Application Code */
11265 /* */
11266 /* RELEASE HISTORY */
11267 /* */
11268 /* DATE NAME DESCRIPTION */
11269 /* */
11270 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11271 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11272 /* resulting in version 6.1 */
11273 /* */
11274 /**************************************************************************/
_nxe_web_http_server_authentication_check_set(NX_WEB_HTTP_SERVER * http_server_ptr,UINT (* authentication_check_extended)(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,UINT * name_length,CHAR ** password,UINT * password_length,CHAR ** realm,UINT * realm_length))11275 UINT _nxe_web_http_server_authentication_check_set(NX_WEB_HTTP_SERVER *http_server_ptr,
11276 UINT (*authentication_check_extended)(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, UINT *name_length, CHAR **password, UINT *password_length, CHAR **realm, UINT *realm_length))
11277 {
11278 UINT status;
11279
11280 /* Check for invalid input pointers. */
11281 if ((http_server_ptr == NX_NULL) || (authentication_check_extended == NX_NULL))
11282 {
11283 return(NX_PTR_ERROR);
11284 }
11285
11286 /* Check for appropriate caller. */
11287 NX_THREADS_ONLY_CALLER_CHECKING
11288
11289 /* Call the actual authentication checking set function. */
11290 status= _nx_web_http_server_authentication_check_set(http_server_ptr, authentication_check_extended);
11291
11292 /* Return staus. */
11293 return(status);
11294 }
11295
11296
11297 /**************************************************************************/
11298 /* */
11299 /* FUNCTION RELEASE */
11300 /* */
11301 /* _nx_web_http_server_authentication_check_set PORTABLE C */
11302 /* 6.1 */
11303 /* AUTHOR */
11304 /* */
11305 /* Yuxin Zhou, Microsoft Corporation */
11306 /* */
11307 /* DESCRIPTION */
11308 /* */
11309 /* This function sets the callback function of authentication checking.*/
11310 /* */
11311 /* Note: The strings of name, password and realm must be */
11312 /* NULL-terminated and length of each string matches the length */
11313 /* specified in the argument list. The string resource in callback */
11314 /* function authentication_check and request_notify is built by */
11315 /* internal logic and always NULL-terminated. */
11316 /* */
11317 /* */
11318 /* INPUT */
11319 /* */
11320 /* http_server_ptr Pointer to HTTP server */
11321 /* authentication_check_extended Pointer to application's */
11322 /* authentication checking */
11323 /* */
11324 /* OUTPUT */
11325 /* */
11326 /* status Completion status */
11327 /* */
11328 /* CALLS */
11329 /* */
11330 /* None */
11331 /* */
11332 /* CALLED BY */
11333 /* */
11334 /* Application Code */
11335 /* */
11336 /* RELEASE HISTORY */
11337 /* */
11338 /* DATE NAME DESCRIPTION */
11339 /* */
11340 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11341 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11342 /* resulting in version 6.1 */
11343 /* */
11344 /**************************************************************************/
_nx_web_http_server_authentication_check_set(NX_WEB_HTTP_SERVER * http_server_ptr,UINT (* authentication_check_extended)(NX_WEB_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,UINT * name_length,CHAR ** password,UINT * password_length,CHAR ** realm,UINT * realm_length))11345 UINT _nx_web_http_server_authentication_check_set(NX_WEB_HTTP_SERVER *http_server_ptr,
11346 UINT (*authentication_check_extended)(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, UINT *name_length, CHAR **password, UINT *password_length, CHAR **realm, UINT *realm_length))
11347 {
11348
11349 /* Set the extended authentication checking function. */
11350 http_server_ptr -> nx_web_http_server_authentication_check_extended = authentication_check_extended;
11351
11352 /* Return success. */
11353 return(NX_SUCCESS);
11354 }