2 * $Id: fcgi.h,v 1.29 2001/03/05 15:45:16 robs Exp $
8 /* Apache header files */
10 #include "http_config.h"
11 #include "http_request.h"
12 #include "http_core.h"
13 #include "http_protocol.h"
14 #include "http_main.h"
16 #include "util_script.h"
17 #include "http_conf_globals.h"
20 #if MODULE_MAGIC_NUMBER < 19980806
21 #error "This version of mod_fastcgi is incompatible with Apache versions 1.3.1 and earlier."
22 #error "Please upgrade, or try the last Apache 1.2 compatible release, mod_fastcgi 2.0.18 (no DSO support)."
30 #include "multithread.h"
35 /* FastCGI header files */
36 #include "mod_fastcgi.h"
37 /* @@@ This should go away when fcgi_protocol is re-written */
38 #include "fcgi_protocol.h"
41 int size
; /* size of entire buffer */
42 int length
; /* number of bytes in current buffer */
43 char *begin
; /* begining of valid data */
44 char *end
; /* end of valid data */
45 char data
[1]; /* buffer data */
52 #define MBOX_EVENT 0 /* mboc is ready to be read */
53 #define TERM_EVENT 1 /* termination event */
54 #define WAKE_EVENT 2 /* notification of child Fserver dieing */
56 /* Reader/Writer lock structure for NT */
57 typedef struct _FcgiRWLock
{
60 long counter
; /* number of readers */
63 typedef struct _fcgi_pm_job
{
69 unsigned long start_time
;
70 struct _fcgi_pm_job
*next
;
75 * ServerProcess holds data for each process associated with
76 * a class. It is embedded in fcgi_server below.
78 typedef struct _FcgiProcessInfo
{
80 HANDLE handle
; /* handle of associated process */
82 pid_t pid
; /* pid of associated process */
83 enum {STATE_STARTED
, /* currently running */
84 STATE_NEEDS_STARTING
, /* needs to be started by PM */
85 STATE_KILL
, /* kill() is needed */
86 STATE_VICTIM
, /* SIGTERM was sent by PM */
87 STATE_KILLED
, /* a wait() collected VICTIM */
88 STATE_READY
} /* empty cell, init state */
89 state
; /* state of the process */
93 * fcgi_server holds info for each AppClass specified in this
94 * Web server's configuration.
96 typedef struct _FastCgiServerInfo
{
98 char *fs_path
; /* pathname of executable */
99 array_header
*pass_headers
; /* names of headers to pass in the env */
100 u_int idle_timeout
; /* fs idle secs allowed before aborting */
101 char **envp
; /* if NOT NULL, this is the env to send
102 * to the fcgi app when starting a server
104 u_int listenQueueDepth
; /* size of listen queue for IPC */
105 u_int appConnectTimeout
; /* timeout (sec) for connect() requests */
106 u_int numProcesses
; /* max allowed processes of this class,
107 * or for dynamic apps, the number of
108 * processes actually running */
109 time_t restartTime
; /* most recent time when the process
110 * manager started a process in this
112 int initStartDelay
; /* min number of seconds to wait between
113 * starting of AppClass processes at init */
114 u_int restartDelay
; /* number of seconds to wait between
115 * restarts after failure. Can be zero. */
116 int restartOnExit
; /* = TRUE = restart. else terminate/free */
117 u_int numRestarts
; /* Total number of restarts */
118 u_int numFailures
; /* num restarts due to exit failure */
119 struct sockaddr
*socket_addr
; /* Socket Address of FCGI app server class */
121 struct sockaddr
*dest_addr
; /* for local apps on NT need socket address */
122 /* bound to localhost */
124 int socket_addr_len
; /* Length of socket */
125 enum {APP_CLASS_UNKNOWN
,
129 directive
; /* AppClass or ExternalAppClass */
130 const char *socket_path
; /* Name used to create a socket */
131 const char *host
; /* Hostname for externally managed
132 * FastCGI application processes */
133 unsigned short port
; /* Port number either for externally
134 * managed FastCGI applications or for
135 * server managed FastCGI applications,
136 * where server became application mngr. */
137 int listenFd
; /* Listener socket of FCGI app server
138 * class. Passed to app server process
139 * at process creation. */
140 u_int processPriority
; /* If locally server managed process,
141 * this is the priority to run the
142 * processes in this class at. */
143 struct _FcgiProcessInfo
*procs
; /* Pointer to array of
144 * processes belonging to this class. */
145 int keepConnection
; /* = 1 = maintain connection to app. */
146 uid_t uid
; /* uid this app should run as (suexec) */
147 gid_t gid
; /* gid this app should run as (suexec) */
148 const char *username
; /* suexec user arg */
149 const char *group
; /* suexec group arg, AND used in comm
150 * between RH and PM */
151 const char *user
; /* used in comm between RH and PM */
152 /* Dynamic FastCGI apps configuration parameters */
153 u_long totalConnTime
; /* microseconds spent by the web server
154 * waiting while fastcgi app performs
155 * request processing since the last
156 * dynamicUpdateInterval */
157 u_long smoothConnTime
; /* exponentially decayed values of the
158 * connection times. */
159 u_long totalQueueTime
; /* microseconds spent by the web server
160 * waiting to connect to the fastcgi app
161 * since the last dynamicUpdateInterval. */
163 FcgiRWLock
*dynamic_lock
; /* dynamic server lock */
167 struct _FastCgiServerInfo
*next
;
172 * fcgi_request holds the state of a particular FastCGI request.
178 int fd
; /* connection to FastCGI server */
180 int gotHeader
; /* TRUE if reading content bytes */
181 unsigned char packetType
; /* type of packet */
182 int dataLen
; /* length of data bytes */
183 int paddingLen
; /* record padding after content */
184 fcgi_server
*fs
; /* FastCGI server info */
185 const char *fs_path
; /* fcgi_server path */
186 Buffer
*serverInputBuffer
; /* input buffer from FastCgi server */
187 Buffer
*serverOutputBuffer
; /* output buffer to FastCgi server */
188 Buffer
*clientInputBuffer
; /* client input buffer */
189 Buffer
*clientOutputBuffer
; /* client output buffer */
190 table
*authHeaders
; /* headers received from an auth fs */
191 int auth_compat
; /* whether the auth request is spec compat */
192 table
*saved_subprocess_env
; /* subprocess_env before auth handling */
193 #if defined(SIGPIPE) && MODULE_MAGIC_NUMBER < 19990320
194 void (*apache_sigpipe_handler
)(int);
196 int expectingClientContent
; /* >0 => more content, <=0 => no more */
197 array_header
*header
;
200 int parseHeader
; /* TRUE iff parsing response headers */
202 int readingEndRequestBody
;
203 FCGI_EndRequestBody endRequestBody
;
207 unsigned int requestId
;
209 int role
; /* FastCGI Role: Authorizer or Responder */
210 int dynamic
; /* whether or not this is a dynamic app */
211 struct timeval startTime
; /* dynamic app's connect() attempt start time */
212 struct timeval queueTime
; /* dynamic app's connect() complete time */
213 struct timeval completeTime
; /* dynamic app's connection close() time */
215 FcgiRWLock
*lockFd
; /* dynamic app's reader/writer lock */
217 int lockFd
; /* dynamic app's lockfile file descriptor */
219 int keepReadingFromFcgiApp
; /* still more to read from fcgi app? */
220 const char *user
; /* user used to invoke app (suexec) */
221 const char *group
; /* group used to invoke app (suexec) */
223 BOOL using_npipe_io
; /* named pipe io */
227 /* Values of parseHeader field */
228 #define SCAN_CGI_READING_HEADERS 1
229 #define SCAN_CGI_FINISHED 0
230 #define SCAN_CGI_BAD_HEADER -1
231 #define SCAN_CGI_INT_REDIRECT -2
232 #define SCAN_CGI_SRV_REDIRECT -3
234 /* Opcodes for Server->ProcMgr communication */
235 #define PLEASE_START 83 /* 'S' - start */
236 #define CONN_TIMEOUT 84 /* 'T' - timeout */
237 #define REQ_COMPLETE 67 /* 'C' - complete */
239 /* Authorizer types, for auth directives handling */
240 #define FCGI_AUTH_TYPE_AUTHENTICATOR 0
241 #define FCGI_AUTH_TYPE_AUTHORIZER 1
242 #define FCGI_AUTH_TYPE_ACCESS_CHECKER 2
244 /* Bits for auth_options */
245 #define FCGI_AUTHORITATIVE 1
246 #define FCGI_COMPAT 2
250 const char *authorizer
;
251 u_char authorizer_options
;
252 const char *authenticator
;
253 u_char authenticator_options
;
254 const char *access_checker
;
255 u_char access_checker_options
;
259 #define FCGI_FAILED 1
263 #define FCGI_LOG_EMERG_ERRNO __FILE__,__LINE__,APLOG_EMERG /* system is unusable */
264 #define FCGI_LOG_ALERT_ERRNO __FILE__,__LINE__,APLOG_ALERT /* action must be taken immediately */
265 #define FCGI_LOG_CRIT_ERRNO __FILE__,__LINE__,APLOG_CRIT /* critical conditions */
266 #define FCGI_LOG_ERR_ERRNO __FILE__,__LINE__,APLOG_ERR /* error conditions */
267 #define FCGI_LOG_WARN_ERRNO __FILE__,__LINE__,APLOG_WARNING /* warning conditions */
268 #define FCGI_LOG_NOTICE_ERRNO __FILE__,__LINE__,APLOG_NOTICE /* normal but significant condition */
269 #define FCGI_LOG_INFO_ERRNO __FILE__,__LINE__,APLOG_INFO /* informational */
270 #define FCGI_LOG_DEBUG_ERRNO __FILE__,__LINE__,APLOG_DEBUG /* debug-level messages */
272 #define FCGI_LOG_EMERG __FILE__,__LINE__,APLOG_EMERG|APLOG_WIN32ERROR
273 #define FCGI_LOG_ALERT __FILE__,__LINE__,APLOG_ALERT|APLOG_WIN32ERROR
274 #define FCGI_LOG_CRIT __FILE__,__LINE__,APLOG_CRIT|APLOG_WIN32ERROR
275 #define FCGI_LOG_ERR __FILE__,__LINE__,APLOG_ERR|APLOG_WIN32ERROR
276 #define FCGI_LOG_WARN __FILE__,__LINE__,APLOG_WARNING|APLOG_WIN32ERROR
277 #define FCGI_LOG_NOTICE __FILE__,__LINE__,APLOG_NOTICE|APLOG_WIN32ERROR
278 #define FCGI_LOG_INFO __FILE__,__LINE__,APLOG_INFO|APLOG_WIN32ERROR
279 #define FCGI_LOG_DEBUG __FILE__,__LINE__,APLOG_DEBUG|APLOG_WIN32ERROR
283 #define FCGI_LOG_EMERG __FILE__,__LINE__,APLOG_EMERG /* system is unusable */
284 #define FCGI_LOG_ALERT __FILE__,__LINE__,APLOG_ALERT /* action must be taken immediately */
285 #define FCGI_LOG_CRIT __FILE__,__LINE__,APLOG_CRIT /* critical conditions */
286 #define FCGI_LOG_ERR __FILE__,__LINE__,APLOG_ERR /* error conditions */
287 #define FCGI_LOG_WARN __FILE__,__LINE__,APLOG_WARNING /* warning conditions */
288 #define FCGI_LOG_NOTICE __FILE__,__LINE__,APLOG_NOTICE /* normal but significant condition */
289 #define FCGI_LOG_INFO __FILE__,__LINE__,APLOG_INFO /* informational */
290 #define FCGI_LOG_DEBUG __FILE__,__LINE__,APLOG_DEBUG /* debug-level messages */
292 #define FCGI_LOG_EMERG_ERRNO FCGI_LOG_EMERG
293 #define FCGI_LOG_ALERT_ERRNO FCGI_LOG_ALERT
294 #define FCGI_LOG_CRIT_ERRNO FCGI_LOG_CRIT
295 #define FCGI_LOG_ERR_ERRNO FCGI_LOG_ERR
296 #define FCGI_LOG_WARN_ERRNO FCGI_LOG_WARN
297 #define FCGI_LOG_NOTICE_ERRNO FCGI_LOG_NOTICE
298 #define FCGI_LOG_INFO_ERRNO FCGI_LOG_INFO
299 #define FCGI_LOG_DEBUG_ERRNO FCGI_LOG_DEBUG
303 #define FCGI_LOG_EMERG_NOERRNO __FILE__,__LINE__,APLOG_EMERG|APLOG_NOERRNO
304 #define FCGI_LOG_ALERT_NOERRNO __FILE__,__LINE__,APLOG_ALERT|APLOG_NOERRNO
305 #define FCGI_LOG_CRIT_NOERRNO __FILE__,__LINE__,APLOG_CRIT|APLOG_NOERRNO
306 #define FCGI_LOG_ERR_NOERRNO __FILE__,__LINE__,APLOG_ERR|APLOG_NOERRNO
307 #define FCGI_LOG_WARN_NOERRNO __FILE__,__LINE__,APLOG_WARNING|APLOG_NOERRNO
308 #define FCGI_LOG_NOTICE_NOERRNO __FILE__,__LINE__,APLOG_NOTICE|APLOG_NOERRNO
309 #define FCGI_LOG_INFO_NOERRNO __FILE__,__LINE__,APLOG_INFO|APLOG_NOERRNO
310 #define FCGI_LOG_DEBUG_NOERRNO __FILE__,__LINE__,APLOG_DEBUG|APLOG_NOERRNO
313 #define FCGIDBG1(a) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a);
314 #define FCGIDBG2(a,b) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a,b);
315 #define FCGIDBG3(a,b,c) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a,b,c);
316 #define FCGIDBG4(a,b,c,d) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a,b,c,d);
317 #define FCGIDBG5(a,b,c,d,e) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a,b,c,d,e);
318 #define FCGIDBG6(a,b,c,d,e,f) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a,b,c,d,e,f);
319 #define FCGIDBG7(a,b,c,d,e,f,g) ap_log_error(FCGI_LOG_DEBUG,fcgi_apache_main_server,a,b,c,d,e,f,g);
322 #define FCGIDBG2(a,b)
323 #define FCGIDBG3(a,b,c)
324 #define FCGIDBG4(a,b,c,d)
325 #define FCGIDBG5(a,b,c,d,e)
326 #define FCGIDBG6(a,b,c,d,e,f)
327 #define FCGIDBG7(a,b,c,d,e,f,g)
331 * Holds the status of the sending of the environment.
332 * A quick hack to dump the static vars for the NT port.
335 enum { PREP
, HEADER
, NAME
, VALUE
} pass
;
337 int headerLen
, nameLen
, valueLen
, totalLen
;
339 unsigned char headerBuff
[8];
345 void *fcgi_config_create_dir_config(pool
*p
, char *dummy
);
346 const char *fcgi_config_make_dir(pool
*tp
, char *path
);
347 const char *fcgi_config_make_dynamic_dir(pool
*p
, const int wax
);
348 const char *fcgi_config_new_static_server(cmd_parms
*cmd
, void *dummy
, const char *arg
);
349 const char *fcgi_config_new_external_server(cmd_parms
*cmd
, void *dummy
, const char *arg
);
350 const char *fcgi_config_set_config(cmd_parms
*cmd
, void *dummy
, const char *arg
);
351 const char *fcgi_config_set_fcgi_uid_n_gid(int set
);
352 const char *fcgi_config_new_auth_server(cmd_parms
* const cmd
,
353 fcgi_dir_config
*dir_config
, const char *fs_path
, const char * const compat
);
354 const char *fcgi_config_set_authoritative_slot(const cmd_parms
* const cmd
,
355 fcgi_dir_config
* const dir_config
, int arg
);
356 const char *fcgi_config_set_socket_dir(cmd_parms
*cmd
, void *dummy
, char *arg
);
357 const char *fcgi_config_set_wrapper(cmd_parms
*cmd
, void *dummy
, const char *arg
);
358 void fcgi_config_reset_globals(void* dummy
);
359 const char *fcgi_config_set_env_var(pool
*p
, char **envp
, unsigned int *envc
, char * var
);
365 void fcgi_pm_main(void *dummy
);
367 int fcgi_pm_main(void *dummy
, child_info
*info
);
373 void fcgi_protocol_queue_begin_request(fcgi_request
*fr
);
374 void fcgi_protocol_queue_client_buffer(fcgi_request
*fr
);
375 int fcgi_protocol_queue_env(request_rec
*r
, fcgi_request
*fr
, env_status
*env
);
376 int fcgi_protocol_dequeue(pool
*p
, fcgi_request
*fr
);
381 #define BufferLength(b) ((b)->length)
382 #define BufferFree(b) ((b)->size - (b)->length)
383 #define BufferSize(b) ((b)->size)
385 void fcgi_buf_check(Buffer
*bufPtr
);
386 void fcgi_buf_reset(Buffer
*bufPtr
);
387 Buffer
*fcgi_buf_new(pool
*p
, int size
);
388 void BufferDelete(Buffer
*bufPtr
);
391 int fcgi_buf_add_fd(Buffer
*buf
, SOCKET fd
);
392 int fcgi_buf_get_to_fd(Buffer
*bufPtr
, SOCKET fd
);
394 int fcgi_buf_add_fd(Buffer
*buf
, int fd
);
395 int fcgi_buf_get_to_fd(Buffer
*bufPtr
, int fd
);
398 void fcgi_buf_get_block_info(Buffer
*bufPtr
, char **beginPtr
, size_t *countPtr
);
399 void fcgi_buf_toss(Buffer
*bufPtr
, size_t count
);
400 void fcgi_buf_get_free_block_info(Buffer
*bufPtr
, char **endPtr
, size_t *countPtr
);
401 void fcgi_buf_add_update(Buffer
*bufPtr
, size_t count
);
402 int fcgi_buf_add_block(Buffer
*bufPtr
, char *data
, size_t datalen
);
403 int fcgi_buf_add_string(Buffer
*bufPtr
, char *str
);
404 int fcgi_buf_get_to_block(Buffer
*bufPtr
, char *data
, int datalen
);
405 void fcgi_buf_get_to_buf(Buffer
*toPtr
, Buffer
*fromPtr
, int len
);
406 void fcgi_buf_get_to_array(Buffer
*buf
,array_header
*arr
, size_t len
);
412 /* Set a shared read lock, wait until you have it. */
414 #define fcgi_wait_for_shared_read_lock(fd) fcgi_rdwr_lock(fd, READER)
416 #define fcgi_wait_for_shared_read_lock(fd) fcgi_util_lock_fd((fd), F_SETLKW, F_RDLCK, 0, SEEK_SET, 0)
419 /* Set an exclusive write lock, no wait, failure->errno==EACCES. */
421 #define fcgi_get_exclusive_write_lock_no_wait(fd) fcgi_rdwr_try_lock(fd, WRITER)
423 #define fcgi_get_exclusive_write_lock_no_wait(fd) fcgi_util_lock_fd(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0)
426 /* Set a shared write lock, wait until you have it. */
428 #define fcgi_wait_for_shared_write_lock(fd) fcgi_rdwr_lock(fd, WRITER)
430 #define fcgi_wait_for_shared_write_lock(fd) fcgi_util_lock_fd(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0)
433 char *fcgi_util_socket_hash_filename(pool
*p
, const char *path
,
434 const char *user
, const char *group
);
435 const char *fcgi_util_socket_make_path_absolute(pool
* const p
,
436 const char *const file
, const int dynamic
);
437 const char *fcgi_util_socket_get_lock_filename(pool
*p
, const char *socket_path
);
439 const char *fcgi_util_socket_make_domain_addr(pool
*p
, struct sockaddr_un
**socket_addr
,
440 int *socket_addr_len
, const char *socket_path
);
442 const char *fcgi_util_socket_make_inet_addr(pool
*p
, struct sockaddr_in
**socket_addr
,
443 int *socket_addr_len
, const char *host
, unsigned short port
);
444 const char *fcgi_util_check_access(pool
*tp
,
445 const char * const path
, const struct stat
*statBuf
,
446 const int mode
, const uid_t uid
, const gid_t gid
);
447 fcgi_server
*fcgi_util_fs_get_by_id(const char *ePath
, uid_t uid
, gid_t gid
);
448 fcgi_server
*fcgi_util_fs_get(const char *ePath
, const char *user
, const char *group
);
449 const char *fcgi_util_fs_is_path_ok(pool
* const p
, const char * const fs_path
,
450 struct stat
*finfo
, const uid_t uid
, const gid_t gid
);
451 fcgi_server
*fcgi_util_fs_new(pool
*p
);
452 void fcgi_util_fs_add(fcgi_server
*s
);
453 const char *fcgi_util_fs_set_uid_n_gid(pool
*p
, fcgi_server
*s
, uid_t uid
, gid_t gid
);
454 ServerProcess
*fcgi_util_fs_create_procs(pool
*p
, int num
);
455 int fcgi_util_lock_fd(int fd
, int cmd
, int type
, off_t offset
, int whence
, off_t len
);
457 int fcgi_util_gettimeofday(struct timeval
*);
460 FcgiRWLock
* fcgi_rdwr_create(void);
461 void fcgi_rdwr_destroy(FcgiRWLock
*);
462 int fcgi_rdwr_lock(FcgiRWLock
*, int);
463 int fcgi_rdwr_try_lock(FcgiRWLock
*, int);
464 int fcgi_rdwr_unlock(FcgiRWLock
*, int);
466 int fcgi_pm_add_job(fcgi_pm_job
*new_job
);
474 extern pool
*fcgi_config_pool
;
476 extern server_rec
*fcgi_apache_main_server
;
478 extern const char *fcgi_wrapper
; /* wrapper path */
479 extern uid_t fcgi_user_id
; /* the run uid of Apache & PM */
480 extern gid_t fcgi_group_id
; /* the run gid of Apache & PM */
482 extern fcgi_server
*fcgi_servers
;
484 extern char *fcgi_socket_dir
; /* default FastCgiIpcDir */
486 /* pipe used for comm between the request handlers and the PM */
487 extern int fcgi_pm_pipe
[];
489 extern pid_t fcgi_pm_pid
;
491 extern char *fcgi_dynamic_dir
; /* directory for the dynamic
492 * fastcgi apps' sockets */
494 extern char *fcgi_empty_env
;
496 extern int fcgi_dynamic_total_proc_count
;
497 extern time_t fcgi_dynamic_epoch
;
498 extern time_t fcgi_dynamic_last_analyzed
;
501 extern HANDLE
*fcgi_dynamic_mbox_mutex
;
502 extern HANDLE fcgi_event_handles
[3];
503 extern fcgi_pm_job
*fcgi_dynamic_mbox
;
506 extern u_int dynamicMaxProcs
;
507 extern u_int dynamicMinProcs
;
508 extern u_int dynamicMaxClassProcs
;
509 extern u_int dynamicKillInterval
;
510 extern u_int dynamicUpdateInterval
;
511 extern float dynamicGain
;
512 extern u_int dynamicThreshold1
;
513 extern u_int dynamicThresholdN
;
514 extern u_int dynamicPleaseStartDelay
;
515 extern u_int dynamicAppConnectTimeout
;
516 extern char **dynamicEnvp
;
517 extern u_int dynamicProcessSlack
;
518 extern int dynamicAutoRestart
;
519 extern int dynamicAutoUpdate
;
520 extern u_int dynamicListenQueueDepth
;
521 extern u_int dynamicInitStartDelay
;
522 extern u_int dynamicRestartDelay
;
523 extern array_header
*dynamic_pass_headers
;
524 extern u_int dynamic_idle_timeout
;
526 extern module MODULE_VAR_EXPORT fastcgi_module
;