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