[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-httpd-dev
Subject:    Re: svn commit: r1912459 - in /httpd/httpd/trunk: include/ modules/proxy/
From:       Ruediger Pluem <rpluem () apache ! org>
Date:       2023-09-30 17:19:46
Message-ID: 9e6edf24-82e5-1ece-62d9-6371cea286b4 () apache ! org
[Download RAW message or body]



On 9/21/23 3:15 PM, ylavic@apache.org wrote:
> Author: ylavic
> Date: Thu Sep 21 13:15:35 2023
> New Revision: 1912459
> 
> URL: http://svn.apache.org/viewvc?rev=1912459&view=rev
> Log:
> mod_proxy: Handle backend address renewal with address_ttl= parameter.
> 
> Define a new proxy_address struct holding the current/latest sockaddr in use
> by each proxy worker and conn. Since backend addresses can be updated when
> their TTL expires and while connections are being processed, each address is
> refcounted and freed only when the last worker (or conn) using it grabs the
> new one.
> 
> The lifetime of the addresses is handled at a single place by the new
> ap_proxy_determine_address() function. It guarantees to bind the current/latest
> backend address to the passed in conn (or do nothing if it's up to date already).
> The function is called indirectly by ap_proxy_determine_connection() for the
> proxy modules that use it, or directly by mod_proxy_ftp and mod_proxy_hcheck.
> It also is called eventually by ap_proxy_connect_backend() when connect()ing all
> the current addresses fails, to check (PROXY_DETERMINE_ADDRESS_CHECK) if some
> new addrs are available.
> 
> This commit is also a rework of the lifetime of conn->addr, conn->hostname
> and conn->forward, using the conn->uds_pool and conn->fwd_pool for the cases
> where the backend is connected through a UDS socket and a remote CONNECT proxy
> respectively.
> 
> * include/ap_mmn.h:
> Minor bump for new function/fields.
> 
> * modules/proxy/mod_proxy.h (struct proxy_address,
> ap_proxy_determine_addresss()):
> Declare ap_proxy_determine_addresss() and opaque struct proxy_address,
> new fields to structs proxy_conn_rec/proxy_worker_shared/proxy_worker.
> 
> * modules/proxy/mod_proxy.c (set_worker_param):
> Parse/set the new worker->address_ttl parameter.
> 
> * modules/proxy/proxy_util.c (proxy_util_register_hooks(),
> ap_proxy_initialize_worker(),
> ap_proxy_connection_reusable(),
> ap_proxyerror(), proxyerror_core(),
> init_conn_pool(), make_conn_subpool(),
> connection_make(), connection_cleanup(),
> connection_constructor()):
> Initialize *proxy_start_time in proxy_util_register_hooks() as the epoch
> from which expiration times are relative (i.e. seconds stored in an uint32_t
> for atomic changes).
> Make sure worker->s->is_address_reusable and worker->s->disablereuse are
> consistant in ap_proxy_initialize_worker(), thus no need to check for both
> in ap_proxy_connection_reusable().
> New proxyerror_core() helper taking an apr_status_t to log, wrap in
> ap_proxyerror().
> New make_conn_subpool() to create worker->cp->{pool,dns} with their own
> allocator.
> New connection_make() helper to factorize code in connection_cleanup() and
> connection_constructor().
> 
> * modules/proxy/proxy_util.c (proxy_address_inc(), proxy_address_dec(),
> proxy_address_cleanup(), proxy_address_set_expired(),
> worker_address_get(), worker_address_set(),
> worker_address_resolve(), proxy_addrs_equal(),
> ap_proxy_determine_address(),
> ap_proxy_determine_connection(),
> ap_proxy_connect_backend()):
> Implement ap_proxy_determine_address() using the above helpers for atomic changes,
> and call it from ap_proxy_determine_connection() and ap_proxy_connect_backend().
> 
> * modules/proxy/mod_proxy_ftp.c (proxy_ftp_handler):
> Use ap_proxy_determine_address() and use the returned backend->addr.
> 
> * modules/proxy/mod_proxy_hcheck.c (hc_determine_connection, hc_get_backend,
> hc_init_worker, hc_watchdog_callback):
> Use ap_proxy_determine_address() in hc_determine_connection() and call the
> latter from hc_get_backend(), replace hc_init_worker() by hc_init_baton()
> which now calls hc_get_hcworker() and hc_get_backend() to resolve the first
> address at init time.
> 
> * modules/proxy/mod_proxy_http.c (proxy_http_handler):
> Use backend->addr and ->hostname instead of worker->cp->addr and
> worker->s->hostname_ex respectively.
> 
> * modules/proxy/mod_proxy_ajp.c (ap_proxy_ajp_request):
> Use backend->addr and ->hostname instead of worker->cp->addr and
> worker->s->hostname_ex respectively.
> 
> 
> Closes #367
> 
> 
> Modified:
> httpd/httpd/trunk/include/ap_mmn.h
> httpd/httpd/trunk/modules/proxy/mod_proxy.c
> httpd/httpd/trunk/modules/proxy/mod_proxy.h
> httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c
> httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c
> httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c
> httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
> httpd/httpd/trunk/modules/proxy/proxy_util.c
> 

> Modified: httpd/httpd/trunk/modules/proxy/proxy_util.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?rev=1912459&r1=1912458&r2=1912459&view=diff
>  ==============================================================================
> --- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
> +++ httpd/httpd/trunk/modules/proxy/proxy_util.c Thu Sep 21 13:15:35 2023

> @@ -2683,56 +3116,83 @@ ap_proxy_determine_connection(apr_pool_t
> *      to check host and port on the conn and be careful about
> *      spilling the cached addr from the worker.
> */
> -    uds_path = (*worker->s->uds_path ? worker->s->uds_path : \
> apr_table_get(r->notes, "uds_path")); +    uds_path = (*worker->s->uds_path
> +                ? worker->s->uds_path
> +                : apr_table_get(r->notes, "uds_path"));
> if (uds_path) {
> -        if (conn->uds_path == NULL) {
> -            /* use (*conn)->pool instead of worker->cp->pool to match lifetime */
> -            conn->uds_path = apr_pstrdup(conn->pool, uds_path);
> -        }
> -        if (conn->uds_path) {
> -            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02545)
> -                         "%s: has determined UDS as %s",
> -                         uri->scheme, conn->uds_path);
> -        }
> -        else {
> -            /* should never happen */
> -            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02546)
> -                         "%s: cannot determine UDS (%s)",
> -                         uri->scheme, uds_path);
> -
> -        }
> -        /*
> -         * In UDS cases, some structs are NULL. Protect from de-refs
> -         * and provide info for logging at the same time.
> -         */
> -        if (!conn->addr) {
> -            apr_sockaddr_t *sa;
> -            apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 0, 0, conn->pool);
> -            conn->addr = sa;
> +        if (!conn->uds_path || strcmp(conn->uds_path, uds_path) != 0) {
> +            apr_pool_t *pool = conn->pool;
> +            if (conn->uds_path) {
> +                address_cleanup(conn);
> +                if (!conn->uds_pool) {
> +                    apr_pool_create(&conn->uds_pool, worker->cp->dns_pool);
> +                }
> +                pool = conn->uds_pool;
> +            }
> +            /*
> +             * In UDS cases, some structs are NULL. Protect from de-refs
> +             * and provide info for logging at the same time.
> +             */
> +#if APR_HAVE_SOCKADDR_UN
> +            apr_sockaddr_info_get(&conn->addr, uds_path, APR_UNIX, 0, 0, pool);
> +            if (conn->addr && conn->addr->hostname) {
> +                conn->uds_path = conn->addr->hostname;
> +            }
> +            else {
> +                conn->uds_path = apr_pstrdup(pool, uds_path);
> +            }
> +#else
> +            apr_sockaddr_info_get(&conn->addr, NULL, APR_UNSPEC, 0, 0, pool);
> +            conn->uds_path = apr_pstrdup(pool, uds_path);
> +#endif
> +            conn->hostname = apr_pstrdup(pool, uri->hostname);
> +            conn->port = uri->port;
> }
> -        conn->hostname = "httpd-UDS";
> -        conn->port = 0;
> +        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02545)
> +                     "%s: has determined UDS as %s (for %s:%hu)",
> +                     uri->scheme, conn->uds_path, conn->hostname, conn->port);
> }
> else {
> -        int will_reuse = worker->s->is_address_reusable && \
>                 !worker->s->disablereuse;
> -        if (!conn->hostname || !will_reuse) {
> -            if (proxyname) {
> -                conn->hostname = apr_pstrdup(conn->pool, proxyname);
> -                conn->port = proxyport;
> +        const char *hostname = uri->hostname;
> +        apr_port_t hostport = uri->port;
> +
> +        if (proxyname) {
> +            forward_info *forward;
> +
> +            hostname = proxyname;
> +            hostport = proxyport;
> +
> +            /* Reset forward info if they changed */
> +            if (conn->is_ssl
> +                && (!(forward = conn->forward)
> +                    || forward->target_port != uri->port
> +                    || ap_cstr_casecmp(forward->target_host,
> +                                       uri->hostname) != 0)) {
> +                apr_pool_t *fwd_pool = conn->pool;
> +                if (worker->s->is_address_reusable) {
> +                    if (conn->fwd_pool) {
> +                        apr_pool_clear(conn->fwd_pool);
> +                    }
> +                    else {
> +                        apr_pool_create(&conn->fwd_pool, conn->pool);
> +                    }


Don't we need to

fwd_pool = conn->fwd_pool

??

> +                }
> +                forward = apr_pcalloc(fwd_pool, sizeof(forward_info));
> +                conn->forward = forward;
> +
> /*
> -                 * If we have a forward proxy and the protocol is HTTPS,
> +                 * If we have a remote proxy and the protocol is HTTPS,
> * then we need to prepend a HTTP CONNECT request before
> * sending our actual HTTPS requests.
> * Save our real backend data for using it later during HTTP CONNECT.
> */
> -                if (conn->is_ssl) {
> +                {
> const char *proxy_auth;
> 
> -                    forward_info *forward = apr_pcalloc(conn->pool, \
>                 sizeof(forward_info));
> -                    conn->forward = forward;
> forward->use_http_connect = 1;
> -                    forward->target_host = apr_pstrdup(conn->pool, uri->hostname);
> +                    forward->target_host = apr_pstrdup(fwd_pool, uri->hostname);
> forward->target_port = uri->port;
> +
> /* Do we want to pass Proxy-Authorization along?
> * If we haven't used it, then YES
> * If we have used it then MAYBE: RFC2616 says we MAY propagate it.

Regards

RĂ¼diger


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic