* Send a HTTP CONNECT request to a remote proxy. * The proxy is given by "backend", the target server * is contained in the "forward" member of "backend". */
| 3556 | * is contained in the "forward" member of "backend". |
| 3557 | */ |
| 3558 | static apr_status_t send_http_connect(proxy_conn_rec *backend, |
| 3559 | server_rec *s) |
| 3560 | { |
| 3561 | int status; |
| 3562 | apr_size_t nbytes; |
| 3563 | apr_size_t left; |
| 3564 | int complete = 0; |
| 3565 | char buffer[HUGE_STRING_LEN]; |
| 3566 | char drain_buffer[HUGE_STRING_LEN]; |
| 3567 | remote_connect_info *connect_info = backend->forward; |
| 3568 | int len = 0; |
| 3569 | |
| 3570 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00948) |
| 3571 | "CONNECT: sending the CONNECT request for %s:%d " |
| 3572 | "to the remote proxy %pI (%s)", |
| 3573 | connect_info->target_host, connect_info->target_port, |
| 3574 | backend->addr, backend->hostname); |
| 3575 | /* Create the CONNECT request */ |
| 3576 | nbytes = apr_snprintf(buffer, sizeof(buffer), |
| 3577 | "CONNECT %s:%d HTTP/1.0" CRLF, |
| 3578 | connect_info->target_host, connect_info->target_port); |
| 3579 | /* Add proxy authorization from the configuration, or initial |
| 3580 | * request if necessary */ |
| 3581 | if (connect_info->proxy_auth != NULL) { |
| 3582 | nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes, |
| 3583 | "Proxy-Authorization: %s" CRLF, |
| 3584 | connect_info->proxy_auth); |
| 3585 | } |
| 3586 | /* Set a reasonable agent and send everything */ |
| 3587 | nbytes += apr_snprintf(buffer + nbytes, sizeof(buffer) - nbytes, |
| 3588 | "Proxy-agent: %s" CRLF CRLF, |
| 3589 | ap_get_server_banner()); |
| 3590 | ap_xlate_proto_to_ascii(buffer, nbytes); |
| 3591 | apr_socket_send(backend->sock, buffer, &nbytes); |
| 3592 | |
| 3593 | /* Receive the whole CONNECT response */ |
| 3594 | left = sizeof(buffer) - 1; |
| 3595 | /* Read until we find the end of the headers or run out of buffer */ |
| 3596 | do { |
| 3597 | nbytes = left; |
| 3598 | status = apr_socket_recv(backend->sock, buffer + len, &nbytes); |
| 3599 | len += nbytes; |
| 3600 | left -= nbytes; |
| 3601 | buffer[len] = '\0'; |
| 3602 | if (strstr(buffer + len - nbytes, CRLF_ASCII CRLF_ASCII) != NULL) { |
| 3603 | ap_xlate_proto_from_ascii(buffer, len); |
| 3604 | complete = 1; |
| 3605 | break; |
| 3606 | } |
| 3607 | } while (status == APR_SUCCESS && left > 0); |
| 3608 | /* Drain what's left */ |
| 3609 | if (!complete) { |
| 3610 | nbytes = sizeof(drain_buffer) - 1; |
| 3611 | while (status == APR_SUCCESS && nbytes) { |
| 3612 | status = apr_socket_recv(backend->sock, drain_buffer, &nbytes); |
| 3613 | drain_buffer[nbytes] = '\0'; |
| 3614 | nbytes = sizeof(drain_buffer) - 1; |
| 3615 | if (strstr(drain_buffer, CRLF_ASCII CRLF_ASCII) != NULL) { |
no test coverage detected