From: Yann Ylavic Date: Fri, 24 Sep 2021 10:27:16 +0000 (+0000) Subject: mod_proxy: Restore ap_proxy_transfer_between_connections(). X-Git-Tag: 2.5.0-alpha2-ci-test-only~782 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=074d55133a2a57346af689b63deba206fbf9040e;p=thirdparty%2Fapache%2Fhttpd.git mod_proxy: Restore ap_proxy_transfer_between_connections(). * modules/proxy/mod_proxy.h: Restore the interface of ap_proxy_transfer_between_connections() back to before MMN 20210506.0. Add ap_proxy_tunnel_conn_bytes_in() and ap_proxy_tunnel_conn_bytes_out(). New proxy_tunnel_conn_t typedef'ed from opaque struct proxy_tunnel_conn. * modules/proxy/mod_proxy.h(ap_proxy_tunnel_conn_get_read, ap_proxy_tunnel_conn_get_transferred): Axed/replaced by ap_proxy_tunnel_conn_bytes_in() and ap_proxy_tunnel_conn_bytes_out(). * modules/proxy/proxy_util.c(struct proxy_tunnel_conn): Replace "exchanged" by "bytes_in" and "bytes_out". * modules/proxy/proxy_util.c(proxy_transfer): New helper implementing ap_proxy_transfer_between_connections() and returning both &bytes_in and &bytes_out. * modules/proxy/proxy_util.c(ap_proxy_transfer_between_connections): Now calls proxy_transfer(). * modules/proxy/proxy_util.c(ap_proxy_tunnel_conn_bytes_in, ap_proxy_tunnel_conn_bytes_out): Return tc->bytes_in and tc->bytes_out respectively. * modules/proxy/proxy_util.c(proxy_tunnel_forward): Use proxy_transfer() which updates in->bytes_in, &out->bytes_out. tunnel->replied will be updated in proxy_tunnel_run(). * modules/proxy/proxy_util.c(proxy_tunnel_forward): Fall through the "done" label in any case to set tunnel->replied based on tunnel->client->bytes_out > 0. * modules/proxy/mod_proxy_http.c(ap_proxy_http_process_response): Use ap_proxy_tunnel_conn_bytes_{in,out}() for worker->s->{read,transferred} accounting. * modules/proxy/mod_proxy_http.c(proxy_http_async_finish): Update worker->s->{read,transferred} when async too. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1893594 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 0d88c3f5e5e..7cc2bcb8120 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -682,14 +682,23 @@ * 20210531.4 (2.5.1-dev) Add ap_create_connection * 20210531.5 (2.5.1-dev) Add ap_pre_connection * 20210531.6 (2.5.1-dev) Add proxy_tunnel_conn_t + * 20210924.0 (2.5.1-dev) Restore ap_proxy_transfer_between_connections() + * interface back to before 20210506.0 (that MAJOR bump + * cancelled), axe ap_proxy_tunnel_conn_get_read() + * and ap_proxy_tunnel_conn_get_transferred() and add + * ap_proxy_tunnel_conn_bytes_in() and + * ap_proxy_tunnel_conn_bytes_out() as replacement + * (this MAJOR bump). Overall there is no MAJOR bumb + * for 20210506.0 + 20210924.0, MINOR bump only for + * adding ap_proxy_tunnel_conn_bytes_{in,out}(). */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ #ifndef MODULE_MAGIC_NUMBER_MAJOR -#define MODULE_MAGIC_NUMBER_MAJOR 20210531 +#define MODULE_MAGIC_NUMBER_MAJOR 20210924 #endif -#define MODULE_MAGIC_NUMBER_MINOR 6 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index e9ff6e91b25..76bf74c6766 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -1369,6 +1369,21 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **tunnel, */ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel); +/* + * Number of incoming bytes on the tunnel connection. + * @param tc tunnel connection + * @return number of bytes. + */ +PROXY_DECLARE(apr_off_t) ap_proxy_tunnel_conn_bytes_in( + const proxy_tunnel_conn_t *tc); +/* + * Number of outgoing bytes on the tunnel connection. + * @param tc tunnel connection + * @return number of bytes. + */ +PROXY_DECLARE(apr_off_t) ap_proxy_tunnel_conn_bytes_out( + const proxy_tunnel_conn_t *tc); + /** * Clear the headers referenced by the Connection header from the given * table, and remove the Connection header. @@ -1512,25 +1527,10 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( apr_bucket_brigade *bb_i, apr_bucket_brigade *bb_o, const char *name, - apr_off_t *sent, + int *sent, apr_off_t bsize, int flags); -/* - * returns number of bytes read from the back end tunnel - * @param ptunnel proxy_tunnel_rec use during the tunnelling. - * @return apr_off_t number of bytes read. - */ -PROXY_DECLARE (apr_off_t) ap_proxy_tunnel_conn_get_read( - proxy_tunnel_rec *ptunnel); -/* - * returns number of bytes sent to the back end tunnel - * @param ptunnel proxy_tunnel_rec use during the tunnelling. - * @return apr_off_t number of bytes sent. - */ -PROXY_DECLARE (apr_off_t) ap_proxy_tunnel_conn_get_transferred( - proxy_tunnel_rec *ptunnel); - extern module PROXY_DECLARE_DATA proxy_module; #endif /*MOD_PROXY_H*/ diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 49b7ec4900f..01436b6a2b0 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -306,6 +306,12 @@ static void proxy_http_async_finish(proxy_http_req_t *req) ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, req->r, "proxy %s: finish async", req->proto); + /* Report bytes exchanged by the backend */ + req->backend->worker->s->read += + ap_proxy_tunnel_conn_bytes_in(req->tunnel->origin); + req->backend->worker->s->transferred += + ap_proxy_tunnel_conn_bytes_out(req->tunnel->origin); + proxy_run_detach_backend(req->r, req->backend); ap_proxy_release_connection(req->proto, req->backend, req->r->server); @@ -1541,8 +1547,12 @@ int ap_proxy_http_process_response(proxy_http_req_t *req) r->status = status; } - backend->worker->s->read = backend->worker->s->read + ap_proxy_tunnel_conn_get_read(req->tunnel); - backend->worker->s->transferred = backend->worker->s->transferred + ap_proxy_tunnel_conn_get_transferred(req->tunnel); + /* Report bytes exchanged by the backend */ + backend->worker->s->read += + ap_proxy_tunnel_conn_bytes_in(req->tunnel->origin); + backend->worker->s->transferred += + ap_proxy_tunnel_conn_bytes_out(req->tunnel->origin); + /* We are done with both connections */ r->connection->keepalive = AP_CONN_CLOSE; backend->close = 1; diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 0e9837a1a9c..c06cfe5f262 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -4481,16 +4481,16 @@ PROXY_DECLARE(apr_status_t) ap_proxy_buckets_lifetime_transform(request_rec *r, */ #define PROXY_TRANSFER_MAX_READS 10000 -PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( - request_rec *r, - conn_rec *c_i, - conn_rec *c_o, - apr_bucket_brigade *bb_i, - apr_bucket_brigade *bb_o, - const char *name, - apr_off_t *sent, - apr_off_t bsize, - int flags) +static apr_status_t proxy_transfer(request_rec *r, + conn_rec *c_i, + conn_rec *c_o, + apr_bucket_brigade *bb_i, + apr_bucket_brigade *bb_o, + const char *name, + apr_off_t bsize, + int flags, + apr_off_t *bytes_in, + apr_off_t *bytes_out) { apr_status_t rv; int flush_each = 0; @@ -4516,8 +4516,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( if (rv != APR_SUCCESS) { if (!APR_STATUS_IS_EAGAIN(rv) && !APR_STATUS_IS_EOF(rv)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(03308) - "ap_proxy_transfer_between_connections: " - "error on %s - ap_get_brigade", + "proxy_transfer: error on %s - ap_get_brigade", name); if (rv == APR_INCOMPLETE) { /* Don't return APR_INCOMPLETE, it'd mean "should yield" @@ -4542,13 +4541,16 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( len = -1; apr_brigade_length(bb_i, 0, &len); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03306) - "ap_proxy_transfer_between_connections: " - "read %" APR_OFF_T_FMT - " bytes from %s", len, name); - if (sent && len > 0) { - *sent = *sent + len; + "proxy_transfer: read %" APR_OFF_T_FMT " bytes " + "of %s", len, name); + if (bytes_in && len > 0) { + *bytes_in += len; } ap_proxy_buckets_lifetime_transform(r, bb_i, bb_o); + if (bytes_out && len > 0) { + *bytes_out += len; + } + if (flush_each) { /* * Do not use ap_fflush here since this would cause the flush @@ -4572,8 +4574,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( apr_brigade_cleanup(bb_o); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(03307) - "ap_proxy_transfer_between_connections: " - "error on %s - ap_pass_brigade", + "proxy_transfer: error on %s - ap_pass_brigade", name); flags &= ~AP_PROXY_TRANSFER_FLUSH_AFTER; break; @@ -4585,8 +4586,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( if ((flags & AP_PROXY_TRANSFER_YIELD_PENDING) && ap_filter_should_yield(c_o->output_filters)) { ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, - "ap_proxy_transfer_between_connections: " - "yield (output pending)"); + "proxy_transfer: yield (output pending)"); rv = APR_INCOMPLETE; break; } @@ -4597,8 +4597,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( if ((flags & AP_PROXY_TRANSFER_YIELD_MAX_READS) && ++num_reads > PROXY_TRANSFER_MAX_READS) { ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, - "ap_proxy_transfer_between_connections: " - "yield (max reads)"); + "proxy_transfer: yield (max reads)"); rv = APR_SUCCESS; break; } @@ -4611,7 +4610,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( apr_brigade_cleanup(bb_i); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r, - "ap_proxy_transfer_between_connections complete (%s %pI)", + "proxy_transfer complete (%s %pI)", (c_i == r->connection) ? "to" : "from", (c_i == r->connection) ? c_o->client_addr : c_i->client_addr); @@ -4622,6 +4621,26 @@ PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( return rv; } +PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections( + request_rec *r, + conn_rec *c_i, + conn_rec *c_o, + apr_bucket_brigade *bb_i, + apr_bucket_brigade *bb_o, + const char *name, + int *sent, + apr_off_t bsize, + int flags) +{ + apr_off_t bytes_out = 0; + apr_status_t rv = proxy_transfer(r, c_i, c_o, bb_i, bb_o, name, bsize, + flags, NULL, &bytes_out); + if (sent && bytes_out > 0) { + *sent = 1; + } + return rv; +} + struct proxy_tunnel_conn { /* the other side of the tunnel */ struct proxy_tunnel_conn *other; @@ -4632,18 +4651,22 @@ struct proxy_tunnel_conn { apr_pollfd_t *pfd; apr_bucket_brigade *bb; + apr_off_t bytes_in, + bytes_out; + unsigned int down_in:1, down_out:1; - apr_off_t exchanged; }; -PROXY_DECLARE(apr_off_t) ap_proxy_tunnel_conn_get_read(proxy_tunnel_rec *ptunnel) +PROXY_DECLARE(apr_off_t) ap_proxy_tunnel_conn_bytes_in( + const proxy_tunnel_conn_t *tc) { - return ptunnel->origin->exchanged; + return tc->bytes_in; } -PROXY_DECLARE(apr_off_t) ap_proxy_tunnel_conn_get_transferred(proxy_tunnel_rec *ptunnel) +PROXY_DECLARE(apr_off_t) ap_proxy_tunnel_conn_bytes_out( + const proxy_tunnel_conn_t *tc) { - return ptunnel->client->exchanged; + return tc->bytes_out; } PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **ptunnel, @@ -4773,30 +4796,23 @@ static void del_pollset(apr_pollset_t *pollset, apr_pollfd_t *pfd, } } -static int proxy_tunnel_forward(proxy_tunnel_rec *tunnel, +static int proxy_tunnel_transfer(proxy_tunnel_rec *tunnel, proxy_tunnel_conn_t *in) { proxy_tunnel_conn_t *out = in->other; apr_status_t rv; - apr_off_t sent = 0; ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, tunnel->r, "proxy: %s: %s input ready", tunnel->scheme, in->name); - rv = ap_proxy_transfer_between_connections(tunnel->r, - in->c, out->c, - in->bb, out->bb, - in->name, &sent, - tunnel->read_buf_size, - AP_PROXY_TRANSFER_YIELD_PENDING | - AP_PROXY_TRANSFER_YIELD_MAX_READS); - if (sent && out == tunnel->client) { - tunnel->replied = 1; - } - - in->exchanged = in->exchanged + sent; - + rv = proxy_transfer(tunnel->r, + in->c, out->c, + in->bb, out->bb, + in->name, tunnel->read_buf_size, + AP_PROXY_TRANSFER_YIELD_PENDING | + AP_PROXY_TRANSFER_YIELD_MAX_READS, + &in->bytes_in, &out->bytes_out); if (rv != APR_SUCCESS) { if (APR_STATUS_IS_INCOMPLETE(rv)) { /* Pause POLLIN while waiting for POLLOUT on the other @@ -4830,7 +4846,7 @@ static int proxy_tunnel_forward(proxy_tunnel_rec *tunnel, PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) { - int rc = OK; + int status = OK, rc; request_rec *r = tunnel->r; apr_pollset_t *pollset = tunnel->pollset; proxy_tunnel_conn_t *client = tunnel->client, @@ -4865,14 +4881,14 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) "(client=%hx, origin=%hx)", scheme, client->pfd->reqevents, origin->pfd->reqevents); - rc = HTTP_GATEWAY_TIME_OUT; + status = HTTP_GATEWAY_TIME_OUT; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10214) "proxy: %s: polling failed", scheme); - rc = HTTP_INTERNAL_SERVER_ERROR; + status = HTTP_INTERNAL_SERVER_ERROR; } - return rc; + goto done; } ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, r, APLOGNO(10215) @@ -4891,7 +4907,8 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) && pfd->desc.s != origin->pfd->desc.s) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10222) "proxy: %s: unknown socket in pollset", scheme); - return HTTP_INTERNAL_SERVER_ERROR; + status = HTTP_INTERNAL_SERVER_ERROR; + goto done; } if (!(pfd->rtnevents & (APR_POLLIN | APR_POLLOUT | @@ -4900,7 +4917,8 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10220) "proxy: %s: polling events error (%x)", scheme, pfd->rtnevents); - return HTTP_INTERNAL_SERVER_ERROR; + status = HTTP_INTERNAL_SERVER_ERROR; + goto done; } /* We want to write if we asked for POLLOUT and got: @@ -4930,7 +4948,8 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10221) "proxy: %s: %s flushing failed (%i)", scheme, out->name, rc); - return rc; + status = rc; + goto done; } /* No more pending data. If the other side is not readable @@ -4955,12 +4974,13 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) * the next POLLIN will trigger and retaining data might * deadlock the underlying protocol. We don't check for * pending data first with ap_filter_input_pending() since - * the read from proxy_tunnel_forward() is nonblocking + * the read from proxy_tunnel_transfer() is nonblocking * anyway and returning OK if there's no data. */ - rc = proxy_tunnel_forward(tunnel, in); + rc = proxy_tunnel_transfer(tunnel, in); if (rc != OK) { - return rc; + status = rc; + goto done; } } } @@ -4973,17 +4993,22 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel) if ((tc->pfd->reqevents & APR_POLLIN) && ((pfd->rtnevents & (APR_POLLIN | APR_POLLHUP)) || !(pfd->rtnevents & APR_POLLOUT))) { - rc = proxy_tunnel_forward(tunnel, tc); + rc = proxy_tunnel_transfer(tunnel, tc); if (rc != OK) { - return rc; + status = rc; + goto done; } } } } while (!client->down_out || !origin->down_out); +done: + if (client->bytes_out > 0) { + tunnel->replied = 1; + } ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(10223) - "proxy: %s: tunnel finished", scheme); - return OK; + "proxy: %s: tunneling returns (%i)", scheme, status); + return status; } PROXY_DECLARE (const char *) ap_proxy_show_hcmethod(hcmethod_t method)