2016-03-19 15:14:35 +00:00
|
|
|
#include "first.h"
|
|
|
|
|
2009-10-11 14:31:42 +00:00
|
|
|
#include "plugin.h"
|
2018-03-25 07:45:05 +00:00
|
|
|
#include "base.h"
|
2019-11-28 15:27:01 +00:00
|
|
|
#include "array.h"
|
2009-10-11 14:31:42 +00:00
|
|
|
#include "log.h"
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2019-11-28 15:27:01 +00:00
|
|
|
array plugin_stats; /* global */
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
#ifdef HAVE_VALGRIND_VALGRIND_H
|
2009-10-11 14:31:42 +00:00
|
|
|
# include <valgrind/valgrind.h>
|
2005-02-20 14:27:00 +00:00
|
|
|
#endif
|
|
|
|
|
2016-02-28 12:12:05 +00:00
|
|
|
#if !defined(__WIN32) && !defined(LIGHTTPD_STATIC)
|
2009-10-11 14:31:42 +00:00
|
|
|
# include <dlfcn.h>
|
2005-02-20 14:27:00 +00:00
|
|
|
#endif
|
|
|
|
/*
|
2006-10-04 13:26:23 +00:00
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
* if you change this enum to add a new callback, be sure
|
|
|
|
* - that PLUGIN_FUNC_SIZEOF is the last entry
|
2019-10-19 06:21:46 +00:00
|
|
|
* - that you add:
|
|
|
|
* 1. PLUGIN_CALL_... as callback-dispatcher
|
|
|
|
* 2. count and assignment in plugins_call_init()
|
2006-10-04 13:26:23 +00:00
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
*/
|
|
|
|
|
2006-10-04 13:26:23 +00:00
|
|
|
typedef enum {
|
2015-08-29 09:28:01 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_URI_CLEAN,
|
|
|
|
PLUGIN_FUNC_HANDLE_URI_RAW,
|
2016-12-21 05:07:12 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_REQUEST_ENV,
|
2015-08-29 09:28:01 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_REQUEST_DONE,
|
2016-12-21 05:07:12 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT,
|
|
|
|
PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR,
|
2015-08-29 09:28:01 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
|
|
|
|
PLUGIN_FUNC_HANDLE_TRIGGER,
|
|
|
|
PLUGIN_FUNC_HANDLE_SIGHUP,
|
2017-09-10 19:28:51 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_WAITPID,
|
2020-01-11 05:54:31 +00:00
|
|
|
/* PLUGIN_FUNC_HANDLE_SUBREQUEST, *//* max one handler_module per req */
|
2015-08-29 09:28:01 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
|
2016-06-22 00:28:55 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_RESPONSE_START,
|
2015-08-29 09:28:01 +00:00
|
|
|
PLUGIN_FUNC_HANDLE_DOCROOT,
|
|
|
|
PLUGIN_FUNC_HANDLE_PHYSICAL,
|
|
|
|
PLUGIN_FUNC_CONNECTION_RESET,
|
2019-11-19 08:39:40 +00:00
|
|
|
/* PLUGIN_FUNC_INIT, *//* handled here in plugin.c */
|
|
|
|
/* PLUGIN_FUNC_CLEANUP, *//* handled here in plugin.c */
|
2015-08-29 09:28:01 +00:00
|
|
|
PLUGIN_FUNC_SET_DEFAULTS,
|
2019-03-22 00:29:34 +00:00
|
|
|
PLUGIN_FUNC_WORKER_INIT,
|
2015-08-29 09:28:01 +00:00
|
|
|
|
|
|
|
PLUGIN_FUNC_SIZEOF
|
2005-02-20 14:27:00 +00:00
|
|
|
} plugin_t;
|
|
|
|
|
|
|
|
static plugin *plugin_init(void) {
|
|
|
|
plugin *p;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
p = calloc(1, sizeof(*p));
|
2016-01-30 13:59:07 +00:00
|
|
|
force_assert(NULL != p);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void plugin_free(plugin *p) {
|
2020-07-08 22:01:52 +00:00
|
|
|
if (NULL == p) return; /*(should not happen w/ current usage)*/
|
2019-10-19 04:30:54 +00:00
|
|
|
#if !defined(LIGHTTPD_STATIC)
|
|
|
|
if (p->lib) {
|
|
|
|
#if defined(HAVE_VALGRIND_VALGRIND_H)
|
|
|
|
/*if (!RUNNING_ON_VALGRIND) */
|
|
|
|
#endif
|
|
|
|
#if defined(__WIN32)
|
|
|
|
FreeLibrary(p->lib);
|
|
|
|
#else
|
|
|
|
dlclose(p->lib);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
free(p);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-10-19 06:21:46 +00:00
|
|
|
static void plugins_register(server *srv, plugin *p) {
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin **ps;
|
2019-02-13 03:36:04 +00:00
|
|
|
if (srv->plugins.used == srv->plugins.size) {
|
2005-02-20 14:27:00 +00:00
|
|
|
srv->plugins.size += 4;
|
|
|
|
srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
|
2016-01-30 13:59:07 +00:00
|
|
|
force_assert(NULL != srv->plugins.ptr);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
ps = srv->plugins.ptr;
|
|
|
|
ps[srv->plugins.used++] = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2006-10-04 13:26:23 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
*/
|
|
|
|
|
2015-08-29 09:28:01 +00:00
|
|
|
#if defined(LIGHTTPD_STATIC)
|
|
|
|
|
|
|
|
/* pre-declare functions, as there is no header for them */
|
2006-01-03 12:53:12 +00:00
|
|
|
#define PLUGIN_INIT(x)\
|
2015-08-29 09:28:01 +00:00
|
|
|
int x ## _plugin_init(plugin *p);
|
2006-01-03 12:53:12 +00:00
|
|
|
|
2006-01-04 23:31:32 +00:00
|
|
|
#include "plugin-static.h"
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2015-08-29 09:28:01 +00:00
|
|
|
#undef PLUGIN_INIT
|
|
|
|
|
|
|
|
/* build NULL-terminated table of name + init-function */
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const char* name;
|
|
|
|
int (*plugin_init)(plugin *p);
|
|
|
|
} plugin_load_functions;
|
|
|
|
|
|
|
|
static const plugin_load_functions load_functions[] = {
|
|
|
|
#define PLUGIN_INIT(x) \
|
|
|
|
{ #x, &x ## _plugin_init },
|
|
|
|
|
|
|
|
#include "plugin-static.h"
|
|
|
|
|
|
|
|
{ NULL, NULL }
|
|
|
|
#undef PLUGIN_INIT
|
|
|
|
};
|
|
|
|
|
|
|
|
int plugins_load(server *srv) {
|
2019-11-25 06:54:08 +00:00
|
|
|
for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
|
2019-10-13 08:59:57 +00:00
|
|
|
data_string *ds = (data_string *)srv->srvconf.modules->data[i];
|
|
|
|
char *module = ds->value.ptr;
|
2015-08-29 09:28:01 +00:00
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
uint32_t j;
|
|
|
|
for (j = 0; j < i; ++j) {
|
2019-10-13 08:59:57 +00:00
|
|
|
if (buffer_is_equal(&ds->value, &((data_string *) srv->srvconf.modules->data[j])->value)) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
|
|
|
"Cannot load plugin %s "
|
|
|
|
"more than once, please fix your config (lighttpd may not accept such configs in future releases)",
|
|
|
|
ds->value.ptr);
|
2015-08-29 09:28:01 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; load_functions[j].name; ++j) {
|
|
|
|
if (0 == strcmp(load_functions[j].name, module)) {
|
2019-11-25 06:54:08 +00:00
|
|
|
plugin * const p = plugin_init();
|
2015-08-29 09:28:01 +00:00
|
|
|
if ((*load_functions[j].plugin_init)(p)) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "%s plugin init failed", module);
|
2015-08-29 09:28:01 +00:00
|
|
|
plugin_free(p);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
plugins_register(srv, p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!load_functions[j].name) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "%s plugin not found", module);
|
2015-08-29 09:28:01 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-03 12:53:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2015-08-29 09:28:01 +00:00
|
|
|
#else /* defined(LIGHTTPD_STATIC) */
|
2005-02-20 14:27:00 +00:00
|
|
|
int plugins_load(server *srv) {
|
2019-12-08 05:28:21 +00:00
|
|
|
buffer * const tb = srv->tmp_buf;
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin *p;
|
|
|
|
int (*init)(plugin *pl);
|
2010-08-05 22:55:18 +00:00
|
|
|
size_t i, j;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
for (i = 0; i < srv->srvconf.modules->used; i++) {
|
2019-10-13 08:59:57 +00:00
|
|
|
data_string *ds = (data_string *)srv->srvconf.modules->data[i];
|
|
|
|
char *module = ds->value.ptr;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2010-08-05 22:55:18 +00:00
|
|
|
for (j = 0; j < i; j++) {
|
2019-10-13 08:59:57 +00:00
|
|
|
if (buffer_is_equal(&ds->value, &((data_string *) srv->srvconf.modules->data[j])->value)) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
|
|
|
"Cannot load plugin %s "
|
|
|
|
"more than once, please fix your config (lighttpd may not accept such configs in future releases)",
|
|
|
|
ds->value.ptr);
|
2010-08-11 21:10:15 +00:00
|
|
|
continue;
|
2010-08-05 22:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-08 05:28:21 +00:00
|
|
|
buffer_copy_buffer(tb, srv->srvconf.modules_dir);
|
2005-08-29 14:11:47 +00:00
|
|
|
|
2019-12-08 05:28:21 +00:00
|
|
|
buffer_append_string_len(tb, CONST_STR_LEN("/"));
|
|
|
|
buffer_append_string(tb, module);
|
2005-02-20 14:27:00 +00:00
|
|
|
#if defined(__WIN32) || defined(__CYGWIN__)
|
2019-12-08 05:28:21 +00:00
|
|
|
buffer_append_string_len(tb, CONST_STR_LEN(".dll"));
|
2005-02-20 14:27:00 +00:00
|
|
|
#else
|
2019-12-08 05:28:21 +00:00
|
|
|
buffer_append_string_len(tb, CONST_STR_LEN(".so"));
|
2005-02-20 14:27:00 +00:00
|
|
|
#endif
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
p = plugin_init();
|
|
|
|
#ifdef __WIN32
|
2019-12-08 05:28:21 +00:00
|
|
|
if (NULL == (p->lib = LoadLibrary(tb->ptr))) {
|
2005-02-20 14:27:00 +00:00
|
|
|
LPVOID lpMsgBuf;
|
|
|
|
FormatMessage(
|
2015-08-29 09:28:01 +00:00
|
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
|
NULL,
|
|
|
|
GetLastError(),
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPTSTR) &lpMsgBuf,
|
|
|
|
0, NULL);
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
2019-12-08 05:28:21 +00:00
|
|
|
"LoadLibrary() failed %s %s", lpMsgBuf, tb->ptr);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin_free(p);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
#else
|
2019-12-08 05:28:21 +00:00
|
|
|
if (NULL == (p->lib = dlopen(tb->ptr, RTLD_NOW|RTLD_GLOBAL))) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
2019-12-08 05:28:21 +00:00
|
|
|
"dlopen() failed for: %s %s", tb->ptr, dlerror());
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin_free(p);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
#endif
|
2019-12-08 05:28:21 +00:00
|
|
|
buffer_copy_string(tb, module);
|
|
|
|
buffer_append_string_len(tb, CONST_STR_LEN("_plugin_init"));
|
2005-02-20 14:27:00 +00:00
|
|
|
|
|
|
|
#ifdef __WIN32
|
2019-12-08 05:28:21 +00:00
|
|
|
init = GetProcAddress(p->lib, tb->ptr);
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2015-08-29 09:28:01 +00:00
|
|
|
if (init == NULL) {
|
2005-02-20 14:27:00 +00:00
|
|
|
LPVOID lpMsgBuf;
|
|
|
|
FormatMessage(
|
2015-08-29 09:28:01 +00:00
|
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
|
NULL,
|
|
|
|
GetLastError(),
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPTSTR) &lpMsgBuf,
|
|
|
|
0, NULL);
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
2019-12-08 05:28:21 +00:00
|
|
|
"getprocaddress failed: %s %s", tb->ptr, lpMsgBuf);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin_free(p);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2005-11-11 12:53:45 +00:00
|
|
|
#else
|
|
|
|
#if 1
|
2019-12-08 05:28:21 +00:00
|
|
|
init = (int (*)(plugin *))(intptr_t)dlsym(p->lib, tb->ptr);
|
2005-02-20 14:27:00 +00:00
|
|
|
#else
|
2019-12-08 05:28:21 +00:00
|
|
|
*(void **)(&init) = dlsym(p->lib, tb->ptr);
|
2005-11-11 12:53:45 +00:00
|
|
|
#endif
|
2016-06-29 12:20:12 +00:00
|
|
|
if (NULL == init) {
|
|
|
|
const char *error = dlerror();
|
|
|
|
if (error != NULL) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "dlsym: %s", error);
|
2016-06-29 12:20:12 +00:00
|
|
|
} else {
|
2019-12-08 05:28:21 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "dlsym symbol not found: %s", tb->ptr);
|
2016-06-29 12:20:12 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin_free(p);
|
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
#endif
|
|
|
|
if ((*init)(p)) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "%s plugin init failed", module);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin_free(p);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#if 0
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "%s plugin loaded", module);
|
2005-02-20 14:27:00 +00:00
|
|
|
#endif
|
|
|
|
plugins_register(srv, p);
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2015-08-29 09:28:01 +00:00
|
|
|
#endif /* defined(LIGHTTPD_STATIC) */
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2019-10-19 06:21:46 +00:00
|
|
|
typedef struct {
|
|
|
|
handler_t(*fn)();
|
2019-10-22 02:49:59 +00:00
|
|
|
plugin_data_base *data;
|
2019-10-19 06:21:46 +00:00
|
|
|
} plugin_fn_data;
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
__attribute_hot__
|
|
|
|
static handler_t plugins_call_fn_req_data(request_st * const r, const int e) {
|
|
|
|
const void * const plugin_slots = r->con->plugin_slots;
|
|
|
|
const uint32_t offset = ((const uint16_t *)plugin_slots)[e];
|
|
|
|
if (0 == offset) return HANDLER_GO_ON;
|
|
|
|
const plugin_fn_data *plfd = (const plugin_fn_data *)
|
|
|
|
(((uintptr_t)plugin_slots) + offset);
|
|
|
|
handler_t rc = HANDLER_GO_ON;
|
|
|
|
while (plfd->fn && (rc = plfd->fn(r, plfd->data)) == HANDLER_GO_ON)
|
|
|
|
++plfd;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-10-19 06:21:46 +00:00
|
|
|
__attribute_hot__
|
2019-11-26 07:13:05 +00:00
|
|
|
static handler_t plugins_call_fn_con_data(connection * const con, const int e) {
|
|
|
|
const void * const plugin_slots = con->plugin_slots;
|
|
|
|
const uint32_t offset = ((const uint16_t *)plugin_slots)[e];
|
2019-10-19 06:21:46 +00:00
|
|
|
if (0 == offset) return HANDLER_GO_ON;
|
|
|
|
const plugin_fn_data *plfd = (const plugin_fn_data *)
|
2019-11-26 07:13:05 +00:00
|
|
|
(((uintptr_t)plugin_slots) + offset);
|
2019-10-19 06:21:46 +00:00
|
|
|
handler_t rc = HANDLER_GO_ON;
|
2019-11-26 07:13:05 +00:00
|
|
|
while (plfd->fn && (rc = plfd->fn(con, plfd->data)) == HANDLER_GO_ON)
|
2019-10-19 06:21:46 +00:00
|
|
|
++plfd;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static handler_t plugins_call_fn_srv_data(server * const srv, const int e) {
|
|
|
|
const uint32_t offset = ((const uint16_t *)srv->plugin_slots)[e];
|
|
|
|
if (0 == offset) return HANDLER_GO_ON;
|
|
|
|
const plugin_fn_data *plfd = (const plugin_fn_data *)
|
|
|
|
(((uintptr_t)srv->plugin_slots) + offset);
|
|
|
|
handler_t rc = HANDLER_GO_ON;
|
|
|
|
while (plfd->fn && (rc = plfd->fn(srv,plfd->data)) == HANDLER_GO_ON)
|
|
|
|
++plfd;
|
|
|
|
return rc;
|
|
|
|
}
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2019-11-20 01:12:31 +00:00
|
|
|
static void plugins_call_fn_srv_data_all(server * const srv, const int e) {
|
|
|
|
const uint32_t offset = ((const uint16_t *)srv->plugin_slots)[e];
|
|
|
|
if (0 == offset) return;
|
|
|
|
const plugin_fn_data *plfd = (const plugin_fn_data *)
|
|
|
|
(((uintptr_t)srv->plugin_slots) + offset);
|
|
|
|
for (; plfd->fn; ++plfd)
|
|
|
|
plfd->fn(srv, plfd->data);
|
|
|
|
}
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
/**
|
2006-10-04 13:26:23 +00:00
|
|
|
* plugins that use
|
|
|
|
*
|
2020-01-13 02:51:12 +00:00
|
|
|
* - request_st *r
|
|
|
|
* - void *p_d (plugin_data *)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define PLUGIN_CALL_FN_REQ_DATA(x, y) \
|
|
|
|
handler_t plugins_call_##y(request_st * const r) {\
|
|
|
|
return plugins_call_fn_req_data(r, x); \
|
|
|
|
}
|
|
|
|
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_REQUEST_ENV, handle_request_env)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_RESPONSE_START, handle_response_start)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
|
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
|
2020-07-25 12:23:58 +00:00
|
|
|
PLUGIN_CALL_FN_REQ_DATA(PLUGIN_FUNC_CONNECTION_RESET, handle_request_reset)
|
2020-01-13 02:51:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* plugins that use
|
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
* - connection *con
|
|
|
|
* - void *p_d (plugin_data *)
|
|
|
|
*/
|
|
|
|
|
2019-11-26 07:13:05 +00:00
|
|
|
#define PLUGIN_CALL_FN_CON_DATA(x, y) \
|
|
|
|
handler_t plugins_call_##y(connection *con) {\
|
|
|
|
return plugins_call_fn_con_data(con, x); \
|
2019-10-19 06:21:46 +00:00
|
|
|
}
|
|
|
|
|
2019-11-26 07:13:05 +00:00
|
|
|
PLUGIN_CALL_FN_CON_DATA(PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT, handle_connection_accept)
|
|
|
|
PLUGIN_CALL_FN_CON_DATA(PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR, handle_connection_shut_wr)
|
|
|
|
PLUGIN_CALL_FN_CON_DATA(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
|
2019-10-19 06:21:46 +00:00
|
|
|
|
|
|
|
#undef PLUGIN_CALL_FN_SRV_CON_DATA
|
2005-02-20 14:27:00 +00:00
|
|
|
|
|
|
|
/**
|
2006-10-04 13:26:23 +00:00
|
|
|
* plugins that use
|
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
* - server *srv
|
|
|
|
* - void *p_d (plugin_data *)
|
|
|
|
*/
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-11-20 01:12:31 +00:00
|
|
|
handler_t plugins_call_set_defaults(server *srv) {
|
|
|
|
return plugins_call_fn_srv_data(srv, PLUGIN_FUNC_SET_DEFAULTS);
|
|
|
|
}
|
2019-10-19 06:21:46 +00:00
|
|
|
|
2019-11-20 01:12:31 +00:00
|
|
|
handler_t plugins_call_worker_init(server *srv) {
|
|
|
|
return plugins_call_fn_srv_data(srv, PLUGIN_FUNC_WORKER_INIT);
|
|
|
|
}
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2019-11-20 01:12:31 +00:00
|
|
|
void plugins_call_handle_trigger(server *srv) {
|
|
|
|
plugins_call_fn_srv_data_all(srv, PLUGIN_FUNC_HANDLE_TRIGGER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plugins_call_handle_sighup(server *srv) {
|
|
|
|
plugins_call_fn_srv_data_all(srv, PLUGIN_FUNC_HANDLE_SIGHUP);
|
|
|
|
}
|
2005-02-20 14:27:00 +00:00
|
|
|
|
2017-09-10 19:28:51 +00:00
|
|
|
handler_t plugins_call_handle_waitpid(server *srv, pid_t pid, int status) {
|
2019-10-19 06:21:46 +00:00
|
|
|
const uint32_t offset =
|
|
|
|
((const uint16_t *)srv->plugin_slots)[PLUGIN_FUNC_HANDLE_WAITPID];
|
|
|
|
if (0 == offset) return HANDLER_GO_ON;
|
|
|
|
const plugin_fn_data *plfd = (const plugin_fn_data *)
|
|
|
|
(((uintptr_t)srv->plugin_slots) + offset);
|
|
|
|
handler_t rc = HANDLER_GO_ON;
|
|
|
|
while (plfd->fn&&(rc=plfd->fn(srv,plfd->data,pid,status))==HANDLER_GO_ON)
|
|
|
|
++plfd;
|
|
|
|
return rc;
|
2017-09-10 19:28:51 +00:00
|
|
|
}
|
|
|
|
|
2019-11-19 08:39:40 +00:00
|
|
|
static void plugins_call_cleanup(server * const srv) {
|
|
|
|
plugin ** const ps = srv->plugins.ptr;
|
|
|
|
for (uint32_t i = 0; i < srv->plugins.used; ++i) {
|
|
|
|
plugin *p = ps[i];
|
|
|
|
if (NULL == p) continue;
|
|
|
|
if (NULL != p->data) {
|
|
|
|
plugin_data_base *pd = p->data;
|
|
|
|
if (p->cleanup)
|
|
|
|
p->cleanup(p->data);
|
|
|
|
free(pd->cvlist);
|
|
|
|
free(pd);
|
|
|
|
p->data = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
/**
|
2006-10-04 13:26:23 +00:00
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
* - call init function of all plugins to init the plugin-internals
|
|
|
|
* - added each plugin that supports has callback to the corresponding slot
|
2006-10-04 13:26:23 +00:00
|
|
|
*
|
2005-02-20 14:27:00 +00:00
|
|
|
* - is only called once.
|
|
|
|
*/
|
|
|
|
|
2019-10-19 06:21:46 +00:00
|
|
|
__attribute_cold__
|
|
|
|
static void plugins_call_init_slot(server *srv, handler_t(*fn)(), void *data, const uint32_t offset) {
|
|
|
|
if (fn) {
|
|
|
|
plugin_fn_data *plfd = (plugin_fn_data *)
|
|
|
|
(((uintptr_t)srv->plugin_slots) + offset);
|
|
|
|
while (plfd->fn) ++plfd;
|
|
|
|
plfd->fn = fn;
|
|
|
|
plfd->data = data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
handler_t plugins_call_init(server *srv) {
|
2019-10-04 06:10:02 +00:00
|
|
|
plugin ** const ps = srv->plugins.ptr;
|
2019-10-19 06:21:46 +00:00
|
|
|
uint16_t offsets[PLUGIN_FUNC_SIZEOF];
|
|
|
|
memset(offsets, 0, sizeof(offsets));
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-10-04 06:10:02 +00:00
|
|
|
for (uint32_t i = 0; i < srv->plugins.used; ++i) {
|
2005-02-20 14:27:00 +00:00
|
|
|
/* check which calls are supported */
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
plugin *p = ps[i];
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (p->init) {
|
|
|
|
if (NULL == (p->data = p->init())) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
|
|
|
"plugin-init failed for module %s", p->name);
|
2005-02-20 14:27:00 +00:00
|
|
|
return HANDLER_ERROR;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2020-01-11 04:12:08 +00:00
|
|
|
((plugin_data_base *)(p->data))->self = p;
|
2019-10-22 02:49:59 +00:00
|
|
|
((plugin_data_base *)(p->data))->id = i + 1;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (p->version != LIGHTTPD_VERSION_ID) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(srv->errh, __FILE__, __LINE__,
|
|
|
|
"plugin-version doesn't match lighttpd-version for %s", p->name);
|
2005-02-20 14:27:00 +00:00
|
|
|
return HANDLER_ERROR;
|
|
|
|
}
|
|
|
|
}
|
2017-05-22 01:26:58 +00:00
|
|
|
|
|
|
|
if (p->priv_defaults && HANDLER_ERROR==p->priv_defaults(srv, p->data)) {
|
|
|
|
return HANDLER_ERROR;
|
|
|
|
}
|
2019-10-19 06:21:46 +00:00
|
|
|
|
|
|
|
if (p->handle_uri_clean)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_URI_CLEAN];
|
|
|
|
if (p->handle_uri_raw)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_URI_RAW];
|
|
|
|
if (p->handle_request_env)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_REQUEST_ENV];
|
|
|
|
if (p->handle_request_done)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_REQUEST_DONE];
|
|
|
|
if (p->handle_connection_accept)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT];
|
|
|
|
if (p->handle_connection_shut_wr)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR];
|
|
|
|
if (p->handle_connection_close)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE];
|
|
|
|
if (p->handle_trigger)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_TRIGGER];
|
|
|
|
if (p->handle_sighup)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_SIGHUP];
|
|
|
|
if (p->handle_waitpid)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_WAITPID];
|
|
|
|
if (p->handle_subrequest_start)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_SUBREQUEST_START];
|
|
|
|
if (p->handle_response_start)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_RESPONSE_START];
|
|
|
|
if (p->handle_docroot)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_DOCROOT];
|
|
|
|
if (p->handle_physical)
|
|
|
|
++offsets[PLUGIN_FUNC_HANDLE_PHYSICAL];
|
2020-07-25 12:23:58 +00:00
|
|
|
if (p->handle_request_reset)
|
2019-10-19 06:21:46 +00:00
|
|
|
++offsets[PLUGIN_FUNC_CONNECTION_RESET];
|
|
|
|
if (p->set_defaults)
|
|
|
|
++offsets[PLUGIN_FUNC_SET_DEFAULTS];
|
|
|
|
if (p->worker_init)
|
|
|
|
++offsets[PLUGIN_FUNC_WORKER_INIT];
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t nslots =
|
|
|
|
(sizeof(offsets)+sizeof(plugin_fn_data)-1) / sizeof(plugin_fn_data);
|
|
|
|
for (uint32_t i = 0; i < PLUGIN_FUNC_SIZEOF; ++i) {
|
|
|
|
if (offsets[i]) {
|
|
|
|
uint32_t offset = nslots;
|
|
|
|
nslots += offsets[i]+1; /* +1 to mark end of each list */
|
|
|
|
force_assert(offset * sizeof(plugin_fn_data) <= USHRT_MAX);
|
|
|
|
offsets[i] = (uint16_t)(offset * sizeof(plugin_fn_data));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate and fill slots of two dimensional array */
|
|
|
|
srv->plugin_slots = calloc(nslots, sizeof(plugin_fn_data));
|
|
|
|
force_assert(NULL != srv->plugin_slots);
|
|
|
|
memcpy(srv->plugin_slots, offsets, sizeof(offsets));
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < srv->plugins.used; ++i) {
|
|
|
|
plugin * const p = ps[i];
|
|
|
|
|
|
|
|
plugins_call_init_slot(srv, p->handle_uri_clean, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_URI_CLEAN]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_uri_raw, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_URI_RAW]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_request_env, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_REQUEST_ENV]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_request_done, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_REQUEST_DONE]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_connection_accept, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_connection_shut_wr, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_connection_close, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_trigger, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_TRIGGER]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_sighup, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_SIGHUP]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_waitpid, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_WAITPID]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_subrequest_start, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_SUBREQUEST_START]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_response_start, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_RESPONSE_START]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_docroot, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_DOCROOT]);
|
|
|
|
plugins_call_init_slot(srv, p->handle_physical, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_HANDLE_PHYSICAL]);
|
2020-07-25 12:23:58 +00:00
|
|
|
plugins_call_init_slot(srv, p->handle_request_reset, p->data,
|
2019-10-19 06:21:46 +00:00
|
|
|
offsets[PLUGIN_FUNC_CONNECTION_RESET]);
|
|
|
|
plugins_call_init_slot(srv, p->set_defaults, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_SET_DEFAULTS]);
|
|
|
|
plugins_call_init_slot(srv, p->worker_init, p->data,
|
|
|
|
offsets[PLUGIN_FUNC_WORKER_INIT]);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plugins_free(server *srv) {
|
2019-10-04 06:10:02 +00:00
|
|
|
if (srv->plugin_slots) {
|
|
|
|
plugins_call_cleanup(srv);
|
|
|
|
free(srv->plugin_slots);
|
|
|
|
srv->plugin_slots = NULL;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-10-04 06:10:02 +00:00
|
|
|
for (uint32_t i = 0; i < srv->plugins.used; ++i) {
|
2019-10-19 06:21:46 +00:00
|
|
|
plugin_free(((plugin **)srv->plugins.ptr)[i]);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
free(srv->plugins.ptr);
|
|
|
|
srv->plugins.ptr = NULL;
|
2005-09-03 03:08:13 +00:00
|
|
|
srv->plugins.used = 0;
|
2019-10-04 06:10:02 +00:00
|
|
|
srv->plugins.size = 0;
|
2019-11-28 15:27:01 +00:00
|
|
|
array_free_data(&plugin_stats);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|