On 09/10/2009 01:56 AM, [email protected] wrote: > Author: minfrin > Date: Wed Sep 9 23:56:29 2009 > New Revision: 813178 > > URL: http://svn.apache.org/viewvc?rev=813178&view=rev > Log: > mod_proxy_connect: The connect method doesn't work if the client is > connecting to the apache proxy through an ssl socket. Fixed. > PR: 29744. > Submitted by: Brad Boyer, Mark Cave-Ayland, Julian Gilbey, Fabrice Durand, > David Gence, Tim Dodge, Per Gunnar Hans, Emmanuel Elango, Kevin Croft, > Rudolf Cardinal > > Modified: > httpd/httpd/trunk/CHANGES > httpd/httpd/trunk/modules/proxy/mod_proxy_connect.c >
> Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_connect.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_connect.c?rev=813178&r1=813177&r2=813178&view=diff > ============================================================================== > --- httpd/httpd/trunk/modules/proxy/mod_proxy_connect.c (original) > +++ httpd/httpd/trunk/modules/proxy/mod_proxy_connect.c Wed Sep 9 23:56:29 > 2009 > @@ -69,6 +71,50 @@ > return OK; > } > > +/* read available data (in blocks of CONN_BLKSZ) from c_i and copy to c_o */ > +static int proxy_connect_transfer(request_rec *r, conn_rec *c_i, conn_rec > *c_o, > + apr_bucket_brigade *bb, char *name) > +{ > + int rv; > +#ifdef DEBUGGING > + apr_off_t len; > +#endif > + > + do { > + apr_brigade_cleanup(bb); > + rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES, > + APR_NONBLOCK_READ, CONN_BLKSZ); > + if (rv == APR_SUCCESS) { > + if (APR_BRIGADE_EMPTY(bb)) > + break; > +#ifdef DEBUGGING > + len = -1; > + apr_brigade_length(bb, 0, &len); > + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > + "proxy: CONNECT: read %" APR_OFF_T_FMT > + " bytes from %s", len, name); > +#endif > + rv = ap_pass_brigade(c_o->output_filters, bb); > + if (rv == APR_SUCCESS) { > + ap_fflush(c_o->output_filters, bb); Why do flushing here? At most I would think that would be needed after the loop. > + } else { > + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, > + "proxy: CONNECT: error on %s - ap_pass_brigade", > + name); > + } > + } else if (!APR_STATUS_IS_EAGAIN(rv)) { > + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, > + "proxy: CONNECT: error on %s - ap_get_brigade", > + name); > + } > + } while (rv == APR_SUCCESS); > + > + if (APR_STATUS_IS_EAGAIN(rv)) { > + rv = APR_SUCCESS; > + } > + return rv; > +} > + > /* CONNECT handler */ > static int proxy_connect_handler(request_rec *r, proxy_worker *worker, > proxy_server_conf *conf, > @@ -203,18 +251,57 @@ > } > } > > + /* setup polling for connection */ > + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > + "proxy: CONNECT: setting up poll()"); > + > + if ((rv = apr_pollset_create(&pollset, 2, r->pool, 0)) != APR_SUCCESS) { > + apr_socket_close(sock); > + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, > + "proxy: CONNECT: error apr_pollset_create()"); > + return HTTP_INTERNAL_SERVER_ERROR; > + } > + > + /* Add client side to the poll */ > + pollfd.p = r->pool; > + pollfd.desc_type = APR_POLL_SOCKET; > + pollfd.reqevents = APR_POLLIN; > + pollfd.desc.s = client_socket; > + pollfd.client_data = NULL; > + apr_pollset_add(pollset, &pollfd); > + > + /* Add the server side to the poll */ > + pollfd.desc.s = sock; > + apr_pollset_add(pollset, &pollfd); > + Why moving this code block up and not leaving it where it was? > /* > * Step Three: Send the Request > * > * Send the HTTP/1.1 CONNECT request to the remote server > */ > > - /* we are acting as a tunnel - the output filter stack should > - * be completely empty, because when we are done here we are done > completely. > - * 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_rerror(APLOG_MARK, APLOG_INFO, 0, r, > + "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_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > + "proxy: CONNECT: pre_connection setup failed (%d)", rc); > + return HTTP_INTERNAL_SERVER_ERROR; > + } > + > + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > + "proxy: CONNECT: connection complete to %pI (%s)", > + connect_addr, connectname); Why do we now use a connection? Why don't we stick to writing to the socket directly for the backend connection. In this direction we clearly do no want to filter anything. > > > /* If we are connecting through a remote proxy, we need to pass > @@ -396,7 +418,9 @@ > * Close the socket and clean up > */ > > - apr_socket_close(sock); > + ap_lingering_close(backconn); > + > + c->aborted = 1; This is certainly wrong. Why is this done? > > return OK; > } > In general I would really appreciate to fix the style before committing such patches especially if a patch contains that much style violations as this one. Regards RĂ¼diger
