mirror of
https://github.com/lxsang/ant-http
synced 2024-12-24 15:58:21 +01:00
add multiport support
This commit is contained in:
parent
d04d29fe6b
commit
3435733ac2
@ -9,8 +9,6 @@ plugins=/opt/www/lib/
|
||||
plugins_ext=.so
|
||||
; SQLITE database path
|
||||
database=/opt/www/database/
|
||||
; Website store here
|
||||
htdocs=/opt/www/htdocs
|
||||
; tmp dir
|
||||
tmpdir=/opt/www/tmp/
|
||||
; server log
|
||||
@ -19,13 +17,35 @@ server_log = /var/log/antd.log
|
||||
error_log = /var/log/antd_error.log
|
||||
; server backlocg
|
||||
backlog=5000
|
||||
; eable or disalbe SSL
|
||||
ssl.enable=0
|
||||
; if SSL is enable, one should specify
|
||||
; number of workers
|
||||
workers = 4
|
||||
; if SSL is enable on one port, one should specify
|
||||
; the SSL cert and key files
|
||||
; ssl.cert=fullchain.pem
|
||||
; ssl.key=privkey.pem
|
||||
; ssl.cipher=ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
|
||||
;Example: self signed key
|
||||
; openssl genrsa -des3 -passout pass:1234 -out keypair.key 2048
|
||||
; openssl rsa -passin pass:1234 -in keypair.key -out server.key
|
||||
; openssl req -new -key server.key -out server.csr
|
||||
; openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
|
||||
ssl.cert=/opt/www/server.crt
|
||||
ssl.key=/opt/www/server.key
|
||||
ssl.cipher=ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
|
||||
|
||||
; a configuration each port
|
||||
|
||||
[PORT:443]
|
||||
; Website store here
|
||||
htdocs=/opt/www/htdocs
|
||||
; enable or disalbe SSL
|
||||
ssl.enable=1
|
||||
|
||||
|
||||
[PORT:80]
|
||||
; Website store here
|
||||
htdocs=/opt/www/htdocs
|
||||
; enable or disalbe SSL
|
||||
ssl.enable=0
|
||||
|
||||
|
||||
; This enable some plugins to be initialised at server startup
|
||||
[AUTOSTART]
|
||||
; to start a plugin at server statup use:
|
||||
|
145
http_server.c
145
http_server.c
@ -82,8 +82,6 @@ void destroy_config()
|
||||
free(server_config.plugins_ext);
|
||||
if (server_config.db_path)
|
||||
free(server_config.db_path);
|
||||
if (server_config.htdocs)
|
||||
free(server_config.htdocs);
|
||||
if (server_config.tmpdir)
|
||||
free(server_config.tmpdir);
|
||||
if(server_config.ssl_cipher)
|
||||
@ -100,19 +98,35 @@ void destroy_config()
|
||||
#endif
|
||||
if(server_config.mimes)
|
||||
freedict(server_config.mimes);
|
||||
if(server_config.ports)
|
||||
{
|
||||
chain_t it;
|
||||
port_config_t* cnf;
|
||||
for_each_assoc(it, server_config.ports)
|
||||
{
|
||||
cnf = (port_config_t*)it->value;
|
||||
if(cnf && cnf->htdocs)
|
||||
free(cnf->htdocs);
|
||||
if(cnf->sock > 0)
|
||||
{
|
||||
close(cnf->sock);
|
||||
}
|
||||
}
|
||||
freedict(server_config.ports);
|
||||
}
|
||||
LOG("Unclosed connection: %d", server_config.connection);
|
||||
}
|
||||
|
||||
static int config_handler(void *conf, const char *section, const char *name,
|
||||
const char *value)
|
||||
const char *value)
|
||||
{
|
||||
config_t *pconfig = (config_t *)conf;
|
||||
regmatch_t port_matches[2];
|
||||
//trim(section, ' ');
|
||||
//trim(value,' ');
|
||||
//trim(name,' ');
|
||||
//char * ppath = NULL;
|
||||
if (MATCH("SERVER", "port"))
|
||||
{
|
||||
pconfig->port = atoi(value);
|
||||
}
|
||||
else if (MATCH("SERVER", "plugins"))
|
||||
if (MATCH("SERVER", "plugins"))
|
||||
{
|
||||
pconfig->plugins_dir = strdup(value);
|
||||
}
|
||||
@ -124,10 +138,6 @@ static int config_handler(void *conf, const char *section, const char *name,
|
||||
{
|
||||
pconfig->db_path = strdup(value);
|
||||
}
|
||||
else if (MATCH("SERVER", "htdocs"))
|
||||
{
|
||||
pconfig->htdocs = strdup(value);
|
||||
}
|
||||
else if (MATCH("SERVER", "tmpdir"))
|
||||
{
|
||||
pconfig->tmpdir = strdup(value);
|
||||
@ -155,10 +165,6 @@ static int config_handler(void *conf, const char *section, const char *name,
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OPENSSL
|
||||
else if (MATCH("SERVER", "ssl.enable"))
|
||||
{
|
||||
pconfig->usessl = atoi(value);
|
||||
}
|
||||
else if (MATCH("SERVER", "ssl.cert"))
|
||||
{
|
||||
pconfig->sslcert = strdup(value);
|
||||
@ -191,6 +197,31 @@ static int config_handler(void *conf, const char *section, const char *name,
|
||||
{
|
||||
dput(pconfig->mimes,name,strdup(value));
|
||||
}
|
||||
else if( regex_match("PORT:\\s*([0-9]+)", section, 2, port_matches) )
|
||||
{
|
||||
char buf[20];
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
memcpy(buf, section + port_matches[1].rm_so, port_matches[1].rm_eo - port_matches[1].rm_so);
|
||||
port_config_t* p = dvalue(pconfig->ports,buf);
|
||||
if(!p)
|
||||
{
|
||||
p = (port_config_t*) malloc( sizeof(port_config_t));
|
||||
p->htdocs = NULL;
|
||||
p->sock = -1;
|
||||
dput(pconfig->ports,buf, p);
|
||||
p->port = atoi(buf);
|
||||
}
|
||||
if(strcmp(name, "htdocs") == 0)
|
||||
{
|
||||
p->htdocs = strdup(value);
|
||||
}
|
||||
else if(strcmp(name, "ssl.enable") == 0)
|
||||
{
|
||||
p->usessl = atoi(value);
|
||||
if(p->usessl)
|
||||
pconfig->enable_ssl = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; /* unknown section/name, error */
|
||||
@ -200,14 +231,23 @@ static int config_handler(void *conf, const char *section, const char *name,
|
||||
void init_file_system()
|
||||
{
|
||||
struct stat st;
|
||||
port_config_t* pcnf;
|
||||
chain_t it;
|
||||
if (stat(server_config.plugins_dir, &st) == -1)
|
||||
mkdir(server_config.plugins_dir, 0755);
|
||||
mkdirp(server_config.plugins_dir, 0755);
|
||||
if (stat(server_config.db_path, &st) == -1)
|
||||
mkdir(server_config.db_path, 0755);
|
||||
if (stat(server_config.htdocs, &st) == -1)
|
||||
mkdir(server_config.htdocs, 0755);
|
||||
mkdirp(server_config.db_path, 0755);
|
||||
for_each_assoc(it, server_config.ports)
|
||||
{
|
||||
pcnf = (port_config_t*) it->value;
|
||||
if (stat(pcnf->htdocs, &st) == -1)
|
||||
{
|
||||
mkdirp(pcnf->htdocs, 0755);
|
||||
}
|
||||
|
||||
}
|
||||
if (stat(server_config.tmpdir, &st) == -1)
|
||||
mkdir(server_config.tmpdir, 0755);
|
||||
mkdirp(server_config.tmpdir, 0755);
|
||||
else
|
||||
{
|
||||
removeAll(server_config.tmpdir, 0);
|
||||
@ -215,22 +255,22 @@ void init_file_system()
|
||||
}
|
||||
void load_config(const char *file)
|
||||
{
|
||||
server_config.port = 8888;
|
||||
server_config.ports = dict();
|
||||
server_config.plugins_dir = "plugins/";
|
||||
server_config.plugins_ext = ".dylib";
|
||||
server_config.db_path = "databases/";
|
||||
server_config.htdocs = "htdocs/";
|
||||
//server_config.htdocs = "htdocs/";
|
||||
server_config.tmpdir = "tmp/";
|
||||
server_config.n_workers = 4;
|
||||
server_config.backlog = 100;
|
||||
server_config.backlog = 1000;
|
||||
server_config.rules = list_init();
|
||||
server_config.handlers = dict();
|
||||
server_config.maxcon = 1000;
|
||||
server_config.maxcon = 100;
|
||||
server_config.connection = 0;
|
||||
server_config.errorfp = NULL;
|
||||
server_config.logfp = NULL;
|
||||
server_config.mimes = dict();
|
||||
server_config.usessl = 0;
|
||||
server_config.enable_ssl = 0;
|
||||
server_config.sslcert = "cert.pem";
|
||||
server_config.sslkey = "key.pem";
|
||||
server_config.ssl_cipher = NULL;
|
||||
@ -247,7 +287,7 @@ void load_config(const char *file)
|
||||
{
|
||||
LOG("Using configuration : %s", file);
|
||||
#ifdef USE_OPENSSL
|
||||
LOG("SSL enable %d", server_config.usessl);
|
||||
LOG("SSL enable %d", server_config.enable_ssl);
|
||||
LOG("SSL cert %s", server_config.sslcert);
|
||||
LOG("SSL key %s", server_config.sslkey);
|
||||
/*if(!server_config.ssl_cipher)
|
||||
@ -257,6 +297,7 @@ void load_config(const char *file)
|
||||
#endif
|
||||
}
|
||||
LOG("%d mimes entries found", server_config.mimes->size);
|
||||
init_file_system();
|
||||
}
|
||||
|
||||
void *accept_request(void *data)
|
||||
@ -303,7 +344,7 @@ void *accept_request(void *data)
|
||||
// perform the ssl handshake if enabled
|
||||
#ifdef USE_OPENSSL
|
||||
int ret = -1, stat;
|
||||
if (server_config.usessl == 1 && client->status == 0)
|
||||
if (client->port_config->usessl == 1 && client->status == 0)
|
||||
{
|
||||
//LOG("Atttempt %d\n", client->attempt);
|
||||
if (SSL_accept((SSL *)client->ssl) == -1)
|
||||
@ -327,10 +368,10 @@ void *accept_request(void *data)
|
||||
task->handle = accept_request;
|
||||
return task;
|
||||
default:
|
||||
ERROR("Error performing SSL handshake %d %d %lu", stat, ret, ERR_get_error());
|
||||
ERROR("Error performing SSL handshake %d %d %s", stat, ret, ERR_error_string(ERR_get_error(), NULL));
|
||||
antd_error(rq->client, 400, "Invalid SSL request");
|
||||
//server_config.connection++;
|
||||
ERR_print_errors_fp(stderr);
|
||||
antd_error(rq->client, 400, "Invalid SSL request");
|
||||
return task;
|
||||
}
|
||||
}
|
||||
@ -405,7 +446,7 @@ void *resolve_request(void *data)
|
||||
char *newurl = NULL;
|
||||
char *rqp = NULL;
|
||||
char *oldrqp = NULL;
|
||||
strcpy(path, server_config.htdocs);
|
||||
strcpy(path, rq->client->port_config->htdocs);
|
||||
strcat(path, url);
|
||||
//LOG("Path is : %s", path);
|
||||
//if (path[strlen(path) - 1] == '/')
|
||||
@ -438,7 +479,7 @@ void *resolve_request(void *data)
|
||||
{
|
||||
newurl = __s("%s/index.%s", url, it->key);
|
||||
memset(path, 0, sizeof(path));
|
||||
strcat(path, server_config.htdocs);
|
||||
strcat(path, rq->client->port_config->htdocs);
|
||||
strcat(path, newurl);
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
@ -578,11 +619,6 @@ int rule_check(const char *k, const char *v, const char *host, const char *_url,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void error_die(const char *sc)
|
||||
{
|
||||
perror(sc);
|
||||
exit(1);
|
||||
}
|
||||
void *serve_file(void *data)
|
||||
{
|
||||
antd_request_t *rq = (antd_request_t *)data;
|
||||
@ -626,23 +662,35 @@ int startup(unsigned *port)
|
||||
|
||||
httpd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (httpd == -1)
|
||||
error_die("socket");
|
||||
{
|
||||
ERROR("Port %d - socket: %s", *port, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
memset(&name, 0, sizeof(name));
|
||||
name.sin_family = AF_INET;
|
||||
name.sin_port = htons(*port);
|
||||
name.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0)
|
||||
error_die("bind");
|
||||
{
|
||||
ERROR("Port %d -bind: %s", *port, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (*port == 0) /* if dynamically allocating a port */
|
||||
{
|
||||
socklen_t namelen = sizeof(name);
|
||||
if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1)
|
||||
error_die("getsockname");
|
||||
{
|
||||
ERROR("Port %d - getsockname: %s", *port, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
*port = ntohs(name.sin_port);
|
||||
}
|
||||
//LOG("back log is %d", server_config.backlog);
|
||||
LOG("back log is %d", server_config.backlog);
|
||||
if (listen(httpd, server_config.backlog) < 0)
|
||||
error_die("listen");
|
||||
{
|
||||
ERROR("Port %d - listen: %s", *port, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return (httpd);
|
||||
}
|
||||
|
||||
@ -703,7 +751,7 @@ void *decode_request_header(void *data)
|
||||
// this for check if web socket is enabled
|
||||
// ip address
|
||||
dput(xheader, "REMOTE_ADDR", (void *)strdup(((antd_client_t *)rq->client)->ip));
|
||||
dput(xheader, "SERVER_PORT", (void *)__s("%d", server_config.port));
|
||||
dput(xheader, "SERVER_PORT", (void *)__s("%d", ((antd_client_t *)rq->client)->port_config->port));
|
||||
//while((line = read_line(client)) && strcmp("\r\n",line))
|
||||
while ((read_buf(rq->client, buf, sizeof(buf))) && strcmp("\r\n", buf))
|
||||
{
|
||||
@ -728,9 +776,9 @@ void *decode_request_header(void *data)
|
||||
//if(line) free(line);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strcat(buf, url);
|
||||
//LOG("Original query: %s", url);
|
||||
LOG("Original query: %s", url);
|
||||
query = apply_rules(host, buf);
|
||||
//LOG("Processed query: %s", query);
|
||||
LOG("Processed query: %s", query);
|
||||
dput(rq->request, "RESOURCE_PATH", url_decode(buf));
|
||||
if (query)
|
||||
{
|
||||
@ -1242,13 +1290,6 @@ void *execute_plugin(void *data, const char *pname)
|
||||
return task;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
int usessl()
|
||||
{
|
||||
return server_config.usessl;
|
||||
}
|
||||
#endif
|
||||
|
||||
dictionary_t mimes_list()
|
||||
{
|
||||
return server_config.mimes;
|
||||
|
@ -27,11 +27,8 @@ void* finish_request(void*);
|
||||
void cat(void*, FILE *);
|
||||
void cannot_execute(void*);
|
||||
//int get_line(int, char *, int);
|
||||
void not_found(void*);
|
||||
void* serve_file(void*);
|
||||
int startup(unsigned *);
|
||||
void unimplemented(void*);
|
||||
void badrequest(void*);
|
||||
int rule_check(const char*, const char*, const char* , const char* , const char* , char*);
|
||||
void ws_confirm_request(void*, const char*);
|
||||
char* post_url_decode(void* client,int len);
|
||||
|
189
httpd.c
189
httpd.c
@ -4,7 +4,6 @@
|
||||
#include "lib/ini.h"
|
||||
|
||||
static antd_scheduler_t scheduler;
|
||||
static int server_sock = -1;
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
|
||||
@ -63,23 +62,26 @@ void configure_context(SSL_CTX *ctx)
|
||||
LOG("Cirpher suit used: %s", suit);
|
||||
if (SSL_CTX_set_cipher_list(ctx, suit) != 1)
|
||||
{
|
||||
ERROR("Fail to set ssl cirpher suit: %s", suit);
|
||||
ERR_print_errors_fp(stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* Set the key and cert */
|
||||
/* use the full chain bundle of certificate */
|
||||
//if (SSL_CTX_use_certificate_file(ctx, server_config->sslcert, SSL_FILETYPE_PEM) <= 0) {
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, config()->sslcert) <= 0) {
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, cnf->sslcert) <= 0) {
|
||||
ERROR("Fail to read SSL certificate chain file: %s", cnf->sslcert);
|
||||
ERR_print_errors_fp(stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, config()->sslkey, SSL_FILETYPE_PEM) <= 0 ) {
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, cnf->sslkey, SSL_FILETYPE_PEM) <= 0 ) {
|
||||
ERROR("Fail to read SSL private file: %s", cnf->sslkey);
|
||||
ERR_print_errors_fp(stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!SSL_CTX_check_private_key(ctx)) {
|
||||
ERROR("Failed to validate cert");
|
||||
ERROR("Failed to validate SSL certificate");
|
||||
ERR_print_errors_fp(stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -111,8 +113,6 @@ void stop_serve(int dummy) {
|
||||
// DEPRECATED: ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
#endif
|
||||
if(server_sock != -1)
|
||||
close(server_sock);
|
||||
destroy_config();
|
||||
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||
}
|
||||
@ -124,7 +124,6 @@ int main(int argc, char* argv[])
|
||||
load_config(CONFIG_FILE);
|
||||
else
|
||||
load_config(argv[1]);
|
||||
unsigned port = config()->port;
|
||||
int client_sock = -1;
|
||||
struct sockaddr_in client_name;
|
||||
socklen_t client_name_len = sizeof(client_name);
|
||||
@ -135,8 +134,10 @@ int main(int argc, char* argv[])
|
||||
signal(SIGABRT, SIG_IGN);
|
||||
signal(SIGINT, stop_serve);
|
||||
|
||||
config_t* conf = config();
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
if( config()->usessl == 1 )
|
||||
if( conf->enable_ssl == 1 )
|
||||
{
|
||||
init_openssl();
|
||||
ctx = create_context();
|
||||
@ -145,10 +146,36 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
#endif
|
||||
server_sock = startup(&port);
|
||||
LOG("httpd running on port %d", port);
|
||||
// startup port
|
||||
chain_t it;
|
||||
port_config_t * pcnf;
|
||||
int nlisten = 0;
|
||||
for_each_assoc(it, conf->ports)
|
||||
{
|
||||
pcnf = (port_config_t*)it->value;
|
||||
if(pcnf)
|
||||
{
|
||||
pcnf->sock = startup(&pcnf->port);
|
||||
if(pcnf->sock>0)
|
||||
{
|
||||
nlisten++;
|
||||
set_nonblock(pcnf->sock);
|
||||
LOG("Listening on port %d", pcnf->port);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR("Port %d is disabled", pcnf->port);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nlisten == 0)
|
||||
{
|
||||
ERROR("No port is listenned, quit!!");
|
||||
stop_serve(0);
|
||||
exit(1);
|
||||
}
|
||||
// default to 4 workers
|
||||
antd_scheduler_init(&scheduler, config()->n_workers);
|
||||
antd_scheduler_init(&scheduler, conf->n_workers);
|
||||
scheduler.validate_data = 1;
|
||||
scheduler.destroy_data = finish_request;
|
||||
// use blocking server_sock
|
||||
@ -169,69 +196,99 @@ int main(int argc, char* argv[])
|
||||
pthread_detach(scheduler_th);
|
||||
}
|
||||
antd_task_t* task = NULL;
|
||||
|
||||
fd_set read_flags, write_flags;
|
||||
// first verify if the socket is ready
|
||||
struct timeval timeout;
|
||||
// select
|
||||
|
||||
while (scheduler.status)
|
||||
{
|
||||
client_sock = accept(server_sock,(struct sockaddr *)&client_name,&client_name_len);
|
||||
if (client_sock == -1)
|
||||
if(conf->connection > conf->maxcon)
|
||||
{
|
||||
//ERROR("Reach max connection %d", conf->connection);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 5000; // 5 ms
|
||||
select(0, NULL, NULL, NULL, &timeout);
|
||||
continue;
|
||||
}
|
||||
// just dump the scheduler when we have a connection
|
||||
antd_client_t* client = (antd_client_t*)malloc(sizeof(antd_client_t));
|
||||
antd_request_t* request = (antd_request_t*)malloc(sizeof(*request));
|
||||
request->client = client;
|
||||
request->request = dict();
|
||||
/*
|
||||
get the remote IP
|
||||
*/
|
||||
client->ip = NULL;
|
||||
if (client_name.sin_family == AF_INET)
|
||||
for_each_assoc(it, conf->ports)
|
||||
{
|
||||
client_ip = inet_ntoa(client_name.sin_addr);
|
||||
client->ip = strdup(client_ip);
|
||||
LOG("Client IP: %s", client_ip);
|
||||
//LOG("socket: %d\n", client_sock);
|
||||
pcnf = (port_config_t*) it->value;
|
||||
if(pcnf->sock > 0)
|
||||
{
|
||||
FD_ZERO(&read_flags);
|
||||
FD_SET(pcnf->sock, &read_flags);
|
||||
FD_ZERO(&write_flags);
|
||||
FD_SET(pcnf->sock, &write_flags);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 5000; // 5 ms
|
||||
int sel = select(pcnf->sock + 1, &read_flags, &write_flags, (fd_set *)0, &timeout);
|
||||
if(sel > 0 && (FD_ISSET(pcnf->sock, &read_flags) || FD_ISSET(pcnf->sock, &write_flags)))
|
||||
{
|
||||
client_sock = accept(pcnf->sock,(struct sockaddr *)&client_name,&client_name_len);
|
||||
if (client_sock > 0)
|
||||
{
|
||||
// just dump the scheduler when we have a connection
|
||||
antd_client_t* client = (antd_client_t*)malloc(sizeof(antd_client_t));
|
||||
antd_request_t* request = (antd_request_t*)malloc(sizeof(*request));
|
||||
request->client = client;
|
||||
request->request = dict();
|
||||
client->port_config = pcnf;
|
||||
/*
|
||||
get the remote IP
|
||||
*/
|
||||
client->ip = NULL;
|
||||
if (client_name.sin_family == AF_INET)
|
||||
{
|
||||
client_ip = inet_ntoa(client_name.sin_addr);
|
||||
client->ip = strdup(client_ip);
|
||||
LOG("Connect to client IP: %s on port:%d", client_ip, pcnf->port);
|
||||
//LOG("socket: %d\n", client_sock);
|
||||
}
|
||||
|
||||
// set timeout to socket
|
||||
set_nonblock(client_sock);
|
||||
/*struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 5000;
|
||||
|
||||
if (setsockopt (client_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
|
||||
perror("setsockopt failed\n");
|
||||
|
||||
if (setsockopt (client_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
|
||||
perror("setsockopt failed\n");
|
||||
*/
|
||||
client->sock = client_sock;
|
||||
time(&client->last_io);
|
||||
#ifdef USE_OPENSSL
|
||||
client->ssl = NULL;
|
||||
client->status = 0;
|
||||
if(pcnf->usessl == 1)
|
||||
{
|
||||
client->ssl = (void*)SSL_new(ctx);
|
||||
if(!client->ssl) continue;
|
||||
SSL_set_fd((SSL*)client->ssl, client->sock);
|
||||
|
||||
/*if (SSL_accept((SSL*)client->ssl) <= 0) {
|
||||
LOG("EROOR accept\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
antd_close(client);
|
||||
continue;
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
conf->connection++;
|
||||
// create callback for the server
|
||||
task = antd_create_task(accept_request,(void*)request, finish_request, client->last_io);
|
||||
//task->type = LIGHT;
|
||||
antd_add_task(&scheduler, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set timeout to socket
|
||||
set_nonblock(client_sock);
|
||||
/*struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 5000;
|
||||
|
||||
if (setsockopt (client_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
|
||||
perror("setsockopt failed\n");
|
||||
|
||||
if (setsockopt (client_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,sizeof(timeout)) < 0)
|
||||
perror("setsockopt failed\n");
|
||||
*/
|
||||
client->sock = client_sock;
|
||||
time(&client->last_io);
|
||||
#ifdef USE_OPENSSL
|
||||
client->ssl = NULL;
|
||||
client->status = 0;
|
||||
if(config()->usessl == 1)
|
||||
{
|
||||
client->ssl = (void*)SSL_new(ctx);
|
||||
if(!client->ssl) continue;
|
||||
SSL_set_fd((SSL*)client->ssl, client->sock);
|
||||
|
||||
/*if (SSL_accept((SSL*)client->ssl) <= 0) {
|
||||
LOG("EROOR accept\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
antd_close(client);
|
||||
continue;
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
config()->connection++;
|
||||
// create callback for the server
|
||||
task = antd_create_task(accept_request,(void*)request, finish_request, client->last_io);
|
||||
//task->type = LIGHT;
|
||||
antd_add_task(&scheduler, task);
|
||||
}
|
||||
|
||||
close(server_sock);
|
||||
|
||||
stop_serve(0);
|
||||
return(0);
|
||||
}
|
||||
|
35
lib/handle.c
35
lib/handle.c
@ -1,6 +1,5 @@
|
||||
#include "handle.h"
|
||||
#define HTML_TPL "<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><h2>%s</h2></BODY></HTML>"
|
||||
#ifdef USE_OPENSSL
|
||||
|
||||
static const char* S_100 = "Continue";
|
||||
static const char* S_101 = "Switching Protocols";
|
||||
@ -70,24 +69,6 @@ static const char* S_510 = "Not Extended";
|
||||
static const char* S_511 = "Network Authentication Required";
|
||||
static const char* S_UNOF = "Unofficial Status";
|
||||
|
||||
int usessl()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void error_log(const char* fmt, ...)
|
||||
{
|
||||
UNUSED(fmt);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
void server_log(const char* fmt, ...)
|
||||
{
|
||||
UNUSED(fmt);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* get_status_str(int stat)
|
||||
{
|
||||
@ -210,7 +191,7 @@ int antd_send(void *src, const void* data, int len)
|
||||
int writelen = 0;
|
||||
int count;
|
||||
#ifdef USE_OPENSSL
|
||||
if(usessl())
|
||||
if(source->port_config->usessl)
|
||||
{
|
||||
//LOG("SSL WRITE\n");
|
||||
//ret = SSL_write((SSL*) source->ssl, data, len);
|
||||
@ -246,7 +227,7 @@ int antd_send(void *src, const void* data, int len)
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
{
|
||||
// peer disconnected...
|
||||
ERROR("SSLWRITE: SSL_ERROR_ZERO_RETURN: peer disconected: %d", source->sock);
|
||||
// ERROR("SSLWRITE: SSL_ERROR_ZERO_RETURN: peer disconected: %d", source->sock);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -324,7 +305,7 @@ int antd_send(void *src, const void* data, int len)
|
||||
{
|
||||
if(written == 0)
|
||||
written = count;
|
||||
//ERROR("Error while writing: %s", strerror(errno));
|
||||
ERROR("Error while writing: %s", strerror(errno));
|
||||
break;
|
||||
//return written;
|
||||
}
|
||||
@ -349,7 +330,7 @@ int antd_recv(void *src, void* data, int len)
|
||||
int readlen=0;
|
||||
antd_client_t * source = (antd_client_t *) src;
|
||||
#ifdef USE_OPENSSL
|
||||
if(usessl())
|
||||
if(source->port_config->usessl)
|
||||
{
|
||||
ptr = (char* )data;
|
||||
readlen = len > BUFFLEN?BUFFLEN:len;
|
||||
@ -435,7 +416,7 @@ int antd_recv(void *src, void* data, int len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(read = 0)
|
||||
if(read == 0)
|
||||
read = received;
|
||||
break;
|
||||
}
|
||||
@ -478,7 +459,7 @@ int antd_recv(void *src, void* data, int len)
|
||||
}
|
||||
else if(errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
ERROR("Error while writing: %s", strerror(errno));
|
||||
ERROR("Error while reading: %s", strerror(errno));
|
||||
if(read ==0)
|
||||
read = received;
|
||||
break;
|
||||
@ -515,7 +496,7 @@ int antd_close(void* src)
|
||||
if(!src) return -1;
|
||||
antd_client_t * source = (antd_client_t *) src;
|
||||
#ifdef USE_OPENSSL
|
||||
if(source->ssl && usessl()){
|
||||
if(source->port_config->usessl && source->ssl){
|
||||
//printf("SSL:Shutdown ssl\n");
|
||||
//SSL_shutdown((SSL*) source->ssl);
|
||||
SSL_set_shutdown((SSL*) source->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
|
||||
@ -727,7 +708,7 @@ void destroy_request(void *data)
|
||||
if (!data)
|
||||
return;
|
||||
antd_request_t *rq = (antd_request_t *)data;
|
||||
LOG("Close request %d", rq->client->sock);
|
||||
//LOG("Close request %d", rq->client->sock);
|
||||
// free all other thing
|
||||
if (rq->request)
|
||||
{
|
||||
|
32
lib/handle.h
32
lib/handle.h
@ -29,22 +29,26 @@
|
||||
#define FORM_URL_ENCODE "application/x-www-form-urlencoded"
|
||||
#define FORM_MULTI_PART "multipart/form-data"
|
||||
#define MAX_WAIT_S 2 // 1/3 minute
|
||||
#ifdef USE_OPENSSL
|
||||
int __attribute__((weak)) usessl();
|
||||
#endif
|
||||
void __attribute__((weak)) error_log(const char*, ...);
|
||||
#ifdef DEBUG
|
||||
void __attribute__((weak)) server_log(const char*, ...);
|
||||
#endif
|
||||
|
||||
//extern config_t server_config;
|
||||
|
||||
typedef struct {
|
||||
unsigned int port;
|
||||
int usessl;
|
||||
char* htdocs;
|
||||
int sock;
|
||||
} port_config_t;
|
||||
|
||||
typedef struct{
|
||||
int sock;
|
||||
void* ssl;
|
||||
char* ip;
|
||||
int port;
|
||||
//#ifdef USE_OPENSSL
|
||||
int status;
|
||||
//#endif
|
||||
time_t last_io;
|
||||
port_config_t* port_config;
|
||||
} antd_client_t;
|
||||
|
||||
typedef struct {
|
||||
@ -61,12 +65,13 @@ typedef struct
|
||||
} antd_response_header_t;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int port;
|
||||
//int port;
|
||||
char *plugins_dir;
|
||||
char *plugins_ext;
|
||||
char *db_path;
|
||||
char* htdocs;
|
||||
//char* htdocs;
|
||||
char* tmpdir;
|
||||
list_t rules;
|
||||
dictionary_t handlers;
|
||||
@ -79,24 +84,21 @@ typedef struct {
|
||||
FILE* logfp;
|
||||
// #endif
|
||||
// #ifdef USE_OPENSSL
|
||||
int usessl;
|
||||
int enable_ssl;
|
||||
char* sslcert;
|
||||
char* sslkey;
|
||||
char* ssl_cipher;
|
||||
dictionary_t mimes;
|
||||
dictionary_t ports;
|
||||
// #endif
|
||||
}config_t;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *dbpath;
|
||||
char * htdocs;
|
||||
char *tmpdir;
|
||||
char*pdir;
|
||||
int sport;
|
||||
int raw_body;
|
||||
//#ifdef USE_OPENSSL
|
||||
int usessl;
|
||||
//#endif
|
||||
} plugin_header_t;
|
||||
|
||||
void set_nonblock(int socket);
|
||||
|
@ -67,7 +67,7 @@ int ini_parse_file(FILE* file,
|
||||
|
||||
/* Maximum line length for any line in INI file. */
|
||||
#ifndef INI_MAX_LINE
|
||||
#define INI_MAX_LINE 200
|
||||
#define INI_MAX_LINE 512
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
30
lib/plugin.h
30
lib/plugin.h
@ -39,13 +39,9 @@ static plugin_header_t __plugin__;
|
||||
// private function
|
||||
void __init_plugin__(const char* pl,config_t* conf){
|
||||
__plugin__.name = strdup(pl);
|
||||
__plugin__.dbpath= strdup(conf->db_path);
|
||||
__plugin__.htdocs = strdup(conf->htdocs);
|
||||
__plugin__.pdir = strdup(conf->plugins_dir);
|
||||
__plugin__.sport = conf->port;
|
||||
#ifdef USE_OPENSSL
|
||||
__plugin__.usessl = conf->usessl;
|
||||
#endif
|
||||
__plugin__.dbpath= conf->db_path;
|
||||
__plugin__.pdir = conf->plugins_dir;
|
||||
__plugin__.tmpdir = = sconf->tmpdir;
|
||||
__plugin__.raw_body = 0;
|
||||
init();
|
||||
};
|
||||
@ -72,13 +68,6 @@ sqldb getdb()
|
||||
}
|
||||
#endif
|
||||
|
||||
/*#ifdef USE_OPENSSL
|
||||
int usessl()
|
||||
{
|
||||
LOG("CALLED from plugin \n");
|
||||
return __plugin__.usessl;
|
||||
}
|
||||
#endif*/
|
||||
plugin_header_t* meta()
|
||||
{
|
||||
return &__plugin__;
|
||||
@ -99,12 +88,9 @@ char* route(const char* repath)
|
||||
return path;
|
||||
}
|
||||
|
||||
char* htdocs(const char* repath)
|
||||
const char* tmpdir()
|
||||
{
|
||||
if(repath != NULL)
|
||||
return __s("%s/%s",__plugin__.htdocs,repath);
|
||||
else
|
||||
return __s("%s",__plugin__.htdocs);
|
||||
return (const char*) __plugin__.tmpdir;
|
||||
}
|
||||
|
||||
char* config_dir()
|
||||
@ -121,9 +107,9 @@ void __release__()
|
||||
destroy();
|
||||
LOG("Releasing plugin\n");
|
||||
if(__plugin__.name) free(__plugin__.name);
|
||||
if(__plugin__.dbpath) free(__plugin__.dbpath);
|
||||
if(__plugin__.htdocs) free(__plugin__.htdocs);
|
||||
if(__plugin__.pdir) free(__plugin__.pdir);
|
||||
//if(__plugin__.dbpath) free(__plugin__.dbpath);
|
||||
//if(__plugin__.htdocs) free(__plugin__.htdocs);
|
||||
//if(__plugin__.pdir) free(__plugin__.pdir);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -25,7 +25,8 @@ static void stop(antd_scheduler_t* scheduler)
|
||||
// unlock all idle workers if any
|
||||
for (int i = 0; i < scheduler->n_workers; i++)
|
||||
sem_post(scheduler->worker_sem);
|
||||
sem_post(scheduler->scheduler_sem);
|
||||
if(scheduler->scheduler_sem)
|
||||
sem_post(scheduler->scheduler_sem);
|
||||
for (int i = 0; i < scheduler->n_workers; i++)
|
||||
if(scheduler->workers[i].id != -1)
|
||||
pthread_join(scheduler->workers[i].tid, NULL);
|
||||
|
48
lib/utils.c
48
lib/utils.c
@ -23,6 +23,22 @@ THE SOFTWARE.
|
||||
*/
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
void error_log(const char* fmt, ...)
|
||||
{
|
||||
UNUSED(fmt);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
void server_log(const char* fmt, ...)
|
||||
{
|
||||
UNUSED(fmt);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Trim a string by a character on both ends
|
||||
* @param str The target string
|
||||
@ -197,8 +213,8 @@ int regex_match(const char* expr,const char* search, int msize, regmatch_t* matc
|
||||
if( reti ){
|
||||
//ERROR("Could not compile regex: %s",expr);
|
||||
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
|
||||
//ERROR("Regex match failed: %s", msgbuf);
|
||||
return 0;
|
||||
ERROR("Regex match failed: %s", msgbuf);
|
||||
//return 0;
|
||||
}
|
||||
|
||||
/* Execute regular expression */
|
||||
@ -457,4 +473,32 @@ char* __s(const char* fstring,...)
|
||||
return data;
|
||||
} else
|
||||
return "";
|
||||
}
|
||||
|
||||
int mkdirp(const char* path, mode_t mode)
|
||||
{
|
||||
char tmp[BUFFLEN];
|
||||
if(strlen(path) > BUFFLEN)
|
||||
{
|
||||
ERROR("mkdirp: Path is too long %s", path);
|
||||
return -1;
|
||||
}
|
||||
char *p = NULL;
|
||||
size_t len;
|
||||
int stat;
|
||||
snprintf(tmp, sizeof(tmp),"%s",path);
|
||||
len = strlen(tmp);
|
||||
if(tmp[len - 1] == '/')
|
||||
tmp[len - 1] = 0;
|
||||
for(p = tmp + 1; *p; p++)
|
||||
{
|
||||
if(*p == '/') {
|
||||
*p = 0;
|
||||
stat = mkdir(tmp, mode);
|
||||
if(stat == -1 && errno != EEXIST)
|
||||
return stat;
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
return mkdir(path, mode);
|
||||
}
|
11
lib/utils.h
11
lib/utils.h
@ -54,13 +54,14 @@ THE SOFTWARE.
|
||||
#define DIR_SEP "/"
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(a,...) server_log("[%s: %d]: " a "\n", __FILE__, \
|
||||
#define LOG(a,...) server_log("%s: [%s: %d]: " a "\n",server_time(), __FILE__, \
|
||||
__LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOG(a,...) do{}while(0)
|
||||
#endif
|
||||
#define ERROR(a,...) error_log("[%s: %d]: " a "\n", __FILE__, \
|
||||
#define ERROR(a,...) error_log("%s: [%s: %d]: " a "\n", server_time() , __FILE__, \
|
||||
__LINE__, ##__VA_ARGS__)
|
||||
// add this to the utils
|
||||
#define UNUSED(x) (void)(x)
|
||||
@ -73,6 +74,11 @@ typedef struct{
|
||||
const char* ext;
|
||||
} mime_t;
|
||||
|
||||
|
||||
void __attribute__((weak)) error_log(const char*, ...);
|
||||
#ifdef DEBUG
|
||||
void __attribute__((weak)) server_log(const char*, ...);
|
||||
#endif
|
||||
dictionary_t __attribute__((weak)) mimes_list();
|
||||
char* __s(const char*,...);
|
||||
void trim(char*,const char);
|
||||
@ -84,6 +90,7 @@ char* mime(const char*);
|
||||
int match_int(const char*);
|
||||
int match_float(const char*);
|
||||
int regex_match(const char*,const char*, int, regmatch_t*);
|
||||
int mkdirp(const char* path,mode_t mode);
|
||||
char *url_decode(const char *str);
|
||||
char *url_encode(const char *str);
|
||||
char from_hex(char ch);
|
||||
|
@ -113,7 +113,7 @@ void unload_plugin_by_name(const char* name)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (np ; np != NULL; np = np->next)
|
||||
for (np = plugin_table[hasval] ; np != NULL; np = np->next)
|
||||
{
|
||||
if (np->next != NULL && strcmp(name, np->next->pname) == 0)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user