diff -ur httpd-2.1.2-alpha/modules/proxy/proxy_connect.c httpd-2.1.2-proxyfix/modules/proxy/proxy_connect.c --- httpd-2.1.2-alpha/modules/proxy/proxy_connect.c 2004-11-21 10:50:36.000000000 -0800 +++ httpd-2.1.2-proxyfix/modules/proxy/proxy_connect.c 2005-01-21 14:56:40.000000000 -0800 @@ -78,10 +78,14 @@ { 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); + apr_socket_t *client_socket = ap_get_module_config(c->conn_config, &core_module); int failed; apr_pollset_t *pollset; apr_pollfd_t pollfd; @@ -208,7 +212,23 @@ * 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_DEBUG, 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); + ap_run_pre_connection(backconn, sock); + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: connection complete to %pI (%s)", + connect_addr, connectname); /* If we are connecting through a remote proxy, we need to pass @@ -219,12 +239,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, @@ -232,11 +251,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. @@ -301,31 +321,31 @@ "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; - } + apr_brigade_cleanup(bb); + rv = ap_get_brigade(backconn->input_filters, bb, + AP_MODE_READBYTES, APR_NONBLOCK_READ, + nbytes); + if (rv != APR_SUCCESS) { +#ifdef DEBUGGING + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "proxy: CONNECT: error ap_get_brigade"); +#endif + break; } - else - break; + rv = ap_pass_brigade(c->output_filters, bb); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: CONNECT: error 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; @@ -335,32 +355,38 @@ "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; #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; - } - } + rv = ap_pass_brigade(backconn->output_filters, bb); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "proxy: CONNECT: error ap_pass_brigade()"); + break; + } + ap_fflush(backconn->output_filters, bb); + } else 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 sock"); break; + } } - else + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: CONNECT: unknown socket in pollset"); break; + } } if (rv != APR_SUCCESS) { break; @@ -376,7 +402,7 @@ * Close the socket and clean up */ - apr_socket_close(sock); + ap_lingering_close(backconn); return OK; }