mirror of
https://github.com/lxsang/ant-http
synced 2025-02-27 18:22:48 +01:00
feat: rework on plugin support
All checks were successful
gitea-sync/ant-http/pipeline/head This commit looks good
All checks were successful
gitea-sync/ant-http/pipeline/head This commit looks good
- New plugin interface that supports multiple instances - Fix and improve memory bugs - Refactory and cleanup lib - Improve scheduler
This commit is contained in:
parent
3bedc3ffb5
commit
58a7738afe
@ -22,7 +22,8 @@ libantd_la_SOURCES = lib/ini.c \
|
|||||||
lib/sha1.c \
|
lib/sha1.c \
|
||||||
lib/list.c \
|
lib/list.c \
|
||||||
lib/bst.c \
|
lib/bst.c \
|
||||||
lib/scheduler.c
|
lib/scheduler.c \
|
||||||
|
lib/plugin.c
|
||||||
|
|
||||||
pkginclude_HEADERS = lib/ini.h \
|
pkginclude_HEADERS = lib/ini.h \
|
||||||
lib/handle.h \
|
lib/handle.h \
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
plugins=/opt/www/lib/
|
plugins=/opt/www/lib/
|
||||||
; plugin extension
|
; plugin extension
|
||||||
plugins_ext=.so
|
plugins_ext=.so
|
||||||
; SQLITE database path
|
|
||||||
database=/opt/www/database/
|
|
||||||
; tmp dir
|
; tmp dir
|
||||||
tmpdir=/opt/www/tmp/
|
tmpdir=/opt/www/tmp/
|
||||||
; max concurent connection
|
; max concurent connection
|
||||||
|
44
config.c
44
config.c
@ -64,7 +64,7 @@ static void init_plugins()
|
|||||||
{
|
{
|
||||||
// load the plugin
|
// load the plugin
|
||||||
LOG("Plugin %s: auto loading...", it->key);
|
LOG("Plugin %s: auto loading...", it->key);
|
||||||
plugin_load(it->key, config);
|
UNUSED(antd_plugin_load(it->key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,23 +105,6 @@ static int config_handler(void *conf, const char *section, const char *name,
|
|||||||
free(pconfig->plugins_ext);
|
free(pconfig->plugins_ext);
|
||||||
pconfig->plugins_ext = strdup(value);
|
pconfig->plugins_ext = strdup(value);
|
||||||
}
|
}
|
||||||
else if (MATCH("SERVER", "database"))
|
|
||||||
{
|
|
||||||
if (stat(value, &st) == -1)
|
|
||||||
mkdirp(value, 0700);
|
|
||||||
tmp = realpath(value, NULL);
|
|
||||||
if (!tmp)
|
|
||||||
{
|
|
||||||
ERROR("Unable to query real path for %s: %s", value, strerror(errno));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pconfig->db_path)
|
|
||||||
free(pconfig->db_path);
|
|
||||||
pconfig->db_path = tmp;
|
|
||||||
LOG("Database root is %s", pconfig->db_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (MATCH("SERVER", "tmpdir"))
|
else if (MATCH("SERVER", "tmpdir"))
|
||||||
{
|
{
|
||||||
if (stat(value, &st) == -1)
|
if (stat(value, &st) == -1)
|
||||||
@ -341,6 +324,13 @@ void load_config(const char *file)
|
|||||||
LOG("SSL Cipher suite: %s", g_server_config.ssl_cipher);*/
|
LOG("SSL Cipher suite: %s", g_server_config.ssl_cipher);*/
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
set_mimes_list(g_server_config.mimes);
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
if(g_server_config.gzip_enable && g_server_config.gzip_types != NULL)
|
||||||
|
{
|
||||||
|
set_gzip_types(g_server_config.gzip_types);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
LOG("%d mimes entries found", g_server_config.mimes->size);
|
LOG("%d mimes entries found", g_server_config.mimes->size);
|
||||||
// Init plugins if necessary
|
// Init plugins if necessary
|
||||||
init_plugins();
|
init_plugins();
|
||||||
@ -361,9 +351,17 @@ void destroy_config()
|
|||||||
if (g_server_config.ssl_cipher)
|
if (g_server_config.ssl_cipher)
|
||||||
free(g_server_config.ssl_cipher);
|
free(g_server_config.ssl_cipher);
|
||||||
if (g_server_config.gzip_types)
|
if (g_server_config.gzip_types)
|
||||||
|
{
|
||||||
list_free(&g_server_config.gzip_types);
|
list_free(&g_server_config.gzip_types);
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
set_gzip_types(g_server_config.gzip_types);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if (g_server_config.mimes)
|
if (g_server_config.mimes)
|
||||||
|
{
|
||||||
freedict(g_server_config.mimes);
|
freedict(g_server_config.mimes);
|
||||||
|
set_mimes_list(NULL);
|
||||||
|
}
|
||||||
if (g_server_config.stat_fifo_path)
|
if (g_server_config.stat_fifo_path)
|
||||||
free(g_server_config.stat_fifo_path);
|
free(g_server_config.stat_fifo_path);
|
||||||
if (g_server_config.plugins)
|
if (g_server_config.plugins)
|
||||||
@ -371,9 +369,18 @@ void destroy_config()
|
|||||||
for_each_assoc(it, g_server_config.plugins)
|
for_each_assoc(it, g_server_config.plugins)
|
||||||
{
|
{
|
||||||
freedict((dictionary_t)it->value);
|
freedict((dictionary_t)it->value);
|
||||||
|
it->value = NULL;
|
||||||
}
|
}
|
||||||
freedict(g_server_config.plugins);
|
freedict(g_server_config.plugins);
|
||||||
}
|
}
|
||||||
|
if(g_server_config.sslcert)
|
||||||
|
{
|
||||||
|
free(g_server_config.sslcert);
|
||||||
|
}
|
||||||
|
if(g_server_config.sslkey)
|
||||||
|
{
|
||||||
|
free(g_server_config.sslkey);
|
||||||
|
}
|
||||||
if (g_server_config.ports)
|
if (g_server_config.ports)
|
||||||
{
|
{
|
||||||
port_config_t *cnf;
|
port_config_t *cnf;
|
||||||
@ -396,4 +403,5 @@ void destroy_config()
|
|||||||
freedict(g_server_config.ports);
|
freedict(g_server_config.ports);
|
||||||
}
|
}
|
||||||
LOG("Unclosed connection: %d", g_server_config.connection);
|
LOG("Unclosed connection: %d", g_server_config.connection);
|
||||||
|
LOG("Config destroyed");
|
||||||
}
|
}
|
4
decode.c
4
decode.c
@ -254,6 +254,7 @@ static void *check_proxy(antd_request_t *rq, const char *path, const char *query
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
|
free(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +368,7 @@ void *decode_request_header(void *data)
|
|||||||
dictionary_t request = dvalue(rq->request, "REQUEST_DATA");
|
dictionary_t request = dvalue(rq->request, "REQUEST_DATA");
|
||||||
char *port_s = (char *)dvalue(rq->request, "SERVER_PORT");
|
char *port_s = (char *)dvalue(rq->request, "SERVER_PORT");
|
||||||
port_config_t *pcnf = (port_config_t *)dvalue(g_server_config.ports, port_s);
|
port_config_t *pcnf = (port_config_t *)dvalue(g_server_config.ports, port_s);
|
||||||
antd_task_t *task;
|
antd_task_t *task = NULL;
|
||||||
// first real all header
|
// first real all header
|
||||||
// this for check if web socket is enabled
|
// this for check if web socket is enabled
|
||||||
|
|
||||||
@ -757,7 +758,6 @@ void *decode_post_request(void *data)
|
|||||||
{
|
{
|
||||||
// WARN: this may not work on ssl socket
|
// WARN: this may not work on ssl socket
|
||||||
// antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_READABLE | TASK_EVT_ON_WRITABLE);
|
// antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_READABLE | TASK_EVT_ON_WRITABLE);
|
||||||
// task->handle = decode_post_request;
|
|
||||||
antd_error(rq->client, 400, "Bad Request, missing content data");
|
antd_error(rq->client, 400, "Bad Request, missing content data");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
16
httpd.c
16
httpd.c
@ -140,7 +140,6 @@ static void configure_context(SSL_CTX *ctx)
|
|||||||
|
|
||||||
static void stop_serve(int dummy)
|
static void stop_serve(int dummy)
|
||||||
{
|
{
|
||||||
UNUSED(dummy);
|
|
||||||
// close log server
|
// close log server
|
||||||
closelog();
|
closelog();
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
@ -151,7 +150,7 @@ static void stop_serve(int dummy)
|
|||||||
sigaddset(&mask, SIGABRT);
|
sigaddset(&mask, SIGABRT);
|
||||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||||
antd_scheduler_destroy(scheduler);
|
antd_scheduler_destroy(scheduler);
|
||||||
unload_all_plugin();
|
antd_unload_all_plugin();
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
// DEPRECATED FIPS_mode_set(0);
|
// DEPRECATED FIPS_mode_set(0);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
@ -165,6 +164,7 @@ static void stop_serve(int dummy)
|
|||||||
#endif
|
#endif
|
||||||
destroy_config();
|
destroy_config();
|
||||||
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||||
|
exit(dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void antd_monitor(port_config_t *pcnf, int sock)
|
static void antd_monitor(port_config_t *pcnf, int sock)
|
||||||
@ -182,6 +182,7 @@ static void antd_monitor(port_config_t *pcnf, int sock)
|
|||||||
// just dump the scheduler when we have a connection
|
// just dump the scheduler when we have a connection
|
||||||
antd_client_t *client = (antd_client_t *)malloc(sizeof(antd_client_t));
|
antd_client_t *client = (antd_client_t *)malloc(sizeof(antd_client_t));
|
||||||
antd_request_t *request = (antd_request_t *)malloc(sizeof(*request));
|
antd_request_t *request = (antd_request_t *)malloc(sizeof(*request));
|
||||||
|
request->context = NULL;
|
||||||
request->client = client;
|
request->client = client;
|
||||||
request->request = dict();
|
request->request = dict();
|
||||||
client->zstream = NULL;
|
client->zstream = NULL;
|
||||||
@ -378,8 +379,7 @@ int main(int argc, char *argv[])
|
|||||||
if (scheduler == NULL)
|
if (scheduler == NULL)
|
||||||
{
|
{
|
||||||
ERROR("Unable to initialise scheduler. Exit");
|
ERROR("Unable to initialise scheduler. Exit");
|
||||||
stop_serve(0);
|
stop_serve(1);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
FD_ZERO(&master_set);
|
FD_ZERO(&master_set);
|
||||||
for_each_assoc(it, g_server_config.ports)
|
for_each_assoc(it, g_server_config.ports)
|
||||||
@ -411,15 +411,13 @@ int main(int argc, char *argv[])
|
|||||||
if (nlisten == 0)
|
if (nlisten == 0)
|
||||||
{
|
{
|
||||||
ERROR("No port is listened, quit!!");
|
ERROR("No port is listened, quit!!");
|
||||||
stop_serve(0);
|
stop_serve(1);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
// Start scheduler
|
// Start scheduler
|
||||||
if (pthread_create(&sched_th, NULL, (void *(*)(void *))antd_scheduler_wait, (void *)scheduler) != 0)
|
if (pthread_create(&sched_th, NULL, (void *(*)(void *))antd_scheduler_wait, (void *)scheduler) != 0)
|
||||||
{
|
{
|
||||||
ERROR("pthread_create: cannot start scheduler thread");
|
ERROR("pthread_create: cannot start scheduler thread");
|
||||||
stop_serve(0);
|
stop_serve(1);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -460,5 +458,5 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop_serve(0);
|
stop_serve(0);
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,7 @@ void free_association(chain_t *asoc)
|
|||||||
|
|
||||||
if (a->key)
|
if (a->key)
|
||||||
{
|
{
|
||||||
|
//printf("Free key %s\n", a->key);
|
||||||
free(a->key);
|
free(a->key);
|
||||||
if (a->value)
|
if (a->value)
|
||||||
free(a->value);
|
free(a->value);
|
||||||
|
22
lib/handle.c
22
lib/handle.c
@ -100,11 +100,31 @@ int require_plugin(const char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
static list_t g_gzip_types = NULL;
|
||||||
|
void set_gzip_types(list_t list)
|
||||||
|
{
|
||||||
|
g_gzip_types = list;
|
||||||
|
}
|
||||||
int compressable(char *ctype)
|
int compressable(char *ctype)
|
||||||
{
|
{
|
||||||
UNUSED(ctype);
|
if (g_gzip_types == NULL)
|
||||||
|
return 0;
|
||||||
|
item_t it;
|
||||||
|
list_for_each(it, g_gzip_types)
|
||||||
|
{
|
||||||
|
if(it->type == LIST_TYPE_POINTER && it->value.ptr)
|
||||||
|
{
|
||||||
|
//LOG("Checking content type %s against GZIP support %s", ctype,(const char *)it->value.ptr);
|
||||||
|
if (regex_match((const char *)it->value.ptr, ctype, 0, NULL))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *get_status_str(int stat)
|
const char *get_status_str(int stat)
|
||||||
{
|
{
|
||||||
|
24
lib/handle.h
24
lib/handle.h
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
#define SERVER_NAME "Antd"
|
#define SERVER_NAME "Antd"
|
||||||
#define IS_POST(method) (strcmp(method, "POST") == 0)
|
#define IS_POST(method) (strcmp(method, "POST") == 0)
|
||||||
@ -28,9 +29,6 @@
|
|||||||
#define ANTD_CLIENT_RQ_DATA_DECODE 0x7
|
#define ANTD_CLIENT_RQ_DATA_DECODE 0x7
|
||||||
#define ANTD_CLIENT_PROXY_MONITOR 0x8
|
#define ANTD_CLIENT_PROXY_MONITOR 0x8
|
||||||
|
|
||||||
#define ANTD_PLUGIN_READY 0x0
|
|
||||||
#define ANTD_PLUGIN_PANNIC 0x1
|
|
||||||
#define ANTD_PLUGIN_INIT 0x2
|
|
||||||
#define MAX_PATH_LEN 256
|
#define MAX_PATH_LEN 256
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -63,6 +61,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
antd_client_t *client;
|
antd_client_t *client;
|
||||||
dictionary_t request;
|
dictionary_t request;
|
||||||
|
antd_plugin_ctx_t * context;
|
||||||
} antd_request_t;
|
} antd_request_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -73,23 +72,12 @@ typedef struct
|
|||||||
|
|
||||||
} antd_response_header_t;
|
} antd_response_header_t;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[MAX_PATH_LEN];
|
|
||||||
char dbpath[MAX_PATH_LEN];
|
|
||||||
char tmpdir[MAX_PATH_LEN];
|
|
||||||
char pdir[MAX_PATH_LEN];
|
|
||||||
dictionary_t config;
|
|
||||||
int raw_body;
|
|
||||||
int status;
|
|
||||||
void *instance_data;
|
|
||||||
} plugin_header_t;
|
|
||||||
|
|
||||||
void set_nonblock(int socket);
|
void set_nonblock(int socket);
|
||||||
//void set_block(int socket);
|
//void set_block(int socket);
|
||||||
|
#ifdef USE_ZLIB
|
||||||
int __attribute__((weak)) compressable(char *ctype);
|
int compressable(char *ctype);
|
||||||
|
void set_gzip_types(list_t list);
|
||||||
|
#endif
|
||||||
void antd_send_header(void *, antd_response_header_t *);
|
void antd_send_header(void *, antd_response_header_t *);
|
||||||
const char *get_status_str(int stat);
|
const char *get_status_str(int stat);
|
||||||
int __t(void *, const char *, ...);
|
int __t(void *, const char *, ...);
|
||||||
|
51
lib/plugin.c
Normal file
51
lib/plugin.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "plugin_ctx.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char * antd_plugin_basedir(antd_plugin_ctx_t * ctx)
|
||||||
|
{
|
||||||
|
return ctx->basedir;
|
||||||
|
}
|
||||||
|
const char * antd_plugin_tmpdir(antd_plugin_ctx_t * ctx)
|
||||||
|
{
|
||||||
|
return ctx->tmpdir;
|
||||||
|
}
|
||||||
|
const char * antd_plugin_confdir(antd_plugin_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
if(ctx->confdir == NULL)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
ctx->confdir = __s("%s%s%s", ctx->basedir,DIR_SEP, ctx->name);
|
||||||
|
if (stat(ctx->confdir, &st) == -1)
|
||||||
|
mkdir(ctx->confdir, 0755);
|
||||||
|
}
|
||||||
|
return ctx->confdir;
|
||||||
|
}
|
||||||
|
const char * antd_plugin_name(antd_plugin_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
return ctx->name;
|
||||||
|
}
|
||||||
|
void antd_plugin_set_status(antd_plugin_ctx_t * ctx, int stat)
|
||||||
|
{
|
||||||
|
ctx->status = stat;
|
||||||
|
}
|
||||||
|
int antd_plugin_status(antd_plugin_ctx_t * ctx)
|
||||||
|
{
|
||||||
|
return ctx->status;
|
||||||
|
}
|
||||||
|
void antd_plugin_use_raw_body(antd_plugin_ctx_t * ctx)
|
||||||
|
{
|
||||||
|
ctx->raw_body = 1;
|
||||||
|
}
|
||||||
|
int antd_plugin_is_raw_body(antd_plugin_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
return ctx->raw_body == 1;
|
||||||
|
}
|
||||||
|
void* antd_plugin_data(antd_plugin_ctx_t* ctx)
|
||||||
|
{
|
||||||
|
return ctx->data;
|
||||||
|
}
|
||||||
|
dictionary_t antd_plugin_config(antd_plugin_ctx_t* ctx)
|
||||||
|
{
|
||||||
|
return ctx->config;
|
||||||
|
}
|
78
lib/plugin.h
78
lib/plugin.h
@ -1,61 +1,41 @@
|
|||||||
#ifndef PLUGIN_H
|
#ifndef PLUGIN_H
|
||||||
#define PLUGIN_H
|
#define PLUGIN_H
|
||||||
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define ANTD_PLUGIN_READY 0x0
|
||||||
|
#define ANTD_PLUGIN_PANNIC 0x1
|
||||||
|
#define ANTD_PLUGIN_INIT 0x2
|
||||||
|
|
||||||
|
#define PLUGIN_INIT "create"
|
||||||
|
#define PLUGIN_HANDLE "handle"
|
||||||
|
#define PLUGIN_DROP "drop"
|
||||||
|
|
||||||
|
#define DEF_PLUGIN_INTERFACE(name, param, ret) ret##name(param)
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "handle.h"
|
#include "dictionary.h"
|
||||||
|
|
||||||
|
#define PLUGIN_PANIC(ctx, a, ...) \
|
||||||
|
ERROR("%s: " a, antd_plugin_name(ctx), ##__VA_ARGS__); \
|
||||||
|
antd_plugin_set_status(ctx, ANTD_PLUGIN_PANNIC);
|
||||||
|
|
||||||
|
typedef struct _plugin_ctx_t antd_plugin_ctx_t;
|
||||||
|
|
||||||
char* config_dir();
|
const char *antd_plugin_basedir(antd_plugin_ctx_t *);
|
||||||
/*Default function for plugin*/
|
const char *antd_plugin_tmpdir(antd_plugin_ctx_t *);
|
||||||
// init the plugin
|
const char *antd_plugin_confdir(antd_plugin_ctx_t *);
|
||||||
void init();
|
const char *antd_plugin_name(antd_plugin_ctx_t *);
|
||||||
void destroy();
|
void antd_plugin_set_status(antd_plugin_ctx_t *, int);
|
||||||
|
int antd_plugin_status(antd_plugin_ctx_t *);
|
||||||
|
void antd_plugin_use_raw_body(antd_plugin_ctx_t *);
|
||||||
|
int antd_plugin_is_raw_body(antd_plugin_ctx_t *);
|
||||||
|
void *antd_plugin_data(antd_plugin_ctx_t *);
|
||||||
|
dictionary_t antd_plugin_config(antd_plugin_ctx_t*);
|
||||||
|
|
||||||
|
/*Default interfaces shall be implemented by plugin*/
|
||||||
|
void *create(antd_plugin_ctx_t *);
|
||||||
|
void drop(antd_plugin_ctx_t *);
|
||||||
void *handle(void *);
|
void *handle(void *);
|
||||||
plugin_header_t* meta();
|
|
||||||
void use_raw_body();
|
|
||||||
|
|
||||||
/*
|
|
||||||
STATIC PART, should be included in any plugin
|
|
||||||
*/
|
|
||||||
#ifdef PLUGIN_IMPLEMENT
|
|
||||||
|
|
||||||
#define PLUGIN_PANIC(a,...) \
|
|
||||||
ERROR("%s: "a,__plugin__.name, ##__VA_ARGS__); \
|
|
||||||
__plugin__.status = ANTD_PLUGIN_PANNIC;
|
|
||||||
|
|
||||||
static plugin_header_t __plugin__;
|
|
||||||
// private function
|
|
||||||
void __init_plugin__(plugin_header_t* pl, dictionary_t* conf){
|
|
||||||
(void) memcpy(&__plugin__, pl, sizeof(plugin_header_t));
|
|
||||||
__plugin__.status = ANTD_PLUGIN_READY;
|
|
||||||
init();
|
|
||||||
};
|
|
||||||
void use_raw_body()
|
|
||||||
{
|
|
||||||
__plugin__.raw_body = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin_header_t* meta()
|
|
||||||
{
|
|
||||||
return &__plugin__;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* config_dir()
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
char* path = __s("%s%s%s", __plugin__.pdir,DIR_SEP, __plugin__.name);
|
|
||||||
if (stat(path, &st) == -1)
|
|
||||||
mkdir(path, 0755);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __release__()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
18
lib/plugin_ctx.h
Normal file
18
lib/plugin_ctx.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef PLUGIN_CTX_H
|
||||||
|
#define PLUGIN_CTX_H
|
||||||
|
#include "handle.h"
|
||||||
|
struct _plugin_ctx_t
|
||||||
|
{
|
||||||
|
char * name;
|
||||||
|
const char * tmpdir;
|
||||||
|
const char * basedir;
|
||||||
|
char * confdir;
|
||||||
|
int raw_body;
|
||||||
|
int status;
|
||||||
|
dictionary_t config;
|
||||||
|
void * data;
|
||||||
|
void *(*handle)(void *);
|
||||||
|
void *(*create)(struct _plugin_ctx_t *);
|
||||||
|
void (*drop)(struct _plugin_ctx_t *);
|
||||||
|
} ;
|
||||||
|
#endif
|
@ -533,7 +533,7 @@ void antd_scheduler_destroy(antd_scheduler_t *scheduler)
|
|||||||
*/
|
*/
|
||||||
antd_task_t *antd_create_task(void *(*handle)(void *), void *data, void *(*callback)(void *), time_t atime)
|
antd_task_t *antd_create_task(void *(*handle)(void *), void *data, void *(*callback)(void *), time_t atime)
|
||||||
{
|
{
|
||||||
antd_task_t *task = (antd_task_t *)malloc(sizeof *task);
|
antd_task_t *task = (antd_task_t *)malloc(sizeof(antd_task_t));
|
||||||
task->stamp = (unsigned long)time(NULL);
|
task->stamp = (unsigned long)time(NULL);
|
||||||
task->data = data;
|
task->data = data;
|
||||||
task->handle = handle;
|
task->handle = handle;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#ifndef ANT_SCHEDULER
|
#ifndef ANT_SCHEDULER
|
||||||
#define ANT_SCHEDULER
|
#define ANT_SCHEDULER
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <semaphore.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
10
lib/utils.c
10
lib/utils.c
@ -46,6 +46,8 @@ THE SOFTWARE.
|
|||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
// #include <time.h>
|
// #include <time.h>
|
||||||
|
|
||||||
|
static dictionary_t g_mime_list = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trim a string by a character on both ends
|
* Trim a string by a character on both ends
|
||||||
* @param str The target string
|
* @param str The target string
|
||||||
@ -184,8 +186,14 @@ void verify_header(char *k)
|
|||||||
|
|
||||||
dictionary_t mimes_list()
|
dictionary_t mimes_list()
|
||||||
{
|
{
|
||||||
return NULL;
|
return g_mime_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_mimes_list(dictionary_t dict)
|
||||||
|
{
|
||||||
|
g_mime_list = dict;
|
||||||
|
}
|
||||||
|
|
||||||
/*get mime file info from type*/
|
/*get mime file info from type*/
|
||||||
mime_t mime_from_type(const char *type)
|
mime_t mime_from_type(const char *type)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
|
|
||||||
|
#define STRINGIFY(x) #x
|
||||||
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
||||||
#define EQU(a,b) (strcmp(a,b) == 0)
|
#define EQU(a,b) (strcmp(a,b) == 0)
|
||||||
#define IEQU(a,b) (strcasecmp(a,b) == 0)
|
#define IEQU(a,b) (strcasecmp(a,b) == 0)
|
||||||
@ -65,7 +66,8 @@ typedef union
|
|||||||
struct sockaddr_in addr4;
|
struct sockaddr_in addr4;
|
||||||
} antd_sockaddr_t;
|
} antd_sockaddr_t;
|
||||||
|
|
||||||
dictionary_t __attribute__((weak)) mimes_list();
|
dictionary_t mimes_list();
|
||||||
|
void set_mimes_list(dictionary_t);
|
||||||
char* __s(const char*,...);
|
char* __s(const char*,...);
|
||||||
void trim(char*,const char);
|
void trim(char*,const char);
|
||||||
void removeAll(const char* path,int mode);
|
void removeAll(const char* path,int mode);
|
||||||
|
335
plugin_manager.c
335
plugin_manager.c
@ -5,16 +5,21 @@
|
|||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "plugin_manager.h"
|
|
||||||
#include "lib/utils.h"
|
#include "lib/utils.h"
|
||||||
#include "lib/handle.h"
|
#include "lib/handle.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "lib/plugin_ctx.h"
|
||||||
|
#include "plugin_manager.h"
|
||||||
|
|
||||||
|
struct plugin_entry {
|
||||||
|
struct plugin_entry *next;
|
||||||
|
char *name;
|
||||||
|
void *handle;
|
||||||
|
dictionary_t instances;
|
||||||
|
};
|
||||||
|
|
||||||
extern config_t g_server_config;
|
extern config_t g_server_config;
|
||||||
|
|
||||||
static void unload_plugin_by_name(const char *);
|
|
||||||
static void *plugin_from_file(char *name, char *path, dictionary_t conf);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin table to store the loaded plugin
|
* Plugin table to store the loaded plugin
|
||||||
*/
|
*/
|
||||||
@ -25,8 +30,12 @@ static struct plugin_entry *plugin_table[HASHSIZE];
|
|||||||
* @param s plugin name
|
* @param s plugin name
|
||||||
* @return a plugin entry in the plugin table
|
* @return a plugin entry in the plugin table
|
||||||
*/
|
*/
|
||||||
struct plugin_entry *plugin_lookup(char *s)
|
static struct plugin_entry *plugin_lookup(const char *s)
|
||||||
{
|
{
|
||||||
|
if(!s)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
struct plugin_entry *np;
|
struct plugin_entry *np;
|
||||||
for (np = plugin_table[hash(s, HASHSIZE)]; np != NULL; np = np->next)
|
for (np = plugin_table[hash(s, HASHSIZE)]; np != NULL; np = np->next)
|
||||||
if (strcmp(s, np->name) == 0)
|
if (strcmp(s, np->name) == 0)
|
||||||
@ -34,6 +43,136 @@ struct plugin_entry *plugin_lookup(char *s)
|
|||||||
return NULL; /* not found */
|
return NULL; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void antd_plugin_ctx_drop(struct plugin_entry* np, antd_plugin_ctx_t* ctx)
|
||||||
|
{
|
||||||
|
if(!ctx)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ctx->drop)
|
||||||
|
{
|
||||||
|
if(ctx->name)
|
||||||
|
LOG("Release user resource for context: %s", ctx->name);
|
||||||
|
ctx->drop((void*)ctx);
|
||||||
|
}
|
||||||
|
if(ctx->name)
|
||||||
|
{
|
||||||
|
LOG("Dropping plugin context: %s", ctx->name);
|
||||||
|
if(np->instances)
|
||||||
|
{
|
||||||
|
dput(np->instances, ctx->name, NULL);
|
||||||
|
}
|
||||||
|
free(ctx->name);
|
||||||
|
}
|
||||||
|
if(ctx->confdir)
|
||||||
|
{
|
||||||
|
free(ctx->confdir);
|
||||||
|
}
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static antd_plugin_ctx_t* antd_plugin_ctx_lookup(struct plugin_entry* np, const char* name)
|
||||||
|
{
|
||||||
|
if(!np || !np->instances)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
LOG("Looking for plugin context: %s", name);
|
||||||
|
antd_plugin_ctx_t* ctx = dvalue(np->instances, name);
|
||||||
|
if(ctx == NULL)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
LOG("Create new plugin context: %s", name);
|
||||||
|
ctx = (antd_plugin_ctx_t *)malloc(sizeof(antd_plugin_ctx_t));
|
||||||
|
if(!ctx)
|
||||||
|
{
|
||||||
|
ERROR("Unable to allocate memory for plugin context `%s`: %s", name, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// init the context
|
||||||
|
ctx->basedir = g_server_config.plugins_dir;
|
||||||
|
ctx->tmpdir = g_server_config.tmpdir;
|
||||||
|
ctx->name = strdup(name);
|
||||||
|
ctx->confdir = NULL;
|
||||||
|
ctx->raw_body = 0;
|
||||||
|
ctx->status = ANTD_PLUGIN_INIT;
|
||||||
|
ctx->config=dvalue(g_server_config.plugins, name);
|
||||||
|
ctx->data = NULL;
|
||||||
|
ctx->handle = NULL;
|
||||||
|
ctx->create = NULL;
|
||||||
|
ctx->drop = NULL;
|
||||||
|
// look for handle function
|
||||||
|
ctx->handle = (void* (*)(void *))dlsym(np->handle, PLUGIN_HANDLE);
|
||||||
|
if ((error = dlerror()) != NULL)
|
||||||
|
{
|
||||||
|
ERROR("Problem when finding plugin handle function for %s : %s", name, error);
|
||||||
|
ctx->handle = NULL;
|
||||||
|
antd_plugin_ctx_drop(np, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// look for drop function
|
||||||
|
ctx->drop = (void (*)(antd_plugin_ctx_t *))dlsym(np->handle, PLUGIN_DROP);
|
||||||
|
if ((error = dlerror()) != NULL)
|
||||||
|
{
|
||||||
|
ERROR("Problem when finding plugin drop function for %s : %s", name, error);
|
||||||
|
ctx->drop = NULL;
|
||||||
|
antd_plugin_ctx_drop(np, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// look for init function
|
||||||
|
ctx->create = (void* (*)(antd_plugin_ctx_t *))dlsym(np->handle, PLUGIN_INIT);
|
||||||
|
if ((error = dlerror()) != NULL)
|
||||||
|
{
|
||||||
|
ERROR("Problem when finding plugin init function for %s : %s.", name, error);
|
||||||
|
ctx->create = NULL;
|
||||||
|
antd_plugin_ctx_drop(np, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// run the init function
|
||||||
|
ctx->data = ctx->create(ctx);
|
||||||
|
if(ctx->status == ANTD_PLUGIN_PANNIC)
|
||||||
|
{
|
||||||
|
ERROR("PANIC happens when init plugin context %s. drop it", name);
|
||||||
|
antd_plugin_ctx_drop(np, ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctx->status = ANTD_PLUGIN_READY;
|
||||||
|
}
|
||||||
|
dput(np->instances, name, (void*)ctx);
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void antd_plugin_entry_drop(struct plugin_entry* np)
|
||||||
|
{
|
||||||
|
if(!np)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(np->name)
|
||||||
|
{
|
||||||
|
LOG("Unloaded %s", np->name);
|
||||||
|
free(np->name);
|
||||||
|
}
|
||||||
|
if(np->instances)
|
||||||
|
{
|
||||||
|
chain_t it;
|
||||||
|
for_each_assoc(it, np->instances)
|
||||||
|
{
|
||||||
|
antd_plugin_ctx_drop(np,(antd_plugin_ctx_t*)it->value);
|
||||||
|
}
|
||||||
|
freedict(np->instances);
|
||||||
|
}
|
||||||
|
if(np->handle)
|
||||||
|
{
|
||||||
|
dlclose(np->handle);
|
||||||
|
}
|
||||||
|
free(np);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a plugin to the plugin table
|
* Load a plugin to the plugin table
|
||||||
* Only load when not available in the plugin table
|
* Only load when not available in the plugin table
|
||||||
@ -41,170 +180,76 @@ struct plugin_entry *plugin_lookup(char *s)
|
|||||||
* @param config: plugin configuration
|
* @param config: plugin configuration
|
||||||
* @return pointer to the loaded plugin
|
* @return pointer to the loaded plugin
|
||||||
*/
|
*/
|
||||||
struct plugin_entry *plugin_load(char *name, dictionary_t pconf)
|
antd_plugin_ctx_t* antd_plugin_load(const char *name)
|
||||||
{
|
{
|
||||||
char *pname = NULL;
|
const char *plugin_file_name = NULL;
|
||||||
char path[BUFFLEN];
|
char path[BUFFLEN];
|
||||||
struct plugin_entry *np;
|
struct plugin_entry *np;
|
||||||
unsigned hashval;
|
unsigned hashval;
|
||||||
plugin_header_t *(*metafn)();
|
antd_plugin_ctx_t *ctx;
|
||||||
plugin_header_t *meta = NULL;
|
dictionary_t pconf = dvalue(g_server_config.plugins, name);
|
||||||
int fromfd, tofd;
|
|
||||||
char *error;
|
|
||||||
struct stat st;
|
|
||||||
int is_tmp = 0;
|
|
||||||
if (pconf)
|
if (pconf)
|
||||||
{
|
{
|
||||||
pname = dvalue(pconf, "name");
|
plugin_file_name = dvalue(pconf, "name");
|
||||||
}
|
}
|
||||||
if ((np = plugin_lookup(name)) == NULL)
|
if(plugin_file_name == NULL)
|
||||||
|
{
|
||||||
|
plugin_file_name = name;
|
||||||
|
}
|
||||||
|
if(plugin_file_name == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((np = plugin_lookup(plugin_file_name)) == NULL)
|
||||||
{ /* not found */
|
{ /* not found */
|
||||||
LOG("Loading plugin: %s...", name);
|
LOG("Loading plugin: %s...", plugin_file_name);
|
||||||
np = (struct plugin_entry *)malloc(sizeof(*np));
|
np = (struct plugin_entry *)malloc(sizeof(struct plugin_entry));
|
||||||
if (np == NULL || name == NULL)
|
np->instances = NULL;
|
||||||
|
if (np == NULL)
|
||||||
{
|
{
|
||||||
if (np)
|
|
||||||
free(np);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.plugins_dir, name, g_server_config.plugins_ext);
|
(void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.plugins_dir, plugin_file_name, g_server_config.plugins_ext);
|
||||||
if (pname && strcmp(name, pname) != 0)
|
np->name = strdup(plugin_file_name);
|
||||||
|
// now load it from file
|
||||||
|
np->handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL /*| RTLD_NODELETE*/);
|
||||||
|
if (!np->handle)
|
||||||
{
|
{
|
||||||
// copy plugin file to tmpdir
|
ERROR("Cannot load plugin '%s' : '%s'", plugin_file_name, dlerror());
|
||||||
(void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.plugins_dir, pname, g_server_config.plugins_ext);
|
antd_plugin_entry_drop(np);
|
||||||
LOG("Original plugin file: %s", path);
|
|
||||||
if ((fromfd = open(path, O_RDONLY)) < 0)
|
|
||||||
{
|
|
||||||
ERROR("Unable to open file for reading %s: %s", path, strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (stat(path, &st) != 0)
|
|
||||||
{
|
|
||||||
close(fromfd);
|
|
||||||
ERROR("Unable to get file stat %s: %s", path, strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
(void)snprintf(path, sizeof(path), "%s/%s%s", g_server_config.tmpdir, name, g_server_config.plugins_ext);
|
|
||||||
LOG("TMP plugin file: %s", path);
|
|
||||||
if ((tofd = open(path, O_WRONLY | O_CREAT, 0600)) < 0)
|
|
||||||
{
|
|
||||||
close(fromfd);
|
|
||||||
ERROR("Unable open file for reading %s: %s", path, strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (sendfile(tofd, fromfd, NULL, st.st_size) != st.st_size)
|
|
||||||
{
|
|
||||||
close(fromfd);
|
|
||||||
close(tofd);
|
|
||||||
ERROR("Unable to copy file: %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
is_tmp = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
np->name = strdup(name);
|
|
||||||
np->handle = plugin_from_file(name, path, pconf);
|
|
||||||
if (is_tmp)
|
|
||||||
{
|
|
||||||
//TODO change this
|
|
||||||
(void)remove(path);
|
|
||||||
}
|
|
||||||
if (np->handle == NULL)
|
|
||||||
{
|
|
||||||
if (np->name)
|
|
||||||
free(np->name);
|
|
||||||
if (np)
|
|
||||||
free(np);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
np->instances = dict();
|
||||||
hashval = hash(name, HASHSIZE);
|
hashval = hash(name, HASHSIZE);
|
||||||
np->next = plugin_table[hashval];
|
np->next = plugin_table[hashval];
|
||||||
plugin_table[hashval] = np;
|
plugin_table[hashval] = np;
|
||||||
}
|
}
|
||||||
else /* already there */
|
else /* already there */
|
||||||
{
|
{
|
||||||
LOG("The plugin %s id already loaded", name);
|
LOG("The plugin %s id already loaded", plugin_file_name);
|
||||||
}
|
}
|
||||||
|
// now look for the plugin context
|
||||||
|
ctx = antd_plugin_ctx_lookup(np, name);
|
||||||
// check if plugin is ready
|
// check if plugin is ready
|
||||||
metafn = (plugin_header_t * (*)()) dlsym(np->handle, "meta");
|
if (ctx == NULL)
|
||||||
if ((error = dlerror()) != NULL)
|
|
||||||
{
|
{
|
||||||
ERROR("Unable to fetch plugin meta-data: [%s] %s", name, error);
|
ERROR("Unable to fetch plugin context for: [%s] %s", plugin_file_name, name);
|
||||||
unload_plugin_by_name(name);
|
|
||||||
free(np);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
meta = metafn();
|
LOG("PLugin instance status: [%s] %d", name, ctx->status);
|
||||||
LOG("PLugin status: [%s] %d", name, meta->status);
|
if (ctx->status != ANTD_PLUGIN_READY)
|
||||||
if (!meta || meta->status != ANTD_PLUGIN_READY)
|
|
||||||
{
|
{
|
||||||
ERROR("Plugin is not ready or error: [%s].", name);
|
ERROR("Plugin instance is not ready or error: [%s].", name);
|
||||||
unload_plugin_by_name(name);
|
antd_plugin_ctx_drop(np, ctx);
|
||||||
free(np);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return np;
|
return ctx;
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Find a plugin in a file, and load it in to the plugin table
|
|
||||||
* @param name Name of the plugin
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static void *plugin_from_file(char *name, char *path, dictionary_t conf)
|
|
||||||
{
|
|
||||||
void *lib_handle;
|
|
||||||
char *error;
|
|
||||||
void (*fn)(plugin_header_t *, dictionary_t);
|
|
||||||
lib_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL /*| RTLD_NODELETE*/);
|
|
||||||
if (!lib_handle)
|
|
||||||
{
|
|
||||||
ERROR("Cannot load plugin '%s' : '%s'", name, dlerror());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
fn = (void (*)(plugin_header_t *, dictionary_t))dlsym(lib_handle, "__init_plugin__");
|
|
||||||
if ((error = dlerror()) != NULL)
|
|
||||||
ERROR("Problem when finding plugin init function for %s : %s", name, error);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
plugin_header_t header;
|
|
||||||
strncpy(header.name, name, MAX_PATH_LEN - 1);
|
|
||||||
strncpy(header.dbpath, g_server_config.db_path, MAX_PATH_LEN - 1);
|
|
||||||
strncpy(header.tmpdir, g_server_config.tmpdir, MAX_PATH_LEN - 1);
|
|
||||||
strncpy(header.pdir, g_server_config.plugins_dir, MAX_PATH_LEN - 1);
|
|
||||||
header.config = conf;
|
|
||||||
header.raw_body = 0;
|
|
||||||
header.status = ANTD_PLUGIN_INIT;
|
|
||||||
(*fn)(&header, conf);
|
|
||||||
}
|
|
||||||
// trick libc that we close this lib, but it is not realy deleted
|
|
||||||
return lib_handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unload_plugin(struct plugin_entry *np)
|
|
||||||
{
|
|
||||||
char *error;
|
|
||||||
void (*fn)() = NULL;
|
|
||||||
// find and execute the exit function
|
|
||||||
fn = (void (*)())dlsym(np->handle, "__release__");
|
|
||||||
if ((error = dlerror()) != NULL)
|
|
||||||
{
|
|
||||||
ERROR("Cant not release plugin %s : %s", np->name, error);
|
|
||||||
}
|
|
||||||
if (fn)
|
|
||||||
{
|
|
||||||
(*fn)();
|
|
||||||
}
|
|
||||||
dlclose(np->handle);
|
|
||||||
LOG("Unloaded %s", np->name);
|
|
||||||
// free((void *) np->handle);
|
|
||||||
if (np->name)
|
|
||||||
free((void *)np->name);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
Unload a plugin by its name
|
Unload a plugin by its name
|
||||||
*/
|
|
||||||
void unload_plugin_by_name(const char *name)
|
void unload_plugin_by_name(const char *name)
|
||||||
{
|
{
|
||||||
struct plugin_entry *np;
|
struct plugin_entry *np;
|
||||||
@ -212,7 +257,7 @@ void unload_plugin_by_name(const char *name)
|
|||||||
np = plugin_table[hasval];
|
np = plugin_table[hasval];
|
||||||
if (strcmp(np->name, name) == 0)
|
if (strcmp(np->name, name) == 0)
|
||||||
{
|
{
|
||||||
unload_plugin(np);
|
antd_plugin_entry_drop(np);
|
||||||
plugin_table[hasval] = np->next;
|
plugin_table[hasval] = np->next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -226,14 +271,16 @@ void unload_plugin_by_name(const char *name)
|
|||||||
}
|
}
|
||||||
if (np == NULL)
|
if (np == NULL)
|
||||||
return; // the plugin is is not loaded
|
return; // the plugin is is not loaded
|
||||||
unload_plugin(np->next);
|
antd_plugin_entry_drop(np->next);
|
||||||
np->next = np->next->next;
|
np->next = np->next->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unload all the plugin loaded on the plugin table
|
* Unload all the plugin loaded on the plugin table
|
||||||
*/
|
*/
|
||||||
void unload_all_plugin()
|
void antd_unload_all_plugin()
|
||||||
{
|
{
|
||||||
LOG("Unload all plugins");
|
LOG("Unload all plugins");
|
||||||
for (int i = 0; i < HASHSIZE; i++)
|
for (int i = 0; i < HASHSIZE; i++)
|
||||||
@ -244,10 +291,14 @@ void unload_all_plugin()
|
|||||||
while ((curr = *np) != NULL)
|
while ((curr = *np) != NULL)
|
||||||
{
|
{
|
||||||
(*np) = (*np)->next;
|
(*np) = (*np)->next;
|
||||||
unload_plugin(curr);
|
antd_plugin_entry_drop(curr);
|
||||||
free(curr);
|
//free(curr);
|
||||||
}
|
}
|
||||||
plugin_table[i] = NULL;
|
plugin_table[i] = NULL;
|
||||||
}
|
}
|
||||||
exit(0);
|
}
|
||||||
|
|
||||||
|
antd_plugin_handle_t antd_get_ctx_handle(antd_plugin_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
return ctx->handle;
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,12 @@
|
|||||||
#define PLUGIN_MANAGER_H
|
#define PLUGIN_MANAGER_H
|
||||||
|
|
||||||
#include "lib/dictionary.h"
|
#include "lib/dictionary.h"
|
||||||
|
#include "lib/plugin.h"
|
||||||
|
#include "lib/scheduler.h"
|
||||||
|
|
||||||
#define PLUGIN_HANDLER "handle"
|
typedef void*(*antd_plugin_handle_t)(void *);
|
||||||
|
|
||||||
struct plugin_entry {
|
antd_plugin_ctx_t *antd_plugin_load(const char *name);
|
||||||
struct plugin_entry *next;
|
void antd_unload_all_plugin();
|
||||||
char *name;
|
antd_plugin_handle_t antd_get_ctx_handle(antd_plugin_ctx_t *);
|
||||||
void *handle;
|
|
||||||
dictionary_t instances;
|
|
||||||
};
|
|
||||||
/* lookup: look for s in hashtable */
|
|
||||||
struct plugin_entry *plugin_lookup(char *s);
|
|
||||||
/* install: put (name, defn) in hashtable */
|
|
||||||
struct plugin_entry *plugin_load(char *name, dictionary_t config);
|
|
||||||
void unload_all_plugin();
|
|
||||||
void unload_plugin(struct plugin_entry*);
|
|
||||||
#endif
|
#endif
|
55
server.c
55
server.c
@ -3,7 +3,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -534,13 +533,8 @@ void *proxify(void *data)
|
|||||||
*/
|
*/
|
||||||
void *execute_plugin(void *data, const char *pname)
|
void *execute_plugin(void *data, const char *pname)
|
||||||
{
|
{
|
||||||
void *(*fn)(void *);
|
|
||||||
plugin_header_t *(*metafn)();
|
|
||||||
plugin_header_t *meta = NULL;
|
|
||||||
struct plugin_entry *plugin;
|
|
||||||
char *error;
|
|
||||||
char pattern[256];
|
char pattern[256];
|
||||||
|
antd_plugin_ctx_t* ctx;
|
||||||
antd_request_t *rq = (antd_request_t *)data;
|
antd_request_t *rq = (antd_request_t *)data;
|
||||||
antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
||||||
antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE);
|
antd_task_bind_event(task, rq->client->sock, 0, TASK_EVT_ON_WRITABLE | TASK_EVT_ON_READABLE);
|
||||||
@ -561,58 +555,23 @@ void *execute_plugin(void *data, const char *pname)
|
|||||||
rq->client->state = ANTD_CLIENT_PLUGIN_EXEC;
|
rq->client->state = ANTD_CLIENT_PLUGIN_EXEC;
|
||||||
// load the plugin
|
// load the plugin
|
||||||
pthread_mutex_lock(&server_mux);
|
pthread_mutex_lock(&server_mux);
|
||||||
plugin = plugin_load((char *)pname, dvalue(g_server_config.plugins, pname));
|
ctx = antd_plugin_load(pname);
|
||||||
pthread_mutex_unlock(&server_mux);
|
pthread_mutex_unlock(&server_mux);
|
||||||
if (plugin == NULL)
|
if (ctx == NULL)
|
||||||
{
|
{
|
||||||
antd_error(rq->client, 503, "Requested service not found");
|
antd_error(rq->client, 503, "Requested service not found");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
// check if the plugin want rawbody or decoded body
|
rq->context = ctx;
|
||||||
metafn = (plugin_header_t * (*)()) dlsym(plugin->handle, "meta");
|
|
||||||
if ((error = dlerror()) == NULL)
|
|
||||||
{
|
|
||||||
meta = metafn();
|
|
||||||
}
|
|
||||||
// load the function
|
|
||||||
fn = (void *(*)(void *))dlsym(plugin->handle, PLUGIN_HANDLER);
|
|
||||||
if ((error = dlerror()) != NULL)
|
|
||||||
{
|
|
||||||
ERROR("Problem when finding %s method from %s : %s", PLUGIN_HANDLER, pname, error);
|
|
||||||
antd_error(rq->client, 503, "Requested service not found");
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
// check if we need the raw data or not
|
// check if we need the raw data or not
|
||||||
if (meta && meta->raw_body == 1)
|
if (antd_plugin_is_raw_body(ctx) == 1)
|
||||||
{
|
{
|
||||||
task->handle = fn;
|
task->handle = antd_get_ctx_handle(ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free(task);
|
free(task);
|
||||||
task = antd_create_task(decode_post_request, (void *)rq, fn, rq->client->last_io);
|
task = antd_create_task(decode_post_request, (void *)rq, antd_get_ctx_handle(ctx), rq->client->last_io);
|
||||||
}
|
}
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictionary_t mimes_list()
|
|
||||||
{
|
|
||||||
return g_server_config.mimes;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_ZLIB
|
|
||||||
int compressable(char *ctype)
|
|
||||||
{
|
|
||||||
if (!g_server_config.gzip_enable || g_server_config.gzip_types == NULL)
|
|
||||||
return 0;
|
|
||||||
item_t it;
|
|
||||||
list_for_each(it, g_server_config.gzip_types)
|
|
||||||
{
|
|
||||||
if (it->type == LIST_TYPE_POINTER && it->value.ptr && regex_match((const char *)it->value.ptr, ctype, 0, NULL))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user