]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Backport:
authorGraham Leggett <minfrin@apache.org>
Fri, 10 Dec 2021 13:23:51 +0000 (13:23 +0000)
committerGraham Leggett <minfrin@apache.org>
Fri, 10 Dec 2021 13:23:51 +0000 (13:23 +0000)
  *) mod_proxy_connect: Honor the smallest of the backend or client timeout
     while tunneling, and handle "proxy-nohalfclose" as opt-out for hlaf-close
     tunneling. PR 65631, 65662, 65689.
     trunk patch: http://svn.apache.org/r1894290
                  http://svn.apache.org/r1895304
     backport PR: https://github.com/apache/httpd/pull/278
     2.4.x patch: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/278.patch
     +1: ylavic, rpluem, minfrin

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1895762 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
modules/proxy/mod_proxy.h
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index 6bbe0383ec1dacce7b127c32654a8355deaaf08d..37fda08f5447614538a6d084e3f1637c7d62fb1d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,12 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.4.52
 
+  *) mod_proxy_connect: Honor the smallest of the backend or client timeout
+     while tunneling.  [Yann Ylavic]
+
+  *) mod_proxy: SetEnv proxy-nohalfclose (or alike) allows to disable TCP
+     half-close forwarding when tunneling protocols.  [Yann Ylavic]
+
   *) core: Be safe with ap_lingering_close() called with a socket NULL-ed by
      a third-party module.  PR 65627.
      [acmondor <bz.apache.org acmondor.ca>, Yann Ylavic]
diff --git a/STATUS b/STATUS
index a6a7ee2beb137a6ae04739b5a0aad8d65e643781..92794c1337612c3000bc0911143e807117f1c173 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -144,14 +144,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) mod_proxy_connect: Honor the smallest of the backend or client timeout
-     while tunneling, and handle "proxy-nohalfclose" as opt-out for hlaf-close
-     tunneling. PR 65631, 65662, 65689.
-     trunk patch: http://svn.apache.org/r1894290
-                  http://svn.apache.org/r1895304
-     backport PR: https://github.com/apache/httpd/pull/278
-     2.4.x patch: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/278.patch
-     +1: ylavic, rpluem, minfrin
 
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
index 1219e9f172779dbc881538c0eeeece33bf403075..35acc49a4a3e955d788a5af053e4ff2ee9e81938 100644 (file)
@@ -1335,7 +1335,8 @@ typedef struct {
     struct proxy_tunnel_conn *client,
                              *origin;
     apr_size_t read_buf_size;
-    int replied;
+    int replied; /* TODO 2.5+: one bit to merge in below bitmask */
+    unsigned int nohalfclose :1;
 } proxy_tunnel_rec;
 
 /**
index f291a0d55f2274950996e8fd44b8cec440c7a4a7..a3cf54604872a2b6a89360dc1487210a100ff714 100644 (file)
@@ -4673,6 +4673,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **ptunnel,
 {
     apr_status_t rv;
     conn_rec *c_i = r->connection;
+    apr_interval_time_t timeout = -1;
     proxy_tunnel_rec *tunnel;
 
     *ptunnel = NULL;
@@ -4712,6 +4713,13 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **ptunnel,
     tunnel->origin->pfd->desc.s = ap_get_conn_socket(c_o);
     tunnel->origin->pfd->client_data = tunnel->origin;
 
+    /* Defaults to the smallest timeout of both connections */
+    apr_socket_timeout_get(tunnel->client->pfd->desc.s, &timeout);
+    apr_socket_timeout_get(tunnel->origin->pfd->desc.s, &tunnel->timeout);
+    if (timeout >= 0 && (tunnel->timeout < 0 || tunnel->timeout > timeout)) {
+        tunnel->timeout = timeout;
+    }
+
     /* We should be nonblocking from now on the sockets */
     apr_socket_opt_set(tunnel->client->pfd->desc.s, APR_SO_NONBLOCK, 1);
     apr_socket_opt_set(tunnel->origin->pfd->desc.s, APR_SO_NONBLOCK, 1);
@@ -4733,6 +4741,11 @@ PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **ptunnel,
     c_i->keepalive = AP_CONN_CLOSE;
     c_o->keepalive = AP_CONN_CLOSE;
 
+    /* Disable half-close forwarding for this request? */
+    if (apr_table_get(r->subprocess_env, "proxy-nohalfclose")) {
+        tunnel->nohalfclose = 1;
+    }
+
     /* Start with POLLOUT and let ap_proxy_tunnel_run() schedule both
      * directions when there are no output data pending (anymore).
      */
@@ -4838,6 +4851,12 @@ static int proxy_tunnel_forward(proxy_tunnel_rec *tunnel,
             ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, tunnel->r,
                           "proxy: %s: %s read shutdown",
                           tunnel->scheme, in->name);
+            if (tunnel->nohalfclose) {
+                /* No half-close forwarding, we are done both ways as
+                 * soon as one side shuts down.
+                 */
+                return DONE;
+            }
             in->down_in = 1;
         }
         else {
@@ -4854,7 +4873,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;
     struct proxy_tunnel_conn *client = tunnel->client,
@@ -4889,14 +4908,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)
@@ -4915,7 +4934,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 |
@@ -4924,7 +4944,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:
@@ -4954,7 +4975,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
@@ -4984,7 +5006,8 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel)
                      */
                     rc = proxy_tunnel_forward(tunnel, in);
                     if (rc != OK) {
-                        return rc;
+                        status = rc;
+                        goto done;
                     }
                 }
             }
@@ -4999,15 +5022,20 @@ PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel)
                         || !(pfd->rtnevents & APR_POLLOUT))) {
                 rc = proxy_tunnel_forward(tunnel, tc);
                 if (rc != OK) {
-                    return rc;
+                    status = rc;
+                    goto done;
                 }
             }
         }
     } while (!client->down_out || !origin->down_out);
 
+done:
     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);
+    if (status == DONE) {
+        status = OK;
+    }
+    return status;
 }
 
 PROXY_DECLARE (const char *) ap_proxy_show_hcmethod(hcmethod_t method)