github.com/krum110487/go-htaccess@v0.0.0-20240316004156-60641c8e7598/tests/data/apache_2_4_58/include/mod_proxy.h (about)

     1  /* Licensed to the Apache Software Foundation (ASF) under one or more
     2   * contributor license agreements.  See the NOTICE file distributed with
     3   * this work for additional information regarding copyright ownership.
     4   * The ASF licenses this file to You under the Apache License, Version 2.0
     5   * (the "License"); you may not use this file except in compliance with
     6   * the License.  You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #ifndef MOD_PROXY_H
    18  #define MOD_PROXY_H
    19  
    20  /**
    21   * @file  mod_proxy.h
    22   * @brief Proxy Extension Module for Apache
    23   *
    24   * @defgroup MOD_PROXY mod_proxy
    25   * @ingroup  APACHE_MODS
    26   * @{
    27   */
    28  
    29  #include "apr_hooks.h"
    30  #include "apr_optional.h"
    31  #include "apr.h"
    32  #include "apr_lib.h"
    33  #include "apr_strings.h"
    34  #include "apr_buckets.h"
    35  #include "apr_md5.h"
    36  #include "apr_network_io.h"
    37  #include "apr_pools.h"
    38  #include "apr_strings.h"
    39  #include "apr_uri.h"
    40  #include "apr_date.h"
    41  #include "apr_strmatch.h"
    42  #include "apr_fnmatch.h"
    43  #include "apr_reslist.h"
    44  #define APR_WANT_STRFUNC
    45  #include "apr_want.h"
    46  #include "apr_uuid.h"
    47  #include "util_mutex.h"
    48  #include "apr_global_mutex.h"
    49  #include "apr_thread_mutex.h"
    50  
    51  #include "httpd.h"
    52  #include "http_config.h"
    53  #include "ap_config.h"
    54  #include "http_core.h"
    55  #include "http_protocol.h"
    56  #include "http_request.h"
    57  #include "http_vhost.h"
    58  #include "http_main.h"
    59  #include "http_log.h"
    60  #include "http_connection.h"
    61  #include "http_ssl.h"
    62  #include "util_filter.h"
    63  #include "util_ebcdic.h"
    64  #include "ap_provider.h"
    65  #include "ap_slotmem.h"
    66  
    67  #if APR_HAVE_NETINET_IN_H
    68  #include <netinet/in.h>
    69  #endif
    70  #if APR_HAVE_ARPA_INET_H
    71  #include <arpa/inet.h>
    72  #endif
    73  
    74  /* for proxy_canonenc() */
    75  enum enctype {
    76      enc_path, enc_search, enc_user, enc_fpath, enc_parm
    77  };
    78  
    79  /* Flags for ap_proxy_canonenc_ex */
    80  #define PROXY_CANONENC_FORCEDEC 0x01
    81  #define PROXY_CANONENC_NOENCODEDSLASHENCODING 0x02
    82  
    83  typedef enum {
    84      NONE, TCP, OPTIONS, HEAD, GET, CPING, PROVIDER, OPTIONS11, HEAD11, GET11, EOT
    85  } hcmethod_t;
    86  
    87  typedef struct {
    88      hcmethod_t method;
    89      char *name;
    90      int implemented;
    91  } proxy_hcmethods_t;
    92  
    93  typedef struct {
    94      unsigned int bit;
    95      char flag;
    96      const char *name;
    97  } proxy_wstat_t;
    98  
    99  #define BALANCER_PREFIX "balancer://"
   100  
   101  #if APR_CHARSET_EBCDIC
   102  #define CRLF   "\r\n"
   103  #else /*APR_CHARSET_EBCDIC*/
   104  #define CRLF   "\015\012"
   105  #endif /*APR_CHARSET_EBCDIC*/
   106  
   107  /* default Max-Forwards header setting */
   108  /* Set this to -1, which complies with RFC2616 by not setting
   109   * max-forwards if the client didn't send it to us.
   110   */
   111  #define DEFAULT_MAX_FORWARDS    -1
   112  
   113  typedef struct proxy_balancer  proxy_balancer;
   114  typedef struct proxy_worker    proxy_worker;
   115  typedef struct proxy_conn_pool proxy_conn_pool;
   116  typedef struct proxy_balancer_method proxy_balancer_method;
   117  
   118  /* static information about a remote proxy */
   119  struct proxy_remote {
   120      const char *scheme;     /* the schemes handled by this proxy, or '*' */
   121      const char *protocol;   /* the scheme used to talk to this proxy */
   122      const char *hostname;   /* the hostname of this proxy */
   123      ap_regex_t *regexp;     /* compiled regex (if any) for the remote */
   124      int use_regex;          /* simple boolean. True if we have a regex pattern */
   125      apr_port_t  port;       /* the port for this proxy */
   126  };
   127  
   128  #define PROXYPASS_NOCANON 0x01
   129  #define PROXYPASS_INTERPOLATE 0x02
   130  #define PROXYPASS_NOQUERY 0x04
   131  #define PROXYPASS_MAP_ENCODED 0x08
   132  #define PROXYPASS_MAP_SERVLET 0x18 /* + MAP_ENCODED */
   133  struct proxy_alias {
   134      const char  *real;
   135      const char  *fake;
   136      ap_regex_t  *regex;
   137      unsigned int flags;
   138      proxy_balancer *balancer; /* only valid for reverse-proxys */
   139  };
   140  
   141  struct dirconn_entry {
   142      char *name;
   143      struct in_addr addr, mask;
   144      struct apr_sockaddr_t *hostaddr;
   145      int (*matcher) (struct dirconn_entry * This, request_rec *r);
   146  };
   147  
   148  struct noproxy_entry {
   149      const char *name;
   150      struct apr_sockaddr_t *addr;
   151  };
   152  
   153  typedef struct {
   154      apr_array_header_t *proxies;
   155      apr_array_header_t *sec_proxy;
   156      apr_array_header_t *aliases;
   157      apr_array_header_t *noproxies;
   158      apr_array_header_t *dirconn;
   159      apr_array_header_t *workers;    /* non-balancer workers, eg ProxyPass http://example.com */
   160      apr_array_header_t *balancers;  /* list of balancers @ config time */
   161      proxy_worker       *forward;    /* forward proxy worker */
   162      proxy_worker       *reverse;    /* reverse "module-driven" proxy worker */
   163      const char *domain;     /* domain name to use in absence of a domain name in the request */
   164      const char *id;
   165      apr_pool_t *pool;       /* Pool used for allocating this struct's elements */
   166      int req;                /* true if proxy requests are enabled */
   167      int max_balancers;      /* maximum number of allowed balancers */
   168      int bgrowth;            /* number of post-config balancers can added */
   169      enum {
   170        via_off,
   171        via_on,
   172        via_block,
   173        via_full
   174      } viaopt;                   /* how to deal with proxy Via: headers */
   175      apr_size_t recv_buffer_size;
   176      apr_size_t io_buffer_size;
   177      long maxfwd;
   178      apr_interval_time_t timeout;
   179      enum {
   180        bad_error,
   181        bad_ignore,
   182        bad_body
   183      } badopt;                   /* how to deal with bad headers */
   184      enum {
   185          status_off,
   186          status_on,
   187          status_full
   188      } proxy_status;             /* Status display options */
   189      apr_sockaddr_t *source_address;
   190      apr_global_mutex_t  *mutex; /* global lock, for pool, etc */
   191      ap_slotmem_instance_t *bslot;  /* balancers shm data - runtime */
   192      ap_slotmem_provider_t *storage;
   193  
   194      unsigned int req_set:1;
   195      unsigned int viaopt_set:1;
   196      unsigned int recv_buffer_size_set:1;
   197      unsigned int io_buffer_size_set:1;
   198      unsigned int maxfwd_set:1;
   199      unsigned int timeout_set:1;
   200      unsigned int badopt_set:1;
   201      unsigned int proxy_status_set:1;
   202      unsigned int source_address_set:1;
   203      unsigned int bgrowth_set:1;
   204      unsigned int bal_persist:1;
   205      unsigned int inherit:1;
   206      unsigned int inherit_set:1;
   207      unsigned int ppinherit:1;
   208      unsigned int ppinherit_set:1;
   209      unsigned int map_encoded_one:1;
   210      unsigned int map_encoded_all:1;
   211  } proxy_server_conf;
   212  
   213  typedef struct {
   214      const char *p;            /* The path */
   215      ap_regex_t  *r;            /* Is this a regex? */
   216  
   217  /* FIXME
   218   * ProxyPassReverse and friends are documented as working inside
   219   * <Location>.  But in fact they never have done in the case of
   220   * more than one <Location>, because the server_conf can't see it.
   221   * We need to move them to the per-dir config.
   222   * Discussed in February 2005:
   223   * http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=110726027118798&w=2
   224   */
   225      apr_array_header_t *raliases;
   226      apr_array_header_t* cookie_paths;
   227      apr_array_header_t* cookie_domains;
   228      signed char p_is_fnmatch; /* Is the path an fnmatch candidate? */
   229      signed char interpolate_env;
   230      struct proxy_alias *alias;
   231  
   232      /**
   233       * the following setting masks the error page
   234       * returned from the 'proxied server' and just
   235       * forwards the status code upwards.
   236       * This allows the main server (us) to generate
   237       * the error page, (so it will look like a error
   238       * returned from the rest of the system
   239       */
   240      unsigned int error_override:1;
   241      unsigned int preserve_host:1;
   242      unsigned int preserve_host_set:1;
   243      unsigned int error_override_set:1;
   244      unsigned int alias_set:1;
   245      unsigned int add_forwarded_headers:1;
   246      unsigned int add_forwarded_headers_set:1;
   247  
   248      /** Named back references */
   249      apr_array_header_t *refs;
   250  
   251      unsigned int forward_100_continue:1;
   252      unsigned int forward_100_continue_set:1;
   253  
   254      apr_array_header_t *error_override_codes;
   255  } proxy_dir_conf;
   256  
   257  /* if we interpolate env vars per-request, we'll need a per-request
   258   * copy of the reverse proxy config
   259   */
   260  typedef struct {
   261      apr_array_header_t *raliases;
   262      apr_array_header_t* cookie_paths;
   263      apr_array_header_t* cookie_domains;
   264  } proxy_req_conf;
   265  
   266  typedef struct {
   267      conn_rec     *connection;
   268      request_rec  *r;           /* Request record of the backend request
   269                                  * that is used over the backend connection. */
   270      proxy_worker *worker;      /* Connection pool this connection belongs to */
   271      apr_pool_t   *pool;        /* Subpool for hostname and addr data */
   272      const char   *hostname;
   273      apr_sockaddr_t *addr;      /* Preparsed remote address info */
   274      apr_pool_t   *scpool;      /* Subpool used for socket and connection data */
   275      apr_socket_t *sock;        /* Connection socket */
   276      void         *data;        /* per scheme connection data */
   277      void         *forward;     /* opaque forward proxy data */
   278      apr_uint32_t flags;        /* Connection flags */
   279      apr_port_t   port;
   280      unsigned int is_ssl:1;
   281      unsigned int close:1;      /* Close 'this' connection */
   282      unsigned int need_flush:1; /* Flag to decide whether we need to flush the
   283                                  * filter chain or not */
   284      unsigned int inreslist:1;  /* connection in apr_reslist? */
   285      const char   *uds_path;    /* Unix domain socket path */
   286      const char   *ssl_hostname;/* Hostname (SNI) in use by SSL connection */
   287      apr_bucket_brigade *tmp_bb;/* Temporary brigade created with the connection
   288                                  * and its scpool/bucket_alloc (NULL before),
   289                                  * must be left cleaned when used (locally).
   290                                  */
   291  } proxy_conn_rec;
   292  
   293  typedef struct {
   294          float cache_completion; /* completion percentage */
   295          int content_length; /* length of the content */
   296  } proxy_completion;
   297  
   298  /* Connection pool */
   299  struct proxy_conn_pool {
   300      apr_pool_t     *pool;     /* The pool used in constructor and destructor calls */
   301      apr_sockaddr_t *addr;     /* Preparsed remote address info */
   302      apr_reslist_t  *res;      /* Connection resource list */
   303      proxy_conn_rec *conn;     /* Single connection for prefork mpm */
   304      apr_pool_t     *dns_pool; /* The pool used for worker scoped DNS resolutions */
   305  };
   306  
   307  #define AP_VOLATILIZE_T(T, x) (*(T volatile *)&(x))
   308  
   309  /* worker status bits */
   310  /*
   311   * NOTE: Keep up-to-date w/ proxy_wstat_tbl[]
   312   * in mod_proxy.c !
   313   */
   314  #define PROXY_WORKER_INITIALIZED    0x0001
   315  #define PROXY_WORKER_IGNORE_ERRORS  0x0002
   316  #define PROXY_WORKER_DRAIN          0x0004
   317  #define PROXY_WORKER_GENERIC        0x0008
   318  #define PROXY_WORKER_IN_SHUTDOWN    0x0010
   319  #define PROXY_WORKER_DISABLED       0x0020
   320  #define PROXY_WORKER_STOPPED        0x0040
   321  #define PROXY_WORKER_IN_ERROR       0x0080
   322  #define PROXY_WORKER_HOT_STANDBY    0x0100
   323  #define PROXY_WORKER_FREE           0x0200
   324  #define PROXY_WORKER_HC_FAIL        0x0400
   325  #define PROXY_WORKER_HOT_SPARE      0x0800
   326  
   327  /* worker status flags */
   328  #define PROXY_WORKER_INITIALIZED_FLAG    'O'
   329  #define PROXY_WORKER_IGNORE_ERRORS_FLAG  'I'
   330  #define PROXY_WORKER_DRAIN_FLAG          'N'
   331  #define PROXY_WORKER_GENERIC_FLAG        'G'
   332  #define PROXY_WORKER_IN_SHUTDOWN_FLAG    'U'
   333  #define PROXY_WORKER_DISABLED_FLAG       'D'
   334  #define PROXY_WORKER_STOPPED_FLAG        'S'
   335  #define PROXY_WORKER_IN_ERROR_FLAG       'E'
   336  #define PROXY_WORKER_HOT_STANDBY_FLAG    'H'
   337  #define PROXY_WORKER_FREE_FLAG           'F'
   338  #define PROXY_WORKER_HC_FAIL_FLAG        'C'
   339  #define PROXY_WORKER_HOT_SPARE_FLAG      'R'
   340  
   341  #define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \
   342  PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR | \
   343  PROXY_WORKER_HC_FAIL )
   344  
   345  /* NOTE: these check the shared status */
   346  #define PROXY_WORKER_IS_INITIALIZED(f)  ( (f)->s->status &  PROXY_WORKER_INITIALIZED )
   347  
   348  #define PROXY_WORKER_IS_STANDBY(f)   ( (f)->s->status &  PROXY_WORKER_HOT_STANDBY )
   349  
   350  #define PROXY_WORKER_IS_SPARE(f)   ( (f)->s->status &  PROXY_WORKER_HOT_SPARE )
   351  
   352  #define PROXY_WORKER_IS_USABLE(f)   ( ( !( (f)->s->status & PROXY_WORKER_NOT_USABLE_BITMAP) ) && \
   353    PROXY_WORKER_IS_INITIALIZED(f) )
   354  
   355  #define PROXY_WORKER_IS_DRAINING(f)   ( (f)->s->status &  PROXY_WORKER_DRAIN )
   356  
   357  #define PROXY_WORKER_IS_GENERIC(f)   ( (f)->s->status &  PROXY_WORKER_GENERIC )
   358  
   359  #define PROXY_WORKER_IS_HCFAILED(f)   ( (f)->s->status &  PROXY_WORKER_HC_FAIL )
   360  
   361  #define PROXY_WORKER_IS_ERROR(f)   ( (f)->s->status &  PROXY_WORKER_IN_ERROR )
   362  
   363  #define PROXY_WORKER_IS(f, b)   ( (f)->s->status & (b) )
   364  
   365  /* default worker retry timeout in seconds */
   366  #define PROXY_WORKER_DEFAULT_RETRY    60
   367  
   368  /* Some max char string sizes, for shm fields */
   369  #define PROXY_WORKER_MAX_SCHEME_SIZE    16
   370  #define PROXY_WORKER_MAX_ROUTE_SIZE     64
   371  #define PROXY_BALANCER_MAX_ROUTE_SIZE PROXY_WORKER_MAX_ROUTE_SIZE
   372  #define PROXY_WORKER_MAX_NAME_SIZE      96
   373  #define PROXY_BALANCER_MAX_NAME_SIZE PROXY_WORKER_MAX_NAME_SIZE
   374  #define PROXY_WORKER_MAX_HOSTNAME_SIZE  64
   375  #define PROXY_BALANCER_MAX_HOSTNAME_SIZE PROXY_WORKER_MAX_HOSTNAME_SIZE
   376  #define PROXY_BALANCER_MAX_STICKY_SIZE  64
   377  #define PROXY_WORKER_MAX_SECRET_SIZE     64
   378  
   379  #define PROXY_RFC1035_HOSTNAME_SIZE	256
   380  #define PROXY_WORKER_EXT_NAME_SIZE      384
   381  
   382  /* RFC-1035 mentions limits of 255 for host-names and 253 for domain-names,
   383   * dotted together(?) this would fit the below size (+ trailing NUL).
   384   */
   385  #define PROXY_WORKER_RFC1035_NAME_SIZE  512
   386  
   387  #define PROXY_MAX_PROVIDER_NAME_SIZE    16
   388  
   389  #define PROXY_STRNCPY(dst, src) ap_proxy_strncpy((dst), (src), (sizeof(dst)))
   390  
   391  #define PROXY_COPY_CONF_PARAMS(w, c) \
   392  do {                             \
   393  (w)->s->timeout              = (c)->timeout;               \
   394  (w)->s->timeout_set          = (c)->timeout_set;           \
   395  (w)->s->recv_buffer_size     = (c)->recv_buffer_size;      \
   396  (w)->s->recv_buffer_size_set = (c)->recv_buffer_size_set;  \
   397  (w)->s->io_buffer_size       = (c)->io_buffer_size;        \
   398  (w)->s->io_buffer_size_set   = (c)->io_buffer_size_set;    \
   399  } while (0)
   400  
   401  #define PROXY_SHOULD_PING_100_CONTINUE(w, r) \
   402      ((w)->s->ping_timeout_set \
   403       && (PROXYREQ_REVERSE == (r)->proxyreq) \
   404       && ap_request_has_body((r)))
   405  
   406  #define PROXY_DO_100_CONTINUE(w, r) \
   407      (PROXY_SHOULD_PING_100_CONTINUE(w, r) \
   408       && !apr_table_get((r)->subprocess_env, "force-proxy-request-1.0"))
   409  
   410  /* use 2 hashes */
   411  typedef struct {
   412      unsigned int def;
   413      unsigned int fnv;
   414  } proxy_hashes ;
   415  
   416  /* Runtime worker status information. Shared in scoreboard */
   417  /* The addition of member uds_path in 2.4.7 was an incompatible API change. */
   418  typedef struct {
   419      char      name[PROXY_WORKER_MAX_NAME_SIZE];
   420      char      scheme[PROXY_WORKER_MAX_SCHEME_SIZE];   /* scheme to use ajp|http|https */
   421      char      hostname[PROXY_WORKER_MAX_HOSTNAME_SIZE];  /* remote backend address (deprecated, use hostname_ex below) */
   422      char      route[PROXY_WORKER_MAX_ROUTE_SIZE];     /* balancing route */
   423      char      redirect[PROXY_WORKER_MAX_ROUTE_SIZE];  /* temporary balancing redirection route */
   424      char      flusher[PROXY_WORKER_MAX_SCHEME_SIZE];  /* flush provider used by mod_proxy_fdpass */
   425      char      uds_path[PROXY_WORKER_MAX_NAME_SIZE];   /* path to worker's unix domain socket if applicable */
   426      int             lbset;      /* load balancer cluster set */
   427      int             retries;    /* number of retries on this worker */
   428      int             lbstatus;   /* Current lbstatus */
   429      int             lbfactor;   /* dynamic lbfactor */
   430      int             min;        /* Desired minimum number of available connections */
   431      int             smax;       /* Soft maximum on the total number of connections */
   432      int             hmax;       /* Hard maximum on the total number of connections */
   433      int             flush_wait; /* poll wait time in microseconds if flush_auto */
   434      int             index;      /* shm array index */
   435      proxy_hashes    hash;       /* hash of worker name */
   436      unsigned int    status;     /* worker status bitfield */
   437      enum {
   438          flush_off,
   439          flush_on,
   440          flush_auto
   441      } flush_packets;           /* control AJP flushing */
   442      apr_time_t      updated;    /* timestamp of last update for dynamic workers, or queue-time of HC workers */
   443      apr_time_t      error_time; /* time of the last error */
   444      apr_interval_time_t ttl;    /* maximum amount of time in seconds a connection
   445                                   * may be available while exceeding the soft limit */
   446      apr_interval_time_t retry;   /* retry interval */
   447      apr_interval_time_t timeout; /* connection timeout */
   448      apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
   449      apr_interval_time_t ping_timeout;
   450      apr_interval_time_t conn_timeout;
   451      apr_size_t      recv_buffer_size;
   452      apr_size_t      io_buffer_size;
   453      apr_size_t      elected;    /* Number of times the worker was elected */
   454      apr_size_t      busy;       /* busyness factor */
   455      apr_port_t      port;
   456      apr_off_t       transferred;/* Number of bytes transferred to remote */
   457      apr_off_t       read;       /* Number of bytes read from remote */
   458      void            *context;   /* general purpose storage */
   459      unsigned int     keepalive:1;
   460      unsigned int     disablereuse:1;
   461      unsigned int     is_address_reusable:1;
   462      unsigned int     retry_set:1;
   463      unsigned int     timeout_set:1;
   464      unsigned int     acquire_set:1;
   465      unsigned int     ping_timeout_set:1;
   466      unsigned int     conn_timeout_set:1;
   467      unsigned int     recv_buffer_size_set:1;
   468      unsigned int     io_buffer_size_set:1;
   469      unsigned int     keepalive_set:1;
   470      unsigned int     disablereuse_set:1;
   471      unsigned int     was_malloced:1;
   472      unsigned int     is_name_matchable:1;
   473      char      hcuri[PROXY_WORKER_MAX_ROUTE_SIZE];     /* health check uri */
   474      char      hcexpr[PROXY_WORKER_MAX_SCHEME_SIZE];   /* name of condition expr for health check */
   475      int             passes;     /* number of successes for check to pass */
   476      int             pcount;     /* current count of passes */
   477      int             fails;      /* number of failures for check to fail */
   478      int             fcount;     /* current count of failures */
   479      hcmethod_t      method;     /* method to use for health check */
   480      apr_interval_time_t interval;
   481      char      upgrade[PROXY_WORKER_MAX_SCHEME_SIZE];/* upgrade protocol used by mod_proxy_wstunnel */
   482      char      hostname_ex[PROXY_RFC1035_HOSTNAME_SIZE];  /* RFC1035 compliant version of the remote backend address */
   483      apr_size_t   response_field_size; /* Size of proxy response buffer in bytes. */
   484      unsigned int response_field_size_set:1;
   485      char      secret[PROXY_WORKER_MAX_SECRET_SIZE]; /* authentication secret (e.g. AJP13) */
   486      char      name_ex[PROXY_WORKER_EXT_NAME_SIZE]; /* Extended name (>96 chars for 2.4.x) */
   487  } proxy_worker_shared;
   488  
   489  #define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared)))
   490  
   491  /* Worker configuration */
   492  struct proxy_worker {
   493      proxy_hashes    hash;       /* hash of worker name */
   494      unsigned int local_status;  /* status of per-process worker */
   495      proxy_conn_pool     *cp;    /* Connection pool to use */
   496      proxy_worker_shared   *s;   /* Shared data */
   497      proxy_balancer  *balancer;  /* which balancer am I in? */
   498  #if APR_HAS_THREADS
   499      apr_thread_mutex_t  *tmutex; /* Thread lock for updating address cache */
   500  #endif
   501      void            *context;   /* general purpose storage */
   502      ap_conf_vector_t *section_config; /* <Proxy>-section wherein defined */
   503  };
   504  
   505  /* default to health check every 30 seconds */
   506  #define HCHECK_WATHCHDOG_DEFAULT_INTERVAL (30)
   507  /* The watchdog runs every 2 seconds, which is also the minimal check */
   508  #define HCHECK_WATHCHDOG_INTERVAL (2)
   509  
   510  /*
   511   * Time to wait (in microseconds) to find out if more data is currently
   512   * available at the backend.
   513   */
   514  #define PROXY_FLUSH_WAIT 10000
   515  
   516  typedef struct {
   517      char      sticky_path[PROXY_BALANCER_MAX_STICKY_SIZE];     /* URL sticky session identifier */
   518      char      sticky[PROXY_BALANCER_MAX_STICKY_SIZE];          /* sticky session identifier */
   519      char      lbpname[PROXY_MAX_PROVIDER_NAME_SIZE];  /* lbmethod provider name */
   520      char      nonce[APR_UUID_FORMATTED_LENGTH + 1];
   521      char      name[PROXY_BALANCER_MAX_NAME_SIZE];
   522      char      sname[PROXY_BALANCER_MAX_NAME_SIZE];
   523      char      vpath[PROXY_BALANCER_MAX_ROUTE_SIZE];
   524      char      vhost[PROXY_BALANCER_MAX_HOSTNAME_SIZE];
   525      apr_interval_time_t timeout;  /* Timeout for waiting on free connection */
   526      apr_time_t      wupdated;     /* timestamp of last change to workers list */
   527      int             max_attempts;     /* Number of attempts before failing */
   528      int             index;      /* shm array index */
   529      proxy_hashes hash;
   530      unsigned int    sticky_force:1;   /* Disable failover for sticky sessions */
   531      unsigned int    scolonsep:1;      /* true if ';' seps sticky session paths */
   532      unsigned int    max_attempts_set:1;
   533      unsigned int    was_malloced:1;
   534      unsigned int    need_reset:1;
   535      unsigned int    vhosted:1;
   536      unsigned int    inactive:1;
   537      unsigned int    forcerecovery:1;
   538      char      sticky_separator;                                /* separator for sessionid/route */
   539      unsigned int    forcerecovery_set:1;
   540      unsigned int    scolonsep_set:1;
   541      unsigned int    sticky_force_set:1; 
   542      unsigned int    nonce_set:1;
   543      unsigned int    sticky_separator_set:1;
   544  } proxy_balancer_shared;
   545  
   546  #define ALIGNED_PROXY_BALANCER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_balancer_shared)))
   547  
   548  struct proxy_balancer {
   549      apr_array_header_t *workers;  /* initially configured workers */
   550      apr_array_header_t *errstatuses;  /* statuses to force members into error */
   551      ap_slotmem_instance_t *wslot;  /* worker shm data - runtime */
   552      ap_slotmem_provider_t *storage;
   553      int growth;                   /* number of post-config workers can added */
   554      int max_workers;              /* maximum number of allowed workers */
   555      proxy_hashes hash;
   556      apr_time_t      wupdated;    /* timestamp of last change to workers list */
   557      proxy_balancer_method *lbmethod;
   558      apr_global_mutex_t  *gmutex; /* global lock for updating list of workers */
   559  #if APR_HAS_THREADS
   560      apr_thread_mutex_t  *tmutex; /* Thread lock for updating shm */
   561  #endif
   562      proxy_server_conf *sconf;
   563      void            *context;    /* general purpose storage */
   564      proxy_balancer_shared *s;    /* Shared data */
   565      int failontimeout;           /* Whether to mark a member in Err if IO timeout occurs */
   566      unsigned int failontimeout_set:1;
   567      unsigned int growth_set:1;
   568      unsigned int lbmethod_set:1;
   569      ap_conf_vector_t *section_config; /* <Proxy>-section wherein defined */
   570  };
   571  
   572  struct proxy_balancer_method {
   573      const char *name;            /* name of the load balancer method*/
   574      proxy_worker *(*finder)(proxy_balancer *balancer,
   575                              request_rec *r);
   576      void            *context;   /* general purpose storage */
   577      apr_status_t (*reset)(proxy_balancer *balancer, server_rec *s);
   578      apr_status_t (*age)(proxy_balancer *balancer, server_rec *s);
   579      apr_status_t (*updatelbstatus)(proxy_balancer *balancer, proxy_worker *elected, server_rec *s);
   580  };
   581  
   582  #define PROXY_THREAD_LOCK(x)      ( (x) && (x)->tmutex ? apr_thread_mutex_lock((x)->tmutex) : APR_SUCCESS)
   583  #define PROXY_THREAD_UNLOCK(x)    ( (x) && (x)->tmutex ? apr_thread_mutex_unlock((x)->tmutex) : APR_SUCCESS)
   584  
   585  #define PROXY_GLOBAL_LOCK(x)      ( (x) && (x)->gmutex ? apr_global_mutex_lock((x)->gmutex) : APR_SUCCESS)
   586  #define PROXY_GLOBAL_UNLOCK(x)    ( (x) && (x)->gmutex ? apr_global_mutex_unlock((x)->gmutex) : APR_SUCCESS)
   587  
   588  /* hooks */
   589  
   590  /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
   591   * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
   592   */
   593  #if !defined(WIN32)
   594  #define PROXY_DECLARE(type)            type
   595  #define PROXY_DECLARE_NONSTD(type)     type
   596  #define PROXY_DECLARE_DATA
   597  #elif defined(PROXY_DECLARE_STATIC)
   598  #define PROXY_DECLARE(type)            type __stdcall
   599  #define PROXY_DECLARE_NONSTD(type)     type
   600  #define PROXY_DECLARE_DATA
   601  #elif defined(PROXY_DECLARE_EXPORT)
   602  #define PROXY_DECLARE(type)            __declspec(dllexport) type __stdcall
   603  #define PROXY_DECLARE_NONSTD(type)     __declspec(dllexport) type
   604  #define PROXY_DECLARE_DATA             __declspec(dllexport)
   605  #else
   606  #define PROXY_DECLARE(type)            __declspec(dllimport) type __stdcall
   607  #define PROXY_DECLARE_NONSTD(type)     __declspec(dllimport) type
   608  #define PROXY_DECLARE_DATA             __declspec(dllimport)
   609  #endif
   610  
   611  /* Using PROXY_DECLARE_OPTIONAL_HOOK instead of
   612   * APR_DECLARE_EXTERNAL_HOOK allows build/make_nw_export.awk
   613   * to distinguish between hooks that implement
   614   * proxy_hook_xx and proxy_hook_get_xx in mod_proxy.c and
   615   * those which don't.
   616   */
   617  #define PROXY_DECLARE_OPTIONAL_HOOK APR_DECLARE_EXTERNAL_HOOK
   618  
   619  /* These 2 are in mod_proxy.c */
   620  extern PROXY_DECLARE_DATA proxy_hcmethods_t proxy_hcmethods[];
   621  extern PROXY_DECLARE_DATA proxy_wstat_t proxy_wstat_tbl[];
   622  
   623  /* Following 4 from health check */
   624  APR_DECLARE_OPTIONAL_FN(void, hc_show_exprs, (request_rec *));
   625  APR_DECLARE_OPTIONAL_FN(void, hc_select_exprs, (request_rec *, const char *));
   626  APR_DECLARE_OPTIONAL_FN(int, hc_valid_expr, (request_rec *, const char *));
   627  APR_DECLARE_OPTIONAL_FN(const char *, set_worker_hc_param,
   628                          (apr_pool_t *, server_rec *, proxy_worker *,
   629                           const char *, const char *, void *));
   630  
   631  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, section_post_config,
   632                            (apr_pool_t *p, apr_pool_t *plog,
   633                             apr_pool_t *ptemp, server_rec *s,
   634                             ap_conf_vector_t *section_config))
   635  
   636  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler,
   637                            (request_rec *r, proxy_worker *worker,
   638                             proxy_server_conf *conf, char *url,
   639                             const char *proxyhost, apr_port_t proxyport))
   640  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, check_trans,
   641                            (request_rec *r, const char *url))
   642  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler,
   643                            (request_rec *r, char *url))
   644  
   645  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
   646  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
   647  
   648  
   649  /**
   650   * pre request hook.
   651   * It will return the most suitable worker at the moment
   652   * and corresponding balancer.
   653   * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
   654   * and then the scheme_handler is called.
   655   *
   656   */
   657  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
   658                            proxy_balancer **balancer,
   659                            request_rec *r,
   660                            proxy_server_conf *conf, char **url))
   661  /**
   662   * post request hook.
   663   * It is called after request for updating runtime balancer status.
   664   */
   665  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
   666                            proxy_balancer *balancer, request_rec *r,
   667                            proxy_server_conf *conf))
   668  
   669  /**
   670   * request status hook
   671   * It is called after all proxy processing has been done.  This gives other
   672   * modules a chance to create default content on failure, for example
   673   */
   674  APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status,
   675                            (int *status, request_rec *r))
   676  
   677  /* proxy_util.c */
   678  
   679  PROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src,
   680                                               apr_size_t dlen);
   681  PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
   682  PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
   683  PROXY_DECLARE(char *)ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len, enum enctype t,
   684                                            int flags, int proxyreq);
   685  PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
   686                                         int forcedec, int proxyreq);
   687  PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
   688                                             char **passwordp, char **hostp, apr_port_t *port);
   689  PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
   690  PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
   691  
   692  /** Test whether the hostname/address of the request are blocked by the ProxyBlock
   693   * configuration.
   694   * @param r         request
   695   * @param conf      server configuration
   696   * @param hostname  hostname from request URI
   697   * @param addr      resolved address of hostname, or NULL if not known
   698   * @return OK on success, or else an error
   699   */
   700  PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf, 
   701                                               const char *hostname, apr_sockaddr_t *addr);
   702  
   703  PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
   704  /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
   705  PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, request_rec *);
   706  /* DEPRECATED (will be replaced with ap_proxy_check_connection */
   707  PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
   708                                                              request_rec *r);
   709  PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
   710  PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
   711  PROXY_DECLARE(int) ap_proxy_ssl_engine(conn_rec *c,
   712                                         ap_conf_vector_t *per_dir_config,
   713                                         int enable);
   714  PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
   715  PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
   716  
   717  /* Header mapping functions, and a typedef of their signature */
   718  PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url);
   719  PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str);
   720  
   721  #if !defined(WIN32)
   722  typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
   723                         proxy_dir_conf *, const char *);
   724  #elif defined(PROXY_DECLARE_STATIC)
   725  typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
   726                                   proxy_dir_conf *, const char *);
   727  #elif defined(PROXY_DECLARE_EXPORT)
   728  typedef __declspec(dllexport) const char *
   729    (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
   730                 proxy_dir_conf *, const char *);
   731  #else
   732  typedef __declspec(dllimport) const char *
   733    (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
   734                 proxy_dir_conf *, const char *);
   735  #endif
   736  
   737  
   738  /* Connection pool API */
   739  /**
   740   * Return the user-land, UDS aware worker name
   741   * @param p        memory pool used for displaying worker name
   742   * @param worker   the worker
   743   * @return         name
   744   */
   745  
   746  PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p,
   747                                             proxy_worker *worker);
   748  
   749  /**
   750   * Return whether a worker upgrade configuration matches Upgrade header
   751   * @param p       memory pool used for displaying worker name
   752   * @param worker  the worker
   753   * @param upgrade the Upgrade header to match
   754   * @param dflt    default protocol (NULL for none)
   755   * @return        1 (true) or 0 (false)
   756   */
   757  PROXY_DECLARE(int) ap_proxy_worker_can_upgrade(apr_pool_t *p,
   758                                                 const proxy_worker *worker,
   759                                                 const char *upgrade,
   760                                                 const char *dflt);
   761  
   762  /* Bitmask for ap_proxy_{define,get}_worker_ex(). */
   763  #define AP_PROXY_WORKER_IS_PREFIX   (1u << 0)
   764  #define AP_PROXY_WORKER_IS_MATCH    (1u << 1)
   765  #define AP_PROXY_WORKER_IS_MALLOCED (1u << 2)
   766  #define AP_PROXY_WORKER_NO_UDS      (1u << 3)
   767  
   768  /**
   769   * Get the worker from proxy configuration, looking for either PREFIXED or
   770   * MATCHED or both types of workers according to given mask
   771   * @param p        memory pool used for finding worker
   772   * @param balancer the balancer that the worker belongs to
   773   * @param conf     current proxy server configuration
   774   * @param url      url to find the worker from
   775   * @param mask     bitmask of AP_PROXY_WORKER_IS_*
   776   * @return         proxy_worker or NULL if not found
   777   */
   778  PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p,
   779                                                       proxy_balancer *balancer,
   780                                                       proxy_server_conf *conf,
   781                                                       const char *url,
   782                                                       unsigned int mask);
   783  
   784  /**
   785   * Get the worker from proxy configuration, both types
   786   * @param p        memory pool used for finding worker
   787   * @param balancer the balancer that the worker belongs to
   788   * @param conf     current proxy server configuration
   789   * @param url      url to find the worker from
   790   * @return         proxy_worker or NULL if not found
   791   */
   792  PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
   793                                                    proxy_balancer *balancer,
   794                                                    proxy_server_conf *conf,
   795                                                    const char *url);
   796  
   797  /**
   798   * Define and Allocate space for the worker to proxy configuration, of either
   799   * PREFIXED or MATCHED type according to given mask
   800   * @param p         memory pool to allocate worker from
   801   * @param worker    the new worker
   802   * @param balancer  the balancer that the worker belongs to
   803   * @param conf      current proxy server configuration
   804   * @param url       url containing worker name
   805   * @param mask      bitmask of AP_PROXY_WORKER_IS_*
   806   * @return          error message or NULL if successful (*worker is new worker)
   807   */
   808  PROXY_DECLARE(char *) ap_proxy_define_worker_ex(apr_pool_t *p,
   809                                               proxy_worker **worker,
   810                                               proxy_balancer *balancer,
   811                                               proxy_server_conf *conf,
   812                                               const char *url,
   813                                               unsigned int mask);
   814  
   815   /**
   816   * Define and Allocate space for the worker to proxy configuration
   817   * @param p         memory pool to allocate worker from
   818   * @param worker    the new worker
   819   * @param balancer  the balancer that the worker belongs to
   820   * @param conf      current proxy server configuration
   821   * @param url       url containing worker name
   822   * @param do_malloc true if shared struct should be malloced
   823   * @return          error message or NULL if successful (*worker is new worker)
   824   */
   825  PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
   826                                               proxy_worker **worker,
   827                                               proxy_balancer *balancer,
   828                                               proxy_server_conf *conf,
   829                                               const char *url,
   830                                               int do_malloc);
   831  
   832  /**
   833   * Define and Allocate space for the ap_strcmp_match()able worker to proxy
   834   * configuration.
   835   * @param p         memory pool to allocate worker from
   836   * @param worker    the new worker
   837   * @param balancer  the balancer that the worker belongs to
   838   * @param conf      current proxy server configuration
   839   * @param url       url containing worker name (produces match pattern)
   840   * @param do_malloc true if shared struct should be malloced
   841   * @return          error message or NULL if successful (*worker is new worker)
   842   * @deprecated Replaced by ap_proxy_define_worker_ex()
   843   */
   844  PROXY_DECLARE(char *) ap_proxy_define_match_worker(apr_pool_t *p,
   845                                               proxy_worker **worker,
   846                                               proxy_balancer *balancer,
   847                                               proxy_server_conf *conf,
   848                                               const char *url,
   849                                               int do_malloc);
   850  
   851  /**
   852   * Share a defined proxy worker via shm
   853   * @param worker  worker to be shared
   854   * @param shm     location of shared info
   855   * @param i       index into shm
   856   * @return        APR_SUCCESS or error code
   857   */
   858  PROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker,
   859                                                    proxy_worker_shared *shm,
   860                                                    int i);
   861  
   862  /**
   863   * Initialize the worker by setting up worker connection pool and mutex
   864   * @param worker worker to initialize
   865   * @param s      current server record
   866   * @param p      memory pool used for mutex and connection pool
   867   * @return       APR_SUCCESS or error code
   868   */
   869  PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
   870                                                         server_rec *s,
   871                                                         apr_pool_t *p);
   872  
   873  /**
   874   * Verifies valid balancer name (eg: balancer://foo)
   875   * @param name  name to test
   876   * @param i     number of chars to test; 0 for all.
   877   * @return      true/false
   878   */
   879  PROXY_DECLARE(int) ap_proxy_valid_balancer_name(char *name, int i);
   880  
   881  
   882  /**
   883   * Get the balancer from proxy configuration
   884   * @param p     memory pool used for temporary storage while finding balancer
   885   * @param conf  current proxy server configuration
   886   * @param url   url to find the worker from; must have balancer:// prefix
   887   * @param careactive true if we care if the balancer is active or not
   888   * @return      proxy_balancer or NULL if not found
   889   */
   890  PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
   891                                                        proxy_server_conf *conf,
   892                                                        const char *url,
   893                                                        int careactive);
   894  
   895  /**
   896   * Update the balancer's vhost related fields
   897   * @param p     memory pool used for temporary storage while finding balancer
   898   * @param balancer  balancer to be updated
   899   * @param url   url to find vhost info
   900   * @return      error string or NULL if OK
   901   */
   902  PROXY_DECLARE(char *) ap_proxy_update_balancer(apr_pool_t *p,
   903                                                 proxy_balancer *balancer,
   904                                                 const char *url);
   905  
   906  /**
   907   * Define and Allocate space for the balancer to proxy configuration
   908   * @param p      memory pool to allocate balancer from
   909   * @param balancer the new balancer
   910   * @param conf   current proxy server configuration
   911   * @param url    url containing balancer name
   912   * @param alias  alias/fake-path to this balancer
   913   * @param do_malloc true if shared struct should be malloced
   914   * @return       error message or NULL if successful
   915   */
   916  PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p,
   917                                                 proxy_balancer **balancer,
   918                                                 proxy_server_conf *conf,
   919                                                 const char *url,
   920                                                 const char *alias,
   921                                                 int do_malloc);
   922  
   923  /**
   924   * Share a defined proxy balancer via shm
   925   * @param balancer  balancer to be shared
   926   * @param shm       location of shared info
   927   * @param i         index into shm
   928   * @return          APR_SUCCESS or error code
   929   */
   930  PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer,
   931                                                      proxy_balancer_shared *shm,
   932                                                      int i);
   933  
   934  /**
   935   * Initialize the balancer as needed
   936   * @param balancer balancer to initialize
   937   * @param s        current server record
   938   * @param p        memory pool used for mutex and connection pool
   939   * @return         APR_SUCCESS or error code
   940   */
   941  PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer,
   942                                                           server_rec *s,
   943                                                           apr_pool_t *p);
   944  
   945  typedef int (proxy_is_best_callback_fn_t)(proxy_worker *current, proxy_worker *prev_best, void *baton);
   946  
   947  /**
   948   * Retrieve the best worker in a balancer for the current request
   949   * @param balancer balancer for which to find the best worker
   950   * @param r        current request record
   951   * @param is_best  a callback function provide by the lbmethod
   952   *                 that determines if the current worker is best
   953   * @param baton    an lbmethod-specific context pointer (baton)
   954   *                 passed to the is_best callback
   955   * @return         the best worker to be used for the request
   956   */
   957  PROXY_DECLARE(proxy_worker *) ap_proxy_balancer_get_best_worker(proxy_balancer *balancer,
   958                                                                  request_rec *r,
   959                                                                  proxy_is_best_callback_fn_t *is_best,
   960                                                                  void *baton);
   961  /*
   962   * Needed by the lb modules.
   963   */
   964  APR_DECLARE_OPTIONAL_FN(proxy_worker *, proxy_balancer_get_best_worker,
   965                                          (proxy_balancer *balancer,
   966                                           request_rec *r,
   967                                           proxy_is_best_callback_fn_t *is_best,
   968                                           void *baton));
   969  
   970  /**
   971   * Find the shm of the worker as needed
   972   * @param storage slotmem provider
   973   * @param slot    slotmem instance
   974   * @param worker  worker to find
   975   * @param index   pointer to index within slotmem of worker
   976   * @return        pointer to shm of worker, or NULL
   977   */
   978  PROXY_DECLARE(proxy_worker_shared *) ap_proxy_find_workershm(ap_slotmem_provider_t *storage,
   979                                                               ap_slotmem_instance_t *slot,
   980                                                               proxy_worker *worker,
   981                                                               unsigned int *index);
   982  
   983  /**
   984   * Find the shm of the balancer as needed
   985   * @param storage  slotmem provider
   986   * @param slot     slotmem instance
   987   * @param balancer balancer of shm to find
   988   * @param index    pointer to index within slotmem of balancer
   989   * @return         pointer to shm of balancer, or NULL
   990   */
   991  PROXY_DECLARE(proxy_balancer_shared *) ap_proxy_find_balancershm(ap_slotmem_provider_t *storage,
   992                                                                   ap_slotmem_instance_t *slot,
   993                                                                   proxy_balancer *balancer,
   994                                                                   unsigned int *index);
   995  
   996  /**
   997   * Get the most suitable worker and/or balancer for the request
   998   * @param worker   worker used for processing request
   999   * @param balancer balancer used for processing request
  1000   * @param r        current request
  1001   * @param conf     current proxy server configuration
  1002   * @param url      request url that balancer can rewrite.
  1003   * @return         OK or  HTTP_XXX error
  1004   * @note It calls balancer pre_request hook if the url starts with balancer://
  1005   * The balancer then rewrites the url to particular worker, like http://host:port
  1006   */
  1007  PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
  1008                                          proxy_balancer **balancer,
  1009                                          request_rec *r,
  1010                                          proxy_server_conf *conf,
  1011                                          char **url);
  1012  /**
  1013   * Post request worker and balancer cleanup
  1014   * @param worker   worker used for processing request
  1015   * @param balancer balancer used for processing request
  1016   * @param r        current request
  1017   * @param conf     current proxy server configuration
  1018   * @return         OK or  HTTP_XXX error
  1019   * @note Whenever the pre_request is called, the post_request has to be
  1020   * called too.
  1021   */
  1022  PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
  1023                                           proxy_balancer *balancer,
  1024                                           request_rec *r,
  1025                                           proxy_server_conf *conf);
  1026  
  1027  /**
  1028   * Determine backend hostname and port
  1029   * @param p       memory pool used for processing
  1030   * @param r       current request
  1031   * @param conf    current proxy server configuration
  1032   * @param worker  worker used for processing request
  1033   * @param conn    proxy connection struct
  1034   * @param uri     processed uri
  1035   * @param url     request url
  1036   * @param proxyname are we connecting directly or via a proxy
  1037   * @param proxyport proxy host port
  1038   * @param server_portstr Via headers server port, must be non-NULL
  1039   * @param server_portstr_size size of the server_portstr buffer; must
  1040   * be at least one, even if the protocol doesn't use this
  1041   * @return         OK or HTTP_XXX error
  1042   */
  1043  PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
  1044                                                   proxy_server_conf *conf,
  1045                                                   proxy_worker *worker,
  1046                                                   proxy_conn_rec *conn,
  1047                                                   apr_uri_t *uri,
  1048                                                   char **url,
  1049                                                   const char *proxyname,
  1050                                                   apr_port_t proxyport,
  1051                                                   char *server_portstr,
  1052                                                   int server_portstr_size);
  1053  
  1054  /**
  1055   * Mark a worker for retry
  1056   * @param proxy_function calling proxy scheme (http, ajp, ...)
  1057   * @param worker  worker used for retrying
  1058   * @param s       current server record
  1059   * @return        OK if marked for retry, DECLINED otherwise
  1060   * @note The error status of the worker will cleared if the retry interval has
  1061   * elapsed since the last error.
  1062   */
  1063  APR_DECLARE_OPTIONAL_FN(int, ap_proxy_retry_worker,
  1064          (const char *proxy_function, proxy_worker *worker, server_rec *s));
  1065  
  1066  /**
  1067   * Acquire a connection from worker connection pool
  1068   * @param proxy_function calling proxy scheme (http, ajp, ...)
  1069   * @param conn    acquired connection
  1070   * @param worker  worker used for obtaining connection
  1071   * @param s       current server record
  1072   * @return        OK or HTTP_XXX error
  1073   * @note If the connection limit has been reached, the function will
  1074   * block until a connection becomes available or the timeout has
  1075   * elapsed.
  1076   */
  1077  PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
  1078                                                 proxy_conn_rec **conn,
  1079                                                 proxy_worker *worker,
  1080                                                 server_rec *s);
  1081  /**
  1082   * Release a connection back to worker connection pool
  1083   * @param proxy_function calling proxy scheme (http, ajp, ...)
  1084   * @param conn    acquired connection
  1085   * @param s       current server record
  1086   * @return        OK or HTTP_XXX error
  1087   * @note The connection will be closed if conn->close_on_release is set
  1088   */
  1089  PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
  1090                                                 proxy_conn_rec *conn,
  1091                                                 server_rec *s);
  1092  
  1093  #define PROXY_CHECK_CONN_EMPTY (1 << 0)
  1094  /**
  1095   * Check a connection to the backend
  1096   * @param scheme calling proxy scheme (http, ajp, ...)
  1097   * @param conn   acquired connection
  1098   * @param server current server record
  1099   * @param max_blank_lines how many blank lines to consume,
  1100   *                        or zero for none (considered data)
  1101   * @param flags  PROXY_CHECK_* bitmask
  1102   * @return APR_SUCCESS: connection established,
  1103   *         APR_ENOTEMPTY: connection established with data,
  1104   *         APR_ENOSOCKET: not connected,
  1105   *         APR_EINVAL: worker in error state (unusable),
  1106   *         other: connection closed/aborted (remotely)
  1107   */
  1108  PROXY_DECLARE(apr_status_t) ap_proxy_check_connection(const char *scheme,
  1109                                                        proxy_conn_rec *conn,
  1110                                                        server_rec *server,
  1111                                                        unsigned max_blank_lines,
  1112                                                        int flags);
  1113  
  1114  /**
  1115   * Make a connection to the backend
  1116   * @param proxy_function calling proxy scheme (http, ajp, ...)
  1117   * @param conn    acquired connection
  1118   * @param worker  connection worker
  1119   * @param s       current server record
  1120   * @return        OK or HTTP_XXX error
  1121   * @note In case the socket already exists for conn, just check the link
  1122   * status.
  1123   */
  1124  PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
  1125                                              proxy_conn_rec *conn,
  1126                                              proxy_worker *worker,
  1127                                              server_rec *s);
  1128  
  1129  /**
  1130   * Make a connection to a Unix Domain Socket (UDS) path
  1131   * @param sock     UDS to connect
  1132   * @param uds_path UDS path to connect to
  1133   * @param p        pool to make the sock addr
  1134   * @return         APR_SUCCESS or error status
  1135   */
  1136  PROXY_DECLARE(apr_status_t) ap_proxy_connect_uds(apr_socket_t *sock,
  1137                                                   const char *uds_path,
  1138                                                   apr_pool_t *p);
  1139  /**
  1140   * Make a connection record for backend connection
  1141   * @param proxy_function calling proxy scheme (http, ajp, ...)
  1142   * @param conn    acquired connection
  1143   * @param c       client connection record (unused, deprecated)
  1144   * @param s       current server record
  1145   * @return        OK or HTTP_XXX error
  1146   * @note The function will return immediately if conn->connection
  1147   * is already set,
  1148   */
  1149  PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
  1150                                                proxy_conn_rec *conn,
  1151                                                conn_rec *c, server_rec *s);
  1152  
  1153  /**
  1154   * Make a connection record for backend connection, using request dir config
  1155   * @param proxy_function calling proxy scheme (http, ajp, ...)
  1156   * @param conn    acquired connection
  1157   * @param r       current request record
  1158   * @return        OK or HTTP_XXX error
  1159   * @note The function will return immediately if conn->connection
  1160   * is already set,
  1161   */
  1162  PROXY_DECLARE(int) ap_proxy_connection_create_ex(const char *proxy_function,
  1163                                                   proxy_conn_rec *conn,
  1164                                                   request_rec *r);
  1165  /**
  1166   * Determine if proxy connection can potentially be reused at the
  1167   * end of this request.
  1168   * @param conn proxy connection
  1169   * @return non-zero if reusable, 0 otherwise
  1170   * @note Even if this function returns non-zero, the connection may
  1171   * be subsequently marked for closure.
  1172   */
  1173  PROXY_DECLARE(int) ap_proxy_connection_reusable(proxy_conn_rec *conn);
  1174  
  1175  /**
  1176   * Signal the upstream chain that the connection to the backend broke in the
  1177   * middle of the response. This is done by sending an error bucket with
  1178   * status HTTP_BAD_GATEWAY and an EOS bucket up the filter chain.
  1179   * @param r       current request record of client request
  1180   * @param brigade The brigade that is sent through the output filter chain
  1181   */
  1182  PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
  1183                                             apr_bucket_brigade *brigade);
  1184  
  1185  /**
  1186   * Return a hash based on the passed string
  1187   * @param str     string to produce hash from
  1188   * @param method  hashing method to use
  1189   * @return        hash as unsigned int
  1190   */
  1191  
  1192  typedef enum { PROXY_HASHFUNC_DEFAULT, PROXY_HASHFUNC_APR,  PROXY_HASHFUNC_FNV } proxy_hash_t;
  1193  
  1194  PROXY_DECLARE(unsigned int) ap_proxy_hashfunc(const char *str, proxy_hash_t method);
  1195  
  1196  
  1197  /**
  1198   * Set/unset the worker status bitfield depending on flag
  1199   * @param c    flag
  1200   * @param set  set or unset bit
  1201   * @param w    worker to use
  1202   * @return     APR_SUCCESS if valid flag
  1203   */
  1204  PROXY_DECLARE(apr_status_t) ap_proxy_set_wstatus(char c, int set, proxy_worker *w);
  1205  
  1206  
  1207  /**
  1208   * Create readable representation of worker status bitfield
  1209   * @param p  pool
  1210   * @param w  worker to use
  1211   * @return   string representation of status
  1212   */
  1213  PROXY_DECLARE(char *) ap_proxy_parse_wstatus(apr_pool_t *p, proxy_worker *w);
  1214  
  1215  
  1216  /**
  1217   * Sync balancer and workers based on any updates w/i shm
  1218   * @param b  balancer to check/update member list of
  1219   * @param s  server rec
  1220   * @param conf config
  1221   * @return   APR_SUCCESS if all goes well
  1222   */
  1223  PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b,
  1224                                                     server_rec *s,
  1225                                                     proxy_server_conf *conf);
  1226  
  1227  /**
  1228   * Configure and create workers (and balancer) in mod_balancer.
  1229   * @param r request
  1230   * @param params table with the parameters like b=mycluster etc.
  1231   * @return 404 when the worker/balancer doesn't exist,
  1232   *         400 if something is invalid
  1233   *         200 for success.
  1234   */ 
  1235  APR_DECLARE_OPTIONAL_FN(apr_status_t, balancer_manage,
  1236          (request_rec *, apr_table_t *params));
  1237  
  1238  /**
  1239   * Find the matched alias for this request and setup for proxy handler
  1240   * @param r     request
  1241   * @param ent   proxy_alias record
  1242   * @param dconf per-dir config or NULL
  1243   * @return      OK if the alias matched,
  1244   *              DONE if the alias matched and r->uri was normalized so
  1245   *                   no further transformation should happen on it,
  1246   *              DECLINED if proxying is disabled for this alias,
  1247   *              HTTP_CONTINUE if the alias did not match
  1248   */
  1249  PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r,
  1250                                          struct proxy_alias *ent,
  1251                                          proxy_dir_conf *dconf);
  1252  
  1253  /**
  1254   * Create a HTTP request header brigade,  old_cl_val and old_te_val as required.
  1255   * @param p               pool
  1256   * @param header_brigade  header brigade to use/fill
  1257   * @param r               request
  1258   * @param p_conn          proxy connection rec
  1259   * @param worker          selected worker
  1260   * @param conf            per-server proxy config
  1261   * @param uri             uri
  1262   * @param url             url
  1263   * @param server_portstr  port as string
  1264   * @param old_cl_val      stored old content-len val
  1265   * @param old_te_val      stored old TE val
  1266   * @return                OK or HTTP_EXPECTATION_FAILED
  1267   */
  1268  PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p,
  1269                                             apr_bucket_brigade *header_brigade,
  1270                                             request_rec *r,
  1271                                             proxy_conn_rec *p_conn,
  1272                                             proxy_worker *worker,
  1273                                             proxy_server_conf *conf,
  1274                                             apr_uri_t *uri,
  1275                                             char *url, char *server_portstr,
  1276                                             char **old_cl_val,
  1277                                             char **old_te_val);
  1278  
  1279  /**
  1280   * Prefetch the client request body (in memory), up to a limit.
  1281   * Read what's in the client pipe. If nonblocking is set and read is EAGAIN,
  1282   * pass a FLUSH bucket to the backend and read again in blocking mode.
  1283   * @param r             client request
  1284   * @param backend       backend connection
  1285   * @param input_brigade input brigade to use/fill
  1286   * @param block         blocking or non-blocking mode
  1287   * @param bytes_read    number of bytes read
  1288   * @param max_read      maximum number of bytes to read
  1289   * @return              OK or HTTP_* error code
  1290   * @note max_read is rounded up to APR_BUCKET_BUFF_SIZE
  1291   */
  1292  PROXY_DECLARE(int) ap_proxy_prefetch_input(request_rec *r,
  1293                                             proxy_conn_rec *backend,
  1294                                             apr_bucket_brigade *input_brigade,
  1295                                             apr_read_type_e block,
  1296                                             apr_off_t *bytes_read,
  1297                                             apr_off_t max_read);
  1298  
  1299  /**
  1300   * Spool the client request body to memory, or disk above given limit.
  1301   * @param r             client request
  1302   * @param backend       backend connection
  1303   * @param input_brigade input brigade to use/fill
  1304   * @param bytes_spooled number of bytes spooled
  1305   * @param max_mem_spool maximum number of in-memory bytes
  1306   * @return              OK or HTTP_* error code
  1307   */
  1308  PROXY_DECLARE(int) ap_proxy_spool_input(request_rec *r,
  1309                                          proxy_conn_rec *backend,
  1310                                          apr_bucket_brigade *input_brigade,
  1311                                          apr_off_t *bytes_spooled,
  1312                                          apr_off_t max_mem_spool);
  1313  
  1314  /**
  1315   * Read what's in the client pipe. If the read would block (EAGAIN),
  1316   * pass a FLUSH bucket to the backend and read again in blocking mode.
  1317   * @param r             client request
  1318   * @param backend       backend connection
  1319   * @param input_brigade brigade to use/fill
  1320   * @param max_read      maximum number of bytes to read
  1321   * @return              OK or HTTP_* error code
  1322   */
  1323  PROXY_DECLARE(int) ap_proxy_read_input(request_rec *r,
  1324                                         proxy_conn_rec *backend,
  1325                                         apr_bucket_brigade *input_brigade,
  1326                                         apr_off_t max_read);
  1327  
  1328  /**
  1329   * @param bucket_alloc  bucket allocator
  1330   * @param r             request
  1331   * @param p_conn        proxy connection
  1332   * @param origin        connection rec of origin
  1333   * @param  bb           brigade to send to origin
  1334   * @param  flush        flush
  1335   * @return              status (OK)
  1336   */
  1337  PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc,
  1338                                           request_rec *r, proxy_conn_rec *p_conn,
  1339                                           conn_rec *origin, apr_bucket_brigade *bb,
  1340                                           int flush);
  1341  
  1342  struct proxy_tunnel_conn; /* opaque */
  1343  typedef struct {
  1344      request_rec *r;
  1345      const char *scheme;
  1346      apr_pollset_t *pollset;
  1347      apr_array_header_t *pfds;
  1348      apr_interval_time_t timeout;
  1349      struct proxy_tunnel_conn *client,
  1350                               *origin;
  1351      apr_size_t read_buf_size;
  1352      int replied; /* TODO 2.5+: one bit to merge in below bitmask */
  1353      unsigned int nohalfclose :1;
  1354  } proxy_tunnel_rec;
  1355  
  1356  /**
  1357   * Create a tunnel, to be activated by ap_proxy_tunnel_run().
  1358   * @param tunnel   tunnel created
  1359   * @param r        client request
  1360   * @param c_o      connection to origin
  1361   * @param scheme   caller proxy scheme (connect, ws(s), http(s), ...)
  1362   * @return         APR_SUCCESS or error status
  1363   */
  1364  PROXY_DECLARE(apr_status_t) ap_proxy_tunnel_create(proxy_tunnel_rec **tunnel,
  1365                                                     request_rec *r, conn_rec *c_o,
  1366                                                     const char *scheme);
  1367  
  1368  /**
  1369   * Forward anything from either side of the tunnel to the other,
  1370   * until one end aborts or a polling timeout/error occurs.
  1371   * @param tunnel  tunnel to run
  1372   * @return        OK if completion is full, HTTP_GATEWAY_TIME_OUT on timeout
  1373   *                or another HTTP_ error otherwise.
  1374   */
  1375  PROXY_DECLARE(int) ap_proxy_tunnel_run(proxy_tunnel_rec *tunnel);
  1376  
  1377  /**
  1378   * Clear the headers referenced by the Connection header from the given
  1379   * table, and remove the Connection header.
  1380   * @param r request
  1381   * @param headers table of headers to clear
  1382   * @return 1 if "close" was present, 0 otherwise.
  1383   */
  1384  APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection,
  1385          (request_rec *r, apr_table_t *headers));
  1386  
  1387  /**
  1388   * Do a AJP CPING and wait for CPONG on the socket
  1389   *
  1390   */
  1391  APR_DECLARE_OPTIONAL_FN(apr_status_t, ajp_handle_cping_cpong,
  1392          (apr_socket_t *sock, request_rec *r,
  1393           apr_interval_time_t timeout));
  1394  
  1395  
  1396  /**
  1397   * @param socket        socket to test
  1398   * @return              TRUE if socket is connected/active
  1399   */
  1400  PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket);
  1401  
  1402  #define PROXY_LBMETHOD "proxylbmethod"
  1403  
  1404  /* The number of dynamic workers that can be added when reconfiguring.
  1405   * If this limit is reached you must stop and restart the server.
  1406   */
  1407  #define PROXY_DYNAMIC_BALANCER_LIMIT    16
  1408  
  1409  /**
  1410   * Calculate maximum number of workers in scoreboard.
  1411   * @return  number of workers to allocate in the scoreboard
  1412   */
  1413  int ap_proxy_lb_workers(void);
  1414  
  1415  /**
  1416   * Returns 1 if a response with the given status should be overridden.
  1417   *
  1418   * @param conf   proxy directory configuration
  1419   * @param code   http status code
  1420   * @return       1 if code is considered an error-code, 0 otherwise
  1421   */
  1422  PROXY_DECLARE(int) ap_proxy_should_override(proxy_dir_conf *conf, int code);
  1423  
  1424  /**
  1425   * Return the port number of a known scheme (eg: http -> 80).
  1426   * @param scheme        scheme to test
  1427   * @return              port number or 0 if unknown
  1428   */
  1429  PROXY_DECLARE(apr_port_t) ap_proxy_port_of_scheme(const char *scheme);
  1430  
  1431  /**
  1432   * Return the name of the health check method (eg: "OPTIONS").
  1433   * @param method        method enum
  1434   * @return              name of method
  1435   */
  1436  PROXY_DECLARE (const char *) ap_proxy_show_hcmethod(hcmethod_t method);
  1437  
  1438  /**
  1439   * Strip a unix domain socket (UDS) prefix from the input URL
  1440   * @param p             pool to allocate result from
  1441   * @param url           a URL potentially prefixed with a UDS path
  1442   * @return              URL with the UDS prefix removed
  1443   */
  1444  PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url);
  1445  
  1446  /*
  1447   * Transform buckets from one bucket allocator to another one by creating a
  1448   * transient bucket for each data bucket and let it use the data read from
  1449   * the old bucket. Metabuckets are transformed by just recreating them.
  1450   * Attention: Currently only the following bucket types are handled:
  1451   *
  1452   * All data buckets
  1453   * FLUSH
  1454   * EOS
  1455   *
  1456   * If an other bucket type is found its type is logged as a debug message
  1457   * and APR_EGENERAL is returned.
  1458   *
  1459   * @param r     request_rec of the actual request. Used for logging purposes
  1460   * @param from  the bucket brigade to take the buckets from
  1461   * @param to    the bucket brigade to store the transformed buckets
  1462   * @return      apr_status_t of the operation. Either APR_SUCCESS or
  1463   *              APR_EGENERAL
  1464   */
  1465  PROXY_DECLARE(apr_status_t) ap_proxy_buckets_lifetime_transform(request_rec *r,
  1466                                                        apr_bucket_brigade *from,
  1467                                                        apr_bucket_brigade *to);
  1468  
  1469  /* 
  1470   * The flags for ap_proxy_transfer_between_connections(), where for legacy and
  1471   * compatibility reasons FLUSH_EACH and FLUSH_AFTER are boolean values.
  1472   */
  1473  #define AP_PROXY_TRANSFER_FLUSH_EACH        (0x00)
  1474  #define AP_PROXY_TRANSFER_FLUSH_AFTER       (0x01)
  1475  #define AP_PROXY_TRANSFER_YIELD_PENDING     (0x02)
  1476  #define AP_PROXY_TRANSFER_YIELD_MAX_READS   (0x04)
  1477  
  1478  /*
  1479   * Sends all data that can be read non blocking from the input filter chain of
  1480   * c_i and send it down the output filter chain of c_o. For reading it uses
  1481   * the bucket brigade bb_i which should be created from the bucket allocator
  1482   * associated with c_i. For sending through the output filter chain it uses
  1483   * the bucket brigade bb_o which should be created from the bucket allocator
  1484   * associated with c_o. In order to get the buckets from bb_i to bb_o
  1485   * ap_proxy_buckets_lifetime_transform is used.
  1486   *
  1487   * @param r     request_rec of the actual request. Used for logging purposes
  1488   * @param c_i   inbound connection conn_rec
  1489   * @param c_o   outbound connection conn_rec
  1490   * @param bb_i  bucket brigade for pulling data from the inbound connection
  1491   * @param bb_o  bucket brigade for sending data through the outbound connection
  1492   * @param name  string for logging from where data was pulled
  1493   * @param sent  if not NULL will be set to 1 if data was sent through c_o
  1494   * @param bsize maximum amount of data pulled in one iteration from c_i
  1495   * @param flags AP_PROXY_TRANSFER_* bitmask
  1496   * @return      apr_status_t of the operation. Could be any error returned from
  1497   *              either the input filter chain of c_i or the output filter chain
  1498   *              of c_o, APR_EPIPE if the outgoing connection was aborted, or
  1499   *              APR_INCOMPLETE if AP_PROXY_TRANSFER_YIELD_PENDING was set and
  1500   *              the output stack gets full before the input stack is exhausted.
  1501   */
  1502  PROXY_DECLARE(apr_status_t) ap_proxy_transfer_between_connections(
  1503                                                         request_rec *r,
  1504                                                         conn_rec *c_i,
  1505                                                         conn_rec *c_o,
  1506                                                         apr_bucket_brigade *bb_i,
  1507                                                         apr_bucket_brigade *bb_o,
  1508                                                         const char *name,
  1509                                                         int *sent,
  1510                                                         apr_off_t bsize,
  1511                                                         int flags);
  1512  
  1513  extern module PROXY_DECLARE_DATA proxy_module;
  1514  
  1515  #endif /*MOD_PROXY_H*/
  1516  /** @} */