1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Component */
17 /** */
18 /** HTTP Proxy Protocol */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22 #define NX_SOURCE_CODE
23
24
25 #include "nx_ip.h"
26 #include "nx_ipv6.h"
27 #include "nx_packet.h"
28 #include "nx_tcp.h"
29 #include "nx_http_proxy_client.h"
30
31 #ifdef NX_ENABLE_HTTP_PROXY
32 #define NX_HTTP_CRLF "\r\n"
33 #define NX_HTTP_CRLF_SIZE 2
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _nxe_http_proxy_client_enable PORTABLE C */
40 /* 6.2.0 */
41 /* AUTHOR */
42 /* */
43 /* Wenhui Xie, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function checks for errors in the HTTP Proxy enable call. */
48 /* */
49 /* */
50 /* INPUT */
51 /* */
52 /* ip_ptr Pointer to IP instance */
53 /* proxy_server_ip IP address of proxy server */
54 /* proxy_server_port Port of proxy server */
55 /* username Pointer to username */
56 /* username_length Length of username */
57 /* password Pointer to password */
58 /* password_length Length of password */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* status Completion status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _nx_http_proxy_client_enable Actual HTTP Proxy enable call */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Application Code */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */
77 /* */
78 /**************************************************************************/
_nxe_http_proxy_client_enable(NX_IP * ip_ptr,NXD_ADDRESS * proxy_server_ip,UINT proxy_server_port,UCHAR * username,UINT username_length,UCHAR * password,UINT password_length)79 UINT _nxe_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port,
80 UCHAR *username, UINT username_length, UCHAR *password, UINT password_length)
81 {
82 UINT status;
83
84 /* Check for invalid input pointers. */
85 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
86 (proxy_server_ip == NX_NULL) || (proxy_server_port == 0) ||
87 ((username == NX_NULL) && (username_length != 0)) ||
88 ((password == NX_NULL) && (password_length != 0)))
89 {
90 return(NX_PTR_ERROR);
91 }
92
93 /* Check the length of username and password. */
94 if ((username_length > NX_HTTP_PROXY_MAX_USERNAME) ||
95 (password_length > NX_HTTP_PROXY_MAX_PASSWORD))
96 {
97 return(NX_SIZE_ERROR);
98 }
99
100 /* Check that the server IP address version is either IPv4 or IPv6. */
101 if ((proxy_server_ip -> nxd_ip_version != NX_IP_VERSION_V4) &&
102 (proxy_server_ip -> nxd_ip_version != NX_IP_VERSION_V6))
103 {
104
105 return(NX_IP_ADDRESS_ERROR);
106 }
107
108 #ifndef NX_DISABLE_IPV4
109 /* Check for a valid server IP address if the server_ip is version IPv4. */
110 if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
111 {
112 if (((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_A_MASK) != NX_IP_CLASS_A_TYPE) &&
113 ((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_B_MASK) != NX_IP_CLASS_B_TYPE) &&
114 ((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_C_MASK) != NX_IP_CLASS_C_TYPE))
115 {
116 return(NX_IP_ADDRESS_ERROR);
117 }
118 }
119 #endif /* !NX_DISABLE_IPV4 */
120
121 /* Check for an invalid port. */
122 if (((ULONG)proxy_server_port) > (ULONG)NX_MAX_PORT)
123 {
124 return(NX_INVALID_PORT);
125 }
126
127 /* Call actual HTTP proxy enable function. */
128 status = _nx_http_proxy_client_enable(ip_ptr, proxy_server_ip, proxy_server_port, username,
129 username_length, password, password_length);
130
131 /* Return completion status. */
132 return(status);
133 }
134
135 /**************************************************************************/
136 /* */
137 /* FUNCTION RELEASE */
138 /* */
139 /* _nx_http_proxy_client_enable PORTABLE C */
140 /* 6.2.0 */
141 /* AUTHOR */
142 /* */
143 /* Wenhui Xie, Microsoft Corporation */
144 /* */
145 /* DESCRIPTION */
146 /* */
147 /* This function enables the HTTP Proxy and sets the information of */
148 /* the HTTP Proxy server. */
149 /* */
150 /* */
151 /* INPUT */
152 /* */
153 /* ip_ptr Pointer to IP instance */
154 /* proxy_server_ip IP address of proxy server */
155 /* proxy_server_port Port of proxy server */
156 /* username Pointer to username */
157 /* username_length Length of username */
158 /* password Pointer to password */
159 /* password_length Length of password */
160 /* */
161 /* OUTPUT */
162 /* */
163 /* status Completion status */
164 /* */
165 /* CALLS */
166 /* */
167 /* COPY_IPV6_ADDRESS Copy IPv6 address */
168 /* */
169 /* CALLED BY */
170 /* */
171 /* Application Code */
172 /* */
173 /* RELEASE HISTORY */
174 /* */
175 /* DATE NAME DESCRIPTION */
176 /* */
177 /* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */
178 /* */
179 /**************************************************************************/
_nx_http_proxy_client_enable(NX_IP * ip_ptr,NXD_ADDRESS * proxy_server_ip,UINT proxy_server_port,UCHAR * username,UINT username_length,UCHAR * password,UINT password_length)180 UINT _nx_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port,
181 UCHAR *username, UINT username_length, UCHAR *password, UINT password_length)
182 {
183
184 UINT status;
185 UCHAR string[NX_HTTP_PROXY_MAX_USERNAME + NX_HTTP_PROXY_MAX_PASSWORD + 2];
186
187 /* Set the IP address of HTTP proxy. */
188 ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_version = proxy_server_ip -> nxd_ip_version;
189
190 #ifndef NX_DISABLE_IPV4
191 if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V4)
192 {
193
194 /* Copy the IPv4 address */
195 ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_address.v4 = proxy_server_ip -> nxd_ip_address.v4;
196 }
197 #endif /* !NX_DISABLE_IPV4 */
198
199 #ifdef FEATURE_NX_IPV6
200 if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V6)
201 {
202
203 /* Copy the IPv6 address */
204 COPY_IPV6_ADDRESS(proxy_server_ip -> nxd_ip_address.v6,
205 ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_address.v6);
206 }
207 #endif /* FEATURE_NX_IPV6 */
208
209 /* Set the port of HTTP proxy. */
210 ip_ptr -> nx_ip_http_proxy_port = (USHORT)proxy_server_port;
211
212 /* Determine if basic authentication is required. */
213 if ((username_length) && (password_length))
214 {
215
216 /* Encode the "name:password" into authentication buffer. */
217
218 /* Place the name and password in a single string. */
219
220 /* Copy the name into the merged string. */
221 memcpy(string, username, username_length); /* Use case of memcpy is verified. */
222
223 /* Insert the colon. */
224 string[username_length] = ':';
225
226 /* Copy the password into the merged string. */
227 memcpy(&string[username_length + 1], password, password_length); /* Use case of memcpy is verified. */
228
229 /* Make combined string NULL terminated. */
230 string[username_length + password_length + 1] = NX_NULL;
231
232 /* Now encode the username:password string. */
233 status = _nx_utility_base64_encode((UCHAR *)string, username_length + password_length + 1,
234 (UCHAR *)ip_ptr -> nx_ip_http_proxy_authentication,
235 sizeof(ip_ptr -> nx_ip_http_proxy_authentication),
236 &(ip_ptr -> nx_ip_http_proxy_authentication_length));
237
238 /* Check status. */
239 if (status)
240 {
241 return(status);
242 }
243 }
244 else
245 {
246 ip_ptr -> nx_ip_http_proxy_authentication_length = 0;
247 }
248
249 /* Set HTTP proxy as enabled. */
250 ip_ptr -> nx_ip_http_proxy_enable = NX_TRUE;
251
252 return(NX_SUCCESS);
253 }
254
255 /**************************************************************************/
256 /* */
257 /* FUNCTION RELEASE */
258 /* */
259 /* _nx_http_proxy_client_initialize PORTABLE C */
260 /* 6.2.0 */
261 /* AUTHOR */
262 /* */
263 /* Wenhui Xie, Microsoft Corporation */
264 /* */
265 /* DESCRIPTION */
266 /* */
267 /* This function initializes the state of HTTP Proxy and stores the */
268 /* the information of remote server. */
269 /* */
270 /* */
271 /* INPUT */
272 /* */
273 /* socket_ptr Pointer to TCP client socket */
274 /* server_ip IP address of remote server */
275 /* server_port Port of remote server */
276 /* */
277 /* OUTPUT */
278 /* */
279 /* NONE */
280 /* */
281 /* CALLS */
282 /* */
283 /* COPY_IPV6_ADDRESS Copy IPv6 address */
284 /* */
285 /* CALLED BY */
286 /* */
287 /* _nxd_tcp_client_socket_connect Connect TCP client socket */
288 /* */
289 /* RELEASE HISTORY */
290 /* */
291 /* DATE NAME DESCRIPTION */
292 /* */
293 /* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */
294 /* */
295 /**************************************************************************/
_nx_http_proxy_client_initialize(NX_TCP_SOCKET * socket_ptr,NXD_ADDRESS ** server_ip,UINT * server_port)296 VOID _nx_http_proxy_client_initialize(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS **server_ip, UINT *server_port)
297 {
298
299 NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
300
301 /* Store the server's IP and port for sending CONNECT request later. */
302 socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_version = (*server_ip) -> nxd_ip_version;
303
304 #ifndef NX_DISABLE_IPV4
305 if ((*server_ip) -> nxd_ip_version == NX_IP_VERSION_V4)
306 {
307
308 /* Copy the IPv4 address */
309 socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_address.v4 = (*server_ip) -> nxd_ip_address.v4;
310 }
311 #endif /* !NX_DISABLE_IPV4 */
312
313 #ifdef FEATURE_NX_IPV6
314 if ((*server_ip) -> nxd_ip_version == NX_IP_VERSION_V6)
315 {
316
317 /* Copy the IPv6 address */
318 COPY_IPV6_ADDRESS((*server_ip) -> nxd_ip_address.v6,
319 socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_address.v6);
320 }
321 #endif /* FEATURE_NX_IPV6 */
322
323 socket_ptr -> nx_tcp_socket_original_server_port = *server_port;
324
325 /* Replace the peer info with HTTP proxy's IP and port. */
326 *server_ip = &(ip_ptr -> nx_ip_http_proxy_ip_address);
327 *server_port = ip_ptr -> nx_ip_http_proxy_port;
328
329 /* Initialize the state. */
330 socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_INIT;
331 socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL;
332 }
333
334 /**************************************************************************/
335 /* */
336 /* FUNCTION RELEASE */
337 /* */
338 /* _nx_http_proxy_client_connect PORTABLE C */
339 /* 6.2.0 */
340 /* AUTHOR */
341 /* */
342 /* Wenhui Xie, Microsoft Corporation */
343 /* */
344 /* DESCRIPTION */
345 /* */
346 /* This function sends HTTP request to connect with HTTP Proxy server. */
347 /* */
348 /* */
349 /* INPUT */
350 /* */
351 /* socket_ptr Pointer to TCP client socket */
352 /* */
353 /* OUTPUT */
354 /* */
355 /* status Completion status */
356 /* */
357 /* CALLS */
358 /* */
359 /* _nx_tcp_socket_disconnect Disconnect TCP socket */
360 /* _nx_utility_uint_to_string Convert integer to string */
361 /* _nx_utility_base64_encode Base64 encode */
362 /* _nx_packet_allocate Allocate packet */
363 /* _nx_packet_data_append Append packet data */
364 /* _nx_packet_release Release packet */
365 /* */
366 /* CALLED BY */
367 /* */
368 /* _nx_tcp_socket_state_syn_received Process SYN RECEIVED state */
369 /* _nx_tcp_socket_state_syn_sent Process SYN SENT state */
370 /* */
371 /* RELEASE HISTORY */
372 /* */
373 /* DATE NAME DESCRIPTION */
374 /* */
375 /* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */
376 /* */
377 /**************************************************************************/
_nx_http_proxy_client_connect(NX_TCP_SOCKET * socket_ptr)378 UINT _nx_http_proxy_client_connect(NX_TCP_SOCKET *socket_ptr)
379 {
380
381 UINT status;
382 NX_PACKET *packet_ptr;
383 NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
384 NX_PACKET_POOL *pool_ptr = ip_ptr -> nx_ip_default_packet_pool;
385 CHAR *ip_string_ptr;
386 UINT ip_string_len = 0;
387 CHAR *port_string_ptr;
388 UINT port_string_len = 0;
389 UINT temp_length = 0;
390 NXD_ADDRESS *server_ip = &(socket_ptr -> nx_tcp_socket_original_server_ip);
391 UINT port = socket_ptr -> nx_tcp_socket_original_server_port;
392
393
394 /* Check the IP version of the server. */
395 if (server_ip -> nxd_ip_version != NX_IP_VERSION_V4)
396 {
397
398 /* Only IPv4 is supported. */
399 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
400 return(NX_NOT_SUPPORTED);
401 }
402
403 /* Allocate packet. */
404 if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4)
405 {
406 status = _nx_packet_allocate(pool_ptr, &packet_ptr, NX_IPv4_TCP_PACKET, NX_NO_WAIT);
407 }
408 else
409 {
410 status = _nx_packet_allocate(pool_ptr, &packet_ptr, NX_IPv6_TCP_PACKET, NX_NO_WAIT);
411 }
412
413 /* Check status. */
414 if (status)
415 {
416 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
417 return(status);
418 }
419
420 /* Convert IP address and port to string. */
421 /* Use the buffer before prepend pointer to store the IP and port string. */
422 ip_string_ptr = (CHAR *)packet_ptr -> nx_packet_data_start;
423 temp_length = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start);
424
425 /* Convert IP address to string. */
426 ip_string_len = _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 24), 10, ip_string_ptr, temp_length);
427 ip_string_ptr[ip_string_len++] = '.';
428 ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 16), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
429 ip_string_ptr[ip_string_len++] = '.';
430 ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 8), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
431 ip_string_ptr[ip_string_len++] = '.';
432 ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
433
434 /* Convert port to string. */
435 port_string_ptr = ip_string_ptr + ip_string_len;
436 port_string_len = _nx_utility_uint_to_string(port, 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len);
437
438 /* HTTP proxy opening handshake message format:
439 CONNECT IP address:port HTTP/1.1
440 Host: IP address
441 */
442
443 /* Build the CONNECT request: CONNECT + Request URI(IP address:port) + HTTP version. */
444 status = _nx_packet_data_append(packet_ptr, "CONNECT ", sizeof("CONNECT ") - 1, pool_ptr, NX_NO_WAIT);
445 status += _nx_packet_data_append(packet_ptr, ip_string_ptr, ip_string_len, pool_ptr, NX_NO_WAIT);
446 status += _nx_packet_data_append(packet_ptr, ":", sizeof(":") - 1, pool_ptr, NX_NO_WAIT);
447 status += _nx_packet_data_append(packet_ptr, port_string_ptr, port_string_len, pool_ptr, NX_NO_WAIT);
448 status += _nx_packet_data_append(packet_ptr, " HTTP/1.1", sizeof(" HTTP/1.1") - 1, pool_ptr, NX_NO_WAIT);
449 status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
450
451 /* Place the Host in the header. */
452 status += _nx_packet_data_append(packet_ptr, "Host: ", sizeof("Host: ") - 1, pool_ptr, NX_NO_WAIT);
453 status += _nx_packet_data_append(packet_ptr, ip_string_ptr, ip_string_len, pool_ptr, NX_NO_WAIT);
454 status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
455
456 /* Check status. */
457 if (status)
458 {
459 _nx_packet_release(packet_ptr);
460 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
461 return(NX_NOT_SUCCESSFUL);
462 }
463
464 /* Determine if basic authentication is required. */
465 if (ip_ptr -> nx_ip_http_proxy_authentication_length)
466 {
467
468 /* Yes, attempt to build basic authentication. */
469 status = _nx_packet_data_append(packet_ptr, "Proxy-authorization: Basic ", 27, pool_ptr, NX_NO_WAIT);
470
471 /* Check status. */
472 if (status)
473 {
474 _nx_packet_release(packet_ptr);
475 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
476 return(status);
477 }
478
479 /* Append authentication string. */
480 status = _nx_packet_data_append(packet_ptr, ip_ptr -> nx_ip_http_proxy_authentication,
481 ip_ptr -> nx_ip_http_proxy_authentication_length, pool_ptr, NX_NO_WAIT);
482 status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
483
484 /* Check status. */
485 if (status)
486 {
487 _nx_packet_release(packet_ptr);
488 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
489 return(NX_NOT_SUCCESSFUL);
490 }
491 }
492
493 /* Append CRLF. */
494 status = _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT);
495
496 /* Check status. */
497 if (status)
498 {
499 _nx_packet_release(packet_ptr);
500 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
501 return(status);
502 }
503
504 /* Send out the packet. */
505 status = _nx_tcp_socket_send(socket_ptr, packet_ptr, NX_NO_WAIT);
506
507 /* Check status. */
508 if (status)
509 {
510 _nx_packet_release(packet_ptr);
511 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
512 return(status);
513 }
514
515 /* Update HTTP Proxy state. */
516 socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_CONNECTING;
517
518 /* Return successful completion. */
519 return(NX_SUCCESS);
520 }
521
522 /**************************************************************************/
523 /* */
524 /* FUNCTION RELEASE */
525 /* */
526 /* _nx_http_proxy_client_connect_response_process PORTABLE C */
527 /* 6.2.0 */
528 /* AUTHOR */
529 /* */
530 /* Wenhui Xie, Microsoft Corporation */
531 /* */
532 /* DESCRIPTION */
533 /* */
534 /* This function processes the CONNECT response from HTTP Proxy server.*/
535 /* */
536 /* */
537 /* INPUT */
538 /* */
539 /* socket_ptr Pointer to TCP client socket */
540 /* */
541 /* OUTPUT */
542 /* */
543 /* status Completion status */
544 /* */
545 /* CALLS */
546 /* */
547 /* _nx_tcp_socket_receive Receive TCP socket */
548 /* _nx_tcp_socket_disconnect Disconnect TCP socket */
549 /* _nx_tcp_socket_thread_resume Resume the suspended thread */
550 /* _nx_packet_data_append Append packet data */
551 /* _nx_packet_release Release packet */
552 /* */
553 /* CALLED BY */
554 /* */
555 /* _nx_tcp_socket_packet_process Process socket packet */
556 /* */
557 /* RELEASE HISTORY */
558 /* */
559 /* DATE NAME DESCRIPTION */
560 /* */
561 /* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */
562 /* */
563 /**************************************************************************/
_nx_http_proxy_client_connect_response_process(NX_TCP_SOCKET * socket_ptr)564 UINT _nx_http_proxy_client_connect_response_process(NX_TCP_SOCKET *socket_ptr)
565 {
566 NX_PACKET *head_packet_ptr = socket_ptr -> nx_tcp_socket_http_proxy_header_packet;
567 NX_PACKET *new_packet_ptr;
568 CHAR *buffer_ptr;
569 UINT status = NX_SUCCESS;
570 NX_PACKET *work_ptr;
571 UINT crlf_found = 0;
572 NX_PACKET *tmp_ptr;
573 NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
574 NX_PACKET_POOL *pool_ptr = ip_ptr -> nx_ip_default_packet_pool;
575
576
577 if (head_packet_ptr == NX_NULL)
578 {
579
580 /* Wait for a response from HTTP proxy. */
581 status = _nx_tcp_socket_receive(socket_ptr, &head_packet_ptr, NX_NO_WAIT);
582
583 /* Check the return status. */
584 if (status == NX_NO_PACKET)
585 {
586 return(NX_IN_PROGRESS);
587 }
588 else if (status != NX_SUCCESS)
589 {
590
591 /* Return an error condition. */
592 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
593 return(status);
594 }
595
596 socket_ptr -> nx_tcp_socket_http_proxy_header_packet = head_packet_ptr;
597 }
598
599 crlf_found = 0;
600 work_ptr = head_packet_ptr;
601
602 /* Build a pointer to the buffer area. */
603 buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr;
604
605 do
606 {
607
608 /* See if there is a blank line present in the buffer. */
609 /* Search the buffer for a cr/lf pair. */
610 while ((buffer_ptr < (CHAR *) work_ptr -> nx_packet_append_ptr) &&
611 (crlf_found < 4))
612 {
613 if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13))
614 {
615
616 /* Found CR. */
617 crlf_found++;
618 }
619 else if((crlf_found & 1) && (*buffer_ptr == (CHAR)10))
620 {
621
622 /* Found LF. */
623 crlf_found++;
624 }
625 else
626 {
627
628 /* Reset the CRLF marker. */
629 crlf_found = 0;
630 }
631
632 /* Move the buffer pointer up. */
633 buffer_ptr++;
634 }
635
636 if (crlf_found == 4)
637 {
638
639 /* Yes, we have found the end of the HTTP response header. */
640 break;
641 }
642
643 /* Determine if the packet has already overflowed into another packet. */
644
645 #ifndef NX_DISABLE_PACKET_CHAIN
646
647 if (work_ptr -> nx_packet_next != NX_NULL)
648 {
649
650 /* Get the next packet in the chain. */
651 work_ptr = work_ptr -> nx_packet_next;
652 buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr;
653 }
654 else
655 #endif
656 {
657 /* Receive another packet from the HTTP proxy. */
658 status = _nx_tcp_socket_receive(socket_ptr, &new_packet_ptr, NX_NO_WAIT);
659
660 /* Check the return status. */
661 if (status == NX_NO_PACKET)
662 {
663 return(NX_IN_PROGRESS);
664 }
665 else if (status != NX_SUCCESS)
666 {
667 break;
668 }
669
670 /* Successfully received another packet. Its contents now need to be placed in the head packet. */
671 tmp_ptr = new_packet_ptr;
672
673 #ifndef NX_DISABLE_PACKET_CHAIN
674 while (tmp_ptr)
675 #endif /* NX_DISABLE_PACKET_CHAIN */
676 {
677
678 /* Copy the contents of the current packet into the head packet. */
679 status = _nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr,
680 (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr),
681 pool_ptr, NX_NO_WAIT);
682
683 #ifndef NX_DISABLE_PACKET_CHAIN
684
685 /* Determine if an error occurred. */
686 if (status != NX_SUCCESS)
687 {
688 break;
689 }
690 else
691 {
692 tmp_ptr = tmp_ptr -> nx_packet_next;
693 }
694 #endif /* NX_DISABLE_PACKET_CHAIN */
695 }
696
697 /* Release the new packet. */
698 _nx_packet_release(new_packet_ptr);
699 }
700
701 } while (status == NX_SUCCESS);
702
703 if (status)
704 {
705
706 /* Return an error condition. */
707 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
708 return(status);
709 }
710
711 /* Check the packet length and response code. */
712 if ((head_packet_ptr -> nx_packet_append_ptr - head_packet_ptr -> nx_packet_prepend_ptr < 12) ||
713 (*(head_packet_ptr -> nx_packet_prepend_ptr + 9) != '2'))
714 {
715
716 /* If error occurs, disconnect the TCP connection. */
717 _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT);
718 return(NX_NOT_SUCCESSFUL);
719 }
720
721 /* Update the HTTP Proxy state. */
722 socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_CONNECTED;
723
724 /* Release the packet. */
725 _nx_packet_release(head_packet_ptr);
726 socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL;
727
728 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
729
730 /* Is a connection completion callback registered with the TCP socket? */
731 if (socket_ptr -> nx_tcp_establish_notify)
732 {
733
734 /* Call the application's establish callback function. */
735 (socket_ptr -> nx_tcp_establish_notify)(socket_ptr);
736 }
737 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
738
739 /* Determine if we need to wake a thread suspended on the connection. */
740 if (socket_ptr -> nx_tcp_socket_connect_suspended_thread)
741 {
742
743 /* Resume the suspended thread. */
744 _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS);
745 }
746
747 /* Return status. */
748 return(NX_SUCCESS);
749 }
750
751 /**************************************************************************/
752 /* */
753 /* FUNCTION RELEASE */
754 /* */
755 /* _nx_http_proxy_client_cleanup PORTABLE C */
756 /* 6.2.0 */
757 /* AUTHOR */
758 /* */
759 /* Wenhui Xie, Microsoft Corporation */
760 /* */
761 /* DESCRIPTION */
762 /* */
763 /* This function cleans up the HTTP Proxy by resetting the state and */
764 /* release the processing packet. */
765 /* */
766 /* */
767 /* INPUT */
768 /* */
769 /* socket_ptr Pointer to TCP client socket */
770 /* */
771 /* OUTPUT */
772 /* */
773 /* status Completion status */
774 /* */
775 /* CALLS */
776 /* */
777 /* _nx_packet_release Release packet */
778 /* */
779 /* CALLED BY */
780 /* */
781 /* _nx_tcp_socket_block_cleanup Clean up the socket block */
782 /* */
783 /* RELEASE HISTORY */
784 /* */
785 /* DATE NAME DESCRIPTION */
786 /* */
787 /* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */
788 /* */
789 /**************************************************************************/
_nx_http_proxy_client_cleanup(NX_TCP_SOCKET * socket_ptr)790 VOID _nx_http_proxy_client_cleanup(NX_TCP_SOCKET *socket_ptr)
791 {
792
793 /* Clear the HTTP Proxy connection state. */
794 socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_INIT;
795
796 /* Release HTTP Proxy header packet. */
797 if (socket_ptr -> nx_tcp_socket_http_proxy_header_packet)
798 {
799 _nx_packet_release(socket_ptr -> nx_tcp_socket_http_proxy_header_packet);
800 socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL;
801 }
802 }
803 #endif /* NX_ENABLE_HTTP_PROXY */