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/*
30
31   Also note numerous FIXMEs and CHECKMEs which should be eliminated.
32
33   This code is once again experimental!
34
35   Things to do:
36
37   1. Make it completely work (for FTP too)
38
39   2. HTTP/1.1
40
41   Chuck Murcko <chuck@topsail.org> 02-06-01
42
43 */
44
45#define CORE_PRIVATE
46
47#include "apr_hooks.h"
48#include "apr.h"
49#include "apr_lib.h"
50#include "apr_strings.h"
51#include "apr_buckets.h"
52#include "apr_md5.h"
53#include "apr_network_io.h"
54#include "apr_pools.h"
55#include "apr_strings.h"
56#include "apr_uri.h"
57#include "apr_date.h"
58#include "apr_strmatch.h"
59#include "apr_fnmatch.h"
60#include "apr_reslist.h"
61#define APR_WANT_STRFUNC
62#include "apr_want.h"
63
64#include "httpd.h"
65#include "http_config.h"
66#include "ap_config.h"
67#include "http_core.h"
68#include "http_protocol.h"
69#include "http_request.h"
70#include "http_vhost.h"
71#include "http_main.h"
72#include "http_log.h"
73#include "http_connection.h"
74#include "util_filter.h"
75#include "util_ebcdic.h"
76#include "ap_provider.h"
77
78#if APR_HAVE_NETINET_IN_H
79#include <netinet/in.h>
80#endif
81#if APR_HAVE_ARPA_INET_H
82#include <arpa/inet.h>
83#endif
84
85/* for proxy_canonenc() */
86enum enctype {
87    enc_path, enc_search, enc_user, enc_fpath, enc_parm
88};
89
90#if APR_CHARSET_EBCDIC
91#define CRLF   "\r\n"
92#else /*APR_CHARSET_EBCDIC*/
93#define CRLF   "\015\012"
94#endif /*APR_CHARSET_EBCDIC*/
95
96/* default Max-Forwards header setting */
97/* Set this to -1, which complies with RFC2616 by not setting
98 * max-forwards if the client didn't send it to us.
99 */
100#define DEFAULT_MAX_FORWARDS    -1
101
102/* static information about a remote proxy */
103struct proxy_remote {
104    const char *scheme;     /* the schemes handled by this proxy, or '*' */
105    const char *protocol;   /* the scheme used to talk to this proxy */
106    const char *hostname;   /* the hostname of this proxy */
107    apr_port_t  port;       /* the port for this proxy */
108    ap_regex_t *regexp;        /* compiled regex (if any) for the remote */
109    int use_regex;          /* simple boolean. True if we have a regex pattern */
110};
111
112#define PROXYPASS_NOCANON 0x01
113#define PROXYPASS_INTERPOLATE 0x02
114struct proxy_alias {
115    const char  *real;
116    const char  *fake;
117    ap_regex_t  *regex;
118    unsigned int flags;
119};
120
121struct dirconn_entry {
122    char *name;
123    struct in_addr addr, mask;
124    struct apr_sockaddr_t *hostaddr;
125    int (*matcher) (struct dirconn_entry * This, request_rec *r);
126};
127
128struct noproxy_entry {
129    const char *name;
130    struct apr_sockaddr_t *addr;
131};
132
133typedef struct proxy_balancer  proxy_balancer;
134typedef struct proxy_worker    proxy_worker;
135typedef struct proxy_conn_pool proxy_conn_pool;
136typedef struct proxy_balancer_method proxy_balancer_method;
137
138typedef struct {
139    apr_array_header_t *proxies;
140    apr_array_header_t *sec_proxy;
141    apr_array_header_t *aliases;
142    apr_array_header_t *noproxies;
143    apr_array_header_t *dirconn;
144    apr_array_header_t *allowed_connect_ports;
145    apr_array_header_t *workers;
146    apr_array_header_t *balancers;
147    proxy_worker       *forward;    /* forward proxy worker */
148    proxy_worker       *reverse;    /* reverse "module-driven" proxy worker */
149    const char *domain;     /* domain name to use in absence of a domain name in the request */
150    int req;                /* true if proxy requests are enabled */
151    char req_set;
152    enum {
153      via_off,
154      via_on,
155      via_block,
156      via_full
157    } viaopt;                   /* how to deal with proxy Via: headers */
158    char viaopt_set;
159    apr_size_t recv_buffer_size;
160    char recv_buffer_size_set;
161    apr_size_t io_buffer_size;
162    char io_buffer_size_set;
163    long maxfwd;
164    char maxfwd_set;
165    /**
166     * the following setting masks the error page
167     * returned from the 'proxied server' and just
168     * forwards the status code upwards.
169     * This allows the main server (us) to generate
170     * the error page, (so it will look like a error
171     * returned from the rest of the system
172     */
173    int error_override;
174    int error_override_set;
175    int preserve_host;
176    int preserve_host_set;
177    apr_interval_time_t timeout;
178    char timeout_set;
179    enum {
180      bad_error,
181      bad_ignore,
182      bad_body
183    } badopt;                   /* how to deal with bad headers */
184    char badopt_set;
185/* putting new stuff on the end maximises binary back-compatibility.
186 * the strmatch_patterns are really a const just to have a
187 * case-independent strstr.
188 */
189    enum {
190        status_off,
191        status_on,
192        status_full
193    } proxy_status;             /* Status display options */
194    char proxy_status_set;
195    apr_pool_t *pool;           /* Pool used for allocating this struct */
196} proxy_server_conf;
197
198
199typedef struct {
200    const char *p;            /* The path */
201    int         p_is_fnmatch; /* Is this path an fnmatch candidate? */
202    ap_regex_t  *r;            /* Is this a regex? */
203
204/* ProxyPassReverse and friends are documented as working inside
205 * <Location>.  But in fact they never have done in the case of
206 * more than one <Location>, because the server_conf can't see it.
207 * We need to move them to the per-dir config.
208 * Discussed in February:
209 * http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=110726027118798&w=2
210 */
211    apr_array_header_t *raliases;
212    apr_array_header_t* cookie_paths;
213    apr_array_header_t* cookie_domains;
214    const apr_strmatch_pattern* cookie_path_str;
215    const apr_strmatch_pattern* cookie_domain_str;
216    const char *ftp_directory_charset;
217    int interpolate_env;
218} proxy_dir_conf;
219
220/* if we interpolate env vars per-request, we'll need a per-request
221 * copy of the reverse proxy config
222 */
223typedef struct {
224    apr_array_header_t *raliases;
225    apr_array_header_t* cookie_paths;
226    apr_array_header_t* cookie_domains;
227} proxy_req_conf;
228
229typedef struct {
230    conn_rec     *connection;
231    const char   *hostname;
232    apr_port_t   port;
233    int          is_ssl;
234    apr_pool_t   *pool;     /* Subpool for hostname and addr data */
235    apr_socket_t *sock;     /* Connection socket */
236    apr_sockaddr_t *addr;   /* Preparsed remote address info */
237    apr_uint32_t flags;     /* Conection flags */
238    int          close;     /* Close 'this' connection */
239    int          close_on_recycle; /* Close the connection when returning to pool */
240    proxy_worker *worker;   /* Connection pool this connection belongs to */
241    void         *data;     /* per scheme connection data */
242#if APR_HAS_THREADS
243    int          inreslist; /* connection in apr_reslist? */
244#endif
245    apr_pool_t   *scpool;   /* Subpool used for socket and connection data */
246    request_rec  *r;        /* Request record of the frontend request
247                             * which the backend currently answers. */
248    int          need_flush;/* Flag to decide whether we need to flush the
249                             * filter chain or not */
250    void         *forward;  /* opaque forward proxy data */
251} proxy_conn_rec;
252
253typedef struct {
254        float cache_completion; /* completion percentage */
255        int content_length; /* length of the content */
256} proxy_completion;
257
258/* Connection pool */
259struct proxy_conn_pool {
260    apr_pool_t     *pool;   /* The pool used in constructor and destructor calls */
261    apr_sockaddr_t *addr;   /* Preparsed remote address info */
262#if APR_HAS_THREADS
263    apr_reslist_t  *res;    /* Connection resource list */
264#endif
265    proxy_conn_rec *conn;   /* Single connection for prefork mpm's */
266};
267
268/* worker status flags */
269#define PROXY_WORKER_INITIALIZED    0x0001
270#define PROXY_WORKER_IGNORE_ERRORS  0x0002
271#define PROXY_WORKER_IN_SHUTDOWN    0x0010
272#define PROXY_WORKER_DISABLED       0x0020
273#define PROXY_WORKER_STOPPED        0x0040
274#define PROXY_WORKER_IN_ERROR       0x0080
275#define PROXY_WORKER_HOT_STANDBY    0x0100
276
277#define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \
278PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR )
279
280/* NOTE: these check the shared status */
281#define PROXY_WORKER_IS_INITIALIZED(f)   ( (f)->s && \
282  ( (f)->s->status &  PROXY_WORKER_INITIALIZED ) )
283
284#define PROXY_WORKER_IS_STANDBY(f)   ( (f)->s && \
285  ( (f)->s->status &  PROXY_WORKER_HOT_STANDBY ) )
286
287#define PROXY_WORKER_IS_USABLE(f)   ( (f)->s && \
288  ( !( (f)->s->status & PROXY_WORKER_NOT_USABLE_BITMAP) ) && \
289  PROXY_WORKER_IS_INITIALIZED(f) )
290
291/* default worker retry timeout in seconds */
292#define PROXY_WORKER_DEFAULT_RETRY  60
293#define PROXY_WORKER_MAX_ROUTE_SIZ  63
294
295/* Runtime worker status informations. Shared in scoreboard */
296typedef struct {
297    int             status;
298    apr_time_t      error_time; /* time of the last error */
299    int             retries;    /* number of retries on this worker */
300    int             lbstatus;   /* Current lbstatus */
301    int             lbfactor;   /* dynamic lbfactor */
302    apr_off_t       transferred;/* Number of bytes transferred to remote */
303    apr_off_t       read;       /* Number of bytes read from remote */
304    apr_size_t      elected;    /* Number of times the worker was elected */
305    char            route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
306    char            redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
307    void            *context;   /* general purpose storage */
308    apr_size_t      busy;       /* busyness factor */
309    int             lbset;      /* load balancer cluster set */
310} proxy_worker_stat;
311
312/* Worker configuration */
313struct proxy_worker {
314    int             id;         /* scoreboard id */
315    apr_interval_time_t retry;  /* retry interval */
316    int             lbfactor;   /* initial load balancing factor */
317    const char      *name;
318    const char      *scheme;    /* scheme to use ajp|http|https */
319    const char      *hostname;  /* remote backend address */
320    const char      *route;     /* balancing route */
321    const char      *redirect;  /* temporary balancing redirection route */
322    int             status;     /* temporary worker status */
323    apr_port_t      port;
324    int             min;        /* Desired minimum number of available connections */
325    int             smax;       /* Soft maximum on the total number of connections */
326    int             hmax;       /* Hard maximum on the total number of connections */
327    apr_interval_time_t ttl;    /* maximum amount of time in seconds a connection
328                                 * may be available while exceeding the soft limit */
329    apr_interval_time_t timeout; /* connection timeout */
330    char            timeout_set;
331    apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
332    char            acquire_set;
333    apr_size_t      recv_buffer_size;
334    char            recv_buffer_size_set;
335    apr_size_t      io_buffer_size;
336    char            io_buffer_size_set;
337    char            keepalive;
338    char            keepalive_set;
339    proxy_conn_pool     *cp;        /* Connection pool to use */
340    proxy_worker_stat   *s;         /* Shared data */
341    void            *opaque;    /* per scheme worker data */
342    int             is_address_reusable;
343#if APR_HAS_THREADS
344    apr_thread_mutex_t  *mutex;  /* Thread lock for updating address cache */
345#endif
346    void            *context;   /* general purpose storage */
347    enum {
348         flush_off,
349         flush_on,
350         flush_auto
351    } flush_packets;           /* control AJP flushing */
352    int             flush_wait;  /* poll wait time in microseconds if flush_auto */
353    int             lbset;      /* load balancer cluster set */
354    apr_interval_time_t ping_timeout;
355    char ping_timeout_set;
356    char            retry_set;
357    char            disablereuse;
358    char            disablereuse_set;
359    apr_interval_time_t conn_timeout;
360    char            conn_timeout_set;
361};
362
363/*
364 * Wait 10000 microseconds to find out if more data is currently
365 * available at the backend. Just an arbitrary choose.
366 */
367#define PROXY_FLUSH_WAIT 10000
368
369struct proxy_balancer {
370    apr_array_header_t *workers; /* array of proxy_workers */
371    const char *name;            /* name of the load balancer */
372    const char *sticky;          /* sticky session identifier */
373    int         sticky_force;    /* Disable failover for sticky sessions */
374    apr_interval_time_t timeout; /* Timeout for waiting on free connection */
375    int                 max_attempts; /* Number of attempts before failing */
376    char                max_attempts_set;
377    proxy_balancer_method *lbmethod;
378
379    /* XXX: Perhaps we will need the proc mutex too.
380     * Altrough we are only using arithmetic operations
381     * it may lead to a incorrect calculations.
382     * For now use only the thread mutex.
383     */
384#if APR_HAS_THREADS
385    apr_thread_mutex_t  *mutex;  /* Thread lock for updating lb params */
386#endif
387    void            *context;   /* general purpose storage */
388    int             scolonsep;  /* true if ';' seps sticky session paths */
389
390    apr_array_header_t *errstatuses; /* statuses to force members into error */
391    int forcerecovery; /* Force recovery if all workers are in error state */
392    int failontimeout;          /* Whether to mark a member in Err if IO timeout occurs */
393};
394
395struct proxy_balancer_method {
396    const char *name;            /* name of the load balancer method*/
397    proxy_worker *(*finder)(proxy_balancer *balancer,
398                            request_rec *r);
399    void            *context;   /* general purpose storage */
400};
401
402#if APR_HAS_THREADS
403#define PROXY_THREAD_LOCK(x)      apr_thread_mutex_lock((x)->mutex)
404#define PROXY_THREAD_UNLOCK(x)    apr_thread_mutex_unlock((x)->mutex)
405#else
406#define PROXY_THREAD_LOCK(x)      APR_SUCCESS
407#define PROXY_THREAD_UNLOCK(x)    APR_SUCCESS
408#endif
409
410/* hooks */
411
412/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
413 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
414 */
415#if !defined(WIN32)
416#define PROXY_DECLARE(type)            type
417#define PROXY_DECLARE_NONSTD(type)     type
418#define PROXY_DECLARE_DATA
419#elif defined(PROXY_DECLARE_STATIC)
420#define PROXY_DECLARE(type)            type __stdcall
421#define PROXY_DECLARE_NONSTD(type)     type
422#define PROXY_DECLARE_DATA
423#elif defined(PROXY_DECLARE_EXPORT)
424#define PROXY_DECLARE(type)            __declspec(dllexport) type __stdcall
425#define PROXY_DECLARE_NONSTD(type)     __declspec(dllexport) type
426#define PROXY_DECLARE_DATA             __declspec(dllexport)
427#else
428#define PROXY_DECLARE(type)            __declspec(dllimport) type __stdcall
429#define PROXY_DECLARE_NONSTD(type)     __declspec(dllimport) type
430#define PROXY_DECLARE_DATA             __declspec(dllimport)
431#endif
432
433/**
434 * Hook an optional proxy hook.  Unlike static hooks, this uses a macro
435 * instead of a function.
436 */
437#define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
438        APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
439
440APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
441                          proxy_worker *worker, proxy_server_conf *conf, char *url,
442                          const char *proxyhost, apr_port_t proxyport))
443APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
444                          char *url))
445
446APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
447APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
448
449/**
450 * pre request hook.
451 * It will return the most suitable worker at the moment
452 * and coresponding balancer.
453 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
454 * and then the scheme_handler is called.
455 *
456 */
457APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
458                          proxy_balancer **balancer,
459                          request_rec *r,
460                          proxy_server_conf *conf, char **url))
461/**
462 * post request hook.
463 * It is called after request for updating runtime balancer status.
464 */
465APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
466                          proxy_balancer *balancer, request_rec *r,
467                          proxy_server_conf *conf))
468
469/**
470 * request status hook
471 * It is called after all proxy processing has been done.  This gives other
472 * modules a chance to create default content on failure, for example
473 */
474APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status,
475                          (int *status, request_rec *r))
476
477/* proxy_util.c */
478
479PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
480PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
481PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
482PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
483                                       int forcedec, int proxyreq);
484PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
485                                           char **passwordp, char **hostp, apr_port_t *port);
486PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
487PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
488PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
489PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
490PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
491PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
492PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
493PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
494PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
495PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
496PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
497PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
498PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, apr_size_t bufflen, int *eos);
499PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
500/* DEPRECATED (will be replaced with ap_proxy_connect_backend */
501PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, server_rec *, apr_pool_t *);
502PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
503                                                            request_rec *r);
504PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
505PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
506PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
507PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
508
509/* Header mapping functions, and a typedef of their signature */
510PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url);
511PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str);
512
513#if !defined(WIN32)
514typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
515                       proxy_dir_conf *, const char *);
516#elif defined(PROXY_DECLARE_STATIC)
517typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
518                                 proxy_dir_conf *, const char *);
519#elif defined(PROXY_DECLARE_EXPORT)
520typedef __declspec(dllexport) const char *
521  (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
522               proxy_dir_conf *, const char *);
523#else
524typedef __declspec(dllimport) const char *
525  (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
526               proxy_dir_conf *, const char *);
527#endif
528
529
530/* Connection pool API */
531/**
532 * Get the worker from proxy configuration
533 * @param p     memory pool used for finding worker
534 * @param conf  current proxy server configuration
535 * @param url   url to find the worker from
536 * @return      proxy_worker or NULL if not found
537 */
538PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
539                                                  proxy_server_conf *conf,
540                                                  const char *url);
541/**
542 * Add the worker to proxy configuration
543 * @param worker the new worker
544 * @param p      memory pool to allocate worker from
545 * @param conf   current proxy server configuration
546 * @param url    url containing worker name
547 * @return       error message or NULL if successfull
548 */
549PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
550                                                apr_pool_t *p,
551                                                proxy_server_conf *conf,
552                                                const char *url);
553
554/**
555 * Create new worker
556 * @param p      memory pool to allocate worker from
557 * @return       new worker
558 */
559PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
560
561/**
562 * Initize the worker's shared data
563 * @param conf   current proxy server configuration
564 * @param worker worker to initialize
565 * @param s      current server record
566 * @param worker worker to initialize
567 */
568PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
569                                                     proxy_worker *worker,
570                                                     server_rec *s);
571
572
573/**
574 * Initize the worker
575 * @param worker worker to initialize
576 * @param s      current server record
577 * @return       APR_SUCCESS or error code
578 */
579PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
580                                                       server_rec *s);
581/**
582 * Get the balancer from proxy configuration
583 * @param p     memory pool used for finding balancer
584 * @param conf  current proxy server configuration
585 * @param url   url to find the worker from. Has to have balancer:// prefix
586 * @return      proxy_balancer or NULL if not found
587 */
588PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
589                                                      proxy_server_conf *conf,
590                                                      const char *url);
591/**
592 * Add the balancer to proxy configuration
593 * @param balancer the new balancer
594 * @param p      memory pool to allocate balancer from
595 * @param conf   current proxy server configuration
596 * @param url    url containing balancer name
597 * @return       error message or NULL if successfull
598 */
599PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
600                                                  apr_pool_t *p,
601                                                  proxy_server_conf *conf,
602                                                  const char *url);
603
604/**
605 * Add the worker to the balancer
606 * @param pool     memory pool for adding worker
607 * @param balancer balancer to add to
608 * @param balancer worker to add
609 * @note Single worker can be added to multiple balancers.
610 */
611PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
612                                                    proxy_balancer *balancer,
613                                                    proxy_worker *worker);
614/**
615 * Get the most suitable worker and(or) balancer for the request
616 * @param worker   worker used for processing request
617 * @param balancer balancer used for processing request
618 * @param r        current request
619 * @param conf     current proxy server configuration
620 * @param url      request url that balancer can rewrite.
621 * @return         OK or  HTTP_XXX error
622 * @note It calls balancer pre_request hook if the url starts with balancer://
623 * The balancer then rewrites the url to particular worker, like http://host:port
624 */
625PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
626                                        proxy_balancer **balancer,
627                                        request_rec *r,
628                                        proxy_server_conf *conf,
629                                        char **url);
630/**
631 * Post request worker and balancer cleanup
632 * @param worker   worker used for processing request
633 * @param balancer balancer used for processing request
634 * @param r        current request
635 * @param conf     current proxy server configuration
636 * @return         OK or  HTTP_XXX error
637 * @note When ever the pre_request is called, the post_request has to be
638 * called too.
639 */
640PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
641                                         proxy_balancer *balancer,
642                                         request_rec *r,
643                                         proxy_server_conf *conf);
644
645/**
646 * Deternime backend hostname and port
647 * @param p       memory pool used for processing
648 * @param r       current request
649 * @param conf    current proxy server configuration
650 * @param worker  worker used for processing request
651 * @param conn    proxy connection struct
652 * @param uri     processed uri
653 * @param url     request url
654 * @param proxyname are we connecting directly or via s proxy
655 * @param proxyport proxy host port
656 * @param server_portstr Via headers server port
657 * @param server_portstr_size size of the server_portstr buffer
658 * @return         OK or HTTP_XXX error
659 */
660PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
661                                                 proxy_server_conf *conf,
662                                                 proxy_worker *worker,
663                                                 proxy_conn_rec *conn,
664                                                 apr_uri_t *uri,
665                                                 char **url,
666                                                 const char *proxyname,
667                                                 apr_port_t proxyport,
668                                                 char *server_portstr,
669                                                 int server_portstr_size);
670/**
671 * Mark a worker for retry
672 * @param proxy_function calling proxy scheme (http, ajp, ...)
673 * @param conf    current proxy server configuration
674 * @param worker  worker used for retrying
675 * @param s       current server record
676 * @return        OK if marked for retry, DECLINED otherwise
677 * @note Worker will be marker for retry if the time of the last retry
678 * has been ellapsed. In case there is no retry option set, defaults to
679 * number_of_retries seconds.
680 */
681PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
682                                         proxy_worker *worker,
683                                         server_rec *s);
684/**
685 * Acquire a connection from workers connection pool
686 * @param proxy_function calling proxy scheme (http, ajp, ...)
687 * @param conn    acquired connection
688 * @param worker  worker used for obtaining connection
689 * @param s       current server record
690 * @return        OK or HTTP_XXX error
691 * @note If the number of connections is exhaused the function will
692 * block untill the timeout is reached.
693 */
694PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
695                                               proxy_conn_rec **conn,
696                                               proxy_worker *worker,
697                                               server_rec *s);
698/**
699 * Release a connection back to worker connection pool
700 * @param proxy_function calling proxy scheme (http, ajp, ...)
701 * @param conn    acquired connection
702 * @param s       current server record
703 * @return        OK or HTTP_XXX error
704 * @note The connection will be closed if conn->close_on_release is set
705 */
706PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
707                                               proxy_conn_rec *conn,
708                                               server_rec *s);
709/**
710 * Make a connection to the backend
711 * @param proxy_function calling proxy scheme (http, ajp, ...)
712 * @param conn    acquired connection
713 * @param worker  connection worker
714 * @param s       current server record
715 * @return        OK or HTTP_XXX error
716 * @note In case the socket already exists for conn, just check the link
717 * status.
718 */
719PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
720                                            proxy_conn_rec *conn,
721                                            proxy_worker *worker,
722                                            server_rec *s);
723/**
724 * Make a connection record for backend connection
725 * @param proxy_function calling proxy scheme (http, ajp, ...)
726 * @param conn    acquired connection
727 * @param c       client connection record
728 * @param s       current server record
729 * @return        OK or HTTP_XXX error
730 */
731PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
732                                              proxy_conn_rec *conn,
733                                              conn_rec *c, server_rec *s);
734/**
735 * Signal the upstream chain that the connection to the backend broke in the
736 * middle of the response. This is done by sending an error bucket with
737 * status HTTP_BAD_GATEWAY and an EOS bucket up the filter chain.
738 * @param r       current request record of client request
739 * @param brigade The brigade that is sent through the output filter chain
740 */
741PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
742                                           apr_bucket_brigade *brigade);
743
744/* Scoreboard */
745#if MODULE_MAGIC_NUMBER_MAJOR > 20020903
746#define PROXY_HAS_SCOREBOARD 1
747#else
748#define PROXY_HAS_SCOREBOARD 0
749#endif
750
751/**
752 * Transform buckets from one bucket allocator to another one by creating a
753 * transient bucket for each data bucket and let it use the data read from
754 * the old bucket. Metabuckets are transformed by just recreating them.
755 * Attention: Currently only the following bucket types are handled:
756 *
757 * All data buckets
758 * FLUSH
759 * EOS
760 *
761 * If an other bucket type is found its type is logged as a debug message
762 * and APR_EGENERAL is returned.
763 * @param r    current request record of client request. Only used for logging
764 *             purposes
765 * @param from the brigade that contains the buckets to transform
766 * @param to   the brigade that will receive the transformed buckets
767 * @return     APR_SUCCESS if all buckets could be transformed APR_EGENERAL
768 *             otherwise
769 */
770PROXY_DECLARE(apr_status_t)
771ap_proxy_buckets_lifetime_transform(request_rec *r, apr_bucket_brigade *from,
772                                        apr_bucket_brigade *to);
773
774#define PROXY_LBMETHOD "proxylbmethod"
775
776/* The number of dynamic workers that can be added when reconfiguring.
777 * If this limit is reached you must stop and restart the server.
778 */
779#define PROXY_DYNAMIC_BALANCER_LIMIT    16
780/**
781 * Calculate number of maximum number of workers in scoreboard.
782 * @return  number of workers to allocate in the scoreboard
783 */
784int ap_proxy_lb_workers(void);
785
786/* For proxy_util */
787extern module PROXY_DECLARE_DATA proxy_module;
788
789extern int PROXY_DECLARE_DATA proxy_lb_workers;
790
791#endif /*MOD_PROXY_H*/
792/** @} */
793