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 */