1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Hypertext Transfer Protocol (HTTP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_HTTP_SOURCE_CODE
23
24
25 /* Force error checking to be disabled in this module */
26
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif
30
31 /* Include necessary system files. */
32
33
34 #include "nx_api.h"
35 #include "nx_ip.h"
36 #include "nx_tcp.h"
37 #include "nxd_http_client.h"
38 #include "stdio.h"
39 #include "string.h"
40
41
42 /* Define global HTTP variables and strings. */
43
44 /* Bring in externs for caller checking code. */
45
46 NX_CALLER_CHECKING_EXTERNS
47
48
49 /**************************************************************************/
50 /* */
51 /* FUNCTION RELEASE */
52 /* */
53 /* _nxe_http_client_create PORTABLE C */
54 /* 6.1 */
55 /* AUTHOR */
56 /* */
57 /* Yuxin Zhou, Microsoft Corporation */
58 /* */
59 /* DESCRIPTION */
60 /* */
61 /* This function checks for errors in the HTTP client create call. */
62 /* */
63 /* */
64 /* INPUT */
65 /* */
66 /* client_ptr Pointer to HTTP client */
67 /* client_name Name of HTTP client */
68 /* ip_ptr Pointer to IP instance */
69 /* pool_ptr Pointer to packet pool */
70 /* window_size Size of HTTP client rx window */
71 /* http_client_size Size of HTTP client */
72 /* */
73 /* OUTPUT */
74 /* */
75 /* status Completion status */
76 /* */
77 /* CALLS */
78 /* */
79 /* _nx_http_client_create Actual client create call */
80 /* */
81 /* CALLED BY */
82 /* */
83 /* Application Code */
84 /* */
85 /* RELEASE HISTORY */
86 /* */
87 /* DATE NAME DESCRIPTION */
88 /* */
89 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
90 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
91 /* resulting in version 6.1 */
92 /* */
93 /**************************************************************************/
_nxe_http_client_create(NX_HTTP_CLIENT * client_ptr,CHAR * client_name,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,ULONG window_size,UINT http_client_size)94 UINT _nxe_http_client_create(NX_HTTP_CLIENT *client_ptr, CHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, ULONG window_size, UINT http_client_size)
95 {
96
97 NX_PACKET *packet_ptr;
98 UINT status;
99
100
101 /* Check for invalid input pointers. */
102 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
103 (client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id == NXD_HTTP_CLIENT_ID) ||
104 (pool_ptr == NX_NULL) || (http_client_size != sizeof(NX_HTTP_CLIENT)))
105 return(NX_PTR_ERROR);
106
107 /* Pickup a packet from the supplied packet pool. */
108 packet_ptr = pool_ptr -> nx_packet_pool_available_list;
109
110 /* Determine if the packet payload is equal to or greater than the maximum HTTP header supported. */
111 if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start) < NX_HTTP_CLIENT_MIN_PACKET_SIZE)
112 return(NX_HTTP_POOL_ERROR);
113
114 /* Call actual client create function. */
115 status = _nx_http_client_create(client_ptr, client_name, ip_ptr, pool_ptr, window_size);
116
117 /* Return completion status. */
118 return(status);
119 }
120
121
122 /**************************************************************************/
123 /* */
124 /* FUNCTION RELEASE */
125 /* */
126 /* _nx_http_client_create PORTABLE C */
127 /* 6.1 */
128 /* AUTHOR */
129 /* */
130 /* Yuxin Zhou, Microsoft Corporation */
131 /* */
132 /* DESCRIPTION */
133 /* */
134 /* This function creates a HTTP client on the specified IP. In doing */
135 /* so this function creates an TCP socket for subsequent HTTP */
136 /* transfers. */
137 /* */
138 /* */
139 /* INPUT */
140 /* */
141 /* client_ptr Pointer to HTTP client */
142 /* client_name Name of HTTP client */
143 /* ip_ptr Pointer to IP instance */
144 /* pool_ptr Pointer to packet pool */
145 /* window_size Size of HTTP client rx window */
146 /* */
147 /* OUTPUT */
148 /* */
149 /* status Completion status */
150 /* */
151 /* CALLS */
152 /* */
153 /* nx_tcp_socket_create Create HTTP client socket */
154 /* */
155 /* CALLED BY */
156 /* */
157 /* Application Code */
158 /* */
159 /* RELEASE HISTORY */
160 /* */
161 /* DATE NAME DESCRIPTION */
162 /* */
163 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
164 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
165 /* resulting in version 6.1 */
166 /* */
167 /**************************************************************************/
_nx_http_client_create(NX_HTTP_CLIENT * client_ptr,CHAR * client_name,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,ULONG window_size)168 UINT _nx_http_client_create(NX_HTTP_CLIENT *client_ptr, CHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, ULONG window_size)
169 {
170
171 UINT status;
172
173
174 /* Clear the HTTP Client structure. */
175 memset((void *) client_ptr, 0, sizeof(NX_HTTP_CLIENT));
176
177 /* Create the Client's TCP socket. */
178 status = nx_tcp_socket_create(ip_ptr, &(client_ptr -> nx_http_client_socket), client_name,
179 NX_HTTP_TYPE_OF_SERVICE, NX_HTTP_FRAGMENT_OPTION, NX_HTTP_TIME_TO_LIVE,
180 window_size, NX_NULL, NX_NULL);
181
182 /* Determine if an error occurred. */
183 if (status != NX_SUCCESS)
184 {
185
186 /* Yes, return error code. */
187 return(status);
188 }
189
190 /* Save the Client name. */
191 client_ptr -> nx_http_client_name = client_name;
192
193 /* Save the IP pointer address. */
194 client_ptr -> nx_http_client_ip_ptr = ip_ptr;
195
196 /* Save the packet pool pointer. */
197 client_ptr -> nx_http_client_packet_pool_ptr = pool_ptr;
198
199 /* Set the client state to ready to indicate a get or put operation can be done. */
200 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
201
202 /* Set the Client ID to indicate the HTTP client thread is ready. */
203 client_ptr -> nx_http_client_id = NXD_HTTP_CLIENT_ID;
204
205 /* Set the default port the client connects to the HTTP server on (80). */
206 client_ptr -> nx_http_client_connect_port = NX_HTTP_SERVER_PORT;
207
208
209 /* Return successful completion. */
210 return(NX_SUCCESS);
211 }
212
213
214 /**************************************************************************/
215 /* */
216 /* FUNCTION RELEASE */
217 /* */
218 /* _nxe_http_client_delete PORTABLE C */
219 /* 6.1 */
220 /* AUTHOR */
221 /* */
222 /* Yuxin Zhou, Microsoft Corporation */
223 /* */
224 /* DESCRIPTION */
225 /* */
226 /* This function checks for errors in the HTTP client delete call. */
227 /* */
228 /* */
229 /* INPUT */
230 /* */
231 /* client_ptr Pointer to HTTP client */
232 /* */
233 /* OUTPUT */
234 /* */
235 /* status Completion status */
236 /* */
237 /* CALLS */
238 /* */
239 /* _nx_http_client_delete Actual client delete call */
240 /* */
241 /* CALLED BY */
242 /* */
243 /* Application Code */
244 /* */
245 /* RELEASE HISTORY */
246 /* */
247 /* DATE NAME DESCRIPTION */
248 /* */
249 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
250 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
251 /* resulting in version 6.1 */
252 /* */
253 /**************************************************************************/
_nxe_http_client_delete(NX_HTTP_CLIENT * client_ptr)254 UINT _nxe_http_client_delete(NX_HTTP_CLIENT *client_ptr)
255 {
256
257 UINT status;
258
259
260 /* Check for invalid input pointers. */
261 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID))
262 return(NX_PTR_ERROR);
263
264 /* Check for appropriate caller. */
265 NX_THREADS_ONLY_CALLER_CHECKING
266
267 /* Call actual client delete function. */
268 status = _nx_http_client_delete(client_ptr);
269
270 /* Return completion status. */
271 return(status);
272 }
273
274
275 /**************************************************************************/
276 /* */
277 /* FUNCTION RELEASE */
278 /* */
279 /* _nx_http_client_delete PORTABLE C */
280 /* 6.1 */
281 /* AUTHOR */
282 /* */
283 /* Yuxin Zhou, Microsoft Corporation */
284 /* */
285 /* DESCRIPTION */
286 /* */
287 /* This function deletes a previously created HTTP client on the */
288 /* specified IP. */
289 /* */
290 /* */
291 /* INPUT */
292 /* */
293 /* client_ptr Pointer to HTTP client */
294 /* */
295 /* OUTPUT */
296 /* */
297 /* status Completion status */
298 /* */
299 /* CALLS */
300 /* */
301 /* nx_tcp_socket_delete Delete the HTTP client socket */
302 /* */
303 /* CALLED BY */
304 /* */
305 /* Application Code */
306 /* */
307 /* RELEASE HISTORY */
308 /* */
309 /* DATE NAME DESCRIPTION */
310 /* */
311 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
312 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
313 /* resulting in version 6.1 */
314 /* */
315 /**************************************************************************/
_nx_http_client_delete(NX_HTTP_CLIENT * client_ptr)316 UINT _nx_http_client_delete(NX_HTTP_CLIENT *client_ptr)
317 {
318
319 /* Clear the client ID to indicate the HTTP client is no longer ready. */
320 client_ptr -> nx_http_client_id = 0;
321
322 /* Determine if a GET or PUT state is present. */
323 if ((client_ptr -> nx_http_client_state == NX_HTTP_CLIENT_STATE_PUT) ||
324 (client_ptr -> nx_http_client_state == NX_HTTP_CLIENT_STATE_GET))
325 {
326
327 /* Check for a saved packet. */
328 if (client_ptr -> nx_http_client_first_packet)
329 {
330
331 /* Release the packet. */
332 nx_packet_release(client_ptr -> nx_http_client_first_packet);
333 }
334
335 /* Disconnect and unbind the socket. */
336 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), NX_HTTP_CLIENT_TIMEOUT);
337 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
338 }
339
340 /* Delete the TCP socket. */
341 nx_tcp_socket_delete(&(client_ptr -> nx_http_client_socket));
342
343 /* Return successful completion. */
344 return(NX_SUCCESS);
345 }
346
347 /**************************************************************************/
348 /* */
349 /* FUNCTION RELEASE */
350 /* */
351 /* _nxe_http_client_set_connect_port PORTABLE C */
352 /* 6.1 */
353 /* AUTHOR */
354 /* */
355 /* Yuxin Zhou, Microsoft Corporation */
356 /* */
357 /* DESCRIPTION */
358 /* */
359 /* This function checks for errors in the HTTP client set connect port */
360 /* call. */
361 /* */
362 /* */
363 /* INPUT */
364 /* */
365 /* client_ptr Pointer to HTTP client */
366 /* port Port to connect to server on */
367 /* */
368 /* OUTPUT */
369 /* */
370 /* status Completion status */
371 /* */
372 /* CALLS */
373 /* */
374 /* _nx_http_client_set_connect_port Actual set port call */
375 /* */
376 /* CALLED BY */
377 /* */
378 /* Application Code */
379 /* */
380 /* RELEASE HISTORY */
381 /* */
382 /* DATE NAME DESCRIPTION */
383 /* */
384 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
385 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
386 /* resulting in version 6.1 */
387 /* */
388 /**************************************************************************/
_nxe_http_client_set_connect_port(NX_HTTP_CLIENT * client_ptr,UINT port)389 UINT _nxe_http_client_set_connect_port(NX_HTTP_CLIENT *client_ptr, UINT port)
390 {
391 UINT status;
392
393
394 /* Check for invalid input pointers. */
395 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID))
396 return(NX_PTR_ERROR);
397
398 /* Check for an invalid port. */
399 if (((ULONG)port) > (ULONG)NX_MAX_PORT)
400 {
401 return(NX_INVALID_PORT);
402 }
403 else if (port == 0)
404 {
405 return(NX_INVALID_PORT);
406 }
407
408 status = _nx_http_client_set_connect_port(client_ptr, port);
409
410 return(status);
411 }
412
413 /**************************************************************************/
414 /* */
415 /* FUNCTION RELEASE */
416 /* */
417 /* _nx_http_client_set_connect_port PORTABLE C */
418 /* 6.1 */
419 /* AUTHOR */
420 /* */
421 /* Yuxin Zhou, Microsoft Corporation */
422 /* */
423 /* DESCRIPTION */
424 /* */
425 /* This function sets the HTTP Client port to connect to the server on.*/
426 /* This is useful if the HTTP Client needs to connect to a server on */
427 /* another port than the default 80 port. */
428 /* */
429 /* INPUT */
430 /* */
431 /* client_ptr Pointer to HTTP client */
432 /* port Port to connect to server on */
433 /* */
434 /* OUTPUT */
435 /* */
436 /* NX_SUCCESS Completion status */
437 /* */
438 /* CALLS */
439 /* */
440 /* None */
441 /* */
442 /* CALLED BY */
443 /* */
444 /* Application Code */
445 /* */
446 /* RELEASE HISTORY */
447 /* */
448 /* DATE NAME DESCRIPTION */
449 /* */
450 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
451 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
452 /* resulting in version 6.1 */
453 /* */
454 /**************************************************************************/
_nx_http_client_set_connect_port(NX_HTTP_CLIENT * client_ptr,UINT port)455 UINT _nx_http_client_set_connect_port(NX_HTTP_CLIENT *client_ptr, UINT port)
456 {
457
458 client_ptr-> nx_http_client_connect_port = port;
459
460 return(NX_SUCCESS);
461 }
462
463
464 /**************************************************************************/
465 /* */
466 /* FUNCTION RELEASE */
467 /* */
468 /* _nxe_http_client_get_start PORTABLE C */
469 /* 6.1 */
470 /* AUTHOR */
471 /* */
472 /* Yuxin Zhou, Microsoft Corporation */
473 /* */
474 /* DESCRIPTION */
475 /* */
476 /* This function checks for errors in the HTTP client get start call. */
477 /* */
478 /* */
479 /* INPUT */
480 /* */
481 /* client_ptr Pointer to HTTP client */
482 /* ip_address IP address of HTTP Server */
483 /* resource Pointer to resource (URL) */
484 /* input_ptr Additional input pointer */
485 /* input_size Additional input size */
486 /* username Pointer to username */
487 /* password Pointer to password */
488 /* wait_option Suspension option */
489 /* */
490 /* OUTPUT */
491 /* */
492 /* status Completion status */
493 /* */
494 /* CALLS */
495 /* */
496 /* _nx_http_client_get_start Actual client get start call */
497 /* */
498 /* CALLED BY */
499 /* */
500 /* Application Code */
501 /* */
502 /* RELEASE HISTORY */
503 /* */
504 /* DATE NAME DESCRIPTION */
505 /* */
506 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
507 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
508 /* resulting in version 6.1 */
509 /* */
510 /**************************************************************************/
_nxe_http_client_get_start(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,CHAR * input_ptr,UINT input_size,CHAR * username,CHAR * password,ULONG wait_option)511 UINT _nxe_http_client_get_start(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource, CHAR *input_ptr,
512 UINT input_size, CHAR *username, CHAR *password, ULONG wait_option)
513 {
514
515 #ifndef NX_DISABLE_IPV4
516 UINT status;
517
518
519 /* Check for invalid input pointers. */
520 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) || (resource == NX_NULL))
521 return(NX_PTR_ERROR);
522
523 /* Check for appropriate caller. */
524 NX_THREADS_ONLY_CALLER_CHECKING
525
526 /* Call actual GET start routine. */
527 status = _nx_http_client_get_start(client_ptr, ip_address, resource, input_ptr, input_size,
528 username, password, wait_option);
529
530 /* Return completion status. */
531 return(status);
532 #else
533 NX_PARAMETER_NOT_USED(client_ptr);
534 NX_PARAMETER_NOT_USED(ip_address);
535 NX_PARAMETER_NOT_USED(resource);
536 NX_PARAMETER_NOT_USED(input_ptr);
537 NX_PARAMETER_NOT_USED(input_size);
538 NX_PARAMETER_NOT_USED(username);
539 NX_PARAMETER_NOT_USED(password);
540 NX_PARAMETER_NOT_USED(wait_option);
541
542 return(NX_NOT_SUPPORTED);
543 #endif /* NX_DISABLE_IPV4 */
544 }
545
546 /**************************************************************************/
547 /* */
548 /* FUNCTION RELEASE */
549 /* */
550 /* _nxe_http_client_get_start_extended PORTABLE C */
551 /* 6.1 */
552 /* AUTHOR */
553 /* */
554 /* Yuxin Zhou, Microsoft Corporation */
555 /* */
556 /* DESCRIPTION */
557 /* */
558 /* This function checks for errors in the HTTP client get start call. */
559 /* */
560 /* */
561 /* INPUT */
562 /* */
563 /* client_ptr Pointer to HTTP client */
564 /* ip_address IP address of HTTP Server */
565 /* resource Pointer to resource (URL) */
566 /* resource_length Length of resource (URL) */
567 /* input_ptr Additional input pointer */
568 /* input_size Additional input size */
569 /* username Pointer to username */
570 /* username_length Length of username */
571 /* password Pointer to password */
572 /* password_length Length of password */
573 /* wait_option Suspension option */
574 /* */
575 /* OUTPUT */
576 /* */
577 /* status Completion status */
578 /* */
579 /* CALLS */
580 /* */
581 /* _nx_http_client_get_start_extended Actual client get start call */
582 /* */
583 /* CALLED BY */
584 /* */
585 /* Application Code */
586 /* */
587 /* RELEASE HISTORY */
588 /* */
589 /* DATE NAME DESCRIPTION */
590 /* */
591 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
592 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
593 /* resulting in version 6.1 */
594 /* */
595 /**************************************************************************/
_nxe_http_client_get_start_extended(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,UINT resource_length,CHAR * input_ptr,UINT input_size,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG wait_option)596 UINT _nxe_http_client_get_start_extended(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource, UINT resource_length,
597 CHAR *input_ptr, UINT input_size, CHAR *username, UINT username_length,
598 CHAR *password, UINT password_length, ULONG wait_option)
599 {
600
601 #ifndef NX_DISABLE_IPV4
602 UINT status;
603
604
605 /* Check for invalid input pointers. */
606 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) || (resource == NX_NULL))
607 return(NX_PTR_ERROR);
608
609 /* Check for appropriate caller. */
610 NX_THREADS_ONLY_CALLER_CHECKING
611
612 /* Call actual GET start routine. */
613 status = _nx_http_client_get_start_extended(client_ptr, ip_address, resource, resource_length,
614 input_ptr, input_size, username, username_length,
615 password, password_length, wait_option);
616
617 /* Return completion status. */
618 return(status);
619 #else
620 NX_PARAMETER_NOT_USED(client_ptr);
621 NX_PARAMETER_NOT_USED(ip_address);
622 NX_PARAMETER_NOT_USED(resource);
623 NX_PARAMETER_NOT_USED(resource_length);
624 NX_PARAMETER_NOT_USED(input_ptr);
625 NX_PARAMETER_NOT_USED(input_size);
626 NX_PARAMETER_NOT_USED(username);
627 NX_PARAMETER_NOT_USED(username_length);
628 NX_PARAMETER_NOT_USED(password);
629 NX_PARAMETER_NOT_USED(password_length);
630 NX_PARAMETER_NOT_USED(wait_option);
631
632 return(NX_NOT_SUPPORTED);
633 #endif /* NX_DISABLE_IPV4 */
634 }
635
636
637 /**************************************************************************/
638 /* */
639 /* FUNCTION RELEASE */
640 /* */
641 /* _nx_http_client_get_start PORTABLE C */
642 /* 6.1 */
643 /* AUTHOR */
644 /* */
645 /* Yuxin Zhou, Microsoft Corporation */
646 /* */
647 /* DESCRIPTION */
648 /* */
649 /* This function is a wrapper for the actual _nxd_http_client_get_start*/
650 /* service that enables HTTP applications running on IPv4 to access */
651 /* HTTP duo API without enabling IPv6. */
652 /* */
653 /* */
654 /* INPUT */
655 /* */
656 /* client_ptr Pointer to HTTP client */
657 /* ip_address IPv4 address of HTTP Server */
658 /* resource Pointer to resource (URL) */
659 /* input_ptr Additional input pointer */
660 /* input_size Additional input size */
661 /* username Pointer to username */
662 /* password Pointer to password */
663 /* wait_option Suspension option */
664 /* */
665 /* OUTPUT */
666 /* */
667 /* status Completion status */
668 /* */
669 /* CALLS */
670 /* */
671 /* _nxd_http_client_get_start Actual HTTP Client duo get */
672 /* start service */
673 /* CALLED BY */
674 /* */
675 /* Application Code */
676 /* */
677 /* RELEASE HISTORY */
678 /* */
679 /* DATE NAME DESCRIPTION */
680 /* */
681 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
682 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
683 /* resulting in version 6.1 */
684 /* */
685 /**************************************************************************/
_nx_http_client_get_start(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,CHAR * input_ptr,UINT input_size,CHAR * username,CHAR * password,ULONG wait_option)686 UINT _nx_http_client_get_start(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource, CHAR *input_ptr,
687 UINT input_size, CHAR *username, CHAR *password, ULONG wait_option)
688 {
689
690 #ifndef NX_DISABLE_IPV4
691 UINT status;
692 NXD_ADDRESS server_ip_addr;
693
694 /* Construct an IP address structure, and fill in IPv4 address information. */
695 server_ip_addr.nxd_ip_version = NX_IP_VERSION_V4;
696 server_ip_addr.nxd_ip_address.v4 = ip_address;
697
698 /* Call the NetX HTTP 'duo' get start service. */
699 status = _nxd_http_client_get_start(client_ptr, &server_ip_addr, resource, input_ptr, input_size,
700 username, password, wait_option);
701
702 return status;
703 #else
704 NX_PARAMETER_NOT_USED(client_ptr);
705 NX_PARAMETER_NOT_USED(ip_address);
706 NX_PARAMETER_NOT_USED(resource);
707 NX_PARAMETER_NOT_USED(input_ptr);
708 NX_PARAMETER_NOT_USED(input_size);
709 NX_PARAMETER_NOT_USED(username);
710 NX_PARAMETER_NOT_USED(password);
711 NX_PARAMETER_NOT_USED(wait_option);
712
713 return(NX_NOT_SUPPORTED);
714 #endif /* NX_DISABLE_IPV4 */
715 }
716
717 /**************************************************************************/
718 /* */
719 /* FUNCTION RELEASE */
720 /* */
721 /* _nx_http_client_get_start_extended PORTABLE C */
722 /* 6.1 */
723 /* AUTHOR */
724 /* */
725 /* Yuxin Zhou, Microsoft Corporation */
726 /* */
727 /* DESCRIPTION */
728 /* */
729 /* This function is a wrapper for the actual _nxd_http_client_get_start*/
730 /* service that enables HTTP applications running on IPv4 to access */
731 /* HTTP duo API without enabling IPv6. */
732 /* */
733 /* Note: The strings of resource, username and password must be */
734 /* NULL-terminated and length of each string matches the length */
735 /* specified in the argument list. */
736 /* */
737 /* */
738 /* INPUT */
739 /* */
740 /* client_ptr Pointer to HTTP client */
741 /* ip_address IPv4 address of HTTP Server */
742 /* resource Pointer to resource (URL) */
743 /* resource_length Length to resource (URL) */
744 /* input_ptr Additional input pointer */
745 /* input_size Additional input size */
746 /* username Pointer to username */
747 /* username_length Length of username */
748 /* password Pointer to password */
749 /* password_length Length of password */
750 /* wait_option Suspension option */
751 /* */
752 /* OUTPUT */
753 /* */
754 /* status Completion status */
755 /* */
756 /* CALLS */
757 /* */
758 /* _nxd_http_client_get_start_extended Actual HTTP Client duo get */
759 /* start service */
760 /* CALLED BY */
761 /* */
762 /* Application Code */
763 /* */
764 /* RELEASE HISTORY */
765 /* */
766 /* DATE NAME DESCRIPTION */
767 /* */
768 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
769 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
770 /* resulting in version 6.1 */
771 /* */
772 /**************************************************************************/
_nx_http_client_get_start_extended(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,UINT resource_length,CHAR * input_ptr,UINT input_size,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG wait_option)773 UINT _nx_http_client_get_start_extended(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource, UINT resource_length,
774 CHAR *input_ptr, UINT input_size, CHAR *username, UINT username_length,
775 CHAR *password, UINT password_length, ULONG wait_option)
776 {
777
778 #ifndef NX_DISABLE_IPV4
779 UINT status;
780 NXD_ADDRESS server_ip_addr;
781
782 /* Construct an IP address structure, and fill in IPv4 address information. */
783 server_ip_addr.nxd_ip_version = NX_IP_VERSION_V4;
784 server_ip_addr.nxd_ip_address.v4 = ip_address;
785
786 /* Call the NetX HTTP 'duo' get start service. */
787 status = _nxd_http_client_get_start_extended(client_ptr, &server_ip_addr, resource, resource_length,
788 input_ptr, input_size, username, username_length,
789 password, password_length, wait_option);
790
791 return status;
792 #else
793 NX_PARAMETER_NOT_USED(client_ptr);
794 NX_PARAMETER_NOT_USED(ip_address);
795 NX_PARAMETER_NOT_USED(resource);
796 NX_PARAMETER_NOT_USED(resource_length);
797 NX_PARAMETER_NOT_USED(input_ptr);
798 NX_PARAMETER_NOT_USED(input_size);
799 NX_PARAMETER_NOT_USED(username);
800 NX_PARAMETER_NOT_USED(username_length);
801 NX_PARAMETER_NOT_USED(password);
802 NX_PARAMETER_NOT_USED(password_length);
803 NX_PARAMETER_NOT_USED(wait_option);
804
805 return(NX_NOT_SUPPORTED);
806 #endif /* NX_DISABLE_IPV4 */
807 }
808
809
810 /**************************************************************************/
811 /* */
812 /* FUNCTION RELEASE */
813 /* */
814 /* _nxde_http_client_get_start PORTABLE C */
815 /* 6.1 */
816 /* AUTHOR */
817 /* */
818 /* Yuxin Zhou, Microsoft Corporation */
819 /* */
820 /* DESCRIPTION */
821 /* */
822 /* This function checks for errors in the HTTP Duo client get start */
823 /* call. */
824 /* */
825 /* */
826 /* INPUT */
827 /* */
828 /* client_ptr Pointer to HTTP client */
829 /* ip_address IP duo address of HTTP Server */
830 /* resource Pointer to resource (URL) */
831 /* input_ptr Additional input pointer */
832 /* input_size Additional input size */
833 /* username Pointer to username */
834 /* password Pointer to password */
835 /* wait_option Suspension option */
836 /* */
837 /* OUTPUT */
838 /* */
839 /* status Completion status */
840 /* */
841 /* CALLS */
842 /* */
843 /* _nx_http_client_get_start Actual client get start call */
844 /* */
845 /* CALLED BY */
846 /* */
847 /* Application Code */
848 /* */
849 /* RELEASE HISTORY */
850 /* */
851 /* DATE NAME DESCRIPTION */
852 /* */
853 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
854 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
855 /* resulting in version 6.1 */
856 /* */
857 /**************************************************************************/
_nxde_http_client_get_start(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * ip_address,CHAR * resource,CHAR * input_ptr,UINT input_size,CHAR * username,CHAR * password,ULONG wait_option)858 UINT _nxde_http_client_get_start(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *ip_address, CHAR *resource,
859 CHAR *input_ptr, UINT input_size, CHAR *username, CHAR *password,
860 ULONG wait_option)
861 {
862
863 UINT status;
864
865
866 /* Check for invalid input pointers. */
867 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
868 (resource == NX_NULL) || !ip_address)
869 return(NX_PTR_ERROR);
870
871 /* Check for appropriate caller. */
872 NX_THREADS_ONLY_CALLER_CHECKING
873
874 /* Call actual GET start routine. */
875 status = _nxd_http_client_get_start(client_ptr, ip_address, resource, input_ptr, input_size,
876 username, password, wait_option);
877
878 /* Return completion status. */
879 return(status);
880 }
881
882 /**************************************************************************/
883 /* */
884 /* FUNCTION RELEASE */
885 /* */
886 /* _nxde_http_client_get_start_extended PORTABLE C */
887 /* 6.1 */
888 /* AUTHOR */
889 /* */
890 /* Yuxin Zhou, Microsoft Corporation */
891 /* */
892 /* DESCRIPTION */
893 /* */
894 /* This function checks for errors in the HTTP Duo client get start */
895 /* call. */
896 /* */
897 /* */
898 /* INPUT */
899 /* */
900 /* client_ptr Pointer to HTTP client */
901 /* ip_address IP duo address of HTTP Server */
902 /* resource Pointer to resource (URL) */
903 /* resource_length Length of resource (URL) */
904 /* input_ptr Additional input pointer */
905 /* input_size Additional input size */
906 /* username Pointer to username */
907 /* username_length Length of username */
908 /* password Pointer to password */
909 /* password_length Length of password */
910 /* wait_option Suspension option */
911 /* */
912 /* OUTPUT */
913 /* */
914 /* status Completion status */
915 /* */
916 /* CALLS */
917 /* */
918 /* _nxd_http_client_get_start_extended Actual client get start call */
919 /* */
920 /* CALLED BY */
921 /* */
922 /* Application Code */
923 /* */
924 /* RELEASE HISTORY */
925 /* */
926 /* DATE NAME DESCRIPTION */
927 /* */
928 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
929 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
930 /* resulting in version 6.1 */
931 /* */
932 /**************************************************************************/
_nxde_http_client_get_start_extended(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * ip_address,CHAR * resource,UINT resource_length,CHAR * input_ptr,UINT input_size,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG wait_option)933 UINT _nxde_http_client_get_start_extended(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *ip_address, CHAR *resource, UINT resource_length,
934 CHAR *input_ptr, UINT input_size, CHAR *username, UINT username_length,
935 CHAR *password, UINT password_length, ULONG wait_option)
936 {
937
938 UINT status;
939
940
941 /* Check for invalid input pointers. */
942 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
943 (resource == NX_NULL) || !ip_address)
944 return(NX_PTR_ERROR);
945
946 /* Check for appropriate caller. */
947 NX_THREADS_ONLY_CALLER_CHECKING
948
949 /* Call actual GET start routine. */
950 status = _nxd_http_client_get_start_extended(client_ptr, ip_address, resource, resource_length,
951 input_ptr, input_size, username, username_length,
952 password, password_length, wait_option);
953
954 /* Return completion status. */
955 return(status);
956 }
957
958 /**************************************************************************/
959 /* */
960 /* FUNCTION RELEASE */
961 /* */
962 /* _nxd_http_client_get_start PORTABLE C */
963 /* 6.1 */
964 /* AUTHOR */
965 /* */
966 /* Yuxin Zhou, Microsoft Corporation */
967 /* */
968 /* DESCRIPTION */
969 /* */
970 /* This function processes the application GET request. The specified */
971 /* resource (URL) is requested from the HTTP Server at the specified */
972 /* IP address. If input was specified, the request will actually be */
973 /* sent as a POST instead of a GET. */
974 /* */
975 /* */
976 /* INPUT */
977 /* */
978 /* client_ptr Pointer to HTTP client */
979 /* server_ip HTTP Server IP address */
980 /* resource Pointer to resource (URL) */
981 /* input_ptr Additional input pointer */
982 /* input_size Additional input size */
983 /* username Pointer to username */
984 /* password Pointer to password */
985 /* wait_option Suspension option */
986 /* */
987 /* OUTPUT */
988 /* */
989 /* status Completion status */
990 /* */
991 /* CALLS */
992 /* */
993 /* _nxd_http_client_get_start_extended Actual client get start call */
994 /* _nx_utility_string_length_check Check string length */
995 /* */
996 /* CALLED BY */
997 /* */
998 /* Application Code */
999 /* */
1000 /* RELEASE HISTORY */
1001 /* */
1002 /* DATE NAME DESCRIPTION */
1003 /* */
1004 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1005 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1006 /* resulting in version 6.1 */
1007 /* */
1008 /**************************************************************************/
_nxd_http_client_get_start(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * server_ip,CHAR * resource,CHAR * input_ptr,UINT input_size,CHAR * username,CHAR * password,ULONG wait_option)1009 UINT _nxd_http_client_get_start(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource, CHAR *input_ptr,
1010 UINT input_size, CHAR *username, CHAR *password, ULONG wait_option)
1011 {
1012
1013 UINT resource_length = 0;
1014 UINT username_length = 0;
1015 UINT password_length = 0;
1016 UINT status;
1017
1018 /* Make sure there is enough room in the destination string. */
1019 if((username) && (password))
1020 {
1021 if (_nx_utility_string_length_check(username, &username_length, NX_HTTP_MAX_NAME) ||
1022 _nx_utility_string_length_check(password, &password_length, NX_HTTP_MAX_PASSWORD))
1023 {
1024
1025 /* Error, return to caller. */
1026 return(NX_HTTP_PASSWORD_TOO_LONG);
1027 }
1028 }
1029
1030 /* Check resource length. */
1031 if (_nx_utility_string_length_check(resource, &resource_length, NX_MAX_STRING_LENGTH))
1032 {
1033 return(NX_HTTP_ERROR);
1034 }
1035
1036 status = _nxd_http_client_get_start_extended(client_ptr, server_ip, resource, resource_length,
1037 input_ptr, input_size, username, username_length,
1038 password, password_length, wait_option);
1039
1040 return(status);
1041 }
1042
1043
1044 /**************************************************************************/
1045 /* */
1046 /* FUNCTION RELEASE */
1047 /* */
1048 /* _nxd_http_client_get_start_extended PORTABLE C */
1049 /* 6.1.11 */
1050 /* AUTHOR */
1051 /* */
1052 /* Yuxin Zhou, Microsoft Corporation */
1053 /* */
1054 /* DESCRIPTION */
1055 /* */
1056 /* This function processes the application GET request. The specified */
1057 /* resource (URL) is requested from the HTTP Server at the specified */
1058 /* IP address. If input was specified, the request will actually be */
1059 /* sent as a POST instead of a GET. */
1060 /* */
1061 /* Note: The strings of resource, username and password must be */
1062 /* NULL-terminated and length of each string matches the length */
1063 /* specified in the argument list. */
1064 /* */
1065 /* */
1066 /* INPUT */
1067 /* */
1068 /* client_ptr Pointer to HTTP client */
1069 /* server_ip HTTP Server IP address */
1070 /* resource Pointer to resource (URL) */
1071 /* resource_length Length of resource (URL) */
1072 /* input_ptr Additional input pointer */
1073 /* input_size Additional input size */
1074 /* username Pointer to username */
1075 /* username_length Length of username */
1076 /* password Pointer to password */
1077 /* password_length Length of password */
1078 /* wait_option Suspension option */
1079 /* */
1080 /* OUTPUT */
1081 /* */
1082 /* status Completion status */
1083 /* */
1084 /* CALLS */
1085 /* */
1086 /* _nx_http_client_base64_encode Encode username/password */
1087 /* _nx_http_client_calculate_content_offset Calculate content offset */
1088 /* _nx_http_client_content_length_get Get content length */
1089 /* _nx_http_client_number_convert Convert number to ASCII */
1090 /* nx_packet_allocate Allocate a packet */
1091 /* nx_packet_data_append Append data to packet */
1092 /* nx_packet_release Release packet */
1093 /* nx_tcp_client_socket_bind Bind client socket to port */
1094 /* nxd_tcp_client_socket_connect Connect to HTTP Server */
1095 /* nx_tcp_socket_disconnect Disconnect client socket */
1096 /* nx_tcp_client_socket_unbind Unbind client socket */
1097 /* nx_tcp_socket_receive Get response packet */
1098 /* nx_tcp_socket_send Send request to Server */
1099 /* _nx_utility_string_length_check Check string length */
1100 /* */
1101 /* CALLED BY */
1102 /* */
1103 /* Application Code */
1104 /* */
1105 /* RELEASE HISTORY */
1106 /* */
1107 /* DATE NAME DESCRIPTION */
1108 /* */
1109 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1110 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
1111 /* verified memcpy use cases, */
1112 /* resulting in version 6.1 */
1113 /* 04-02-2021 Yuxin Zhou Modified comment(s), and */
1114 /* improved the logic of */
1115 /* parsing base64, */
1116 /* resulting in version 6.1.6 */
1117 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
1118 /* correted the status when */
1119 /* received error code, */
1120 /* resulting in version 6.1.11 */
1121 /* */
1122 /**************************************************************************/
_nxd_http_client_get_start_extended(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * server_ip,CHAR * resource,UINT resource_length,CHAR * input_ptr,UINT input_size,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG wait_option)1123 UINT _nxd_http_client_get_start_extended(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource, UINT resource_length,
1124 CHAR *input_ptr, UINT input_size, CHAR *username, UINT username_length,
1125 CHAR *password, UINT password_length, ULONG wait_option)
1126 {
1127
1128 UINT status;
1129 NX_PACKET *packet_ptr;
1130 UINT length = 0, offset = 0;
1131 NX_PACKET *response_packet_ptr;
1132 CHAR string1[NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 2];
1133 CHAR string2[NX_HTTP_MAX_STRING + 1];
1134 CHAR *buffer_ptr;
1135 CHAR crlf[2] = {13,10};
1136 UINT string1_length;
1137 UINT string2_length;
1138 UINT temp_resource_length = 0;
1139 UINT temp_username_length = 0;
1140 UINT temp_password_length = 0;
1141
1142
1143 /* Determine if the client is in a ready state. */
1144 if (client_ptr -> nx_http_client_state != NX_HTTP_CLIENT_STATE_READY)
1145 {
1146
1147 /* Client not ready, return error. */
1148 return(NX_HTTP_NOT_READY);
1149 }
1150
1151 /* Make sure there is enough room in the destination string. */
1152 if((username) && (password))
1153 {
1154 if (_nx_utility_string_length_check(username, &temp_username_length, username_length) ||
1155 _nx_utility_string_length_check(password, &temp_password_length, password_length))
1156 {
1157
1158 /* Error, return to caller. */
1159 return(NX_HTTP_PASSWORD_TOO_LONG);
1160 }
1161
1162 /* Validate string length. */
1163 if ((username_length != temp_username_length) ||
1164 (password_length != temp_password_length))
1165 {
1166 return(NX_HTTP_ERROR);
1167 }
1168 }
1169
1170 /* Check resource length. */
1171 if (_nx_utility_string_length_check(resource, &temp_resource_length, resource_length))
1172 {
1173 return(NX_HTTP_ERROR);
1174 }
1175
1176 /* Validate string length. */
1177 if (resource_length != temp_resource_length)
1178 {
1179 return(NX_HTTP_ERROR);
1180 }
1181
1182 /* Otherwise, attempt to bind the client socket. */
1183 status = nx_tcp_client_socket_bind(&(client_ptr -> nx_http_client_socket), NX_ANY_PORT, wait_option);
1184
1185 /* Check status of the bind. */
1186 if (status != NX_SUCCESS)
1187 {
1188
1189 /* Error binding to a port, return to caller. */
1190 return(status);
1191 }
1192
1193 /* Invoke the connection call. */
1194 status = nxd_tcp_client_socket_connect(&(client_ptr -> nx_http_client_socket), server_ip,
1195 client_ptr -> nx_http_client_connect_port, wait_option);
1196
1197 /* Check for connection status. */
1198 if (status != NX_SUCCESS)
1199 {
1200
1201 /* Error, unbind the port and return an error. */
1202 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1203 return(status);
1204 }
1205
1206 /* At this point we have a connection setup with an HTTP server! */
1207
1208 /* Allocate a packet for the GET (or POST) message. */
1209 if (server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
1210 {
1211 status = nx_packet_allocate(client_ptr -> nx_http_client_packet_pool_ptr, &packet_ptr,
1212 NX_IPv4_TCP_PACKET, wait_option);
1213 }
1214 else
1215 {
1216
1217 status = nx_packet_allocate(client_ptr -> nx_http_client_packet_pool_ptr, &packet_ptr,
1218 NX_IPv6_TCP_PACKET, wait_option);
1219 }
1220
1221 /* Check allocation status. */
1222 if (status != NX_SUCCESS)
1223 {
1224
1225 /* Error, unbind the port and return an error. */
1226 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1227 return(status);
1228 }
1229
1230 /* Determine if a GET or POST is requested. */
1231 if ((input_ptr) && (input_size))
1232 {
1233
1234 /* Additional information requested, build the POST request. */
1235 nx_packet_data_append(packet_ptr, "POST ", 5, client_ptr -> nx_http_client_packet_pool_ptr,
1236 NX_WAIT_FOREVER);
1237 }
1238 else
1239 {
1240
1241 /* No additional information, build the GET request. */
1242 nx_packet_data_append(packet_ptr, "GET ", 4, client_ptr -> nx_http_client_packet_pool_ptr,
1243 NX_WAIT_FOREVER);
1244 }
1245
1246 /* Determine if the resource needs a leading "/". */
1247 if (resource[0] != '/')
1248 {
1249
1250 /* Is this another website e.g. begins with http and has a colon? */
1251 if (
1252 ((resource[0] == 'h') || (resource[0] == 'H')) &&
1253 ((resource[1] == 't') || (resource[1] == 'T')) &&
1254 ((resource[2] == 't') || (resource[2] == 'T')) &&
1255 ((resource[3] == 'p') || (resource[3] == 'P')) &&
1256 (resource[4] == ':')
1257 )
1258 {
1259
1260 /* Yes, to send this string as is. */
1261 }
1262 else
1263 {
1264
1265 /* Local file URI which needs a leading '/' character. */
1266 nx_packet_data_append(packet_ptr, "/", 1, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1267 }
1268 }
1269 /* Else URI string refers to root directory file, and has a leading '/' character already. */
1270
1271 /* Place the resource in the header. */
1272 nx_packet_data_append(packet_ptr, resource, resource_length, client_ptr -> nx_http_client_packet_pool_ptr,
1273 NX_WAIT_FOREVER);
1274
1275 /* Place the HTTP version in the header. */
1276 nx_packet_data_append(packet_ptr, " HTTP/1.0", 9, client_ptr -> nx_http_client_packet_pool_ptr,
1277 NX_WAIT_FOREVER);
1278
1279 /* Place the end of line character in the header. */
1280 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr,
1281 NX_WAIT_FOREVER);
1282
1283 /* Determine if basic authentication is required. */
1284 if ((username) && (password))
1285 {
1286
1287 /* Yes, attempt to build basic authentication. */
1288 nx_packet_data_append(packet_ptr, "Authorization: Basic ", 21, client_ptr -> nx_http_client_packet_pool_ptr,
1289 NX_WAIT_FOREVER);
1290
1291 /* Encode and append the "name:password" into next. */
1292
1293 /* Place the name and password in a single string. */
1294
1295 /* Copy the name into the merged string. */
1296 memcpy(string1, username, username_length); /* Use case of memcpy is verified. */
1297
1298 /* Insert the colon. */
1299 string1[username_length] = ':';
1300
1301 /* Copy the password into the merged string. */
1302 memcpy(&string1[username_length + 1], password, password_length); /* Use case of memcpy is verified. */
1303
1304 /* Make combined string NULL terminated. */
1305 string1[username_length + password_length + 1] = NX_NULL;
1306
1307 /* Now encode the username:password string. */
1308 _nx_utility_base64_encode((UCHAR *)string1, username_length + password_length + 1, (UCHAR *)string2, sizeof(string2), &string2_length);
1309 nx_packet_data_append(packet_ptr, string2, string2_length, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1310 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1311 }
1312
1313 /* Check to see if a Content-Length field is needed. */
1314 if ((input_ptr) && (input_size))
1315 {
1316
1317 /* Now build the content-length entry. */
1318 nx_packet_data_append(packet_ptr, "Content-Length: ", 16, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1319 string1_length = _nx_http_client_number_convert(input_size, string1);
1320 nx_packet_data_append(packet_ptr, string1, string1_length, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1321 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1322 }
1323
1324 /* Place an extra cr/lf to signal the end of the HTTP header. */
1325 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1326
1327 /* Check to see if we need to append the additional user data. */
1328 if ((input_ptr) && (input_size))
1329 {
1330
1331 /* Now build the content-length entry. */
1332 nx_packet_data_append(packet_ptr, input_ptr, input_size, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1333 }
1334
1335 /* Now send the packet to the HTTP server. */
1336 status = nx_tcp_socket_send(&(client_ptr -> nx_http_client_socket), packet_ptr, wait_option);
1337
1338 /* Determine if the send was successful. */
1339 if (status != NX_SUCCESS)
1340 {
1341
1342 /* No, send was not successful. */
1343
1344 /* Release the packet. */
1345 nx_packet_release(packet_ptr);
1346
1347 /* Disconnect and unbind the socket. */
1348 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
1349 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1350
1351 /* Return an error. */
1352 return(status);
1353 }
1354
1355 /* Pickup the response from the Server. */
1356 status = nx_tcp_socket_receive(&(client_ptr -> nx_http_client_socket), &response_packet_ptr, wait_option);
1357
1358 /* Check for a response from the Server. */
1359 if (status == NX_SUCCESS)
1360 {
1361
1362 /* Setup pointer to server response. */
1363 buffer_ptr = (CHAR *) response_packet_ptr -> nx_packet_prepend_ptr;
1364
1365 /* Check if packet contains the HTTP status. */
1366 if ((buffer_ptr + 11) >= (CHAR *)response_packet_ptr -> nx_packet_append_ptr)
1367 {
1368
1369 /* Release the packet. */
1370 nx_packet_release(response_packet_ptr);
1371
1372 /* Disconnect and unbind the socket. */
1373 nx_tcp_socket_disconnect(&(client_ptr->nx_http_client_socket), wait_option);
1374 nx_tcp_client_socket_unbind(&(client_ptr->nx_http_client_socket));
1375
1376 /* Return an error. */
1377 return(NX_HTTP_FAILED);
1378 }
1379
1380 /* Determine if the request was successful. */
1381 if (buffer_ptr[9] == '2')
1382 {
1383
1384 /* Determine if we need to copy the packet. */
1385 if ((response_packet_ptr -> nx_packet_data_end - response_packet_ptr -> nx_packet_data_start) < NX_HTTP_CLIENT_MIN_PACKET_SIZE)
1386 {
1387
1388 /* Copy the packet to a packet in the packet pool. */
1389 nx_packet_copy(response_packet_ptr, &packet_ptr, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
1390
1391 /* Release the original packet. */
1392 nx_packet_release(response_packet_ptr);
1393
1394 /* Copy the packet pointer. */
1395 response_packet_ptr = packet_ptr;
1396 }
1397
1398 /* Pickup the content length. */
1399 length = _nx_http_client_content_length_get(response_packet_ptr);
1400
1401 /* Pickup the content offset. */
1402 offset = _nx_http_client_calculate_content_offset(response_packet_ptr);
1403
1404 /* Indicate a successful completion. */
1405 status = NX_SUCCESS;
1406 }
1407 /* Determine if it is an authentication error. */
1408 else if ((buffer_ptr[9] == '4') && (buffer_ptr[10] == '0') && (buffer_ptr[11] == '1'))
1409 {
1410
1411 /* Release the packet. */
1412 nx_packet_release(response_packet_ptr);
1413
1414 /* Inform caller of an authentication error. */
1415 status = NX_HTTP_AUTHENTICATION_ERROR;
1416 }
1417 else
1418 {
1419
1420 /* Release the packet. */
1421 nx_packet_release(response_packet_ptr);
1422
1423 /* Received error code. */
1424 status = NX_HTTP_REQUEST_UNSUCCESSFUL_CODE;
1425 }
1426 }
1427
1428 /* Check for error processing received packet. */
1429 if (status != NX_SUCCESS)
1430 {
1431
1432 /* Disconnect and unbind the socket. */
1433 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
1434 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1435
1436 return status;
1437 }
1438
1439 /* Check for invalid packet parameters. */
1440 if ((length == 0) || (offset == 0))
1441 {
1442
1443 /* Release the packet. */
1444 nx_packet_release(response_packet_ptr);
1445
1446 /* Disconnect and unbind the socket. */
1447 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
1448 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1449
1450 /* Return an error. */
1451 return(NX_HTTP_FAILED);
1452 }
1453
1454
1455 /* Determine if the offset is in this request. */
1456 if (response_packet_ptr -> nx_packet_length > (offset + 3))
1457 {
1458
1459 /* Adjust the pointers to skip over the response header. */
1460 response_packet_ptr -> nx_packet_prepend_ptr = response_packet_ptr -> nx_packet_prepend_ptr + offset;
1461
1462 /* Reduce the length. */
1463 response_packet_ptr -> nx_packet_length = response_packet_ptr -> nx_packet_length - offset;
1464
1465 /* Save the packet pointer for the get packet call. */
1466 client_ptr -> nx_http_client_first_packet = response_packet_ptr;
1467 }
1468 else
1469 {
1470
1471 /* Clear the saved packet pointer. */
1472 client_ptr -> nx_http_client_first_packet = NX_NULL;
1473
1474 /* This packet only contains the header, just release it! */
1475 nx_packet_release(response_packet_ptr);
1476 }
1477
1478 /* Store the total number of bytes to receive. */
1479 client_ptr -> nx_http_client_total_transfer_bytes = length;
1480 client_ptr -> nx_http_client_actual_bytes_transferred = 0;
1481
1482 /* Enter the GET state. */
1483 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_GET;
1484
1485 /* Return success to the caller. */
1486 return NX_SUCCESS;
1487 }
1488
1489
1490 /**************************************************************************/
1491 /* */
1492 /* FUNCTION RELEASE */
1493 /* */
1494 /* _nxe_http_client_get_packet PORTABLE C */
1495 /* 6.1 */
1496 /* AUTHOR */
1497 /* */
1498 /* Yuxin Zhou, Microsoft Corporation */
1499 /* */
1500 /* DESCRIPTION */
1501 /* */
1502 /* This function checks for errors in the HTTP client get packet call. */
1503 /* */
1504 /* */
1505 /* INPUT */
1506 /* */
1507 /* client_ptr Pointer to HTTP client */
1508 /* packet_ptr Destination for packet pointer*/
1509 /* wait_option Suspension option */
1510 /* */
1511 /* OUTPUT */
1512 /* */
1513 /* status Completion status */
1514 /* */
1515 /* CALLS */
1516 /* */
1517 /* _nx_http_client_get_packet Actual client get packet call */
1518 /* */
1519 /* CALLED BY */
1520 /* */
1521 /* Application Code */
1522 /* */
1523 /* RELEASE HISTORY */
1524 /* */
1525 /* DATE NAME DESCRIPTION */
1526 /* */
1527 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1528 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1529 /* resulting in version 6.1 */
1530 /* */
1531 /**************************************************************************/
_nxe_http_client_get_packet(NX_HTTP_CLIENT * client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)1532 UINT _nxe_http_client_get_packet(NX_HTTP_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
1533 {
1534
1535 UINT status;
1536
1537
1538 /* Check for invalid input pointers. */
1539 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
1540 (packet_ptr == NX_NULL))
1541 return(NX_PTR_ERROR);
1542
1543 /* Check for appropriate caller. */
1544 NX_THREADS_ONLY_CALLER_CHECKING
1545
1546 /* Call actual GET packet routine. */
1547 status = _nx_http_client_get_packet(client_ptr, packet_ptr, wait_option);
1548
1549 /* Return completion status. */
1550 return(status);
1551 }
1552
1553
1554 /**************************************************************************/
1555 /* */
1556 /* FUNCTION RELEASE */
1557 /* */
1558 /* _nx_http_client_get_packet PORTABLE C */
1559 /* 6.1 */
1560 /* AUTHOR */
1561 /* */
1562 /* Yuxin Zhou, Microsoft Corporation */
1563 /* */
1564 /* DESCRIPTION */
1565 /* */
1566 /* This function gets a data packet associated with the resource */
1567 /* specified by the previous GET start request. */
1568 /* */
1569 /* */
1570 /* INPUT */
1571 /* */
1572 /* client_ptr Pointer to HTTP client */
1573 /* packet_ptr Destination for packet pointer*/
1574 /* wait_option Suspension option */
1575 /* */
1576 /* OUTPUT */
1577 /* */
1578 /* status Completion status */
1579 /* */
1580 /* CALLS */
1581 /* */
1582 /* nx_tcp_client_socket_unbind Unbind client socket */
1583 /* nx_tcp_socket_disconnect Disconnect client socket */
1584 /* nx_tcp_socket_receive Receive a resource data packet*/
1585 /* */
1586 /* CALLED BY */
1587 /* */
1588 /* Application Code */
1589 /* */
1590 /* RELEASE HISTORY */
1591 /* */
1592 /* DATE NAME DESCRIPTION */
1593 /* */
1594 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1595 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1596 /* resulting in version 6.1 */
1597 /* */
1598 /**************************************************************************/
_nx_http_client_get_packet(NX_HTTP_CLIENT * client_ptr,NX_PACKET ** packet_ptr,ULONG wait_option)1599 UINT _nx_http_client_get_packet(NX_HTTP_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option)
1600 {
1601
1602 NX_PACKET *data_packet_ptr;
1603 UINT status;
1604
1605
1606 /* Default the return packet to NULL. */
1607 *packet_ptr = NX_NULL;
1608
1609 /* Determine if the client is in a get state. */
1610 if (client_ptr -> nx_http_client_state != NX_HTTP_CLIENT_STATE_GET)
1611 {
1612
1613 /* Client not ready, return error. */
1614 return(NX_HTTP_NOT_READY);
1615 }
1616
1617 /* Determine if the GET packet operation is complete. */
1618 if (client_ptr -> nx_http_client_total_transfer_bytes == client_ptr -> nx_http_client_actual_bytes_transferred)
1619 {
1620
1621 /* Yes, we are finished. */
1622
1623 /* Disconnect and unbind the socket. */
1624 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
1625 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1626
1627 /* Reenter the READY state. */
1628 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
1629
1630 /* Return the GET done code. */
1631 return(NX_HTTP_GET_DONE);
1632 }
1633
1634 /* Determine if there is a queued packet. */
1635 if (client_ptr -> nx_http_client_first_packet)
1636 {
1637
1638 /* Yes, just use the saved packet. */
1639 data_packet_ptr = client_ptr -> nx_http_client_first_packet;
1640
1641 /* Clear the saved packet pointer. */
1642 client_ptr -> nx_http_client_first_packet = NX_NULL;
1643 }
1644 else
1645 {
1646
1647 /* Receive a data packet from the TCP connection. */
1648 status = nx_tcp_socket_receive(&(client_ptr -> nx_http_client_socket), &data_packet_ptr, wait_option);
1649
1650 /* Determine if a packet is available. */
1651 if (status != NX_SUCCESS)
1652 {
1653
1654 /* Ensure the packet pointer is NULL. */
1655 data_packet_ptr = NX_NULL;
1656 /* Disconnect and unbind the socket. */
1657 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
1658 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1659 return status;
1660 }
1661 }
1662
1663 /* Check for an error condition. */
1664 if (data_packet_ptr -> nx_packet_length > (client_ptr -> nx_http_client_total_transfer_bytes - client_ptr -> nx_http_client_actual_bytes_transferred))
1665 {
1666
1667 /* Release the invalid HTTP packet. */
1668 nx_packet_release(data_packet_ptr);
1669
1670 /* Error, break down the connection and return to the caller. */
1671
1672 /* Disconnect and unbind the socket. */
1673 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
1674 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
1675
1676 /* Reenter the READY state. */
1677 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
1678
1679 /* Return an error. */
1680 return(NX_HTTP_BAD_PACKET_LENGTH);
1681 }
1682
1683 /* Adjust the actual transfer bytes. */
1684 client_ptr -> nx_http_client_actual_bytes_transferred = client_ptr -> nx_http_client_actual_bytes_transferred +
1685 data_packet_ptr -> nx_packet_length;
1686
1687 /* Move the packet pointer into the return pointer. */
1688 *packet_ptr = data_packet_ptr;
1689
1690 /* Return a successful completion. */
1691 return(NX_SUCCESS);
1692 }
1693
1694 /**************************************************************************/
1695 /* */
1696 /* FUNCTION RELEASE */
1697 /* */
1698 /* _nxe_http_client_put_start PORTABLE C */
1699 /* 6.1 */
1700 /* AUTHOR */
1701 /* */
1702 /* Yuxin Zhou, Microsoft Corporation */
1703 /* */
1704 /* DESCRIPTION */
1705 /* */
1706 /* This function checks for errors in the HTTP (IPv4) Client put start */
1707 /* call. */
1708 /* */
1709 /* */
1710 /* INPUT */
1711 /* */
1712 /* client_ptr Pointer to HTTP client */
1713 /* ip_address IPv4 address of HTTP Server */
1714 /* resource Pointer to resource (URL) */
1715 /* username Pointer to username */
1716 /* password Pointer to password */
1717 /* total_bytes Total bytes to send */
1718 /* wait_option Suspension option */
1719 /* */
1720 /* OUTPUT */
1721 /* */
1722 /* status Completion status */
1723 /* */
1724 /* CALLS */
1725 /* */
1726 /* _nx_http_client_put_start Actual IPv4 HTTP Client put */
1727 /* start call */
1728 /* */
1729 /* CALLED BY */
1730 /* */
1731 /* Application Code */
1732 /* */
1733 /* RELEASE HISTORY */
1734 /* */
1735 /* DATE NAME DESCRIPTION */
1736 /* */
1737 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1738 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1739 /* resulting in version 6.1 */
1740 /* */
1741 /**************************************************************************/
1742
_nxe_http_client_put_start(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,CHAR * username,CHAR * password,ULONG total_bytes,ULONG wait_option)1743 UINT _nxe_http_client_put_start(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource,
1744 CHAR *username, CHAR *password, ULONG total_bytes, ULONG wait_option)
1745 {
1746
1747 #ifndef NX_DISABLE_IPV4
1748 UINT status;
1749
1750
1751 /* Check for invalid input pointers. */
1752 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
1753 resource == NX_NULL || !ip_address)
1754 return(NX_PTR_ERROR);
1755
1756 /* Check for invalid total bytes. */
1757 if (total_bytes == 0)
1758 return(NX_SIZE_ERROR);
1759
1760 /* Check for appropriate caller. */
1761 NX_THREADS_ONLY_CALLER_CHECKING
1762
1763 /* Call actual PUT start routine. */
1764 status = _nx_http_client_put_start(client_ptr, ip_address, resource, username, password,
1765 total_bytes, wait_option);
1766
1767 /* Return completion status. */
1768 return(status);
1769 #else
1770 NX_PARAMETER_NOT_USED(client_ptr);
1771 NX_PARAMETER_NOT_USED(ip_address);
1772 NX_PARAMETER_NOT_USED(resource);
1773 NX_PARAMETER_NOT_USED(username);
1774 NX_PARAMETER_NOT_USED(password);
1775 NX_PARAMETER_NOT_USED(total_bytes);
1776 NX_PARAMETER_NOT_USED(wait_option);
1777
1778 return(NX_NOT_SUPPORTED);
1779 #endif /* NX_DISABLE_IPV4 */
1780 }
1781
1782
1783 /**************************************************************************/
1784 /* */
1785 /* FUNCTION RELEASE */
1786 /* */
1787 /* _nxe_http_client_put_start_extended PORTABLE C */
1788 /* 6.1 */
1789 /* AUTHOR */
1790 /* */
1791 /* Yuxin Zhou, Microsoft Corporation */
1792 /* */
1793 /* DESCRIPTION */
1794 /* */
1795 /* This function checks for errors in the HTTP (IPv4) Client put start */
1796 /* call. */
1797 /* */
1798 /* */
1799 /* INPUT */
1800 /* */
1801 /* client_ptr Pointer to HTTP client */
1802 /* ip_address IPv4 address of HTTP Server */
1803 /* resource Pointer to resource (URL) */
1804 /* resource_length Length of resource (URL) */
1805 /* username Pointer to username */
1806 /* username_length Length of username */
1807 /* password Pointer to password */
1808 /* password_length Length of password */
1809 /* total_bytes Total bytes to send */
1810 /* wait_option Suspension option */
1811 /* */
1812 /* OUTPUT */
1813 /* */
1814 /* status Completion status */
1815 /* */
1816 /* CALLS */
1817 /* */
1818 /* _nx_http_client_put_start_extended Actual IPv4 HTTP Client put */
1819 /* start call */
1820 /* */
1821 /* CALLED BY */
1822 /* */
1823 /* Application Code */
1824 /* */
1825 /* RELEASE HISTORY */
1826 /* */
1827 /* DATE NAME DESCRIPTION */
1828 /* */
1829 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1830 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1831 /* resulting in version 6.1 */
1832 /* */
1833 /**************************************************************************/
1834
_nxe_http_client_put_start_extended(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,UINT resource_length,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG total_bytes,ULONG wait_option)1835 UINT _nxe_http_client_put_start_extended(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource,
1836 UINT resource_length, CHAR *username, UINT username_length,
1837 CHAR *password, UINT password_length, ULONG total_bytes, ULONG wait_option)
1838 {
1839
1840 #ifndef NX_DISABLE_IPV4
1841 UINT status;
1842
1843
1844 /* Check for invalid input pointers. */
1845 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
1846 resource == NX_NULL || !ip_address)
1847 return(NX_PTR_ERROR);
1848
1849 /* Check for invalid total bytes. */
1850 if (total_bytes == 0)
1851 return(NX_SIZE_ERROR);
1852
1853 /* Check for appropriate caller. */
1854 NX_THREADS_ONLY_CALLER_CHECKING
1855
1856 /* Call actual PUT start routine. */
1857 status = _nx_http_client_put_start_extended(client_ptr, ip_address, resource, resource_length,
1858 username, username_length, password, password_length,
1859 total_bytes, wait_option);
1860
1861 /* Return completion status. */
1862 return(status);
1863 #else
1864 NX_PARAMETER_NOT_USED(client_ptr);
1865 NX_PARAMETER_NOT_USED(ip_address);
1866 NX_PARAMETER_NOT_USED(resource);
1867 NX_PARAMETER_NOT_USED(resource_length);
1868 NX_PARAMETER_NOT_USED(username);
1869 NX_PARAMETER_NOT_USED(username_length);
1870 NX_PARAMETER_NOT_USED(password);
1871 NX_PARAMETER_NOT_USED(password_length);
1872 NX_PARAMETER_NOT_USED(total_bytes);
1873 NX_PARAMETER_NOT_USED(wait_option);
1874
1875 return(NX_NOT_SUPPORTED);
1876 #endif /* NX_DISABLE_IPV4 */
1877 }
1878
1879
1880 /**************************************************************************/
1881 /* */
1882 /* FUNCTION RELEASE */
1883 /* */
1884 /* _nx_http_client_put_start PORTABLE C */
1885 /* 6.1 */
1886 /* AUTHOR */
1887 /* */
1888 /* Yuxin Zhou, Microsoft Corporation */
1889 /* */
1890 /* DESCRIPTION */
1891 /* */
1892 /* This function is a wrapper for the actual _nxd_http_client_put_start*/
1893 /* service that enables HTTP applications running on IPv4 to access */
1894 /* HTTP duo API without enabling IPv6. */
1895 /* */
1896 /* */
1897 /* INPUT */
1898 /* */
1899 /* client_ptr Pointer to HTTP client */
1900 /* ip_address IPv4 address of HTTP Server */
1901 /* resource Pointer to resource (URL) */
1902 /* username Pointer to username */
1903 /* password Pointer to password */
1904 /* total_bytes Total bytes to send */
1905 /* wait_option Suspension option */
1906 /* */
1907 /* OUTPUT */
1908 /* */
1909 /* status Completion status */
1910 /* */
1911 /* CALLS */
1912 /* */
1913 /* _nxd_http_client_put_start Actual put start service for */
1914 /* HTTP Duo Client */
1915 /* */
1916 /* CALLED BY */
1917 /* */
1918 /* Application Code */
1919 /* */
1920 /* RELEASE HISTORY */
1921 /* */
1922 /* DATE NAME DESCRIPTION */
1923 /* */
1924 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1925 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1926 /* resulting in version 6.1 */
1927 /* */
1928 /**************************************************************************/
_nx_http_client_put_start(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,CHAR * username,CHAR * password,ULONG total_bytes,ULONG wait_option)1929 UINT _nx_http_client_put_start(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource, CHAR *username,
1930 CHAR *password, ULONG total_bytes, ULONG wait_option)
1931 {
1932
1933 #ifndef NX_DISABLE_IPV4
1934 UINT status;
1935 NXD_ADDRESS server_ip_addr;
1936
1937
1938 /* Construct an IP address structure, and fill in IPv4 address information. */
1939 server_ip_addr.nxd_ip_version = NX_IP_VERSION_V4;
1940 server_ip_addr.nxd_ip_address.v4 = ip_address;
1941
1942 status = _nxd_http_client_put_start(client_ptr, &server_ip_addr, resource, username,
1943 password, total_bytes, wait_option);
1944
1945 return status;
1946 #else
1947 NX_PARAMETER_NOT_USED(client_ptr);
1948 NX_PARAMETER_NOT_USED(ip_address);
1949 NX_PARAMETER_NOT_USED(resource);
1950 NX_PARAMETER_NOT_USED(username);
1951 NX_PARAMETER_NOT_USED(password);
1952 NX_PARAMETER_NOT_USED(total_bytes);
1953 NX_PARAMETER_NOT_USED(wait_option);
1954
1955 return(NX_NOT_SUPPORTED);
1956 #endif /* NX_DISABLE_IPV4 */
1957 }
1958
1959 /**************************************************************************/
1960 /* */
1961 /* FUNCTION RELEASE */
1962 /* */
1963 /* _nx_http_client_put_start_extended PORTABLE C */
1964 /* 6.1 */
1965 /* AUTHOR */
1966 /* */
1967 /* Yuxin Zhou, Microsoft Corporation */
1968 /* */
1969 /* DESCRIPTION */
1970 /* */
1971 /* This function is a wrapper for the actual _nxd_http_client_put_start*/
1972 /* service that enables HTTP applications running on IPv4 to access */
1973 /* HTTP duo API without enabling IPv6. */
1974 /* */
1975 /* Note: The strings of resource, username and password must be */
1976 /* NULL-terminated and length of each string matches the length */
1977 /* specified in the argument list. */
1978 /* */
1979 /* */
1980 /* INPUT */
1981 /* */
1982 /* client_ptr Pointer to HTTP client */
1983 /* ip_address IPv4 address of HTTP Server */
1984 /* resource Pointer to resource (URL) */
1985 /* resource_length Length of resource (URL) */
1986 /* username Pointer to username */
1987 /* username_length Length of username */
1988 /* password Pointer to password */
1989 /* password_length Length of password */
1990 /* total_bytes Total bytes to send */
1991 /* wait_option Suspension option */
1992 /* */
1993 /* OUTPUT */
1994 /* */
1995 /* status Completion status */
1996 /* */
1997 /* CALLS */
1998 /* */
1999 /* _nxd_http_client_put_start_extended Actual put start service for */
2000 /* HTTP Duo Client */
2001 /* */
2002 /* CALLED BY */
2003 /* */
2004 /* Application Code */
2005 /* */
2006 /* RELEASE HISTORY */
2007 /* */
2008 /* DATE NAME DESCRIPTION */
2009 /* */
2010 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2011 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2012 /* resulting in version 6.1 */
2013 /* */
2014 /**************************************************************************/
_nx_http_client_put_start_extended(NX_HTTP_CLIENT * client_ptr,ULONG ip_address,CHAR * resource,UINT resource_length,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG total_bytes,ULONG wait_option)2015 UINT _nx_http_client_put_start_extended(NX_HTTP_CLIENT *client_ptr, ULONG ip_address, CHAR *resource,
2016 UINT resource_length, CHAR *username, UINT username_length,
2017 CHAR *password, UINT password_length, ULONG total_bytes, ULONG wait_option)
2018 {
2019
2020 #ifndef NX_DISABLE_IPV4
2021 UINT status;
2022 NXD_ADDRESS server_ip_addr;
2023
2024
2025 /* Construct an IP address structure, and fill in IPv4 address information. */
2026 server_ip_addr.nxd_ip_version = NX_IP_VERSION_V4;
2027 server_ip_addr.nxd_ip_address.v4 = ip_address;
2028
2029 status = _nxd_http_client_put_start_extended(client_ptr, &server_ip_addr, resource, resource_length,
2030 username, username_length, password, password_length,
2031 total_bytes, wait_option);
2032
2033 return status;
2034 #else
2035 NX_PARAMETER_NOT_USED(client_ptr);
2036 NX_PARAMETER_NOT_USED(ip_address);
2037 NX_PARAMETER_NOT_USED(resource);
2038 NX_PARAMETER_NOT_USED(resource_length);
2039 NX_PARAMETER_NOT_USED(username);
2040 NX_PARAMETER_NOT_USED(username_length);
2041 NX_PARAMETER_NOT_USED(password);
2042 NX_PARAMETER_NOT_USED(password_length);
2043 NX_PARAMETER_NOT_USED(total_bytes);
2044 NX_PARAMETER_NOT_USED(wait_option);
2045
2046 return(NX_NOT_SUPPORTED);
2047 #endif /* NX_DISABLE_IPV4 */
2048 }
2049
2050 /**************************************************************************/
2051 /* */
2052 /* FUNCTION RELEASE */
2053 /* */
2054 /* _nxde_http_client_put_start PORTABLE C */
2055 /* 6.1 */
2056 /* AUTHOR */
2057 /* */
2058 /* Yuxin Zhou, Microsoft Corporation */
2059 /* */
2060 /* DESCRIPTION */
2061 /* */
2062 /* This function checks for errors in the HTTP Duo Client put start */
2063 /* call. */
2064 /* */
2065 /* */
2066 /* INPUT */
2067 /* */
2068 /* client_ptr Pointer to HTTP client */
2069 /* server_ip IP duo address of HTTP Server */
2070 /* resource Pointer to resource (URL) */
2071 /* username Pointer to username */
2072 /* password Pointer to password */
2073 /* total_bytes Total bytes to send */
2074 /* wait_option Suspension option */
2075 /* */
2076 /* OUTPUT */
2077 /* */
2078 /* status Completion status */
2079 /* */
2080 /* CALLS */
2081 /* */
2082 /* _nx_http_client_put_start Actual client put start call */
2083 /* */
2084 /* CALLED BY */
2085 /* */
2086 /* Application Code */
2087 /* */
2088 /* RELEASE HISTORY */
2089 /* */
2090 /* DATE NAME DESCRIPTION */
2091 /* */
2092 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2093 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2094 /* resulting in version 6.1 */
2095 /* */
2096 /**************************************************************************/
_nxde_http_client_put_start(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * server_ip,CHAR * resource,CHAR * username,CHAR * password,ULONG total_bytes,ULONG wait_option)2097 UINT _nxde_http_client_put_start(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource,
2098 CHAR *username, CHAR *password, ULONG total_bytes, ULONG wait_option)
2099 {
2100
2101 UINT status;
2102
2103
2104 /* Check for invalid input pointers. */
2105 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
2106 resource == NX_NULL || !server_ip)
2107 return(NX_PTR_ERROR);
2108
2109 /* Check for invalid total bytes. */
2110 if (total_bytes == 0)
2111 return(NX_SIZE_ERROR);
2112
2113 /* Check for appropriate caller. */
2114 NX_THREADS_ONLY_CALLER_CHECKING
2115
2116 /* Call actual PUT start routine. */
2117 status = _nxd_http_client_put_start(client_ptr, server_ip, resource, username, password,
2118 total_bytes, wait_option);
2119
2120 /* Return completion status. */
2121 return(status);
2122 }
2123
2124
2125 /**************************************************************************/
2126 /* */
2127 /* FUNCTION RELEASE */
2128 /* */
2129 /* _nxde_http_client_put_start_extended PORTABLE C */
2130 /* 6.1 */
2131 /* AUTHOR */
2132 /* */
2133 /* Yuxin Zhou, Microsoft Corporation */
2134 /* */
2135 /* DESCRIPTION */
2136 /* */
2137 /* This function checks for errors in the HTTP Duo Client put start */
2138 /* call. */
2139 /* */
2140 /* */
2141 /* INPUT */
2142 /* */
2143 /* client_ptr Pointer to HTTP client */
2144 /* server_ip IP duo address of HTTP Server */
2145 /* resource Pointer to resource (URL) */
2146 /* resource_length Length of resource (URL) */
2147 /* username Pointer to username */
2148 /* username_length Length of username */
2149 /* password Pointer to password */
2150 /* password_length Length of password */
2151 /* total_bytes Total bytes to send */
2152 /* wait_option Suspension option */
2153 /* */
2154 /* OUTPUT */
2155 /* */
2156 /* status Completion status */
2157 /* */
2158 /* CALLS */
2159 /* */
2160 /* _nxd_http_client_put_start_extended Actual client put start call */
2161 /* */
2162 /* CALLED BY */
2163 /* */
2164 /* Application Code */
2165 /* */
2166 /* RELEASE HISTORY */
2167 /* */
2168 /* DATE NAME DESCRIPTION */
2169 /* */
2170 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2171 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2172 /* resulting in version 6.1 */
2173 /* */
2174 /**************************************************************************/
_nxde_http_client_put_start_extended(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * server_ip,CHAR * resource,UINT resource_length,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG total_bytes,ULONG wait_option)2175 UINT _nxde_http_client_put_start_extended(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource,
2176 UINT resource_length, CHAR *username, UINT username_length,
2177 CHAR *password, UINT password_length, ULONG total_bytes, ULONG wait_option)
2178 {
2179
2180 UINT status;
2181
2182
2183 /* Check for invalid input pointers. */
2184 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
2185 resource == NX_NULL || !server_ip)
2186 return(NX_PTR_ERROR);
2187
2188 /* Check for invalid total bytes. */
2189 if (total_bytes == 0)
2190 return(NX_SIZE_ERROR);
2191
2192 /* Check for appropriate caller. */
2193 NX_THREADS_ONLY_CALLER_CHECKING
2194
2195 /* Call actual PUT start routine. */
2196 status = _nxd_http_client_put_start_extended(client_ptr, server_ip, resource, resource_length,
2197 username, username_length, password, password_length,
2198 total_bytes, wait_option);
2199
2200 /* Return completion status. */
2201 return(status);
2202 }
2203
2204
2205 /**************************************************************************/
2206 /* */
2207 /* FUNCTION RELEASE */
2208 /* */
2209 /* _nxd_http_client_put_start PORTABLE C */
2210 /* 6.1 */
2211 /* AUTHOR */
2212 /* */
2213 /* Yuxin Zhou, Microsoft Corporation */
2214 /* */
2215 /* DESCRIPTION */
2216 /* */
2217 /* This function processesthe application PUT request. Transferring the*/
2218 /* specified resource (URL) is started by this routine. The */
2219 /* application must call put packet one or more times to transfer */
2220 /* the resource contents. */
2221 /* */
2222 /* */
2223 /* INPUT */
2224 /* */
2225 /* client_ptr Pointer to HTTP client */
2226 /* server_ip IP address of HTTP Server */
2227 /* resource Pointer to resource (URL) */
2228 /* username Pointer to username */
2229 /* password Pointer to password */
2230 /* total_bytes Total bytes to send */
2231 /* wait_option Suspension option */
2232 /* */
2233 /* OUTPUT */
2234 /* */
2235 /* status Completion status */
2236 /* */
2237 /* CALLS */
2238 /* */
2239 /* _nxd_http_client_put_start_extended Actual client put start call */
2240 /* _nx_utility_string_length_check Check string length */
2241 /* */
2242 /* CALLED BY */
2243 /* */
2244 /* Application Code */
2245 /* */
2246 /* RELEASE HISTORY */
2247 /* */
2248 /* DATE NAME DESCRIPTION */
2249 /* */
2250 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2251 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2252 /* resulting in version 6.1 */
2253 /* */
2254 /**************************************************************************/
_nxd_http_client_put_start(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * server_ip,CHAR * resource,CHAR * username,CHAR * password,ULONG total_bytes,ULONG wait_option)2255 UINT _nxd_http_client_put_start(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource,
2256 CHAR *username, CHAR *password, ULONG total_bytes, ULONG wait_option)
2257
2258 {
2259
2260 UINT resource_length = 0;
2261 UINT username_length = 0;
2262 UINT password_length = 0;
2263 UINT status;
2264
2265 /* Make sure there is enough room in the destination string. */
2266 if((username) && (password))
2267 {
2268 if (_nx_utility_string_length_check(username, &username_length, NX_HTTP_MAX_NAME) ||
2269 _nx_utility_string_length_check(password, &password_length, NX_HTTP_MAX_PASSWORD))
2270 {
2271
2272 /* Error, return to caller. */
2273 return(NX_HTTP_PASSWORD_TOO_LONG);
2274 }
2275 }
2276
2277 /* Check resource length. */
2278 if (_nx_utility_string_length_check(resource, &resource_length, NX_MAX_STRING_LENGTH))
2279 {
2280 return(NX_HTTP_ERROR);
2281 }
2282
2283 status = _nxd_http_client_put_start_extended(client_ptr, server_ip, resource, resource_length,
2284 username, username_length, password, password_length,
2285 total_bytes, wait_option);
2286
2287 /* Return status to the caller. */
2288 return(status);
2289 }
2290
2291
2292 /**************************************************************************/
2293 /* */
2294 /* FUNCTION RELEASE */
2295 /* */
2296 /* _nxd_http_client_put_start_extended PORTABLE C */
2297 /* 6.1.6 */
2298 /* AUTHOR */
2299 /* */
2300 /* Yuxin Zhou, Microsoft Corporation */
2301 /* */
2302 /* DESCRIPTION */
2303 /* */
2304 /* This function processesthe application PUT request. Transferring the*/
2305 /* specified resource (URL) is started by this routine. The */
2306 /* application must call put packet one or more times to transfer */
2307 /* the resource contents. */
2308 /* */
2309 /* Note: The strings of resource, username and password must be */
2310 /* NULL-terminated and length of each string matches the length */
2311 /* specified in the argument list. */
2312 /* */
2313 /* */
2314 /* INPUT */
2315 /* */
2316 /* client_ptr Pointer to HTTP client */
2317 /* server_ip IP address of HTTP Server */
2318 /* resource Pointer to resource (URL) */
2319 /* resource_length Length of resource (URL) */
2320 /* username Pointer to username */
2321 /* username_length Length of username */
2322 /* password Pointer to password */
2323 /* password_length Length of password */
2324 /* total_bytes Total bytes to send */
2325 /* wait_option Suspension option */
2326 /* */
2327 /* OUTPUT */
2328 /* */
2329 /* status Completion status */
2330 /* */
2331 /* CALLS */
2332 /* */
2333 /* _nx_http_client_base64_encode Encode username/password */
2334 /* _nx_http_client_number_convert Convert number to ASCII */
2335 /* nx_http_client_type_get Get the HTTP file type */
2336 /* nx_packet_allocate Allocate a packet */
2337 /* nx_packet_data_append Append data to packet */
2338 /* nx_packet_release Release packet */
2339 /* nx_tcp_client_socket_bind Bind client socket to port */
2340 /* nxd_tcp_client_socket_connect Connect to HTTP Server */
2341 /* nx_tcp_socket_disconnect Disconnect client socket */
2342 /* nx_tcp_client_socket_unbind Unbind client socket */
2343 /* nx_tcp_socket_send Send request to Server */
2344 /* _nx_utility_string_length_check Check string length */
2345 /* */
2346 /* CALLED BY */
2347 /* */
2348 /* Application Code */
2349 /* */
2350 /* RELEASE HISTORY */
2351 /* */
2352 /* DATE NAME DESCRIPTION */
2353 /* */
2354 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2355 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2356 /* verified memcpy use cases, */
2357 /* resulting in version 6.1 */
2358 /* 04-02-2021 Yuxin Zhou Modified comment(s), and */
2359 /* improved the logic of */
2360 /* parsing base64, */
2361 /* resulting in version 6.1.6 */
2362 /* */
2363 /**************************************************************************/
_nxd_http_client_put_start_extended(NX_HTTP_CLIENT * client_ptr,NXD_ADDRESS * server_ip,CHAR * resource,UINT resource_length,CHAR * username,UINT username_length,CHAR * password,UINT password_length,ULONG total_bytes,ULONG wait_option)2364 UINT _nxd_http_client_put_start_extended(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource,
2365 UINT resource_length, CHAR *username, UINT username_length,
2366 CHAR *password, UINT password_length, ULONG total_bytes, ULONG wait_option)
2367
2368 {
2369
2370 NX_PACKET *packet_ptr;
2371 CHAR string1[NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 2];
2372 CHAR string2[NX_HTTP_MAX_STRING + 1];
2373 CHAR crlf[2] = {13,10};
2374 UINT status;
2375 UINT string1_length;
2376 UINT string2_length;
2377 UINT temp_resource_length = 0;
2378 UINT temp_username_length = 0;
2379 UINT temp_password_length = 0;
2380
2381
2382
2383 /* Determine if the client is in a ready state. */
2384 if (client_ptr -> nx_http_client_state != NX_HTTP_CLIENT_STATE_READY)
2385 {
2386
2387 /* Client not ready, return error. */
2388 return(NX_HTTP_NOT_READY);
2389 }
2390
2391 if ((username) && (password))
2392 {
2393
2394 /* Make sure there is enough room in the destination string. */
2395 if (_nx_utility_string_length_check(username, &temp_username_length, username_length) ||
2396 _nx_utility_string_length_check(password, &temp_password_length, password_length))
2397 {
2398
2399 /* Error, return to caller. */
2400 return(NX_HTTP_USERNAME_TOO_LONG);
2401 }
2402
2403 /* Validate string length. */
2404 if ((username_length != temp_username_length) ||
2405 (password_length != temp_password_length))
2406 {
2407 return(NX_HTTP_ERROR);
2408 }
2409 }
2410
2411 /* Check resource length. */
2412 if (_nx_utility_string_length_check(resource, &temp_resource_length, resource_length))
2413 {
2414 return(NX_HTTP_ERROR);
2415 }
2416
2417 /* Validate string length. */
2418 if (resource_length != temp_resource_length)
2419 {
2420 return(NX_HTTP_ERROR);
2421 }
2422
2423 /* Otherwise, attempt to bind the client socket. */
2424 status = nx_tcp_client_socket_bind(&(client_ptr -> nx_http_client_socket), NX_ANY_PORT, wait_option);
2425
2426 /* Check status of the bind. */
2427 if (status != NX_SUCCESS)
2428 {
2429
2430 /* Error binding to a port, return to caller. */
2431 return(status);
2432 }
2433
2434 /* Connect to the HTTP server. */
2435
2436 /* Invoke the 'Duo' (supports IPv6/IPv4) connection call. */
2437 status = nxd_tcp_client_socket_connect(&(client_ptr -> nx_http_client_socket), server_ip,
2438 client_ptr -> nx_http_client_connect_port, wait_option);
2439
2440 /* Check for connection status. */
2441 if (status != NX_SUCCESS)
2442 {
2443
2444 /* Error, unbind the port and return an error. */
2445 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2446 return(status);
2447 }
2448
2449 /* At this point we have a connection setup with an HTTP server! */
2450
2451 /* Allocate a packet for the PUT message. */
2452 if (server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
2453 {
2454 status = nx_packet_allocate(client_ptr -> nx_http_client_packet_pool_ptr, &packet_ptr,
2455 NX_IPv4_TCP_PACKET, wait_option);
2456 }
2457 else
2458 {
2459
2460 status = nx_packet_allocate(client_ptr -> nx_http_client_packet_pool_ptr, &packet_ptr,
2461 NX_IPv6_TCP_PACKET, wait_option);
2462 }
2463
2464 /* Check allocation status. */
2465 if (status != NX_SUCCESS)
2466 {
2467
2468 /* Error, unbind the port and return an error. */
2469 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2470 return(status);
2471 }
2472
2473 /* Build the PUT request. */
2474 nx_packet_data_append(packet_ptr, "PUT ", 4,
2475 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2476
2477 /* Determine if this is a root directory based URI string. */
2478 if (resource[0] != '/')
2479 {
2480
2481 /* Then check if this another website e.g. begins with http and has a colon. */
2482 if (
2483 ((resource[0] == 'h') || (resource[0] == 'H')) &&
2484 ((resource[1] == 't') || (resource[1] == 'T')) &&
2485 ((resource[2] == 't') || (resource[2] == 'T')) &&
2486 ((resource[3] == 'p') || (resource[3] == 'P')) &&
2487 (resource[4] == ':')
2488 )
2489 {
2490
2491 /* Yes, ok to send this string as is. */
2492 }
2493 else
2494 {
2495
2496 /* This URI is a root directory based file but it needs a leading / character. */
2497 nx_packet_data_append(packet_ptr, "/", 1, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2498 }
2499 }
2500
2501 /* (Else the URI begins with a '/' and is ok to send as is.) */
2502
2503 /* Place the resource in the header. */
2504 nx_packet_data_append(packet_ptr, resource, resource_length,
2505 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2506
2507 /* Place the HTTP version in the header. */
2508 nx_packet_data_append(packet_ptr, " HTTP/1.0", 9,
2509 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2510
2511 /* Place the end of line character in the header. */
2512 nx_packet_data_append(packet_ptr, crlf, 2,
2513 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2514
2515 /* Determine if basic authentication is required. */
2516 if ((username) && (password))
2517 {
2518
2519 /* Yes, attempt to build basic authentication. */
2520 nx_packet_data_append(packet_ptr, "Authorization: Basic ", 21,
2521 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2522
2523 /* Encode and append the "name:password" into next. */
2524
2525 /* Place the name and password in a single string. */
2526
2527 /* Copy the name into the merged string. */
2528 memcpy(string1, username, username_length); /* Use case of memcpy is verified. */
2529
2530 /* Insert the colon. */
2531 string1[username_length] = ':';
2532
2533 /* Copy the password into the merged string. */
2534 memcpy(&string1[username_length + 1], password, password_length); /* Use case of memcpy is verified. */
2535
2536 /* Make combined string NULL terminated. */
2537 string1[username_length + password_length + 1] = NX_NULL;
2538
2539 /* Now encode the username:password string. */
2540 _nx_utility_base64_encode((UCHAR *)string1, username_length + password_length + 1, (UCHAR *)string2, sizeof(string2), &string2_length);
2541 nx_packet_data_append(packet_ptr, string2, string2_length,
2542 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2543 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2544 }
2545
2546 /* Now build the content-type entry. */
2547 nx_packet_data_append(packet_ptr, "Content-Type: ", 14,
2548 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2549 string1_length = _nx_http_client_type_get(resource, string1);
2550 nx_packet_data_append(packet_ptr, string1, string1_length, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2551 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2552
2553 /* Now build the content-length entry. */
2554 nx_packet_data_append(packet_ptr, "Content-Length: ", 16,
2555 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2556 string1_length = _nx_http_client_number_convert(total_bytes, string1);
2557 nx_packet_data_append(packet_ptr, string1, string1_length, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2558 nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2559
2560 /* Place an extra cr/lf to signal the end of the HTTP header. */
2561 nx_packet_data_append(packet_ptr, crlf, 2,
2562 client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER);
2563
2564 /* Now send the packet to the HTTP server. */
2565 status = nx_tcp_socket_send(&(client_ptr -> nx_http_client_socket), packet_ptr, wait_option);
2566
2567 /* Determine if the send was successful. */
2568 if (status != NX_SUCCESS)
2569 {
2570
2571 /* No, send was not successful. */
2572
2573 /* Release the packet. */
2574 nx_packet_release(packet_ptr);
2575
2576 /* Disconnect and unbind the socket. */
2577 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
2578 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2579
2580 /* Return an error. */
2581 return(status);
2582 }
2583
2584 /* Store the total number of bytes to send. */
2585 client_ptr -> nx_http_client_total_transfer_bytes = total_bytes;
2586 client_ptr -> nx_http_client_actual_bytes_transferred = 0;
2587
2588 /* Enter the PUT state. */
2589 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_PUT;
2590
2591 /* Return success to the caller. */
2592 return(NX_SUCCESS);
2593 }
2594
2595
2596 /**************************************************************************/
2597 /* */
2598 /* FUNCTION RELEASE */
2599 /* */
2600 /* _nxe_http_client_put_packet PORTABLE C */
2601 /* 6.1 */
2602 /* AUTHOR */
2603 /* */
2604 /* Yuxin Zhou, Microsoft Corporation */
2605 /* */
2606 /* DESCRIPTION */
2607 /* */
2608 /* This function checks for errors in the HTTP client put packet call. */
2609 /* */
2610 /* */
2611 /* INPUT */
2612 /* */
2613 /* client_ptr Pointer to HTTP client */
2614 /* packet_ptr Resource data packet pointer */
2615 /* wait_option Suspension option */
2616 /* */
2617 /* OUTPUT */
2618 /* */
2619 /* status Completion status */
2620 /* */
2621 /* CALLS */
2622 /* */
2623 /* _nx_http_client_put_packet Actual client put packet call */
2624 /* */
2625 /* CALLED BY */
2626 /* */
2627 /* Application Code */
2628 /* */
2629 /* RELEASE HISTORY */
2630 /* */
2631 /* DATE NAME DESCRIPTION */
2632 /* */
2633 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2634 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2635 /* resulting in version 6.1 */
2636 /* */
2637 /**************************************************************************/
_nxe_http_client_put_packet(NX_HTTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,ULONG wait_option)2638 UINT _nxe_http_client_put_packet(NX_HTTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
2639 {
2640
2641 UINT status;
2642
2643
2644 /* Check for invalid input pointers. */
2645 if ((client_ptr == NX_NULL) || (client_ptr -> nx_http_client_id != NXD_HTTP_CLIENT_ID) ||
2646 (packet_ptr == NX_NULL))
2647 return(NX_PTR_ERROR);
2648
2649 /* Check for appropriate caller. */
2650 NX_THREADS_ONLY_CALLER_CHECKING
2651
2652 /* Ensure there is enough room for the TCP packet header. */
2653 if ((packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start) < NX_TCP_PACKET)
2654 {
2655
2656 /* Return an invalid packet error. */
2657 return(NX_INVALID_PACKET);
2658 }
2659
2660 /* Call actual PUT data routine. */
2661 status = _nx_http_client_put_packet(client_ptr, packet_ptr, wait_option);
2662
2663 /* Return completion status. */
2664 return(status);
2665 }
2666
2667
2668 /**************************************************************************/
2669 /* */
2670 /* FUNCTION RELEASE */
2671 /* */
2672 /* _nx_http_client_put_packet PORTABLE C */
2673 /* 6.1 */
2674 /* AUTHOR */
2675 /* */
2676 /* Yuxin Zhou, Microsoft Corporation */
2677 /* */
2678 /* DESCRIPTION */
2679 /* */
2680 /* This function processes a packet of resource data associated with */
2681 /* the previous PUT request. */
2682 /* */
2683 /* */
2684 /* INPUT */
2685 /* */
2686 /* client_ptr Pointer to HTTP client */
2687 /* packet_ptr Resource data packet pointer */
2688 /* wait_option Suspension option */
2689 /* */
2690 /* OUTPUT */
2691 /* */
2692 /* status Completion status */
2693 /* */
2694 /* CALLS */
2695 /* */
2696 /* nx_packet_release Release the packet */
2697 /* nx_tcp_client_socket_unbind Unbind the client socket */
2698 /* nx_tcp_socket_disconnect Disconnect form Server */
2699 /* nx_tcp_socket_receive Receive response from Server */
2700 /* nx_tcp_socket_send Send resource data packet */
2701 /* */
2702 /* CALLED BY */
2703 /* */
2704 /* Application Code */
2705 /* */
2706 /* RELEASE HISTORY */
2707 /* */
2708 /* DATE NAME DESCRIPTION */
2709 /* */
2710 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2711 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2712 /* resulting in version 6.1 */
2713 /* */
2714 /**************************************************************************/
_nx_http_client_put_packet(NX_HTTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,ULONG wait_option)2715 UINT _nx_http_client_put_packet(NX_HTTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, ULONG wait_option)
2716 {
2717
2718 NX_PACKET *response_packet_ptr;
2719 CHAR *buffer_ptr;
2720 UINT length;
2721 UINT status;
2722
2723
2724 /* First, check and see if the client instance is still in the PUT state. */
2725 if (client_ptr -> nx_http_client_state != NX_HTTP_CLIENT_STATE_PUT)
2726 {
2727
2728 /* Client not ready, return error. */
2729 return(NX_HTTP_NOT_READY);
2730 }
2731
2732 /* Next, check and see if there is a response from the Server. */
2733 status = nx_tcp_socket_receive(&(client_ptr -> nx_http_client_socket), &response_packet_ptr, NX_NO_WAIT);
2734
2735 /* Check for an early response from the Server. */
2736 if (status == NX_SUCCESS)
2737 {
2738
2739 /* This is an error condition since the Server should not respond until the PUT is complete. */
2740
2741 /* Setup pointer to server response. */
2742 buffer_ptr = (CHAR *) response_packet_ptr -> nx_packet_prepend_ptr;
2743
2744 /* Determine if it is an authentication error. */
2745 if (((buffer_ptr + 11) < (CHAR *)response_packet_ptr -> nx_packet_append_ptr) &&
2746 (buffer_ptr[9] == '4') && (buffer_ptr[10] == '0') && (buffer_ptr[11] == '1'))
2747 {
2748
2749 /* Inform caller of an authentication error. */
2750 status = NX_HTTP_AUTHENTICATION_ERROR;
2751 }
2752 else
2753 {
2754
2755 /* Inform caller of general Server failure. */
2756 status = NX_HTTP_INCOMPLETE_PUT_ERROR;
2757 }
2758
2759 /* Release the packet. */
2760 nx_packet_release(response_packet_ptr);
2761
2762 /* Disconnect and unbind the socket. */
2763 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
2764 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2765
2766 /* Return to the READY state. */
2767 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
2768
2769 /* Return error to caller. */
2770 return(status);
2771 }
2772
2773 /* Otherwise, determine if the packet length fits in the available bytes to send. */
2774 if (packet_ptr -> nx_packet_length >
2775 (client_ptr -> nx_http_client_total_transfer_bytes - client_ptr -> nx_http_client_actual_bytes_transferred))
2776 {
2777
2778 /* Request doesn't fit into the remaining transfer window. */
2779 return(NX_HTTP_BAD_PACKET_LENGTH);
2780 }
2781
2782 /* Remember the packet length. */
2783 length = packet_ptr -> nx_packet_length;
2784
2785 /* Now send the packet out. */
2786 status = nx_tcp_socket_send(&(client_ptr -> nx_http_client_socket), packet_ptr, wait_option);
2787
2788 /* Determine if the send was successful. */
2789 if (status != NX_SUCCESS)
2790 {
2791
2792 /* No, send was not successful. */
2793
2794 /* Release the packet. */
2795 nx_packet_release(packet_ptr);
2796
2797 /* Disconnect and unbind the socket. */
2798 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
2799 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2800
2801 /* Return to the READY state. */
2802 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
2803
2804 /* Return an error. */
2805 return(status);
2806 }
2807
2808 /* Otherwise, update the actual bytes transferred. */
2809 client_ptr -> nx_http_client_actual_bytes_transferred = client_ptr -> nx_http_client_actual_bytes_transferred + length;
2810
2811 /* Are we finished? */
2812 if (client_ptr -> nx_http_client_total_transfer_bytes > client_ptr -> nx_http_client_actual_bytes_transferred)
2813 {
2814
2815 /* No, we are not finished so just return success to the caller. */
2816 return(NX_SUCCESS);
2817 }
2818
2819 /* We are finished sending the PUT data. Now wait for a response from the Server. */
2820 status = nx_tcp_socket_receive(&(client_ptr -> nx_http_client_socket), &response_packet_ptr, wait_option);
2821
2822 if (status != NX_SUCCESS)
2823 {
2824 /* Disconnect and unbind the socket. */
2825 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
2826 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2827
2828 /* Return to the READY state. */
2829 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
2830
2831 /* Return status to caller. */
2832 return(status);
2833 }
2834
2835
2836 /* Setup pointer to server response. */
2837 buffer_ptr = (CHAR *) response_packet_ptr -> nx_packet_prepend_ptr;
2838
2839 /* Determine if the request was successful. */
2840 if (((buffer_ptr + 9) >= (CHAR *) response_packet_ptr -> nx_packet_append_ptr) ||
2841 (buffer_ptr[9] != '2'))
2842 {
2843
2844 /* Inform caller of a successful completion. */
2845 status = NX_HTTP_REQUEST_UNSUCCESSFUL_CODE;
2846 }
2847
2848 /* Release the packet. */
2849 nx_packet_release(response_packet_ptr);
2850
2851 /* Disconnect and unbind the socket. */
2852 nx_tcp_socket_disconnect(&(client_ptr -> nx_http_client_socket), wait_option);
2853 nx_tcp_client_socket_unbind(&(client_ptr -> nx_http_client_socket));
2854
2855 /* Return to the READY state. */
2856 client_ptr -> nx_http_client_state = NX_HTTP_CLIENT_STATE_READY;
2857
2858 /* Return status to caller. */
2859 return(status);
2860 }
2861
2862
2863 /**************************************************************************/
2864 /* */
2865 /* FUNCTION RELEASE */
2866 /* */
2867 /* _nx_http_client_type_get PORTABLE C */
2868 /* 6.1 */
2869 /* AUTHOR */
2870 /* */
2871 /* Yuxin Zhou, Microsoft Corporation */
2872 /* */
2873 /* DESCRIPTION */
2874 /* */
2875 /* This function derives the type of the resource. */
2876 /* */
2877 /* INPUT */
2878 /* */
2879 /* name Name string */
2880 /* http_type_string Destination HTTP type string */
2881 /* */
2882 /* OUTPUT */
2883 /* */
2884 /* Size Number of bytes in string */
2885 /* */
2886 /* CALLS */
2887 /* */
2888 /* None */
2889 /* */
2890 /* CALLED BY */
2891 /* */
2892 /* _nx_http_client_put_start_extended Start the PUT process */
2893 /* */
2894 /* RELEASE HISTORY */
2895 /* */
2896 /* DATE NAME DESCRIPTION */
2897 /* */
2898 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2899 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2900 /* resulting in version 6.1 */
2901 /* */
2902 /**************************************************************************/
_nx_http_client_type_get(CHAR * name,CHAR * http_type_string)2903 UINT _nx_http_client_type_get(CHAR *name, CHAR *http_type_string)
2904 {
2905
2906 UINT i;
2907
2908
2909 /* First find the end of the string. */
2910 i = 0;
2911 while (name[i] != (CHAR) NX_NULL)
2912 {
2913 i++;
2914 }
2915
2916 /* Now look backwards to find the last period that signals the
2917 file extension. */
2918 while ((i) && (name[i] != '.'))
2919 {
2920 i--;
2921 }
2922
2923 /* Position forward again, past the period. */
2924 i++;
2925
2926 /* Now see what HTTP file type to return. */
2927
2928 /* Check for .txt file extension. */
2929 if (((name[i] == 't') || (name[i] == 'T')) &&
2930 ((name[i+1] == 'x') || (name[i+1] == 'X')) &&
2931 ((name[i+2] == 't') || (name[i+2] == 'T')))
2932 {
2933
2934 /* Yes, we have a plain text file. */
2935 http_type_string[0] = 't';
2936 http_type_string[1] = 'e';
2937 http_type_string[2] = 'x';
2938 http_type_string[3] = 't';
2939 http_type_string[4] = '/';
2940 http_type_string[5] = 'p';
2941 http_type_string[6] = 'l';
2942 http_type_string[7] = 'a';
2943 http_type_string[8] = 'i';
2944 http_type_string[9] = 'n';
2945
2946 /* Return the size of the HTTP ASCII type string. */
2947 return(10);
2948 }
2949
2950 /* Check for .htm[l] file extension. */
2951 else if (((name[i] == 'h') || (name[i] == 'H')) &&
2952 ((name[i+1] == 't') || (name[i+1] == 'T')) &&
2953 ((name[i+2] == 'm') || (name[i+2] == 'M')))
2954 {
2955
2956 /* Yes, we have an HTML text file. */
2957 http_type_string[0] = 't';
2958 http_type_string[1] = 'e';
2959 http_type_string[2] = 'x';
2960 http_type_string[3] = 't';
2961 http_type_string[4] = '/';
2962 http_type_string[5] = 'h';
2963 http_type_string[6] = 't';
2964 http_type_string[7] = 'm';
2965 http_type_string[8] = 'l';
2966
2967 /* Return the size of the HTTP ASCII type string. */
2968 return(9);
2969 }
2970
2971 /* Check for .gif file extension. */
2972 else if (((name[i] == 'g') || (name[i] == 'G')) &&
2973 ((name[i+1] == 'i') || (name[i+1] == 'I')) &&
2974 ((name[i+2] == 'f') || (name[i+2] == 'F')))
2975 {
2976
2977 /* Yes, we have a GIF image file. */
2978 http_type_string[0] = 'i';
2979 http_type_string[1] = 'm';
2980 http_type_string[2] = 'a';
2981 http_type_string[3] = 'g';
2982 http_type_string[4] = 'e';
2983 http_type_string[5] = '/';
2984 http_type_string[6] = 'g';
2985 http_type_string[7] = 'i';
2986 http_type_string[8] = 'f';
2987
2988 /* Return the size of the HTTP ASCII type string. */
2989 return(9);
2990 }
2991
2992 /* Check for .xbm file extension. */
2993 else if (((name[i] == 'x') || (name[i] == 'X')) &&
2994 ((name[i+1] == 'b') || (name[i+1] == 'B')) &&
2995 ((name[i+2] == 'm') || (name[i+2] == 'M')))
2996 {
2997
2998 /* Yes, we have a x-xbitmap image file. */
2999 http_type_string[0] = 'i';
3000 http_type_string[1] = 'm';
3001 http_type_string[2] = 'a';
3002 http_type_string[3] = 'g';
3003 http_type_string[4] = 'e';
3004 http_type_string[5] = '/';
3005 http_type_string[6] = 'x';
3006 http_type_string[7] = '-';
3007 http_type_string[8] = 'x';
3008 http_type_string[9] = 'b';
3009 http_type_string[10] = 'i';
3010 http_type_string[11] = 't';
3011 http_type_string[12] = 'm';
3012 http_type_string[13] = 'a';
3013 http_type_string[14] = 'p';
3014
3015 /* Return the size of the HTTP ASCII type string. */
3016 return(15);
3017 }
3018
3019 /* Default to plain text. */
3020 else
3021 {
3022
3023 /* Default to plain text. */
3024 http_type_string[0] = 't';
3025 http_type_string[1] = 'e';
3026 http_type_string[2] = 'x';
3027 http_type_string[3] = 't';
3028 http_type_string[4] = '/';
3029 http_type_string[5] = 'p';
3030 http_type_string[6] = 'l';
3031 http_type_string[7] = 'a';
3032 http_type_string[8] = 'i';
3033 http_type_string[9] = 'n';
3034
3035 /* Return the size of the HTTP ASCII type string. */
3036 return(10);
3037 }
3038 }
3039
3040
3041 /**************************************************************************/
3042 /* */
3043 /* FUNCTION RELEASE */
3044 /* */
3045 /* _nx_http_client_content_length_get PORTABLE C */
3046 /* 6.1 */
3047 /* AUTHOR */
3048 /* */
3049 /* Yuxin Zhou, Microsoft Corporation */
3050 /* */
3051 /* DESCRIPTION */
3052 /* */
3053 /* This function returns the content length of the supplied HTTP */
3054 /* response packet. If the packet is no content or the packet is */
3055 /* invalid, a zero is returned. */
3056 /* */
3057 /* */
3058 /* INPUT */
3059 /* */
3060 /* packet_ptr Pointer to HTTP request packet*/
3061 /* */
3062 /* OUTPUT */
3063 /* */
3064 /* length Length of content */
3065 /* */
3066 /* CALLS */
3067 /* */
3068 /* None */
3069 /* */
3070 /* CALLED BY */
3071 /* */
3072 /* _nx_http_client_get_start Start the GET operation */
3073 /* */
3074 /* RELEASE HISTORY */
3075 /* */
3076 /* DATE NAME DESCRIPTION */
3077 /* */
3078 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3079 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3080 /* resulting in version 6.1 */
3081 /* */
3082 /**************************************************************************/
_nx_http_client_content_length_get(NX_PACKET * packet_ptr)3083 UINT _nx_http_client_content_length_get(NX_PACKET *packet_ptr)
3084 {
3085
3086 UINT length;
3087 CHAR *buffer_ptr;
3088 UINT found = NX_FALSE;
3089
3090
3091 /* Default the content length to an invalid value. */
3092 length = 0;
3093
3094 /* Setup pointer to buffer. */
3095 buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
3096
3097 /* Find the "Content-length:" token first. */
3098 while ((buffer_ptr+14) < (CHAR *)packet_ptr -> nx_packet_append_ptr)
3099 {
3100
3101 /* Check for the Content-length token. */
3102 if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) &&
3103 ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) &&
3104 ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) &&
3105 ((*(buffer_ptr+3) == 't') || (*(buffer_ptr+3) == 'T')) &&
3106 ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) &&
3107 ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) &&
3108 ((*(buffer_ptr+6) == 't') || (*(buffer_ptr+6) == 'T')) &&
3109 (*(buffer_ptr+7) == '-') &&
3110 ((*(buffer_ptr+8) == 'l') || (*(buffer_ptr+8) == 'L')) &&
3111 ((*(buffer_ptr+9) == 'e') || (*(buffer_ptr+9) == 'E')) &&
3112 ((*(buffer_ptr+10) == 'n') || (*(buffer_ptr+10) == 'N')) &&
3113 ((*(buffer_ptr+11) == 'g') || (*(buffer_ptr+11) == 'G')) &&
3114 ((*(buffer_ptr+12) == 't') || (*(buffer_ptr+12) == 'T')) &&
3115 ((*(buffer_ptr+13) == 'h') || (*(buffer_ptr+13) == 'H')) &&
3116 (*(buffer_ptr+14) == ':'))
3117 {
3118
3119 /* Yes, found content-length token. */
3120 found = NX_TRUE;
3121
3122 /* Move past the Content-Length: field. Exit the loop. */
3123 buffer_ptr += 15;
3124 break;
3125 }
3126
3127 /* Move the pointer up to the next character. */
3128 buffer_ptr++;
3129 }
3130
3131 /* Check if found the content-length token. */
3132 if (found != NX_TRUE)
3133 {
3134
3135 /* No, return an invalid length indicating a bad HTTP packet. */
3136 return(length);
3137 }
3138
3139 /* Now skip over white space. */
3140 while ((buffer_ptr < (CHAR *)packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' '))
3141 {
3142 buffer_ptr++;
3143 }
3144
3145 /* Now convert the length into a numeric value. */
3146 while ((buffer_ptr < (CHAR *)packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr >= '0') && (*buffer_ptr <= '9'))
3147 {
3148
3149 /* Update the content length. */
3150 length = length * 10;
3151 length = length + (((UINT) (*buffer_ptr)) - 0x30);
3152
3153 /* Move the buffer pointer forward. */
3154 buffer_ptr++;
3155 }
3156
3157 /* Determine if the content length was picked up properly. */
3158 if ((buffer_ptr >= (CHAR *)packet_ptr -> nx_packet_append_ptr) ||
3159 ((*buffer_ptr != ' ') && (*buffer_ptr != (CHAR)13)))
3160 {
3161
3162 /* Error, set the length to zero. */
3163 length = 0;
3164 }
3165
3166 /* Return the length to the caller. */
3167 return(length);
3168 }
3169
3170
3171 /**************************************************************************/
3172 /* */
3173 /* FUNCTION RELEASE */
3174 /* */
3175 /* _nx_http_client_calculate_content_offset PORTABLE C */
3176 /* 6.1 */
3177 /* AUTHOR */
3178 /* */
3179 /* Yuxin Zhou, Microsoft Corporation */
3180 /* */
3181 /* DESCRIPTION */
3182 /* */
3183 /* This function calculates the byte offset to the start of the */
3184 /* HTTP request content area. This area immediately follows the HTTP */
3185 /* request header (which ends with a blank line). */
3186 /* */
3187 /* */
3188 /* INPUT */
3189 /* */
3190 /* packet_ptr Pointer to request packet */
3191 /* */
3192 /* OUTPUT */
3193 /* */
3194 /* Byte Offset (0 implies no content) */
3195 /* */
3196 /* CALLS */
3197 /* */
3198 /* None */
3199 /* */
3200 /* CALLED BY */
3201 /* */
3202 /* _nx_http_client_get_start Start GET processing */
3203 /* */
3204 /* RELEASE HISTORY */
3205 /* */
3206 /* DATE NAME DESCRIPTION */
3207 /* */
3208 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3209 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3210 /* resulting in version 6.1 */
3211 /* */
3212 /**************************************************************************/
_nx_http_client_calculate_content_offset(NX_PACKET * packet_ptr)3213 UINT _nx_http_client_calculate_content_offset(NX_PACKET *packet_ptr)
3214 {
3215
3216 UINT offset;
3217 CHAR *buffer_ptr;
3218
3219
3220 /* Default the content offset to zero. */
3221 offset = 0;
3222
3223 /* Setup pointer to buffer. */
3224 buffer_ptr = (CHAR *) packet_ptr -> nx_packet_prepend_ptr;
3225
3226 /* Find the "cr,lf,cr,lf" token. */
3227 while (((buffer_ptr+3) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0))
3228 {
3229
3230 /* Check for the <cr,lf,cr,lf> token. This signals a blank line, which also
3231 specifies the start of the content. */
3232 if ((*buffer_ptr == (CHAR) 13) &&
3233 (*(buffer_ptr+1) == (CHAR) 10) &&
3234 (*(buffer_ptr+2) == (CHAR) 13) &&
3235 (*(buffer_ptr+3) == (CHAR) 10))
3236 {
3237
3238 /* Adjust the offset. */
3239 offset = offset + 4;
3240 break;
3241 }
3242
3243 /* Move the pointer up to the next character. */
3244 buffer_ptr++;
3245
3246 /* Increment the offset. */
3247 offset++;
3248 }
3249
3250 /* Return the offset to the caller. */
3251 return(offset);
3252 }
3253
3254
3255 /**************************************************************************/
3256 /* */
3257 /* FUNCTION RELEASE */
3258 /* */
3259 /* _nx_http_client_number_convert PORTABLE C */
3260 /* 6.1 */
3261 /* AUTHOR */
3262 /* */
3263 /* Yuxin Zhou, Microsoft Corporation */
3264 /* */
3265 /* DESCRIPTION */
3266 /* */
3267 /* This function converts a number into an ASCII string. */
3268 /* */
3269 /* INPUT */
3270 /* */
3271 /* number Unsigned integer number */
3272 /* string Destination string */
3273 /* */
3274 /* OUTPUT */
3275 /* */
3276 /* Size Number of bytes in string */
3277 /* (0 implies an error) */
3278 /* */
3279 /* CALLS */
3280 /* */
3281 /* None */
3282 /* */
3283 /* CALLED BY */
3284 /* */
3285 /* _nx_http_client_get_start_extended Start GET processing */
3286 /* _nx_http_client_put_start_extended Start PUT processing */
3287 /* */
3288 /* RELEASE HISTORY */
3289 /* */
3290 /* DATE NAME DESCRIPTION */
3291 /* */
3292 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3293 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3294 /* resulting in version 6.1 */
3295 /* */
3296 /**************************************************************************/
_nx_http_client_number_convert(UINT number,CHAR * string)3297 UINT _nx_http_client_number_convert(UINT number, CHAR *string)
3298 {
3299
3300 UINT j;
3301 UINT digit;
3302 UINT size;
3303
3304
3305 /* Default string to return '0'. */
3306 string[0] = '0';
3307
3308 /* Initialize counters. */
3309 size = 0;
3310
3311 /* Loop to convert the number to ASCII. */
3312 while ((size < 10) && (number))
3313 {
3314
3315 /* Shift the current digits over one. */
3316 for (j = size; j != 0; j--)
3317 {
3318
3319 /* Move each digit over one place. */
3320 string[j] = string[j-1];
3321 }
3322
3323 /* Compute the next decimal digit. */
3324 digit = number % 10;
3325
3326 /* Update the input number. */
3327 number = number / 10;
3328
3329 /* Store the new digit in ASCII form. */
3330 string[0] = (CHAR) (digit + 0x30);
3331
3332 /* Increment the size. */
3333 size++;
3334 }
3335
3336 /* Make the string NULL terminated. */
3337 string[size] = (CHAR) NX_NULL;
3338
3339 /* Determine if there is an overflow error. */
3340 if (number)
3341 {
3342
3343 /* Error, return bad values to user. */
3344 size = 0;
3345 string[0] = '0';
3346 }
3347
3348 /* Return size to caller. */
3349 return(size);
3350 }
3351