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