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