mirror of
https://github.com/lxsang/antd-fcgi-plugin.git
synced 2024-12-26 13:18:21 +01:00
Add basic features:
- Read fastCGI configuration from server conf - Support TCP socket o Unix socket - Launch FastCGI server automatically if the server binary is in the config
This commit is contained in:
parent
14e6f28767
commit
3426eda29b
191
fcgi.c
191
fcgi.c
@ -23,8 +23,11 @@
|
|||||||
//#include <libgen.h>
|
//#include <libgen.h>
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
|
|
||||||
|
#ifdef MAX_PATH_LEN
|
||||||
|
#undef MAX_PATH_LEN
|
||||||
|
#endif
|
||||||
#define MAX_PATH_LEN 108
|
#define MAX_PATH_LEN 108
|
||||||
#define MAX_BACK_LOG 1024
|
#define MAX_BACK_LOG 64
|
||||||
#define PROCESS_TIMEOUT 200u
|
#define PROCESS_TIMEOUT 200u
|
||||||
|
|
||||||
#define FCGI_CLIENT_REQUEST_SENT (0)
|
#define FCGI_CLIENT_REQUEST_SENT (0)
|
||||||
@ -39,26 +42,40 @@ typedef struct {
|
|||||||
// only for TCP socket
|
// only for TCP socket
|
||||||
int port;
|
int port;
|
||||||
// server fd
|
// server fd
|
||||||
// int fd;
|
int fd;
|
||||||
// pid of the application process
|
// pid of the application process
|
||||||
// pid_t pid;
|
pid_t pid;
|
||||||
} fcgi_config_t;
|
} fcgi_config_t;
|
||||||
|
|
||||||
static fcgi_config_t g_config;
|
static fcgi_config_t g_config;
|
||||||
|
|
||||||
|
static int mk_socket();
|
||||||
|
static int read_config();
|
||||||
|
static int open_un_socket();
|
||||||
|
static int open_tcp_socket();
|
||||||
|
static int open_socket();
|
||||||
|
static char* read_line(char** buff, int* size);
|
||||||
|
static int read_header(antd_client_t* cl, antd_request_t* rq);
|
||||||
|
static int read_data(antd_client_t* cl, antd_request_t* rq);
|
||||||
|
static void *process(void *data);
|
||||||
|
static int send_request(antd_client_t *cl, antd_request_t* rq);
|
||||||
|
void* handle(void* data);
|
||||||
|
static int mk_un_socket();
|
||||||
|
static int mk_tcp_socket();
|
||||||
|
|
||||||
static int read_config()
|
static int read_config()
|
||||||
{
|
{
|
||||||
char * tmp;
|
char * tmp;
|
||||||
(void*) memset(g_config.app_bin, 0, MAX_PATH_LEN);
|
(void*) memset(g_config.app_bin, 0, MAX_PATH_LEN);
|
||||||
(void*) memset(g_config.address, 0, MAX_PATH_LEN);
|
(void*) memset(g_config.address, 0, MAX_PATH_LEN);
|
||||||
g_config.port = -1;
|
g_config.port = -1;
|
||||||
//g_config.fd = -1;
|
g_config.fd = -1;
|
||||||
//g_config.pid = -1;
|
g_config.pid = -1;
|
||||||
regmatch_t regex_matches[3];
|
regmatch_t regex_matches[3];
|
||||||
// read plugin configuration
|
// read plugin configuration
|
||||||
if(!__plugin__.config)
|
if(!__plugin__.config)
|
||||||
{
|
{
|
||||||
PLUGIN_PANIC("No plugin configuration found. Please specify it it server config file");
|
PLUGIN_PANIC("No plugin configuration found. Please specify it in server config file");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tmp = (char*) dvalue(__plugin__.config, "socket");
|
tmp = (char*) dvalue(__plugin__.config, "socket");
|
||||||
@ -96,20 +113,127 @@ static int read_config()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
tmp = (char*) dvalue(__plugin__.config, "bin");
|
tmp = (char*) dvalue(__plugin__.config, "bin");
|
||||||
if(!tmp)
|
if(tmp)
|
||||||
{
|
{
|
||||||
PLUGIN_PANIC("No FastCGI application configuration found (bin)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(strlen(tmp) > MAX_PATH_LEN - 1)
|
if(strlen(tmp) > MAX_PATH_LEN - 1)
|
||||||
{
|
{
|
||||||
PLUGIN_PANIC("Bin applicqtion configuration is too long: %s", tmp);
|
PLUGIN_PANIC("Bin application configuration is too long: %s", tmp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
snprintf(g_config.app_bin, MAX_PATH_LEN,"%s", tmp);
|
snprintf(g_config.app_bin, MAX_PATH_LEN,"%s", tmp);
|
||||||
LOG("Binary application configuration: %s", g_config.app_bin);
|
LOG("Binary application configuration: %s", g_config.app_bin);
|
||||||
|
// create the server socket then launched it
|
||||||
|
g_config.fd = mk_socket();
|
||||||
|
if(g_config.fd == -1)
|
||||||
|
{
|
||||||
|
PLUGIN_PANIC("Unable to create FastCGI server socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// launch the application
|
||||||
|
g_config.pid = fork();
|
||||||
|
if(g_config.pid == -1)
|
||||||
|
{
|
||||||
|
PLUGIN_PANIC("Unable to create FastCGI server socket");
|
||||||
|
close(g_config.fd);
|
||||||
|
g_config.fd = -1;
|
||||||
|
g_config.pid = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(g_config.pid == 0)
|
||||||
|
{
|
||||||
|
// child
|
||||||
|
// close the original stdin
|
||||||
|
close(0);
|
||||||
|
// redirect the stdin to the socket
|
||||||
|
dup2(g_config.fd, 0);
|
||||||
|
char *argv[] = {g_config.app_bin, 0};
|
||||||
|
char *env[] = {NULL, NULL};
|
||||||
|
env[0] = getenv("ANTD_DEBUG");
|
||||||
|
if(env[0] && (
|
||||||
|
(strcmp(env[0], "1") == 0) || (strcmp(env[0], "true") == 0)) )
|
||||||
|
{
|
||||||
|
env[0] = "debug=1";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
env[0] = "debug=0";
|
||||||
|
}
|
||||||
|
execve(argv[0], &argv[0], &env[0]);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
// parent
|
||||||
|
LOG("FastCGI process (%d) created", g_config.pid);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mk_un_socket()
|
||||||
|
{
|
||||||
|
struct sockaddr_un address;
|
||||||
|
address.sun_family = AF_UNIX;
|
||||||
|
//remove socket file if exists
|
||||||
|
(void) remove(g_config.address);
|
||||||
|
// create the socket
|
||||||
|
(void)strncpy(address.sun_path, g_config.address, sizeof(address.sun_path));
|
||||||
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
ERROR("Unable to create Unix domain socket: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bind(fd, (struct sockaddr *)(&address), sizeof(address)) == -1)
|
||||||
|
{
|
||||||
|
ERROR("Unable to bind name: %s to a socket: %s", address.sun_path, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// mark the socket as passive mode
|
||||||
|
|
||||||
|
if (listen(fd, MAX_BACK_LOG) == -1)
|
||||||
|
{
|
||||||
|
ERROR("Unable to listen to socket: %d (%s): %s", fd, g_config.address, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LOG("Socket %s is created successfully: %d", g_config.address, fd);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
static int mk_tcp_socket()
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
struct sockaddr_in name;
|
||||||
|
fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
ERROR("Unable to create TCP socket socket: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) == -1)
|
||||||
|
{
|
||||||
|
ERROR("Unable to set reuse address on port %d - setsockopt: %s", g_config.port, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&name, 0, sizeof(name));
|
||||||
|
name.sin_family = AF_INET;
|
||||||
|
name.sin_port = htons(g_config.port);
|
||||||
|
name.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
if (bind(fd, (struct sockaddr *)&name, sizeof(name)) < 0)
|
||||||
|
{
|
||||||
|
ERROR("Unable to bind TCP socket at port %d -bind: %s", g_config.port, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(fd, MAX_BACK_LOG) < 0)
|
||||||
|
{
|
||||||
|
ERROR("Unable to listen on Port %d - listen: %s", g_config.port, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
static int open_un_socket()
|
static int open_un_socket()
|
||||||
{
|
{
|
||||||
struct sockaddr_un address;
|
struct sockaddr_un address;
|
||||||
@ -171,6 +295,18 @@ static int open_socket()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mk_socket()
|
||||||
|
{
|
||||||
|
if(g_config.port != -1)
|
||||||
|
{
|
||||||
|
return mk_tcp_socket();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mk_un_socket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
use_raw_body();
|
use_raw_body();
|
||||||
@ -184,15 +320,22 @@ void init()
|
|||||||
}
|
}
|
||||||
void destroy()
|
void destroy()
|
||||||
{
|
{
|
||||||
/*if(g_config.fd)
|
if(g_config.pid > 0)
|
||||||
{
|
{
|
||||||
LOG("Close socket: %d", g_config.fd);
|
LOG("Process killed: %d", g_config.pid);
|
||||||
|
(void)kill(g_config.pid, SIGKILL);
|
||||||
|
g_config.pid = -1;
|
||||||
|
}
|
||||||
|
if(g_config.fd > 0)
|
||||||
|
{
|
||||||
|
LOG("Close server socket: %d", g_config.fd);
|
||||||
close(g_config.fd);
|
close(g_config.fd);
|
||||||
}*/
|
g_config.fd = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* read_line(char** buff, int* size)
|
static char* read_line(char** buff, int* size)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(i <= *size-1 && (*buff)[i] != '\n') i++;
|
while(i <= *size-1 && (*buff)[i] != '\n') i++;
|
||||||
@ -366,6 +509,18 @@ static void *process(void *data)
|
|||||||
antd_request_t *rq = (antd_request_t *)data;
|
antd_request_t *rq = (antd_request_t *)data;
|
||||||
antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "FCGI_CL_DATA");
|
antd_client_t* cl = (antd_client_t* ) dvalue(rq->request, "FCGI_CL_DATA");
|
||||||
struct pollfd pfds[2];
|
struct pollfd pfds[2];
|
||||||
|
int status;
|
||||||
|
if(g_config.pid > 0)
|
||||||
|
{
|
||||||
|
if(waitpid(g_config.pid, &status, WNOHANG) > 0)
|
||||||
|
{
|
||||||
|
PLUGIN_PANIC("FastCGI process exits unexpectedly");
|
||||||
|
antd_close(cl);
|
||||||
|
dput(rq->request, "FCGI_CL_DATA", NULL);
|
||||||
|
return antd_create_task(NULL, data, NULL, rq->client->last_io);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pfds[0].fd = rq->client->sock;
|
pfds[0].fd = rq->client->sock;
|
||||||
pfds[0].events = POLLIN;
|
pfds[0].events = POLLIN;
|
||||||
if(rq->client->ssl)
|
if(rq->client->ssl)
|
||||||
@ -488,7 +643,11 @@ static int send_request(antd_client_t *cl, antd_request_t* rq)
|
|||||||
dictionary_t header = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
|
dictionary_t header = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
|
||||||
ret += fcgi_begin_request(cl, cl->sock, FCGI_RESPONDER, 0);
|
ret += fcgi_begin_request(cl, cl->sock, FCGI_RESPONDER, 0);
|
||||||
//ret += fcgi_send_param(cl, cl->sock, "", "");
|
//ret += fcgi_send_param(cl, cl->sock, "", "");
|
||||||
|
// ANTD specific params
|
||||||
|
ret += fcgi_send_param(cl, cl->sock, "TMP_DIR", __plugin__.tmpdir);
|
||||||
|
ret += fcgi_send_param(cl, cl->sock, "DB_DIR", __plugin__.dbpath);
|
||||||
|
ret += fcgi_send_param(cl, cl->sock, "LIB_DIR", __plugin__.pdir);
|
||||||
|
// CGI parms
|
||||||
ret += fcgi_send_param(cl, cl->sock, "GATEWAY_INTERFACE", "CGI/1.1");
|
ret += fcgi_send_param(cl, cl->sock, "GATEWAY_INTERFACE", "CGI/1.1");
|
||||||
ret += fcgi_send_param(cl, cl->sock, "SERVER_SOFTWARE", SERVER_NAME);
|
ret += fcgi_send_param(cl, cl->sock, "SERVER_SOFTWARE", SERVER_NAME);
|
||||||
root = (char *)dvalue(request, "SERVER_WWW_ROOT");
|
root = (char *)dvalue(request, "SERVER_WWW_ROOT");
|
||||||
|
Loading…
Reference in New Issue
Block a user