diff -urN httpd-2.1.6-alpha/modules/proxy/mod_proxy_connect.c apache-httpd-2.1/modules/proxy/mod_proxy_connect.c --- httpd-2.1.6-alpha/modules/proxy/mod_proxy_connect.c 2005-02-17 14:02:16.000000000 -0800 +++ apache-httpd-2.1/modules/proxy/mod_proxy_connect.c 2005-08-16 17:29:49.000000000 -0700 @@ -79,11 +79,15 @@ { apr_pool_t *p = r->pool; apr_socket_t *sock; + conn_rec *c = r->connection; + conn_rec *backconn; + apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc); + apr_status_t err, rv; apr_size_t i, o, nbytes; char buffer[HUGE_STRING_LEN]; - apr_socket_t *client_socket = ap_get_module_config(r->connection->conn_config, &core_module); - int failed; + apr_socket_t *client_socket = ap_get_module_config(c->conn_config, &core_module); + int failed, rc; apr_pollset_t *pollset; apr_pollfd_t pollfd; const apr_pollfd_t *signalled; @@ -209,7 +213,29 @@ * We add the NULL filter to the stack to do this... */ r->output_filters = NULL; - r->connection->output_filters = NULL; + + backconn = ap_run_create_connection(c->pool, r->server, sock, + c->id, c->sbh, c->bucket_alloc); + if (!backconn) { + /* peer reset */ + ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, + "proxy: an error occurred creating a new connection " + "to %pI (%s)", connect_addr, connectname); + apr_socket_close(sock); + return HTTP_INTERNAL_SERVER_ERROR; + } + ap_proxy_ssl_disable(backconn); + rc = ap_run_pre_connection(backconn, sock); + if (rc != OK && rc != DONE) { + backconn->aborted = 1; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: CONNECT: pre_connection setup failed (%d)", rc); + return HTTP_INTERNAL_SERVER_ERROR; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: CONNECT: connection complete to %pI (%s)", + connect_addr, connectname); /* If we are connecting through a remote proxy, we need to pass @@ -220,12 +246,11 @@ */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: sending the CONNECT request to the remote proxy"); - nbytes = apr_snprintf(buffer, sizeof(buffer), - "CONNECT %s HTTP/1.0" CRLF, r->uri); - apr_socket_send(sock, buffer, &nbytes); - nbytes = apr_snprintf(buffer, sizeof(buffer), - "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); - apr_socket_send(sock, buffer, &nbytes); + ap_fprintf(backconn->output_filters, bb, + "CONNECT %s HTTP/1.0" CRLF, r->uri); + ap_fprintf(backconn->output_filters, bb, + "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); + ap_fflush(backconn->output_filters, bb); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, @@ -233,11 +258,12 @@ nbytes = apr_snprintf(buffer, sizeof(buffer), "HTTP/1.0 200 Connection Established" CRLF); ap_xlate_proto_to_ascii(buffer, nbytes); - apr_socket_send(client_socket, buffer, &nbytes); + ap_fwrite(c->output_filters, bb, buffer, nbytes); nbytes = apr_snprintf(buffer, sizeof(buffer), "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); ap_xlate_proto_to_ascii(buffer, nbytes); - apr_socket_send(client_socket, buffer, &nbytes); + ap_fwrite(c->output_filters, bb, buffer, nbytes); + ap_fflush(c->output_filters, bb); #if 0 /* This is safer code, but it doesn't work yet. I'm leaving it * here so that I can fix it later. @@ -302,31 +328,34 @@ "proxy: CONNECT: sock was set"); #endif nbytes = sizeof(buffer); - rv = apr_socket_recv(sock, buffer, &nbytes); - if (rv == APR_SUCCESS) { - o = 0; - i = nbytes; - while(i > 0) - { - nbytes = i; - /* This is just plain wrong. No module should ever write directly - * to the client. For now, this works, but this is high on my list of - * things to fix. The correct line is: - * if ((nbytes = ap_rwrite(buffer + o, nbytes, r)) < 0) - * rbb - */ - rv = apr_socket_send(client_socket, buffer + o, &nbytes); - if (rv != APR_SUCCESS) - break; - o += nbytes; - i -= nbytes; - } - } - else + apr_brigade_cleanup(bb); + rv = ap_get_brigade(backconn->input_filters, bb, + AP_MODE_READBYTES, APR_NONBLOCK_READ, + nbytes); + if (APR_STATUS_IS_EAGAIN(rv)) { + rv = APR_SUCCESS; + } else if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "proxy: CONNECT: error on backconn " + "- ap_get_brigade"); break; + } else { + rv = ap_pass_brigade(c->output_filters, bb); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: CONNECT: error on backconn " + "- ap_pass_brigade"); + break; + } + ap_fflush(c->output_filters, bb); + } } - else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) + if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { + rv = APR_EPIPE; + ap_log_rerror(APLOG_MARK, APLOG_NOTICE, rv, r, + "proxy: CONNECT: err/hup on backconn"); break; + } } else if (cur->desc.s == client_socket) { pollevent = cur->rtnevents; @@ -336,32 +365,47 @@ "proxy: CONNECT: client was set"); #endif nbytes = sizeof(buffer); - rv = apr_socket_recv(client_socket, buffer, &nbytes); + apr_brigade_cleanup(bb); + rv = ap_get_brigade(c->input_filters, bb, + AP_MODE_READBYTES, APR_NONBLOCK_READ, + nbytes); if (rv == APR_SUCCESS) { - o = 0; - i = nbytes; + i = nbytes; #ifdef DEBUGGING ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: CONNECT: read %d from client", i); #endif - while(i > 0) - { - nbytes = i; - rv = apr_socket_send(sock, buffer + o, &nbytes); - if (rv != APR_SUCCESS) - break; - o += nbytes; - i -= nbytes; - } - } - else + rv = ap_pass_brigade(backconn->output_filters, bb); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: CONNECT: error on client " + "ap_pass_brigade"); + break; + } + ap_fflush(backconn->output_filters, bb); + } + else if (APR_STATUS_IS_EAGAIN(rv)) { + rv = APR_SUCCESS; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "proxy: CONNECT: error on client " + "- ap_get_brigade"); break; + } } - else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) + if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP)) { + rv = APR_EPIPE; + ap_log_rerror(APLOG_MARK, APLOG_NOTICE, rv, r, + "proxy: CONNECT: err/hup on client socket"); break; + } } - else + else { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, + "proxy: CONNECT: unknown socket in pollset"); break; + } } if (rv != APR_SUCCESS) { break; @@ -377,7 +421,7 @@ * Close the socket and clean up */ - apr_socket_close(sock); + ap_lingering_close(backconn); return OK; }