1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Hypertext Transfer Protocol (HTTP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_HTTP_SOURCE_CODE
23
24
25 /* Force error checking to be disabled in this module */
26
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif
30
31 /* Include necessary system files. */
32
33 #include "nx_api.h"
34 #include "nx_ip.h"
35 #include "nxd_http_server.h"
36 #include "stdio.h"
37 #include "string.h"
38 #ifdef NX_HTTP_DIGEST_ENABLE
39 #include "nx_md5.h"
40 #endif
41
42 #ifdef NX_HTTP_DIGEST_ENABLE
43
44 /* Use for mapping random nonces to printable characters. */
45 static CHAR _nx_http_server_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
46 #endif
47
48 /* Define date strings. */
49 const CHAR *_nx_http_server_weekday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
50 const CHAR *_nx_http_server_month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
51
52 /* Define basic MIME maps. */
53 static NX_HTTP_SERVER_MIME_MAP _nx_http_server_mime_maps[] =
54 {
55 {"html", "text/html"},
56 {"htm", "text/html"},
57 {"txt", "text/plain"},
58 {"gif", "image/gif"},
59 {"jpg", "image/jpeg"},
60 {"ico", "image/x-icon"},
61 };
62
63
64 /* Create two arrays to hold encoded and decoded username/password data. */
65 static CHAR authorization_request[NX_HTTP_MAX_STRING + 1];
66 static CHAR authorization_decoded[NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 2];
67
68 /* Bring in externs for caller checking code. */
69
70 NX_CALLER_CHECKING_EXTERNS
71
72
73 /**************************************************************************/
74 /* */
75 /* FUNCTION RELEASE */
76 /* */
77 /* _nxe_http_server_content_get PORTABLE C */
78 /* 6.1 */
79 /* AUTHOR */
80 /* */
81 /* Yuxin Zhou, Microsoft Corporation */
82 /* */
83 /* DESCRIPTION */
84 /* */
85 /* This function checks for errors in the HTTP content get call. */
86 /* */
87 /* */
88 /* INPUT */
89 /* */
90 /* server_ptr Pointer to HTTP server */
91 /* packet_ptr Pointer to HTTP request packet*/
92 /* byte_offset Byte offset into content */
93 /* destination_ptr Pointer to content destination*/
94 /* destination_size Maximum size of destination */
95 /* actual_size Actual amount of content */
96 /* */
97 /* OUTPUT */
98 /* */
99 /* status Completion status */
100 /* */
101 /* CALLS */
102 /* */
103 /* _nx_http_server_content_get Actual server content get call*/
104 /* */
105 /* CALLED BY */
106 /* */
107 /* Application Code */
108 /* */
109 /* RELEASE HISTORY */
110 /* */
111 /* DATE NAME DESCRIPTION */
112 /* */
113 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
114 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
115 /* resulting in version 6.1 */
116 /* */
117 /**************************************************************************/
_nxe_http_server_content_get(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)118 UINT _nxe_http_server_content_get(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset, CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
119 {
120
121 UINT status;
122
123
124 /* Check for invalid input pointers. */
125 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
126 (packet_ptr == NX_NULL) || (destination_ptr == NX_NULL) || (actual_size == NX_NULL))
127 return(NX_PTR_ERROR);
128
129 /* Check for appropriate caller. */
130 NX_THREADS_ONLY_CALLER_CHECKING
131
132 /* Call actual server content get function. */
133 status = _nx_http_server_content_get(server_ptr, packet_ptr, byte_offset, destination_ptr, destination_size, actual_size);
134
135 /* Return completion status. */
136 return(status);
137 }
138
139
140 /**************************************************************************/
141 /* */
142 /* FUNCTION RELEASE */
143 /* */
144 /* _nx_http_server_content_get PORTABLE C */
145 /* 6.1 */
146 /* AUTHOR */
147 /* */
148 /* Yuxin Zhou, Microsoft Corporation */
149 /* */
150 /* DESCRIPTION */
151 /* */
152 /* This function returns the user's specified portion of the HTTP */
153 /* content. Content is typically included in POST and PUT requests */
154 /* from the client. This routine is designed to be called from the */
155 /* application's request notify callback. */
156 /* */
157 /* */
158 /* INPUT */
159 /* */
160 /* server_ptr Pointer to HTTP server */
161 /* packet_ptr Pointer to HTTP request packet*/
162 /* byte_offset Byte offset into content */
163 /* destination_ptr Pointer to content destination*/
164 /* destination_size Maximum size of destination */
165 /* actual_size Actual amount of content */
166 /* */
167 /* OUTPUT */
168 /* */
169 /* status Completion status */
170 /* */
171 /* CALLS */
172 /* */
173 /* nx_tcp_socket_receive Receive another packet */
174 /* _nx_http_server_content_length_get Pickup the content length */
175 /* _nx_http_server_calculate_content_offset Pickup content offset */
176 /* */
177 /* CALLED BY */
178 /* */
179 /* Application Code */
180 /* */
181 /* RELEASE HISTORY */
182 /* */
183 /* DATE NAME DESCRIPTION */
184 /* */
185 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
186 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
187 /* resulting in version 6.1 */
188 /* */
189 /**************************************************************************/
_nx_http_server_content_get(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)190 UINT _nx_http_server_content_get(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset, CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
191 {
192
193 ULONG content_length;
194 ULONG get_offset;
195 ULONG offset;
196 #ifndef NX_DISABLE_PACKET_CHAIN
197 UINT status;
198 #endif /* NX_DISABLE_PACKET_CHAIN */
199 UINT remaining_bytes;
200 NX_PACKET *new_packet_ptr;
201 CHAR *buffer_ptr;
202
203
204 /* Default the actual size to zero. */
205 *actual_size = 0;
206
207 /* Determine if there is content in this HTTP request. */
208 content_length = (ULONG) _nx_http_server_content_length_get(packet_ptr);
209
210 /* Make sure the content length is at least greater than the byte offset supplied. */
211 if (content_length <= byte_offset)
212 {
213
214 /* No more data in this buffer. */
215 return(NX_HTTP_DATA_END);
216 }
217
218 /* Determine if the destination size is greater than the content length. */
219 if (destination_size > content_length)
220 {
221
222 /* Yes, make the destination size equal to the content length. */
223 destination_size = content_length;
224 }
225
226 /* Calculate the offset to the requested content area. */
227 get_offset = ((ULONG) _nx_http_server_calculate_content_offset(packet_ptr)) + byte_offset;
228
229 /* Determine if we need to read one or more additional packets. */
230 while (get_offset >= packet_ptr -> nx_packet_length)
231 {
232
233 #ifdef NX_DISABLE_PACKET_CHAIN
234 NX_PARAMETER_NOT_USED(server_ptr);
235
236 return NX_HTTP_ERROR;
237 #else
238 /* Read another packet because the offset reaches past the current packet
239 length. */
240 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
241
242 /* Check the return status. */
243 if (status != NX_SUCCESS)
244 {
245
246 /* Error, return to caller. */
247 return(NX_HTTP_TIMEOUT);
248 }
249
250 /* Otherwise, we have a new packet to append to the head packet. */
251
252 /* Determine if the current packet is already chained. */
253 if (packet_ptr -> nx_packet_next)
254 {
255
256 /* Yes, link the current last packet to the new packet. */
257 (packet_ptr -> nx_packet_last) -> nx_packet_next = new_packet_ptr;
258 }
259 else
260 {
261
262 /* Otherwise, this is our first chained packet. Link to the head. */
263 packet_ptr -> nx_packet_next = new_packet_ptr;
264 }
265
266 /* Is the new packet chained? */
267 if (new_packet_ptr -> nx_packet_next)
268 {
269
270 /* Yes, there is a last packet pointer. Point to this from the head packet. */
271 packet_ptr -> nx_packet_last = new_packet_ptr -> nx_packet_last;
272 }
273 else
274 {
275
276 /* No, there isn't a last packet pointer. Point to new packet from the head packet. */
277 packet_ptr -> nx_packet_last = new_packet_ptr;
278 }
279
280 /* Update the packet length. */
281 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + new_packet_ptr -> nx_packet_length;
282 #endif /* NX_DISABLE_PACKET_CHAIN */
283 }
284
285 /* Default the buffer pointer to NULL. */
286 buffer_ptr = NX_NULL;
287
288 /* Now find the packet that contains the offset. */
289 offset = 0;
290 new_packet_ptr = packet_ptr;
291 do
292 {
293
294 /* Determine if the get request falls into this packet. */
295 if (get_offset < (offset + (ULONG)(new_packet_ptr -> nx_packet_append_ptr - new_packet_ptr -> nx_packet_prepend_ptr)))
296 {
297
298 /* Yes, the get offset is in this packet. */
299
300 /* Setup the starting byte pointer. */
301 buffer_ptr = ((CHAR *) new_packet_ptr -> nx_packet_prepend_ptr) + (get_offset - offset);
302 break;
303 }
304
305 /* Otherwise update the offset. */
306 offset = offset + (ULONG)(new_packet_ptr -> nx_packet_append_ptr - new_packet_ptr -> nx_packet_prepend_ptr);
307
308 #ifdef NX_DISABLE_PACKET_CHAIN
309 new_packet_ptr = NX_NULL;
310 #else
311 /* Move to next packet in the chain. */
312 new_packet_ptr = new_packet_ptr -> nx_packet_next;
313 #endif /* NX_DISABLE_PACKET_CHAIN */
314
315 } while (new_packet_ptr);
316
317 /* Determine if an error occurred in the search. */
318 if ((buffer_ptr == (CHAR *) NX_NULL) || (new_packet_ptr == NX_NULL))
319 return(NX_HTTP_ERROR);
320
321 /* Now determine if the maximum buffer size has to be adjusted. */
322 if (destination_size > (UINT) (new_packet_ptr -> nx_packet_append_ptr - (UCHAR *) buffer_ptr))
323 {
324
325 /* Adjust the destination size downward. */
326 destination_size = (UINT) (new_packet_ptr -> nx_packet_append_ptr - (UCHAR *) buffer_ptr);
327 }
328
329 /* Initialize the remaining bytes. */
330 remaining_bytes = destination_size;
331
332 /* Otherwise copy the bytes from the offset to the end of the packet pointer. */
333 while (remaining_bytes--)
334 {
335
336 /* Copy a byte to the destination. */
337 *destination_ptr++ = *buffer_ptr++;
338 }
339
340 /* Successful completion. */
341 *actual_size = destination_size;
342 return(NX_SUCCESS);
343 }
344
345
346
347
348 /**************************************************************************/
349 /* */
350 /* FUNCTION RELEASE */
351 /* */
352 /* _nxe_http_server_packet_content_find PORTABLE C */
353 /* 6.1 */
354 /* AUTHOR */
355 /* */
356 /* Yuxin Zhou, Microsoft Corporation */
357 /* */
358 /* DESCRIPTION */
359 /* */
360 /* This function checks for errors in the HTTP packet content find */
361 /* call. */
362 /* */
363 /* */
364 /* INPUT */
365 /* */
366 /* server_ptr Pointer to HTTP server */
367 /* packet_ptr Pointer to pointer to the */
368 /* packet that contains the */
369 /* HTTP header */
370 /* content_length Pointer to content length */
371 /* */
372 /* OUTPUT */
373 /* */
374 /* status Completion status */
375 /* */
376 /* CALLS */
377 /* */
378 /* _nx_http_server_packet_content_find Actual server packet content */
379 /* find call */
380 /* */
381 /* CALLED BY */
382 /* */
383 /* Application Code */
384 /* */
385 /* RELEASE HISTORY */
386 /* */
387 /* DATE NAME DESCRIPTION */
388 /* */
389 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
390 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
391 /* resulting in version 6.1 */
392 /* */
393 /**************************************************************************/
_nxe_http_server_packet_content_find(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,ULONG * content_length)394 UINT _nxe_http_server_packet_content_find(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG *content_length)
395 {
396
397
398 /* Check for invalid packet pointer. */
399 if((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
400 (packet_ptr == NX_NULL) || (*packet_ptr == NX_NULL))
401 return(NX_PTR_ERROR);
402
403 /* Call actual server content length get function. */
404 return(_nx_http_server_packet_content_find(server_ptr, packet_ptr, content_length));
405
406 }
407
408 /**************************************************************************/
409 /* */
410 /* FUNCTION RELEASE */
411 /* */
412 /* _nx_http_server_packet_content_find PORTABLE C */
413 /* 6.1 */
414 /* AUTHOR */
415 /* */
416 /* Yuxin Zhou, Microsoft Corporation */
417 /* */
418 /* DESCRIPTION */
419 /* */
420 /* This function finds the content length specified in the HTTP */
421 /* header, and move the nx_packet_prepend_ptr to the beginning of */
422 /* the content. If the beginning of the content is not in the packet, */
423 /* this function attempts to read the HTTP server socket for the */
424 /* next packet. */
425 /* */
426 /* */
427 /* INPUT */
428 /* */
429 /* server_ptr Pointer to HTTP server */
430 /* packet_ptr Pointer to pointer to the */
431 /* packet that contains the */
432 /* HTTP header */
433 /* content_length Pointer to content length */
434 /* */
435 /* OUTPUT */
436 /* */
437 /* status Completion status */
438 /* */
439 /* CALLS */
440 /* */
441 /* nx_tcp_socket_receive Receive another packet */
442 /* _nx_http_server_calculate_content_offset Pickup content offset */
443 /* nx_packet_release Release the packet */
444 /* */
445 /* CALLED BY */
446 /* */
447 /* Application Code */
448 /* */
449 /* RELEASE HISTORY */
450 /* */
451 /* DATE NAME DESCRIPTION */
452 /* */
453 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
454 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
455 /* resulting in version 6.1 */
456 /* */
457 /**************************************************************************/
_nx_http_server_packet_content_find(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr,ULONG * content_length)458 UINT _nx_http_server_packet_content_find(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG *content_length)
459 {
460
461 ULONG get_offset;
462 UINT status;
463
464 /* Determine if there is content in this HTTP request. */
465 if(content_length)
466 *content_length = (ULONG) _nx_http_server_content_length_get(*packet_ptr);
467
468
469 get_offset = (ULONG)_nx_http_server_calculate_content_offset(*packet_ptr);
470
471 while((*packet_ptr) -> nx_packet_length <= get_offset)
472 {
473 /* Data is not present in this packet. So we have to read the next packet from the socket. */
474 get_offset -= (*packet_ptr) -> nx_packet_length;
475
476 /* Release this packet. */
477 nx_packet_release(*packet_ptr);
478
479 /* Make the receive call to obtain the next packet. */
480 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
481
482 if(status != NX_SUCCESS)
483 {
484 return(NX_HTTP_TIMEOUT);
485 }
486
487 }
488
489 (*packet_ptr) -> nx_packet_prepend_ptr += get_offset;
490 (*packet_ptr) -> nx_packet_length -= get_offset;
491
492
493 return(NX_SUCCESS);
494 }
495
496
497 /**************************************************************************/
498 /* */
499 /* FUNCTION RELEASE */
500 /* */
501 /* _nxe_http_server_packet_get PORTABLE C */
502 /* 6.1 */
503 /* AUTHOR */
504 /* */
505 /* Yuxin Zhou, Microsoft Corporation */
506 /* */
507 /* DESCRIPTION */
508 /* */
509 /* This function checks for errors in the HTTP server packet get call. */
510 /* */
511 /* */
512 /* INPUT */
513 /* */
514 /* server_ptr Pointer to HTTP server */
515 /* packet_ptr Pointer to the packet to */
516 /* be returned. */
517 /* */
518 /* OUTPUT */
519 /* */
520 /* status Completion status */
521 /* */
522 /* CALLS */
523 /* */
524 /* _nx_http_server_packet_get Actual server packet get call */
525 /* */
526 /* CALLED BY */
527 /* */
528 /* Application Code */
529 /* */
530 /* RELEASE HISTORY */
531 /* */
532 /* DATE NAME DESCRIPTION */
533 /* */
534 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
535 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
536 /* resulting in version 6.1 */
537 /* */
538 /**************************************************************************/
_nxe_http_server_packet_get(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr)539 UINT _nxe_http_server_packet_get(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr)
540 {
541
542
543 /* Check for invalid packet pointer. */
544 if((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
545 (packet_ptr == NX_NULL))
546 return(NX_PTR_ERROR);
547
548 /* Call actual server content length get function. */
549 return(_nx_http_server_packet_get(server_ptr, packet_ptr));
550
551 }
552
553
554 /**************************************************************************/
555 /* */
556 /* FUNCTION RELEASE */
557 /* */
558 /* _nx_http_server_packet_get PORTABLE C */
559 /* 6.1 */
560 /* AUTHOR */
561 /* */
562 /* Yuxin Zhou, Microsoft Corporation */
563 /* */
564 /* DESCRIPTION */
565 /* */
566 /* This function obtains the next packet from the HTTP server socket. */
567 /* */
568 /* */
569 /* INPUT */
570 /* */
571 /* server_ptr Pointer to HTTP server */
572 /* packet_ptr Pointer to the packet to */
573 /* be returned. */
574 /* */
575 /* OUTPUT */
576 /* */
577 /* status Completion status */
578 /* */
579 /* CALLS */
580 /* */
581 /* nx_tcp_socket_receive Receive another packet */
582 /* nx_packet_release Packet release */
583 /* */
584 /* CALLED BY */
585 /* */
586 /* Application Code */
587 /* */
588 /* RELEASE HISTORY */
589 /* */
590 /* DATE NAME DESCRIPTION */
591 /* */
592 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
593 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
594 /* resulting in version 6.1 */
595 /* */
596 /**************************************************************************/
_nx_http_server_packet_get(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr)597 UINT _nx_http_server_packet_get(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr)
598 {
599 NX_PACKET *new_packet_ptr;
600 UINT status;
601
602 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
603
604 /* Check the return status. */
605 if (status != NX_SUCCESS)
606 {
607
608 /* Error, return to caller. */
609 return(NX_HTTP_TIMEOUT);
610 }
611
612 *packet_ptr = new_packet_ptr;
613
614 return(NX_SUCCESS);
615
616 }
617
618
619 /**************************************************************************/
620 /* */
621 /* FUNCTION RELEASE */
622 /* */
623 /* _nxe_http_server_content_length_get PORTABLE C */
624 /* 6.1 */
625 /* AUTHOR */
626 /* */
627 /* Yuxin Zhou, Microsoft Corporation */
628 /* */
629 /* DESCRIPTION */
630 /* */
631 /* This function checks for errors in the HTTP content length get */
632 /* call. */
633 /* */
634 /* */
635 /* INPUT */
636 /* */
637 /* packet_ptr Pointer to HTTP request packet*/
638 /* */
639 /* OUTPUT */
640 /* */
641 /* status Completion status */
642 /* */
643 /* CALLS */
644 /* */
645 /* _nx_http_server_content_length_get Actual server content length */
646 /* call */
647 /* */
648 /* CALLED BY */
649 /* */
650 /* Application Code */
651 /* */
652 /* RELEASE HISTORY */
653 /* */
654 /* DATE NAME DESCRIPTION */
655 /* */
656 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
657 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
658 /* resulting in version 6.1 */
659 /* */
660 /**************************************************************************/
_nxe_http_server_content_length_get(NX_PACKET * packet_ptr)661 UINT _nxe_http_server_content_length_get(NX_PACKET *packet_ptr)
662 {
663
664 UINT length;
665
666 /* Check for invalid packet pointer. */
667 if (packet_ptr == NX_NULL)
668 return(0);
669
670 /* Call actual server content length get function. */
671 length = _nx_http_server_content_length_get(packet_ptr);
672
673 /* Return the length. */
674 return(length);
675 }
676
677
678 /**************************************************************************/
679 /* */
680 /* FUNCTION RELEASE */
681 /* */
682 /* _nx_http_server_content_length_get PORTABLE C */
683 /* 6.1 */
684 /* AUTHOR */
685 /* */
686 /* Yuxin Zhou, Microsoft Corporation */
687 /* */
688 /* DESCRIPTION */
689 /* */
690 /* This function returns the content length of the supplied HTTP */
691 /* request packet. If the packet is no content or the packet is */
692 /* invalid, a zero is returned. */
693 /* */
694 /* */
695 /* INPUT */
696 /* */
697 /* packet_ptr Pointer to HTTP request packet*/
698 /* */
699 /* OUTPUT */
700 /* */
701 /* length Length of content */
702 /* */
703 /* CALLS */
704 /* */
705 /* None */
706 /* */
707 /* CALLED BY */
708 /* */
709 /* Application Code */
710 /* */
711 /* RELEASE HISTORY */
712 /* */
713 /* DATE NAME DESCRIPTION */
714 /* */
715 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
716 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
717 /* resulting in version 6.1 */
718 /* */
719 /**************************************************************************/
_nx_http_server_content_length_get(NX_PACKET * packet_ptr)720 UINT _nx_http_server_content_length_get(NX_PACKET *packet_ptr)
721 {
722
723 UINT length;
724 CHAR *buffer_ptr;
725
726
727 /* Default the content length to zero. */
728 length = 0;
729
730 /* Setup pointer to buffer. */
731 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
732
733 /* Find the "Content-length: " token first. */
734 while (((buffer_ptr+17) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
735 {
736
737 /* Check for the Content-length token. */
738 if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) &&
739 ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) &&
740 ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) &&
741 ((*(buffer_ptr+3) == 't') || (*(buffer_ptr+3) == 'T')) &&
742 ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) &&
743 ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) &&
744 ((*(buffer_ptr+6) == 't') || (*(buffer_ptr+6) == 'T')) &&
745 (*(buffer_ptr+7) == '-') &&
746 ((*(buffer_ptr+8) == 'l') || (*(buffer_ptr+8) == 'L')) &&
747 ((*(buffer_ptr+9) == 'e') || (*(buffer_ptr+9) == 'E')) &&
748 ((*(buffer_ptr+10) == 'n') || (*(buffer_ptr+10) == 'N')) &&
749 ((*(buffer_ptr+11) == 'g') || (*(buffer_ptr+11) == 'G')) &&
750 ((*(buffer_ptr+12) == 't') || (*(buffer_ptr+12) == 'T')) &&
751 ((*(buffer_ptr+13) == 'h') || (*(buffer_ptr+13) == 'H')) &&
752 (*(buffer_ptr+14) == ':') &&
753 (*(buffer_ptr+15) == ' '))
754 {
755
756 /* Move the pointer up to the length token. */
757 buffer_ptr = buffer_ptr + 16;
758 break;
759 }
760
761 /* Move the pointer up to the next character. */
762 buffer_ptr++;
763 }
764
765 /* Now convert the length into a numeric value. */
766 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
767 {
768
769 /* Update the content length. */
770 length = length * 10;
771 length = length + (((UINT) (*buffer_ptr)) - 0x30);
772
773 /* Move the buffer pointer forward. */
774 buffer_ptr++;
775 }
776
777 /* Determine if the content length was picked up properly. */
778 if ((*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13))
779 {
780
781 /* Error, set the length to zero. */
782 length = 0;
783 }
784
785 /* Return the length to the caller. */
786 return(length);
787 }
788 /**************************************************************************/
789 /* */
790 /* FUNCTION RELEASE */
791 /* */
792 /* _nxe_http_server_content_get_extended PORTABLE C */
793 /* 6.1 */
794 /* AUTHOR */
795 /* */
796 /* Yuxin Zhou, Microsoft Corporation */
797 /* */
798 /* DESCRIPTION */
799 /* */
800 /* This function checks for errors in the HTTP extended get content */
801 /* service. */
802 /* */
803 /* */
804 /* INPUT */
805 /* */
806 /* server_ptr Pointer to HTTP server */
807 /* packet_ptr Pointer to HTTP request packet*/
808 /* byte_offset Byte offset into content */
809 /* destination_ptr Pointer to content destination*/
810 /* destination_size Maximum size of destination */
811 /* actual_size Actual amount of content */
812 /* */
813 /* OUTPUT */
814 /* */
815 /* status Completion status */
816 /* */
817 /* CALLS */
818 /* */
819 /* _nx_http_server_content_get_extended Actual extended get content */
820 /* get service */
821 /* */
822 /* CALLED BY */
823 /* */
824 /* Application Code */
825 /* */
826 /* RELEASE HISTORY */
827 /* */
828 /* DATE NAME DESCRIPTION */
829 /* */
830 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
831 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
832 /* resulting in version 6.1 */
833 /* */
834 /**************************************************************************/
_nxe_http_server_content_get_extended(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)835 UINT _nxe_http_server_content_get_extended(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset,
836 CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
837 {
838
839 UINT status;
840
841
842 /* Check for invalid input pointers. */
843 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
844 (packet_ptr == NX_NULL) || (destination_ptr == NX_NULL) || (actual_size == NX_NULL))
845 return(NX_PTR_ERROR);
846
847 /* Check for appropriate caller. */
848 NX_THREADS_ONLY_CALLER_CHECKING
849
850 /* Call actual server content get function. */
851 status = _nx_http_server_content_get_extended(server_ptr, packet_ptr, byte_offset, destination_ptr, destination_size, actual_size);
852
853 /* Return completion status. */
854 return(status);
855 }
856
857
858 /**************************************************************************/
859 /* */
860 /* FUNCTION RELEASE */
861 /* */
862 /* _nx_http_server_content_get_extended PORTABLE C */
863 /* 6.1 */
864 /* AUTHOR */
865 /* */
866 /* Yuxin Zhou, Microsoft Corporation */
867 /* */
868 /* DESCRIPTION */
869 /* */
870 /* This function returns the user's specified portion of the HTTP */
871 /* content. Content is typically included in POST and PUT requests */
872 /* from the client. This routine is designed to be called from the */
873 /* application's request notify callback. */
874 /* */
875 /* This API is identical to _nx_http_server_content_get service except */
876 /* for detecting a valid Content Length of length zero. In this case, */
877 /* it sets the actual_size pointer to that value and returns a */
878 /* successful outcome (empty POST requests are allowed in HTTP */
879 /* 1.0/1.1). If this is called from a request notify callback the */
880 /* caller is responsible for responding to the HTTP Client. */
881 /* */
882 /* INPUT */
883 /* */
884 /* server_ptr Pointer to HTTP server */
885 /* packet_ptr Pointer to HTTP request packet*/
886 /* byte_offset Byte offset into content */
887 /* destination_ptr Pointer to content destination*/
888 /* destination_size Maximum size of destination */
889 /* actual_size Actual amount of content */
890 /* */
891 /* OUTPUT */
892 /* */
893 /* status Completion status */
894 /* */
895 /* CALLS */
896 /* */
897 /* nx_tcp_socket_receive Receive another packet */
898 /* _nx_http_server_content_length_get_extended */
899 /* Get content length with error */
900 /* status returned separately */
901 /* content length value. */
902 /* _nx_http_server_calculate_content_offset */
903 /* Pickup content offset */
904 /* */
905 /* CALLED BY */
906 /* */
907 /* Application Code */
908 /* */
909 /* RELEASE HISTORY */
910 /* */
911 /* DATE NAME DESCRIPTION */
912 /* */
913 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
914 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
915 /* resulting in version 6.1 */
916 /* */
917 /**************************************************************************/
_nx_http_server_content_get_extended(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,ULONG byte_offset,CHAR * destination_ptr,UINT destination_size,UINT * actual_size)918 UINT _nx_http_server_content_get_extended(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset,
919 CHAR *destination_ptr, UINT destination_size, UINT *actual_size)
920 {
921
922 ULONG content_length;
923 ULONG get_offset;
924 ULONG offset;
925 UINT status;
926 UINT remaining_bytes;
927 NX_PACKET *new_packet_ptr;
928 CHAR *buffer_ptr;
929
930
931 /* Default the actual size to zero. */
932 *actual_size = 0;
933
934 /* Determine if there is content in this HTTP request. */
935 status = (ULONG) _nx_http_server_content_length_get_extended(packet_ptr, &content_length);
936
937 if (status != NX_SUCCESS)
938 {
939 return status;
940 }
941
942 /* Check for a empty POST request. */
943 if (content_length == 0)
944 {
945
946 /* Return the zero message body (content-length) size. */
947 *actual_size = content_length;
948
949 /* No more data in this buffer. */
950 return(NX_SUCCESS);
951 }
952
953 /* Make sure the content length is at least greater than the byte offset supplied. */
954 if (content_length <= byte_offset)
955 {
956
957 /* No more data in this buffer. */
958 return(NX_HTTP_DATA_END);
959 }
960
961 /* Determine if the destination size is greater than the content length. */
962 if (destination_size > content_length)
963 {
964
965 /* Yes, make the destination size equal to the content length. */
966 destination_size = content_length;
967 }
968
969 /* Calculate the offset to the requested content area. */
970 get_offset = ((ULONG) _nx_http_server_calculate_content_offset(packet_ptr)) + byte_offset;
971
972 /* Determine if we need to read one or more additional packets. */
973 while (get_offset >= packet_ptr -> nx_packet_length)
974 {
975
976 #ifdef NX_DISABLE_PACKET_CHAIN
977 NX_PARAMETER_NOT_USED(server_ptr);
978
979 return NX_HTTP_ERROR;
980 #else
981 /* Read another packet because the offset reaches past the current packet
982 length. */
983 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
984
985 /* Check the return status. */
986 if (status != NX_SUCCESS)
987 {
988
989 /* Error, return to caller. */
990 return(NX_HTTP_TIMEOUT);
991 }
992
993 /* Otherwise, we have a new packet to append to the head packet. */
994
995 /* Determine if the current packet is already chained. */
996 if (packet_ptr -> nx_packet_next)
997 {
998
999 /* Yes, link the current last packet to the new packet. */
1000 (packet_ptr -> nx_packet_last) -> nx_packet_next = new_packet_ptr;
1001 }
1002 else
1003 {
1004
1005 /* Otherwise, this is our first chained packet. Link to the head. */
1006 packet_ptr -> nx_packet_next = new_packet_ptr;
1007 }
1008
1009 /* Is the new packet chained? */
1010 if (new_packet_ptr -> nx_packet_next)
1011 {
1012
1013 /* Yes, there is a last packet pointer. Point to this from the head packet. */
1014 packet_ptr -> nx_packet_last = new_packet_ptr -> nx_packet_last;
1015 }
1016 else
1017 {
1018
1019 /* No, there isn't a last packet pointer. Point to new packet from the head packet. */
1020 packet_ptr -> nx_packet_last = new_packet_ptr;
1021 }
1022
1023 /* Update the packet length. */
1024 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + new_packet_ptr -> nx_packet_length;
1025 #endif /* NX_DISABLE_PACKET_CHAIN */
1026 }
1027
1028 /* Default the buffer pointer to NULL. */
1029 buffer_ptr = NX_NULL;
1030
1031 /* Now find the packet that contains the offset. */
1032 offset = 0;
1033 new_packet_ptr = packet_ptr;
1034 do
1035 {
1036
1037 /* Determine if the get request falls into this packet. */
1038 if (get_offset < (offset + (ULONG)(new_packet_ptr -> nx_packet_append_ptr - new_packet_ptr -> nx_packet_prepend_ptr)))
1039 {
1040
1041 /* Yes, the get offset is in this packet. */
1042
1043 /* Setup the starting byte pointer. */
1044 buffer_ptr = ((CHAR *) new_packet_ptr -> nx_packet_prepend_ptr) + (get_offset - offset);
1045 break;
1046 }
1047
1048 /* Otherwise update the offset. */
1049 offset = offset + (ULONG)(new_packet_ptr -> nx_packet_append_ptr - new_packet_ptr -> nx_packet_prepend_ptr);
1050
1051 #ifdef NX_DISABLE_PACKET_CHAIN
1052 new_packet_ptr = NX_NULL;
1053 #else
1054 /* Move to next packet in the chain. */
1055 new_packet_ptr = new_packet_ptr -> nx_packet_next;
1056 #endif /* NX_DISABLE_PACKET_CHAIN */
1057
1058 } while (new_packet_ptr);
1059
1060 /* Determine if an error occurred in the search. */
1061 if ((buffer_ptr == (CHAR *) NX_NULL) || (new_packet_ptr == NX_NULL))
1062 return(NX_HTTP_ERROR);
1063
1064 /* Now determine if the maximum buffer size has to be adjusted. */
1065 if (destination_size > (UINT) (new_packet_ptr -> nx_packet_append_ptr - (UCHAR *) buffer_ptr))
1066 {
1067
1068 /* Adjust the destination size downward. */
1069 destination_size = (UINT) (new_packet_ptr -> nx_packet_append_ptr - (UCHAR *) buffer_ptr);
1070 }
1071
1072 /* Initialize the remaining bytes. */
1073 remaining_bytes = destination_size;
1074
1075 /* Otherwise copy the bytes from the offset to the end of the packet pointer. */
1076 while (remaining_bytes--)
1077 {
1078
1079 /* Copy a byte to the destination. */
1080 *destination_ptr++ = *buffer_ptr++;
1081 }
1082
1083 /* Successful completion. */
1084 *actual_size = destination_size;
1085 return(NX_SUCCESS);
1086 }
1087
1088
1089 /**************************************************************************/
1090 /* */
1091 /* FUNCTION RELEASE */
1092 /* */
1093 /* _nxe_http_server_content_length_get_extended PORTABLE C */
1094 /* 6.1 */
1095 /* AUTHOR */
1096 /* */
1097 /* Yuxin Zhou, Microsoft Corporation */
1098 /* */
1099 /* DESCRIPTION */
1100 /* */
1101 /* This function checks for errors in the extended HTTP content length */
1102 /* service. */
1103 /* */
1104 /* */
1105 /* INPUT */
1106 /* */
1107 /* packet_ptr Pointer to HTTP paclet */
1108 /* content_length Pointer for returning content */
1109 /* length value */
1110 /* */
1111 /* OUTPUT */
1112 /* */
1113 /* status Completion status */
1114 /* */
1115 /* CALLS */
1116 /* */
1117 /* _nx_http_server_content_length_get_extended */
1118 /* Actual extended get content */
1119 /* length service */
1120 /* */
1121 /* CALLED BY */
1122 /* */
1123 /* Application Code */
1124 /* */
1125 /* RELEASE HISTORY */
1126 /* */
1127 /* DATE NAME DESCRIPTION */
1128 /* */
1129 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1130 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1131 /* resulting in version 6.1 */
1132 /* */
1133 /**************************************************************************/
1134
_nxe_http_server_content_length_get_extended(NX_PACKET * packet_ptr,ULONG * content_length)1135 UINT _nxe_http_server_content_length_get_extended(NX_PACKET *packet_ptr, ULONG *content_length)
1136 {
1137
1138 UINT status;
1139
1140
1141 /* Check for invalid input pointers. */
1142 if ((packet_ptr == NX_NULL) || (content_length == NX_NULL))
1143 return(NX_PTR_ERROR);
1144
1145 /* Call actual server content length get function. */
1146 status = _nx_http_server_content_length_get_extended(packet_ptr, content_length);
1147
1148 /* Return completion status. */
1149 return status;
1150 }
1151
1152 /**************************************************************************/
1153 /* */
1154 /* FUNCTION RELEASE */
1155 /* */
1156 /* _nx_http_server_content_length_get_extended PORTABLE C */
1157 /* 6.1 */
1158 /* AUTHOR */
1159 /* */
1160 /* Yuxin Zhou, Microsoft Corporation */
1161 /* */
1162 /* DESCRIPTION */
1163 /* */
1164 /* This function find a valid content length field and returns a */
1165 /* successful completion status (NX_SUCCESS) if so. Otherwise it */
1166 /* it returns an error status. A valid content length value is */
1167 /* zero or more and matches the size of the message body. */
1168 /* */
1169 /* */
1170 /* INPUT */
1171 /* */
1172 /* packet_ptr Pointer to HTTP request packet*/
1173 /* content_length Pointer to a valid Content */
1174 /* Length value */
1175 /* */
1176 /* OUTPUT */
1177 /* */
1178 /* NX_SUCCESS Content length extracted */
1179 /* status Invalid content length */
1180 /* */
1181 /* CALLS */
1182 /* */
1183 /* None */
1184 /* */
1185 /* CALLED BY */
1186 /* */
1187 /* Threads */
1188 /* */
1189 /* RELEASE HISTORY */
1190 /* */
1191 /* DATE NAME DESCRIPTION */
1192 /* */
1193 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1194 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1195 /* resulting in version 6.1 */
1196 /* */
1197 /**************************************************************************/
_nx_http_server_content_length_get_extended(NX_PACKET * packet_ptr,ULONG * length)1198 UINT _nx_http_server_content_length_get_extended(NX_PACKET *packet_ptr, ULONG *length)
1199 {
1200
1201 CHAR *buffer_ptr;
1202
1203
1204 /* Default the content length to no data. */
1205 *length = 0;
1206
1207 /* Setup pointer to buffer. */
1208 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
1209
1210 /* Find the "Content-length: " token first. */
1211 while (((buffer_ptr+17) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
1212 {
1213
1214 /* Check for the Content-length token. */
1215 if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) &&
1216 ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) &&
1217 ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) &&
1218 ((*(buffer_ptr+3) == 't') || (*(buffer_ptr+3) == 'T')) &&
1219 ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) &&
1220 ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) &&
1221 ((*(buffer_ptr+6) == 't') || (*(buffer_ptr+6) == 'T')) &&
1222 (*(buffer_ptr+7) == '-') &&
1223 ((*(buffer_ptr+8) == 'l') || (*(buffer_ptr+8) == 'L')) &&
1224 ((*(buffer_ptr+9) == 'e') || (*(buffer_ptr+9) == 'E')) &&
1225 ((*(buffer_ptr+10) == 'n') || (*(buffer_ptr+10) == 'N')) &&
1226 ((*(buffer_ptr+11) == 'g') || (*(buffer_ptr+11) == 'G')) &&
1227 ((*(buffer_ptr+12) == 't') || (*(buffer_ptr+12) == 'T')) &&
1228 ((*(buffer_ptr+13) == 'h') || (*(buffer_ptr+13) == 'H')) &&
1229 (*(buffer_ptr+14) == ':') &&
1230 (*(buffer_ptr+15) == ' '))
1231 {
1232
1233 /* Move the pointer up to the length token. */
1234 buffer_ptr = buffer_ptr + 16;
1235 break;
1236 }
1237
1238 /* Move the pointer up to the next character. */
1239 buffer_ptr++;
1240 }
1241
1242 /* Now convert the length into a numeric value. */
1243 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
1244 {
1245
1246 /* Update the content length. */
1247 *length = *length * 10;
1248 *length = *length + (((UINT) (*buffer_ptr)) - 0x30);
1249
1250 /* Move the buffer pointer forward. */
1251 buffer_ptr++;
1252 }
1253
1254 /* Determine if the content length was picked up properly. */
1255 if ((*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13))
1256 {
1257
1258 /* Error, set the length to zero. */
1259 return NX_HTTP_INCOMPLETE_PUT_ERROR;
1260 }
1261
1262 /* Return successful completion status to the caller. */
1263 return NX_SUCCESS;
1264 }
1265
1266
1267 /**************************************************************************/
1268 /* */
1269 /* FUNCTION RELEASE */
1270 /* */
1271 /* _nxe_http_server_create PORTABLE C */
1272 /* 6.1 */
1273 /* AUTHOR */
1274 /* */
1275 /* Yuxin Zhou, Microsoft Corporation */
1276 /* */
1277 /* DESCRIPTION */
1278 /* */
1279 /* This function checks for errors in the HTTP server create call. */
1280 /* */
1281 /* */
1282 /* INPUT */
1283 /* */
1284 /* http_server_ptr Pointer to HTTP server */
1285 /* http_server_name Name of 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 /* http_server_size Size of HTTP server */
1296 /* */
1297 /* OUTPUT */
1298 /* */
1299 /* status Completion status */
1300 /* */
1301 /* CALLS */
1302 /* */
1303 /* _nx_http_server_create Actual server create call */
1304 /* */
1305 /* CALLED BY */
1306 /* */
1307 /* Application Code */
1308 /* */
1309 /* RELEASE HISTORY */
1310 /* */
1311 /* DATE NAME DESCRIPTION */
1312 /* */
1313 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1314 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1315 /* resulting in version 6.1 */
1316 /* */
1317 /**************************************************************************/
_nxe_http_server_create(NX_HTTP_SERVER * http_server_ptr,CHAR * http_server_name,NX_IP * ip_ptr,FX_MEDIA * media_ptr,VOID * stack_ptr,ULONG stack_size,NX_PACKET_POOL * pool_ptr,UINT (* authentication_check)(NX_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,CHAR ** password,CHAR ** realm),UINT (* request_notify)(NX_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,NX_PACKET * packet_ptr),UINT http_server_size)1318 UINT _nxe_http_server_create(NX_HTTP_SERVER *http_server_ptr, CHAR *http_server_name, NX_IP *ip_ptr, FX_MEDIA *media_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr,
1319 UINT (*authentication_check)(NX_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm),
1320 UINT (*request_notify)(NX_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr),
1321 UINT http_server_size)
1322 {
1323
1324 NX_PACKET *packet_ptr;
1325 UINT status;
1326
1327
1328 /* Check for invalid input pointers. */
1329 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
1330 (http_server_ptr == NX_NULL) || (http_server_ptr -> nx_http_server_id == NXD_HTTP_SERVER_ID) ||
1331 (stack_ptr == NX_NULL) || (pool_ptr == NX_NULL) ||
1332 (http_server_size != sizeof(NX_HTTP_SERVER)))
1333 return(NX_PTR_ERROR);
1334
1335 /* Pickup a packet from the supplied packet pool. */
1336 packet_ptr = pool_ptr -> nx_packet_pool_available_list;
1337
1338 /* Determine if the packet payload is equal to or greater than the maximum HTTP header supported. */
1339 if (((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start) - NX_PHYSICAL_TRAILER)
1340 < NX_HTTP_SERVER_MIN_PACKET_SIZE)
1341 return(NX_HTTP_POOL_ERROR);
1342
1343 /* Call actual server create function. */
1344 status = _nx_http_server_create(http_server_ptr, http_server_name, ip_ptr, media_ptr, stack_ptr, stack_size, pool_ptr,
1345 authentication_check, request_notify);
1346
1347 /* Return completion status. */
1348 return(status);
1349 }
1350
1351
1352 /**************************************************************************/
1353 /* */
1354 /* FUNCTION RELEASE */
1355 /* */
1356 /* _nx_http_server_create PORTABLE C */
1357 /* 6.1 */
1358 /* AUTHOR */
1359 /* */
1360 /* Yuxin Zhou, Microsoft Corporation */
1361 /* */
1362 /* DESCRIPTION */
1363 /* */
1364 /* This function creates a HTTP server on the specified IP. In doing */
1365 /* so this function creates an TCP socket for subsequent HTTP */
1366 /* transfers and a thread for the HTTP server. */
1367 /* */
1368 /* */
1369 /* INPUT */
1370 /* */
1371 /* http_server_ptr Pointer to HTTP server */
1372 /* http_server_name Name of HTTP server */
1373 /* ip_ptr Pointer to IP instance */
1374 /* media_ptr Pointer to media structure */
1375 /* stack_ptr Server thread's stack pointer */
1376 /* stack_size Server thread's stack size */
1377 /* pool_ptr Pointer to packet pool */
1378 /* authentication_check Pointer to application's */
1379 /* authentication checking */
1380 /* request_notify Pointer to application's */
1381 /* request notify service */
1382 /* */
1383 /* OUTPUT */
1384 /* */
1385 /* status Completion status */
1386 /* */
1387 /* CALLS */
1388 /* */
1389 /* nx_tcp_socket_create Create HTTP server socket */
1390 /* nx_tcp_socket_delete Delete the HTTP server socket */
1391 /* tx_thread_create Create the HTTP server thread */
1392 /* */
1393 /* CALLED BY */
1394 /* */
1395 /* Application Code */
1396 /* */
1397 /* RELEASE HISTORY */
1398 /* */
1399 /* DATE NAME DESCRIPTION */
1400 /* */
1401 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1402 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1403 /* resulting in version 6.1 */
1404 /* */
1405 /**************************************************************************/
_nx_http_server_create(NX_HTTP_SERVER * http_server_ptr,CHAR * http_server_name,NX_IP * ip_ptr,FX_MEDIA * media_ptr,VOID * stack_ptr,ULONG stack_size,NX_PACKET_POOL * pool_ptr,UINT (* authentication_check)(NX_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,CHAR ** password,CHAR ** realm),UINT (* request_notify)(NX_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,NX_PACKET * packet_ptr))1406 UINT _nx_http_server_create(NX_HTTP_SERVER *http_server_ptr, CHAR *http_server_name, NX_IP *ip_ptr, FX_MEDIA *media_ptr, VOID *stack_ptr, ULONG stack_size, NX_PACKET_POOL *pool_ptr,
1407 UINT (*authentication_check)(NX_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm),
1408 UINT (*request_notify)(NX_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr))
1409 {
1410
1411 UINT status;
1412
1413
1414 /* Clear the HTTP server structure. */
1415 memset((void *) http_server_ptr, 0, sizeof(NX_HTTP_SERVER));
1416
1417 /* Create the Server's TCP socket. */
1418 status = nx_tcp_socket_create(ip_ptr, &(http_server_ptr -> nx_http_server_socket), http_server_name,
1419 NX_HTTP_TYPE_OF_SERVICE, NX_HTTP_FRAGMENT_OPTION, NX_HTTP_TIME_TO_LIVE,
1420 NX_HTTP_SERVER_WINDOW_SIZE, NX_NULL, NX_NULL);
1421
1422 /* Determine if an error occurred. */
1423 if (status != NX_SUCCESS)
1424 {
1425
1426 /* Yes, return error code. */
1427 return(status);
1428 }
1429
1430 /* Now create the HTTP Server thread. */
1431 status = tx_thread_create(&(http_server_ptr -> nx_http_server_thread), "HTTP Server Thread", _nx_http_server_thread_entry,
1432 (ULONG) http_server_ptr, stack_ptr, stack_size, NX_HTTP_SERVER_PRIORITY, NX_HTTP_SERVER_PRIORITY,
1433 NX_HTTP_SERVER_THREAD_TIME_SLICE, TX_DONT_START);
1434
1435 /* Determine if an error occurred creating the thread. */
1436 if (status != NX_SUCCESS)
1437 {
1438
1439 /* Delete the TCP socket. */
1440 nx_tcp_socket_delete(&(http_server_ptr -> nx_http_server_socket));
1441
1442 /* Yes, return error code. */
1443 return(status);
1444 }
1445
1446 /* Save the Server name. */
1447 http_server_ptr -> nx_http_server_name = http_server_name;
1448
1449 /* Save the IP pointer address. */
1450 http_server_ptr -> nx_http_server_ip_ptr = ip_ptr;
1451
1452 /* Save the packet pool pointer. */
1453 http_server_ptr -> nx_http_server_packet_pool_ptr = pool_ptr;
1454
1455 /* Save the media pointer address. */
1456 http_server_ptr -> nx_http_server_media_ptr = media_ptr;
1457
1458 /* Save the user-supplied routines, if specified. */
1459 http_server_ptr -> nx_http_server_authentication_check = authentication_check;
1460 http_server_ptr -> nx_http_server_request_notify = request_notify;
1461
1462
1463 /* Remember this server structure in the TCP socket. */
1464 http_server_ptr -> nx_http_server_socket.nx_tcp_socket_reserved_ptr = (void *) http_server_ptr;
1465
1466 /* Set the server ID to indicate the HTTP server thread is ready. */
1467 http_server_ptr -> nx_http_server_id = NXD_HTTP_SERVER_ID;
1468
1469 /* Return successful completion. */
1470 return(NX_SUCCESS);
1471 }
1472
1473
1474 /**************************************************************************/
1475 /* */
1476 /* FUNCTION RELEASE */
1477 /* */
1478 /* _nxe_http_server_delete PORTABLE C */
1479 /* 6.1 */
1480 /* AUTHOR */
1481 /* */
1482 /* Yuxin Zhou, Microsoft Corporation */
1483 /* */
1484 /* DESCRIPTION */
1485 /* */
1486 /* This function checks for errors in the HTTP server delete call. */
1487 /* */
1488 /* */
1489 /* INPUT */
1490 /* */
1491 /* http_server_ptr Pointer to HTTP server */
1492 /* */
1493 /* OUTPUT */
1494 /* */
1495 /* status Completion status */
1496 /* */
1497 /* CALLS */
1498 /* */
1499 /* _nx_http_server_delete Actual server delete call */
1500 /* */
1501 /* CALLED BY */
1502 /* */
1503 /* Application Code */
1504 /* */
1505 /* RELEASE HISTORY */
1506 /* */
1507 /* DATE NAME DESCRIPTION */
1508 /* */
1509 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1510 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1511 /* resulting in version 6.1 */
1512 /* */
1513 /**************************************************************************/
_nxe_http_server_delete(NX_HTTP_SERVER * http_server_ptr)1514 UINT _nxe_http_server_delete(NX_HTTP_SERVER *http_server_ptr)
1515 {
1516
1517 UINT status;
1518
1519
1520 /* Check for invalid input pointers. */
1521 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID))
1522 return(NX_PTR_ERROR);
1523
1524 /* Check for appropriate caller. */
1525 NX_THREADS_ONLY_CALLER_CHECKING
1526
1527 /* Call actual server delete function. */
1528 status = _nx_http_server_delete(http_server_ptr);
1529
1530 /* Return completion status. */
1531 return(status);
1532 }
1533
1534
1535 /**************************************************************************/
1536 /* */
1537 /* FUNCTION RELEASE */
1538 /* */
1539 /* _nx_http_server_delete PORTABLE C */
1540 /* 6.2.0 */
1541 /* AUTHOR */
1542 /* */
1543 /* Yuxin Zhou, Microsoft Corporation */
1544 /* */
1545 /* DESCRIPTION */
1546 /* */
1547 /* This function deletes a previously created HTTP server on the */
1548 /* specified IP. */
1549 /* */
1550 /* */
1551 /* INPUT */
1552 /* */
1553 /* http_server_ptr Pointer to HTTP server */
1554 /* */
1555 /* OUTPUT */
1556 /* */
1557 /* status Completion status */
1558 /* */
1559 /* CALLS */
1560 /* */
1561 /* nx_tcp_socket_delete Delete the HTTP server socket */
1562 /* _nx_http_server_disconnect Disconnect HTTP server socket */
1563 /* nx_tcp_server_socket_unlisten Unlisten on the HTTP port */
1564 /* tx_thread_delete Delete the HTTP server thread */
1565 /* tx_thread_suspend Suspend the HTTP server thread*/
1566 /* tx_thread_terminate Terminate the HTTP server */
1567 /* thread */
1568 /* */
1569 /* CALLED BY */
1570 /* */
1571 /* Application Code */
1572 /* */
1573 /* RELEASE HISTORY */
1574 /* */
1575 /* DATE NAME DESCRIPTION */
1576 /* */
1577 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1578 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1579 /* resulting in version 6.1 */
1580 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
1581 /* supported random nonce, */
1582 /* resulting in version 6.2.0 */
1583 /* */
1584 /**************************************************************************/
_nx_http_server_delete(NX_HTTP_SERVER * http_server_ptr)1585 UINT _nx_http_server_delete(NX_HTTP_SERVER *http_server_ptr)
1586 {
1587
1588
1589 /* Clear the server ID to indicate the HTTP server is no longer ready. */
1590 http_server_ptr -> nx_http_server_id = 0;
1591
1592 /* Disconnect the TCP socket. */
1593 _nx_http_server_disconnect(http_server_ptr, NX_HTTP_SERVER_TIMEOUT_DISCONNECT);
1594
1595 /* Delete the TCP socket. */
1596 nx_tcp_socket_delete(&(http_server_ptr -> nx_http_server_socket));
1597
1598 /* Unlisten on the HTTP server port. */
1599 nx_tcp_server_socket_unlisten(http_server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT);
1600
1601 /* Suspend the HTTP server thread. */
1602 tx_thread_suspend(&(http_server_ptr -> nx_http_server_thread));
1603
1604 /* Terminate server thread. */
1605 tx_thread_terminate(&(http_server_ptr -> nx_http_server_thread));
1606
1607 /* Delete server thread. */
1608 tx_thread_delete(&(http_server_ptr -> nx_http_server_thread));
1609
1610 /* Return successful completion. */
1611 return(NX_SUCCESS);
1612 }
1613
1614
1615 /**************************************************************************/
1616 /* */
1617 /* FUNCTION RELEASE */
1618 /* */
1619 /* _nxe_http_server_param_get PORTABLE C */
1620 /* 6.1 */
1621 /* AUTHOR */
1622 /* */
1623 /* Yuxin Zhou, Microsoft Corporation */
1624 /* */
1625 /* DESCRIPTION */
1626 /* */
1627 /* This function checks for errors in the HTTP parameter get call. */
1628 /* */
1629 /* */
1630 /* INPUT */
1631 /* */
1632 /* packet_ptr Pointer to HTTP request packet*/
1633 /* param_number Parameter number (start at 0) */
1634 /* param_ptr Pointer to destination */
1635 /* max_param_size Maximum size of destination */
1636 /* */
1637 /* OUTPUT */
1638 /* */
1639 /* status Completion status */
1640 /* */
1641 /* CALLS */
1642 /* */
1643 /* _nx_http_server_param_get Actual server parameter get */
1644 /* call */
1645 /* */
1646 /* CALLED BY */
1647 /* */
1648 /* Application Code */
1649 /* */
1650 /* RELEASE HISTORY */
1651 /* */
1652 /* DATE NAME DESCRIPTION */
1653 /* */
1654 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1655 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1656 /* resulting in version 6.1 */
1657 /* */
1658 /**************************************************************************/
_nxe_http_server_param_get(NX_PACKET * packet_ptr,UINT param_number,CHAR * param_ptr,UINT max_param_size)1659 UINT _nxe_http_server_param_get(NX_PACKET *packet_ptr, UINT param_number, CHAR *param_ptr, UINT max_param_size)
1660 {
1661
1662 UINT status;
1663
1664
1665 /* Check for invalid input pointers. */
1666 if ((packet_ptr == NX_NULL) || (param_ptr == NX_NULL))
1667 return(NX_PTR_ERROR);
1668
1669 /* Check for appropriate caller. */
1670 NX_THREADS_ONLY_CALLER_CHECKING
1671
1672 /* Call actual server parameter get function. */
1673 status = _nx_http_server_param_get(packet_ptr, param_number, param_ptr, max_param_size);
1674
1675 /* Return completion status. */
1676 return(status);
1677 }
1678
1679
1680 /**************************************************************************/
1681 /* */
1682 /* FUNCTION RELEASE */
1683 /* */
1684 /* _nx_http_server_param_get PORTABLE C */
1685 /* 6.1 */
1686 /* AUTHOR */
1687 /* */
1688 /* Yuxin Zhou, Microsoft Corporation */
1689 /* */
1690 /* DESCRIPTION */
1691 /* */
1692 /* This function returns the requested parameter specified in the URL */
1693 /* requested by the client. If the specified parameter is not present, */
1694 /* a not found error is returned to the caller. */
1695 /* */
1696 /* */
1697 /* INPUT */
1698 /* */
1699 /* packet_ptr Pointer to HTTP request packet*/
1700 /* param_number Parameter number (start at 0) */
1701 /* param_ptr Pointer to destination */
1702 /* max_param_size Maximum size of destination */
1703 /* */
1704 /* OUTPUT */
1705 /* */
1706 /* status Completion status */
1707 /* */
1708 /* CALLS */
1709 /* */
1710 /* None */
1711 /* */
1712 /* CALLED BY */
1713 /* */
1714 /* Application Code */
1715 /* */
1716 /* RELEASE HISTORY */
1717 /* */
1718 /* DATE NAME DESCRIPTION */
1719 /* */
1720 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1721 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1722 /* resulting in version 6.1 */
1723 /* */
1724 /**************************************************************************/
_nx_http_server_param_get(NX_PACKET * packet_ptr,UINT param_number,CHAR * param_ptr,UINT max_param_size)1725 UINT _nx_http_server_param_get(NX_PACKET *packet_ptr, UINT param_number, CHAR *param_ptr, UINT max_param_size)
1726 {
1727
1728 UINT i;
1729 UINT current_param;
1730 CHAR *buffer_ptr;
1731
1732
1733 /* Set the destination string to NULL. */
1734 param_ptr[0] = (CHAR) NX_NULL;
1735
1736 /* Set current parameter to 0. */
1737 current_param = 0;
1738
1739 /* Setup a pointer to the HTTP buffer. */
1740 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
1741
1742 /* Position to the start of the URL. */
1743 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != '/'))
1744 {
1745
1746 /* Move the buffer pointer. */
1747 buffer_ptr++;
1748 }
1749
1750 /* Not find URL. */
1751 if (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr)
1752 {
1753 return(NX_HTTP_NOT_FOUND);
1754 }
1755
1756 /* Loop through the buffer to search for the specified parameter. */
1757 do
1758 {
1759
1760 /* Determine if the character is a semicolon, indicating a parameter
1761 is present. */
1762 if (*buffer_ptr == ';')
1763 {
1764
1765 /* Yes, a parameter is present. */
1766
1767 /* Move the buffer pointer forward. */
1768 buffer_ptr++;
1769
1770 /* Is this the parameter requested? */
1771 if (current_param == param_number)
1772 {
1773
1774
1775 /* Yes, we have found the parameter. */
1776 for (i = 0; i < max_param_size; i++)
1777 {
1778
1779 /* Check if reach the end of the packet data. */
1780 if (buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr)
1781 {
1782 return(NX_HTTP_NOT_FOUND);
1783 }
1784
1785 /* Check for end of parameter. */
1786 if ((*buffer_ptr == ';') || (*buffer_ptr == '?') ||
1787 (*buffer_ptr == '&') || (*buffer_ptr == ' ') ||
1788 (*buffer_ptr == (CHAR) 13))
1789 {
1790
1791 /* Yes, we are finished and need to get out of the loop. */
1792 break;
1793 }
1794
1795 /* Otherwise, store the character in the destination. */
1796 param_ptr[i] = *buffer_ptr++;
1797 }
1798
1799 /* NULL terminate the parameter. */
1800 if (i < max_param_size)
1801 param_ptr[i] = (CHAR) NX_NULL;
1802
1803 /* Return to caller. */
1804 if (param_ptr[i] == (CHAR) NX_NULL)
1805 return(NX_SUCCESS);
1806 else
1807 return(NX_HTTP_IMPROPERLY_TERMINATED_PARAM);
1808 }
1809 else
1810 {
1811
1812 /* Increment the current parameter. */
1813 current_param++;
1814 }
1815 }
1816 else
1817 {
1818
1819 /* Check for any other character that signals the end of the param list. */
1820 if ((*buffer_ptr == '?') || (*buffer_ptr == ' ') || (*buffer_ptr == '&'))
1821 break;
1822
1823 /* Update the buffer pointer. */
1824 buffer_ptr++;
1825 }
1826
1827 } while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 13));
1828
1829 /* Return a not found error. */
1830 return(NX_HTTP_NOT_FOUND);
1831 }
1832
1833
1834 /**************************************************************************/
1835 /* */
1836 /* FUNCTION RELEASE */
1837 /* */
1838 /* _nxe_http_server_query_get PORTABLE C */
1839 /* 6.1 */
1840 /* AUTHOR */
1841 /* */
1842 /* Yuxin Zhou, Microsoft Corporation */
1843 /* */
1844 /* DESCRIPTION */
1845 /* */
1846 /* This function checks for errors in the HTTP query get call. */
1847 /* */
1848 /* */
1849 /* INPUT */
1850 /* */
1851 /* packet_ptr Pointer to HTTP request packet*/
1852 /* query_number Query number (start at 0) */
1853 /* query_ptr Pointer to destination */
1854 /* max_query_size Maximum size of destination */
1855 /* */
1856 /* OUTPUT */
1857 /* */
1858 /* status Completion status */
1859 /* */
1860 /* CALLS */
1861 /* */
1862 /* _nx_http_server_query_get Actual server query get */
1863 /* call */
1864 /* */
1865 /* CALLED BY */
1866 /* */
1867 /* Application Code */
1868 /* */
1869 /* RELEASE HISTORY */
1870 /* */
1871 /* DATE NAME DESCRIPTION */
1872 /* */
1873 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1874 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1875 /* resulting in version 6.1 */
1876 /* */
1877 /**************************************************************************/
_nxe_http_server_query_get(NX_PACKET * packet_ptr,UINT query_number,CHAR * query_ptr,UINT max_query_size)1878 UINT _nxe_http_server_query_get(NX_PACKET *packet_ptr, UINT query_number, CHAR *query_ptr, UINT max_query_size)
1879 {
1880
1881 UINT status;
1882
1883
1884 /* Check for invalid input pointers. */
1885 if ((packet_ptr == NX_NULL) || (query_ptr == NX_NULL))
1886 return(NX_PTR_ERROR);
1887
1888 /* Check for appropriate caller. */
1889 NX_THREADS_ONLY_CALLER_CHECKING
1890
1891 /* Call actual server query get function. */
1892 status = _nx_http_server_query_get(packet_ptr, query_number, query_ptr, max_query_size);
1893
1894 /* Return completion status. */
1895 return(status);
1896 }
1897
1898
1899 /**************************************************************************/
1900 /* */
1901 /* FUNCTION RELEASE */
1902 /* */
1903 /* _nx_http_server_query_get PORTABLE C */
1904 /* 6.1 */
1905 /* AUTHOR */
1906 /* */
1907 /* Yuxin Zhou, Microsoft Corporation */
1908 /* */
1909 /* DESCRIPTION */
1910 /* */
1911 /* This function returns the requested query specified in the URL */
1912 /* requested by the client. If the specified query is not present, */
1913 /* a not found error is returned to the caller. */
1914 /* */
1915 /* */
1916 /* INPUT */
1917 /* */
1918 /* packet_ptr Pointer to HTTP request packet*/
1919 /* query_number Query number (start at 0) */
1920 /* query_ptr Pointer to destination */
1921 /* max_query_size Maximum size of destination */
1922 /* */
1923 /* OUTPUT */
1924 /* */
1925 /* status Completion status */
1926 /* */
1927 /* CALLS */
1928 /* */
1929 /* None */
1930 /* */
1931 /* CALLED BY */
1932 /* */
1933 /* Application Code */
1934 /* */
1935 /* RELEASE HISTORY */
1936 /* */
1937 /* DATE NAME DESCRIPTION */
1938 /* */
1939 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1940 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1941 /* resulting in version 6.1 */
1942 /* */
1943 /**************************************************************************/
_nx_http_server_query_get(NX_PACKET * packet_ptr,UINT query_number,CHAR * query_ptr,UINT max_query_size)1944 UINT _nx_http_server_query_get(NX_PACKET *packet_ptr, UINT query_number, CHAR *query_ptr, UINT max_query_size)
1945 {
1946
1947 UINT i;
1948 UINT current_query;
1949 CHAR *buffer_ptr;
1950
1951
1952 /* Set the destination string to NULL. */
1953 query_ptr[0] = (CHAR) NX_NULL;
1954
1955 /* Set current query number to 0. */
1956 current_query = 0;
1957
1958 /* Setup a pointer to the HTTP buffer. */
1959 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
1960
1961 /* Position to the start of the URL. */
1962 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != '/'))
1963 {
1964
1965 /* Move the buffer pointer. */
1966 buffer_ptr++;
1967 }
1968
1969 /* Not find URL. */
1970 if (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr)
1971 {
1972 return(NX_HTTP_NOT_FOUND);
1973 }
1974
1975 /* Loop through the buffer to search for the specified query instance. */
1976 do
1977 {
1978
1979 /* Determine if the character is a '?' or a '&', indicating a query
1980 is present. */
1981 if (((*buffer_ptr == '?') && (current_query == 0)) ||
1982 ((*buffer_ptr == '&') && (current_query != 0)))
1983 {
1984
1985 /* Yes, a query is present. */
1986
1987 /* Move the buffer pointer forward. */
1988 buffer_ptr++;
1989
1990 /* Is this the query requested? */
1991 if (current_query == query_number)
1992 {
1993
1994
1995 /* Yes, we have found the query. */
1996 for (i = 0; i < max_query_size; i++)
1997 {
1998
1999 /* Check if reach the end of the packet data. */
2000 if (buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr)
2001 {
2002 return(NX_HTTP_NOT_FOUND);
2003 }
2004
2005 /* Check for end of query. */
2006 if ((*buffer_ptr == ';') || (*buffer_ptr == '?') ||
2007 (*buffer_ptr == '&') || (*buffer_ptr == ' ') ||
2008 (*buffer_ptr == (CHAR) 13))
2009 {
2010
2011 /* Yes, we are finished and need to get out of the loop. */
2012 break;
2013 }
2014
2015 /* Otherwise, store the character in the destination. */
2016 query_ptr[i] = *buffer_ptr++;
2017 }
2018
2019 /* NULL terminate the query. */
2020 query_ptr[i] = (CHAR) NX_NULL;
2021
2022 /* Return to caller. */
2023 if (i)
2024 return(NX_SUCCESS);
2025 else
2026 return(NX_HTTP_NO_QUERY_PARSED);
2027 }
2028 else
2029 {
2030
2031 /* Increment the current query. */
2032 current_query++;
2033 }
2034 }
2035 else
2036 {
2037
2038 /* Check for any other character that signals the end of the query list. */
2039 if ((*buffer_ptr == '?') || (*buffer_ptr == ' ') || (*buffer_ptr == ';'))
2040 break;
2041
2042 /* Update the buffer pointer. */
2043 buffer_ptr++;
2044 }
2045
2046 } while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 13));
2047
2048 /* Return a not found error. */
2049 return(NX_HTTP_NOT_FOUND);
2050 }
2051
2052
2053 /**************************************************************************/
2054 /* */
2055 /* FUNCTION RELEASE */
2056 /* */
2057 /* _nxe_http_server_start PORTABLE C */
2058 /* 6.1 */
2059 /* AUTHOR */
2060 /* */
2061 /* Yuxin Zhou, Microsoft Corporation */
2062 /* */
2063 /* DESCRIPTION */
2064 /* */
2065 /* This function checks for errors in the HTTP server start call. */
2066 /* */
2067 /* */
2068 /* INPUT */
2069 /* */
2070 /* http_server_ptr Pointer to HTTP server */
2071 /* */
2072 /* OUTPUT */
2073 /* */
2074 /* status Completion status */
2075 /* */
2076 /* CALLS */
2077 /* */
2078 /* _nx_http_server_start Actual server start call */
2079 /* */
2080 /* CALLED BY */
2081 /* */
2082 /* Application Code */
2083 /* */
2084 /* RELEASE HISTORY */
2085 /* */
2086 /* DATE NAME DESCRIPTION */
2087 /* */
2088 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2089 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2090 /* resulting in version 6.1 */
2091 /* */
2092 /**************************************************************************/
_nxe_http_server_start(NX_HTTP_SERVER * http_server_ptr)2093 UINT _nxe_http_server_start(NX_HTTP_SERVER *http_server_ptr)
2094 {
2095
2096 UINT status;
2097
2098
2099 /* Check for invalid input pointers. */
2100 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID))
2101 return(NX_PTR_ERROR);
2102
2103 /* Call actual server start function. */
2104 status = _nx_http_server_start(http_server_ptr);
2105
2106 /* Return completion status. */
2107 return(status);
2108 }
2109
2110
2111 /**************************************************************************/
2112 /* */
2113 /* FUNCTION RELEASE */
2114 /* */
2115 /* _nx_http_server_start PORTABLE C */
2116 /* 6.1 */
2117 /* AUTHOR */
2118 /* */
2119 /* Yuxin Zhou, Microsoft Corporation */
2120 /* */
2121 /* DESCRIPTION */
2122 /* */
2123 /* This function starts a previously created HTTP server on the */
2124 /* specified IP. */
2125 /* */
2126 /* */
2127 /* INPUT */
2128 /* */
2129 /* http_server_ptr Pointer to HTTP server */
2130 /* */
2131 /* OUTPUT */
2132 /* */
2133 /* status Completion status */
2134 /* */
2135 /* CALLS */
2136 /* */
2137 /* nx_tcp_server_socket_listen Start listening on HTTP port */
2138 /* tx_thread_resume Resume the HTTP server thread */
2139 /* */
2140 /* CALLED BY */
2141 /* */
2142 /* Application Code */
2143 /* */
2144 /* RELEASE HISTORY */
2145 /* */
2146 /* DATE NAME DESCRIPTION */
2147 /* */
2148 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2149 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2150 /* resulting in version 6.1 */
2151 /* */
2152 /**************************************************************************/
_nx_http_server_start(NX_HTTP_SERVER * http_server_ptr)2153 UINT _nx_http_server_start(NX_HTTP_SERVER *http_server_ptr)
2154 {
2155
2156 UINT status;
2157
2158
2159
2160 /* Start listening on the HTTP server port. */
2161 status = nx_tcp_server_socket_listen(http_server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT,
2162 &(http_server_ptr -> nx_http_server_socket), NX_HTTP_SERVER_MAX_PENDING,
2163 _nx_http_server_connection_present);
2164
2165 /* Determine if the listen was unsuccessful. */
2166 if (status != NX_SUCCESS)
2167 {
2168
2169 /* Just return an HTTP error. */
2170 return(status);
2171 }
2172
2173 /* Start the HTTP server thread. */
2174 tx_thread_resume(&(http_server_ptr -> nx_http_server_thread));
2175
2176 /* Return successful completion. */
2177 return(NX_SUCCESS);
2178 }
2179
2180
2181 /**************************************************************************/
2182 /* */
2183 /* FUNCTION RELEASE */
2184 /* */
2185 /* _nxe_http_server_stop PORTABLE C */
2186 /* 6.1 */
2187 /* AUTHOR */
2188 /* */
2189 /* Yuxin Zhou, Microsoft Corporation */
2190 /* */
2191 /* DESCRIPTION */
2192 /* */
2193 /* This function checks for errors in the HTTP server stop call. */
2194 /* */
2195 /* */
2196 /* INPUT */
2197 /* */
2198 /* http_server_ptr Pointer to HTTP server */
2199 /* */
2200 /* OUTPUT */
2201 /* */
2202 /* status Completion status */
2203 /* */
2204 /* CALLS */
2205 /* */
2206 /* _nx_http_server_stop Actual server stop call */
2207 /* */
2208 /* CALLED BY */
2209 /* */
2210 /* Application Code */
2211 /* */
2212 /* RELEASE HISTORY */
2213 /* */
2214 /* DATE NAME DESCRIPTION */
2215 /* */
2216 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2217 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2218 /* resulting in version 6.1 */
2219 /* */
2220 /**************************************************************************/
_nxe_http_server_stop(NX_HTTP_SERVER * http_server_ptr)2221 UINT _nxe_http_server_stop(NX_HTTP_SERVER *http_server_ptr)
2222 {
2223
2224 UINT status;
2225
2226
2227 /* Check for invalid input pointers. */
2228 if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID))
2229 return(NX_PTR_ERROR);
2230
2231 /* Check for appropriate caller. */
2232 NX_THREADS_ONLY_CALLER_CHECKING
2233
2234 /* Call actual server stop function. */
2235 status = _nx_http_server_stop(http_server_ptr);
2236
2237 /* Return completion status. */
2238 return(status);
2239 }
2240
2241
2242 /**************************************************************************/
2243 /* */
2244 /* FUNCTION RELEASE */
2245 /* */
2246 /* _nx_http_server_stop PORTABLE C */
2247 /* 6.2.0 */
2248 /* AUTHOR */
2249 /* */
2250 /* Yuxin Zhou, Microsoft Corporation */
2251 /* */
2252 /* DESCRIPTION */
2253 /* */
2254 /* This function stops a previously started HTTP server on the */
2255 /* specified IP. */
2256 /* */
2257 /* */
2258 /* INPUT */
2259 /* */
2260 /* http_server_ptr Pointer to HTTP server */
2261 /* */
2262 /* OUTPUT */
2263 /* */
2264 /* status Completion status */
2265 /* */
2266 /* CALLS */
2267 /* */
2268 /* _nx_http_server_disconnect Disconnect HTTP server socket */
2269 /* nx_tcp_server_socket_unlisten Unlisten on the HTTP port */
2270 /* tx_thread_suspend Suspend the HTTP server thread*/
2271 /* */
2272 /* CALLED BY */
2273 /* */
2274 /* Application Code */
2275 /* */
2276 /* RELEASE HISTORY */
2277 /* */
2278 /* DATE NAME DESCRIPTION */
2279 /* */
2280 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2281 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2282 /* resulting in version 6.1 */
2283 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
2284 /* supported random nonce, */
2285 /* resulting in version 6.2.0 */
2286 /* */
2287 /**************************************************************************/
_nx_http_server_stop(NX_HTTP_SERVER * http_server_ptr)2288 UINT _nx_http_server_stop(NX_HTTP_SERVER *http_server_ptr)
2289 {
2290
2291 /* Disconnect the TCP socket. */
2292 _nx_http_server_disconnect(http_server_ptr, NX_NO_WAIT);
2293
2294 /* Unlisten on the HTTP server port. */
2295 nx_tcp_server_socket_unlisten(http_server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT);
2296
2297 /* Suspend the HTTP server thread. */
2298 tx_thread_suspend(&(http_server_ptr -> nx_http_server_thread));
2299
2300 /* Return successful completion. */
2301 return(NX_SUCCESS);
2302 }
2303
2304
2305 /**************************************************************************/
2306 /* */
2307 /* FUNCTION RELEASE */
2308 /* */
2309 /* _nx_http_server_disconnect PORTABLE C */
2310 /* 6.2.0 */
2311 /* AUTHOR */
2312 /* */
2313 /* Yuxin Zhou, Microsoft Corporation */
2314 /* */
2315 /* DESCRIPTION */
2316 /* */
2317 /* This function disconnects the HTTP server socket. */
2318 /* */
2319 /* */
2320 /* INPUT */
2321 /* */
2322 /* http_server_ptr Pointer to HTTP server */
2323 /* wait_option Wait option */
2324 /* */
2325 /* OUTPUT */
2326 /* */
2327 /* status Completion status */
2328 /* */
2329 /* CALLS */
2330 /* */
2331 /* nx_tcp_socket_disconnect Disconnect HTTP server socket */
2332 /* nx_tcp_socket_unaccept Unaccept HTTP server connect */
2333 /* */
2334 /* CALLED BY */
2335 /* */
2336 /* Application Code */
2337 /* */
2338 /* RELEASE HISTORY */
2339 /* */
2340 /* DATE NAME DESCRIPTION */
2341 /* */
2342 /* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */
2343 /* */
2344 /**************************************************************************/
_nx_http_server_disconnect(NX_HTTP_SERVER * http_server_ptr,UINT wait_option)2345 UINT _nx_http_server_disconnect(NX_HTTP_SERVER *http_server_ptr, UINT wait_option)
2346 {
2347
2348 #ifdef NX_HTTP_DIGEST_ENABLE
2349 UINT i;
2350
2351 /* Once the nonce has been accepted, set the state as invalid. */
2352 for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++)
2353 {
2354 if (http_server_ptr -> nx_http_server_nonces[i].nonce_state == NX_HTTP_SERVER_NONCE_ACCEPTED)
2355 {
2356 http_server_ptr -> nx_http_server_nonces[i].nonce_state = NX_HTTP_SERVER_NONCE_INVALID;
2357 break;
2358 }
2359 }
2360 #endif /* NX_HTTP_DIGEST_ENABLE */
2361
2362 /* Disconnect the TCP socket. */
2363 nx_tcp_socket_disconnect(&(http_server_ptr -> nx_http_server_socket), wait_option);
2364
2365 /* Unaccept any remaining connection on the TCP socket. */
2366 nx_tcp_server_socket_unaccept(&(http_server_ptr -> nx_http_server_socket));
2367
2368 /* Return successful completion. */
2369 return(NX_SUCCESS);
2370 }
2371
2372
2373 /**************************************************************************/
2374 /* */
2375 /* FUNCTION RELEASE */
2376 /* */
2377 /* _nxe_http_server_callback_data_send PORTABLE C */
2378 /* 6.1 */
2379 /* AUTHOR */
2380 /* */
2381 /* Yuxin Zhou, Microsoft Corporation */
2382 /* */
2383 /* DESCRIPTION */
2384 /* */
2385 /* This function checks errors for sending data. */
2386 /* */
2387 /* */
2388 /* INPUT */
2389 /* */
2390 /* http_server_ptr Pointer to HTTP server */
2391 /* data_ptr Pointer to data to send */
2392 /* data_length Length of data to send */
2393 /* */
2394 /* OUTPUT */
2395 /* */
2396 /* status Completion status */
2397 /* */
2398 /* CALLS */
2399 /* */
2400 /* _nx_http_server_callback_data_send Actual data send call */
2401 /* */
2402 /* CALLED BY */
2403 /* */
2404 /* Application Code */
2405 /* */
2406 /* RELEASE HISTORY */
2407 /* */
2408 /* DATE NAME DESCRIPTION */
2409 /* */
2410 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2411 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2412 /* resulting in version 6.1 */
2413 /* */
2414 /**************************************************************************/
_nxe_http_server_callback_data_send(NX_HTTP_SERVER * server_ptr,VOID * data_ptr,ULONG data_length)2415 UINT _nxe_http_server_callback_data_send(NX_HTTP_SERVER *server_ptr, VOID *data_ptr, ULONG data_length)
2416 {
2417 UINT status;
2418
2419
2420 /* Check for invalid input pointers. */
2421 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID))
2422 return(NX_PTR_ERROR);
2423
2424 /* Check for appropriate caller. */
2425 NX_THREADS_ONLY_CALLER_CHECKING
2426
2427 /* Call actual data send function. */
2428 status = _nx_http_server_callback_data_send(server_ptr, data_ptr, data_length);
2429
2430 /* Return completion status. */
2431 return(status);
2432 }
2433
2434
2435 /**************************************************************************/
2436 /* */
2437 /* FUNCTION RELEASE */
2438 /* */
2439 /* _nx_http_server_callback_data_send PORTABLE C */
2440 /* 6.1 */
2441 /* AUTHOR */
2442 /* */
2443 /* Yuxin Zhou, Microsoft Corporation */
2444 /* */
2445 /* DESCRIPTION */
2446 /* */
2447 /* This function sends data to the client from the application */
2448 /* callback function. This is typically done to satisfy a GET or */
2449 /* POST request that is processed completely by the application */
2450 /* callback function. */
2451 /* */
2452 /* */
2453 /* INPUT */
2454 /* */
2455 /* http_server_ptr Pointer to HTTP server */
2456 /* data_ptr Pointer to data to send */
2457 /* data_length Length of data to send */
2458 /* */
2459 /* OUTPUT */
2460 /* */
2461 /* status Completion status */
2462 /* */
2463 /* CALLS */
2464 /* */
2465 /* nx_packet_allocate Allocate a NetX packet */
2466 /* nx_packet_data_append Append data to packet */
2467 /* nx_tcp_socket_send Send TCP data */
2468 /* */
2469 /* CALLED BY */
2470 /* */
2471 /* Application Code */
2472 /* */
2473 /* RELEASE HISTORY */
2474 /* */
2475 /* DATE NAME DESCRIPTION */
2476 /* */
2477 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2478 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2479 /* resulting in version 6.1 */
2480 /* */
2481 /**************************************************************************/
_nx_http_server_callback_data_send(NX_HTTP_SERVER * server_ptr,VOID * data_ptr,ULONG data_length)2482 UINT _nx_http_server_callback_data_send(NX_HTTP_SERVER *server_ptr, VOID *data_ptr, ULONG data_length)
2483 {
2484
2485 NX_PACKET *new_packet_ptr;
2486 UINT status;
2487
2488
2489 /* Allocate a new packet for data. */
2490 status = nx_packet_allocate(server_ptr -> nx_http_server_packet_pool_ptr, &new_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
2491
2492 /* Determine if an error is present. */
2493 if (status != NX_SUCCESS)
2494 {
2495
2496 /* Indicate an allocation error occurred. */
2497 server_ptr -> nx_http_server_allocation_errors++;
2498
2499 /* Error, return to caller. */
2500 return(NX_HTTP_ERROR);
2501 }
2502
2503 /* Now append the data to the packet. */
2504 status = nx_packet_data_append(new_packet_ptr, data_ptr, data_length,
2505 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
2506
2507 /* Determine if an error is present. */
2508 if (status != NX_SUCCESS)
2509 {
2510
2511 /* Indicate an allocation error occurred. */
2512 server_ptr -> nx_http_server_allocation_errors++;
2513
2514 /* Release the initial packet. */
2515 nx_packet_release(new_packet_ptr);
2516
2517 /* Error, return to caller. */
2518 return(status);
2519 }
2520
2521 /* Send the data back to the client. */
2522 status = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
2523
2524 /* Determine if this is successful. */
2525 if (status != NX_SUCCESS)
2526 {
2527
2528 /* Map the status to the generic HTTP error. */
2529 status = status;
2530
2531 /* Release the packet. */
2532 nx_packet_release(new_packet_ptr);
2533 }
2534
2535 /* Return completion status. */
2536 return(status);
2537 }
2538
2539
2540 /**************************************************************************/
2541 /* */
2542 /* FUNCTION RELEASE */
2543 /* */
2544 /* _nxe_http_server_callback_response_send PORTABLE C */
2545 /* 6.1 */
2546 /* AUTHOR */
2547 /* */
2548 /* Yuxin Zhou, Microsoft Corporation */
2549 /* */
2550 /* DESCRIPTION */
2551 /* */
2552 /* This function checks errors for sending HTTP response. */
2553 /* */
2554 /* */
2555 /* INPUT */
2556 /* */
2557 /* http_server_ptr Pointer to HTTP server */
2558 /* header Pointer to HTTP header string */
2559 /* information Pointer to HTTP info string */
2560 /* additional_information Pointer to additional HTTP */
2561 /* information */
2562 /* */
2563 /* OUTPUT */
2564 /* */
2565 /* status Completion status */
2566 /* */
2567 /* CALLS */
2568 /* */
2569 /* _nx_http_server_callback_response_send */
2570 /* Actual HTTP response send call*/
2571 /* */
2572 /* CALLED BY */
2573 /* */
2574 /* Application Code */
2575 /* */
2576 /* RELEASE HISTORY */
2577 /* */
2578 /* DATE NAME DESCRIPTION */
2579 /* */
2580 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2581 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2582 /* resulting in version 6.1 */
2583 /* */
2584 /**************************************************************************/
_nxe_http_server_callback_response_send(NX_HTTP_SERVER * server_ptr,CHAR * header,CHAR * information,CHAR * additional_info)2585 UINT _nxe_http_server_callback_response_send(NX_HTTP_SERVER *server_ptr, CHAR *header, CHAR *information, CHAR *additional_info)
2586 {
2587 UINT status;
2588
2589
2590 /* Check for invalid input pointers. */
2591 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (header == NX_NULL))
2592 return(NX_PTR_ERROR);
2593
2594 /* Check for appropriate caller. */
2595 NX_THREADS_ONLY_CALLER_CHECKING
2596
2597 /* Call actual data send function. */
2598 status = _nx_http_server_callback_response_send(server_ptr, header, information, additional_info);
2599
2600 /* Return completion status. */
2601 return(status);
2602 }
2603
2604
2605 /**************************************************************************/
2606 /* */
2607 /* FUNCTION RELEASE */
2608 /* */
2609 /* _nx_http_server_callback_response_send PORTABLE C */
2610 /* 6.1 */
2611 /* AUTHOR */
2612 /* */
2613 /* Yuxin Zhou, Microsoft Corporation */
2614 /* */
2615 /* DESCRIPTION */
2616 /* */
2617 /* This function sends the completion response to the client from the */
2618 /* application callback function. This is typically done to satisfy a */
2619 /* GET or POST request that is processed completely by the application */
2620 /* callback function. */
2621 /* */
2622 /* */
2623 /* INPUT */
2624 /* */
2625 /* http_server_ptr Pointer to HTTP server */
2626 /* header Pointer to HTTP header string */
2627 /* information Pointer to HTTP info string */
2628 /* additional_information Pointer to additional HTTP */
2629 /* information */
2630 /* */
2631 /* OUTPUT */
2632 /* */
2633 /* status Completion status */
2634 /* */
2635 /* CALLS */
2636 /* */
2637 /* _nx_http_server_response_send Send HTTP response */
2638 /* _nx_utility_string_length_check Check string length */
2639 /* */
2640 /* CALLED BY */
2641 /* */
2642 /* Application Code */
2643 /* */
2644 /* RELEASE HISTORY */
2645 /* */
2646 /* DATE NAME DESCRIPTION */
2647 /* */
2648 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2649 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2650 /* resulting in version 6.1 */
2651 /* */
2652 /**************************************************************************/
_nx_http_server_callback_response_send(NX_HTTP_SERVER * server_ptr,CHAR * header,CHAR * information,CHAR * additional_info)2653 UINT _nx_http_server_callback_response_send(NX_HTTP_SERVER *server_ptr, CHAR *header, CHAR *information, CHAR *additional_info)
2654 {
2655
2656 UINT header_length = 0;
2657 UINT information_length = 0;
2658 UINT additional_info_length = 0;
2659 UINT status;
2660
2661 /* Check length of header, information and additional information. */
2662 if (_nx_utility_string_length_check(header, &header_length, NX_MAX_STRING_LENGTH) ||
2663 (information && _nx_utility_string_length_check(information, &information_length, NX_MAX_STRING_LENGTH)) ||
2664 (additional_info && _nx_utility_string_length_check(additional_info, &additional_info_length, NX_MAX_STRING_LENGTH)))
2665 {
2666 return(NX_HTTP_ERROR);
2667 }
2668
2669 /* Call the internal HTTP response send function. */
2670 status = _nx_http_server_response_send(server_ptr, header, header_length, information, information_length, additional_info, additional_info_length);
2671
2672 /* Return status. */
2673 return(status);
2674 }
2675
2676
2677 /**************************************************************************/
2678 /* */
2679 /* FUNCTION RELEASE */
2680 /* */
2681 /* _nxe_http_server_callback_response_send_extended PORTABLE C */
2682 /* 6.1 */
2683 /* AUTHOR */
2684 /* */
2685 /* Yuxin Zhou, Microsoft Corporation */
2686 /* */
2687 /* DESCRIPTION */
2688 /* */
2689 /* This function checks errors for sending HTTP response. */
2690 /* */
2691 /* */
2692 /* INPUT */
2693 /* */
2694 /* http_server_ptr Pointer to HTTP server */
2695 /* header Pointer to HTTP header string */
2696 /* header_length Length of HTTP header string */
2697 /* information Pointer to HTTP info string */
2698 /* information_length Length of HTTP info string */
2699 /* additional_info Pointer to additional HTTP */
2700 /* information */
2701 /* additional_info_length Length of additional HTTP */
2702 /* information */
2703 /* */
2704 /* OUTPUT */
2705 /* */
2706 /* status Completion status */
2707 /* */
2708 /* CALLS */
2709 /* */
2710 /* _nx_http_server_callback_response_send_extended */
2711 /* Actual HTTP response send call*/
2712 /* */
2713 /* CALLED BY */
2714 /* */
2715 /* Application Code */
2716 /* */
2717 /* RELEASE HISTORY */
2718 /* */
2719 /* DATE NAME DESCRIPTION */
2720 /* */
2721 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2722 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2723 /* resulting in version 6.1 */
2724 /* */
2725 /**************************************************************************/
_nxe_http_server_callback_response_send_extended(NX_HTTP_SERVER * server_ptr,CHAR * header,UINT header_length,CHAR * information,UINT information_length,CHAR * additional_info,UINT additional_info_length)2726 UINT _nxe_http_server_callback_response_send_extended(NX_HTTP_SERVER *server_ptr, CHAR *header, UINT header_length, CHAR *information,
2727 UINT information_length, CHAR *additional_info, UINT additional_info_length)
2728 {
2729 UINT status;
2730
2731
2732 /* Check for invalid input pointers. */
2733 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (header == NX_NULL))
2734 return(NX_PTR_ERROR);
2735
2736 /* Check for appropriate caller. */
2737 NX_THREADS_ONLY_CALLER_CHECKING
2738
2739 /* Call actual data send function. */
2740 status = _nx_http_server_callback_response_send_extended(server_ptr, header, header_length, information,
2741 information_length, additional_info, additional_info_length);
2742
2743 /* Return completion status. */
2744 return(status);
2745 }
2746
2747
2748 /**************************************************************************/
2749 /* */
2750 /* FUNCTION RELEASE */
2751 /* */
2752 /* _nx_http_server_callback_response_send_extended PORTABLE C */
2753 /* 6.1 */
2754 /* AUTHOR */
2755 /* */
2756 /* Yuxin Zhou, Microsoft Corporation */
2757 /* */
2758 /* DESCRIPTION */
2759 /* */
2760 /* This function sends the completion response to the client from the */
2761 /* application callback function. This is typically done to satisfy a */
2762 /* GET or POST request that is processed completely by the application */
2763 /* callback function. */
2764 /* */
2765 /* Note: The strings of header, information and additional info must */
2766 /* be NULL-terminated and length of this string matches the length */
2767 /* specified in the argument list. */
2768 /* */
2769 /* */
2770 /* INPUT */
2771 /* */
2772 /* http_server_ptr Pointer to HTTP server */
2773 /* header Pointer to HTTP header string */
2774 /* header_length Length of HTTP header string */
2775 /* information Pointer to HTTP info string */
2776 /* information_length Length of HTTP info string */
2777 /* additional_info Pointer to additional HTTP */
2778 /* information */
2779 /* additional_info_length Length of additional HTTP */
2780 /* information */
2781 /* */
2782 /* OUTPUT */
2783 /* */
2784 /* status Completion status */
2785 /* */
2786 /* CALLS */
2787 /* */
2788 /* _nx_http_server_response_send Send HTTP response */
2789 /* _nx_utility_string_length_check Check string length */
2790 /* */
2791 /* CALLED BY */
2792 /* */
2793 /* Application Code */
2794 /* */
2795 /* RELEASE HISTORY */
2796 /* */
2797 /* DATE NAME DESCRIPTION */
2798 /* */
2799 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2800 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2801 /* resulting in version 6.1 */
2802 /* */
2803 /**************************************************************************/
_nx_http_server_callback_response_send_extended(NX_HTTP_SERVER * server_ptr,CHAR * header,UINT header_length,CHAR * information,UINT information_length,CHAR * additional_info,UINT additional_info_length)2804 UINT _nx_http_server_callback_response_send_extended(NX_HTTP_SERVER *server_ptr, CHAR *header, UINT header_length, CHAR *information,
2805 UINT information_length, CHAR *additional_info, UINT additional_info_length)
2806 {
2807 UINT status;
2808 UINT temp_header_length = 0;
2809 UINT temp_information_length = 0;
2810 UINT temp_additional_info_length = 0;
2811
2812 /* Check length of header, information and additional information. */
2813 if (_nx_utility_string_length_check(header, &temp_header_length, NX_MAX_STRING_LENGTH) ||
2814 (information && _nx_utility_string_length_check(information, &temp_information_length, NX_MAX_STRING_LENGTH)) ||
2815 (additional_info && _nx_utility_string_length_check(additional_info, &temp_additional_info_length, NX_MAX_STRING_LENGTH)))
2816 {
2817 return(NX_HTTP_ERROR);
2818 }
2819
2820 /* Validate string length. */
2821 if ((temp_header_length != header_length) ||
2822 (information && (temp_information_length != information_length)) ||
2823 (additional_info && (temp_additional_info_length != additional_info_length)))
2824 {
2825 return(NX_HTTP_ERROR);
2826 }
2827
2828 /* Call the internal HTTP response send function. */
2829 status = _nx_http_server_response_send(server_ptr, header, header_length, information, information_length, additional_info, additional_info_length);
2830
2831 /* Return status. */
2832 return(status);
2833 }
2834
2835
2836 /**************************************************************************/
2837 /* */
2838 /* FUNCTION RELEASE */
2839 /* */
2840 /* _nx_http_server_connection_present PORTABLE C */
2841 /* 6.1 */
2842 /* AUTHOR */
2843 /* */
2844 /* Yuxin Zhou, Microsoft Corporation */
2845 /* */
2846 /* DESCRIPTION */
2847 /* */
2848 /* This function is the callback function executed whenever a client */
2849 /* connection appears on the HTTP Server port. It is responsible for */
2850 /* waking up the HTTP Server thread. */
2851 /* */
2852 /* */
2853 /* INPUT */
2854 /* */
2855 /* socket_ptr Pointer to HTTP Server socket */
2856 /* port HTTP Server port */
2857 /* */
2858 /* OUTPUT */
2859 /* */
2860 /* None */
2861 /* */
2862 /* CALLS */
2863 /* */
2864 /* tx_thread_resume Server thread resume */
2865 /* */
2866 /* CALLED BY */
2867 /* */
2868 /* NetX */
2869 /* */
2870 /* RELEASE HISTORY */
2871 /* */
2872 /* DATE NAME DESCRIPTION */
2873 /* */
2874 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2875 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2876 /* resulting in version 6.1 */
2877 /* */
2878 /**************************************************************************/
_nx_http_server_connection_present(NX_TCP_SOCKET * socket_ptr,UINT port)2879 VOID _nx_http_server_connection_present(NX_TCP_SOCKET *socket_ptr, UINT port)
2880 {
2881
2882 NX_HTTP_SERVER *server_ptr;
2883
2884 NX_PARAMETER_NOT_USED(port);
2885
2886 /* Pickup the server pointer. */
2887 server_ptr = (NX_HTTP_SERVER *) socket_ptr -> nx_tcp_socket_reserved_ptr;
2888
2889 /* Set the connection pending flag. */
2890 server_ptr -> nx_http_connection_pending = NX_TRUE;
2891
2892 /* Resume the HTTP Server thread. */
2893 tx_thread_resume(&(server_ptr -> nx_http_server_thread));
2894 }
2895
2896
2897 /**************************************************************************/
2898 /* */
2899 /* FUNCTION RELEASE */
2900 /* */
2901 /* _nx_http_server_thread_entry PORTABLE C */
2902 /* 6.2.0 */
2903 /* AUTHOR */
2904 /* */
2905 /* Yuxin Zhou, Microsoft Corporation */
2906 /* */
2907 /* DESCRIPTION */
2908 /* */
2909 /* This function is the entry of the HTTP server. All basic */
2910 /* processing is initiated by this function. */
2911 /* */
2912 /* */
2913 /* INPUT */
2914 /* */
2915 /* http_server_address Pointer to HTTP server */
2916 /* */
2917 /* OUTPUT */
2918 /* */
2919 /* status Completion status */
2920 /* */
2921 /* CALLS */
2922 /* */
2923 /* _nx_http_server_delete_process Process client DELETE request */
2924 /* _nx_http_server_get_client_request Get complete HTTP request */
2925 /* _nx_http_server_get_process Process client GET request */
2926 /* _nx_http_server_put_process Process client PUT request */
2927 /* _nx_http_server_response_send Send HTTP Server response */
2928 /* nx_packet_release Release request packet */
2929 /* nx_tcp_server_socket_accept Accept HTTP client connect */
2930 /* _nx_http_server_disconnect Disconnect HTTP server socket */
2931 /* nx_tcp_server_socket_relisten Relisten for another HTTP */
2932 /* client connection */
2933 /* tx_thread_preemption_change Disable/restore preemption */
2934 /* tx_thread_suspend Self suspend HTTP thread */
2935 /* */
2936 /* CALLED BY */
2937 /* */
2938 /* ThreadX */
2939 /* */
2940 /* RELEASE HISTORY */
2941 /* */
2942 /* DATE NAME DESCRIPTION */
2943 /* */
2944 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2945 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2946 /* resulting in version 6.1 */
2947 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
2948 /* supported random nonce, */
2949 /* resulting in version 6.2.0 */
2950 /* */
2951 /**************************************************************************/
_nx_http_server_thread_entry(ULONG http_server)2952 VOID _nx_http_server_thread_entry(ULONG http_server)
2953 {
2954
2955 NX_HTTP_SERVER *server_ptr;
2956 NX_PACKET *packet_ptr;
2957 UCHAR *buffer_ptr;
2958 UINT original_threshold;
2959 UINT status;
2960 UINT loop_endlessly = NX_TRUE;
2961
2962
2963 /* Set the HTTP server pointer. */
2964 server_ptr = (NX_HTTP_SERVER *) http_server;
2965
2966 /* Loop to process HTTP Server requests. */
2967 while(loop_endlessly)
2968 {
2969
2970 /* Temporarily disable preemption. */
2971 tx_thread_preemption_change(&(server_ptr -> nx_http_server_thread), 0, &original_threshold);
2972
2973 /* Is the connection pending flag not set? */
2974 if (server_ptr -> nx_http_connection_pending == NX_FALSE)
2975 {
2976
2977 /* If not, suspend the server thread. */
2978 tx_thread_suspend(&(server_ptr -> nx_http_server_thread));
2979 }
2980
2981 /* Clear the connection pending flag. */
2982 server_ptr -> nx_http_connection_pending = NX_FALSE;
2983
2984 /* Restore preemption. */
2985 tx_thread_preemption_change(&(server_ptr -> nx_http_server_thread), original_threshold, &original_threshold);
2986
2987 /* Wait for connection on HTTP Server port. */
2988 status = nx_tcp_server_socket_accept(&(server_ptr -> nx_http_server_socket), NX_HTTP_SERVER_TIMEOUT_ACCEPT);
2989
2990 /* Determine if we have an HTTP connection error. */
2991 if (status != NX_SUCCESS)
2992 {
2993
2994 /* Increment the number of failed connections. */
2995 server_ptr -> nx_http_server_connection_failures++;
2996
2997 /* Unaccept the connection. */
2998 nx_tcp_server_socket_unaccept(&(server_ptr -> nx_http_server_socket));
2999
3000 /* Relisten on the HTTP Server port. */
3001 nx_tcp_server_socket_relisten(server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT,
3002 &(server_ptr -> nx_http_server_socket));
3003 /* Restart the loop. */
3004 continue;
3005 }
3006
3007 /* Increment the number of successful connections. */
3008 server_ptr -> nx_http_server_connection_successes++;
3009
3010 /* Get the complete HTTP client request. */
3011 status = _nx_http_server_get_client_request(server_ptr, &packet_ptr);
3012
3013 /* Check if the HTTP request is valid. */
3014 if (status == NX_SUCCESS)
3015 {
3016 if (packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr < 7)
3017 {
3018 nx_packet_release(packet_ptr);
3019 status = NX_HTTP_ERROR;
3020 }
3021 }
3022
3023 /* Determine if it was successful. */
3024 if (status != NX_SUCCESS)
3025 {
3026
3027 if(status != NX_NO_PACKET)
3028 {
3029
3030 /* Increment the number of invalid HTTP requests. */
3031 server_ptr -> nx_http_server_invalid_http_headers++;
3032 }
3033
3034 /* Disconnect from the current connection. */
3035 _nx_http_server_disconnect(server_ptr, NX_HTTP_SERVER_TIMEOUT_DISCONNECT);
3036
3037 /* Relisten on the HTTP Server port. */
3038 nx_tcp_server_socket_relisten(server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT,
3039 &(server_ptr -> nx_http_server_socket));
3040 /* Restart the loop. */
3041 continue;
3042 }
3043
3044 /* Otherwise, we have received an HTTP client request successfully. */
3045
3046 /* Setup a pointer to packet buffer area. */
3047 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr;
3048
3049 /* Determine what type of request is present. */
3050
3051 /* Check for a GET request. */
3052 if ((buffer_ptr[0] == 'G') && (buffer_ptr[1] == 'E') && (buffer_ptr[2] == 'T') && (buffer_ptr[3] == ' '))
3053 {
3054
3055 /* We have a HTTP GET request to get a resource from this HTTP Server. */
3056 server_ptr -> nx_http_server_request_type = NX_HTTP_SERVER_GET_REQUEST;
3057
3058 /* Increment the number of GET requests. */
3059 server_ptr -> nx_http_server_get_requests++;
3060
3061 /* Process the GET request. */
3062 _nx_http_server_get_process(server_ptr, NX_HTTP_SERVER_GET_REQUEST, packet_ptr);
3063 }
3064
3065 /* Check for a PUT request. */
3066 else if ((buffer_ptr[0] == 'P') && (buffer_ptr[1] == 'U') && (buffer_ptr[2] == 'T') && (buffer_ptr[3] == ' '))
3067 {
3068
3069 /* We have a HTTP PUT request to store a resource on this HTTP Server. */
3070 server_ptr -> nx_http_server_request_type = NX_HTTP_SERVER_PUT_REQUEST;
3071
3072 /* Increment the number of PUT requests. */
3073 server_ptr -> nx_http_server_put_requests++;
3074
3075 /* Process the PUT request. */
3076 _nx_http_server_put_process(server_ptr, packet_ptr);
3077 }
3078
3079 /* Check for a DELETE request. */
3080 else if ((buffer_ptr[0] == 'D') && (buffer_ptr[1] == 'E') && (buffer_ptr[2] == 'L') && (buffer_ptr[3] == 'E') &&
3081 (buffer_ptr[4] == 'T') && (buffer_ptr[5] == 'E') && (buffer_ptr[6] == ' '))
3082 {
3083
3084 /* We have a HTTP DELETE request to delete a resource from this HTTP Server. */
3085 server_ptr -> nx_http_server_request_type = NX_HTTP_SERVER_DELETE_REQUEST;
3086
3087 /* Increment the number of DELETE requests. */
3088 server_ptr -> nx_http_server_delete_requests++;
3089
3090 /* Process the Delete request. */
3091 _nx_http_server_delete_process(server_ptr, packet_ptr);
3092 }
3093
3094 /* Check for a POST request. */
3095 else if ((buffer_ptr[0] == 'P') && (buffer_ptr[1] == 'O') && (buffer_ptr[2] == 'S') &&
3096 (buffer_ptr[3] == 'T') && (buffer_ptr[4] == ' '))
3097 {
3098
3099 /* We have a HTTP POST request to send data to this HTTP Server for processing. Note that the POST
3100 request is nearly identical to the GET request, except the parameter/query data is found in the
3101 content rather than as part of the URL (resource). */
3102 server_ptr -> nx_http_server_request_type = NX_HTTP_SERVER_POST_REQUEST;
3103
3104 /* Increment the number of POST requests. */
3105 server_ptr -> nx_http_server_post_requests++;
3106
3107 #ifdef NX_HTTP_MULTIPART_ENABLE
3108
3109 /* Reset last received multipart packet. */
3110 server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet = NX_NULL;
3111 #endif /* NX_HTTP_MULTIPART_ENABLE */
3112
3113 /* Process the POST request. */
3114 _nx_http_server_get_process(server_ptr, NX_HTTP_SERVER_POST_REQUEST, packet_ptr);
3115
3116 #ifdef NX_HTTP_MULTIPART_ENABLE
3117 /* Restore the packet to release. */
3118 if (server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet)
3119 packet_ptr = server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet;
3120 #endif /* NX_HTTP_MULTIPART_ENABLE */
3121 }
3122
3123 /* Check for a HEAD request. */
3124 else if ((buffer_ptr[0] == 'H') && (buffer_ptr[1] == 'E') && (buffer_ptr[2] == 'A') &&
3125 (buffer_ptr[3] == 'D') && (buffer_ptr[4] == ' '))
3126 {
3127
3128 /* We have a HTTP HEAD request to get a resource header from this HTTP Server. Note that the HEAD
3129 request is nearly identical to the GET request, except the requested content is not returned to
3130 the client. */
3131 server_ptr -> nx_http_server_request_type = NX_HTTP_SERVER_HEAD_REQUEST;
3132
3133 /* Increment the number of HEAD requests. */
3134 server_ptr -> nx_http_server_head_requests++;
3135
3136 /* Process the HEAD request. */
3137 _nx_http_server_get_process(server_ptr, NX_HTTP_SERVER_HEAD_REQUEST, packet_ptr);
3138 }
3139
3140 /* Unhandled request. */
3141 else
3142 {
3143
3144 /* We have an unhandled HTTP request. */
3145 server_ptr -> nx_http_server_request_type = NX_HTTP_SERVER_UNKNOWN_REQUEST;
3146
3147 /* Send response back to HTTP Client. */
3148 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_NOT_IMPLEMENTED, sizeof(NX_HTTP_STATUS_NOT_IMPLEMENTED) - 1,
3149 "NetX HTTP Request Not Implemented", sizeof("NetX HTTP Request Not Implemented") - 1, NX_NULL, 0);
3150
3151 /* Increment the number of unhandled requests. */
3152 server_ptr -> nx_http_server_unknown_requests++;
3153 }
3154
3155 /* Release the packet. */
3156 nx_packet_release(packet_ptr);
3157
3158 /* Disconnect from the current connection. */
3159 _nx_http_server_disconnect(server_ptr, NX_HTTP_SERVER_TIMEOUT_DISCONNECT);
3160
3161 /* Relisten on the HTTP Server port. */
3162 nx_tcp_server_socket_relisten(server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT,
3163 &(server_ptr -> nx_http_server_socket));
3164 }
3165
3166 return;
3167 }
3168
3169
3170 /**************************************************************************/
3171 /* */
3172 /* FUNCTION RELEASE */
3173 /* */
3174 /* _nx_http_server_get_client_request PORTABLE C */
3175 /* 6.1 */
3176 /* AUTHOR */
3177 /* */
3178 /* Yuxin Zhou, Microsoft Corporation */
3179 /* */
3180 /* DESCRIPTION */
3181 /* */
3182 /* This function builds the complete HTTP client request in a single */
3183 /* NetX packet. Doing this makes the other parsing and searching */
3184 /* routines simple. */
3185 /* */
3186 /* */
3187 /* INPUT */
3188 /* */
3189 /* server_ptr HTTP Server pointer */
3190 /* packet_ptr Destination for request */
3191 /* packet pointer */
3192 /* */
3193 /* OUTPUT */
3194 /* */
3195 /* status Completion status */
3196 /* */
3197 /* CALLS */
3198 /* */
3199 /* nx_packet_copy Copy packet */
3200 /* nx_packet_data_append Move data into packet */
3201 /* nx_packet_release Release packet */
3202 /* nx_tcp_socket_receive Receive an HTTP request packet*/
3203 /* */
3204 /* CALLED BY */
3205 /* */
3206 /* _nx_http_server_thread_entry HTTP Server thread */
3207 /* */
3208 /* RELEASE HISTORY */
3209 /* */
3210 /* DATE NAME DESCRIPTION */
3211 /* */
3212 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3213 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3214 /* resulting in version 6.1 */
3215 /* */
3216 /**************************************************************************/
_nx_http_server_get_client_request(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_ptr)3217 UINT _nx_http_server_get_client_request(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr)
3218 {
3219
3220 NX_PACKET *head_packet_ptr;
3221 NX_PACKET *new_packet_ptr;
3222 CHAR *buffer_ptr;
3223 UINT status;
3224 NX_PACKET *work_ptr;
3225 UINT crlf_found = 0;
3226 NX_PACKET *tmp_ptr;
3227
3228
3229 /* Default the return packet pointer to NULL. */
3230 *packet_ptr = NX_NULL;
3231
3232 /* Wait for a request on the HTTP TCP well know port 80. */
3233 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &head_packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
3234
3235 /* At this point we have a connection setup with an HTTP server! */
3236
3237 /* Check the return status. */
3238 if (status != NX_SUCCESS)
3239 {
3240
3241 /* Return an error condition. */
3242 return(status);
3243 }
3244
3245 /* Setup pointer to start of buffer. */
3246 buffer_ptr = (CHAR *) head_packet_ptr -> nx_packet_prepend_ptr;
3247
3248 /* Determine if the packet is an HTTP request. */
3249 if ((buffer_ptr[0] != 'G') && (buffer_ptr[0] != 'g') && (buffer_ptr[0] != 'P') && (buffer_ptr[0] != 'p') &&
3250 (buffer_ptr[0] != 'D') && (buffer_ptr[0] != 'd') && (buffer_ptr[0] != 'H') && (buffer_ptr[0] != 'h') &&
3251 (buffer_ptr[0] != 'T') && (buffer_ptr[0] != 't'))
3252 {
3253
3254 /* Invalid first packet for HTTP request. */
3255
3256 /* Release the packet. */
3257 nx_packet_release(head_packet_ptr);
3258
3259 /* Return an error. */
3260 return(NX_HTTP_ERROR);
3261 }
3262
3263 /* Determine if this packet is large enough. */
3264 if (((head_packet_ptr -> nx_packet_data_end - head_packet_ptr -> nx_packet_data_start) -
3265 NX_PHYSICAL_TRAILER)< NX_HTTP_SERVER_MIN_PACKET_SIZE)
3266 {
3267
3268 /* Copy the packet into a packet allocated from the Server's packet pool (which must have packets
3269 with a payload size >= NX_HTTP_SERVER_MIN_PACKET_SIZE. */
3270 status = nx_packet_copy(head_packet_ptr, &new_packet_ptr, server_ptr -> nx_http_server_packet_pool_ptr, NX_HTTP_SERVER_TIMEOUT);
3271
3272 /* Determine if the packet copy was successful. */
3273 if (status != NX_SUCCESS)
3274 {
3275
3276 /* Error in packet copy. Release packet and return an error. */
3277 nx_packet_release(head_packet_ptr);
3278 return(status);
3279 }
3280
3281 /* Copy is successful, release the original pointer and move the new pointer to the head pointer. */
3282 nx_packet_release(head_packet_ptr);
3283 head_packet_ptr = new_packet_ptr;
3284 }
3285
3286 crlf_found = 0;
3287 work_ptr = head_packet_ptr;
3288
3289 /* Build a pointer to the buffer area. */
3290 buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr;
3291
3292 do
3293 {
3294
3295 /* See if there is a blank line present in the buffer. */
3296 /* Search the buffer for a cr/lf pair. */
3297 while (buffer_ptr < (CHAR *) work_ptr -> nx_packet_append_ptr)
3298 {
3299 if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13))
3300 {
3301
3302 /* Found CR. */
3303 crlf_found++;
3304 }
3305 else if((crlf_found & 1) && (*buffer_ptr == (CHAR)10))
3306 {
3307
3308 /* Found LF. */
3309 crlf_found++;
3310 }
3311 else
3312 {
3313
3314 /* Reset the CRLF marker. */
3315 crlf_found = 0;
3316 }
3317
3318 if (crlf_found == 4)
3319 {
3320
3321 /* Yes, we have found the end of the HTTP request header. */
3322
3323 /* Set the return packet pointer. */
3324 *packet_ptr = head_packet_ptr;
3325
3326 /* Return a successful completion. */
3327 return(NX_SUCCESS);
3328 }
3329
3330 /* Move the buffer pointer up. */
3331 buffer_ptr++;
3332 }
3333
3334 /* Determine if the packet has already overflowed into another packet. */
3335
3336 #ifndef NX_DISABLE_PACKET_CHAIN
3337
3338 if (work_ptr -> nx_packet_next != NX_NULL)
3339 {
3340 /* Get the next packet in the chain. */
3341 work_ptr = work_ptr -> nx_packet_next;
3342 buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr;
3343 }
3344 else
3345
3346 #endif
3347 {
3348 /* Receive another packet from the HTTP server port. */
3349 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
3350
3351 /* Check the return status. */
3352 if (status != NX_SUCCESS)
3353 {
3354
3355 /* Release the current head packet. */
3356 nx_packet_release(head_packet_ptr);
3357
3358 /* Return an error condition. */
3359 return(status);
3360 }
3361
3362 /* Successfully received another packet. Its contents now need to be placed in the head packet. */
3363 tmp_ptr = new_packet_ptr;
3364 #ifndef NX_DISABLE_PACKET_CHAIN
3365 while (tmp_ptr)
3366 {
3367 #endif /* NX_DISABLE_PACKET_CHAIN */
3368
3369 /* Copy the contents of the current packet into the head packet. */
3370 status = nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr,
3371 (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr),
3372 server_ptr -> nx_http_server_packet_pool_ptr, NX_HTTP_SERVER_TIMEOUT);
3373
3374 /* Determine if an error occurred. */
3375 if (status != NX_SUCCESS)
3376 {
3377
3378 /* Yes, an error is present. */
3379
3380 /* Release both packets. */
3381 nx_packet_release(head_packet_ptr);
3382 nx_packet_release(new_packet_ptr);
3383
3384 /* Return an error condition. */
3385 return(status);
3386 }
3387
3388 #ifndef NX_DISABLE_PACKET_CHAIN
3389 tmp_ptr = tmp_ptr -> nx_packet_next;
3390 }
3391 #endif /* NX_DISABLE_PACKET_CHAIN */
3392
3393 /* Release the new packet. */
3394 nx_packet_release(new_packet_ptr);
3395 }
3396
3397 } while (status == NX_SUCCESS);
3398
3399 /* Release the packet. */
3400 nx_packet_release(head_packet_ptr);
3401
3402 return NX_HTTP_ERROR;
3403 }
3404
3405
3406 /**************************************************************************/
3407 /* */
3408 /* FUNCTION RELEASE */
3409 /* */
3410 /* _nx_http_server_get_process PORTABLE C */
3411 /* 6.1 */
3412 /* AUTHOR */
3413 /* */
3414 /* Yuxin Zhou, Microsoft Corporation */
3415 /* */
3416 /* DESCRIPTION */
3417 /* */
3418 /* This function processes the GET, POST, and HEAD HTTP client */
3419 /* requests. */
3420 /* */
3421 /* */
3422 /* INPUT */
3423 /* */
3424 /* server_ptr HTTP Server pointer */
3425 /* request_type Type of request (GET, POST, */
3426 /* or HEAD) */
3427 /* packet_ptr Request packet pointer */
3428 /* */
3429 /* OUTPUT */
3430 /* */
3431 /* None */
3432 /* */
3433 /* CALLS */
3434 /* */
3435 /* _nx_http_server_basic_authenticate Process basic authentication */
3436 /* _nx_http_server_digest_authenticate Process digest authentication */
3437 /* _nx_http_server_calculate_content_offset Retrieve content offset */
3438 /* _nx_http_server_content_length_get Retrieve content length */
3439 /* _nx_http_server_response_send Send response back to client */
3440 /* _nx_http_server_retrieve_resource Retrieve resource from request*/
3441 /* _nx_http_server_type_get_extended Derive file type */
3442 /* fx_directory_information_get Get length of resource file */
3443 /* fx_file_close Close resource file */
3444 /* fx_file_open Open resource file */
3445 /* fx_file_read Read data from resource file */
3446 /* nx_packet_allocate Allocate a new packet */
3447 /* nx_packet_data_append Append information to response*/
3448 /* nx_packet_release Release packet */
3449 /* nx_tcp_socket_send Send HTTP Server response */
3450 /* */
3451 /* CALLED BY */
3452 /* */
3453 /* _nx_http_server_thread_entry HTTP Server thread */
3454 /* */
3455 /* RELEASE HISTORY */
3456 /* */
3457 /* DATE NAME DESCRIPTION */
3458 /* */
3459 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3460 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3461 /* resulting in version 6.1 */
3462 /* */
3463 /**************************************************************************/
_nx_http_server_get_process(NX_HTTP_SERVER * server_ptr,UINT request_type,NX_PACKET * packet_ptr)3464 VOID _nx_http_server_get_process(NX_HTTP_SERVER *server_ptr, UINT request_type, NX_PACKET *packet_ptr)
3465 {
3466
3467 ULONG length = 0;
3468 UINT status;
3469 NX_PACKET *new_packet_ptr;
3470 CHAR *name_ptr;
3471 CHAR *password_ptr;
3472 CHAR *realm_ptr;
3473 ULONG temp;
3474 CHAR temp_string[30];
3475 UINT auth_request_present = NX_FALSE;
3476 UINT resource_length;
3477 UINT name_length = 0;
3478 UINT password_length = 0;
3479 UINT realm_length = 0;
3480 UINT temp_name_length = 0;
3481 UINT temp_password_length = 0;
3482 UINT temp_realm_length = 0;
3483
3484
3485 /* Pickup the URL (resource) from the request. */
3486 status = _nx_http_server_retrieve_resource(packet_ptr, server_ptr -> nx_http_server_request_resource, NX_HTTP_MAX_RESOURCE + 1);
3487
3488 /* Determine if the resource was extracted successfully. */
3489 if (status != NX_SUCCESS)
3490 {
3491
3492 /* Send response back to HTTP Client. */
3493 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
3494 "NetX HTTP URL Bad", sizeof("NetX HTTP URL Bad") - 1, NX_NULL, 0);
3495
3496 /* Error, return to caller. */
3497 return;
3498 }
3499
3500 /* Determine if a POST is present. */
3501 if (request_type == NX_HTTP_SERVER_POST_REQUEST)
3502 {
3503
3504 /* It is. Check for a valid content-length field. */
3505 status = _nx_http_server_content_length_get_extended(packet_ptr, &length);
3506
3507 /* Check for errors. */
3508 if ( status != NX_SUCCESS)
3509 {
3510
3511 /* Send response back to HTTP Client. */
3512 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
3513 "NetX HTTP Invalid Content Length", sizeof("NetX HTTP Invalid Content Length") - 1, NX_NULL, 0);
3514
3515 /* Error, return to caller. */
3516 return;
3517 }
3518
3519 /* Check for an invalid content offset . */
3520 if (_nx_http_server_calculate_content_offset(packet_ptr) == 0)
3521 {
3522
3523 /* Send response back to HTTP Client. */
3524 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
3525 "NetX HTTP Invalid Content Offset", sizeof("NetX HTTP Invalid Content Offset") - 1, NX_NULL, 0);
3526
3527 /* Error, return to caller. */
3528 return;
3529 }
3530
3531 #ifdef NX_HTTP_MULTIPART_ENABLE
3532 /* Cleanup the multipart field. */
3533 memset(&server_ptr -> nx_http_server_multipart, 0, sizeof(NX_HTTP_SERVER_MULTIPART));
3534 #endif /* NX_HTTP_MULTIPART_ENABLE */
3535 }
3536
3537 /* Determine if the application has specified an authentication function for this server. */
3538 if (server_ptr -> nx_http_server_authentication_check ||
3539 server_ptr -> nx_http_server_authentication_check_extended)
3540 {
3541
3542 /* Determine if authentication is required for the specified resource. */
3543 if (server_ptr -> nx_http_server_authentication_check_extended)
3544 {
3545 status = (server_ptr -> nx_http_server_authentication_check_extended)(server_ptr, request_type, server_ptr -> nx_http_server_request_resource,
3546 &name_ptr, &name_length, &password_ptr, &password_length, &realm_ptr, &realm_length);
3547 }
3548 else
3549 {
3550 status = (server_ptr -> nx_http_server_authentication_check)(server_ptr, request_type, server_ptr -> nx_http_server_request_resource,
3551 &name_ptr, &password_ptr, &realm_ptr);
3552 }
3553
3554 if (status == NX_HTTP_BASIC_AUTHENTICATE ||
3555 status == NX_HTTP_DIGEST_AUTHENTICATE)
3556 {
3557
3558 /* Check name, password and realm string. */
3559 if (_nx_utility_string_length_check(name_ptr, &temp_name_length, NX_HTTP_MAX_NAME) ||
3560 _nx_utility_string_length_check(password_ptr, &temp_password_length, NX_HTTP_MAX_PASSWORD) ||
3561 _nx_utility_string_length_check(realm_ptr, &temp_realm_length, NX_MAX_STRING_LENGTH))
3562 {
3563
3564 /* Error, return to caller. */
3565 return;
3566 }
3567
3568 /* Validate string length. */
3569 if (server_ptr -> nx_http_server_authentication_check_extended &&
3570 ((realm_length != temp_realm_length) ||
3571 (name_length != temp_name_length) ||
3572 (password_length != temp_password_length)))
3573 {
3574 return;
3575 }
3576 }
3577
3578 /* Determine what kind - if any - authentication is requested for this resource. */
3579 if (status == NX_HTTP_BASIC_AUTHENTICATE)
3580 {
3581
3582 /* Process basic authentication request. */
3583 status = _nx_http_server_basic_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, temp_realm_length, &auth_request_present);
3584 }
3585 #ifdef NX_HTTP_DIGEST_ENABLE
3586 else if (status == NX_HTTP_DIGEST_AUTHENTICATE)
3587 {
3588
3589 /* Process digest authentication request. */
3590 status = _nx_http_server_digest_authenticate(server_ptr, packet_ptr, name_ptr, temp_name_length, password_ptr, temp_password_length, realm_ptr, temp_realm_length, &auth_request_present);
3591 }
3592 #endif
3593
3594 /* Determine if the authentication failed. */
3595 if ((status != NX_HTTP_DONT_AUTHENTICATE) && (status != NX_SUCCESS))
3596 {
3597
3598 /* Yes it did. Inform the HTTP server application about the failed authentication. */
3599 if (server_ptr -> nx_http_server_invalid_username_password_callback && auth_request_present)
3600 {
3601
3602 NXD_ADDRESS client_nxd_address;
3603 ULONG client_port;
3604
3605 /* Get the IP address of the client: */
3606 status = nxd_tcp_socket_peer_info_get(&(server_ptr->nx_http_server_socket), &client_nxd_address , &client_port);
3607
3608 if (status == NX_SUCCESS)
3609 {
3610 /* Send this information to the host application. */
3611 (server_ptr -> nx_http_server_invalid_username_password_callback)(server_ptr -> nx_http_server_request_resource, &client_nxd_address, request_type);
3612 }
3613 }
3614
3615 return;
3616 }
3617 }
3618
3619 /* Check whether a full response is necessary. */
3620 if((server_ptr -> nx_http_server_cache_info_get) &&
3621 (server_ptr -> nx_http_server_request_type == NX_HTTP_SERVER_GET_REQUEST))
3622 {
3623
3624 /* Searching for "If-Modified-Since" header. */
3625 if(_nx_http_server_field_value_get(packet_ptr, (UCHAR *)"if-modified-since", 17, (UCHAR *)temp_string, sizeof(temp_string)) == NX_SUCCESS)
3626 {
3627 UINT max_age;
3628 NX_HTTP_SERVER_DATE date;
3629 CHAR date_string[30];
3630
3631 /* Get last modified date of this resource. */
3632 if(server_ptr -> nx_http_server_cache_info_get(server_ptr -> nx_http_server_request_resource, &max_age, &date) == NX_TRUE)
3633 {
3634
3635 /* Convert date to string, return length is always 29. */
3636 temp = _nx_http_server_date_to_string(&date, date_string);
3637 date_string[temp] = 0;
3638
3639 /* Check the last modified date with if-modified-since. */
3640 if(memcmp(temp_string, date_string, temp + 1) == 0)
3641 {
3642
3643 /* Send not modified. */
3644 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_NOT_MODIFIED, sizeof(NX_HTTP_STATUS_NOT_MODIFIED) - 1, NX_NULL, 0, NX_NULL, 0);
3645
3646 /* Return to caller. */
3647 return;
3648 }
3649 }
3650 }
3651 }
3652
3653 /* Setup the server socket with a specific packet transmit retry logic. */
3654 nx_tcp_socket_transmit_configure(&(server_ptr -> nx_http_server_socket),
3655 NX_HTTP_SERVER_TRANSMIT_QUEUE_DEPTH,
3656 NX_HTTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE,
3657 NX_HTTP_SERVER_RETRY_MAX,
3658 NX_HTTP_SERVER_RETRY_SHIFT);
3659
3660 /* At this point, either there isn't any required authentication for this resource or the authentication is
3661 complete. */
3662
3663 /* If the HTTP server receives an empty POST request (no message body, content length = 0, it is the
3664 responsibility of the request notify callback to send a response (if any) to the HTTP Client.
3665 The HTTP server will process the request no further. */
3666
3667 /* Determine if a user supplied get function has been specified. */
3668 if (server_ptr -> nx_http_server_request_notify)
3669 {
3670
3671 /* Call the user supplied function to notify the user of the get request. */
3672 status = (server_ptr -> nx_http_server_request_notify)(server_ptr, request_type, server_ptr -> nx_http_server_request_resource, packet_ptr);
3673
3674 #ifdef NX_HTTP_MULTIPART_ENABLE
3675 /* Release the packet that is not processed by callback function. */
3676 if(server_ptr -> nx_http_server_multipart.nx_http_server_multipart_next_packet)
3677 nx_packet_release(server_ptr -> nx_http_server_multipart.nx_http_server_multipart_next_packet);
3678 #endif /* NX_HTTP_MULTIPART_ENABLE */
3679
3680 /* Determine if the user supplied routine is requesting the get should be aborted. */
3681 if (status != NX_SUCCESS)
3682 {
3683
3684 /* Determine if the user callback routine successfully completed the request processing. */
3685 if (status == NX_HTTP_CALLBACK_COMPLETED)
3686 {
3687
3688 /* User callback routine already sent success response back to HTTP Client. */
3689 return;
3690 }
3691
3692 /* Send response back to HTTP Client. */
3693 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
3694 "NetX HTTP Request Aborted", sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
3695
3696 /* Yes, error was detected. Abort the remainder of the get processing. */
3697 return;
3698 }
3699 }
3700
3701 /* Was there a message body in the request? */
3702 if ((request_type == NX_HTTP_SERVER_POST_REQUEST) && (length == 0))
3703 {
3704
3705 /* No. Regardless if a reply was sent via the request notify callback, we are done with this packet. */
3706 return;
3707 }
3708
3709 /* Get the length of request resource. */
3710 if (_nx_utility_string_length_check(server_ptr -> nx_http_server_request_resource, &resource_length,
3711 sizeof(server_ptr -> nx_http_server_request_resource) - 1))
3712 {
3713 return;
3714 }
3715
3716 /* Open the specified file for reading. */
3717 status = fx_file_open(server_ptr -> nx_http_server_media_ptr, &(server_ptr -> nx_http_server_file), server_ptr -> nx_http_server_request_resource, FX_OPEN_FOR_READ);
3718
3719 /* Check for error condition. */
3720 if (status != NX_SUCCESS)
3721 {
3722
3723 /* Send response back to HTTP Client. */
3724 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_NOT_FOUND, sizeof(NX_HTTP_STATUS_NOT_FOUND) - 1,
3725 "NetX HTTP Server unable to find file: ", sizeof("NetX HTTP Server unable to find file: ") - 1, server_ptr -> nx_http_server_request_resource, resource_length);
3726
3727 /* Error, return to caller. */
3728 return;
3729 }
3730
3731 /* Calculate the size of the file. */
3732 length = 0;
3733 fx_directory_information_get(server_ptr -> nx_http_server_media_ptr, server_ptr -> nx_http_server_request_resource, FX_NULL,
3734 &length, FX_NULL, FX_NULL, FX_NULL, FX_NULL, FX_NULL, FX_NULL);
3735
3736 /* Derive the file type. */
3737 temp = (ULONG) _nx_http_server_type_get_extended(server_ptr, server_ptr -> nx_http_server_request_resource, resource_length, temp_string, sizeof(temp_string));
3738 temp_string[temp] = 0;
3739
3740 /* Now build a response header. */
3741 status = _nx_http_server_generate_response_header(server_ptr, &new_packet_ptr, NX_HTTP_STATUS_OK, sizeof(NX_HTTP_STATUS_OK) - 1, length, temp_string, temp, NX_NULL, 0);
3742 if(status)
3743 {
3744
3745 /* Send response back to HTTP Client. */
3746 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
3747 "NetX HTTP Request Aborted", sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
3748
3749 /* Close the file. */
3750 fx_file_close(&(server_ptr -> nx_http_server_file));
3751
3752 /* Error, return to caller. */
3753 return;
3754 }
3755
3756 /* Check to see if only a response is required. */
3757 if ((!length) || (request_type == NX_HTTP_SERVER_HEAD_REQUEST))
3758 {
3759
3760 /* Yes, only a response is required... send it! */
3761 status = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
3762
3763 /* Determine if this is successful. */
3764 if (status != NX_SUCCESS)
3765 {
3766
3767 /* Release the packet. */
3768 nx_packet_release(new_packet_ptr);
3769
3770 /* Force zero length. */
3771 length = 0;
3772 }
3773 }
3774
3775 /* Get length of packet */
3776 temp = new_packet_ptr -> nx_packet_length;
3777
3778 /* Now, loop to send the data contents. If the request type is "HEAD", skip this loop to output the
3779 file contents. */
3780 while ((length) && (request_type != NX_HTTP_SERVER_HEAD_REQUEST))
3781 {
3782
3783 /* Determine if we need to allocate a new packet for data. */
3784 if (!temp)
3785 {
3786
3787 /* Yes, allocate a new packet. */
3788 status = nx_packet_allocate(server_ptr -> nx_http_server_packet_pool_ptr, &new_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
3789
3790 /* Determine if an error is present. */
3791 if (status != NX_SUCCESS)
3792 {
3793
3794 /* Indicate an allocation error occurred. */
3795 server_ptr -> nx_http_server_allocation_errors++;
3796
3797 /* Error, return to caller. */
3798 break;
3799 }
3800 }
3801
3802 /* Calculate the maximum length. */
3803 temp = ((ULONG) (new_packet_ptr -> nx_packet_data_end - new_packet_ptr -> nx_packet_append_ptr)) - NX_PHYSICAL_TRAILER;
3804
3805 /* Determine if this exceeds the MSS of the peer. */
3806 if (temp > server_ptr -> nx_http_server_socket.nx_tcp_socket_connect_mss)
3807 {
3808
3809 /* Yes, reduce the maximum size to the mss size. */
3810 temp = server_ptr -> nx_http_server_socket.nx_tcp_socket_connect_mss;
3811 }
3812
3813 /* Read data from the file. */
3814 status = fx_file_read(&(server_ptr -> nx_http_server_file), new_packet_ptr -> nx_packet_append_ptr,
3815 temp, &temp);
3816
3817 /* Check for an error. */
3818 if (status != NX_SUCCESS)
3819 {
3820
3821 /* Release the packet. */
3822 nx_packet_release(new_packet_ptr);
3823
3824 /* Error, return. */
3825 break;
3826 }
3827
3828 /* Update the packet information with the data read. */
3829 new_packet_ptr -> nx_packet_length = new_packet_ptr -> nx_packet_length + temp;
3830 new_packet_ptr -> nx_packet_append_ptr = new_packet_ptr -> nx_packet_append_ptr + temp;
3831
3832 /* Send the packet out. */
3833 status = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), new_packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
3834
3835 /* Check for success. */
3836 if (status != NX_SUCCESS)
3837 {
3838
3839 /* Release the packet. */
3840 nx_packet_release(new_packet_ptr);
3841
3842 /* Return to caller. */
3843 break;
3844 }
3845
3846 /* Increment the bytes sent count. */
3847 server_ptr -> nx_http_server_total_bytes_sent = server_ptr -> nx_http_server_total_bytes_sent + temp;
3848
3849 /* Adjust the file length based on what we have sent. */
3850 length = length - temp;
3851
3852 /* Indicate new packet needed */
3853 temp = 0;
3854 }
3855
3856 /* Close the file. */
3857 fx_file_close(&(server_ptr -> nx_http_server_file));
3858 }
3859
3860
3861 /**************************************************************************/
3862 /* */
3863 /* FUNCTION RELEASE */
3864 /* */
3865 /* _nx_http_server_put_process PORTABLE C */
3866 /* 6.1 */
3867 /* AUTHOR */
3868 /* */
3869 /* Yuxin Zhou, Microsoft Corporation */
3870 /* */
3871 /* DESCRIPTION */
3872 /* */
3873 /* This function processes the PUT HTTP client requests. */
3874 /* */
3875 /* */
3876 /* INPUT */
3877 /* */
3878 /* server_ptr HTTP Server pointer */
3879 /* packet_ptr Request packet pointer */
3880 /* */
3881 /* OUTPUT */
3882 /* */
3883 /* None */
3884 /* */
3885 /* CALLS */
3886 /* */
3887 /* _nx_http_server_basic_authenticate Process basic authentication */
3888 /* _nx_http_server_digest_authenticate Process digest authentication */
3889 /* _nx_http_server_calculate_content_offset Retrieve content offset */
3890 /* _nx_http_server_content_length_get Retrieve content length */
3891 /* _nx_http_server_response_send Send response back to client */
3892 /* _nx_http_server_retrieve_resource Retrieve resource from request*/
3893 /* fx_file_close Close resource file */
3894 /* fx_file_create Create resource file */
3895 /* fx_file_open Open resource file */
3896 /* fx_file_write Write data to resource file */
3897 /* nx_packet_allocate Allocate a new packet */
3898 /* nx_packet_data_append Append information to response*/
3899 /* nx_packet_release Release packet */
3900 /* nx_tcp_socket_receive Receive HTTP data from client */
3901 /* nx_tcp_socket_send Send HTTP Server response */
3902 /* */
3903 /* CALLED BY */
3904 /* */
3905 /* _nx_http_server_content_get Content get processing */
3906 /* _nx_http_server_get_process GET request processing */
3907 /* _nx_http_server_put_process PUT request processing */
3908 /* */
3909 /* RELEASE HISTORY */
3910 /* */
3911 /* DATE NAME DESCRIPTION */
3912 /* */
3913 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3914 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3915 /* resulting in version 6.1 */
3916 /* */
3917 /**************************************************************************/
_nx_http_server_put_process(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)3918 VOID _nx_http_server_put_process(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
3919 {
3920
3921 UINT status;
3922 ULONG length;
3923 UINT offset;
3924 CHAR *name_ptr;
3925 CHAR *password_ptr;
3926 CHAR *realm_ptr;
3927 NX_PACKET *data_packet_ptr;
3928 NX_PACKET *next_packet_ptr;
3929 UINT auth_request_present = NX_FALSE;
3930 UINT name_length = 0;
3931 UINT password_length = 0;
3932 UINT realm_length = 0;
3933 UINT temp_name_length = 0;
3934 UINT temp_password_length = 0;
3935 UINT temp_realm_length = 0;
3936
3937
3938 /* Pickup the URL (resource) from the request. */
3939 status = _nx_http_server_retrieve_resource(packet_ptr, server_ptr -> nx_http_server_request_resource, NX_HTTP_MAX_RESOURCE + 1);
3940
3941 /* Determine if the resource was extracted successfully. */
3942 if (status != NX_SUCCESS)
3943 {
3944
3945 /* Send response back to HTTP Client. */
3946 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
3947 "NetX HTTP URL Bad", sizeof("NetX HTTP URL Bad") - 1, NX_NULL, 0);
3948
3949 /* Error, return to caller. */
3950 return;
3951 }
3952
3953 /* Calculate the content length from the request. */
3954 status = _nx_http_server_content_length_get_extended(packet_ptr, &length);
3955
3956 /* Determine if the content length is valid. */
3957 if (status != NX_SUCCESS)
3958 {
3959
3960 /* Send response back to HTTP Client. */
3961 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
3962 "NetX HTTP Invalid Content Length", sizeof("NetX HTTP Invalid Content Length") - 1, NX_NULL, 0);
3963
3964 /* Error, return to caller. */
3965 return;
3966 }
3967
3968 /* Calculate the offset to the content (the two Cr LF tokens) in the request. */
3969 offset = _nx_http_server_calculate_content_offset(packet_ptr);
3970
3971 /* Determine if the offset to the content is valid. */
3972 if (offset == 0)
3973 {
3974
3975 /* Send response back to HTTP Client. */
3976 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
3977 "NetX HTTP Invalid Content Offset", sizeof("NetX HTTP Invalid Content Offset") - 1, NX_NULL, 0);
3978
3979 /* Error, return to caller. */
3980 return;
3981 }
3982
3983 /* Determine if the application has specified an authentication function for this server. */
3984 if (server_ptr -> nx_http_server_authentication_check ||
3985 server_ptr -> nx_http_server_authentication_check_extended)
3986 {
3987
3988 /* Determine if authentication is required for the specified resource. */
3989 if (server_ptr -> nx_http_server_authentication_check_extended)
3990 {
3991 status = (server_ptr -> nx_http_server_authentication_check_extended)(server_ptr, NX_HTTP_SERVER_PUT_REQUEST, server_ptr -> nx_http_server_request_resource,
3992 &name_ptr, &name_length, &password_ptr, &password_length, &realm_ptr, &realm_length);
3993 }
3994 else
3995 {
3996 status = (server_ptr -> nx_http_server_authentication_check)(server_ptr, NX_HTTP_SERVER_PUT_REQUEST, server_ptr -> nx_http_server_request_resource,
3997 &name_ptr, &password_ptr, &realm_ptr);
3998 }
3999
4000 if (status == NX_HTTP_BASIC_AUTHENTICATE ||
4001 status == NX_HTTP_DIGEST_AUTHENTICATE)
4002 {
4003
4004 /* Check name, password and realm string. */
4005 if (_nx_utility_string_length_check(name_ptr, &temp_name_length, NX_HTTP_MAX_NAME) ||
4006 _nx_utility_string_length_check(password_ptr, &temp_password_length, NX_HTTP_MAX_PASSWORD) ||
4007 _nx_utility_string_length_check(realm_ptr, &temp_realm_length, NX_MAX_STRING_LENGTH))
4008 {
4009
4010 /* Error, return to caller. */
4011 return;
4012 }
4013
4014 /* Validate string length. */
4015 if (server_ptr -> nx_http_server_authentication_check_extended &&
4016 ((realm_length != temp_realm_length) ||
4017 (name_length != temp_name_length) ||
4018 (password_length != temp_password_length)))
4019 {
4020 return;
4021 }
4022 }
4023
4024 /* Determine what kind - if any - authentication is requested for this resource. */
4025 if (status == NX_HTTP_BASIC_AUTHENTICATE)
4026 {
4027
4028 /* Process basic authentication request. */
4029 status = _nx_http_server_basic_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, temp_realm_length, &auth_request_present);
4030 }
4031 #ifdef NX_HTTP_DIGEST_ENABLE
4032 else if (status == NX_HTTP_DIGEST_AUTHENTICATE)
4033 {
4034
4035 /* Process digest authentication request. */
4036 status = _nx_http_server_digest_authenticate(server_ptr, packet_ptr, name_ptr, temp_name_length, password_ptr, temp_password_length, realm_ptr, temp_realm_length, &auth_request_present);
4037 }
4038 #endif
4039
4040 /* Determine if the authentication is currently in progress. */
4041 if ((status != NX_HTTP_DONT_AUTHENTICATE) && (status != NX_SUCCESS))
4042 {
4043
4044 /* Yes, authentication is in progress. The HTTP 401 has already been sent. */
4045 if (server_ptr -> nx_http_server_invalid_username_password_callback && auth_request_present)
4046 {
4047
4048 NXD_ADDRESS client_nxd_address;
4049 ULONG client_port;
4050
4051 /* Get the IP address of the client: */
4052 status = nxd_tcp_socket_peer_info_get(&(server_ptr->nx_http_server_socket), &client_nxd_address , &client_port);
4053
4054 if (status == NX_SUCCESS)
4055 {
4056 /* Send this information to the host application. */
4057 (server_ptr -> nx_http_server_invalid_username_password_callback)(server_ptr -> nx_http_server_request_resource, &client_nxd_address, NX_HTTP_SERVER_PUT_REQUEST);
4058 }
4059 }
4060
4061 return;
4062 }
4063 }
4064
4065 /* At this point, either there isn't any required authentication for this resource or the authentication is
4066 complete. */
4067
4068 /* If the request is empty (content-length = 0) the request notify callback is where a response is generated
4069 to return to the Client. NetX HTTP Server will not process an empty request further. */
4070
4071 /* Determine if a user supplied get function has been specified. */
4072 if (server_ptr -> nx_http_server_request_notify)
4073 {
4074
4075 /* Call the user supplied function to notify the user of the put request. */
4076 status = (server_ptr -> nx_http_server_request_notify)(server_ptr, NX_HTTP_SERVER_PUT_REQUEST, server_ptr -> nx_http_server_request_resource, packet_ptr);
4077
4078 /* Determine if the user supplied routine is requesting the put should be aborted. */
4079 if (status != NX_SUCCESS)
4080 {
4081
4082 /* Determine if the user callback routine successfully completed the request processing. */
4083 if (status == NX_HTTP_CALLBACK_COMPLETED)
4084 {
4085
4086 /* Send success response back to HTTP Client. */
4087 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_OK, sizeof(NX_HTTP_STATUS_OK) - 1, NX_NULL, 0, NX_NULL, 0);
4088 return;
4089 }
4090
4091 /* No, an error was detected. Abort the remainder of the get processing. */
4092 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4093 "NetX HTTP Request Aborted", sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
4094 return;
4095 }
4096 }
4097
4098 /* Was there a message body in the request? */
4099 if (length == 0)
4100 {
4101
4102 /* No. Regardless if a reply was sent via the request notify callback, we are done with this packet. */
4103 return;
4104 }
4105
4106 /* Otherwise, everything is okay... complete the request. */
4107
4108 /* Create the specified file. */
4109 status = fx_file_create(server_ptr -> nx_http_server_media_ptr, server_ptr -> nx_http_server_request_resource);
4110
4111
4112 if (status != NX_SUCCESS)
4113 {
4114 /* Send response back to HTTP Client. */
4115 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4116 "NetX HTTP File Create Failed", sizeof("NetX HTTP File Create Failed") - 1, NX_NULL, 0);
4117
4118 /* Error, return to caller. */
4119 return;
4120 }
4121
4122 /* Open the specified file for writing. */
4123 status = fx_file_open(server_ptr -> nx_http_server_media_ptr, &(server_ptr -> nx_http_server_file), server_ptr -> nx_http_server_request_resource, FX_OPEN_FOR_WRITE);
4124
4125 /* Check for error condition. */
4126 if (status != NX_SUCCESS)
4127 {
4128
4129 /* Send response back to HTTP Client. */
4130 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4131 "NetX HTTP File Open Failed", sizeof("NetX HTTP File Open Failed") - 1, NX_NULL, 0);
4132
4133 /* Error, return to caller. */
4134 return;
4135 }
4136
4137
4138 /* Determine if there is any content in the first packet. */
4139 if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > offset)
4140 {
4141
4142 /* Write the content found in this packet. */
4143 status = fx_file_write(&(server_ptr -> nx_http_server_file), (packet_ptr -> nx_packet_prepend_ptr + offset),
4144 ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - offset));
4145
4146 /* Check the status. */
4147 if (status != NX_SUCCESS)
4148 {
4149
4150 /* Send response back to HTTP Client. */
4151 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4152 "NetX HTTP File Write Failed", sizeof("NetX HTTP File Write Failed") - 1, NX_NULL, 0);
4153
4154 /* Error, return to caller. */
4155 return;
4156 }
4157
4158 /* Update the length. */
4159 length = length - ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - offset);
4160
4161 /* Increment the bytes received count. */
4162 server_ptr -> nx_http_server_total_bytes_received = server_ptr -> nx_http_server_total_bytes_received +
4163 ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) - offset);
4164 }
4165
4166
4167 #ifndef NX_DISABLE_PACKET_CHAIN
4168 /* Loop to write chained packets out to the file. */
4169 next_packet_ptr = packet_ptr -> nx_packet_next;
4170 while ((length) && (next_packet_ptr))
4171 {
4172
4173 /* Write the content of the next packet. */
4174 status = fx_file_write(&(server_ptr -> nx_http_server_file), next_packet_ptr -> nx_packet_prepend_ptr,
4175 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr));
4176
4177 /* Check the status. */
4178 if (status != NX_SUCCESS)
4179 {
4180
4181 /* Send response back to HTTP Client. */
4182 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4183 "NetX HTTP File Write Failed", sizeof("NetX HTTP File Write Failed") - 1, NX_NULL, 0);
4184
4185 /* Error, return to caller. */
4186 return;
4187 }
4188
4189 /* Update the length. */
4190 length = length - (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4191
4192 /* Increment the bytes received count. */
4193 server_ptr -> nx_http_server_total_bytes_received = server_ptr -> nx_http_server_total_bytes_received +
4194 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4195
4196 /* Move to the next pointer. */
4197 next_packet_ptr = next_packet_ptr -> nx_packet_next;
4198 }
4199 #endif /* NX_DISABLE_PACKET_CHAIN */
4200
4201 /* If necessary, receive more packets from the TCP socket to complete the write request. */
4202 while (length)
4203 {
4204
4205 /* Wait for a request on the HTTP TCP well know port 80. */
4206 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &data_packet_ptr, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
4207
4208 /* Check the return status. */
4209 if (status != NX_SUCCESS)
4210 {
4211
4212 /* Send response back to HTTP Client. */
4213 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4214 "NetX HTTP Receive Timeout", sizeof("NetX HTTP Receive Timeout") - 1, NX_NULL, 0);
4215
4216 /* Error, return to caller. */
4217 return;
4218 }
4219
4220 /* Loop to write the packet chain out to the file. */
4221 next_packet_ptr = data_packet_ptr;
4222 do
4223 {
4224
4225 /* Write the content of this packet. */
4226 status = fx_file_write(&(server_ptr -> nx_http_server_file), next_packet_ptr -> nx_packet_prepend_ptr,
4227 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr));
4228
4229 /* Check the status. */
4230 if (status != NX_SUCCESS)
4231 {
4232
4233 /* Send response back to HTTP Client. */
4234 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4235 "NetX HTTP File Write Failed", sizeof("NetX HTTP File Write Failed") - 1, NX_NULL, 0);
4236
4237 /* Release the previous data packet. */
4238 nx_packet_release(data_packet_ptr);
4239
4240 /* Error, return to caller. */
4241 return;
4242 }
4243
4244 /* Update the length. */
4245 length = length - (UINT)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4246
4247 /* Increment the bytes received count. */
4248 server_ptr -> nx_http_server_total_bytes_received = server_ptr -> nx_http_server_total_bytes_received +
4249 (ULONG)(next_packet_ptr -> nx_packet_append_ptr - next_packet_ptr -> nx_packet_prepend_ptr);
4250
4251 #ifdef NX_DISABLE_PACKET_CHAIN
4252 next_packet_ptr = NX_NULL;
4253 #else
4254 /* Move to the next pointer. */
4255 next_packet_ptr = next_packet_ptr -> nx_packet_next;
4256 #endif /* NX_DISABLE_PACKET_CHAIN */
4257
4258 } while ((length) && (next_packet_ptr));
4259
4260 /* Release the previous data packet. */
4261 nx_packet_release(data_packet_ptr);
4262 }
4263
4264 /* Success, at this point close the file and prepare a successful response for the client. */
4265 fx_file_close(&(server_ptr -> nx_http_server_file));
4266
4267
4268 /* Now build a response header. */
4269 status = _nx_http_server_generate_response_header(server_ptr, &data_packet_ptr, NX_HTTP_STATUS_OK, sizeof(NX_HTTP_STATUS_OK) - 1, 0, NX_NULL, 0, NX_NULL, 0);
4270 if (status == NX_SUCCESS)
4271 {
4272
4273 /* Send the response back to the client. */
4274 status = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), data_packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
4275
4276 /* Check for an error. */
4277 if (status != NX_SUCCESS)
4278 {
4279
4280 /* Just release the packet. */
4281 nx_packet_release(data_packet_ptr);
4282 }
4283 }
4284
4285 }
4286
4287
4288 /**************************************************************************/
4289 /* */
4290 /* FUNCTION RELEASE */
4291 /* */
4292 /* _nx_http_server_delete_process PORTABLE C */
4293 /* 6.1 */
4294 /* AUTHOR */
4295 /* */
4296 /* Yuxin Zhou, Microsoft Corporation */
4297 /* */
4298 /* DESCRIPTION */
4299 /* */
4300 /* This function processes the DELETE HTTP client requests. */
4301 /* */
4302 /* */
4303 /* INPUT */
4304 /* */
4305 /* server_ptr HTTP Server pointer */
4306 /* packet_ptr Request packet pointer */
4307 /* */
4308 /* OUTPUT */
4309 /* */
4310 /* None */
4311 /* */
4312 /* CALLS */
4313 /* */
4314 /* _nx_http_server_basic_authenticate Process basic authentication */
4315 /* _nx_http_server_digest_authenticate Process digest authentication */
4316 /* _nx_http_server_response_send Send response back to client */
4317 /* _nx_http_server_retrieve_resource Retrieve resource from request*/
4318 /* fx_file_delete Delete resource file */
4319 /* nx_packet_allocate Allocate a new packet */
4320 /* nx_packet_data_append Append information to response*/
4321 /* nx_packet_release Release packet */
4322 /* nx_tcp_socket_send Send HTTP Server response */
4323 /* */
4324 /* CALLED BY */
4325 /* */
4326 /* _nx_http_server_thread_entry HTTP Server thread */
4327 /* */
4328 /* RELEASE HISTORY */
4329 /* */
4330 /* DATE NAME DESCRIPTION */
4331 /* */
4332 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4333 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4334 /* resulting in version 6.1 */
4335 /* */
4336 /**************************************************************************/
_nx_http_server_delete_process(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)4337 VOID _nx_http_server_delete_process(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
4338 {
4339
4340 UINT status;
4341 CHAR *name_ptr;
4342 CHAR *password_ptr;
4343 CHAR *realm_ptr;
4344 NX_PACKET *response_ptr;
4345 UINT auth_request_present = NX_FALSE;
4346 UINT name_length = 0;
4347 UINT password_length = 0;
4348 UINT realm_length = 0;
4349 UINT temp_name_length = 0;
4350 UINT temp_password_length = 0;
4351 UINT temp_realm_length = 0;
4352
4353
4354 /* Pickup the URL (resource) from the request. */
4355 status = _nx_http_server_retrieve_resource(packet_ptr, server_ptr -> nx_http_server_request_resource, NX_HTTP_MAX_RESOURCE + 1);
4356
4357 /* Determine if the resource was extracted successfully. */
4358 if (status != NX_SUCCESS)
4359 {
4360
4361 /* Send response back to HTTP Client. */
4362 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_BAD_REQUEST, sizeof(NX_HTTP_STATUS_BAD_REQUEST) - 1,
4363 "NetX HTTP URL Bad", sizeof("NetX HTTP URL Bad") - 1, NX_NULL, 0);
4364
4365 /* Error, return to caller. */
4366 return;
4367 }
4368
4369 /* Determine if the application has specified an authentication function for this server. */
4370 if (server_ptr -> nx_http_server_authentication_check ||
4371 server_ptr -> nx_http_server_authentication_check_extended)
4372 {
4373
4374 /* Determine if authentication is required for the specified resource. */
4375 if (server_ptr -> nx_http_server_authentication_check_extended)
4376 {
4377 status = (server_ptr -> nx_http_server_authentication_check_extended)(server_ptr, NX_HTTP_SERVER_DELETE_REQUEST, server_ptr -> nx_http_server_request_resource,
4378 &name_ptr, &name_length, &password_ptr, &password_length, &realm_ptr, &realm_length);
4379 }
4380 else
4381 {
4382 status = (server_ptr -> nx_http_server_authentication_check)(server_ptr, NX_HTTP_SERVER_DELETE_REQUEST, server_ptr -> nx_http_server_request_resource,
4383 &name_ptr, &password_ptr, &realm_ptr);
4384 }
4385
4386 if (status == NX_HTTP_BASIC_AUTHENTICATE ||
4387 status == NX_HTTP_DIGEST_AUTHENTICATE)
4388 {
4389
4390 /* Check name, password and realm string. */
4391 if (_nx_utility_string_length_check(name_ptr, &temp_name_length, NX_HTTP_MAX_NAME) ||
4392 _nx_utility_string_length_check(password_ptr, &temp_password_length, NX_HTTP_MAX_PASSWORD) ||
4393 _nx_utility_string_length_check(realm_ptr, &temp_realm_length, NX_MAX_STRING_LENGTH))
4394 {
4395
4396 /* Error, return to caller. */
4397 return;
4398 }
4399
4400 /* Validate string length. */
4401 if (server_ptr -> nx_http_server_authentication_check_extended &&
4402 ((realm_length != temp_realm_length) ||
4403 (name_length != temp_name_length) ||
4404 (password_length != temp_password_length)))
4405 {
4406 return;
4407 }
4408 }
4409
4410 /* Determine what kind - if any - authentication is requested for this resource. */
4411 if (status == NX_HTTP_BASIC_AUTHENTICATE)
4412 {
4413
4414 /* Process basic authentication request. */
4415 status = _nx_http_server_basic_authenticate(server_ptr, packet_ptr, name_ptr, password_ptr, realm_ptr, temp_realm_length, &auth_request_present);
4416 }
4417 #ifdef NX_HTTP_DIGEST_ENABLE
4418 else if (status == NX_HTTP_DIGEST_AUTHENTICATE)
4419 {
4420
4421 /* Process digest authentication request. */
4422 status = _nx_http_server_digest_authenticate(server_ptr, packet_ptr, name_ptr, temp_name_length, password_ptr, temp_password_length, realm_ptr, temp_realm_length, &auth_request_present);
4423 }
4424 #endif
4425
4426 /* Determine if the authentication is currently in progress. */
4427 if ((status != NX_HTTP_DONT_AUTHENTICATE) && (status != NX_SUCCESS))
4428 {
4429
4430 /* Yes, authentication is in progress. The HTTP 401 has already been sent. */
4431 if (server_ptr -> nx_http_server_invalid_username_password_callback && auth_request_present)
4432 {
4433
4434 NXD_ADDRESS client_nxd_address;
4435 ULONG client_port;
4436
4437 /* Get the IP address of the client: */
4438 status = nxd_tcp_socket_peer_info_get(&(server_ptr->nx_http_server_socket), &client_nxd_address , &client_port);
4439
4440 if (status == NX_SUCCESS)
4441 {
4442 /* Send this information to the host application. */
4443 (server_ptr -> nx_http_server_invalid_username_password_callback)(server_ptr -> nx_http_server_request_resource, &client_nxd_address, NX_HTTP_SERVER_DELETE_REQUEST);
4444 }
4445 }
4446
4447 return;
4448 }
4449 }
4450
4451 /* Determine if a user supplied notify function has been specified. */
4452 if (server_ptr -> nx_http_server_request_notify)
4453 {
4454
4455 /* Call the user supplied function to notify the user of the delete request. */
4456 status = (server_ptr -> nx_http_server_request_notify)(server_ptr, NX_HTTP_SERVER_DELETE_REQUEST, server_ptr -> nx_http_server_request_resource, packet_ptr);
4457
4458 /* Determine if the user supplied routine is requesting the delete should be aborted. */
4459 if (status != NX_SUCCESS)
4460 {
4461
4462 /* Determine if the user callback routine successfully completed the request processing. */
4463 if (status == NX_HTTP_CALLBACK_COMPLETED)
4464 {
4465
4466 /* Send success response back to HTTP Client. */
4467 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_OK, sizeof(NX_HTTP_STATUS_OK) - 1, NX_NULL, 0, NX_NULL, 0);
4468 return;
4469 }
4470
4471 /* Send response back to HTTP Client. */
4472 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4473 "NetX HTTP Request Aborted", sizeof("NetX HTTP Request Aborted") - 1, NX_NULL, 0);
4474
4475 /* Yes, error was detected. Abort the remainder of the delete processing. */
4476 return;
4477 }
4478 }
4479
4480 /* Otherwise, everything is okay... complete the request. */
4481
4482 /* Delete the specified file. */
4483 status = fx_file_delete(server_ptr -> nx_http_server_media_ptr, server_ptr -> nx_http_server_request_resource);
4484
4485 /* Check for error condition. */
4486 if (status != NX_SUCCESS)
4487 {
4488
4489 /* Send response back to HTTP Client. */
4490 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
4491 "NetX HTTP File Delete Failed", sizeof("NetX HTTP File Delete Failed") - 1, NX_NULL, 0);
4492
4493 /* Error, return to caller. */
4494 return;
4495 }
4496
4497 /* Now build a response header. */
4498 status = _nx_http_server_generate_response_header(server_ptr, &response_ptr, NX_HTTP_STATUS_OK, sizeof(NX_HTTP_STATUS_OK) - 1, 0, NX_NULL, 0, NX_NULL, 0);
4499 if (status == NX_SUCCESS)
4500 {
4501
4502 /* Send the response back to the client. */
4503 status = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), response_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
4504
4505 /* Check for an error. */
4506 if (status != NX_SUCCESS)
4507 {
4508
4509 /* Just release the packet. */
4510 nx_packet_release(response_ptr);
4511 }
4512 }
4513 }
4514
4515
4516 /**************************************************************************/
4517 /* */
4518 /* FUNCTION RELEASE */
4519 /* */
4520 /* _nxe_http_server_invalid_userpassword_notify_set PORTABLE C */
4521 /* 6.1 */
4522 /* AUTHOR */
4523 /* */
4524 /* Yuxin Zhou, Microsoft Corporation */
4525 /* */
4526 /* DESCRIPTION */
4527 /* */
4528 /* This function performs error checking for service to set invalid */
4529 /* username password callback function. */
4530 /* */
4531 /* */
4532 /* INPUT */
4533 /* */
4534 /* http_server_ptr Pointer to HTTP server */
4535 /* invalid_username_password_callback Pointer to application's */
4536 /* invalid username password */
4537 /* callback function */
4538 /* */
4539 /* OUTPUT */
4540 /* */
4541 /* status Completion status */
4542 /* */
4543 /* CALLED BY */
4544 /* */
4545 /* Application Code */
4546 /* */
4547 /* RELEASE HISTORY */
4548 /* */
4549 /* DATE NAME DESCRIPTION */
4550 /* */
4551 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4552 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4553 /* resulting in version 6.1 */
4554 /* */
4555 /**************************************************************************/
_nxe_http_server_invalid_userpassword_notify_set(NX_HTTP_SERVER * http_server_ptr,UINT (* invalid_username_password_callback)(CHAR * resource,NXD_ADDRESS * client_nxd_address,UINT request_type))4556 UINT _nxe_http_server_invalid_userpassword_notify_set(NX_HTTP_SERVER *http_server_ptr,
4557 UINT (*invalid_username_password_callback)(CHAR *resource, NXD_ADDRESS *client_nxd_address, UINT request_type))
4558 {
4559
4560 UINT status;
4561
4562
4563 if ((http_server_ptr == NX_NULL) || (invalid_username_password_callback == NX_NULL))
4564 {
4565 return NX_PTR_ERROR;
4566 }
4567
4568 status = _nx_http_server_invalid_userpassword_notify_set(http_server_ptr, invalid_username_password_callback);
4569
4570 return status;
4571 }
4572
4573
4574 /**************************************************************************/
4575 /* */
4576 /* FUNCTION RELEASE */
4577 /* */
4578 /* nx_http_server_invalid_userpassword_notify_set PORTABLE C */
4579 /* 6.1 */
4580 /* AUTHOR */
4581 /* */
4582 /* Yuxin Zhou, Microsoft Corporation */
4583 /* */
4584 /* DESCRIPTION */
4585 /* */
4586 /* This function sets invalid username password callback function. */
4587 /* */
4588 /* Note: The string length of resource in */
4589 /* invalid_username_password_callback is limited by */
4590 /* NX_HTTP_MAX_RESOURCE. */
4591 /* */
4592 /* */
4593 /* INPUT */
4594 /* */
4595 /* http_server_ptr Pointer to HTTP server */
4596 /* invalid_username_password_callback Pointer to application's */
4597 /* invalid username password */
4598 /* callback function */
4599 /* */
4600 /* OUTPUT */
4601 /* */
4602 /* status Completion status */
4603 /* */
4604 /* CALLED BY */
4605 /* */
4606 /* Application Code */
4607 /* */
4608 /* RELEASE HISTORY */
4609 /* */
4610 /* DATE NAME DESCRIPTION */
4611 /* */
4612 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4613 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4614 /* resulting in version 6.1 */
4615 /* */
4616 /**************************************************************************/
_nx_http_server_invalid_userpassword_notify_set(NX_HTTP_SERVER * http_server_ptr,UINT (* invalid_username_password_callback)(CHAR * resource,NXD_ADDRESS * client_nxd_address,UINT request_type))4617 UINT _nx_http_server_invalid_userpassword_notify_set(NX_HTTP_SERVER *http_server_ptr,
4618 UINT (*invalid_username_password_callback)(CHAR *resource, NXD_ADDRESS *client_nxd_address, UINT request_type))
4619 {
4620
4621 http_server_ptr -> nx_http_server_invalid_username_password_callback = invalid_username_password_callback;
4622
4623 return NX_SUCCESS;
4624 }
4625
4626
4627 /**************************************************************************/
4628 /* */
4629 /* FUNCTION RELEASE */
4630 /* */
4631 /* _nx_http_server_response_send PORTABLE C */
4632 /* 6.1 */
4633 /* AUTHOR */
4634 /* */
4635 /* Yuxin Zhou, Microsoft Corporation */
4636 /* */
4637 /* DESCRIPTION */
4638 /* */
4639 /* This function sends the specified Server response to the requesting */
4640 /* HTTP client. */
4641 /* */
4642 /* Note: The strings of status code, information and additional info */
4643 /* must be NULL-terminated and length of this string matches the length*/
4644 /* specified in the argument list. */
4645 /* */
4646 /* INPUT */
4647 /* */
4648 /* server_ptr HTTP Server pointer */
4649 /* status_code Status-code and reason-phrase */
4650 /* information Pointer to HTTP info string */
4651 /* information_length Length of HTTP info string */
4652 /* additional_information Pointer to additional HTTP */
4653 /* information */
4654 /* additional_info_length Length of additional HTTP */
4655 /* information */
4656 /* */
4657 /* OUTPUT */
4658 /* */
4659 /* None */
4660 /* */
4661 /* CALLS */
4662 /* */
4663 /* nx_packet_allocate Allocate a new packet */
4664 /* nx_packet_data_append Append information to response*/
4665 /* nx_packet_release Release packet */
4666 /* nx_tcp_socket_send Send HTTP Server response */
4667 /* _nx_utility_string_length_check Check string length */
4668 /* */
4669 /* CALLED BY */
4670 /* */
4671 /* _nx_http_server_thread_entry HTTP Server thread */
4672 /* _nx_http_server_get_process Process GET request */
4673 /* _nx_http_server_put_process Process PUT request */
4674 /* _nx_http_server_delete_process Process DELETE request */
4675 /* */
4676 /* RELEASE HISTORY */
4677 /* */
4678 /* DATE NAME DESCRIPTION */
4679 /* */
4680 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4681 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4682 /* resulting in version 6.1 */
4683 /* */
4684 /**************************************************************************/
_nx_http_server_response_send(NX_HTTP_SERVER * server_ptr,CHAR * status_code,UINT status_code_length,CHAR * information,UINT information_length,CHAR * additional_information,UINT additional_info_length)4685 UINT _nx_http_server_response_send(NX_HTTP_SERVER *server_ptr, CHAR *status_code, UINT status_code_length, CHAR *information,
4686 UINT information_length, CHAR *additional_information, UINT additional_info_length)
4687 {
4688
4689 UINT status;
4690 UINT length;
4691 NX_PACKET *packet_ptr;
4692
4693
4694 /* Determine if there is additional information. */
4695 if(information)
4696 {
4697
4698 /* Calculate the size of the information field. */
4699 length = information_length;
4700
4701 /* Determine if there is additional information. */
4702 if (additional_information)
4703 {
4704
4705 /* Update the length with it as well. */
4706 length = length + additional_info_length;
4707 }
4708 }
4709 else
4710 length = 0;
4711
4712 /* Generate response header. */
4713 status = _nx_http_server_generate_response_header(server_ptr, &packet_ptr, status_code, status_code_length, length, NX_NULL, 0, NX_NULL, 0);
4714
4715 /* Determine if an error occurred. */
4716 if (status != NX_SUCCESS)
4717 {
4718
4719 /* Just return. */
4720 return(NX_HTTP_ERROR);
4721 }
4722
4723 /* Determine if there is additional information. */
4724 if (information)
4725 {
4726
4727 /* Place the first informational field. */
4728 status = nx_packet_data_append(packet_ptr, information, information_length,
4729 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4730
4731 /* If there is additional information, place it in the buffer as well. */
4732 if (additional_information)
4733 {
4734
4735 /* Now, place the additional informational field. */
4736 status += nx_packet_data_append(packet_ptr, additional_information, additional_info_length,
4737 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4738 }
4739 }
4740
4741 /* Check for an error. */
4742 if (status != NX_SUCCESS)
4743 {
4744
4745 /* Just release the packet and return. */
4746 nx_packet_release(packet_ptr);
4747 return(NX_HTTP_ERROR);
4748 }
4749
4750 /* Send the response back to the client. */
4751 status = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
4752
4753 /* Check for an error. */
4754 if (status != NX_SUCCESS)
4755 {
4756
4757 /* Just release the packet. */
4758 nx_packet_release(packet_ptr);
4759 }
4760
4761 return(status);
4762 }
4763
4764
4765 /**************************************************************************/
4766 /* */
4767 /* FUNCTION RELEASE */
4768 /* */
4769 /* _nx_http_server_basic_authenticate PORTABLE C */
4770 /* 6.2.0 */
4771 /* AUTHOR */
4772 /* */
4773 /* Yuxin Zhou, Microsoft Corporation */
4774 /* */
4775 /* DESCRIPTION */
4776 /* */
4777 /* This function checks for basic (name & password) authentication. */
4778 /* If found and correct, it returns a success. Otherwise, it returns */
4779 /* an authentication request to the requesting client. */
4780 /* */
4781 /* */
4782 /* INPUT */
4783 /* */
4784 /* server_ptr HTTP Server pointer */
4785 /* packet_ptr Request packet pointer */
4786 /* name_ptr Pointer to name string */
4787 /* password_ptr Pointer to password string */
4788 /* realm_ptr Pointer to realm string */
4789 /* realm_length Length of realm string */
4790 /* auth_request_present Indicate if authentication */
4791 /* must be performed */
4792 /* */
4793 /* OUTPUT */
4794 /* */
4795 /* status Completion status */
4796 /* */
4797 /* CALLS */
4798 /* */
4799 /* _nx_http_server_retrieve_basic_authorization Pickup authorization */
4800 /* _nx_http_base64_decode Decode authorization */
4801 /* nx_packet_allocate Allocate a new packet */
4802 /* nx_packet_data_append Append information to response*/
4803 /* nx_packet_release Release packet */
4804 /* nx_tcp_socket_send Send HTTP Server response */
4805 /* */
4806 /* CALLED BY */
4807 /* */
4808 /* _nx_http_server_get_process Process GET request */
4809 /* _nx_http_server_put_process Process PUT request */
4810 /* _nx_http_server_delete_process Process DELETE request */
4811 /* */
4812 /* RELEASE HISTORY */
4813 /* */
4814 /* DATE NAME DESCRIPTION */
4815 /* */
4816 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4817 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4818 /* resulting in version 6.1 */
4819 /* 04-02-2021 Yuxin Zhou Modified comment(s), and */
4820 /* improved the logic of */
4821 /* parsing base64, */
4822 /* resulting in version 6.1.6 */
4823 /* 10-31-2022 Yuxin Zhou Modified comment(s), fixed */
4824 /* the issue of processing */
4825 /* empty password, */
4826 /* resulting in version 6.2.0 */
4827 /* */
4828 /**************************************************************************/
_nx_http_server_basic_authenticate(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * name_ptr,CHAR * password_ptr,CHAR * realm_ptr,UINT realm_length,UINT * auth_request_present)4829 UINT _nx_http_server_basic_authenticate(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT realm_length, UINT *auth_request_present)
4830 {
4831
4832 UINT i, j;
4833 UINT status, status1;
4834 CHAR quote[2] = {0x22, 0};
4835 CHAR crlf[2] = {13,10};
4836 UINT match;
4837 UINT length;
4838 UINT authorization_decoded_size;
4839
4840 /* Default to no authentication request detected. */
4841 *auth_request_present = NX_FALSE;
4842
4843 /* Default the status to authenticate. */
4844 status = NX_HTTP_BASIC_AUTHENTICATE;
4845
4846 memset(&authorization_request[0], 0, sizeof(authorization_request));
4847
4848 memset(&authorization_decoded[0], 0, sizeof(authorization_decoded));
4849
4850 /* Is the authorization request present? */
4851 length = _nx_http_server_retrieve_basic_authorization(packet_ptr, authorization_request);
4852 if (length)
4853 {
4854
4855 /* Yes, an authorization request is present. */
4856 *auth_request_present = NX_TRUE;
4857
4858 /* Convert the request from Base64 representation to ASCII. */
4859 _nx_utility_base64_decode((UCHAR *)authorization_request, length, (UCHAR *)authorization_decoded, sizeof(authorization_decoded), &authorization_decoded_size);
4860
4861 /* See if it is valid. */
4862
4863 /* Compare the name. */
4864 i = 0;
4865 match = NX_TRUE;
4866 while (name_ptr[i] && (i < authorization_decoded_size))
4867 {
4868
4869 /* Is there a mismatch? */
4870 if (name_ptr[i] != authorization_decoded[i])
4871 {
4872
4873 /* Name mismatch. Continue to avoid timing attack. */
4874 match = NX_FALSE;
4875 }
4876
4877 /* Move to next character. */
4878 i++;
4879 }
4880
4881 /* Determine if everything matches. */
4882 if (match && (i < authorization_decoded_size) && (authorization_decoded[i] == ':'))
4883 {
4884
4885 /* Move the authorization index past the semicolon. */
4886 i++;
4887
4888 /* Now compare the passwords. */
4889 j = 0;
4890 match = NX_TRUE;
4891 while (password_ptr[j] && (i < authorization_decoded_size))
4892 {
4893
4894 /* Is there a mismatch? */
4895 if (password_ptr[j] != authorization_decoded[i])
4896 {
4897
4898 /* Password mismatch. Continue to avoid timing attack. */
4899 match = NX_FALSE;
4900 }
4901
4902 /* Move to next character. */
4903 i++;
4904 j++;
4905 }
4906
4907 /* Determine if we have a match. */
4908 if (match && (i == authorization_decoded_size) &&
4909 (authorization_decoded[i] == (CHAR) NX_NULL) &&
4910 (password_ptr[j] == (CHAR) NX_NULL))
4911 {
4912
4913 /* Yes, we have successful authorization!! */
4914 status = NX_SUCCESS;
4915 }
4916 }
4917 }
4918
4919 /* Determine if we need to send back an unauthorized request. */
4920 if (status == NX_HTTP_BASIC_AUTHENTICATE)
4921 {
4922
4923 /* We need authorization so build the HTTP 401 Unauthorized message to send to the server. */
4924
4925 /* Allocate a packet for sending the response back. */
4926 status1 = nx_packet_allocate(server_ptr -> nx_http_server_packet_pool_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
4927
4928 /* Determine if an error occurred in the packet allocation. */
4929 if (status1 != NX_SUCCESS)
4930 {
4931
4932 /* Indicate an allocation error occurred. */
4933 server_ptr -> nx_http_server_allocation_errors++;
4934
4935 /* Just return. */
4936 return(status1);
4937 }
4938
4939 /* Insert the response header. */
4940 nx_packet_data_append(packet_ptr, NX_HTTP_VERSION, sizeof(NX_HTTP_VERSION) - 1,
4941 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4942 nx_packet_data_append(packet_ptr, " ", 1, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4943 nx_packet_data_append(packet_ptr, NX_HTTP_STATUS_UNAUTHORIZED, sizeof(NX_HTTP_STATUS_UNAUTHORIZED) - 1,
4944 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4945
4946 /* Place the <cr,lf> into the buffer. */
4947 nx_packet_data_append(packet_ptr, crlf, 2,
4948 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4949
4950 /* Insert the type of authentication requested. */
4951 nx_packet_data_append(packet_ptr, "WWW-Authenticate: Basic realm=", 30,
4952 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4953
4954 /* Insert the double quote. */
4955 nx_packet_data_append(packet_ptr, quote, 1,
4956 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4957
4958 /* Place the realm string into the buffer. */
4959 nx_packet_data_append(packet_ptr, realm_ptr, realm_length,
4960 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4961
4962 /* Insert the double quote. */
4963 nx_packet_data_append(packet_ptr, quote, 1,
4964 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4965
4966 /* Place the <cr,lf> into the buffer. */
4967 nx_packet_data_append(packet_ptr, crlf, 2,
4968 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4969
4970 /* Place another <cr,lf> into the buffer to signal end of FULL HTTP response. */
4971 nx_packet_data_append(packet_ptr, crlf, 2,
4972 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
4973
4974 /* Send the response back to the client. */
4975 status1 = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
4976
4977 /* Check for an error. */
4978 if (status1)
4979 {
4980
4981 /* Return the internal NetX error. */
4982 status = status1;
4983
4984 /* Just release the packet. */
4985 nx_packet_release(packet_ptr);
4986 }
4987 }
4988
4989 /* Return the result of the authentication request. */
4990 return(status);
4991 }
4992
4993
4994 /**************************************************************************/
4995 /* */
4996 /* FUNCTION RELEASE */
4997 /* */
4998 /* _nx_http_server_retrieve_basic_authorization PORTABLE C */
4999 /* 6.1.10 */
5000 /* AUTHOR */
5001 /* */
5002 /* Yuxin Zhou, Microsoft Corporation */
5003 /* */
5004 /* DESCRIPTION */
5005 /* */
5006 /* This function retrieves basic authentication information from the */
5007 /* HTTP request packet. */
5008 /* */
5009 /* */
5010 /* INPUT */
5011 /* */
5012 /* packet_ptr Request packet pointer */
5013 /* authorization_request_ptr Pointer to destination for */
5014 /* authorization string */
5015 /* */
5016 /* OUTPUT */
5017 /* */
5018 /* status Completion status */
5019 /* */
5020 /* CALLS */
5021 /* */
5022 /* None */
5023 /* */
5024 /* CALLED BY */
5025 /* */
5026 /* _nx_http_server_basic_authenticate Basic authenticate processing */
5027 /* */
5028 /* RELEASE HISTORY */
5029 /* */
5030 /* DATE NAME DESCRIPTION */
5031 /* */
5032 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5033 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5034 /* resulting in version 6.1 */
5035 /* 01-31-2022 Yuxin Zhou Modified comment(s), fixed */
5036 /* the HTTP Server state issue */
5037 /* with basic authorization, */
5038 /* resulting in version 6.1.10 */
5039 /* */
5040 /**************************************************************************/
_nx_http_server_retrieve_basic_authorization(NX_PACKET * packet_ptr,CHAR * authorization_request_ptr)5041 UINT _nx_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr)
5042 {
5043
5044 UINT length;
5045 UINT found;
5046 CHAR *buffer_ptr;
5047
5048
5049 /* Set the found flag to false. */
5050 found = NX_FALSE;
5051
5052 /* Default the authorization request to zero. */
5053 length = 0;
5054
5055 /* Set the authorization request string to NULL. */
5056 authorization_request_ptr[0] = NX_NULL;
5057
5058 /* Setup pointer to buffer. */
5059 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5060
5061
5062 /* Find the "Authorization: " token first. */
5063 while (((buffer_ptr+15) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
5064 {
5065
5066 /* Check for the Authorization: token. */
5067 if (((*buffer_ptr == 'a') || (*buffer_ptr == 'A')) &&
5068 ((*(buffer_ptr+1) == 'u') || (*(buffer_ptr+1) == 'U')) &&
5069 ((*(buffer_ptr+2) == 't') || (*(buffer_ptr+2) == 'T')) &&
5070 ((*(buffer_ptr+3) == 'h') || (*(buffer_ptr+3) == 'H')) &&
5071 ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) &&
5072 ((*(buffer_ptr+5) == 'r') || (*(buffer_ptr+5) == 'R')) &&
5073 ((*(buffer_ptr+6) == 'i') || (*(buffer_ptr+6) == 'I')) &&
5074 ((*(buffer_ptr+7) == 'z') || (*(buffer_ptr+7) == 'Z')) &&
5075 ((*(buffer_ptr+8) == 'a') || (*(buffer_ptr+8) == 'A')) &&
5076 ((*(buffer_ptr+9) == 't') || (*(buffer_ptr+9) == 'T')) &&
5077 ((*(buffer_ptr+10) == 'i') || (*(buffer_ptr+10) == 'I')) &&
5078 ((*(buffer_ptr+11) == 'o') || (*(buffer_ptr+11) == 'O')) &&
5079 ((*(buffer_ptr+12) == 'n') || (*(buffer_ptr+12) == 'N')) &&
5080 (*(buffer_ptr+13) == ':') &&
5081 (*(buffer_ptr+14) == ' '))
5082 {
5083
5084 /* Move the pointer up to the length token. */
5085 buffer_ptr = buffer_ptr + 15;
5086
5087 /* Set the found flag. */
5088 found = NX_TRUE;
5089 break;
5090 }
5091
5092 /* Move the pointer up to the next character. */
5093 buffer_ptr++;
5094 }
5095
5096 /* Determine if the first token was found. */
5097 if (!found)
5098 {
5099
5100 /* No, authorization is not present. Return a zero length. */
5101 return(length);
5102 }
5103
5104 /* Set the found flag back to false. */
5105 found = NX_FALSE;
5106
5107 /* Now remove any extra blanks. */
5108 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
5109 {
5110
5111 /* Move the pointer up one character. */
5112 buffer_ptr++;
5113 }
5114
5115 /* Now check for the "Basic " token. */
5116 while (((buffer_ptr+6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
5117 {
5118
5119 /* Check for the Basic token. */
5120 if (((*buffer_ptr == 'b') || (*buffer_ptr == 'B')) &&
5121 ((*(buffer_ptr+1) == 'a') || (*(buffer_ptr+1) == 'A')) &&
5122 ((*(buffer_ptr+2) == 's') || (*(buffer_ptr+2) == 'S')) &&
5123 ((*(buffer_ptr+3) == 'i') || (*(buffer_ptr+3) == 'I')) &&
5124 ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+4) == 'C')) &&
5125 (*(buffer_ptr+5) == ' '))
5126 {
5127
5128 /* Move the pointer up to the actual authorization string. */
5129 buffer_ptr = buffer_ptr + 6;
5130
5131 /* Set the found flag. */
5132 found = NX_TRUE;
5133 break;
5134 }
5135
5136 /* Move the pointer up to the next character. */
5137 buffer_ptr++;
5138 }
5139
5140 /* Determine if the first token was found. */
5141 if (!found)
5142 {
5143
5144 /* No, authorization is not present. Return a zero length. */
5145 return(length);
5146 }
5147
5148 /* Now remove any extra blanks. */
5149 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
5150 {
5151
5152 /* Move the pointer up one character. */
5153 buffer_ptr++;
5154 }
5155
5156 /* Now pickup the authorization string. */
5157 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_HTTP_MAX_STRING))
5158 {
5159
5160 /* Copy a character of the authorization string into the destination. */
5161 authorization_request_ptr[length] = *buffer_ptr++;
5162 length++;
5163 }
5164
5165 /* Return the length to the caller. */
5166 return(length);
5167 }
5168
5169
5170 /**************************************************************************/
5171 /* */
5172 /* FUNCTION RELEASE */
5173 /* */
5174 /* _nx_http_server_retrieve_resource PORTABLE C */
5175 /* 6.1 */
5176 /* AUTHOR */
5177 /* */
5178 /* Yuxin Zhou, Microsoft Corporation */
5179 /* */
5180 /* DESCRIPTION */
5181 /* */
5182 /* This function retrieves the resource (URL) portion of the request */
5183 /* and places it in the destination. */
5184 /* */
5185 /* */
5186 /* INPUT */
5187 /* */
5188 /* server_ptr HTTP Server pointer */
5189 /* destination Destination for resource */
5190 /* max_size Maximum size of destination */
5191 /* */
5192 /* OUTPUT */
5193 /* */
5194 /* Status Completion status */
5195 /* */
5196 /* CALLS */
5197 /* */
5198 /* None */
5199 /* */
5200 /* CALLED BY */
5201 /* */
5202 /* _nx_http_server_get_process Process GET request */
5203 /* _nx_http_server_put_process Process PUT request */
5204 /* _nx_http_server_delete_process Process DELETE request */
5205 /* */
5206 /* RELEASE HISTORY */
5207 /* */
5208 /* DATE NAME DESCRIPTION */
5209 /* */
5210 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5211 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5212 /* resulting in version 6.1 */
5213 /* */
5214 /**************************************************************************/
_nx_http_server_retrieve_resource(NX_PACKET * packet_ptr,CHAR * destination,UINT max_size)5215 UINT _nx_http_server_retrieve_resource(NX_PACKET *packet_ptr, CHAR *destination, UINT max_size)
5216 {
5217
5218 UINT i;
5219 CHAR *buffer_ptr;
5220
5221
5222 /* Set the destination to NULL. */
5223 destination[0] = (CHAR) 0;
5224
5225 /* Setup pointer to buffer. */
5226 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5227
5228 /* Find the first space which is the start position of URI. */
5229 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != ' '))
5230 {
5231
5232 /* Move the pointer up to the next character. */
5233 buffer_ptr++;
5234 }
5235
5236 /* Check for an error condition. */
5237 if (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr)
5238 return(NX_HTTP_ERROR);
5239
5240 buffer_ptr++;
5241
5242 if ((buffer_ptr + 7 < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != '/'))
5243 {
5244
5245 /* Check whether it is an absoluteURI*/
5246 if (((*buffer_ptr == 'h') || (*buffer_ptr == 'H')) &&
5247 ((*(buffer_ptr + 1) == 't') || (*(buffer_ptr + 1) == 'T')) &&
5248 ((*(buffer_ptr + 2) == 't') || (*(buffer_ptr + 1) == 'T')) &&
5249 ((*(buffer_ptr + 3) == 'p') || (*(buffer_ptr + 1) == 'P')) &&
5250 (*(buffer_ptr + 4) == ':') &&
5251 (*(buffer_ptr + 5) == '/') &&
5252 (*(buffer_ptr + 6) == '/'))
5253 {
5254
5255 /* Yes it is. Find the absolute path. */
5256 buffer_ptr += 7;
5257
5258 /* Find the first slash character. The first slash marks the beginning of the URL. */
5259 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != '/'))
5260 {
5261
5262 /* Move the pointer up to the next character. */
5263 buffer_ptr++;
5264 }
5265 }
5266 }
5267
5268 /* Check for an error condition. */
5269 if ((buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr) || (*buffer_ptr != '/'))
5270 return(NX_HTTP_ERROR);
5271
5272 /* Copy the rest of the resource to the destination. Space, semicolon, and question mark characters signal the
5273 end of the resource. */
5274 i = 0;
5275 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != ' ') && (*buffer_ptr != ';') && (*buffer_ptr != '?') && (i < (max_size-1)))
5276 {
5277
5278 /* Check escape characters. */
5279 if(*buffer_ptr == '%')
5280 {
5281
5282 /* It is an escape character. */
5283 if((buffer_ptr + 2) < (CHAR *)packet_ptr -> nx_packet_append_ptr)
5284 {
5285
5286 /* Convert the HEX number. */
5287 buffer_ptr++;
5288 if((*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
5289 destination[i] = (CHAR)(*buffer_ptr - '0');
5290 else if((*buffer_ptr >= 'a') && (*buffer_ptr <= 'f'))
5291 destination[i] = (CHAR)(*buffer_ptr - 'a' + 10);
5292 else if((*buffer_ptr >= 'A') && (*buffer_ptr <= 'F'))
5293 destination[i] = (CHAR)(*buffer_ptr - 'A' + 10);
5294 else
5295 {
5296
5297 /* Error picking up the resource. */
5298 destination[0] = (CHAR) 0;
5299 return(NX_HTTP_ERROR);
5300 }
5301 destination[i] = (CHAR)(destination[i] << 4);
5302
5303 /* Convert the HEX number. */
5304 buffer_ptr++;
5305 if((*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
5306 destination[i] = (CHAR)(destination[i] + (*buffer_ptr - '0'));
5307 else if((*buffer_ptr >= 'a') && (*buffer_ptr <= 'f'))
5308 destination[i] = (CHAR)(destination[i] + (*buffer_ptr - 'a' + 10));
5309 else if((*buffer_ptr >= 'A') && (*buffer_ptr <= 'F'))
5310 destination[i] = (CHAR)(destination[i] + (*buffer_ptr - 'A' + 10));
5311 else
5312 {
5313
5314 /* Error picking up the resource. */
5315 destination[0] = (CHAR) 0;
5316 return(NX_HTTP_ERROR);
5317 }
5318
5319 /* Move to the next byte. */
5320 i++;
5321 buffer_ptr++;
5322 }
5323 else
5324 {
5325
5326 /* Error picking up the resource. */
5327 destination[0] = (CHAR) 0;
5328 return(NX_HTTP_ERROR);
5329 }
5330 }
5331 else
5332 {
5333
5334 /* Copy the URL name into the destination. */
5335 destination[i++] = *buffer_ptr++;
5336 }
5337 }
5338
5339 /* Determine if the resource was retrieved. */
5340 if ((destination[0] == (CHAR) 0) || (buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr) || ((*buffer_ptr != ' ') && (*buffer_ptr != '?') && (*buffer_ptr != ';')))
5341 {
5342
5343 /* Error picking up the resource. */
5344 destination[0] = (CHAR) 0;
5345 return(NX_HTTP_ERROR);
5346 }
5347
5348 /* Everything is okay, place a NULL at the end of the resource. */
5349 destination[i] = (CHAR) 0;
5350
5351 /* Return success. */
5352 return(NX_SUCCESS);
5353 }
5354
5355
5356 /**************************************************************************/
5357 /* */
5358 /* FUNCTION RELEASE */
5359 /* */
5360 /* _nx_http_server_calculate_content_offset PORTABLE C */
5361 /* 6.1 */
5362 /* AUTHOR */
5363 /* */
5364 /* Yuxin Zhou, Microsoft Corporation */
5365 /* */
5366 /* DESCRIPTION */
5367 /* */
5368 /* This function calculates the byte offset to the start of the */
5369 /* HTTP request content area. This area immediately follows the HTTP */
5370 /* request header (which ends with a blank line). */
5371 /* */
5372 /* */
5373 /* INPUT */
5374 /* */
5375 /* packet_ptr Pointer to request packet */
5376 /* */
5377 /* OUTPUT */
5378 /* */
5379 /* Byte Offset (0 implies no content) */
5380 /* */
5381 /* CALLS */
5382 /* */
5383 /* None */
5384 /* */
5385 /* CALLED BY */
5386 /* */
5387 /* _nx_http_server_content_get Application content get */
5388 /* _nx_http_server_get_process Process GET request */
5389 /* _nx_http_server_put_process Process PUT request */
5390 /* */
5391 /* RELEASE HISTORY */
5392 /* */
5393 /* DATE NAME DESCRIPTION */
5394 /* */
5395 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5396 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5397 /* resulting in version 6.1 */
5398 /* */
5399 /**************************************************************************/
_nx_http_server_calculate_content_offset(NX_PACKET * packet_ptr)5400 UINT _nx_http_server_calculate_content_offset(NX_PACKET *packet_ptr)
5401 {
5402
5403 UINT offset;
5404 CHAR *buffer_ptr;
5405
5406
5407 /* Default the content offset to zero. */
5408 offset = 0;
5409
5410 /* Setup pointer to buffer. */
5411 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5412
5413 /* Find the "cr,lf,cr,lf" token. */
5414 while (((buffer_ptr+3) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
5415 {
5416
5417 /* Check for the <cr,lf,cr,lf> token. This signals a blank line, which also
5418 specifies the start of the content. */
5419 if ((*buffer_ptr == (CHAR) 13) &&
5420 (*(buffer_ptr+1) == (CHAR) 10) &&
5421 (*(buffer_ptr+2) == (CHAR) 13) &&
5422 (*(buffer_ptr+3) == (CHAR) 10))
5423 {
5424
5425 /* Adjust the offset. */
5426 offset = offset + 4;
5427 break;
5428 }
5429
5430 /* Move the pointer up to the next character. */
5431 buffer_ptr++;
5432
5433 /* Increment the offset. */
5434 offset++;
5435 }
5436
5437 /* Return the offset to the caller. */
5438 return(offset);
5439 }
5440
5441
5442 /**************************************************************************/
5443 /* */
5444 /* FUNCTION RELEASE */
5445 /* */
5446 /* _nxe_http_server_type_get PORTABLE C */
5447 /* 6.1 */
5448 /* AUTHOR */
5449 /* */
5450 /* Yuxin Zhou, Microsoft Corporation */
5451 /* */
5452 /* DESCRIPTION */
5453 /* */
5454 /* This function checks error for deriving the type of the resource. */
5455 /* */
5456 /* INPUT */
5457 /* */
5458 /* server_ptr HTTP Server pointer */
5459 /* name Name string */
5460 /* http_type_string Destination HTTP type string */
5461 /* */
5462 /* OUTPUT */
5463 /* */
5464 /* Size Number of bytes in string */
5465 /* */
5466 /* CALLS */
5467 /* */
5468 /* _nx_http_server_type_get */
5469 /* */
5470 /* CALLED BY */
5471 /* */
5472 /* Application Code */
5473 /* */
5474 /* RELEASE HISTORY */
5475 /* */
5476 /* DATE NAME DESCRIPTION */
5477 /* */
5478 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5479 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5480 /* resulting in version 6.1 */
5481 /* */
5482 /**************************************************************************/
_nxe_http_server_type_get(NX_HTTP_SERVER * server_ptr,CHAR * name,CHAR * http_type_string)5483 UINT _nxe_http_server_type_get(NX_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string)
5484 {
5485
5486 /* Check for invalid input pointers. */
5487 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (name == NX_NULL) || (http_type_string == NX_NULL))
5488 return(0);
5489
5490 return _nx_http_server_type_get(server_ptr, name, http_type_string);
5491 }
5492
5493
5494 /**************************************************************************/
5495 /* */
5496 /* FUNCTION RELEASE */
5497 /* */
5498 /* _nx_http_server_type_get PORTABLE C */
5499 /* 6.1 */
5500 /* AUTHOR */
5501 /* */
5502 /* Yuxin Zhou, Microsoft Corporation */
5503 /* */
5504 /* DESCRIPTION */
5505 /* */
5506 /* This function derives the type of the resource. */
5507 /* */
5508 /* INPUT */
5509 /* */
5510 /* server_ptr HTTP Server pointer */
5511 /* name Name string */
5512 /* http_type_string Destination HTTP type string */
5513 /* */
5514 /* OUTPUT */
5515 /* */
5516 /* Size Number of bytes in string */
5517 /* */
5518 /* CALLS */
5519 /* */
5520 /* _nx_http_server_type_get_extended */
5521 /* _nx_utility_string_length_check */
5522 /* */
5523 /* CALLED BY */
5524 /* */
5525 /* _nx_http_server_get_process Process GET request */
5526 /* Application Code */
5527 /* */
5528 /* RELEASE HISTORY */
5529 /* */
5530 /* DATE NAME DESCRIPTION */
5531 /* */
5532 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5533 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5534 /* resulting in version 6.1 */
5535 /* */
5536 /**************************************************************************/
_nx_http_server_type_get(NX_HTTP_SERVER * server_ptr,CHAR * name,CHAR * http_type_string)5537 UINT _nx_http_server_type_get(NX_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string)
5538 {
5539 UINT name_length = 0;
5540
5541 if (_nx_utility_string_length_check(name, &name_length, NX_MAX_STRING_LENGTH))
5542 {
5543 return(0);
5544 }
5545
5546 return _nx_http_server_type_get_extended(server_ptr, name, name_length, http_type_string, NX_MAX_STRING_LENGTH + 1);
5547 }
5548
5549
5550 /**************************************************************************/
5551 /* */
5552 /* FUNCTION RELEASE */
5553 /* */
5554 /* _nxe_http_server_type_get_extended PORTABLE C */
5555 /* 6.1 */
5556 /* AUTHOR */
5557 /* */
5558 /* Yuxin Zhou, Microsoft Corporation */
5559 /* */
5560 /* DESCRIPTION */
5561 /* */
5562 /* This function checks error for deriving the type of the resource. */
5563 /* */
5564 /* INPUT */
5565 /* */
5566 /* server_ptr HTTP Server pointer */
5567 /* name Name string */
5568 /* name_length Length of name string */
5569 /* http_type_string Destination HTTP type string */
5570 /* http_type_string_max_size Size of the destination string*/
5571 /* */
5572 /* OUTPUT */
5573 /* */
5574 /* Size Number of bytes in string, or */
5575 /* 0 if http_type_string is too */
5576 /* small for the resource string*/
5577 /* */
5578 /* CALLS */
5579 /* */
5580 /* _nx_http_server_type_get_extended */
5581 /* */
5582 /* CALLED BY */
5583 /* */
5584 /* Application Code */
5585 /* */
5586 /* RELEASE HISTORY */
5587 /* */
5588 /* DATE NAME DESCRIPTION */
5589 /* */
5590 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5591 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5592 /* resulting in version 6.1 */
5593 /* */
5594 /**************************************************************************/
_nxe_http_server_type_get_extended(NX_HTTP_SERVER * server_ptr,CHAR * name,UINT name_length,CHAR * http_type_string,UINT http_type_string_max_size)5595 UINT _nxe_http_server_type_get_extended(NX_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length, CHAR *http_type_string, UINT http_type_string_max_size)
5596 {
5597
5598 /* Check for invalid input pointers. */
5599 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (name == NX_NULL) || (http_type_string == NX_NULL))
5600 return(0);
5601
5602 /* Check for appropriate caller. */
5603 NX_THREADS_ONLY_CALLER_CHECKING
5604
5605 return _nx_http_server_type_get_extended(server_ptr, name, name_length, http_type_string, http_type_string_max_size);
5606 }
5607
5608
5609 /**************************************************************************/
5610 /* */
5611 /* FUNCTION RELEASE */
5612 /* */
5613 /* _nx_http_server_type_get_extended PORTABLE C */
5614 /* 6.1 */
5615 /* AUTHOR */
5616 /* */
5617 /* Yuxin Zhou, Microsoft Corporation */
5618 /* */
5619 /* DESCRIPTION */
5620 /* */
5621 /* This function derives the type of the resource. */
5622 /* */
5623 /* Note: The string of name must be NULL-terminated and length of each */
5624 /* string matches the length specified in the argument list. */
5625 /* */
5626 /* INPUT */
5627 /* */
5628 /* server_ptr HTTP Server pointer */
5629 /* name Name string */
5630 /* name_length Length of name string */
5631 /* http_type_string Destination HTTP type string */
5632 /* http_type_string_max_size Size of the destination string*/
5633 /* */
5634 /* OUTPUT */
5635 /* */
5636 /* Size Number of bytes in string, or */
5637 /* 0 if http_type_string is too */
5638 /* small for the resource */
5639 /* string, or name exceeds */
5640 /* NX_HTTP_MAX_RESOURCE */
5641 /* */
5642 /* CALLS */
5643 /* */
5644 /* _nx_http_server_memicmp */
5645 /* _nx_utility_string_length_check */
5646 /* */
5647 /* CALLED BY */
5648 /* */
5649 /* _nx_http_server_get_process Process GET request */
5650 /* Application Code */
5651 /* */
5652 /* RELEASE HISTORY */
5653 /* */
5654 /* DATE NAME DESCRIPTION */
5655 /* */
5656 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5657 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
5658 /* verified memcpy use cases, */
5659 /* resulting in version 6.1 */
5660 /* */
5661 /**************************************************************************/
_nx_http_server_type_get_extended(NX_HTTP_SERVER * server_ptr,CHAR * name,UINT name_length,CHAR * http_type_string,UINT http_type_string_max_size)5662 UINT _nx_http_server_type_get_extended(NX_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length, CHAR *http_type_string, UINT http_type_string_max_size)
5663 {
5664
5665 UINT i;
5666 CHAR *ch;
5667 UINT ext_length;
5668 UINT map_ext_length;
5669 UINT map_type_length;
5670 UINT temp_name_length;
5671
5672 /* Check name length. */
5673 if (_nx_utility_string_length_check(name, &temp_name_length, name_length))
5674 {
5675 return(NX_HTTP_ERROR);
5676 }
5677
5678 /* Validate string length. */
5679 if (name_length != temp_name_length)
5680 {
5681 return(NX_HTTP_ERROR);
5682 }
5683
5684 /* First find the end of the string. */
5685 ch = name + name_length;
5686
5687 /* Now look backwards to find the last period that signals the
5688 file extension. */
5689 ext_length = 0;
5690 while ((ch >= name) && (*ch != '.') &&(*ch != '/'))
5691 {
5692 ch--;
5693 ext_length++;
5694 }
5695
5696 if(*ch != '.')
5697 {
5698
5699 /* No extension is found. Return the default mime type. */
5700 if(http_type_string_max_size < (sizeof(NX_HTTP_SERVER_DEFAULT_MIME)))
5701 {
5702 /* NX_HTTP_SERVER_DEFAULT_MIME does not fit into
5703 the caller-supplied http_type_string. */
5704 return (0);
5705 }
5706
5707 /* return the default MIME type. */
5708 memcpy(http_type_string, NX_HTTP_SERVER_DEFAULT_MIME, sizeof(NX_HTTP_SERVER_DEFAULT_MIME)); /* Use case of memcpy is verified. */
5709 return(sizeof(NX_HTTP_SERVER_DEFAULT_MIME) - 1);
5710 }
5711
5712 /* Position forward again, past the period. */
5713 ch++;
5714 ext_length--;
5715
5716 /* Now see what HTTP file type to return. */
5717 /* Search user defined MIME maps first. */
5718 if(server_ptr -> nx_http_server_mime_maps_additional &&
5719 (server_ptr -> nx_http_server_mime_maps_additional_num > 0))
5720 {
5721 for(i = 0; i < server_ptr -> nx_http_server_mime_maps_additional_num; i++)
5722 {
5723 /* Check map extension and type length. */
5724 if (_nx_utility_string_length_check(server_ptr -> nx_http_server_mime_maps_additional[i].nx_http_server_mime_map_extension,
5725 &map_ext_length, ext_length) ||
5726 _nx_utility_string_length_check(server_ptr -> nx_http_server_mime_maps_additional[i].nx_http_server_mime_map_type,
5727 &map_type_length, http_type_string_max_size - 1))
5728 {
5729 continue;
5730 }
5731
5732 if(_nx_http_server_memicmp((UCHAR *)ch, ext_length,
5733 (UCHAR *)server_ptr -> nx_http_server_mime_maps_additional[i].nx_http_server_mime_map_extension,
5734 map_ext_length) == NX_SUCCESS)
5735 {
5736
5737 /* Find the extension. Return the mapped MIME type. */
5738 memcpy(http_type_string, server_ptr -> nx_http_server_mime_maps_additional[i].nx_http_server_mime_map_type, map_type_length + 1); /* Use case of memcpy is verified. */
5739 return(map_type_length);
5740 }
5741 }
5742 }
5743
5744 /* Search default MIME maps. */
5745 for(i = 0; i < sizeof(_nx_http_server_mime_maps) / sizeof(NX_HTTP_SERVER_MIME_MAP); i++)
5746 {
5747
5748 /* Check map extension and type length. */
5749 if (_nx_utility_string_length_check(_nx_http_server_mime_maps[i].nx_http_server_mime_map_extension,
5750 &map_ext_length, ext_length) ||
5751 _nx_utility_string_length_check(_nx_http_server_mime_maps[i].nx_http_server_mime_map_type,
5752 &map_type_length, http_type_string_max_size - 1))
5753 {
5754 continue;
5755 }
5756
5757 if(_nx_http_server_memicmp((UCHAR *)ch, ext_length,
5758 (UCHAR *)_nx_http_server_mime_maps[i].nx_http_server_mime_map_extension,
5759 map_ext_length) == NX_SUCCESS)
5760 {
5761
5762 /* Find the extension. Return the mapped MIME type. */
5763 memcpy(http_type_string, _nx_http_server_mime_maps[i].nx_http_server_mime_map_type, map_type_length + 1); /* Use case of memcpy is verified. */
5764 return(map_type_length);
5765 }
5766 }
5767
5768 /* No extension matches. Return the default mime type. */
5769 if(http_type_string_max_size < (sizeof(NX_HTTP_SERVER_DEFAULT_MIME)))
5770 {
5771 /* NX_HTTP_SERVER_DEFAULT_MIME does not fit into
5772 the caller-supplied http_type_string. */
5773 return (0);
5774 }
5775
5776 /* return the default MIME type. */
5777 memcpy(http_type_string, NX_HTTP_SERVER_DEFAULT_MIME, sizeof(NX_HTTP_SERVER_DEFAULT_MIME)); /* Use case of memcpy is verified. */
5778 return(sizeof(NX_HTTP_SERVER_DEFAULT_MIME) - 1);
5779 }
5780
5781 #ifdef NX_HTTP_DIGEST_ENABLE
5782 /**************************************************************************/
5783 /* */
5784 /* FUNCTION RELEASE */
5785 /* */
5786 /* _nx_http_server_nonce_allocate PORTABLE C */
5787 /* 6.2.0 */
5788 /* AUTHOR */
5789 /* */
5790 /* Yuxin Zhou, Microsoft Corporation */
5791 /* */
5792 /* DESCRIPTION */
5793 /* */
5794 /* This function allocate a new nonce for digest authentication. */
5795 /* */
5796 /* INPUT */
5797 /* */
5798 /* server_ptr HTTP Server pointer */
5799 /* nonce_ptr Allocated nonce pointer */
5800 /* */
5801 /* OUTPUT */
5802 /* */
5803 /* None */
5804 /* */
5805 /* CALLS */
5806 /* */
5807 /* tx_time_get Get system time */
5808 /* */
5809 /* CALLED BY */
5810 /* */
5811 /* _nx_http_server_digest_authenticate Digest authentication */
5812 /* */
5813 /* RELEASE HISTORY */
5814 /* */
5815 /* DATE NAME DESCRIPTION */
5816 /* */
5817 /* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */
5818 /* */
5819 /**************************************************************************/
_nx_http_server_nonce_allocate(NX_HTTP_SERVER * server_ptr,NX_HTTP_SERVER_NONCE ** nonce_ptr)5820 UINT _nx_http_server_nonce_allocate(NX_HTTP_SERVER *server_ptr, NX_HTTP_SERVER_NONCE **nonce_ptr)
5821 {
5822 UINT i;
5823 UCHAR random_value;
5824 NX_HTTP_SERVER_NONCE *nonces_list = server_ptr -> nx_http_server_nonces;
5825
5826
5827 /* Search if there is free entry for new nonce. */
5828 for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++)
5829 {
5830 if (nonces_list[i].nonce_state == NX_HTTP_SERVER_NONCE_INVALID)
5831 {
5832 *nonce_ptr = &(nonces_list[i]);
5833 break;
5834 }
5835 }
5836
5837 if (i == NX_HTTP_SERVER_NONCE_MAX)
5838 {
5839
5840 /* If no free entry, check the timeout of allocated nonces. */
5841 for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++)
5842 {
5843 if (nonces_list[i].nonce_state == NX_HTTP_SERVER_NONCE_VALID)
5844 {
5845 if (tx_time_get() > nonces_list[i].nonce_timestamp + NX_HTTP_SERVER_NONCE_TIMEOUT)
5846 {
5847
5848 /* If this nonce is timed out, free up this entry for new nonce. */
5849 *nonce_ptr = &(nonces_list[i]);
5850 break;
5851 }
5852 }
5853 }
5854
5855 /* If no entry can be allocated, return error. */
5856 if (i == NX_HTTP_SERVER_NONCE_MAX)
5857 {
5858 return(NX_NOT_FOUND);
5859 }
5860 }
5861
5862 /* Generate new nonce for digest authentication. */
5863 for (i = 0; i < NX_HTTP_SERVER_NONCE_SIZE; i++)
5864 {
5865 random_value = (UCHAR)NX_RAND() % (sizeof(_nx_http_server_base64_array) - 1);
5866 (*nonce_ptr) -> nonce_buffer[i] = (UCHAR)_nx_http_server_base64_array[random_value];
5867 }
5868
5869 /* Reset the timestamp and state for the new nonce. */
5870 (*nonce_ptr) -> nonce_timestamp = tx_time_get();
5871 (*nonce_ptr) -> nonce_state = NX_HTTP_SERVER_NONCE_VALID;
5872
5873 return(NX_SUCCESS);
5874 }
5875
5876 /**************************************************************************/
5877 /* */
5878 /* FUNCTION RELEASE */
5879 /* */
5880 /* _nx_http_server_digest_authenticate PORTABLE C */
5881 /* 6.2.0 */
5882 /* AUTHOR */
5883 /* */
5884 /* Yuxin Zhou, Microsoft Corporation */
5885 /* */
5886 /* DESCRIPTION */
5887 /* */
5888 /* This function checks for digest (MD5 only) authentication. */
5889 /* If the digest is correct, it returns a success. Otherwise, it */
5890 /* returns an authentication request to the requesting client. */
5891 /* */
5892 /* */
5893 /* INPUT */
5894 /* */
5895 /* server_ptr HTTP Server pointer */
5896 /* packet_ptr Request packet pointer */
5897 /* name_ptr Pointer to name string */
5898 /* name_length Length of name string */
5899 /* password_ptr Pointer to password string */
5900 /* password_length Length of password string */
5901 /* realm_ptr Pointer to realm string */
5902 /* realm_length Length of realm string */
5903 /* auth_request_present Indicate if authentication */
5904 /* must be performed */
5905 /* */
5906 /* OUTPUT */
5907 /* */
5908 /* status Completion status */
5909 /* */
5910 /* CALLS */
5911 /* */
5912 /* _nx_http_server_retrieve_digest_authorization Pickup authorization */
5913 /* _nx_http_server_digest_response_calculate Calculate the digest */
5914 /* nx_packet_allocate Allocate a new packet */
5915 /* nx_packet_data_append Append information to response*/
5916 /* nx_packet_release Release packet */
5917 /* nx_tcp_socket_send Send HTTP Server response */
5918 /* */
5919 /* CALLED BY */
5920 /* */
5921 /* _nx_http_server_get_process Process GET request */
5922 /* _nx_http_server_put_process Process PUT request */
5923 /* _nx_http_server_delete_process Process DELETE request */
5924 /* */
5925 /* RELEASE HISTORY */
5926 /* */
5927 /* DATE NAME DESCRIPTION */
5928 /* */
5929 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5930 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5931 /* resulting in version 6.1 */
5932 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
5933 /* supported random nonce, */
5934 /* resulting in version 6.2.0 */
5935 /* */
5936 /**************************************************************************/
_nx_http_server_digest_authenticate(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * name_ptr,UINT name_length,CHAR * password_ptr,UINT password_length,CHAR * realm_ptr,UINT realm_length,UINT * auth_request_present)5937 UINT _nx_http_server_digest_authenticate(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, UINT name_length, CHAR *password_ptr, UINT password_length, CHAR *realm_ptr, UINT realm_length, UINT *auth_request_present)
5938 {
5939
5940 CHAR authorization_response[NX_HTTP_MAX_ASCII_MD5 + 1];
5941 CHAR calculated_response[NX_HTTP_MAX_ASCII_MD5 + 1];
5942 CHAR authorization_uri[NX_HTTP_MAX_RESOURCE + 1];
5943 CHAR method[8];
5944 CHAR quote[2] = {0x22, 0};
5945 CHAR *buffer_ptr;
5946 UINT i;
5947 UINT status, status1, callback_status;
5948 CHAR crlf[2] = {13,10};
5949 CHAR authorization_nc[NX_HTTP_MAX_RESOURCE + 1];
5950 CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1];
5951 NX_HTTP_SERVER_NONCE *nonce_ptr = NX_NULL;
5952
5953
5954 /* Default to no authentication request detected. */
5955 *auth_request_present = NX_FALSE;
5956
5957 /* Default the status to authenticate. */
5958 status = NX_HTTP_DIGEST_AUTHENTICATE;
5959
5960 /* Is the authorization request present? */
5961 if (_nx_http_server_retrieve_digest_authorization(server_ptr, packet_ptr, authorization_response, authorization_uri, authorization_nc, authorization_cnonce, &nonce_ptr))
5962 {
5963
5964 /* Yes, an authorization request is present. */
5965 *auth_request_present = NX_TRUE;
5966
5967 /* Pickup method from the packet. */
5968 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
5969 i = 0;
5970 while (((buffer_ptr + i) < (CHAR *)packet_ptr -> nx_packet_append_ptr) && (buffer_ptr[i] != ' ') && (i < (sizeof(method) - 1)))
5971 {
5972
5973 /* Copy bytes of method. */
5974 method[i] = buffer_ptr[i];
5975 i++;
5976 }
5977
5978 /* Null terminate method. */
5979 method[i] = (CHAR) NX_NULL;
5980
5981 /* If the digest authenticate callback function is set, invoke the callback function. */
5982 if(server_ptr -> nx_http_server_digest_authenticate_callback)
5983 {
5984 callback_status = (server_ptr -> nx_http_server_digest_authenticate_callback)(server_ptr, name_ptr, realm_ptr, password_ptr, method, authorization_uri, authorization_nc, authorization_cnonce);
5985 }
5986 else
5987 {
5988
5989 /* If the digest authenticate callback is not set, assume it is success, for backward
5990 compatibility reasons. */
5991 callback_status = NX_SUCCESS;
5992 }
5993
5994
5995 /* Calculate what the MD5 should be. */
5996 _nx_http_server_digest_response_calculate(server_ptr, name_ptr, name_length, realm_ptr, realm_length, password_ptr, password_length, (CHAR *)(nonce_ptr -> nonce_buffer), method, authorization_uri, authorization_nc, authorization_cnonce, calculated_response);
5997
5998 /* Determine if the calculated response is the same as the received response. */
5999 i = 0;
6000 status = NX_SUCCESS;
6001 while (i < NX_HTTP_MAX_ASCII_MD5 + 1)
6002 {
6003 /* Is there a mismatch? */
6004 if (calculated_response[i] != authorization_response[i])
6005 {
6006
6007 /* Authorization mismatch. Continue to avoid timing attack. */
6008 status = NX_HTTP_DIGEST_AUTHENTICATE;
6009 }
6010
6011 /* Otherwise, look at next character. */
6012 i++;
6013 }
6014
6015 /* If the response is authenticated, mark the nonce as accepted. */
6016 if (status == NX_SUCCESS)
6017 {
6018 nonce_ptr -> nonce_state = NX_HTTP_SERVER_NONCE_ACCEPTED;
6019 }
6020 else
6021 {
6022 nonce_ptr -> nonce_state = NX_HTTP_SERVER_NONCE_INVALID;
6023 }
6024
6025 /* If digest authenticate callback function returns non-success value, the request is
6026 considered unauthenticated. */
6027 if(callback_status != NX_SUCCESS)
6028 status = NX_HTTP_DIGEST_AUTHENTICATE;
6029 }
6030
6031 /* Determine if we need to send back an unauthorized request. */
6032 if (status == NX_HTTP_DIGEST_AUTHENTICATE)
6033 {
6034
6035 /* Allocate a new nonce for digest authentication. */
6036 status1 = _nx_http_server_nonce_allocate(server_ptr, &nonce_ptr);
6037
6038 /* Determine if an error occurred in the packet allocation. */
6039 if (status1)
6040 {
6041
6042 /* Send response back to HTTP Client. */
6043 _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1,
6044 "NetX HTTP Server Internal Error", sizeof("NetX HTTP Server Internal Error") - 1, NX_NULL, 0);
6045
6046 /* Indicate an allocation error occurred. */
6047 server_ptr -> nx_http_server_allocation_errors++;
6048
6049 /* Return the internal NetX error. */
6050 return(status1);
6051 }
6052
6053 /* We need authorization so build the HTTP 401 Unauthorized message to send to the server. */
6054
6055 /* Allocate a packet for sending the response back. */
6056 status1 = nx_packet_allocate(server_ptr -> nx_http_server_packet_pool_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
6057
6058 /* Determine if an error occurred in the packet allocation. */
6059 if (status1 != NX_SUCCESS)
6060 {
6061
6062 /* Indicate an allocation error occurred. */
6063 server_ptr -> nx_http_server_allocation_errors++;
6064
6065 /* Return the internal NetX error. */
6066 return(status1);
6067 }
6068
6069 /* Insert the response header. */
6070 nx_packet_data_append(packet_ptr, NX_HTTP_VERSION, sizeof(NX_HTTP_VERSION) - 1,
6071 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6072 nx_packet_data_append(packet_ptr, " ", 1, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6073 nx_packet_data_append(packet_ptr, NX_HTTP_STATUS_UNAUTHORIZED, sizeof(NX_HTTP_STATUS_UNAUTHORIZED) - 1,
6074 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6075
6076 /* Place the <cr,lf> into the buffer. */
6077 nx_packet_data_append(packet_ptr, crlf, 2,
6078 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6079
6080 /* Insert the type of authentication requested. */
6081 nx_packet_data_append(packet_ptr, "WWW-Authenticate: Digest realm=", 31,
6082 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6083
6084 /* Insert the double quote. */
6085 nx_packet_data_append(packet_ptr, quote, 1,
6086 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6087
6088 /* Place the realm string into the buffer. */
6089 nx_packet_data_append(packet_ptr, realm_ptr, realm_length,
6090 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6091
6092 /* Insert the double quote. */
6093 nx_packet_data_append(packet_ptr, quote, 1,
6094 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6095
6096 /* Place a comma into the buffer. */
6097 nx_packet_data_append(packet_ptr, ",", 1,
6098 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6099
6100 /* Insert the algorithm into the buffer. */
6101 nx_packet_data_append(packet_ptr, " algorithm=", 11,
6102 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6103
6104 /* Insert the double quote. */
6105 nx_packet_data_append(packet_ptr, quote, 1,
6106 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6107
6108 /* Insert the md5 tag into the buffer. */
6109 nx_packet_data_append(packet_ptr, "md5", 3,
6110 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6111
6112 /* Insert the double quote. */
6113 nx_packet_data_append(packet_ptr, quote, 1,
6114 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6115
6116 /* Place a comma into the buffer. */
6117 nx_packet_data_append(packet_ptr, ",", 1,
6118 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6119
6120 /* Insert the nonce into the buffer. */
6121 nx_packet_data_append(packet_ptr, " nonce=", 7,
6122 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6123
6124 /* Insert the double quote. */
6125 nx_packet_data_append(packet_ptr, quote, 1,
6126 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6127
6128 /* Place the nonce string into the buffer. */
6129 nx_packet_data_append(packet_ptr, nonce_ptr -> nonce_buffer, NX_HTTP_SERVER_NONCE_SIZE,
6130 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6131
6132 /* Insert the double quote. */
6133 nx_packet_data_append(packet_ptr, quote, 1,
6134 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6135
6136 /* Place the qop="auth" parameter string into the buffer. */
6137 nx_packet_data_append(packet_ptr, ", qop=\"auth\"", 12,
6138 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6139
6140 /* Place the <cr,lf> into the buffer. */
6141 nx_packet_data_append(packet_ptr, crlf, 2,
6142 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6143
6144 /* Set Content-Length as 0. */
6145 nx_packet_data_append(packet_ptr, "Content-Length: 0", 17,
6146 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6147
6148 /* Place the <cr,lf> into the buffer. */
6149 nx_packet_data_append(packet_ptr, crlf, 2,
6150 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6151
6152 /* Place another <cr,lf> into the buffer to signal end of FULL HTTP response. */
6153 nx_packet_data_append(packet_ptr, crlf, 2,
6154 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
6155
6156 /* Send the response back to the client. */
6157 status1 = nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
6158
6159 /* Check for an error. */
6160 if (status1)
6161 {
6162
6163 /* Set the internal NetX error as the status return. */
6164 status = status1;
6165
6166 /* Just release the packet. */
6167 nx_packet_release(packet_ptr);
6168 }
6169 }
6170
6171 /* Return the result of the authentication request. */
6172 return(status);
6173 }
6174
6175
6176 /**************************************************************************/
6177 /* */
6178 /* FUNCTION RELEASE */
6179 /* */
6180 /* _nx_http_server_digest_response_calculate PORTABLE C */
6181 /* 6.2.0 */
6182 /* AUTHOR */
6183 /* */
6184 /* Yuxin Zhou, Microsoft Corporation */
6185 /* */
6186 /* DESCRIPTION */
6187 /* */
6188 /* This function computes the MD5 digest based on the supplied input */
6189 /* parameters. */
6190 /* */
6191 /* INPUT */
6192 /* */
6193 /* server_ptr HTTP Server pointer */
6194 /* username Username string */
6195 /* realm Realm string */
6196 /* password Password string */
6197 /* nonce Authentication nonce string */
6198 /* method Request method string */
6199 /* uri Resource request string */
6200 /* nc Nonce count string */
6201 /* cnonce Client nonce string */
6202 /* result Computed digest string */
6203 /* */
6204 /* OUTPUT */
6205 /* */
6206 /* None */
6207 /* */
6208 /* CALLS */
6209 /* */
6210 /* _nx_http_server_hex_ascii_convert Convert hex to ASCII */
6211 /* _nx_md5_initialize Initialize MD5 algorithm */
6212 /* _nx_md5_update Update MD5 digest */
6213 /* _nx_md5_digest_calculate Complete the MD5 algorithm */
6214 /* _nx_utility_string_length_check Check string length */
6215 /* */
6216 /* CALLED BY */
6217 /* */
6218 /* _nx_http_server_digest_authenticate Digest authentication */
6219 /* */
6220 /* RELEASE HISTORY */
6221 /* */
6222 /* DATE NAME DESCRIPTION */
6223 /* */
6224 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6225 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6226 /* resulting in version 6.1 */
6227 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
6228 /* supported random nonce, */
6229 /* resulting in version 6.2.0 */
6230 /* */
6231 /**************************************************************************/
_nx_http_server_digest_response_calculate(NX_HTTP_SERVER * server_ptr,CHAR * username,UINT username_length,CHAR * realm,UINT realm_length,CHAR * password,UINT password_length,CHAR * nonce,CHAR * method,CHAR * uri,CHAR * nc,CHAR * cnonce,CHAR * result)6232 VOID _nx_http_server_digest_response_calculate(NX_HTTP_SERVER *server_ptr, CHAR *username, UINT username_length, CHAR *realm, UINT realm_length, CHAR *password, UINT password_length, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result)
6233 {
6234
6235 CHAR md5_binary[NX_HTTP_MAX_BINARY_MD5];
6236 CHAR ha1_string[NX_HTTP_MAX_ASCII_MD5 + 1];
6237 CHAR ha2_string[NX_HTTP_MAX_ASCII_MD5 + 1];
6238 UINT method_length;
6239 UINT uri_length;
6240 UINT nc_length;
6241 UINT cnonce_length;
6242
6243 /* Check string length. */
6244 if (_nx_utility_string_length_check(method, &method_length, 7) ||
6245 _nx_utility_string_length_check(uri, &uri_length, NX_HTTP_MAX_RESOURCE) ||
6246 _nx_utility_string_length_check(nc, &nc_length, NX_HTTP_MAX_RESOURCE) ||
6247 _nx_utility_string_length_check(cnonce, &cnonce_length, NX_HTTP_MAX_RESOURCE))
6248 {
6249 return;
6250 }
6251
6252
6253 /* Calculate the H(A1) portion of the digest. */
6254 _nx_md5_initialize(&(server_ptr -> nx_http_server_md5data));
6255 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) username, username_length);
6256 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6257 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) realm, realm_length);
6258 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6259 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) password, password_length);
6260 _nx_md5_digest_calculate(&(server_ptr -> nx_http_server_md5data), (unsigned char *) md5_binary);
6261
6262 /* Convert this H(A1) portion to ASCII Hex representation. */
6263 _nx_http_server_hex_ascii_convert(md5_binary, NX_HTTP_MAX_BINARY_MD5, ha1_string);
6264
6265 /* Make the H(A2) portion of the digest. */
6266 _nx_md5_initialize(&(server_ptr -> nx_http_server_md5data));
6267 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) method, method_length);
6268 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6269 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) uri, uri_length);
6270 _nx_md5_digest_calculate(&(server_ptr -> nx_http_server_md5data), (unsigned char *) md5_binary);
6271
6272 /* Convert this H(A2) portion to ASCII Hex representation. */
6273 _nx_http_server_hex_ascii_convert(md5_binary, NX_HTTP_MAX_BINARY_MD5, ha2_string);
6274
6275 /* Now make the final MD5 digest. */
6276 _nx_md5_initialize(&(server_ptr -> nx_http_server_md5data));
6277 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ha1_string, sizeof(ha1_string) - 1);
6278 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6279 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) nonce, NX_HTTP_SERVER_NONCE_SIZE);
6280
6281 /* Start of Internet Explorer bug work-around. */
6282 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6283 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) nc, nc_length);
6284 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6285 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) cnonce, cnonce_length);
6286 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":auth", 5);
6287 /* End of Internet Explorer bug work-around. */
6288
6289 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1);
6290 _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ha2_string, sizeof(ha2_string) - 1);
6291 _nx_md5_digest_calculate(&(server_ptr -> nx_http_server_md5data), (unsigned char *) md5_binary);
6292
6293 /* Finally, convert the response back to an ASCII string and place in
6294 the destination. */
6295 _nx_http_server_hex_ascii_convert(md5_binary, NX_HTTP_MAX_BINARY_MD5, result);
6296 }
6297
6298
6299 /**************************************************************************/
6300 /* */
6301 /* FUNCTION RELEASE */
6302 /* */
6303 /* _nx_http_server_retrieve_digest_authorization PORTABLE C */
6304 /* 6.2.0 */
6305 /* AUTHOR */
6306 /* */
6307 /* Yuxin Zhou, Microsoft Corporation */
6308 /* */
6309 /* DESCRIPTION */
6310 /* */
6311 /* This function retrieves the MD5 digest parameters from the */
6312 /* supplied request packet. */
6313 /* */
6314 /* INPUT */
6315 /* */
6316 /* server_ptr HTTP Server pointer */
6317 /* packet_ptr Request packet pointer */
6318 /* response Digest response pointer */
6319 /* uri URI from response pointer */
6320 /* nc Nonce count string */
6321 /* cnonce Client nonce string */
6322 /* nonce_ptr Server nonce pointer */
6323 /* */
6324 /* OUTPUT */
6325 /* */
6326 /* length Length of response (should be */
6327 /* 32). A value of 0 indicates */
6328 /* an error is present */
6329 /* */
6330 /* CALLS */
6331 /* */
6332 /* None */
6333 /* */
6334 /* CALLED BY */
6335 /* */
6336 /* _nx_http_server_digest_authenticate Digest authentication */
6337 /* */
6338 /* RELEASE HISTORY */
6339 /* */
6340 /* DATE NAME DESCRIPTION */
6341 /* */
6342 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6343 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6344 /* resulting in version 6.1 */
6345 /* 10-31-2022 Yuxin Zhou Modified comment(s), and */
6346 /* supported random nonce, */
6347 /* resulting in version 6.2.0 */
6348 /* */
6349 /**************************************************************************/
_nx_http_server_retrieve_digest_authorization(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr,CHAR * response,CHAR * uri,CHAR * nc,CHAR * cnonce,NX_HTTP_SERVER_NONCE ** nonce_ptr)6350 UINT _nx_http_server_retrieve_digest_authorization(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce, NX_HTTP_SERVER_NONCE **nonce_ptr)
6351 {
6352
6353 UINT length;
6354 UINT found;
6355 CHAR *buffer_ptr;
6356 CHAR *saved_buffer_ptr;
6357 UCHAR *nonce_buffer;
6358 UINT i;
6359
6360
6361 /* Set the found flag to false. */
6362 found = NX_FALSE;
6363
6364 /* Default the authorization request to zero. */
6365 length = 0;
6366
6367 /* Set the response and uri strings to NULL. */
6368 response[0] = NX_NULL;
6369 uri[0] = NX_NULL;
6370
6371 /* Internet Explorer bug work-around. */
6372 nc[0] = NX_NULL;
6373 cnonce[0] = NX_NULL;
6374
6375 /* Setup pointer to buffer. */
6376 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
6377
6378 /* Find the "Authorization: " token first. */
6379 while (((buffer_ptr+15) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6380 {
6381
6382 /* Check for the Authorization: token. */
6383 if (((*buffer_ptr == 'a') || (*buffer_ptr == 'A')) &&
6384 ((*(buffer_ptr+1) == 'u') || (*(buffer_ptr+1) == 'U')) &&
6385 ((*(buffer_ptr+2) == 't') || (*(buffer_ptr+2) == 'T')) &&
6386 ((*(buffer_ptr+3) == 'h') || (*(buffer_ptr+3) == 'H')) &&
6387 ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) &&
6388 ((*(buffer_ptr+5) == 'r') || (*(buffer_ptr+5) == 'R')) &&
6389 ((*(buffer_ptr+6) == 'i') || (*(buffer_ptr+6) == 'I')) &&
6390 ((*(buffer_ptr+7) == 'z') || (*(buffer_ptr+7) == 'Z')) &&
6391 ((*(buffer_ptr+8) == 'a') || (*(buffer_ptr+8) == 'A')) &&
6392 ((*(buffer_ptr+9) == 't') || (*(buffer_ptr+9) == 'T')) &&
6393 ((*(buffer_ptr+10) == 'i') || (*(buffer_ptr+10) == 'I')) &&
6394 ((*(buffer_ptr+11) == 'o') || (*(buffer_ptr+11) == 'O')) &&
6395 ((*(buffer_ptr+12) == 'n') || (*(buffer_ptr+12) == 'N')) &&
6396 (*(buffer_ptr+13) == ':') &&
6397 (*(buffer_ptr+14) == ' '))
6398 {
6399
6400 /* Move the pointer up to the length token. */
6401 buffer_ptr = buffer_ptr + 15;
6402
6403 /* Set the found flag. */
6404 found = NX_TRUE;
6405 break;
6406 }
6407
6408 /* Move the pointer up to the next character. */
6409 buffer_ptr++;
6410 }
6411
6412 /* Determine if the first token was found. */
6413 if (!found)
6414 {
6415
6416 /* No, authorization is not present. Return a zero length. */
6417 return(length);
6418 }
6419
6420 /* Set the found flag back to false. */
6421 found = NX_FALSE;
6422
6423 /* Now remove any extra blanks. */
6424 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
6425 {
6426
6427 /* Move the pointer up one character. */
6428 buffer_ptr++;
6429 }
6430
6431 /* Now check for the "Digest " token. */
6432 while (((buffer_ptr+7) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6433 {
6434
6435 /* Check for the Digest token. */
6436 if (((*buffer_ptr == 'd') || (*buffer_ptr == 'D')) &&
6437 ((*(buffer_ptr+1) == 'i') || (*(buffer_ptr+1) == 'I')) &&
6438 ((*(buffer_ptr+2) == 'g') || (*(buffer_ptr+2) == 'G')) &&
6439 ((*(buffer_ptr+3) == 'e') || (*(buffer_ptr+3) == 'E')) &&
6440 ((*(buffer_ptr+4) == 's') || (*(buffer_ptr+4) == 'S')) &&
6441 ((*(buffer_ptr+5) == 't') || (*(buffer_ptr+5) == 'T')) &&
6442 (*(buffer_ptr+6) == ' '))
6443 {
6444
6445 /* Move the pointer up to the actual authorization string. */
6446 buffer_ptr = buffer_ptr + 7;
6447
6448 /* Set the found flag. */
6449 found = NX_TRUE;
6450 break;
6451 }
6452
6453 /* Move the pointer up to the next character. */
6454 buffer_ptr++;
6455 }
6456
6457 /* Determine if the second token was found. */
6458 if (!found)
6459 {
6460
6461 /* No, digest is not present. Return a zero length. */
6462 return(length);
6463 }
6464
6465 /* Now remove any extra blanks. */
6466 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
6467 {
6468
6469 /* Move the pointer up one character. */
6470 buffer_ptr++;
6471 }
6472
6473 /* Start of Internet Explorer bug work-around (Parses nc and cnonce parameters). */
6474
6475 /* Save current buffer pointer, so each parameter search always starts from here. */
6476 saved_buffer_ptr = buffer_ptr;
6477
6478 while (((buffer_ptr + 6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6479 {
6480
6481 /* Check for the uri token. */
6482 if (((*(buffer_ptr) == 'n') || (*(buffer_ptr) == 'N')) &&
6483 ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) &&
6484 ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) &&
6485 ((*(buffer_ptr+3) == 'c') || (*(buffer_ptr+3) == 'C')) &&
6486 ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) &&
6487 (*(buffer_ptr+5) == '='))
6488 {
6489
6490 /* Move the pointer up to the actual nonce string. */
6491 buffer_ptr = buffer_ptr + 6;
6492 found = NX_TRUE;
6493
6494 break;
6495 }
6496
6497 /* Move the pointer up to the next character. */
6498 buffer_ptr++;
6499 }
6500
6501 /* Check if nonce is found. */
6502 if (!found)
6503 {
6504 return(0);
6505 }
6506
6507 /* Now remove any extra blanks and quotes. */
6508 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
6509 {
6510
6511 /* Move the pointer up one character. */
6512 buffer_ptr++;
6513 }
6514
6515 /* Now pickup the nonce string. */
6516 length = 0;
6517 nonce_buffer = (UCHAR *)buffer_ptr;
6518 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13))
6519 {
6520
6521 /* Determine if the ending quote is present. */
6522 if (*buffer_ptr == (CHAR) 0x22)
6523 {
6524 break;
6525 }
6526
6527 /* Increase the length. */
6528 length++;
6529 buffer_ptr++;
6530 }
6531
6532 /* Check the nonce size. */
6533 if (length != NX_HTTP_SERVER_NONCE_SIZE)
6534 {
6535 return(0);
6536 }
6537
6538 /* Check if the nonce is valid. */
6539 for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++)
6540 {
6541 if ((server_ptr -> nx_http_server_nonces[i].nonce_state != NX_HTTP_SERVER_NONCE_INVALID) &&
6542 (memcmp(server_ptr -> nx_http_server_nonces[i].nonce_buffer, nonce_buffer, NX_HTTP_SERVER_NONCE_SIZE) == 0)) /* Use case of memcmp is verified. */
6543 {
6544 *nonce_ptr = &(server_ptr -> nx_http_server_nonces[i]);
6545 break;
6546 }
6547 }
6548
6549 /* If the nonca is invalid, just return. */
6550 if (i == NX_HTTP_SERVER_NONCE_MAX)
6551 {
6552 return(0);
6553 }
6554
6555 /* Get saved buffer pointer. */
6556 buffer_ptr = saved_buffer_ptr;
6557
6558 /* Now look for the nc in the digest response. */
6559 while (((buffer_ptr+3) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6560 {
6561
6562 /* Check for the nc token. */
6563 if (((*buffer_ptr == 'n') || (*buffer_ptr == 'N')) &&
6564 ((*(buffer_ptr+1) == 'c') || (*(buffer_ptr+1) == 'C')) &&
6565 (*(buffer_ptr+2) == '='))
6566 {
6567
6568 /* Move the pointer up to the actual authorization string. */
6569 buffer_ptr = buffer_ptr + 3;
6570
6571 break;
6572 }
6573
6574 /* Move the pointer up to the next character. */
6575 buffer_ptr++;
6576 }
6577
6578 /* Now remove any extra blanks and quotes (should be no starting quote). */
6579 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
6580 {
6581
6582 /* Move the pointer up one character. */
6583 buffer_ptr++;
6584 }
6585
6586 /* Now pickup the nc string (should be 8 hex characters; should not be quoted). */
6587 length = 0;
6588 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_HTTP_MAX_RESOURCE))
6589 {
6590
6591 /* Determine if the ending quote or comma is present (should be no ending quote). */
6592 if ((*buffer_ptr == (CHAR) 0x22) || (*buffer_ptr == ','))
6593 {
6594
6595 break;
6596 }
6597
6598 /* Copy a character of the authorization string into the destination. */
6599 nc[length++] = *buffer_ptr++;
6600 }
6601
6602 /* Null terminate the NC. */
6603 nc[length] = (CHAR) NX_NULL;
6604
6605
6606 /* Get saved buffer pointer. */
6607 buffer_ptr = saved_buffer_ptr;
6608
6609 /* Now look for the cnonce in the digest response. */
6610 while (((buffer_ptr+7) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6611 {
6612
6613 /* Check for the uri token. */
6614 if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) &&
6615 ((*(buffer_ptr+1) == 'n') || (*(buffer_ptr+1) == 'N')) &&
6616 ((*(buffer_ptr+2) == 'o') || (*(buffer_ptr+2) == 'O')) &&
6617 ((*(buffer_ptr+3) == 'n') || (*(buffer_ptr+3) == 'N')) &&
6618 ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+4) == 'C')) &&
6619 ((*(buffer_ptr+5) == 'e') || (*(buffer_ptr+5) == 'E')) &&
6620 (*(buffer_ptr+6) == '='))
6621 {
6622
6623 /* Move the pointer up to the actual authorization string. */
6624 buffer_ptr = buffer_ptr + 7;
6625
6626 break;
6627 }
6628
6629 /* Move the pointer up to the next character. */
6630 buffer_ptr++;
6631 }
6632
6633 /* Now remove any extra blanks and quotes. */
6634 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
6635 {
6636
6637 /* Move the pointer up one character. */
6638 buffer_ptr++;
6639 }
6640
6641 /* Now pickup the cnonce string. */
6642 length = 0;
6643 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_HTTP_MAX_RESOURCE))
6644 {
6645
6646 /* Determine if the ending quote is present. */
6647 if (*buffer_ptr == (CHAR) 0x22)
6648 {
6649
6650 break;
6651 }
6652
6653 /* Copy a character of the authorization string into the destination. */
6654 cnonce[length++] = *buffer_ptr++;
6655 }
6656
6657 /* Null terminate the CNONCE. */
6658 cnonce[length] = (CHAR) NX_NULL;
6659
6660 /* End of Internet Explorer bug work-around. */
6661
6662 /* Get saved buffer pointer. */
6663 buffer_ptr = saved_buffer_ptr;
6664
6665 /* Now look for the uri in the digest response. */
6666 while (((buffer_ptr+4) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6667 {
6668
6669 /* Check for the uri token. */
6670 if (((*buffer_ptr == 'u') || (*buffer_ptr == 'U')) &&
6671 ((*(buffer_ptr+1) == 'r') || (*(buffer_ptr+1) == 'R')) &&
6672 ((*(buffer_ptr+2) == 'i') || (*(buffer_ptr+2) == 'I')) &&
6673 (*(buffer_ptr+3) == '='))
6674 {
6675
6676 /* Move the pointer up to the actual authorization string. */
6677 buffer_ptr = buffer_ptr + 4;
6678
6679 break;
6680 }
6681
6682 /* Move the pointer up to the next character. */
6683 buffer_ptr++;
6684 }
6685
6686 /* Now remove any extra blanks and quotes. */
6687 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
6688 {
6689
6690 /* Move the pointer up one character. */
6691 buffer_ptr++;
6692 }
6693
6694 /* Now pickup the uri string. */
6695 length = 0;
6696 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13) && (length < NX_HTTP_MAX_RESOURCE))
6697 {
6698
6699 /* Determine if the ending quote is present. */
6700 if (*buffer_ptr == (CHAR) 0x22)
6701 {
6702
6703 break;
6704 }
6705
6706 /* Copy a character of the authorization string into the destination. */
6707 uri[length++] = *buffer_ptr++;
6708 }
6709
6710 /* Null terminate the URI. */
6711 uri[length] = (CHAR) NX_NULL;
6712
6713 /* Get saved buffer pointer. */
6714 buffer_ptr = saved_buffer_ptr;
6715
6716 /* Now look for the digest response. */
6717 while (((buffer_ptr+9) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
6718 {
6719
6720 /* Check for the uri token. */
6721 if (((*buffer_ptr == 'r') || (*buffer_ptr == 'R')) &&
6722 ((*(buffer_ptr+1) == 'e') || (*(buffer_ptr+1) == 'E')) &&
6723 ((*(buffer_ptr+2) == 's') || (*(buffer_ptr+2) == 'S')) &&
6724 ((*(buffer_ptr+3) == 'p') || (*(buffer_ptr+3) == 'P')) &&
6725 ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) &&
6726 ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) &&
6727 ((*(buffer_ptr+6) == 's') || (*(buffer_ptr+6) == 'S')) &&
6728 ((*(buffer_ptr+7) == 'e') || (*(buffer_ptr+7) == 'E')) &&
6729 (*(buffer_ptr+8) == '='))
6730 {
6731
6732 /* Move the pointer up to the actual authorization string. */
6733 buffer_ptr = buffer_ptr + 9;
6734
6735 break;
6736 }
6737
6738 /* Move the pointer up to the next character. */
6739 buffer_ptr++;
6740 }
6741
6742 /* Now remove any extra blanks and leading quote. */
6743 while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22)))
6744 {
6745
6746 /* Move the pointer up one character. */
6747 buffer_ptr++;
6748 }
6749
6750 /* Finally, pickup the response. */
6751 length = 0;
6752 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_HTTP_MAX_ASCII_MD5))
6753 {
6754
6755 /* Determine if the ending quote is present. */
6756 if (*buffer_ptr == (CHAR) 0x22)
6757 {
6758
6759 break;
6760 }
6761
6762 /* Copy a character of the response string into the destination. */
6763 response[length++] = *buffer_ptr++;
6764 }
6765
6766 /* Null terminate response. */
6767 response[length] = (CHAR) NX_NULL;
6768
6769 /* Check for an error. */
6770 if ((length != 32) || (buffer_ptr >= (CHAR *) packet_ptr -> nx_packet_append_ptr) || (*buffer_ptr != (CHAR) 0x22))
6771 {
6772
6773 /* Error, clear the length and the response string. */
6774 length = 0;
6775 response[0] = (CHAR) NX_NULL;
6776 }
6777
6778 /* Return the length to the caller. */
6779 return(length);
6780 }
6781
6782
6783 /**************************************************************************/
6784 /* */
6785 /* FUNCTION RELEASE */
6786 /* */
6787 /* _nx_http_server_hex_ascii_convert PORTABLE C */
6788 /* 6.1 */
6789 /* AUTHOR */
6790 /* */
6791 /* Yuxin Zhou, Microsoft Corporation */
6792 /* */
6793 /* DESCRIPTION */
6794 /* */
6795 /* This function converts hexadecimal characters into an ASCII string. */
6796 /* */
6797 /* INPUT */
6798 /* */
6799 /* source Source hex string */
6800 /* source_length Length of source string */
6801 /* destination Pointer to destination string */
6802 /* */
6803 /* OUTPUT */
6804 /* */
6805 /* None */
6806 /* */
6807 /* CALLS */
6808 /* */
6809 /* None */
6810 /* */
6811 /* CALLED BY */
6812 /* */
6813 /* _nx_http_server_digest_response_calculate Digest authentication */
6814 /* */
6815 /* RELEASE HISTORY */
6816 /* */
6817 /* DATE NAME DESCRIPTION */
6818 /* */
6819 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6820 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6821 /* resulting in version 6.1 */
6822 /* */
6823 /**************************************************************************/
_nx_http_server_hex_ascii_convert(CHAR * source,UINT source_length,CHAR * destination)6824 VOID _nx_http_server_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination)
6825 {
6826
6827 UINT i,j;
6828 CHAR digit;
6829
6830
6831 /* Setup destination index. */
6832 j = 0;
6833
6834 /* Loop to process the entire source string. */
6835 for (i = 0; i < source_length; i++)
6836 {
6837
6838 /* Pickup the first nibble. */
6839 digit = (source[i] >> 4) & 0xF;
6840
6841 /* Convert to ASCII and store. */
6842 if (digit <= 9)
6843 destination[j++] = (CHAR)(digit + '0');
6844 else
6845 destination[j++] = (CHAR)(digit + 'a' - 10);
6846
6847 /* Pickup the second nibble. */
6848 digit = source[i] & 0xF;
6849
6850 /* Convert to ASCII and store. */
6851 if (digit <= 9)
6852 destination[j++] = (CHAR)(digit + '0');
6853 else
6854 destination[j++] = (CHAR)(digit + 'a' - 10);
6855 }
6856
6857 /* Finally, place a NULL in the destination string. */
6858 destination[j] = (CHAR) NX_NULL;
6859 }
6860 #endif
6861
6862
6863 /**************************************************************************/
6864 /* */
6865 /* FUNCTION RELEASE */
6866 /* */
6867 /* _nxe_http_server_get_entity_header PORTABLE C */
6868 /* 6.1 */
6869 /* AUTHOR */
6870 /* */
6871 /* Yuxin Zhou, Microsoft Corporation */
6872 /* */
6873 /* DESCRIPTION */
6874 /* */
6875 /* This function checks error for getting the entity header. */
6876 /* */
6877 /* INPUT */
6878 /* */
6879 /* server_ptr Pointer to HTTP server */
6880 /* packet_pptr Pointer to packet */
6881 /* entity_header_buffer Buffer to get entity header */
6882 /* buffer_size Size of buffer */
6883 /* */
6884 /* OUTPUT */
6885 /* */
6886 /* status Completion status */
6887 /* */
6888 /* CALLS */
6889 /* */
6890 /* _nx_http_server_get_entity_header */
6891 /* */
6892 /* CALLED BY */
6893 /* */
6894 /* Application Code */
6895 /* */
6896 /* RELEASE HISTORY */
6897 /* */
6898 /* DATE NAME DESCRIPTION */
6899 /* */
6900 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6901 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6902 /* resulting in version 6.1 */
6903 /* */
6904 /**************************************************************************/
_nxe_http_server_get_entity_header(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,UCHAR * entity_header_buffer,ULONG buffer_size)6905 UINT _nxe_http_server_get_entity_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, UCHAR *entity_header_buffer, ULONG buffer_size)
6906 {
6907
6908 #ifdef NX_HTTP_MULTIPART_ENABLE
6909 /* Check for invalid input pointers. */
6910 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
6911 (packet_pptr == NX_NULL))
6912 return NX_PTR_ERROR;
6913
6914 /* Check for appropriate caller. */
6915 NX_THREADS_ONLY_CALLER_CHECKING
6916
6917 return _nx_http_server_get_entity_header(server_ptr, packet_pptr, entity_header_buffer, buffer_size);
6918 #else
6919 NX_PARAMETER_NOT_USED(server_ptr);
6920 NX_PARAMETER_NOT_USED(packet_pptr);
6921 NX_PARAMETER_NOT_USED(entity_header_buffer);
6922 NX_PARAMETER_NOT_USED(buffer_size);
6923
6924 return NX_HTTP_ERROR;
6925 #endif /* NX_HTTP_MULTIPART_ENABLE */
6926 }
6927
6928
6929 /**************************************************************************/
6930 /* */
6931 /* FUNCTION RELEASE */
6932 /* */
6933 /* _nx_http_server_get_entity_header PORTABLE C */
6934 /* 6.1.11 */
6935 /* AUTHOR */
6936 /* */
6937 /* Yuxin Zhou, Microsoft Corporation */
6938 /* */
6939 /* DESCRIPTION */
6940 /* */
6941 /* This function gets the entity header and skip header. */
6942 /* */
6943 /* INPUT */
6944 /* */
6945 /* server_ptr Pointer to HTTP server */
6946 /* packet_pptr Pointer to packet */
6947 /* entity_header_buffer Buffer to get entity header */
6948 /* buffer_size Size of buffer */
6949 /* */
6950 /* OUTPUT */
6951 /* */
6952 /* status Completion status */
6953 /* */
6954 /* CALLS */
6955 /* */
6956 /* _nx_http_server_field_value_get */
6957 /* _nx_http_server_memicmp */
6958 /* _nx_http_server_boundary_find */
6959 /* nx_packet_release */
6960 /* nx_tcp_socket_receive */
6961 /* _nx_utility_string_length_check */
6962 /* memmove */
6963 /* */
6964 /* CALLED BY */
6965 /* */
6966 /* Application Code */
6967 /* */
6968 /* RELEASE HISTORY */
6969 /* */
6970 /* DATE NAME DESCRIPTION */
6971 /* */
6972 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6973 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6974 /* fixed write underflow, */
6975 /* resulting in version 6.1 */
6976 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
6977 /* verified memmove use cases, */
6978 /* resulting in version 6.1.11 */
6979 /* */
6980 /**************************************************************************/
_nx_http_server_get_entity_header(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,UCHAR * entity_header_buffer,ULONG buffer_size)6981 UINT _nx_http_server_get_entity_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, UCHAR *entity_header_buffer, ULONG buffer_size)
6982 {
6983
6984 #ifdef NX_HTTP_MULTIPART_ENABLE
6985 NX_HTTP_SERVER_MULTIPART *multipart_ptr;
6986 UINT status;
6987 UINT offset;
6988 NX_PACKET *available_packet;
6989 UINT crlf_match_count = 0;
6990 UINT end_boundary_count = 2;
6991 UINT skip_count = 2;
6992 UCHAR *ch;
6993 UINT index;
6994
6995 /* Get multipart context. */
6996 multipart_ptr = &server_ptr -> nx_http_server_multipart;
6997
6998 /* Is the multipart context initialized? */
6999 if(multipart_ptr -> nx_http_server_multipart_boundary[0] == 0)
7000 {
7001 ULONG field_length;
7002 UINT quotation_index;
7003 UINT i;
7004
7005 /* No, it is not initialized. */
7006
7007 /* Get content type. */
7008 status = _nx_http_server_field_value_get(*packet_pptr, (UCHAR *)"content-type", 12,
7009 multipart_ptr -> nx_http_server_multipart_boundary, NX_HTTP_MAX_HEADER_FIELD + 1);
7010 if(status)
7011 return status;
7012
7013 /* Is the content type "multipart"? */
7014 /* Check the length. The length of "multipart/" is 10. */
7015 if (_nx_utility_string_length_check((CHAR *)multipart_ptr -> nx_http_server_multipart_boundary, (UINT *)&field_length, NX_HTTP_MAX_HEADER_FIELD))
7016 return NX_HTTP_ERROR;
7017 if(field_length < 10)
7018 return NX_HTTP_NOT_FOUND;
7019
7020 /* Check the data. */
7021 if(_nx_http_server_memicmp(multipart_ptr -> nx_http_server_multipart_boundary, 10,
7022 (UCHAR *)"multipart/", 10) != NX_SUCCESS)
7023 return NX_HTTP_NOT_FOUND;
7024
7025 /* Find the boundary. The length of "boundary=" is 9. */
7026 index = 0;
7027 while((index + 9) < field_length)
7028 {
7029 if(_nx_http_server_memicmp(&multipart_ptr -> nx_http_server_multipart_boundary[index], 9,
7030 (UCHAR *)"boundary=", 9) == NX_SUCCESS)
7031 {
7032
7033 break;
7034 }
7035
7036 /* Move the pointer up to the next character. */
7037 index++;
7038 }
7039
7040 /* Move the pointer up to the boundary value. */
7041 index += 9;
7042
7043 /* Is boundary string found? */
7044 if((field_length - index) <= 1)
7045 {
7046
7047 /* Boundary not found or no boundary value. */
7048 return NX_HTTP_NOT_FOUND;
7049 }
7050
7051 /* Boundary is started with "CRLF--". */
7052 multipart_ptr -> nx_http_server_multipart_boundary[0] = 13;
7053 multipart_ptr -> nx_http_server_multipart_boundary[1] = 10;
7054 multipart_ptr -> nx_http_server_multipart_boundary[2] = '-';
7055 multipart_ptr -> nx_http_server_multipart_boundary[3] = '-';
7056
7057 /* Remove quotation. */
7058 if(multipart_ptr -> nx_http_server_multipart_boundary[index] == '"')
7059 {
7060
7061 /* Find the right quotation. */
7062 index++;
7063 for(quotation_index = field_length; quotation_index > index; quotation_index--)
7064 {
7065 if(multipart_ptr -> nx_http_server_multipart_boundary[quotation_index] == '"')
7066 break;
7067 }
7068
7069 /* Is the right quotation found? */
7070 if(quotation_index > index)
7071 multipart_ptr -> nx_http_server_multipart_boundary[quotation_index] = 0;
7072 else
7073 {
7074
7075 /* Boundary not valid. */
7076 return NX_HTTP_NOT_FOUND;
7077 }
7078
7079 /* Leave boundary string only. */
7080 memmove(&multipart_ptr -> nx_http_server_multipart_boundary[4],
7081 &multipart_ptr -> nx_http_server_multipart_boundary[index],
7082 quotation_index - index + 1); /* Use case of memmove is verified. */
7083 }
7084 else
7085 {
7086
7087 /* Directly copy boundary string to the head field. */
7088 i = 4;
7089 index -= 4;
7090 do
7091 {
7092 multipart_ptr -> nx_http_server_multipart_boundary[i] = multipart_ptr -> nx_http_server_multipart_boundary[index + i];
7093 i++;
7094 }while((multipart_ptr -> nx_http_server_multipart_boundary[i - 1] != 0) &&
7095 (multipart_ptr -> nx_http_server_multipart_boundary[i - 1] != ' '));
7096
7097 /* Set the terminal character. */
7098 multipart_ptr -> nx_http_server_multipart_boundary[i - 1] = 0;
7099 }
7100 }
7101
7102 /* Find the boundary. */
7103 while(multipart_ptr -> nx_http_server_multipart_boundary_find == NX_FALSE)
7104 {
7105 if(_nx_http_server_boundary_find(server_ptr, packet_pptr) != NX_SUCCESS)
7106 break;
7107 }
7108
7109 /* Whether the boundary is found? */
7110 if(multipart_ptr -> nx_http_server_multipart_boundary_find == NX_FALSE)
7111 return NX_HTTP_NOT_FOUND;
7112
7113 /* Update the packet and offset. */
7114 _nx_http_server_boundary_find(server_ptr, packet_pptr);
7115
7116 /* Get offset of available data in the packet. */
7117 offset = multipart_ptr -> nx_http_server_multipart_available_offset;
7118
7119 /* Skip data that are not header. */
7120 available_packet = *packet_pptr;
7121
7122 if(offset >= available_packet -> nx_packet_length)
7123 {
7124
7125 /* Release the packet that has been processed. */
7126 nx_packet_release(*packet_pptr);
7127
7128 /* All data has been processed. Get a new packet. */
7129 if(nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &available_packet, NX_HTTP_SERVER_TIMEOUT_RECEIVE) != NX_SUCCESS)
7130 {
7131
7132 /* Error, return to caller. */
7133 return(NX_HTTP_TIMEOUT);
7134 }
7135
7136 /* FIXME: Check if the "offset" should be updated. */
7137
7138 /* Store the packet. */
7139 *packet_pptr = available_packet;
7140 server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet = available_packet;
7141 }
7142 #ifndef NX_DISABLE_PACKET_CHAIN
7143 else
7144 {
7145 while((UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr) <= offset)
7146 {
7147 offset -= (UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr);
7148
7149 /* Get next packet. */
7150 available_packet = available_packet -> nx_packet_next;
7151 }
7152 }
7153 #endif /* NX_DISABLE_PACKET_CHAIN */
7154
7155 /* Get entity header. */
7156 ch = available_packet -> nx_packet_prepend_ptr + offset;
7157 index = 0;
7158 while((entity_header_buffer == NX_NULL) || (index < buffer_size))
7159 {
7160
7161 /* Calculate valid CRLF. */
7162 if((*ch == 13) && ((crlf_match_count & 1) == 0))
7163 crlf_match_count++;
7164 else if((*ch == 10) && ((crlf_match_count & 1) == 1))
7165 crlf_match_count++;
7166 else if(*ch == '-')
7167 {
7168
7169 /* Check whether the last boundary is found. */
7170 if(end_boundary_count < 3)
7171 end_boundary_count--;
7172
7173 if(end_boundary_count == 0)
7174 break;
7175 }
7176 else
7177 {
7178 end_boundary_count = 0xFF;
7179 crlf_match_count = 0;
7180 }
7181
7182 /* Copy data to buffer. */
7183 if(skip_count >0)
7184 skip_count--;
7185 else
7186 {
7187 if(entity_header_buffer)
7188 entity_header_buffer[index] = *ch;
7189 index++;
7190 }
7191 multipart_ptr -> nx_http_server_multipart_available_offset++;
7192
7193 /* Check whether two CRLFs are found. */
7194 if(crlf_match_count == 4)
7195 break;
7196
7197 /* Get next character. */
7198 if((ch + 1) >= available_packet -> nx_packet_append_ptr)
7199 {
7200
7201 /* ch points to the end of this packet. */
7202 #ifndef NX_DISABLE_PACKET_CHAIN
7203 if(available_packet -> nx_packet_next)
7204 {
7205
7206 /* Copy data from next packet. */
7207 available_packet = available_packet -> nx_packet_next;
7208 }
7209 else
7210 #endif /* NX_DISABLE_PACKET_CHAIN */
7211 {
7212
7213 /* Release the packet that has been processed. */
7214 nx_packet_release(*packet_pptr);
7215
7216 /* Get a new packet and copy data from it. */
7217 status = nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &available_packet, NX_HTTP_SERVER_TIMEOUT_RECEIVE);
7218
7219 /* Check the return status. */
7220 if (status != NX_SUCCESS)
7221 {
7222
7223 /* Error, return to caller. */
7224 return(NX_HTTP_TIMEOUT);
7225 }
7226
7227 /* Store the packet. */
7228 *packet_pptr = available_packet;
7229 server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet = available_packet;
7230
7231 /* Reset the offset. */
7232 multipart_ptr -> nx_http_server_multipart_available_offset = 0;
7233 }
7234
7235 ch = available_packet -> nx_packet_prepend_ptr;
7236 }
7237 else
7238 ch++;
7239
7240 }
7241
7242 /* Check whether two CRLFs are found. */
7243 if(crlf_match_count == 4)
7244 {
7245
7246 /* Set terminal 0. */
7247 if(entity_header_buffer)
7248 {
7249 if (index >= 4)
7250 {
7251 entity_header_buffer[index - 4] = 0;
7252 }
7253 else
7254 {
7255 entity_header_buffer[0] = 0;
7256 }
7257 }
7258 return NX_SUCCESS;
7259 }
7260 else
7261 return NX_HTTP_NOT_FOUND;
7262 #else
7263 NX_PARAMETER_NOT_USED(server_ptr);
7264 NX_PARAMETER_NOT_USED(packet_pptr);
7265 NX_PARAMETER_NOT_USED(entity_header_buffer);
7266 NX_PARAMETER_NOT_USED(buffer_size);
7267
7268 return NX_HTTP_ERROR;
7269 #endif /* NX_HTTP_MULTIPART_ENABLE */
7270 }
7271
7272
7273 /**************************************************************************/
7274 /* */
7275 /* FUNCTION RELEASE */
7276 /* */
7277 /* _nxe_http_server_get_entity_content PORTABLE C */
7278 /* 6.1 */
7279 /* AUTHOR */
7280 /* */
7281 /* Yuxin Zhou, Microsoft Corporation */
7282 /* */
7283 /* DESCRIPTION */
7284 /* */
7285 /* This function checks error for getting the entity content. */
7286 /* */
7287 /* INPUT */
7288 /* */
7289 /* server_ptr Pointer to HTTP server */
7290 /* packet_pptr Pointer to packet */
7291 /* available_offset Return the offset */
7292 /* available_length Return the length */
7293 /* */
7294 /* OUTPUT */
7295 /* */
7296 /* status Completion status */
7297 /* */
7298 /* CALLS */
7299 /* */
7300 /* _nx_http_server_get_entity_content */
7301 /* */
7302 /* CALLED BY */
7303 /* */
7304 /* Application Code */
7305 /* */
7306 /* RELEASE HISTORY */
7307 /* */
7308 /* DATE NAME DESCRIPTION */
7309 /* */
7310 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7311 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7312 /* resulting in version 6.1 */
7313 /* */
7314 /**************************************************************************/
_nxe_http_server_get_entity_content(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,ULONG * available_offset,ULONG * available_length)7315 UINT _nxe_http_server_get_entity_content(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, ULONG *available_offset, ULONG *available_length)
7316 {
7317
7318 #ifdef NX_HTTP_MULTIPART_ENABLE
7319 /* Check for invalid input pointers. */
7320 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
7321 (packet_pptr == NX_NULL) || (available_offset == NX_NULL) || (available_length == NX_NULL))
7322 return(NX_PTR_ERROR);
7323
7324 /* Check whether boundary is found. */
7325 if(server_ptr -> nx_http_server_multipart.nx_http_server_multipart_boundary[0] == 0)
7326 return(NX_HTTP_ERROR);
7327
7328 return _nx_http_server_get_entity_content(server_ptr, packet_pptr, available_offset, available_length);
7329 #else
7330 NX_PARAMETER_NOT_USED(server_ptr);
7331 NX_PARAMETER_NOT_USED(packet_pptr);
7332 NX_PARAMETER_NOT_USED(available_offset);
7333 NX_PARAMETER_NOT_USED(available_length);
7334
7335 return NX_HTTP_ERROR;
7336 #endif /* NX_HTTP_MULTIPART_ENABLE */
7337 }
7338
7339
7340 /**************************************************************************/
7341 /* */
7342 /* FUNCTION RELEASE */
7343 /* */
7344 /* _nx_http_server_get_entity_content PORTABLE C */
7345 /* 6.1 */
7346 /* AUTHOR */
7347 /* */
7348 /* Yuxin Zhou, Microsoft Corporation */
7349 /* */
7350 /* DESCRIPTION */
7351 /* */
7352 /* This function gets the entity content. */
7353 /* */
7354 /* INPUT */
7355 /* */
7356 /* server_ptr Pointer to HTTP server */
7357 /* packet_pptr Pointer to packet */
7358 /* available_offset Return the offset */
7359 /* available_length Return the length */
7360 /* */
7361 /* OUTPUT */
7362 /* */
7363 /* status Completion status */
7364 /* */
7365 /* CALLS */
7366 /* */
7367 /* _nx_http_server_boundary_find */
7368 /* */
7369 /* CALLED BY */
7370 /* */
7371 /* Application Code */
7372 /* */
7373 /* RELEASE HISTORY */
7374 /* */
7375 /* DATE NAME DESCRIPTION */
7376 /* */
7377 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7378 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7379 /* resulting in version 6.1 */
7380 /* */
7381 /**************************************************************************/
_nx_http_server_get_entity_content(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,ULONG * available_offset,ULONG * available_length)7382 UINT _nx_http_server_get_entity_content(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, ULONG *available_offset, ULONG *available_length)
7383 {
7384
7385 #ifdef NX_HTTP_MULTIPART_ENABLE
7386 UINT status;
7387
7388 /* Whether the boundary is found? */
7389 if(server_ptr -> nx_http_server_multipart.nx_http_server_multipart_boundary_find == NX_TRUE)
7390 return NX_HTTP_BOUNDARY_ALREADY_FOUND;
7391
7392 status = _nx_http_server_boundary_find(server_ptr, packet_pptr);
7393 if(status)
7394 return status;
7395
7396 /* Set the offset and length. */
7397 *available_offset = server_ptr -> nx_http_server_multipart.nx_http_server_multipart_available_offset;
7398 *available_length = server_ptr -> nx_http_server_multipart.nx_http_server_multipart_available_length;
7399
7400 return NX_SUCCESS;
7401 #else
7402 NX_PARAMETER_NOT_USED(server_ptr);
7403 NX_PARAMETER_NOT_USED(packet_pptr);
7404 NX_PARAMETER_NOT_USED(available_offset);
7405 NX_PARAMETER_NOT_USED(available_length);
7406
7407 return NX_HTTP_ERROR;
7408 #endif /* NX_HTTP_MULTIPART_ENABLE */
7409 }
7410
7411
7412 #ifdef NX_HTTP_MULTIPART_ENABLE
7413 /**************************************************************************/
7414 /* */
7415 /* FUNCTION RELEASE */
7416 /* */
7417 /* _nx_http_server_boundary_find PORTABLE C */
7418 /* 6.1 */
7419 /* AUTHOR */
7420 /* */
7421 /* Yuxin Zhou, Microsoft Corporation */
7422 /* */
7423 /* DESCRIPTION */
7424 /* */
7425 /* This function finds boundary in packet even if it is chained. */
7426 /* */
7427 /* INPUT */
7428 /* */
7429 /* server_ptr Pointer to HTTP server */
7430 /* packet_pptr Pointer to packet */
7431 /* */
7432 /* OUTPUT */
7433 /* */
7434 /* status Completion status */
7435 /* */
7436 /* CALLS */
7437 /* */
7438 /* nx_packet_release */
7439 /* nx_tcp_socket_receive */
7440 /* _nx_http_server_match_string */
7441 /* _nx_utility_string_length_check */
7442 /* */
7443 /* CALLED BY */
7444 /* */
7445 /* _nx_http_server_get_entity_header */
7446 /* _nx_http_server_get_entity_content */
7447 /* */
7448 /* RELEASE HISTORY */
7449 /* */
7450 /* DATE NAME DESCRIPTION */
7451 /* */
7452 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7453 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7454 /* resulting in version 6.1 */
7455 /* */
7456 /**************************************************************************/
_nx_http_server_boundary_find(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr)7457 UINT _nx_http_server_boundary_find(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr)
7458 {
7459
7460 NX_HTTP_SERVER_MULTIPART *multipart_ptr;
7461 NX_PACKET *available_packet;
7462 UINT offset;
7463 ULONG match_count = 0;
7464 UCHAR *match_end_ptr;
7465 UINT boundary_length;
7466
7467 /* Get multipart context. */
7468 multipart_ptr = &server_ptr -> nx_http_server_multipart;
7469
7470 /* Is boundary already found? */
7471 if(multipart_ptr -> nx_http_server_multipart_boundary_find == NX_TRUE)
7472 {
7473
7474 /* Yes. Update the packet and offset. */
7475 if(multipart_ptr -> nx_http_server_multipart_next_packet != NX_NULL)
7476 {
7477 nx_packet_release(*packet_pptr);
7478 *packet_pptr = multipart_ptr -> nx_http_server_multipart_next_packet;
7479 server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet = multipart_ptr -> nx_http_server_multipart_next_packet;
7480 }
7481
7482 multipart_ptr -> nx_http_server_multipart_available_offset = multipart_ptr -> nx_http_server_multipart_next_available_offset;
7483
7484 /* Reset next packet and available offset. */
7485 multipart_ptr -> nx_http_server_multipart_next_packet = NX_NULL;
7486 multipart_ptr -> nx_http_server_multipart_next_available_offset = 0;
7487
7488 /* Reset boundary find. */
7489 multipart_ptr -> nx_http_server_multipart_boundary_find = NX_FALSE;
7490
7491 return NX_SUCCESS;
7492 }
7493
7494 /* Is the boundary in the next packet? */
7495 if(multipart_ptr -> nx_http_server_multipart_next_packet)
7496 {
7497
7498 /* Yes, we're done with this packet. */
7499 nx_packet_release(*packet_pptr);
7500
7501 /* Update the packet and multipart offset. */
7502 *packet_pptr = multipart_ptr -> nx_http_server_multipart_next_packet;
7503 server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet = multipart_ptr -> nx_http_server_multipart_next_packet;
7504 multipart_ptr -> nx_http_server_multipart_available_offset = 0;
7505 }
7506 else if(multipart_ptr -> nx_http_server_multipart_next_available_offset)
7507 {
7508
7509 /* Find boundary in this packet. */
7510 /* Update the offset. */
7511 multipart_ptr -> nx_http_server_multipart_available_offset = multipart_ptr -> nx_http_server_multipart_next_available_offset;
7512 }
7513 else
7514 {
7515
7516 /* Find boundary from this packet. */
7517 /* Initialize the offset. */
7518 multipart_ptr -> nx_http_server_multipart_next_available_offset = multipart_ptr -> nx_http_server_multipart_available_offset;
7519 }
7520
7521 /* Reset next packet. */
7522 multipart_ptr -> nx_http_server_multipart_next_packet = NX_NULL;
7523
7524 /* Reset boundary find. */
7525 multipart_ptr -> nx_http_server_multipart_boundary_find = NX_FALSE;
7526
7527
7528 /* Get offset of available data in the packet. */
7529 offset = multipart_ptr -> nx_http_server_multipart_available_offset;
7530
7531 /* Skip data that are not header. */
7532 available_packet = *packet_pptr;
7533
7534 if(offset >= available_packet -> nx_packet_length)
7535 {
7536
7537 /* Release the packet that has been processed. */
7538 nx_packet_release(*packet_pptr);
7539
7540 /* All data has been processed. Get a new packet. */
7541 if(nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &available_packet, NX_HTTP_SERVER_TIMEOUT_RECEIVE) != NX_SUCCESS)
7542 {
7543
7544 /* Error, return to caller. */
7545 return(NX_HTTP_TIMEOUT);
7546 }
7547
7548 /* Store the packet. */
7549 *packet_pptr = available_packet;
7550 server_ptr -> nx_http_server_multipart.nx_http_server_multipart_last_packet = available_packet;
7551
7552 /* Reset the offset. */
7553 multipart_ptr -> nx_http_server_multipart_available_offset = 0;
7554 multipart_ptr -> nx_http_server_multipart_next_available_offset = 0;
7555 offset = 0;
7556 }
7557 else
7558 {
7559 #ifndef NX_DISABLE_PACKET_CHAIN
7560 while((UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr) <= offset)
7561 {
7562 offset -= (UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr);
7563
7564 /* Get next packet. */
7565 available_packet = available_packet -> nx_packet_next;
7566 }
7567 #endif /* NX_DISABLE_PACKET_CHAIN */
7568 }
7569
7570 /* Check boundary length. */
7571 if (_nx_utility_string_length_check((CHAR *)multipart_ptr->nx_http_server_multipart_boundary, &boundary_length, NX_HTTP_MAX_HEADER_FIELD))
7572 {
7573 return(NX_HTTP_ERROR);
7574 }
7575
7576 /* Look for the boundary string in the (next) packet. */
7577 while(_nx_http_server_match_string(available_packet -> nx_packet_prepend_ptr + offset,
7578 available_packet -> nx_packet_append_ptr,
7579 multipart_ptr -> nx_http_server_multipart_boundary,
7580 boundary_length,
7581 &match_count, &match_end_ptr) != NX_SUCCESS)
7582 {
7583
7584 /* Match string in the next packet. */
7585 #ifndef NX_DISABLE_PACKET_CHAIN
7586 if(available_packet -> nx_packet_next)
7587 {
7588 multipart_ptr -> nx_http_server_multipart_next_available_offset += (UINT)((UINT)(available_packet -> nx_packet_append_ptr - available_packet -> nx_packet_prepend_ptr) - offset);
7589 available_packet = available_packet -> nx_packet_next;
7590 offset = 0;
7591 }
7592 else
7593 #endif /* NX_DISABLE_PACKET_CHAIN */
7594 break;
7595 }
7596
7597 /* Is boundary matched? */
7598 if(match_end_ptr)
7599 {
7600
7601 /* Yes. Found a match. */
7602 multipart_ptr -> nx_http_server_multipart_next_available_offset += (UINT)((UINT)(match_end_ptr - available_packet -> nx_packet_prepend_ptr) - offset);
7603 multipart_ptr -> nx_http_server_multipart_available_length = multipart_ptr -> nx_http_server_multipart_next_available_offset - multipart_ptr -> nx_http_server_multipart_available_offset - match_count;
7604 multipart_ptr -> nx_http_server_multipart_boundary_find = NX_TRUE;
7605
7606 }
7607 else if(match_count)
7608 {
7609
7610 /* Set the available length to all remaining data. */
7611 multipart_ptr -> nx_http_server_multipart_available_length = (*packet_pptr) -> nx_packet_length - multipart_ptr -> nx_http_server_multipart_available_offset;
7612
7613 /* Partial match. Get another packet. */
7614 if(nx_tcp_socket_receive(&(server_ptr -> nx_http_server_socket), &available_packet, NX_HTTP_SERVER_TIMEOUT_RECEIVE) != NX_SUCCESS)
7615 {
7616
7617 /* Error, return to caller. */
7618 return(NX_HTTP_TIMEOUT);
7619 }
7620
7621 /* Match the boundary again. */
7622 if(_nx_http_server_match_string(available_packet -> nx_packet_prepend_ptr,
7623 available_packet -> nx_packet_append_ptr,
7624 multipart_ptr -> nx_http_server_multipart_boundary,
7625 boundary_length,
7626 &match_count, &match_end_ptr) == NX_SUCCESS)
7627 {
7628
7629 /* Yes. Find a match. */
7630 if((ULONG)(match_end_ptr - available_packet -> nx_packet_prepend_ptr) < match_count)
7631 {
7632
7633 /* The boundary is between two packets. */
7634 multipart_ptr -> nx_http_server_multipart_next_available_offset = (UINT)(match_end_ptr - available_packet -> nx_packet_prepend_ptr);
7635 multipart_ptr -> nx_http_server_multipart_available_length -= boundary_length - multipart_ptr -> nx_http_server_multipart_next_available_offset;
7636 multipart_ptr -> nx_http_server_multipart_boundary_find = NX_TRUE;
7637 }
7638 else
7639 {
7640
7641 /* The boundary is in the next packet. */
7642 multipart_ptr -> nx_http_server_multipart_next_available_offset = 0;
7643 }
7644 }
7645 else
7646 {
7647
7648 /* The boundary is not found. */
7649 multipart_ptr -> nx_http_server_multipart_next_available_offset = 0;
7650 }
7651
7652 /* Store the packet. */
7653 multipart_ptr -> nx_http_server_multipart_next_packet = available_packet;
7654
7655 }
7656 else
7657 {
7658
7659 /* Set the available length to all remaining data. */
7660 multipart_ptr -> nx_http_server_multipart_available_length = (*packet_pptr) -> nx_packet_length - multipart_ptr -> nx_http_server_multipart_available_offset;
7661 multipart_ptr -> nx_http_server_multipart_next_available_offset = (*packet_pptr) -> nx_packet_length;
7662 }
7663
7664 return NX_SUCCESS;
7665 }
7666 #endif /* NX_HTTP_MULTIPART_ENABLE */
7667
7668
7669 /**************************************************************************/
7670 /* */
7671 /* FUNCTION RELEASE */
7672 /* */
7673 /* _nx_http_server_match_string PORTABLE C */
7674 /* 6.1 */
7675 /* AUTHOR */
7676 /* */
7677 /* Yuxin Zhou, Microsoft Corporation */
7678 /* */
7679 /* DESCRIPTION */
7680 /* */
7681 /* This function compares a target string in specified memory area. */
7682 /* */
7683 /* INPUT */
7684 /* */
7685 /* src_start Pointer to start of source */
7686 /* src_end Pointer to end of source */
7687 /* target Pointer to target */
7688 /* target_length Length of target */
7689 /* match_count Return the match count */
7690 /* match_end_ptr Return the end match position */
7691 /* */
7692 /* OUTPUT */
7693 /* */
7694 /* status Completion status */
7695 /* */
7696 /* CALLS */
7697 /* */
7698 /* _nx_utility_string_length_check */
7699 /* memcmp */
7700 /* */
7701 /* CALLED BY */
7702 /* */
7703 /* _nx_http_server_boundary_find */
7704 /* */
7705 /* RELEASE HISTORY */
7706 /* */
7707 /* DATE NAME DESCRIPTION */
7708 /* */
7709 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7710 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7711 /* resulting in version 6.1 */
7712 /* */
7713 /**************************************************************************/
_nx_http_server_match_string(UCHAR * src_start,UCHAR * src_end,UCHAR * target,ULONG target_length,ULONG * match_count,UCHAR ** match_end_ptr)7714 UINT _nx_http_server_match_string(UCHAR *src_start, UCHAR *src_end, UCHAR *target, ULONG target_length, ULONG *match_count, UCHAR **match_end_ptr)
7715 {
7716
7717 UCHAR *ch;
7718 ULONG pre_match = *match_count;
7719 ULONG remain_match;
7720
7721 /* Initialize. */
7722 *match_end_ptr = NX_NULL;
7723
7724 /* Process part match. */
7725 while(pre_match)
7726 {
7727
7728 /* Compare pre-match. */
7729 if(memcmp(target, target + (*match_count - pre_match), pre_match) == 0)
7730 {
7731
7732 /* Calculate the remain match. */
7733 remain_match = target_length - pre_match;
7734
7735 /* The pre-match is the same. */
7736 if((ULONG)(src_end - src_start) < remain_match)
7737 remain_match = (ULONG)(src_end - src_start);
7738
7739 if(memcmp(target + pre_match, src_start, remain_match) == 0)
7740 {
7741
7742 /* Remain part matches. */
7743 *match_count = pre_match + remain_match;
7744
7745 if(*match_count < target_length)
7746 {
7747
7748 /* Part match. */
7749 return NX_HTTP_NOT_FOUND;
7750 }
7751
7752 /* Full match. */
7753 *match_end_ptr = src_start + remain_match;
7754 return NX_SUCCESS;
7755 }
7756 }
7757
7758 pre_match--;
7759 }
7760
7761 ch = src_start;
7762
7763 /* Perform full match. */
7764 *match_count = target_length;
7765 while(ch + *match_count <= src_end)
7766 {
7767 if(memcmp(ch, target, *match_count) == 0)
7768 {
7769
7770 /* Find a match. */
7771 *match_end_ptr = ch + *match_count;
7772 return NX_SUCCESS;
7773 }
7774
7775 ch++;
7776 }
7777
7778 /* Perform part match. */
7779 for(*match_count = target_length - 1; *match_count > 0; *match_count = *match_count - 1)
7780 {
7781 if(ch + *match_count <= src_end)
7782 {
7783 if(memcmp(ch, target, *match_count) == 0)
7784 {
7785
7786 /* Find a match. */
7787 return NX_HTTP_NOT_FOUND;
7788 }
7789
7790 ch++;
7791 }
7792 }
7793
7794 return NX_HTTP_NOT_FOUND;
7795 }
7796
7797
7798 /**************************************************************************/
7799 /* */
7800 /* FUNCTION RELEASE */
7801 /* */
7802 /* _nx_http_server_field_value_get PORTABLE C */
7803 /* 6.1 */
7804 /* AUTHOR */
7805 /* */
7806 /* Yuxin Zhou, Microsoft Corporation */
7807 /* */
7808 /* DESCRIPTION */
7809 /* */
7810 /* This function gets field value by field name from HTTP header. */
7811 /* */
7812 /* INPUT */
7813 /* */
7814 /* packet_ptr Pointer to packet */
7815 /* field_name Name of filed in header */
7816 /* name_length Length of filed name */
7817 /* field_value Return fieald of value */
7818 /* field_value_size Size of fieald_value */
7819 /* */
7820 /* OUTPUT */
7821 /* */
7822 /* status Completion status */
7823 /* */
7824 /* CALLS */
7825 /* */
7826 /* _nx_utility_string_length_check */
7827 /* _nx_http_server_memicmp */
7828 /* */
7829 /* CALLED BY */
7830 /* */
7831 /* _nx_http_server_get_process */
7832 /* _nx_http_server_get_entity_header */
7833 /* */
7834 /* RELEASE HISTORY */
7835 /* */
7836 /* DATE NAME DESCRIPTION */
7837 /* */
7838 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7839 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7840 /* resulting in version 6.1 */
7841 /* */
7842 /**************************************************************************/
_nx_http_server_field_value_get(NX_PACKET * packet_ptr,UCHAR * field_name,ULONG name_length,UCHAR * field_value,ULONG field_value_size)7843 UINT _nx_http_server_field_value_get(NX_PACKET *packet_ptr, UCHAR *field_name, ULONG name_length, UCHAR *field_value, ULONG field_value_size)
7844 {
7845
7846 UCHAR *ch;
7847 UINT index;
7848
7849
7850 /* Initialize. */
7851 ch = packet_ptr -> nx_packet_prepend_ptr;
7852
7853 /* Loop to find field name. */
7854 while(ch + name_length < packet_ptr -> nx_packet_append_ptr)
7855 {
7856 if(_nx_http_server_memicmp(ch, name_length, field_name, name_length) == NX_SUCCESS)
7857 {
7858
7859 /* Field name found. */
7860 break;
7861 }
7862
7863 /* Move the pointer up to the next character. */
7864 ch++;
7865 }
7866
7867 /* Skip field name and ':'. */
7868 ch += name_length + 1;
7869
7870 /* Is field name found? */
7871 if(ch >= packet_ptr -> nx_packet_append_ptr)
7872 return NX_HTTP_NOT_FOUND;
7873
7874 /* Skip white spaces. */
7875 while(*ch == ' ')
7876 {
7877 if(ch >= packet_ptr -> nx_packet_append_ptr)
7878 return NX_HTTP_NOT_FOUND;
7879
7880 /* Get next character. */
7881 ch++;
7882 }
7883
7884 /* Copy field value. */
7885 index = 0;
7886 while(index < field_value_size)
7887 {
7888
7889 /* Whether the end of line CRLF is not found? */
7890 if(ch + 2 > packet_ptr -> nx_packet_append_ptr)
7891 return NX_HTTP_NOT_FOUND;
7892
7893 /* Compare CRLF. */
7894 if((*ch == 13) && (*(ch + 1) == 10))
7895 break;
7896
7897 /* Copy data. */
7898 field_value[index++] = *ch++;
7899 }
7900
7901 /* Buffer overflow? */
7902 if(index == field_value_size)
7903 return NX_HTTP_NOT_FOUND;
7904
7905 /* Trim white spaces. */
7906 while((index > 0) && (field_value[index - 1] == ' '))
7907 index--;
7908
7909 /* Append terminal 0. */
7910 field_value[index] = 0;
7911
7912
7913 return NX_SUCCESS;
7914 }
7915
7916
7917 /**************************************************************************/
7918 /* */
7919 /* FUNCTION RELEASE */
7920 /* */
7921 /* _nx_http_server_memicmp PORTABLE C */
7922 /* 6.1 */
7923 /* AUTHOR */
7924 /* */
7925 /* Yuxin Zhou, Microsoft Corporation */
7926 /* */
7927 /* DESCRIPTION */
7928 /* */
7929 /* This function compares two pieces of memory case insensitive. */
7930 /* */
7931 /* INPUT */
7932 /* */
7933 /* src Pointer to source */
7934 /* src_length Length of source */
7935 /* dest Pointer to destination */
7936 /* dest_length Length of destination */
7937 /* */
7938 /* OUTPUT */
7939 /* */
7940 /* status Completion status */
7941 /* */
7942 /* CALLS */
7943 /* */
7944 /* */
7945 /* CALLED BY */
7946 /* */
7947 /* _nx_http_server_get_entity_header */
7948 /* _nx_http_server_field_value_get */
7949 /* */
7950 /* RELEASE HISTORY */
7951 /* */
7952 /* DATE NAME DESCRIPTION */
7953 /* */
7954 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7955 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7956 /* resulting in version 6.1 */
7957 /* */
7958 /**************************************************************************/
_nx_http_server_memicmp(UCHAR * src,ULONG src_length,UCHAR * dest,ULONG dest_length)7959 UINT _nx_http_server_memicmp(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length)
7960 {
7961 UCHAR ch;
7962
7963 /* Compare the length. */
7964 if(src_length != dest_length)
7965 return NX_HTTP_FAILED;
7966
7967 while(src_length)
7968 {
7969
7970 /* Is src lowercase? */
7971 if((*src >= 'a') && (*src <= 'z'))
7972 ch = (UCHAR)(*src - 'a' + 'A');
7973
7974 /* Is src uppercase? */
7975 else if((*src >= 'A') && (*src <= 'Z'))
7976 ch = (UCHAR)(*src - 'A' + 'a');
7977 else
7978 ch = *src;
7979
7980 /* Compare case insensitive. */
7981 if((*src != *dest) && (ch != *dest))
7982 return NX_HTTP_FAILED;
7983
7984 /* Pickup next character. */
7985 src_length--;
7986 src++;
7987 dest++;
7988 }
7989
7990 return NX_SUCCESS;
7991 }
7992
7993
7994 /**************************************************************************/
7995 /* */
7996 /* FUNCTION RELEASE */
7997 /* */
7998 /* _nx_http_server_generate_response_header PORTABLE C */
7999 /* 6.1.8 */
8000 /* AUTHOR */
8001 /* */
8002 /* Yuxin Zhou, Microsoft Corporation */
8003 /* */
8004 /* DESCRIPTION */
8005 /* */
8006 /* This function generates HTTP response header. */
8007 /* */
8008 /* Note: The strings of status code, content type length and additional*/
8009 /* header length must be NULL-terminated and length of this string */
8010 /* matches the length specified in the argument list. */
8011 /* */
8012 /* INPUT */
8013 /* */
8014 /* server_ptr Pointer to HTTP server */
8015 /* packet_pptr Pointer to packet */
8016 /* status_code Status-code and reason-phrase */
8017 /* status_code_length Length of status-code */
8018 /* content_length Length of content */
8019 /* content_type Type of content */
8020 /* content_type_length Length of content type */
8021 /* additional_header Other HTTP headers */
8022 /* additional_header_length Length of other HTTP headers */
8023 /* */
8024 /* OUTPUT */
8025 /* */
8026 /* status Completion status */
8027 /* */
8028 /* CALLS */
8029 /* */
8030 /* nx_packet_allocate */
8031 /* nx_packet_data_append */
8032 /* memcmp */
8033 /* _nx_utility_string_length_check */
8034 /* _nx_utility_uint_to_string */
8035 /* _nx_http_server_date_to_string */
8036 /* nx_packet_release */
8037 /* */
8038 /* CALLED BY */
8039 /* */
8040 /* _nx_http_server_get_process */
8041 /* _nx_http_server_put_process */
8042 /* _nx_http_server_delete_process */
8043 /* _nx_http_server_response_send */
8044 /* _nx_http_server_callback_generate_response_header */
8045 /* */
8046 /* RELEASE HISTORY */
8047 /* */
8048 /* DATE NAME DESCRIPTION */
8049 /* */
8050 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8051 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8052 /* resulting in version 6.1 */
8053 /* 08-02-2021 Yuxin Zhou Modified comment(s), */
8054 /* improved the logic of */
8055 /* converting number to string,*/
8056 /* resulting in version 6.1.8 */
8057 /* */
8058 /**************************************************************************/
_nx_http_server_generate_response_header(NX_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)8059 UINT _nx_http_server_generate_response_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, CHAR *status_code,
8060 UINT status_code_length, UINT content_length, CHAR *content_type,
8061 UINT content_type_length, CHAR* additional_header, UINT additional_header_length)
8062 {
8063
8064 UINT status;
8065 UINT temp;
8066 CHAR temp_string[30];
8067 CHAR crlf[2] = {13,10};
8068 NX_PACKET *packet_ptr;
8069 CHAR status_code_ok;
8070 CHAR status_code_not_modified;
8071
8072 /* Allocate a packet for sending the response back. */
8073 status = nx_packet_allocate(server_ptr -> nx_http_server_packet_pool_ptr, packet_pptr, NX_TCP_PACKET, NX_WAIT_FOREVER);
8074
8075 /* Determine if an error occurred in the packet allocation. */
8076 if(status != NX_SUCCESS)
8077 {
8078
8079 /* Indicate an allocation error occurred. */
8080 server_ptr -> nx_http_server_allocation_errors++;
8081
8082 /* Just return. */
8083 return status;
8084 }
8085 else
8086 packet_ptr = *packet_pptr;
8087
8088 /* Check status code. */
8089 if(memcmp(status_code, NX_HTTP_STATUS_OK, sizeof(NX_HTTP_STATUS_OK)) == 0)
8090 status_code_ok = NX_TRUE;
8091 else
8092 status_code_ok = NX_FALSE;
8093
8094 if(memcmp(status_code, NX_HTTP_STATUS_NOT_MODIFIED, sizeof(NX_HTTP_STATUS_NOT_MODIFIED)) == 0)
8095 status_code_not_modified = NX_TRUE;
8096 else
8097 status_code_not_modified = NX_FALSE;
8098
8099 /* Insert the status line. */
8100 /* Place HTTP-Version. */
8101 status = nx_packet_data_append(packet_ptr, NX_HTTP_VERSION, sizeof(NX_HTTP_VERSION) - 1, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8102
8103 /* Insert space. */
8104 status += nx_packet_data_append(packet_ptr, " ", 1, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8105
8106 /* Insert Status-Code and Reason-Phrase. */
8107 status += nx_packet_data_append(packet_ptr, status_code, status_code_length, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8108
8109 /* Place the <cr,lf> into the buffer. */
8110 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8111
8112 /* Determine if there is content_type. */
8113 if(content_type)
8114 {
8115
8116 /* Insert the content type. */
8117 status += nx_packet_data_append(packet_ptr, "Content-Type: ", 14, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8118 status += nx_packet_data_append(packet_ptr, content_type, content_type_length, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8119
8120 /* Place the <cr,lf> into the buffer. */
8121 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8122 }
8123
8124 #ifndef NX_HTTP_SERVER_OMIT_CONTENT_LENGTH
8125 /* Determine if there is content_length. */
8126 if(content_length || (status_code_not_modified == NX_TRUE))
8127 {
8128
8129 /* Close. */
8130 status += nx_packet_data_append(packet_ptr, "Connection: Close", 17,
8131 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8132
8133 /* Place the <cr,lf> into the buffer. */
8134 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8135
8136 if(content_length)
8137 {
8138
8139 /* Convert the content_length to ASCII representation. */
8140 temp = _nx_utility_uint_to_string(content_length, 10, temp_string, sizeof(temp_string));
8141
8142 /* Place the "Content-Length" field in the header. */
8143 status += nx_packet_data_append(packet_ptr, "Content-Length: ", 16,
8144 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8145 status += nx_packet_data_append(packet_ptr, temp_string, temp,
8146 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8147
8148 /* Place the <cr,lf> into the buffer. */
8149 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8150 }
8151
8152 }
8153 else
8154 #endif /* NX_HTTP_SERVER_OMIT_CONTENT_LENGTH */
8155 {
8156
8157 /* Place the "Connection" field in the header. */
8158
8159 /* Force close the connection since there's no content-length. */
8160 status += nx_packet_data_append(packet_ptr, "Connection: Close", 17,
8161 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8162
8163 /* Place the <cr,lf> into the buffer. */
8164 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8165 }
8166
8167 /* Insert Date header if callback function is set. */
8168 if(server_ptr -> nx_http_server_gmt_get)
8169 {
8170 NX_HTTP_SERVER_DATE date;
8171
8172 /* Get current date. */
8173 server_ptr -> nx_http_server_gmt_get(&date);
8174
8175 /* Convert date to string. */
8176 temp = _nx_http_server_date_to_string(&date, temp_string);
8177
8178 /* Place the "Date" field in the header. */
8179 status += nx_packet_data_append(packet_ptr, "Date: ", 6,
8180 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8181
8182 /* Insert date. */
8183 status += nx_packet_data_append(packet_ptr, temp_string, temp, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8184
8185 /* Place the <cr,lf> into the buffer. */
8186 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8187
8188 /* Set Cache Control if callback function is set. */
8189 if((server_ptr -> nx_http_server_cache_info_get) &&
8190 ((status_code_ok == NX_TRUE) || (status_code_not_modified == NX_TRUE)) &&
8191 (server_ptr -> nx_http_server_request_type == NX_HTTP_SERVER_GET_REQUEST))
8192 {
8193 UINT max_age;
8194
8195 /* Get cache infomation. */
8196 if(server_ptr -> nx_http_server_cache_info_get(server_ptr -> nx_http_server_request_resource, &max_age, &date) == NX_TRUE)
8197 {
8198
8199 /* Place "Cache-control" header. */
8200 status += nx_packet_data_append(packet_ptr, "Cache-Control: max-age=", 23,
8201 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8202
8203 /* Convert the max-age to ASCII representation. */
8204 temp = _nx_utility_uint_to_string(max_age, 10, temp_string, sizeof(temp_string));
8205 status += nx_packet_data_append(packet_ptr, temp_string, temp,
8206 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8207
8208 /* Place the <cr,lf> into the buffer. */
8209 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8210
8211 if(status_code_ok == NX_TRUE)
8212 {
8213
8214 /* Convert date to string. */
8215 temp = _nx_http_server_date_to_string(&date, temp_string);
8216
8217 /* Place the "Last-Modified" field in the header. */
8218 status += nx_packet_data_append(packet_ptr, "Last-Modified: ", 15,
8219 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8220
8221 /* Insert date. */
8222 status += nx_packet_data_append(packet_ptr, temp_string, temp, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8223
8224 /* Place the <cr,lf> into the buffer. */
8225 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8226 }
8227 }
8228 }
8229 }
8230
8231 /* Insert additional header. */
8232 if(additional_header)
8233 {
8234
8235 status += nx_packet_data_append(packet_ptr, additional_header, additional_header_length,
8236 server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8237 }
8238
8239 /* Place the <cr,lf> into the buffer. */
8240 status += nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER);
8241
8242 if (status != NX_SUCCESS)
8243 {
8244
8245 /* Just release the packet. */
8246 nx_packet_release(packet_ptr);
8247 }
8248
8249 return status;
8250 }
8251
8252
8253 /**************************************************************************/
8254 /* */
8255 /* FUNCTION RELEASE */
8256 /* */
8257 /* _nxe_http_server_callback_generate_response_header PORTABLE C */
8258 /* 6.1 */
8259 /* AUTHOR */
8260 /* */
8261 /* Yuxin Zhou, Microsoft Corporation */
8262 /* */
8263 /* DESCRIPTION */
8264 /* */
8265 /* This function checks error for generating HTTP response header. */
8266 /* */
8267 /* INPUT */
8268 /* */
8269 /* server_ptr Pointer to HTTP server */
8270 /* packet_pptr Pointer to packet */
8271 /* status_code Status-code and reason-phrase */
8272 /* content_length Length of content */
8273 /* content_type Type of content */
8274 /* additional_header Other HTTP headers */
8275 /* */
8276 /* OUTPUT */
8277 /* */
8278 /* status Completion status */
8279 /* */
8280 /* CALLS */
8281 /* */
8282 /* _nx_http_server_callback_generate_response_header */
8283 /* */
8284 /* CALLED BY */
8285 /* */
8286 /* Application Code */
8287 /* */
8288 /* RELEASE HISTORY */
8289 /* */
8290 /* DATE NAME DESCRIPTION */
8291 /* */
8292 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8293 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8294 /* resulting in version 6.1 */
8295 /* */
8296 /**************************************************************************/
_nxe_http_server_callback_generate_response_header(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT content_length,CHAR * content_type,CHAR * additional_header)8297 UINT _nxe_http_server_callback_generate_response_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr,
8298 CHAR *status_code, UINT content_length, CHAR *content_type,
8299 CHAR* additional_header)
8300 {
8301
8302 /* Check for invalid input pointers. */
8303 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
8304 (packet_pptr == NX_NULL) || (status_code == NX_NULL))
8305 return(NX_PTR_ERROR);
8306
8307 /* Check for appropriate caller. */
8308 NX_THREADS_ONLY_CALLER_CHECKING
8309
8310 return _nx_http_server_callback_generate_response_header(server_ptr, packet_pptr, status_code, content_length, content_type, additional_header);
8311 }
8312
8313
8314 /**************************************************************************/
8315 /* */
8316 /* FUNCTION RELEASE */
8317 /* */
8318 /* _nxe_http_server_callback_generate_response_header_extended */
8319 /* PORTABLE C */
8320 /* 6.1 */
8321 /* AUTHOR */
8322 /* */
8323 /* Yuxin Zhou, Microsoft Corporation */
8324 /* */
8325 /* DESCRIPTION */
8326 /* */
8327 /* This function checks error for generating HTTP response header. */
8328 /* */
8329 /* INPUT */
8330 /* */
8331 /* server_ptr Pointer to HTTP server */
8332 /* packet_pptr Pointer to packet */
8333 /* status_code Status-code and reason-phrase */
8334 /* status_code_length Length of status-code */
8335 /* content_length Length of content */
8336 /* content_type Type of content */
8337 /* content_type_length Length of content type */
8338 /* additional_header Other HTTP headers */
8339 /* additional_header_length Length of other HTTP headers */
8340 /* */
8341 /* OUTPUT */
8342 /* */
8343 /* status Completion status */
8344 /* */
8345 /* CALLS */
8346 /* */
8347 /* _nx_http_server_callback_generate_response_header_extended */
8348 /* Actual responder header */
8349 /* generation function */
8350 /* */
8351 /* CALLED BY */
8352 /* */
8353 /* Application Code */
8354 /* */
8355 /* RELEASE HISTORY */
8356 /* */
8357 /* DATE NAME DESCRIPTION */
8358 /* */
8359 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8360 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8361 /* resulting in version 6.1 */
8362 /* */
8363 /**************************************************************************/
_nxe_http_server_callback_generate_response_header_extended(NX_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)8364 UINT _nxe_http_server_callback_generate_response_header_extended(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, CHAR *status_code,
8365 UINT status_code_length, UINT content_length, CHAR *content_type,
8366 UINT content_type_length, CHAR* additional_header, UINT additional_header_length)
8367 {
8368
8369 /* Check for invalid input pointers. */
8370 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) ||
8371 (packet_pptr == NX_NULL) || (status_code == NX_NULL))
8372 return(NX_PTR_ERROR);
8373
8374 /* Check for appropriate caller. */
8375 NX_THREADS_ONLY_CALLER_CHECKING
8376
8377 return _nx_http_server_callback_generate_response_header_extended(server_ptr, packet_pptr, status_code, status_code_length, content_length,
8378 content_type, content_type_length, additional_header, additional_header_length);
8379 }
8380
8381
8382 /**************************************************************************/
8383 /* */
8384 /* FUNCTION RELEASE */
8385 /* */
8386 /* _nx_http_server_callback_generate_response_header PORTABLE C */
8387 /* 6.1 */
8388 /* AUTHOR */
8389 /* */
8390 /* Yuxin Zhou, Microsoft Corporation */
8391 /* */
8392 /* DESCRIPTION */
8393 /* */
8394 /* This function is used in callback function to generate HTTP */
8395 /* response header. */
8396 /* */
8397 /* INPUT */
8398 /* */
8399 /* server_ptr Pointer to HTTP server */
8400 /* packet_pptr Pointer to packet */
8401 /* status_code Status-code and reason-phrase */
8402 /* content_length Length of content */
8403 /* content_type Type of content */
8404 /* additional_header Other HTTP headers */
8405 /* */
8406 /* OUTPUT */
8407 /* */
8408 /* status Completion status */
8409 /* */
8410 /* CALLS */
8411 /* */
8412 /* _nx_http_server_generate_response_header */
8413 /* Internal responder header */
8414 /* generation function */
8415 /* _nx_utility_string_length_check Check string length */
8416 /* */
8417 /* CALLED BY */
8418 /* */
8419 /* Application Code */
8420 /* */
8421 /* RELEASE HISTORY */
8422 /* */
8423 /* DATE NAME DESCRIPTION */
8424 /* */
8425 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8426 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8427 /* resulting in version 6.1 */
8428 /* */
8429 /**************************************************************************/
_nx_http_server_callback_generate_response_header(NX_HTTP_SERVER * server_ptr,NX_PACKET ** packet_pptr,CHAR * status_code,UINT content_length,CHAR * content_type,CHAR * additional_header)8430 UINT _nx_http_server_callback_generate_response_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr,
8431 CHAR *status_code, UINT content_length, CHAR *content_type,
8432 CHAR* additional_header)
8433 {
8434 UINT status_code_length = 0;
8435 UINT content_type_length = 0;
8436 UINT additional_header_length = 0;
8437
8438 /* Check status code, content type and additional header length. */
8439 if (_nx_utility_string_length_check(status_code, &status_code_length, NX_MAX_STRING_LENGTH) ||
8440 (content_type && _nx_utility_string_length_check(content_type, &content_type_length, NX_MAX_STRING_LENGTH)) ||
8441 (additional_header && _nx_utility_string_length_check(additional_header, &additional_header_length, NX_MAX_STRING_LENGTH)))
8442 {
8443 return(NX_HTTP_ERROR);
8444 }
8445
8446 /* Call the internal HTTP response send function. */
8447 return _nx_http_server_generate_response_header(server_ptr, packet_pptr, status_code, status_code_length, content_length,
8448 content_type, content_type_length, additional_header, additional_header_length);
8449 }
8450
8451
8452 /**************************************************************************/
8453 /* */
8454 /* FUNCTION RELEASE */
8455 /* */
8456 /* _nx_http_server_callback_generate_response_header_extended */
8457 /* PORTABLE C */
8458 /* 6.1 */
8459 /* AUTHOR */
8460 /* */
8461 /* Yuxin Zhou, Microsoft Corporation */
8462 /* */
8463 /* DESCRIPTION */
8464 /* */
8465 /* This function is used in callback function to generate HTTP */
8466 /* response header. */
8467 /* */
8468 /* Note: The strings of status code, content type length and additional*/
8469 /* header length must be NULL-terminated and length of this string */
8470 /* matches the length specified in the argument list. */
8471 /* */
8472 /* INPUT */
8473 /* */
8474 /* server_ptr Pointer to HTTP server */
8475 /* packet_pptr Pointer to packet */
8476 /* status_code Status-code and reason-phrase */
8477 /* status_code_length Length of status-code */
8478 /* content_length Length of content */
8479 /* content_type Type of content */
8480 /* content_type_length Length of content type */
8481 /* additional_header Other HTTP headers */
8482 /* additional_header_length Length of other HTTP headers */
8483 /* */
8484 /* OUTPUT */
8485 /* */
8486 /* status Completion status */
8487 /* */
8488 /* CALLS */
8489 /* */
8490 /* _nx_http_server_generate_response_header */
8491 /* Internal responder header */
8492 /* generation function */
8493 /* _nx_utility_string_length_check Check string length */
8494 /* */
8495 /* CALLED BY */
8496 /* */
8497 /* Application Code */
8498 /* */
8499 /* RELEASE HISTORY */
8500 /* */
8501 /* DATE NAME DESCRIPTION */
8502 /* */
8503 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8504 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8505 /* resulting in version 6.1 */
8506 /* */
8507 /**************************************************************************/
_nx_http_server_callback_generate_response_header_extended(NX_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)8508 UINT _nx_http_server_callback_generate_response_header_extended(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, CHAR *status_code,
8509 UINT status_code_length, UINT content_length, CHAR *content_type,
8510 UINT content_type_length, CHAR* additional_header, UINT additional_header_length)
8511 {
8512
8513 UINT temp_status_code_length = 0;
8514 UINT temp_content_type_length = 0;
8515 UINT temp_add_header_length = 0;
8516
8517 /* Check status code, content type and additional header length. */
8518 if (_nx_utility_string_length_check(status_code, &temp_status_code_length, status_code_length) ||
8519 (content_type && _nx_utility_string_length_check(content_type, &temp_content_type_length, content_type_length)) ||
8520 (additional_header && _nx_utility_string_length_check(additional_header, &temp_add_header_length, additional_header_length)))
8521 {
8522 return(NX_HTTP_ERROR);
8523 }
8524
8525 /* Validate string length. */
8526 if ((status_code_length != temp_status_code_length) ||
8527 (content_type && content_type_length != temp_content_type_length) ||
8528 (additional_header && additional_header_length != temp_add_header_length))
8529 {
8530 return(NX_HTTP_ERROR);
8531 }
8532
8533 /* Call the internal HTTP response send function. */
8534 return _nx_http_server_generate_response_header(server_ptr, packet_pptr, status_code, status_code_length, content_length,
8535 content_type, content_type_length, additional_header, additional_header_length);
8536 }
8537
8538
8539 /**************************************************************************/
8540 /* */
8541 /* FUNCTION RELEASE */
8542 /* */
8543 /* _nxe_http_server_callback_packet_send PORTABLE C */
8544 /* 6.1 */
8545 /* AUTHOR */
8546 /* */
8547 /* Yuxin Zhou, Microsoft Corporation */
8548 /* */
8549 /* DESCRIPTION */
8550 /* */
8551 /* This function checks error for sending a packet. */
8552 /* */
8553 /* INPUT */
8554 /* */
8555 /* server_ptr Pointer to HTTP server */
8556 /* packet_ptr Pointer to packet */
8557 /* */
8558 /* OUTPUT */
8559 /* */
8560 /* status Completion status */
8561 /* */
8562 /* CALLS */
8563 /* */
8564 /* _nx_http_server_callback_packet_send */
8565 /* */
8566 /* CALLED BY */
8567 /* */
8568 /* Application Code */
8569 /* */
8570 /* RELEASE HISTORY */
8571 /* */
8572 /* DATE NAME DESCRIPTION */
8573 /* */
8574 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8575 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8576 /* resulting in version 6.1 */
8577 /* */
8578 /**************************************************************************/
_nxe_http_server_callback_packet_send(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)8579 UINT _nxe_http_server_callback_packet_send(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
8580 {
8581
8582 /* Check for invalid input pointers. */
8583 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (packet_ptr == NX_NULL))
8584 return(NX_PTR_ERROR);
8585
8586 return _nx_http_server_callback_packet_send(server_ptr, packet_ptr);
8587 }
8588
8589
8590 /**************************************************************************/
8591 /* */
8592 /* FUNCTION RELEASE */
8593 /* */
8594 /* _nx_http_server_callback_packet_send PORTABLE C */
8595 /* 6.1 */
8596 /* AUTHOR */
8597 /* */
8598 /* Yuxin Zhou, Microsoft Corporation */
8599 /* */
8600 /* DESCRIPTION */
8601 /* */
8602 /* This function is used in callback function to send a packet. */
8603 /* */
8604 /* INPUT */
8605 /* */
8606 /* server_ptr Pointer to HTTP server */
8607 /* packet_ptr Pointer to packet */
8608 /* */
8609 /* OUTPUT */
8610 /* */
8611 /* status Completion status */
8612 /* */
8613 /* CALLS */
8614 /* */
8615 /* nx_tcp_socket_send */
8616 /* */
8617 /* CALLED BY */
8618 /* */
8619 /* Application Code */
8620 /* */
8621 /* RELEASE HISTORY */
8622 /* */
8623 /* DATE NAME DESCRIPTION */
8624 /* */
8625 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8626 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8627 /* resulting in version 6.1 */
8628 /* */
8629 /**************************************************************************/
_nx_http_server_callback_packet_send(NX_HTTP_SERVER * server_ptr,NX_PACKET * packet_ptr)8630 UINT _nx_http_server_callback_packet_send(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr)
8631 {
8632
8633 /* Send internal. */
8634 return nx_tcp_socket_send(&(server_ptr -> nx_http_server_socket), packet_ptr, NX_HTTP_SERVER_TIMEOUT_SEND);
8635 }
8636
8637
8638 /**************************************************************************/
8639 /* */
8640 /* FUNCTION RELEASE */
8641 /* */
8642 /* _nxe_http_server_gmt_callback_set PORTABLE C */
8643 /* 6.1 */
8644 /* AUTHOR */
8645 /* */
8646 /* Yuxin Zhou, Microsoft Corporation */
8647 /* */
8648 /* DESCRIPTION */
8649 /* */
8650 /* This function checks error for setting gmt callback function. */
8651 /* */
8652 /* INPUT */
8653 /* */
8654 /* server_ptr Pointer to HTTP server */
8655 /* gmt_get Pointer to application's */
8656 /* GMT time function */
8657 /* */
8658 /* OUTPUT */
8659 /* */
8660 /* status Completion status */
8661 /* */
8662 /* CALLS */
8663 /* */
8664 /* _nx_http_server_gmt_callback_set */
8665 /* */
8666 /* CALLED BY */
8667 /* */
8668 /* Application Code */
8669 /* */
8670 /* RELEASE HISTORY */
8671 /* */
8672 /* DATE NAME DESCRIPTION */
8673 /* */
8674 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8675 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8676 /* resulting in version 6.1 */
8677 /* */
8678 /**************************************************************************/
_nxe_http_server_gmt_callback_set(NX_HTTP_SERVER * server_ptr,VOID (* gmt_get)(NX_HTTP_SERVER_DATE *))8679 UINT _nxe_http_server_gmt_callback_set(NX_HTTP_SERVER *server_ptr, VOID (*gmt_get)(NX_HTTP_SERVER_DATE *))
8680 {
8681
8682 /* Check for invalid input pointers. */
8683 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (gmt_get == NX_NULL))
8684 return(NX_PTR_ERROR);
8685
8686 /* Send internal. */
8687 return _nx_http_server_gmt_callback_set(server_ptr, gmt_get);
8688 }
8689
8690
8691 /**************************************************************************/
8692 /* */
8693 /* FUNCTION RELEASE */
8694 /* */
8695 /* _nx_http_server_gmt_callback_set PORTABLE C */
8696 /* 6.1 */
8697 /* AUTHOR */
8698 /* */
8699 /* Yuxin Zhou, Microsoft Corporation */
8700 /* */
8701 /* DESCRIPTION */
8702 /* */
8703 /* This function sets gmt callback function. */
8704 /* */
8705 /* INPUT */
8706 /* */
8707 /* server_ptr Pointer to HTTP server */
8708 /* gmt_get Pointer to application's */
8709 /* GMT time function */
8710 /* */
8711 /* OUTPUT */
8712 /* */
8713 /* status Completion status */
8714 /* */
8715 /* CALLS */
8716 /* */
8717 /* */
8718 /* CALLED BY */
8719 /* */
8720 /* Application Code */
8721 /* */
8722 /* RELEASE HISTORY */
8723 /* */
8724 /* DATE NAME DESCRIPTION */
8725 /* */
8726 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8727 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8728 /* resulting in version 6.1 */
8729 /* */
8730 /**************************************************************************/
_nx_http_server_gmt_callback_set(NX_HTTP_SERVER * server_ptr,VOID (* gmt_get)(NX_HTTP_SERVER_DATE *))8731 UINT _nx_http_server_gmt_callback_set(NX_HTTP_SERVER *server_ptr, VOID (*gmt_get)(NX_HTTP_SERVER_DATE *))
8732 {
8733
8734 TX_INTERRUPT_SAVE_AREA
8735
8736 /* Lockout interrupts. */
8737 TX_DISABLE
8738
8739 /* Set the function pointer. */
8740 server_ptr -> nx_http_server_gmt_get = gmt_get;
8741
8742 /* Restore interrupts. */
8743 TX_RESTORE
8744
8745 return NX_SUCCESS;
8746 }
8747
8748
8749 /**************************************************************************/
8750 /* */
8751 /* FUNCTION RELEASE */
8752 /* */
8753 /* _nxe_http_server_cache_info_callback_set PORTABLE C */
8754 /* 6.1 */
8755 /* AUTHOR */
8756 /* */
8757 /* Yuxin Zhou, Microsoft Corporation */
8758 /* */
8759 /* DESCRIPTION */
8760 /* */
8761 /* This function checks error for setting cache info callback function.*/
8762 /* */
8763 /* INPUT */
8764 /* */
8765 /* server_ptr Pointer to HTTP server */
8766 /* cache_info_get Pointer to application's */
8767 /* cache information function */
8768 /* */
8769 /* OUTPUT */
8770 /* */
8771 /* status Completion status */
8772 /* */
8773 /* CALLS */
8774 /* */
8775 /* _nx_http_server_cache_info_callback_set */
8776 /* */
8777 /* CALLED BY */
8778 /* */
8779 /* Application Code */
8780 /* */
8781 /* RELEASE HISTORY */
8782 /* */
8783 /* DATE NAME DESCRIPTION */
8784 /* */
8785 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8786 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8787 /* resulting in version 6.1 */
8788 /* */
8789 /**************************************************************************/
_nxe_http_server_cache_info_callback_set(NX_HTTP_SERVER * server_ptr,UINT (* cache_info_get)(CHAR *,UINT *,NX_HTTP_SERVER_DATE *))8790 UINT _nxe_http_server_cache_info_callback_set(NX_HTTP_SERVER *server_ptr, UINT (*cache_info_get)(CHAR *, UINT *, NX_HTTP_SERVER_DATE *))
8791 {
8792
8793 /* Check for invalid input pointers. */
8794 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (cache_info_get == NX_NULL))
8795 return(NX_PTR_ERROR);
8796
8797 /* Send internal. */
8798 return _nx_http_server_cache_info_callback_set(server_ptr, cache_info_get);
8799 }
8800
8801
8802 /**************************************************************************/
8803 /* */
8804 /* FUNCTION RELEASE */
8805 /* */
8806 /* _nx_http_server_cache_info_callback_set PORTABLE C */
8807 /* 6.1 */
8808 /* AUTHOR */
8809 /* */
8810 /* Yuxin Zhou, Microsoft Corporation */
8811 /* */
8812 /* DESCRIPTION */
8813 /* */
8814 /* This function sets cache info callback function. */
8815 /* */
8816 /* Note: The string length of resource in cache_info_get is limited by */
8817 /* NX_HTTP_MAX_RESOURCE. */
8818 /* */
8819 /* INPUT */
8820 /* */
8821 /* server_ptr Pointer to HTTP server */
8822 /* cache_info_get Pointer to application's */
8823 /* cache information function */
8824 /* */
8825 /* OUTPUT */
8826 /* */
8827 /* status Completion status */
8828 /* */
8829 /* CALLS */
8830 /* */
8831 /* */
8832 /* CALLED BY */
8833 /* */
8834 /* Application Code */
8835 /* */
8836 /* RELEASE HISTORY */
8837 /* */
8838 /* DATE NAME DESCRIPTION */
8839 /* */
8840 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8841 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8842 /* resulting in version 6.1 */
8843 /* */
8844 /**************************************************************************/
_nx_http_server_cache_info_callback_set(NX_HTTP_SERVER * server_ptr,UINT (* cache_info_get)(CHAR *,UINT *,NX_HTTP_SERVER_DATE *))8845 UINT _nx_http_server_cache_info_callback_set(NX_HTTP_SERVER *server_ptr, UINT (*cache_info_get)(CHAR *, UINT *, NX_HTTP_SERVER_DATE *))
8846 {
8847
8848 TX_INTERRUPT_SAVE_AREA
8849
8850 /* Lockout interrupts. */
8851 TX_DISABLE
8852
8853 /* Set the function pointer. */
8854 server_ptr -> nx_http_server_cache_info_get = cache_info_get;
8855
8856 /* Restore interrupts. */
8857 TX_RESTORE
8858
8859 return NX_SUCCESS;
8860 }
8861
8862
8863 /**************************************************************************/
8864 /* */
8865 /* FUNCTION RELEASE */
8866 /* */
8867 /* _nx_http_server_date_to_string PORTABLE C */
8868 /* 6.1 */
8869 /* AUTHOR */
8870 /* */
8871 /* Yuxin Zhou, Microsoft Corporation */
8872 /* */
8873 /* DESCRIPTION */
8874 /* */
8875 /* This function converts from date to string. */
8876 /* */
8877 /* INPUT */
8878 /* */
8879 /* date Pointer to HTTP date */
8880 /* string Pointer to output buffer */
8881 /* */
8882 /* OUTPUT */
8883 /* */
8884 /* status Completion status */
8885 /* */
8886 /* CALLS */
8887 /* */
8888 /* _nx_http_server_date_convert */
8889 /* */
8890 /* CALLED BY */
8891 /* */
8892 /* _nx_http_server_get_process */
8893 /* _nx_http_server_generate_response_header */
8894 /* */
8895 /* RELEASE HISTORY */
8896 /* */
8897 /* DATE NAME DESCRIPTION */
8898 /* */
8899 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8900 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8901 /* resulting in version 6.1 */
8902 /* */
8903 /**************************************************************************/
_nx_http_server_date_to_string(NX_HTTP_SERVER_DATE * date,CHAR * string)8904 UINT _nx_http_server_date_to_string(NX_HTTP_SERVER_DATE *date, CHAR *string)
8905 {
8906
8907 UINT index = 0;
8908
8909 /* RDC1122-date. */
8910 /* Append weekday. */
8911 string[index++] = *(_nx_http_server_weekday[date -> nx_http_server_weekday]);
8912 string[index++] = *(_nx_http_server_weekday[date -> nx_http_server_weekday] + 1);
8913 string[index++] = *(_nx_http_server_weekday[date -> nx_http_server_weekday] + 2);
8914 string[index++] = ',';
8915 string[index++] = ' ';
8916
8917 /* Convert and append day. */
8918 _nx_http_server_date_convert(date -> nx_http_server_day, 2, &string[index]);
8919 index += 2;
8920 string[index++] = ' ';
8921
8922 /* Append month. */
8923 string[index++] = *(_nx_http_server_month[date -> nx_http_server_month]);
8924 string[index++] = *(_nx_http_server_month[date -> nx_http_server_month] + 1);
8925 string[index++] = *(_nx_http_server_month[date -> nx_http_server_month] + 2);
8926 string[index++] = ' ';
8927
8928 /* Convert and append year. */
8929 _nx_http_server_date_convert(date -> nx_http_server_year, 4, &string[index]);
8930 index += 4;
8931 string[index++] = ' ';
8932
8933 /* Convert and append hour. */
8934 _nx_http_server_date_convert(date -> nx_http_server_hour, 2, &string[index]);
8935 index += 2;
8936 string[index++] = ':';
8937
8938 /* Convert and append minute. */
8939 _nx_http_server_date_convert(date -> nx_http_server_minute, 2, &string[index]);
8940 index += 2;
8941 string[index++] = ':';
8942
8943 /* Convert and append second. */
8944 _nx_http_server_date_convert(date -> nx_http_server_second, 2, &string[index]);
8945 index += 2;
8946 string[index++] = ' ';
8947 string[index++] = 'G';
8948 string[index++] = 'M';
8949 string[index++] = 'T';
8950
8951 return index;
8952 }
8953
8954
8955 /**************************************************************************/
8956 /* */
8957 /* FUNCTION RELEASE */
8958 /* */
8959 /* _nx_http_server_date_convert PORTABLE C */
8960 /* 6.1 */
8961 /* AUTHOR */
8962 /* */
8963 /* Yuxin Zhou, Microsoft Corporation */
8964 /* */
8965 /* DESCRIPTION */
8966 /* */
8967 /* This function converts a date from number to string. */
8968 /* */
8969 /* INPUT */
8970 /* */
8971 /* date The number to convert */
8972 /* count Digital count for string */
8973 /* string Pointer to output buffer */
8974 /* */
8975 /* OUTPUT */
8976 /* */
8977 /* None */
8978 /* */
8979 /* CALLS */
8980 /* */
8981 /* */
8982 /* CALLED BY */
8983 /* */
8984 /* _nx_http_server_date_to_string */
8985 /* */
8986 /* RELEASE HISTORY */
8987 /* */
8988 /* DATE NAME DESCRIPTION */
8989 /* */
8990 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8991 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8992 /* resulting in version 6.1 */
8993 /* */
8994 /**************************************************************************/
_nx_http_server_date_convert(UINT date,UINT count,CHAR * string)8995 VOID _nx_http_server_date_convert(UINT date, UINT count, CHAR *string)
8996 {
8997
8998 UINT digit;
8999
9000 /* Initialize all 4 bytes to digit 0. */
9001 *((ULONG*)string) = 0x30303030;
9002 string[count] = 0;
9003
9004 /* Loop to convert the number to ASCII. */
9005 while(count > 0)
9006 {
9007 count--;
9008
9009 /* Compute the next decimal digit. */
9010 digit = date % 10;
9011
9012 /* Update the input date. */
9013 date = date / 10;
9014
9015 /* Store the new digit in ASCII form. */
9016 string[count] = (CHAR) (digit + 0x30);
9017 }
9018 }
9019
9020
9021 /**************************************************************************/
9022 /* */
9023 /* FUNCTION RELEASE */
9024 /* */
9025 /* _nxe_http_server_mime_maps_additional_set PORTABLE C */
9026 /* 6.1 */
9027 /* AUTHOR */
9028 /* */
9029 /* Yuxin Zhou, Microsoft Corporation */
9030 /* */
9031 /* DESCRIPTION */
9032 /* */
9033 /* This function checks error for setting additional MIME maps. */
9034 /* */
9035 /* INPUT */
9036 /* */
9037 /* server_ptr Pointer to HTTP server */
9038 /* mime_maps Pointer MIME map array */
9039 /* mime_maps_num Number of MIME map array */
9040 /* */
9041 /* OUTPUT */
9042 /* */
9043 /* status Completion status */
9044 /* */
9045 /* CALLS */
9046 /* */
9047 /* _nx_http_server_mime_maps_additional_set */
9048 /* */
9049 /* CALLED BY */
9050 /* */
9051 /* Application Code */
9052 /* */
9053 /* RELEASE HISTORY */
9054 /* */
9055 /* DATE NAME DESCRIPTION */
9056 /* */
9057 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9058 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9059 /* resulting in version 6.1 */
9060 /* */
9061 /**************************************************************************/
_nxe_http_server_mime_maps_additional_set(NX_HTTP_SERVER * server_ptr,NX_HTTP_SERVER_MIME_MAP * mime_maps,UINT mime_maps_num)9062 UINT _nxe_http_server_mime_maps_additional_set(NX_HTTP_SERVER *server_ptr, NX_HTTP_SERVER_MIME_MAP *mime_maps, UINT mime_maps_num)
9063 {
9064
9065 /* Check for invalid input pointers. */
9066 if ((server_ptr == NX_NULL) || (server_ptr -> nx_http_server_id != NXD_HTTP_SERVER_ID) || (mime_maps == NX_NULL))
9067 return(NX_PTR_ERROR);
9068
9069 /* Send internal. */
9070 return _nx_http_server_mime_maps_additional_set(server_ptr, mime_maps, mime_maps_num);
9071 }
9072
9073
9074 /**************************************************************************/
9075 /* */
9076 /* FUNCTION RELEASE */
9077 /* */
9078 /* _nx_http_server_mime_maps_additional_set PORTABLE C */
9079 /* 6.1 */
9080 /* AUTHOR */
9081 /* */
9082 /* Yuxin Zhou, Microsoft Corporation */
9083 /* */
9084 /* DESCRIPTION */
9085 /* */
9086 /* This function sets additional MIME maps. */
9087 /* */
9088 /* INPUT */
9089 /* */
9090 /* server_ptr Pointer to HTTP server */
9091 /* mime_maps Pointer MIME map array */
9092 /* mime_maps_num Number of MIME map array */
9093 /* */
9094 /* OUTPUT */
9095 /* */
9096 /* status Completion status */
9097 /* */
9098 /* CALLS */
9099 /* */
9100 /* */
9101 /* CALLED BY */
9102 /* */
9103 /* Application Code */
9104 /* */
9105 /* RELEASE HISTORY */
9106 /* */
9107 /* DATE NAME DESCRIPTION */
9108 /* */
9109 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9110 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9111 /* resulting in version 6.1 */
9112 /* */
9113 /**************************************************************************/
_nx_http_server_mime_maps_additional_set(NX_HTTP_SERVER * server_ptr,NX_HTTP_SERVER_MIME_MAP * mime_maps,UINT mime_maps_num)9114 UINT _nx_http_server_mime_maps_additional_set(NX_HTTP_SERVER *server_ptr, NX_HTTP_SERVER_MIME_MAP *mime_maps, UINT mime_maps_num)
9115 {
9116
9117 TX_INTERRUPT_SAVE_AREA
9118
9119 /* Lockout interrupts. */
9120 TX_DISABLE
9121
9122 /* Set the mime maps. */
9123 server_ptr -> nx_http_server_mime_maps_additional = mime_maps;
9124 server_ptr -> nx_http_server_mime_maps_additional_num = mime_maps_num;
9125
9126 /* Restore interrupts. */
9127 TX_RESTORE
9128
9129 return NX_SUCCESS;
9130 }
9131
9132
9133 /**************************************************************************/
9134 /* */
9135 /* FUNCTION RELEASE */
9136 /* */
9137 /* _nxe_http_server_digest_authenticate_notify_set PORTABLE C */
9138 /* 6.1 */
9139 /* AUTHOR */
9140 /* */
9141 /* Yuxin Zhou, Microsoft Corporation */
9142 /* */
9143 /* DESCRIPTION */
9144 /* */
9145 /* This function performs error checking for service to set digest */
9146 /* authenticate callback function. */
9147 /* */
9148 /* INPUT */
9149 /* */
9150 /* http_server_ptr Pointer to HTTP server */
9151 /* digest_authenticate_callback Pointer to application's */
9152 /* digest authenticate callback */
9153 /* function */
9154 /* */
9155 /* OUTPUT */
9156 /* */
9157 /* status Completion status */
9158 /* */
9159 /* CALLS */
9160 /* */
9161 /* _nx_http_server_digest_authenticate_notify_set */
9162 /* */
9163 /* CALLED BY */
9164 /* */
9165 /* Application Code */
9166 /* */
9167 /* RELEASE HISTORY */
9168 /* */
9169 /* DATE NAME DESCRIPTION */
9170 /* */
9171 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9172 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9173 /* resulting in version 6.1 */
9174 /* */
9175 /**************************************************************************/
_nxe_http_server_digest_authenticate_notify_set(NX_HTTP_SERVER * http_server_ptr,UINT (* digest_authenticate_callback)(NX_HTTP_SERVER * server_ptr,CHAR * name_ptr,CHAR * realm_ptr,CHAR * password_ptr,CHAR * method,CHAR * authorization_uri,CHAR * authorization_nc,CHAR * authorization_cnonce))9176 UINT _nxe_http_server_digest_authenticate_notify_set(NX_HTTP_SERVER *http_server_ptr,
9177 UINT (*digest_authenticate_callback)(NX_HTTP_SERVER *server_ptr, CHAR *name_ptr,
9178 CHAR *realm_ptr, CHAR *password_ptr, CHAR *method,
9179 CHAR *authorization_uri, CHAR *authorization_nc,
9180 CHAR *authorization_cnonce))
9181 {
9182
9183 /* Check for invalid input pointers. */
9184 if ((http_server_ptr == NX_NULL) || (digest_authenticate_callback == NX_NULL))
9185 {
9186 return(NX_PTR_ERROR);
9187 }
9188
9189 return(_nx_http_server_digest_authenticate_notify_set(http_server_ptr, digest_authenticate_callback));
9190 }
9191
9192
9193 /**************************************************************************/
9194 /* */
9195 /* FUNCTION RELEASE */
9196 /* */
9197 /* _nx_http_server_digest_authenticate_notify_set PORTABLE C */
9198 /* 6.1 */
9199 /* AUTHOR */
9200 /* */
9201 /* Yuxin Zhou, Microsoft Corporation */
9202 /* */
9203 /* DESCRIPTION */
9204 /* */
9205 /* This function sets digest authenticate callback function. */
9206 /* */
9207 /* Note: The string length of realm_ptr, name_ptr, and password_ptr in */
9208 /* digest_authenticate_callback is checked internally. The method, */
9209 /* authorization_uri, authorization_nc and authorization_cnonce in */
9210 /* digest_authenticate_callback are built internally. */
9211 /* */
9212 /* INPUT */
9213 /* */
9214 /* http_server_ptr Pointer to HTTP server */
9215 /* digest_authenticate_callback Pointer to application's */
9216 /* digest authenticate callback */
9217 /* function */
9218 /* */
9219 /* OUTPUT */
9220 /* */
9221 /* status Completion status */
9222 /* */
9223 /* CALLS */
9224 /* */
9225 /* */
9226 /* CALLED BY */
9227 /* */
9228 /* Application Code */
9229 /* */
9230 /* RELEASE HISTORY */
9231 /* */
9232 /* DATE NAME DESCRIPTION */
9233 /* */
9234 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9235 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9236 /* resulting in version 6.1 */
9237 /* */
9238 /**************************************************************************/
_nx_http_server_digest_authenticate_notify_set(NX_HTTP_SERVER * http_server_ptr,UINT (* digest_authenticate_callback)(NX_HTTP_SERVER * server_ptr,CHAR * name_ptr,CHAR * realm_ptr,CHAR * password_ptr,CHAR * method,CHAR * authorization_uri,CHAR * authorization_nc,CHAR * authorization_cnonce))9239 UINT _nx_http_server_digest_authenticate_notify_set(NX_HTTP_SERVER *http_server_ptr,
9240 UINT (*digest_authenticate_callback)(NX_HTTP_SERVER *server_ptr, CHAR *name_ptr,
9241 CHAR *realm_ptr, CHAR *password_ptr, CHAR *method,
9242 CHAR *authorization_uri, CHAR *authorization_nc,
9243 CHAR *authorization_cnonce))
9244 {
9245
9246 #ifdef NX_HTTP_DIGEST_ENABLE
9247 http_server_ptr -> nx_http_server_digest_authenticate_callback = digest_authenticate_callback;
9248
9249 return(NX_SUCCESS);
9250 #else
9251 NX_PARAMETER_NOT_USED(http_server_ptr);
9252 NX_PARAMETER_NOT_USED(digest_authenticate_callback);
9253
9254 return(NX_NOT_SUPPORTED);
9255 #endif
9256 }
9257
9258
9259 /**************************************************************************/
9260 /* */
9261 /* FUNCTION RELEASE */
9262 /* */
9263 /* _nxe_http_server_authentication_check_set PORTABLE C */
9264 /* 6.1 */
9265 /* AUTHOR */
9266 /* */
9267 /* Yuxin Zhou, Microsoft Corporation */
9268 /* */
9269 /* DESCRIPTION */
9270 /* */
9271 /* This function checks errors for setting authentication checking */
9272 /* callback function. */
9273 /* */
9274 /* */
9275 /* INPUT */
9276 /* */
9277 /* http_server_ptr Pointer to HTTP server */
9278 /* authentication_check_extended Pointer to application's */
9279 /* authentication checking */
9280 /* */
9281 /* OUTPUT */
9282 /* */
9283 /* status Completion status */
9284 /* */
9285 /* CALLS */
9286 /* */
9287 /* _nx_http_server_authentication_check_set */
9288 /* */
9289 /* CALLED BY */
9290 /* */
9291 /* Application Code */
9292 /* */
9293 /* RELEASE HISTORY */
9294 /* */
9295 /* DATE NAME DESCRIPTION */
9296 /* */
9297 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9298 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9299 /* resulting in version 6.1 */
9300 /* */
9301 /**************************************************************************/
_nxe_http_server_authentication_check_set(NX_HTTP_SERVER * http_server_ptr,UINT (* authentication_check_extended)(NX_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,UINT * name_length,CHAR ** password,UINT * password_length,CHAR ** realm,UINT * realm_length))9302 UINT _nxe_http_server_authentication_check_set(NX_HTTP_SERVER *http_server_ptr,
9303 UINT (*authentication_check_extended)(NX_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, UINT *name_length, CHAR **password, UINT *password_length, CHAR **realm, UINT *realm_length))
9304 {
9305 UINT status;
9306
9307 /* Check for invalid input pointers. */
9308 if ((http_server_ptr == NX_NULL) || (authentication_check_extended == NX_NULL))
9309 {
9310 return(NX_PTR_ERROR);
9311 }
9312
9313 /* Check for appropriate caller. */
9314 NX_THREADS_ONLY_CALLER_CHECKING
9315
9316 /* Call the actual authentication checking set function. */
9317 status= _nx_http_server_authentication_check_set(http_server_ptr, authentication_check_extended);
9318
9319 /* Return staus. */
9320 return(status);
9321 }
9322
9323
9324 /**************************************************************************/
9325 /* */
9326 /* FUNCTION RELEASE */
9327 /* */
9328 /* _nx_http_server_authentication_check_set PORTABLE C */
9329 /* 6.1 */
9330 /* AUTHOR */
9331 /* */
9332 /* Yuxin Zhou, Microsoft Corporation */
9333 /* */
9334 /* DESCRIPTION */
9335 /* */
9336 /* This function sets the callback function of authentication checking.*/
9337 /* */
9338 /* Note: The strings of name, password and realm must be */
9339 /* NULL-terminated and length of each string matches the length */
9340 /* specified in the argument list. */
9341 /* */
9342 /* */
9343 /* INPUT */
9344 /* */
9345 /* http_server_ptr Pointer to HTTP server */
9346 /* authentication_check_extended Pointer to application's */
9347 /* authentication checking */
9348 /* */
9349 /* OUTPUT */
9350 /* */
9351 /* status Completion status */
9352 /* */
9353 /* CALLS */
9354 /* */
9355 /* None */
9356 /* */
9357 /* CALLED BY */
9358 /* */
9359 /* Application Code */
9360 /* */
9361 /* RELEASE HISTORY */
9362 /* */
9363 /* DATE NAME DESCRIPTION */
9364 /* */
9365 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9366 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9367 /* resulting in version 6.1 */
9368 /* */
9369 /**************************************************************************/
_nx_http_server_authentication_check_set(NX_HTTP_SERVER * http_server_ptr,UINT (* authentication_check_extended)(NX_HTTP_SERVER * server_ptr,UINT request_type,CHAR * resource,CHAR ** name,UINT * name_length,CHAR ** password,UINT * password_length,CHAR ** realm,UINT * realm_length))9370 UINT _nx_http_server_authentication_check_set(NX_HTTP_SERVER *http_server_ptr,
9371 UINT (*authentication_check_extended)(NX_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, CHAR **name, UINT *name_length, CHAR **password, UINT *password_length, CHAR **realm, UINT *realm_length))
9372 {
9373
9374 /* Set the extended authentication checking function. */
9375 http_server_ptr -> nx_http_server_authentication_check_extended = authentication_check_extended;
9376
9377 /* Return success. */
9378 return(NX_SUCCESS);
9379 }
9380
9381