From: Jim Jagielski Date: Fri, 18 Apr 2014 15:28:41 +0000 (+0000) Subject: Merge r1587036, r1587040, r1587053, r1587654 from trunk: X-Git-Tag: 2.4.10~306 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3051222c5b86f4892603d73d5fb8c930876b6003;p=apache Merge r1587036, r1587040, r1587053, r1587654 from trunk: *) mod_proxy_wstunnel: Don't pool backend websockets connections, because we need to handshake every time. PR 55890. [Eric Covener] actually remove mod_reqtimeout, since the util_filter functions involved only manipulate c->input_filters no matter what we pass. We need to make copies of c->input_filters after, not before, it skips over reqtimeout. Note: reqtimeout doesn't really interfere today with normal operation, but this is misleading/confusing when dealing with other wstunnel issues. cleanup wstunnel error handling Submitted By: covener, ylavic, Edward Lu Commited By: covener followup to r1587036. if backend->close is set too early, proxy_util.c will close it right away and then blow away the field. Submitted by: covener Reviewed/backported by: jim git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1588495 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 48003f1212..fa61a0e205 100644 --- a/CHANGES +++ b/CHANGES @@ -49,6 +49,14 @@ Changes with Apache 2.4.10 when the thread/connection relationship changes. (Should be implemented for any third-party async MPMs.) [Jeff Trawick] + *) mod_proxy_wstunnel: Don't issue AH02447 and log a 500 on routine + hangups from websockets origin servers. PR 56299 + [Yann Ylavic, Edward Lu , Eric Covener] + + *) mod_proxy_wstunnel: Don't pool backend websockets connections, + because we need to handshake every time. PR 55890. + [Eric Covener] + *) mod_lua: Redesign how request record table access behaves, in order to utilize the request record from within these tables. [Daniel Gruno] diff --git a/STATUS b/STATUS index eec238a4e1..f06743b154 100644 --- a/STATUS +++ b/STATUS @@ -100,14 +100,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_proxy_wstunnel: wstunnel rollup for connection handling - trunk patch: http://svn.apache.org/r1587036 (set backend->close) - http://svn.apache.org/r1587040 (remove reqtimeout) - http://svn.apache.org/r1587053 (poll fixes / frontend connection close) - http://svn.apache.org/r1587654 (set backend->close) - 2.4.x patch: http://people.apache.org/~covener/patches/httpd-2.4.x-wstunnel.diff - +1: covener, ylavic, jim - * mod_ssl: workaround for SSLCertificateFile in 2.4.8 or later, when used with OpenSSL prior to 0.9.8h and not specifying an SSLCertificateChainFile (PR 56410) diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c index d17eaff640..aa008fa41b 100644 --- a/modules/proxy/mod_proxy_wstunnel.c +++ b/modules/proxy/mod_proxy_wstunnel.c @@ -103,10 +103,12 @@ static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES, APR_NONBLOCK_READ, AP_IOBUFSIZE); if (rv == APR_SUCCESS) { - if (c_o->aborted) + if (c_o->aborted) { return APR_EPIPE; - if (APR_BRIGADE_EMPTY(bb)) + } + if (APR_BRIGADE_EMPTY(bb)) { break; + } #ifdef DEBUGGING len = -1; apr_brigade_length(bb, 0, &len); @@ -130,9 +132,12 @@ static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, } } while (rv == APR_SUCCESS); + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r, "wstunnel_transfer complete"); + if (APR_STATUS_IS_EAGAIN(rv)) { rv = APR_SUCCESS; } + return rv; } @@ -178,7 +183,6 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r, conn_rec *c = r->connection; apr_socket_t *sock = conn->sock; conn_rec *backconn = conn->connection; - int client_error = 0; char *buf; apr_bucket_brigade *header_brigade; apr_bucket *e; @@ -224,7 +228,7 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r, pollfd.p = p; pollfd.desc_type = APR_POLL_SOCKET; - pollfd.reqevents = APR_POLLIN; + pollfd.reqevents = APR_POLLIN | APR_POLLHUP; pollfd.desc.s = sock; pollfd.client_data = NULL; apr_pollset_add(pollset, &pollfd); @@ -232,13 +236,16 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r, pollfd.desc.s = client_socket; apr_pollset_add(pollset, &pollfd); + remove_reqtimeout(c->input_filters); r->output_filters = c->output_filters; r->proto_output_filters = c->output_filters; r->input_filters = c->input_filters; r->proto_input_filters = c->input_filters; - remove_reqtimeout(r->input_filters); + /* This handler should take care of the entire connection; make it so that + * nothing else is attempted on the connection after returning. */ + c->keepalive = AP_CONN_CLOSE; while (1) { /* Infinite loop until error (one side closes the connection) */ if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) @@ -257,38 +264,34 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r, if (cur->desc.s == sock) { pollevent = cur->rtnevents; - if (pollevent & APR_POLLIN) { + if (pollevent & (APR_POLLIN | APR_POLLHUP)) { ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02446) "sock was readable"); rv = proxy_wstunnel_transfer(r, backconn, c, bb, "sock"); - } - else if ((pollevent & APR_POLLERR) - || (pollevent & APR_POLLHUP)) { - rv = APR_EPIPE; - ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02447) - "err/hup on backconn"); + } + else if (pollevent & APR_POLLERR) { + rv = APR_EPIPE; + ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02447) + "error on backconn"); } else { rv = APR_EGENERAL; ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02605) "unknown event on backconn %d", pollevent); } - if (rv != APR_SUCCESS) - client_error = 1; } else if (cur->desc.s == client_socket) { pollevent = cur->rtnevents; - if (pollevent & APR_POLLIN) { + if (pollevent & (APR_POLLIN | APR_POLLHUP)) { ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02448) "client was readable"); rv = proxy_wstunnel_transfer(r, c, backconn, bb, "client"); } - else if ((pollevent & APR_POLLERR) - || (pollevent & APR_POLLHUP)) { + else if (pollevent & APR_POLLERR) { rv = APR_EPIPE; c->aborted = 1; ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02607) - "err/hup on client conn"); + "error on client conn"); } else { rv = APR_EGENERAL; @@ -311,9 +314,6 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "finished with poll() - cleaning up"); - if (client_error) { - return HTTP_INTERNAL_SERVER_ERROR; - } return OK; } @@ -386,7 +386,10 @@ static int proxy_wstunnel_handler(request_rec *r, proxy_worker *worker, if ((status = ap_proxy_connection_create(scheme, backend, c, r->server)) != OK) break; - } + } + + backend->close = 1; /* must be after ap_proxy_determine_connection */ + /* Step Three: Process the Request */ status = ap_proxy_wstunnel_request(p, r, backend, worker, conf, uri, locurl,