1 #ifndef INCLUDED_GW_BACKEND_H
2 #define INCLUDED_GW_BACKEND_H
3 
4 #include "first.h"
5 
6 #include <sys/types.h>
7 #include "sys-socket.h"
8 
9 #include "array.h"
10 #include "buffer.h"
11 
12 typedef struct {
13     char **ptr;
14 
15     uint32_t size;
16     uint32_t used;
17 } char_array;
18 
19 typedef struct gw_proc {
20     struct gw_proc *next; /* see first */
21     enum {
22         PROC_STATE_RUNNING,    /* alive */
23         PROC_STATE_OVERLOADED, /* listen-queue is full */
24         PROC_STATE_DIED_WAIT_FOR_PID, /* */
25         PROC_STATE_DIED,       /* marked as dead, should be restarted */
26         PROC_STATE_KILLED      /* killed (signal sent to proc) */
27     } state;
28     uint32_t load; /* number of requests waiting on this process */
29     unix_time64_t last_used; /* see idle_timeout */
30     int *stats_load;
31     int *stats_connected;
32     pid_t pid;   /* PID of the spawned process (0 if not spawned locally) */
33     int is_local;
34     uint32_t id; /* id will be between 1 and max_procs */
35     socklen_t saddrlen;
36     struct sockaddr *saddr;
37 
38     unix_time64_t disabled_until; /* proc disabled until given time */
39     struct gw_proc *prev; /* see first */
40 
41     /* either tcp:<host>:<port> or unix:<socket> for debugging purposes */
42     buffer *connection_name;
43     buffer *unixsocket; /* config.socket + "-" + id */
44     unsigned short port;  /* config.port + pno */
45 } gw_proc;
46 
47 struct gw_handler_ctx;  /* declaration */
48 
49 typedef struct {
50     /* list of processes handling this extension
51      * sorted by lowest load
52      *
53      * whenever a job is done move it up in the list
54      * until it is sorted, move it down as soon as the
55      * job is started
56      */
57     gw_proc *first;
58 
59     uint32_t active_procs; /* how many procs in state PROC_STATE_RUNNING */
60     uint32_t gw_hash;
61 
62     int32_t load;
63     int *stats_load;
64     int *stats_global_active;
65 
66     /*
67      * host:port
68      *
69      * if host is one of the local IP addresses the
70      * whole connection is local
71      *
72      * if port is not 0, and host is not specified,
73      * "localhost" (INADDR_LOOPBACK) is assumed.
74      *
75      */
76     unsigned short port;
77     unsigned short family; /* sa_family_t */
78     const buffer *host;
79 
80     /* the key that is used to reference this value */
81     const buffer *id;
82     gw_proc *unused_procs;
83 
84     /*
85      * spawn at least min_procs, at max_procs.
86      *
87      * as soon as the load of the first entry
88      * is max_load_per_proc we spawn a new one
89      * and add it to the first entry and give it
90      * the load
91      *
92      */
93 
94     unsigned short min_procs;
95     unsigned short max_procs;
96     uint32_t num_procs;    /* how many procs are started */
97 
98     unsigned short max_load_per_proc;
99 
100     /*
101      * kick the process from the list if it was not
102      * used for idle_timeout until min_procs is
103      * reached. this helps to get the processlist
104      * small again we had a small peak load.
105      *
106      */
107 
108     unsigned short idle_timeout;
109 
110     /*
111      * time after a disabled remote connection is tried to be re-enabled
112      *
113      *
114      */
115 
116     unsigned short disable_time;
117 
118     unsigned short read_timeout;
119     unsigned short write_timeout;
120     unsigned short connect_timeout;
121     struct gw_handler_ctx *hctxs;
122 
123     /*
124      * some gw processes get a little bit larger
125      * than wanted. max_requests_per_proc kills a
126      * process after a number of handled requests.
127      *
128      */
129     /*uint32_t max_requests_per_proc;*//* not implemented */
130 
131 
132     /* config */
133 
134     /*
135      * Unix Domain Socket
136      *
137      * instead of TCP/IP we can use Unix Domain Sockets
138      * - more secure (you have fileperms to play with)
139      * - more control (on locally)
140      * - more speed (no extra overhead)
141      */
142     const buffer *unixsocket;
143 
144     /* if socket is local we can start the gw process ourself
145      *
146      * bin-path is the path to the binary
147      *
148      * check min_procs and max_procs for the number
149      * of process to start up
150      */
151     const buffer *bin_path;
152 
153     /* bin-path is set bin-environment is taken to
154      * create the environment before starting the
155      * FastCGI process
156      *
157      */
158     const array *bin_env;
159 
160     const array *bin_env_copy;
161 
162     /*
163      * docroot-translation between URL->phys and the
164      * remote host
165      *
166      * reasons:
167      * - different dir-layout if remote
168      * - chroot if local
169      *
170      */
171     const buffer *docroot;
172 
173     /*
174      * append PATH_INFO to SCRIPT_FILENAME
175      *
176      * php needs this if cgi.fix_pathinfo is provided
177      *
178      */
179 
180     unsigned short break_scriptfilename_for_php;
181 
182     /*
183      * check_local tells you if the phys file is stat()ed
184      * or not. FastCGI doesn't care if the service is
185      * remote. If the web-server side doesn't contain
186      * the FastCGI-files we should not stat() for them
187      * and say '404 not found'.
188      */
189     unsigned short check_local;
190 
191     /*
192      * workaround for program when prefix="/"
193      *
194      * rule to build PATH_INFO is hardcoded for when check_local is disabled
195      * enable this option to use the workaround
196      *
197      */
198 
199     unsigned short fix_root_path_name;
200 
201     /*
202      * If the backend includes X-Sendfile in the response
203      * we use the value as filename and ignore the content.
204      *
205      */
206     unsigned short xsendfile_allow;
207     const array *xsendfile_docroot;
208 
209     uint32_t max_id; /* corresponds most of the time to num_procs */
210 
211     const buffer *strip_request_uri;
212 
213     unsigned short tcp_fin_propagate;
214     unsigned short kill_signal; /* we need a setting for this as libfcgi
215                                    applications prefer SIGUSR1 while the
216                                    rest of the world would use SIGTERM
217                                    *sigh* */
218 
219     int listen_backlog;
220     int refcount;
221 
222     char_array args;
223 } gw_host;
224 
225 /*
226  * one extension can have multiple hosts assigned
227  * one host can spawn additional processes on the same
228  *   socket (if we control it)
229  *
230  * ext -> host -> procs
231  *    1:n     1:n
232  *
233  * if the gw process is remote that whole goes down
234  * to
235  *
236  * ext -> host -> procs
237  *    1:n     1:1
238  *
239  * in case of PHP and FCGI_CHILDREN we have again a procs
240  * but we don't control it directly.
241  *
242  */
243 
244 typedef struct {
245     const buffer key; /* like .php */
246 
247     int note_is_sent;
248     int last_used_ndx;
249 
250     gw_host **hosts;
251 
252     uint32_t used;
253     uint32_t size;
254 } gw_extension;
255 
256 typedef struct {
257     gw_extension *exts;
258     uint32_t used;
259     uint32_t size;
260 } gw_exts;
261 
262 
263 
264 
265 #include "base_decls.h"
266 #include "chunk.h"
267 #include "plugin.h"
268 #include "response.h"
269 
270 typedef struct gw_plugin_config {
271     gw_exts *exts;
272     gw_exts *exts_auth;
273     gw_exts *exts_resp;
274     const array *ext_mapping;
275     int balance;
276     int proto;
277     int debug;
278 } gw_plugin_config;
279 
280 /* generic plugin data, shared between all connections */
281 typedef struct gw_plugin_data {
282     PLUGIN_DATA;
283     pid_t srv_pid; /* must precede gw_plugin_config for mods w/ larger struct */
284     gw_plugin_config conf; /* used only as long as no gw_handler_ctx is setup */
285     gw_plugin_config defaults;/*(must not be used by gw_backend.c: lg struct) */
286 } gw_plugin_data;
287 
288 /* connection specific data */
289 typedef enum {
290     GW_STATE_INIT,
291     GW_STATE_CONNECT_DELAYED,
292     GW_STATE_PREPARE_WRITE,
293     GW_STATE_WRITE,
294     GW_STATE_READ
295 } gw_connection_state_t;
296 
297 struct fdevents;        /* declaration */
298 
299 #define GW_RESPONDER  1
300 #define GW_AUTHORIZER 2
301 #define GW_FILTER     3  /*(not implemented)*/
302 
303 typedef struct gw_handler_ctx {
304     gw_proc *proc;
305     gw_host *host;
306     gw_extension *ext;
307     gw_extension *ext_auth; /* (future: might allow multiple authorizers)*/
308     unsigned short gw_mode; /* mode: GW_AUTHORIZER or GW_RESPONDER */
309 
310     gw_connection_state_t state;
311 
312     chunkqueue *rb; /* read queue */
313     off_t     wb_reqlen;
314     chunkqueue wb; /* write queue */
315 
316     buffer   *response;
317 
318     struct fdevents *ev;
319     fdnode   *fdn;       /* fdevent (fdnode *) object */
320     int       fd;        /* fd to the gw process */
321     int       revents;   /* ready events on fd */
322 
323     pid_t     pid;
324     int       reconnects; /* number of reconnect attempts */
325 
326     int       request_id;
327     int       send_content_body;
328 
329     http_response_opts opts;
330     gw_plugin_config conf;
331 
332     request_st *r;               /* dumb pointer */
333     connection *con;             /* dumb pointer */
334     gw_plugin_data *plugin_data; /* dumb pointer */
335     unix_time64_t read_ts;
336     unix_time64_t write_ts;
337     handler_t(*stdin_append)(struct gw_handler_ctx *hctx);
338     handler_t(*create_env)(struct gw_handler_ctx *hctx);
339     struct gw_handler_ctx *prev;
340     struct gw_handler_ctx *next;
341     void(*backend_error)(struct gw_handler_ctx *hctx);
342     void(*handler_ctx_free)(void *hctx);
343 } gw_handler_ctx;
344 
345 
346 __attribute_cold__
347 __attribute_malloc__
348 void * gw_init(void);
349 
350 __attribute_cold__
351 void gw_plugin_config_free(gw_plugin_config *s);
352 
353 __attribute_cold__
354 void gw_free(void *p_d);
355 
356 __attribute_cold__
357 void gw_exts_clear_check_local(gw_exts *exts);
358 
359 __attribute_cold__
360 int gw_set_defaults_backend(server *srv, gw_plugin_data *p, const array *a, gw_plugin_config *s, int sh_exec, const char *cpkkey);
361 
362 __attribute_cold__
363 int gw_get_defaults_balance(server *srv, const buffer *b);
364 
365 handler_t gw_check_extension(request_st *r, gw_plugin_data *p, int uri_path_handler, size_t hctx_sz);
366 handler_t gw_handle_request_reset(request_st *r, void *p_d);
367 handler_t gw_handle_subrequest(request_st *r, void *p_d);
368 handler_t gw_handle_trigger(server *srv, void *p_d);
369 handler_t gw_handle_waitpid_cb(server *srv, void *p_d, pid_t pid, int status);
370 
371 void gw_set_transparent(gw_handler_ctx *hctx);
372 
373 #endif
374