mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fixed fpm-side (tests passes)
This commit is contained in:
305
main/fastcgi.c
305
main/fastcgi.c
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "php.h"
|
||||
#include "php_network.h"
|
||||
#include "fastcgi.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -32,8 +31,6 @@
|
||||
#define MAXFQDNLEN 255
|
||||
#endif
|
||||
|
||||
static fcgi_logger flog;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
@@ -133,10 +130,16 @@ static int is_impersonate = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#include "fastcgi.h"
|
||||
|
||||
/* maybe it's better to use weak name instead */
|
||||
static fcgi_logger logger;
|
||||
|
||||
typedef union _sa_t {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_un sa_unix;
|
||||
struct sockaddr_in sa_inet;
|
||||
struct sockaddr_in6 sa_inet6;
|
||||
} sa_t;
|
||||
|
||||
static HashTable fcgi_mgmt_vars;
|
||||
@@ -144,44 +147,10 @@ static HashTable fcgi_mgmt_vars;
|
||||
static int is_initialized = 0;
|
||||
static int is_fastcgi = 0;
|
||||
static int in_shutdown = 0;
|
||||
static in_addr_t *allowed_clients = NULL;
|
||||
static sa_t *allowed_clients = NULL;
|
||||
static sa_t client_sa;
|
||||
|
||||
/* hash table */
|
||||
|
||||
#define FCGI_HASH_TABLE_SIZE 128
|
||||
#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
|
||||
#define FCGI_HASH_SEG_SIZE 4096
|
||||
|
||||
typedef struct _fcgi_hash_bucket {
|
||||
unsigned int hash_value;
|
||||
unsigned int var_len;
|
||||
char *var;
|
||||
unsigned int val_len;
|
||||
char *val;
|
||||
struct _fcgi_hash_bucket *next;
|
||||
struct _fcgi_hash_bucket *list_next;
|
||||
} fcgi_hash_bucket;
|
||||
|
||||
typedef struct _fcgi_hash_buckets {
|
||||
unsigned int idx;
|
||||
struct _fcgi_hash_buckets *next;
|
||||
struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
|
||||
} fcgi_hash_buckets;
|
||||
|
||||
typedef struct _fcgi_data_seg {
|
||||
char *pos;
|
||||
char *end;
|
||||
struct _fcgi_data_seg *next;
|
||||
char data[1];
|
||||
} fcgi_data_seg;
|
||||
|
||||
typedef struct _fcgi_hash {
|
||||
fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
|
||||
fcgi_hash_bucket *list;
|
||||
fcgi_hash_buckets *buckets;
|
||||
fcgi_data_seg *data;
|
||||
} fcgi_hash;
|
||||
|
||||
static void fcgi_hash_init(fcgi_hash *h)
|
||||
{
|
||||
memset(h->hash_table, 0, sizeof(h->hash_table));
|
||||
@@ -341,29 +310,6 @@ static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
struct _fcgi_request {
|
||||
int listen_socket;
|
||||
int tcp;
|
||||
int fd;
|
||||
int id;
|
||||
int keep;
|
||||
#ifdef TCP_NODELAY
|
||||
int nodelay;
|
||||
#endif
|
||||
int closed;
|
||||
|
||||
int in_len;
|
||||
int in_pad;
|
||||
|
||||
fcgi_header *out_hdr;
|
||||
unsigned char *out_pos;
|
||||
unsigned char out_buf[1024*8];
|
||||
unsigned char reserved[sizeof(fcgi_end_request_rec)];
|
||||
|
||||
int has_env;
|
||||
fcgi_hash env;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
|
||||
@@ -399,6 +345,11 @@ static void fcgi_setup_signals(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
void fcgi_set_in_shutdown(int new_value)
|
||||
{
|
||||
in_shutdown = new_value;
|
||||
}
|
||||
|
||||
int fcgi_in_shutdown(void)
|
||||
{
|
||||
return in_shutdown;
|
||||
@@ -409,8 +360,8 @@ void fcgi_terminate(void)
|
||||
in_shutdown = 1;
|
||||
}
|
||||
|
||||
void fcgi_set_logger(fcgi_logger logger) {
|
||||
flog = logger;
|
||||
void fcgi_set_logger(fcgi_logger lg) {
|
||||
logger = lg;
|
||||
}
|
||||
|
||||
int fcgi_init(void)
|
||||
@@ -632,10 +583,10 @@ int fcgi_listen(const char *path, int backlog)
|
||||
hep = gethostbyname(host);
|
||||
}
|
||||
if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
|
||||
flog(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
|
||||
logger(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
|
||||
return -1;
|
||||
} else if (hep->h_addr_list[1]) {
|
||||
flog(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
|
||||
logger(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
|
||||
return -1;
|
||||
}
|
||||
sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr;
|
||||
@@ -672,7 +623,7 @@ int fcgi_listen(const char *path, int backlog)
|
||||
int path_len = strlen(path);
|
||||
|
||||
if (path_len >= sizeof(sa.sa_unix.sun_path)) {
|
||||
flog(FCGI_ERROR, "Listening socket's path name is too long.\n");
|
||||
logger(FCGI_ERROR, "Listening socket's path name is too long.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -695,7 +646,7 @@ int fcgi_listen(const char *path, int backlog)
|
||||
bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
|
||||
listen(listen_socket, backlog) < 0) {
|
||||
|
||||
flog(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
|
||||
logger(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -714,7 +665,7 @@ int fcgi_listen(const char *path, int backlog)
|
||||
if (*cur == ',') n++;
|
||||
cur++;
|
||||
}
|
||||
allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
|
||||
allowed_clients = malloc(sizeof(sa_t) * (n+2));
|
||||
n = 0;
|
||||
cur = ip;
|
||||
while (cur) {
|
||||
@@ -723,15 +674,25 @@ int fcgi_listen(const char *path, int backlog)
|
||||
*end = 0;
|
||||
end++;
|
||||
}
|
||||
allowed_clients[n] = inet_addr(cur);
|
||||
if (allowed_clients[n] == INADDR_NONE) {
|
||||
flog(FCGI_ERROR, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
|
||||
if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
|
||||
allowed_clients[n].sa.sa_family = AF_INET;
|
||||
n++;
|
||||
#ifdef HAVE_IPV6
|
||||
} else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
|
||||
allowed_clients[n].sa.sa_family = AF_INET6;
|
||||
n++;
|
||||
#endif
|
||||
} else {
|
||||
logger(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
|
||||
}
|
||||
n++;
|
||||
cur = end;
|
||||
}
|
||||
allowed_clients[n] = INADDR_NONE;
|
||||
allowed_clients[n].sa.sa_family = 0;
|
||||
free(ip);
|
||||
if (!n) {
|
||||
logger(FCGI_ERROR, "There are no allowed addresses");
|
||||
/* don't clear allowed_clients as it will create an "open for all" security issue */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,38 +711,81 @@ int fcgi_listen(const char *path, int backlog)
|
||||
return listen_socket;
|
||||
}
|
||||
|
||||
fcgi_request *fcgi_init_request(int listen_socket)
|
||||
void fcgi_set_allowed_clients(char *ip)
|
||||
{
|
||||
fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
|
||||
char *cur, *end;
|
||||
int n;
|
||||
|
||||
if (ip) {
|
||||
ip = strdup(ip);
|
||||
cur = ip;
|
||||
n = 0;
|
||||
while (*cur) {
|
||||
if (*cur == ',') n++;
|
||||
cur++;
|
||||
}
|
||||
if (allowed_clients) free(allowed_clients);
|
||||
allowed_clients = malloc(sizeof(sa_t) * (n+2));
|
||||
n = 0;
|
||||
cur = ip;
|
||||
while (cur) {
|
||||
end = strchr(cur, ',');
|
||||
if (end) {
|
||||
*end = 0;
|
||||
end++;
|
||||
}
|
||||
if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
|
||||
allowed_clients[n].sa.sa_family = AF_INET;
|
||||
n++;
|
||||
#ifdef HAVE_IPV6
|
||||
} else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
|
||||
allowed_clients[n].sa.sa_family = AF_INET6;
|
||||
n++;
|
||||
#endif
|
||||
} else {
|
||||
logger(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
|
||||
}
|
||||
cur = end;
|
||||
}
|
||||
allowed_clients[n].sa.sa_family = 0;
|
||||
free(ip);
|
||||
if (!n) {
|
||||
logger(FCGI_ERROR, "There are no allowed addresses");
|
||||
/* don't clear allowed_clients as it will create an "open for all" security issue */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fcgi_request *fcgi_init_request(fcgi_request *req, int listen_socket)
|
||||
{
|
||||
memset(req, 0, sizeof(fcgi_request));
|
||||
req->listen_socket = listen_socket;
|
||||
req->fd = -1;
|
||||
req->id = -1;
|
||||
|
||||
/*
|
||||
req->in_len = 0;
|
||||
req->in_pad = 0;
|
||||
|
||||
req->out_hdr = NULL;
|
||||
|
||||
#ifdef TCP_NODELAY
|
||||
req->nodelay = 0;
|
||||
#endif
|
||||
|
||||
req->env = NULL;
|
||||
req->has_env = 0;
|
||||
|
||||
*/
|
||||
req->out_pos = req->out_buf;
|
||||
|
||||
#ifdef _WIN32
|
||||
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef TCP_NODELAY
|
||||
req->nodelay = 0;
|
||||
#endif
|
||||
|
||||
fcgi_hash_init(&req->env);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
void fcgi_destroy_request(fcgi_request *req)
|
||||
{
|
||||
fcgi_hash_destroy(&req->env);
|
||||
free(req);
|
||||
}
|
||||
|
||||
static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -919,6 +923,7 @@ static int fcgi_read_request(fcgi_request *req)
|
||||
req->in_len = 0;
|
||||
req->out_hdr = NULL;
|
||||
req->out_pos = req->out_buf;
|
||||
fcgi_hash_init(&req->env);
|
||||
req->has_env = 1;
|
||||
|
||||
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
|
||||
@@ -1058,7 +1063,7 @@ static int fcgi_read_request(fcgi_request *req)
|
||||
}
|
||||
len = (int)(p - buf - sizeof(fcgi_header));
|
||||
len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
|
||||
if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
|
||||
if (safe_write(req, buf, sizeof(fcgi_header) + len) != (ssize_t)sizeof(fcgi_header)+len) {
|
||||
req->keep = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -1123,10 +1128,11 @@ int fcgi_read(fcgi_request *req, char *str, int len)
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline void fcgi_close(fcgi_request *req, int force, int destroy)
|
||||
void fcgi_close(fcgi_request *req, int force, int destroy)
|
||||
{
|
||||
if (destroy && req->has_env) {
|
||||
fcgi_hash_clean(&req->env);
|
||||
fcgi_hash_destroy(&req->env);
|
||||
req->has_env = 0;
|
||||
}
|
||||
|
||||
@@ -1169,9 +1175,57 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
|
||||
req->nodelay = 0;
|
||||
#endif
|
||||
req->fd = -1;
|
||||
|
||||
if (req->hook.on_close) {
|
||||
req->hook.on_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fcgi_is_closed(fcgi_request *req)
|
||||
{
|
||||
return (req->fd < 0);
|
||||
}
|
||||
|
||||
static int fcgi_is_allowed() {
|
||||
int i;
|
||||
|
||||
if (client_sa.sa.sa_family == AF_UNIX) {
|
||||
return 1;
|
||||
}
|
||||
if (!allowed_clients) {
|
||||
return 1;
|
||||
}
|
||||
if (client_sa.sa.sa_family == AF_INET) {
|
||||
for (i = 0; allowed_clients[i].sa.sa_family ; i++) {
|
||||
if (allowed_clients[i].sa.sa_family == AF_INET
|
||||
&& !memcmp(&client_sa.sa_inet.sin_addr, &allowed_clients[i].sa_inet.sin_addr, 4)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (client_sa.sa.sa_family == AF_INET6) {
|
||||
for (i = 0; allowed_clients[i].sa.sa_family ; i++) {
|
||||
if (allowed_clients[i].sa.sa_family == AF_INET6
|
||||
&& !memcmp(&client_sa.sa_inet6.sin6_addr, &allowed_clients[i].sa_inet6.sin6_addr, 12)) {
|
||||
return 1;
|
||||
}
|
||||
#ifdef IN6_IS_ADDR_V4MAPPED
|
||||
if (allowed_clients[i].sa.sa_family == AF_INET
|
||||
&& IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)
|
||||
&& !memcmp(((char *)&client_sa.sa_inet6.sin6_addr)+12, &allowed_clients[i].sa_inet.sin_addr, 4)) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
logger(FCGI_ERROR, "Connection disallowed: IP address '%s' has been dropped.", fcgi_get_last_client_ip());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fcgi_accept_request(fcgi_request *req)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -1215,37 +1269,19 @@ int fcgi_accept_request(fcgi_request *req)
|
||||
sa_t sa;
|
||||
socklen_t len = sizeof(sa);
|
||||
|
||||
if (req->hook.on_accept) {
|
||||
req->hook.on_accept();
|
||||
}
|
||||
|
||||
FCGI_LOCK(req->listen_socket);
|
||||
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
|
||||
FCGI_UNLOCK(req->listen_socket);
|
||||
if (req->fd >= 0) {
|
||||
if (((struct sockaddr *)&sa)->sa_family == AF_INET) {
|
||||
#ifndef _WIN32
|
||||
req->tcp = 1;
|
||||
#endif
|
||||
if (allowed_clients) {
|
||||
int n = 0;
|
||||
int allowed = 0;
|
||||
|
||||
while (allowed_clients[n] != INADDR_NONE) {
|
||||
if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
|
||||
allowed = 1;
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
if (!allowed) {
|
||||
flog(FCGI_ERROR, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
|
||||
closesocket(req->fd);
|
||||
req->fd = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifndef _WIN32
|
||||
} else {
|
||||
req->tcp = 0;
|
||||
#endif
|
||||
}
|
||||
client_sa = sa;
|
||||
if (req->fd >= 0 && !fcgi_is_allowed()) {
|
||||
closesocket(req->fd);
|
||||
req->fd = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,6 +1301,10 @@ int fcgi_accept_request(fcgi_request *req)
|
||||
struct pollfd fds;
|
||||
int ret;
|
||||
|
||||
if (req->hook.on_read) {
|
||||
req->hook.on_read();
|
||||
}
|
||||
|
||||
fds.fd = req->fd;
|
||||
fds.events = POLLIN;
|
||||
fds.revents = 0;
|
||||
@@ -1277,6 +1317,10 @@ int fcgi_accept_request(fcgi_request *req)
|
||||
}
|
||||
fcgi_close(req, 1, 0);
|
||||
#else
|
||||
if (req->hook.on_read) {
|
||||
req->hook.on_read();
|
||||
}
|
||||
|
||||
if (req->fd < FD_SETSIZE) {
|
||||
struct timeval tv = {5,0};
|
||||
fd_set set;
|
||||
@@ -1293,7 +1337,7 @@ int fcgi_accept_request(fcgi_request *req)
|
||||
}
|
||||
fcgi_close(req, 1, 0);
|
||||
} else {
|
||||
flog(FCGI_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
|
||||
logger(FCGI_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
|
||||
fcgi_close(req, 1, 0);
|
||||
}
|
||||
#endif
|
||||
@@ -1560,6 +1604,31 @@ void fcgi_free_mgmt_var_cb(zval *zv)
|
||||
pefree(Z_STR_P(zv), 1);
|
||||
}
|
||||
|
||||
const char *fcgi_get_last_client_ip()
|
||||
{
|
||||
static char str[INET6_ADDRSTRLEN];
|
||||
|
||||
/* Ipv4 */
|
||||
if (client_sa.sa.sa_family == AF_INET) {
|
||||
return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet.sin_addr, str, INET6_ADDRSTRLEN);
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
#ifdef IN6_IS_ADDR_V4MAPPED
|
||||
/* Ipv4-Mapped-Ipv6 */
|
||||
if (client_sa.sa.sa_family == AF_INET6
|
||||
&& IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)) {
|
||||
return inet_ntop(AF_INET, ((char *)&client_sa.sa_inet6.sin6_addr)+12, str, INET6_ADDRSTRLEN);
|
||||
}
|
||||
#endif
|
||||
/* Ipv6 */
|
||||
if (client_sa.sa.sa_family == AF_INET6) {
|
||||
return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet6.sin6_addr, str, INET6_ADDRSTRLEN);
|
||||
}
|
||||
#endif
|
||||
/* Unix socket */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
||||
@@ -49,11 +49,13 @@ typedef enum _fcgi_role {
|
||||
FCGI_FILTER = 3
|
||||
} fcgi_role;
|
||||
|
||||
typedef enum _fcgi_code {
|
||||
FCGI_NOTICE,
|
||||
FCGI_WARNING,
|
||||
FCGI_ERROR,
|
||||
} fcgi_code;
|
||||
enum {
|
||||
FCGI_DEBUG = 1,
|
||||
FCGI_NOTICE = 2,
|
||||
FCGI_WARNING = 3,
|
||||
FCGI_ERROR = 4,
|
||||
FCGI_ALERT = 5,
|
||||
};
|
||||
|
||||
typedef enum _fcgi_request_type {
|
||||
FCGI_BEGIN_REQUEST = 1, /* [in] */
|
||||
@@ -116,21 +118,91 @@ typedef struct _fcgi_end_request_rec {
|
||||
|
||||
typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
|
||||
|
||||
typedef void (*fcgi_logger)(int type, const char *format, ...);
|
||||
typedef void (*fcgi_logger)(int type, const char *fmt, ...);
|
||||
|
||||
typedef struct _fcgi_request fcgi_request;
|
||||
#define FCGI_HASH_TABLE_SIZE 128
|
||||
#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
|
||||
#define FCGI_HASH_SEG_SIZE 4096
|
||||
|
||||
typedef struct _fcgi_hash_bucket {
|
||||
unsigned int hash_value;
|
||||
unsigned int var_len;
|
||||
char *var;
|
||||
unsigned int val_len;
|
||||
char *val;
|
||||
struct _fcgi_hash_bucket *next;
|
||||
struct _fcgi_hash_bucket *list_next;
|
||||
} fcgi_hash_bucket;
|
||||
|
||||
typedef struct _fcgi_hash_buckets {
|
||||
unsigned int idx;
|
||||
struct _fcgi_hash_buckets *next;
|
||||
struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
|
||||
} fcgi_hash_buckets;
|
||||
|
||||
typedef struct _fcgi_data_seg {
|
||||
char *pos;
|
||||
char *end;
|
||||
struct _fcgi_data_seg *next;
|
||||
char data[1];
|
||||
} fcgi_data_seg;
|
||||
|
||||
typedef struct _fcgi_hash {
|
||||
fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
|
||||
fcgi_hash_bucket *list;
|
||||
fcgi_hash_buckets *buckets;
|
||||
fcgi_data_seg *data;
|
||||
} fcgi_hash;
|
||||
|
||||
typedef struct _fcgi_request fcgi_request;
|
||||
typedef struct _fcgi_req_hook fcgi_req_hook;
|
||||
|
||||
struct _fcgi_req_hook {
|
||||
void(*on_accept)();
|
||||
void(*on_read)();
|
||||
void(*on_close)();
|
||||
};
|
||||
|
||||
struct _fcgi_request {
|
||||
int listen_socket;
|
||||
int tcp;
|
||||
int fd;
|
||||
int id;
|
||||
int keep;
|
||||
#ifdef TCP_NODELAY
|
||||
int nodelay;
|
||||
#endif
|
||||
int closed;
|
||||
|
||||
fcgi_req_hook hook;
|
||||
|
||||
int in_len;
|
||||
int in_pad;
|
||||
|
||||
fcgi_header *out_hdr;
|
||||
unsigned char *out_pos;
|
||||
unsigned char out_buf[1024*8];
|
||||
unsigned char reserved[sizeof(fcgi_end_request_rec)];
|
||||
|
||||
int has_env;
|
||||
fcgi_hash env;
|
||||
};
|
||||
|
||||
int fcgi_init(void);
|
||||
void fcgi_shutdown(void);
|
||||
int fcgi_is_fastcgi(void);
|
||||
int fcgi_is_closed(fcgi_request *req);
|
||||
void fcgi_close(fcgi_request *req, int force, int destroy);
|
||||
int fcgi_in_shutdown(void);
|
||||
void fcgi_terminate(void);
|
||||
int fcgi_listen(const char *path, int backlog);
|
||||
fcgi_request* fcgi_init_request(int listen_socket);
|
||||
void fcgi_destroy_request(fcgi_request *req);
|
||||
fcgi_request* fcgi_init_request(fcgi_request *request, int listen_socket);
|
||||
void fcgi_set_allowed_clients(char *ip);
|
||||
int fcgi_accept_request(fcgi_request *req);
|
||||
int fcgi_finish_request(fcgi_request *req, int force_close);
|
||||
void fcgi_set_logger(fcgi_logger logger);
|
||||
void fcgi_set_logger(fcgi_logger lg);
|
||||
const char *fcgi_get_last_client_ip();
|
||||
void fcgi_set_in_shutdown(int new_value);
|
||||
|
||||
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
|
||||
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
|
||||
|
||||
@@ -1034,12 +1034,12 @@ static int is_valid_path(const char *path)
|
||||
/* }}} */
|
||||
|
||||
#define CGI_GETENV(name) \
|
||||
((request) ? \
|
||||
((request->has_env) ? \
|
||||
FCGI_GETENV(request, name) : \
|
||||
getenv(name))
|
||||
|
||||
#define CGI_PUTENV(name, value) \
|
||||
((request) ? \
|
||||
((request->has_env) ? \
|
||||
FCGI_PUTENV(request, name, value) : \
|
||||
_sapi_cgi_putenv(name, sizeof(name)-1, value))
|
||||
|
||||
@@ -1732,7 +1732,7 @@ int main(int argc, char *argv[])
|
||||
int fastcgi;
|
||||
char *bindpath = NULL;
|
||||
int fcgi_fd = 0;
|
||||
fcgi_request *request = NULL;
|
||||
fcgi_request request = {0};
|
||||
int warmup_repeats = 0;
|
||||
int repeats = 1;
|
||||
int benchmark = 0;
|
||||
@@ -1967,109 +1967,109 @@ consult the installation file that came with this distribution, or visit \n\
|
||||
php_import_environment_variables = cgi_php_import_environment_variables;
|
||||
|
||||
/* library is already initialized, now init our request */
|
||||
request = fcgi_init_request(fcgi_fd);
|
||||
fcgi_init_request(&request, fcgi_fd);
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
/* Pre-fork, if required */
|
||||
if (getenv("PHP_FCGI_CHILDREN")) {
|
||||
char * children_str = getenv("PHP_FCGI_CHILDREN");
|
||||
children = atoi(children_str);
|
||||
if (children < 0) {
|
||||
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
|
||||
return FAILURE;
|
||||
}
|
||||
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
|
||||
/* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
|
||||
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
|
||||
} else {
|
||||
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
|
||||
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
|
||||
}
|
||||
|
||||
if (children) {
|
||||
int running = 0;
|
||||
pid_t pid;
|
||||
|
||||
/* Create a process group for ourself & children */
|
||||
setsid();
|
||||
pgroup = getpgrp();
|
||||
#ifdef DEBUG_FASTCGI
|
||||
fprintf(stderr, "Process group %d\n", pgroup);
|
||||
#endif
|
||||
|
||||
/* Set up handler to kill children upon exit */
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = fastcgi_cleanup;
|
||||
if (sigaction(SIGTERM, &act, &old_term) ||
|
||||
sigaction(SIGINT, &act, &old_int) ||
|
||||
sigaction(SIGQUIT, &act, &old_quit)
|
||||
) {
|
||||
perror("Can't set signals");
|
||||
exit(1);
|
||||
/* Pre-fork, if required */
|
||||
if (getenv("PHP_FCGI_CHILDREN")) {
|
||||
char * children_str = getenv("PHP_FCGI_CHILDREN");
|
||||
children = atoi(children_str);
|
||||
if (children < 0) {
|
||||
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
|
||||
return FAILURE;
|
||||
}
|
||||
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
|
||||
/* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
|
||||
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
|
||||
} else {
|
||||
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
|
||||
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
|
||||
}
|
||||
|
||||
if (fcgi_in_shutdown()) {
|
||||
goto parent_out;
|
||||
}
|
||||
if (children) {
|
||||
int running = 0;
|
||||
pid_t pid;
|
||||
|
||||
while (parent) {
|
||||
do {
|
||||
/* Create a process group for ourself & children */
|
||||
setsid();
|
||||
pgroup = getpgrp();
|
||||
#ifdef DEBUG_FASTCGI
|
||||
fprintf(stderr, "Forking, %d running\n", running);
|
||||
fprintf(stderr, "Process group %d\n", pgroup);
|
||||
#endif
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case 0:
|
||||
/* One of the children.
|
||||
* Make sure we don't go round the
|
||||
* fork loop any more
|
||||
*/
|
||||
parent = 0;
|
||||
|
||||
/* don't catch our signals */
|
||||
sigaction(SIGTERM, &old_term, 0);
|
||||
sigaction(SIGQUIT, &old_quit, 0);
|
||||
sigaction(SIGINT, &old_int, 0);
|
||||
break;
|
||||
case -1:
|
||||
perror("php (pre-forking)");
|
||||
exit(1);
|
||||
break;
|
||||
default:
|
||||
/* Fine */
|
||||
running++;
|
||||
break;
|
||||
}
|
||||
} while (parent && (running < children));
|
||||
/* Set up handler to kill children upon exit */
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = fastcgi_cleanup;
|
||||
if (sigaction(SIGTERM, &act, &old_term) ||
|
||||
sigaction(SIGINT, &act, &old_int) ||
|
||||
sigaction(SIGQUIT, &act, &old_quit)
|
||||
) {
|
||||
perror("Can't set signals");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
if (fcgi_in_shutdown()) {
|
||||
goto parent_out;
|
||||
}
|
||||
|
||||
while (parent) {
|
||||
do {
|
||||
#ifdef DEBUG_FASTCGI
|
||||
fprintf(stderr, "Wait for kids, pid %d\n", getpid());
|
||||
fprintf(stderr, "Forking, %d running\n", running);
|
||||
#endif
|
||||
parent_waiting = 1;
|
||||
while (1) {
|
||||
if (wait(&status) >= 0) {
|
||||
running--;
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case 0:
|
||||
/* One of the children.
|
||||
* Make sure we don't go round the
|
||||
* fork loop any more
|
||||
*/
|
||||
parent = 0;
|
||||
|
||||
/* don't catch our signals */
|
||||
sigaction(SIGTERM, &old_term, 0);
|
||||
sigaction(SIGQUIT, &old_quit, 0);
|
||||
sigaction(SIGINT, &old_int, 0);
|
||||
break;
|
||||
} else if (exit_signal) {
|
||||
case -1:
|
||||
perror("php (pre-forking)");
|
||||
exit(1);
|
||||
break;
|
||||
default:
|
||||
/* Fine */
|
||||
running++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exit_signal) {
|
||||
#if 0
|
||||
while (running > 0) {
|
||||
while (wait(&status) < 0) {
|
||||
} while (parent && (running < children));
|
||||
|
||||
if (parent) {
|
||||
#ifdef DEBUG_FASTCGI
|
||||
fprintf(stderr, "Wait for kids, pid %d\n", getpid());
|
||||
#endif
|
||||
parent_waiting = 1;
|
||||
while (1) {
|
||||
if (wait(&status) >= 0) {
|
||||
running--;
|
||||
break;
|
||||
} else if (exit_signal) {
|
||||
break;
|
||||
}
|
||||
running--;
|
||||
}
|
||||
if (exit_signal) {
|
||||
#if 0
|
||||
while (running > 0) {
|
||||
while (wait(&status) < 0) {
|
||||
}
|
||||
running--;
|
||||
}
|
||||
#endif
|
||||
goto parent_out;
|
||||
goto parent_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parent = 0;
|
||||
}
|
||||
} else {
|
||||
parent = 0;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
@@ -2096,9 +2096,6 @@ consult the installation file that came with this distribution, or visit \n\
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
if (request) {
|
||||
fcgi_destroy_request(request);
|
||||
}
|
||||
fcgi_shutdown();
|
||||
no_headers = 1;
|
||||
SG(headers_sent) = 1;
|
||||
@@ -2120,9 +2117,9 @@ consult the installation file that came with this distribution, or visit \n\
|
||||
fcgi_impersonate();
|
||||
}
|
||||
#endif
|
||||
while (!fastcgi || fcgi_accept_request(request) >= 0) {
|
||||
SG(server_context) = fastcgi ? (void *) request : (void *) 1;
|
||||
init_request_info(request);
|
||||
while (!fastcgi || fcgi_accept_request(&request) >= 0) {
|
||||
SG(server_context) = fastcgi ? (void *)&request : (void *) 1;
|
||||
init_request_info(&request);
|
||||
|
||||
if (!cgi && !fastcgi) {
|
||||
while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
|
||||
@@ -2307,7 +2304,7 @@ consult the installation file that came with this distribution, or visit \n\
|
||||
* get path_translated */
|
||||
if (php_request_startup() == FAILURE) {
|
||||
if (fastcgi) {
|
||||
fcgi_finish_request(request, 1);
|
||||
fcgi_finish_request(&request, 1);
|
||||
}
|
||||
SG(server_context) = NULL;
|
||||
php_module_shutdown();
|
||||
@@ -2518,7 +2515,7 @@ fastcgi_request_done:
|
||||
/* only fastcgi will get here */
|
||||
requests++;
|
||||
if (max_requests && (requests == max_requests)) {
|
||||
fcgi_finish_request(request, 1);
|
||||
fcgi_finish_request(&request, 1);
|
||||
if (bindpath) {
|
||||
free(bindpath);
|
||||
}
|
||||
@@ -2530,9 +2527,6 @@ fastcgi_request_done:
|
||||
}
|
||||
/* end of fastcgi loop */
|
||||
}
|
||||
if (request) {
|
||||
fcgi_destroy_request(request);
|
||||
}
|
||||
fcgi_shutdown();
|
||||
|
||||
if (cgi_sapi_module.php_ini_path_override) {
|
||||
|
||||
@@ -678,8 +678,7 @@ if test "$PHP_FPM" != "no"; then
|
||||
|
||||
PHP_FPM_CFLAGS="-I$abs_srcdir/sapi/fpm"
|
||||
|
||||
PHP_FPM_FILES="fpm/fastcgi.c \
|
||||
fpm/fpm.c \
|
||||
PHP_FPM_FILES="fpm/fpm.c \
|
||||
fpm/fpm_children.c \
|
||||
fpm/fpm_cleanup.c \
|
||||
fpm/fpm_clock.c \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2015 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id: fastcgi.h 272370 2008-12-31 11:15:49Z sebastian $ */
|
||||
|
||||
/* FastCGI protocol */
|
||||
|
||||
#define FCGI_VERSION_1 1
|
||||
|
||||
#define FCGI_MAX_LENGTH 0xffff
|
||||
|
||||
#define FCGI_KEEP_CONN 1
|
||||
|
||||
/* this is near the perfect hash function for most useful FastCGI variables
|
||||
* which combines efficiency and minimal hash collisions
|
||||
*/
|
||||
|
||||
#define FCGI_HASH_FUNC(var, var_len) \
|
||||
(UNEXPECTED(var_len < 3) ? var_len : \
|
||||
(((unsigned int)var[3]) << 2) + \
|
||||
(((unsigned int)var[var_len-2]) << 4) + \
|
||||
(((unsigned int)var[var_len-1]) << 2) + \
|
||||
var_len)
|
||||
|
||||
#define FCGI_GETENV(request, name) \
|
||||
fcgi_quick_getenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1))
|
||||
|
||||
#define FCGI_PUTENV(request, name, value) \
|
||||
fcgi_quick_putenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1), value)
|
||||
|
||||
typedef enum _fcgi_role {
|
||||
FCGI_RESPONDER = 1,
|
||||
FCGI_AUTHORIZER = 2,
|
||||
FCGI_FILTER = 3
|
||||
} fcgi_role;
|
||||
|
||||
typedef enum _fcgi_request_type {
|
||||
FCGI_BEGIN_REQUEST = 1, /* [in] */
|
||||
FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */
|
||||
FCGI_END_REQUEST = 3, /* [out] */
|
||||
FCGI_PARAMS = 4, /* [in] environment variables */
|
||||
FCGI_STDIN = 5, /* [in] post data */
|
||||
FCGI_STDOUT = 6, /* [out] response */
|
||||
FCGI_STDERR = 7, /* [out] errors */
|
||||
FCGI_DATA = 8, /* [in] filter data (not supported) */
|
||||
FCGI_GET_VALUES = 9, /* [in] */
|
||||
FCGI_GET_VALUES_RESULT = 10 /* [out] */
|
||||
} fcgi_request_type;
|
||||
|
||||
typedef enum _fcgi_protocol_status {
|
||||
FCGI_REQUEST_COMPLETE = 0,
|
||||
FCGI_CANT_MPX_CONN = 1,
|
||||
FCGI_OVERLOADED = 2,
|
||||
FCGI_UNKNOWN_ROLE = 3
|
||||
} dcgi_protocol_status;
|
||||
|
||||
typedef struct _fcgi_header {
|
||||
unsigned char version;
|
||||
unsigned char type;
|
||||
unsigned char requestIdB1;
|
||||
unsigned char requestIdB0;
|
||||
unsigned char contentLengthB1;
|
||||
unsigned char contentLengthB0;
|
||||
unsigned char paddingLength;
|
||||
unsigned char reserved;
|
||||
} fcgi_header;
|
||||
|
||||
typedef struct _fcgi_begin_request {
|
||||
unsigned char roleB1;
|
||||
unsigned char roleB0;
|
||||
unsigned char flags;
|
||||
unsigned char reserved[5];
|
||||
} fcgi_begin_request;
|
||||
|
||||
typedef struct _fcgi_begin_request_rec {
|
||||
fcgi_header hdr;
|
||||
fcgi_begin_request body;
|
||||
} fcgi_begin_request_rec;
|
||||
|
||||
typedef struct _fcgi_end_request {
|
||||
unsigned char appStatusB3;
|
||||
unsigned char appStatusB2;
|
||||
unsigned char appStatusB1;
|
||||
unsigned char appStatusB0;
|
||||
unsigned char protocolStatus;
|
||||
unsigned char reserved[3];
|
||||
} fcgi_end_request;
|
||||
|
||||
typedef struct _fcgi_end_request_rec {
|
||||
fcgi_header hdr;
|
||||
fcgi_end_request body;
|
||||
} fcgi_end_request_rec;
|
||||
|
||||
/* FastCGI client API */
|
||||
|
||||
typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
|
||||
|
||||
typedef struct _fcgi_request fcgi_request;
|
||||
|
||||
int fcgi_init(void);
|
||||
void fcgi_shutdown(void);
|
||||
int fcgi_in_shutdown(void);
|
||||
void fcgi_terminate(void);
|
||||
fcgi_request* fcgi_init_request(int listen_socket);
|
||||
void fcgi_destroy_request(fcgi_request *req);
|
||||
int fcgi_accept_request(fcgi_request *req);
|
||||
int fcgi_finish_request(fcgi_request *req, int force_close);
|
||||
|
||||
void fcgi_set_allowed_clients(char *);
|
||||
void fcgi_close(fcgi_request *req, int force, int destroy);
|
||||
int fcgi_is_closed(fcgi_request *req);
|
||||
|
||||
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
|
||||
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
|
||||
char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value);
|
||||
char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val);
|
||||
void fcgi_loadenv(fcgi_request *req, fcgi_apply_func load_func, zval *array);
|
||||
|
||||
int fcgi_read(fcgi_request *req, char *str, int len);
|
||||
|
||||
ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
|
||||
int fcgi_flush(fcgi_request *req, int close);
|
||||
|
||||
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
|
||||
void fcgi_free_mgmt_var_cb(zval *ptr);
|
||||
|
||||
const char *fcgi_get_last_client_ip();
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -219,14 +219,15 @@ static php_cgi_globals_struct php_cgi_globals;
|
||||
#define TRANSLATE_SLASHES(path)
|
||||
#endif
|
||||
|
||||
static int print_module_info(zval *zv)
|
||||
static int print_module_info(zval *zv) /* {{{ */
|
||||
{
|
||||
zend_module_entry *module = Z_PTR_P(zv);
|
||||
php_printf("%s\n", module->name);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int module_name_cmp(const void *a, const void *b)
|
||||
static int module_name_cmp(const void *a, const void *b) /* {{{ */
|
||||
{
|
||||
Bucket *f = (Bucket *) a;
|
||||
Bucket *s = (Bucket *) b;
|
||||
@@ -234,8 +235,9 @@ static int module_name_cmp(const void *a, const void *b)
|
||||
return strcasecmp( ((zend_module_entry *) Z_PTR(f->val))->name,
|
||||
((zend_module_entry *) Z_PTR(s->val))->name);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void print_modules(void)
|
||||
static void print_modules(void) /* {{{ */
|
||||
{
|
||||
HashTable sorted_registry;
|
||||
|
||||
@@ -245,20 +247,23 @@ static void print_modules(void)
|
||||
zend_hash_apply(&sorted_registry, print_module_info);
|
||||
zend_hash_destroy(&sorted_registry);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int print_extension_info(zend_extension *ext, void *arg)
|
||||
static int print_extension_info(zend_extension *ext, void *arg) /* {{{ */
|
||||
{
|
||||
php_printf("%s\n", ext->name);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s)
|
||||
static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s) /* {{{ */
|
||||
{
|
||||
return strcmp( ((zend_extension *)(*f)->data)->name,
|
||||
((zend_extension *)(*s)->data)->name);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void print_extensions(void)
|
||||
static void print_extensions(void) /* {{{ */
|
||||
{
|
||||
zend_llist sorted_exts;
|
||||
|
||||
@@ -268,12 +273,13 @@ static void print_extensions(void)
|
||||
zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL);
|
||||
zend_llist_destroy(&sorted_exts);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
|
||||
static inline size_t sapi_cgibin_single_write(const char *str, uint str_length) /* {{{ */
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
@@ -298,8 +304,9 @@ static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
|
||||
return fwrite(str, 1, MIN(str_length, 16384), stdout);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static size_t sapi_cgibin_ub_write(const char *str, size_t str_length)
|
||||
static size_t sapi_cgibin_ub_write(const char *str, size_t str_length) /* {{{ */
|
||||
{
|
||||
const char *ptr = str;
|
||||
uint remaining = str_length;
|
||||
@@ -317,9 +324,9 @@ static size_t sapi_cgibin_ub_write(const char *str, size_t str_length)
|
||||
|
||||
return str_length;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static void sapi_cgibin_flush(void *server_context)
|
||||
static void sapi_cgibin_flush(void *server_context) /* {{{ */
|
||||
{
|
||||
/* fpm has started, let use fcgi instead of stdout */
|
||||
if (fpm_is_running) {
|
||||
@@ -339,10 +346,11 @@ static void sapi_cgibin_flush(void *server_context)
|
||||
php_handle_aborted_connection();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define SAPI_CGI_MAX_HEADER_LENGTH 1024
|
||||
|
||||
static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
|
||||
{
|
||||
char buf[SAPI_CGI_MAX_HEADER_LENGTH];
|
||||
sapi_header_struct *h;
|
||||
@@ -443,12 +451,22 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
|
||||
static void fpm_fcgi_log(int type, const char *fmt, ...) /* {{{ */
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vzlog("", 0, type, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) /* {{{ */
|
||||
{
|
||||
uint read_bytes = 0;
|
||||
int tmp_read_bytes;
|
||||
@@ -486,8 +504,9 @@ static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
|
||||
}
|
||||
return read_bytes;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static char *sapi_cgibin_getenv(char *name, size_t name_len)
|
||||
static char *sapi_cgibin_getenv(char *name, size_t name_len) /* {{{ */
|
||||
{
|
||||
/* if fpm has started, use fcgi env */
|
||||
if (fpm_is_running) {
|
||||
@@ -498,8 +517,9 @@ static char *sapi_cgibin_getenv(char *name, size_t name_len)
|
||||
/* if fpm has not started yet, use std env */
|
||||
return getenv(name);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static char *_sapi_cgibin_putenv(char *name, char *value)
|
||||
static char *_sapi_cgibin_putenv(char *name, char *value) /* {{{ */
|
||||
{
|
||||
int name_len;
|
||||
|
||||
@@ -511,15 +531,17 @@ static char *_sapi_cgibin_putenv(char *name, char *value)
|
||||
fcgi_request *request = (fcgi_request*) SG(server_context);
|
||||
return fcgi_putenv(request, name, name_len, value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static char *sapi_cgi_read_cookies(void)
|
||||
static char *sapi_cgi_read_cookies(void) /* {{{ */
|
||||
{
|
||||
fcgi_request *request = (fcgi_request*) SG(server_context);
|
||||
|
||||
return FCGI_GETENV(request, "HTTP_COOKIE");
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
|
||||
static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */
|
||||
{
|
||||
zval *array_ptr = (zval*)arg;
|
||||
int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER;
|
||||
@@ -529,13 +551,11 @@ static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, uns
|
||||
php_register_variable_safe(var, val, new_val_len, array_ptr);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void cgi_php_import_environment_variables(zval *array_ptr)
|
||||
void cgi_php_import_environment_variables(zval *array_ptr) /* {{{ */
|
||||
{
|
||||
fcgi_request *request;
|
||||
zend_string *var;
|
||||
char *val;
|
||||
int filter_arg;
|
||||
|
||||
if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
|
||||
Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) &&
|
||||
@@ -559,8 +579,9 @@ void cgi_php_import_environment_variables(zval *array_ptr)
|
||||
request = (fcgi_request*) SG(server_context);
|
||||
fcgi_loadenv(request, cgi_php_load_env_var, array_ptr);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void sapi_cgi_register_variables(zval *track_vars_array)
|
||||
static void sapi_cgi_register_variables(zval *track_vars_array) /* {{{ */
|
||||
{
|
||||
fcgi_request *request = (fcgi_request*) SG(server_context);
|
||||
size_t php_self_len;
|
||||
@@ -601,6 +622,7 @@ static void sapi_cgi_register_variables(zval *track_vars_array)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ sapi_cgi_log_fastcgi
|
||||
*
|
||||
@@ -713,7 +735,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int sapi_cgi_activate(void)
|
||||
static int sapi_cgi_activate(void) /* {{{ */
|
||||
{
|
||||
fcgi_request *request = (fcgi_request*) SG(server_context);
|
||||
char *path, *doc_root, *server_name;
|
||||
@@ -784,8 +806,9 @@ static int sapi_cgi_activate(void)
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int sapi_cgi_deactivate(void)
|
||||
static int sapi_cgi_deactivate(void) /* {{{ */
|
||||
{
|
||||
/* flush only when SAPI was started. The reasons are:
|
||||
1. SAPI Deactivate is called from two places: module init and request shutdown
|
||||
@@ -802,14 +825,16 @@ static int sapi_cgi_deactivate(void)
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int php_cgi_startup(sapi_module_struct *sapi_module)
|
||||
static int php_cgi_startup(sapi_module_struct *sapi_module) /* {{{ */
|
||||
{
|
||||
if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ sapi_module_struct cgi_sapi_module
|
||||
*/
|
||||
@@ -1360,6 +1385,14 @@ static void init_request_info(void)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void fpm_init_request(fcgi_request *req, int listen_fd) /* {{{ */ {
|
||||
fcgi_init_request(req, listen_fd);
|
||||
req->hook.on_accept = fpm_request_accepting;
|
||||
req->hook.on_read = fpm_request_reading_headers;
|
||||
req->hook.on_close = fpm_request_finished;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */
|
||||
{
|
||||
int *mode = (int *)arg;
|
||||
@@ -1523,7 +1556,7 @@ int main(int argc, char *argv[])
|
||||
int max_requests = 500;
|
||||
int requests = 0;
|
||||
int fcgi_fd = 0;
|
||||
fcgi_request *request;
|
||||
fcgi_request request;
|
||||
char *fpm_config = NULL;
|
||||
char *fpm_prefix = NULL;
|
||||
char *fpm_pid = NULL;
|
||||
@@ -1553,6 +1586,7 @@ int main(int argc, char *argv[])
|
||||
cgi_sapi_module.php_ini_path_override = NULL;
|
||||
cgi_sapi_module.php_ini_ignore_cwd = 1;
|
||||
|
||||
fcgi_set_logger(fpm_fcgi_log);
|
||||
fcgi_init();
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
@@ -1819,12 +1853,12 @@ consult the installation file that came with this distribution, or visit \n\
|
||||
php_import_environment_variables = cgi_php_import_environment_variables;
|
||||
|
||||
/* library is already initialized, now init our request */
|
||||
request = fcgi_init_request(fcgi_fd);
|
||||
fpm_init_request(&request, fcgi_fd);
|
||||
|
||||
zend_first_try {
|
||||
while (fcgi_accept_request(request) >= 0) {
|
||||
while (fcgi_accept_request(&request) >= 0) {
|
||||
request_body_fd = -1;
|
||||
SG(server_context) = (void *) request;
|
||||
SG(server_context) = (void *) &request;
|
||||
init_request_info();
|
||||
char *primary_script = NULL;
|
||||
|
||||
@@ -1833,7 +1867,7 @@ consult the installation file that came with this distribution, or visit \n\
|
||||
/* request startup only after we've done all we can to
|
||||
* get path_translated */
|
||||
if (php_request_startup() == FAILURE) {
|
||||
fcgi_finish_request(request, 1);
|
||||
fcgi_finish_request(&request, 1);
|
||||
SG(server_context) = NULL;
|
||||
php_module_shutdown();
|
||||
return FPM_EXIT_SOFTWARE;
|
||||
@@ -1926,12 +1960,11 @@ fastcgi_request_done:
|
||||
|
||||
requests++;
|
||||
if (max_requests && (requests == max_requests)) {
|
||||
fcgi_finish_request(request, 1);
|
||||
fcgi_finish_request(&request, 1);
|
||||
break;
|
||||
}
|
||||
/* end of fastcgi loop */
|
||||
}
|
||||
fcgi_destroy_request(request);
|
||||
fcgi_shutdown();
|
||||
|
||||
if (cgi_sapi_module.php_ini_path_override) {
|
||||
|
||||
@@ -98,20 +98,17 @@ int zlog_set_level(int new_value) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */
|
||||
void vzlog(const char *function, int line, int flags, const char *fmt, va_list args) /* {{{ */
|
||||
{
|
||||
struct timeval tv;
|
||||
char buf[MAX_LINE_LENGTH];
|
||||
const size_t buf_size = MAX_LINE_LENGTH;
|
||||
va_list args;
|
||||
size_t len = 0;
|
||||
int truncated = 0;
|
||||
int saved_errno;
|
||||
|
||||
if (external_logger) {
|
||||
va_start(args, fmt);
|
||||
len = vsnprintf(buf, buf_size, fmt, args);
|
||||
va_end(args);
|
||||
if (len >= buf_size) {
|
||||
memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1);
|
||||
len = buf_size - 1;
|
||||
@@ -157,9 +154,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
|
||||
}
|
||||
|
||||
if (!truncated) {
|
||||
va_start(args, fmt);
|
||||
len += vsnprintf(buf + len, buf_size - len, fmt, args);
|
||||
va_end(args);
|
||||
if (len >= buf_size) {
|
||||
truncated = 1;
|
||||
}
|
||||
@@ -197,3 +192,10 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */ {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vzlog(function, line, flags, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ZLOG_H
|
||||
#define ZLOG_H 1
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define zlog(flags,...) zlog_ex(__func__, __LINE__, flags, __VA_ARGS__)
|
||||
|
||||
struct timeval;
|
||||
@@ -17,6 +19,7 @@ void zlog_set_launched(void);
|
||||
|
||||
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
|
||||
|
||||
void vzlog(const char *function, int line, int flags, const char *fmt, va_list args);
|
||||
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
|
||||
__attribute__ ((format(printf,4,5)));
|
||||
|
||||
@@ -24,6 +27,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
|
||||
extern const int syslog_priorities[];
|
||||
#endif
|
||||
|
||||
/* keep this same as FCGI_ERROR */
|
||||
enum {
|
||||
ZLOG_DEBUG = 1,
|
||||
ZLOG_NOTICE = 2,
|
||||
|
||||
Reference in New Issue
Block a user