Browse Source

[angel] Add basic module/plugin support

* renamed some module functions
personal/stbuehler/wip
Stefan Bühler 13 years ago
parent
commit
48bf0071e4
  1. 3
      include/lighttpd/angel_base.h
  2. 2
      include/lighttpd/angel_config_parser.h
  3. 82
      include/lighttpd/angel_log.h
  4. 70
      include/lighttpd/angel_plugin.h
  5. 8
      include/lighttpd/angel_plugin_core.h
  6. 7
      include/lighttpd/angel_server.h
  7. 3
      include/lighttpd/log.h
  8. 4
      include/lighttpd/module.h
  9. 10
      src/CMakeLists.txt
  10. 10
      src/angel_config_parser.rl
  11. 66
      src/angel_log.c
  12. 8
      src/angel_main.c
  13. 351
      src/angel_plugin.c
  14. 7
      src/angel_plugin_core.c
  15. 20
      src/angel_server.c
  16. 2
      src/log.c
  17. 4
      src/module.c
  18. 4
      src/server.c

3
include/lighttpd/angel_base.h

@ -21,7 +21,8 @@ typedef struct instance instance;
#include <lighttpd/angel_value.h>
#include <lighttpd/angel_data.h>
#include <lighttpd/angel_connection.h>
#include <lighttpd/angel_server.h>
#include <lighttpd/angel_log.h>
#include <lighttpd/angel_plugin.h>
#include <lighttpd/angel_server.h>
#endif

2
include/lighttpd/angel_config_parser.h

@ -9,6 +9,6 @@ typedef enum {
ANGEL_CONFIG_PARSER_ERROR_PARSE, /* parse error */
} AngelConfigParserError;
LI_API gboolean angel_config_parse_file(const gchar *filename, GError **err);
LI_API gboolean angel_config_parse_file(server *srv, const gchar *filename, GError **err);
#endif

82
include/lighttpd/angel_log.h

@ -0,0 +1,82 @@
#ifndef _LIGHTTPD_ANGEL_LOG_H_
#define _LIGHTTPD_ANGEL_LOG_H_
#ifndef _LIGHTTPD_ANGEL_BASE_H_
#error Please include <lighttpd/angel_base.h> instead of this file
#endif
/* #include <lighttpd/valgrind/valgrind.h> */
#define REMOVE_PATH_FROM_FILE 1
#if REMOVE_PATH_FROM_FILE
LI_API const char *remove_path(const char *path);
#define REMOVE_PATH(file) remove_path(file)
#else
#define REMOVE_PATH(file) file
#endif
#define SEGFAULT(srv, fmt, ...) \
do { \
log_write_(srv, LOG_LEVEL_ABORT, LOG_FLAG_TIMESTAMP, "(crashing) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__); \
/* VALGRIND_PRINTF_BACKTRACE(fmt, __VA_ARGS__); */\
abort();\
} while(0)
#define ERROR(srv, fmt, ...) \
log_write(srv, LOG_LEVEL_ERROR, LOG_FLAG_TIMESTAMP, "error (%s:%d): "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define WARNING(srv, fmt, ...) \
log_write(srv, LOG_LEVEL_WARNING, LOG_FLAG_TIMESTAMP, "warning (%s:%d): "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define INFO(srv, fmt, ...) \
log_write(srv, LOG_LEVEL_INFO, LOG_FLAG_TIMESTAMP, "info (%s:%d): "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define DEBUG(srv, fmt, ...) \
log_write(srv, LOG_LEVEL_DEBUG, LOG_FLAG_TIMESTAMP, "debug (%s:%d): "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
/* log messages from lighty always as ERROR */
#define INSTANCE(srv, inst, msg) \
log_write(srv, LOG_LEVEL_ERROR, LOG_FLAG_NONE, "lighttpd[%d]: %s", (int) inst->pid, msg)
typedef enum {
LOG_LEVEL_DEBUG,
LOG_LEVEL_INFO,
LOG_LEVEL_WARNING,
LOG_LEVEL_ERROR,
LOG_LEVEL_ABORT
} log_level_t;
#define LOG_LEVEL_COUNT (LOG_LEVEL_ABORT+1)
typedef enum {
LOG_TYPE_STDERR,
LOG_TYPE_FILE,
LOG_TYPE_PIPE,
LOG_TYPE_SYSLOG,
LOG_TYPE_NONE
} log_type_t;
#define LOG_FLAG_NONE (0x0) /* default flag */
#define LOG_FLAG_TIMESTAMP (0x1) /* prepend a timestamp to the log message */
struct log_t;
typedef struct log_t log_t;
struct log_t {
log_type_t type;
gboolean levels[LOG_LEVEL_COUNT];
GString *path;
gint fd;
time_t last_ts;
GString *ts_cache;
GString *log_line;
};
void log_init(server *srv);
void log_clean(server *srv);
LI_API void log_write(server *srv, log_level_t log_level, guint flags, const gchar *fmt, ...) G_GNUC_PRINTF(4, 5);
#endif

70
include/lighttpd/angel_plugin.h

@ -5,7 +5,75 @@
#error Please include <lighttpd/angel_base.h> instead of this file
#endif
typedef struct plugin_item plugin_item;
typedef struct plugin_item_option plugin_item_option;
typedef struct plugin plugin;
typedef struct Plugins Plugins;
LI_API gboolean plugins_handle_item(server *srv, value *hash);
typedef gboolean (*PluginInit) (server *srv, plugin *p);
typedef void (*PluginFree) (server *srv, plugin *p);
typedef void (*PluginCleanConfig) (server *srv, plugin *p);
typedef gboolean (*PluginCheckConfig) (server *srv, plugin *p);
typedef void (*PluginActivateConfig)(server *srv, plugin *p);
typedef void (*PluginParseItem) (server *srv, plugin *p, value **options);
typedef enum {
PLUGIN_ITEM_OPTION_MANDATORY = 1
} plugin_item_option_flags;
struct plugin_item_option {
const gchar *name; /**< name of the option */
value_type type; /**< type of the option; may be VALUE_NONE to accept anything */
plugin_item_option_flags flags; /**< flags of the option */
};
struct plugin_item {
const gchar *name;
PluginParseItem handle_parse_item;
const plugin_item_option options[];
};
struct plugin {
size_t version;
const gchar *name; /**< name of the plugin */
gpointer data; /**< private plugin data */
const plugin_item *items;
PluginInit plugin_init_marker; /**< identify plugin; PluginInit must be unique per plugin */
PluginFree handle_free; /**< called before plugin is unloaded */
PluginCleanConfig handle_clean_config; /**< called before the reloading of the config is started or after the reloading failed */
PluginCheckConfig handle_check_config; /**< called before activating a config to ensure everything works */
PluginActivateConfig handle_activate_config; /**< called to activate a config after successful loading it. this cannot fail */
};
struct Plugins {
GString *config_filename;
GHashTable *items, *load_items; /**< gchar* -> server_item */
struct modules *modules;
GHashTable *module_refs, *load_module_refs; /** gchar* -> server_module */
GPtrArray *plugins, *load_plugins; /* plugin* */
};
void plugins_init(server *srv, const gchar *module_dir);
void plugins_clear(server *srv);
void plugins_config_clean(server *srv);
gboolean plugins_config_load(server *srv, const gchar *filename);
gboolean plugins_handle_item(server *srv, GString *itemname, value *hash);
/* "core" is a reserved module name for interal use */
gboolean plugins_load_module(server *srv, const gchar *name);
/* Needed by modules to register their plugin(s) */
LI_API plugin *angel_plugin_register(server *srv, module *mod, const gchar *name, PluginInit init);
#endif

8
include/lighttpd/angel_plugin_core.h

@ -0,0 +1,8 @@
#ifndef _LIGHTTPD_ANGEL_PLUGIN_CORE_H_
#define _LIGHTTPD_ANGEL_PLUGIN_CORE_H_
#include <lighttpd/angel_base.h>
gboolean plugin_core_init(server *srv);
#endif

7
include/lighttpd/angel_server.h

@ -22,12 +22,9 @@ struct server {
sig_w_TERM,
sig_w_PIPE;
struct modules *modules;
Plugins plugins;
GHashTable *plugins; /**< const gchar* => (plugin*) */
struct plugin *core_plugin;
ev_tstamp started;
log_t log;
};
LI_API server* server_new(const gchar *module_dir);

3
include/lighttpd/log.h

@ -32,7 +32,8 @@ LI_API const char *remove_path(const char *path);
log_write_(srv, vr, LOG_LEVEL_INFO, LOG_FLAG_TIMESTAMP, "(info) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define _DEBUG(srv, vr, fmt, ...) \
log_write_(srv, vr, LOG_LEVEL_INFO, LOG_FLAG_TIMESTAMP, "(debug) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
log_write_(srv, vr, LOG_LEVEL_DEBUG, LOG_FLAG_TIMESTAMP, "(debug) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define _BACKEND(srv, vr, fmt, ...) \
log_write_(srv, vr, LOG_LEVEL_BACKEND, LOG_FLAG_TIMESTAMP, "(backend) %s.%d: "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define _BACKEND_LINES(srv, vr, txt, fmt, ...) \

4
include/lighttpd/module.h

@ -52,8 +52,8 @@ struct modules {
guint8 sizeof_off_t; /** holds the value of sizeof(off_t) to check if loaded module was compiled with the same flags */
};
LI_API modules* modules_init(gpointer main, const gchar *module_dir);
LI_API void modules_cleanup(modules *mods);
LI_API modules* modules_new(gpointer main, const gchar *module_dir);
LI_API void modules_free(modules *mods);
/** Loads a module if not loaded yet and returns the module struct for it (after increasing refcount)
* returns NULL if it couldn't load the module.

10
src/CMakeLists.txt

@ -359,11 +359,17 @@ ADD_TARGET_PROPERTIES(lighttpd LINK_FLAGS ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd COMPILE_FLAGS ${COMMON_CFLAGS})
ADD_EXECUTABLE(lighttpd-angel
angel_config_parser.c
angel_data.c
angel_log.c
angel_main.c
angel_value.c
angel_plugin.c
angel_config_parser.c
angel_plugin_core.c
angel_server.c
angel_value.c
condition_parsers.c
module.c
utils.c
)
ADD_TARGET_PROPERTIES(lighttpd-angel LINK_FLAGS "${LUA_LDFLAGS} ${EV_LDFLAGS} ${GMODULE_LDFLAGS} ${WARN_FLAGS}")

10
src/angel_config_parser.rl

@ -102,9 +102,7 @@ static gchar *format_char(pcontext *ctx, gchar c) {
}
action enditem {
GString *tmp = value_to_string(ctx->itemvalue);
g_printerr("Item '%s': %s\n", ctx->itemname->str, tmp->str);
g_string_free(tmp, TRUE);
plugins_handle_item(srv, ctx->itemname, ctx->itemvalue);
g_string_free(ctx->itemname, TRUE);
ctx->itemname = NULL;
value_free(ctx->itemvalue);
@ -422,7 +420,7 @@ static gboolean angel_config_parser_finalize(pcontext *ctx, filecontext *fctx, G
return TRUE;
}
static gboolean angel_config_parse_data(pcontext *ctx, filecontext *fctx, gchar *data, gsize len, GError **err) {
static gboolean angel_config_parse_data(server *srv, pcontext *ctx, filecontext *fctx, gchar *data, gsize len, GError **err) {
gchar *p = data, *pe = p+len, *eof = NULL, *linestart = p, *tokenstart = NULL;
if (ctx->readingtoken) tokenstart = p;
@ -443,7 +441,7 @@ static gboolean angel_config_parse_data(pcontext *ctx, filecontext *fctx, gchar
return TRUE;
}
gboolean angel_config_parse_file(const gchar *filename, GError **err) {
gboolean angel_config_parse_file(server *srv, const gchar *filename, GError **err) {
char *data = NULL;
gsize len = 0;
filecontext sfctx, *fctx = &sfctx;
@ -456,7 +454,7 @@ gboolean angel_config_parse_file(const gchar *filename, GError **err) {
sfctx.filename = filename;
sfctx.line = 1;
sfctx.column = 1;
if (!angel_config_parse_data(ctx, fctx, data, len, err)) goto error;
if (!angel_config_parse_data(srv, ctx, fctx, data, len, err)) goto error;
if (!angel_config_parser_finalize(ctx, fctx, err)) goto error;
if (data) g_free(data);

66
src/angel_log.c

@ -0,0 +1,66 @@
#include <lighttpd/angel_base.h>
#if REMOVE_PATH_FROM_FILE
const char *remove_path(const char *path) {
char *p = strrchr(path, DIR_SEPERATOR);
if (NULL != p && *(p) != '\0') {
return (p + 1);
}
return path;
}
#endif
void log_init(server *srv) {
srv->log.type = LOG_TYPE_STDERR;
srv->log.levels[LOG_LEVEL_ABORT] = TRUE;
srv->log.levels[LOG_LEVEL_ERROR] = TRUE;
srv->log.levels[LOG_LEVEL_WARNING] = TRUE;
srv->log.fd = -1;
srv->log.ts_cache = g_string_sized_new(0);
srv->log.log_line = g_string_sized_new(0);
}
void log_clean(server *srv) {
g_string_free(srv->log.ts_cache, TRUE);
g_string_free(srv->log.log_line, TRUE);
}
void log_write(server *srv, log_level_t log_level, guint flags, const gchar *fmt, ...) {
va_list ap;
GString *log_line = srv->log.log_line;
if (!srv->log.levels[log_level]) return;
g_string_truncate(log_line, 0);
/* for normal error messages, we prepend a timestamp */
if (flags & LOG_FLAG_TIMESTAMP) {
GString *log_ts = srv->log.ts_cache;
time_t cur_ts;
cur_ts = (time_t)ev_now(srv->loop);
if (cur_ts != srv->log.last_ts) {
gsize s;
g_string_set_size(log_ts, 255);
s = strftime(log_ts->str, log_ts->allocated_len, "%Y-%m-%d %H:%M:%S %Z: ", localtime(&cur_ts));
g_string_set_size(log_ts, s);
srv->log.last_ts = cur_ts;
}
g_string_append_len(log_line, GSTR_LEN(log_ts));
}
va_start(ap, fmt);
g_string_append_vprintf(log_line, fmt, ap);
va_end(ap);
g_string_append_len(log_line, CONST_STR_LEN("\n"));
fprintf(stderr, "%s", log_line->str);
}

8
src/angel_main.c

@ -14,6 +14,7 @@ int main(int argc, char *argv[]) {
gboolean res;
int result = 0;
server* srv = NULL;
GOptionEntry entries[] = {
{ "config", 'c', 0, G_OPTION_ARG_FILENAME, &config_path, "filename/path of the config", "PATH" },
@ -50,9 +51,9 @@ int main(int argc, char *argv[]) {
goto cleanup;
}
if (!angel_config_parse_file(config_path, &error)) {
g_printerr("lighttpd-angel: failed to parse config file: %s\n", error->message);
g_error_free(error);
srv = server_new(module_dir);
if (!plugins_config_load(srv, config_path)) {
result = -1;
goto cleanup;
}
@ -60,6 +61,7 @@ int main(int argc, char *argv[]) {
g_printerr("lighttpd-angel: Parsed config file\n");
cleanup:
if (srv) server_free(srv);
if (config_path) g_free((gchar*) config_path);
if (module_dir != def_module_dir) g_free((gchar*) module_dir);

351
src/angel_plugin.c

@ -0,0 +1,351 @@
#include <lighttpd/angel_base.h>
#include <lighttpd/angel_config_parser.h>
#include <lighttpd/angel_plugin_core.h>
/* internal structures */
typedef struct server_item server_item;
struct server_item {
plugin *p;
guint option_count;
const plugin_item *p_item;
};
typedef struct server_module server_module;
struct server_module {
guint refcount;
gchar *name;
server *srv;
module *mod;
GPtrArray *plugins; /* plugin* */
};
static void _server_item_free(gpointer p) {
g_slice_free(server_item, p);
}
static server_item* server_item_new(plugin *p, const plugin_item *p_item) {
server_item *si = g_slice_new(server_item);
const plugin_item_option *pio;
guint cnt;
for (pio = p_item->options, cnt = 0; pio->name; pio++, cnt++) ;
si->p = p;
si->option_count = cnt;
si->p_item = p_item;
return si;
}
static void plugin_free(server *srv, plugin *p) {
if (p->handle_free) p->handle_free(srv, p);
g_slice_free(plugin, p);
}
static plugin* plugin_new(const char *name) {
plugin *p = g_slice_new0(plugin);
p->name = name;
return p;
}
static void _server_module_release(gpointer d) {
server_module *sm = d;
guint i;
g_assert(sm->refcount > 0);
if (0 != --sm->refcount) return;
for (i = sm->plugins->len; i-- > 0; ) {
plugin *p = g_ptr_array_index(sm->plugins, i);
plugin_free(sm->srv, p);
}
g_ptr_array_free(sm->plugins, TRUE);
if (sm->mod) module_release(sm->srv->plugins.modules, sm->mod);
g_free(sm->name);
g_slice_free(server_module, sm);
}
static void server_module_acquire(server_module *sm) {
g_assert(sm->refcount > 0);
sm->refcount++;
}
static server_module* server_module_new(server *srv, const gchar *name) { /* module is set later */
server_module *sm = g_slice_new0(server_module);
sm->refcount = 1;
sm->srv = srv;
sm->plugins = g_ptr_array_new();
sm->name = g_strdup(name);
return sm;
}
void plugins_init(server *srv, const gchar *module_dir) {
Plugins *ps = &srv->plugins;
ps->modules = modules_new(srv, module_dir);
ps->items = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_item_free);
ps->load_items = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_item_free);
ps->module_refs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_module_release);
ps->load_module_refs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_module_release);
ps->plugins = g_ptr_array_new();
ps->load_plugins = g_ptr_array_new();
}
void plugins_clear(server *srv) {
Plugins *ps = &srv->plugins;
plugins_config_clean(srv);
g_hash_table_destroy(ps->items);
g_hash_table_destroy(ps->load_items);
g_hash_table_destroy(ps->module_refs);
g_hash_table_destroy(ps->load_module_refs);
g_ptr_array_free(ps->plugins, TRUE);
g_ptr_array_free(ps->load_plugins, TRUE);
if (ps->config_filename) g_string_free(ps->config_filename, TRUE);
modules_free(ps->modules);
}
void plugins_config_clean(server *srv) {
Plugins *ps = &srv->plugins;
guint i;
for (i = ps->load_plugins->len; i-- > 0; ) {
plugin *p = g_ptr_array_index(ps->load_plugins, i);
if (p->handle_clean_config) p->handle_clean_config(srv, p);
}
g_hash_table_remove_all(ps->load_items);
g_hash_table_remove_all(ps->load_module_refs);
g_ptr_array_set_size(ps->load_plugins, 0);
}
gboolean plugins_config_load(server *srv, const gchar *filename) {
Plugins *ps = &srv->plugins;
GError *error = NULL;
guint i;
if (!angel_config_parse_file(srv, filename, &error)) {
ERROR(srv, "failed to parse config file: %s\n", error->message);
g_error_free(error);
plugins_config_clean(srv);
return FALSE;
}
/* check new config */
for (i = ps->plugins->len; i-- > 0; ) {
plugin *p = g_ptr_array_index(ps->load_plugins, i);
if (p->handle_check_config) {
if (!p->handle_check_config(srv, p)) {
plugins_config_clean(srv);
return FALSE;
}
}
}
/* activate new config */
for (i = ps->plugins->len; i-- > 0; ) {
plugin *p = g_ptr_array_index(ps->load_plugins, i);
if (p->handle_activate_config) {
p->handle_activate_config(srv, p);
}
}
{ /* swap the arrays */
GPtrArray *tmp = ps->load_plugins; ps->load_plugins = ps->plugins; ps->plugins = tmp;
}
{ /* swap the hash tables */
GHashTable *tmp;
tmp = ps->load_items; ps->load_items = ps->items; ps->items = tmp;
tmp = ps->load_module_refs; ps->load_module_refs = ps->module_refs; ps->module_refs = tmp;
}
g_hash_table_remove_all(ps->load_items);
g_hash_table_remove_all(ps->load_module_refs);
g_ptr_array_set_size(ps->load_plugins, 0);
if (!ps->config_filename) {
ps->config_filename = g_string_new(filename);
} else {
g_string_assign(ps->config_filename, filename);
}
return TRUE;
}
gboolean plugins_handle_item(server *srv, GString *itemname, value *hash) {
Plugins *ps = &srv->plugins;
server_item *si;
#if 1
/* debug items */
{
GString *tmp = value_to_string(hash);
ERROR(srv, "Item '%s': %s\n", itemname->str, tmp->str);
g_string_free(tmp, TRUE);
}
#endif
si = g_hash_table_lookup(ps->load_items, itemname->str);
if (!si) {
WARNING(srv, "Unknown item '%s' - perhaps you forgot to load the module? (ignored)", itemname->str);
} else {
value **optlist = g_slice_alloc0(sizeof(value*) * si->option_count);
GHashTableIter opti;
gpointer k, v;
guint i;
gboolean valid = TRUE;
/* find options and assign them by id */
g_hash_table_iter_init(&opti, hash->data.hash);
while (g_hash_table_iter_next(&opti, &k, &v)) {
const gchar *optkey = ((GString*) k)->str;
for (i = 0; i < si->option_count; i++) {
if (0 == g_strcmp0(si->p_item->options[i].name, optkey)) break;
}
if (i == si->option_count) {
WARNING(srv, "Unknown option '%s' in item '%s' (ignored)", optkey, itemname->str);
} else {
optlist[i] = v;
}
}
/* validate options */
for (i = 0; i < si->option_count; i++) {
const plugin_item_option *pi = &si->p_item->options[i];
if (0 != (pi->flags & PLUGIN_ITEM_OPTION_MANDATORY)) {
if (!optlist[i]) {
ERROR(srv, "Missing mandatory option '%s' in item '%s'", pi->name, itemname->str);
valid = FALSE;
}
}
if (pi->type != VALUE_NONE && optlist[i] && optlist[i]->type != pi->type) {
/* TODO: convert from string if possible */
ERROR(srv, "Invalid value type of option '%s' in item '%s', got '%s' but expected '%s'",
pi->name, itemname->str, value_type_string(optlist[i]->type), value_type_string(pi->type));
valid = FALSE;
}
}
if (valid) {
g_assert(si->p_item->handle_parse_item);
si->p_item->handle_parse_item(srv, si->p, optlist);
}
g_slice_free1(sizeof(value*) * si->option_count, optlist);
}
return TRUE;
}
static gboolean plugins_activate_module(server *srv, server_module *sm) {
Plugins *ps = &srv->plugins;
plugin *p;
const plugin_item *pi;
guint i;
for (i = 0; i < sm->plugins->len; i++) {
p = g_ptr_array_index(sm->plugins, i);
g_ptr_array_add(ps->load_plugins, p);
if (!p->items) continue;
for (pi = p->items; pi->name; pi++) {
server_item *si;
if (NULL != (si = g_hash_table_lookup(ps->load_items, pi->name))) {
ERROR(srv, "Plugin item name conflict: cannot load '%s' for plugin '%s' (already provided by plugin '%s')",
pi->name, p->name, si->p->name);
goto item_collission;
} else {
si = server_item_new(p, pi);
g_hash_table_insert(ps->load_items, (gpointer) pi->name, si);
}
}
}
return TRUE;
item_collission:
/* removed added items and plugins */
for ( ; pi-- != p->items; ) {
g_hash_table_remove(ps->load_items, pi->name);
}
g_ptr_array_set_size(ps->load_plugins, ps->load_plugins->len - i+1);
for ( ; i-- > 0; ) {
p = g_ptr_array_index(sm->plugins, i);
if (!p->items) continue;
for (pi = p->items; pi->name; pi++) {
g_hash_table_remove(ps->load_items, pi->name);
}
}
return FALSE;
}
gboolean plugins_load_module(server *srv, const gchar *name) {
Plugins *ps = &srv->plugins;
server_module *sm;
const gchar* modname = name ? name : "core";
sm = g_hash_table_lookup(ps->load_module_refs, modname);
if (sm) return TRUE; /* already loaded */
sm = g_hash_table_lookup(ps->module_refs, modname);
if (sm) { /* loaded in previous config */
server_module_acquire(sm);
g_hash_table_insert(ps->load_module_refs, sm->name, sm);
} else { /* not loaded yet */
module *mod;
sm = server_module_new(srv, modname);
g_hash_table_insert(ps->load_module_refs, sm->name, sm);
if (name) {
mod = module_load(ps->modules, name);
if (!mod) {
_server_module_release(sm);
return FALSE;
}
sm->mod = mod;
} else {
if (!plugin_core_init(srv)) {
_server_module_release(sm);
return FALSE;
}
}
}
if (!plugins_activate_module(srv, sm)) {
_server_module_release(sm);
return FALSE;
}
return TRUE;
}
plugin *angel_plugin_register(server *srv, module *mod, const gchar *name, PluginInit init) {
Plugins *ps = &srv->plugins;
server_module *sm;
plugin *p;
const gchar* modname = mod ? mod->name->str : "core";
sm = g_hash_table_lookup(ps->load_module_refs, modname);
if (!sm) {
ERROR(srv, "Module '%s' not loaded; cannot load plugin '%s'", mod->name->str, name);
return NULL;
}
p = plugin_new(name);
if (!init(srv, p)) {
plugin_free(srv, p);
return NULL;
}
g_ptr_array_add(sm->plugins, p);
return p;
}

7
src/angel_plugin_core.c

@ -0,0 +1,7 @@
#include <lighttpd/angel_plugin_core.h>
gboolean plugin_core_init(server *srv) {
/* load core plugins */
return TRUE;
}

20
src/angel_server.c

@ -0,0 +1,20 @@
#include <lighttpd/angel_base.h>
server* server_new(const gchar *module_dir) {
server *srv = g_slice_new0(server);
/* TODO: handle sinals */
srv->loop = ev_default_loop(0);
log_init(srv);
plugins_init(srv, module_dir);
return srv;
}
void server_free(server* srv) {
plugins_clear(srv);
log_clean(srv);
g_slice_free(server, srv);
}

2
src/log.c

@ -11,8 +11,6 @@
#include <fcntl.h>
#include <stdarg.h>
/* from server.h */
#if REMOVE_PATH_FROM_FILE
const char *remove_path(const char *path) {
char *p = strrchr(path, DIR_SEPERATOR);

4
src/module.c

@ -1,7 +1,7 @@
#include <lighttpd/module.h>
modules *modules_init(gpointer main, const gchar *module_dir) {
modules *modules_new(gpointer main, const gchar *module_dir) {
modules *m = g_slice_new(modules);
m->version = MODULE_VERSION;
@ -26,7 +26,7 @@ module *module_lookup(modules *mods, const gchar *name) {
return NULL;
}
void modules_cleanup(modules* mods) {
void modules_free(modules* mods) {
/* unload all modules */
GArray *a = mods->mods;
module *mod;

4
src/server.c

@ -91,7 +91,7 @@ server* server_new(const gchar *module_dir) {
srv->sockets = g_ptr_array_new();
srv->modules = modules_init(srv, module_dir);
srv->modules = modules_new(srv, module_dir);
srv->plugins = g_hash_table_new(g_str_hash, g_str_equal);
srv->options = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_value_free);
@ -166,7 +166,7 @@ void server_free(server* srv) {
}
/* release modules */
modules_cleanup(srv->modules);
modules_free(srv->modules);
plugin_free(srv, srv->core_plugin);

Loading…
Cancel
Save