xref: /lighttpd1.4/src/plugin.c (revision e2de4e58)
18abd06a7SGlenn Strauss #include "first.h"
28abd06a7SGlenn Strauss 
322e8b456SStefan Bühler #include "plugin.h"
404d76e7aSGlenn Strauss #include "base.h"
522e8b456SStefan Bühler #include "log.h"
622e8b456SStefan Bühler 
7bcdc6a3bSJan Kneschke #include <string.h>
8bcdc6a3bSJan Kneschke #include <stdlib.h>
9bcdc6a3bSJan Kneschke 
10bcdc6a3bSJan Kneschke #ifdef HAVE_VALGRIND_VALGRIND_H
11bcdc6a3bSJan Kneschke # include <valgrind/valgrind.h>
12bcdc6a3bSJan Kneschke #endif
13bcdc6a3bSJan Kneschke 
1402594f10SStefan Bühler #if !defined(__WIN32) && !defined(LIGHTTPD_STATIC)
15bcdc6a3bSJan Kneschke # include <dlfcn.h>
16bcdc6a3bSJan Kneschke #endif
17bcdc6a3bSJan Kneschke /*
18bcdc6a3bSJan Kneschke  *
19bcdc6a3bSJan Kneschke  * if you change this enum to add a new callback, be sure
20bcdc6a3bSJan Kneschke  * - that PLUGIN_FUNC_SIZEOF is the last entry
21bcdc6a3bSJan Kneschke  * - that you add PLUGIN_TO_SLOT twice:
22bcdc6a3bSJan Kneschke  *   1. as callback-dispatcher
23bcdc6a3bSJan Kneschke  *   2. in plugins_call_init()
24bcdc6a3bSJan Kneschke  *
25bcdc6a3bSJan Kneschke  */
26bcdc6a3bSJan Kneschke 
27bcdc6a3bSJan Kneschke typedef struct {
28bcdc6a3bSJan Kneschke 	PLUGIN_DATA;
29bcdc6a3bSJan Kneschke } plugin_data;
30bcdc6a3bSJan Kneschke 
31bcdc6a3bSJan Kneschke typedef enum {
32bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_UNSET,
33b66fa2cbSStefan Bühler 
34bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_URI_CLEAN,
35bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_URI_RAW,
36cb7ed136SGlenn Strauss 	PLUGIN_FUNC_HANDLE_REQUEST_ENV,
37bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_REQUEST_DONE,
38cb7ed136SGlenn Strauss 	PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT,
39cb7ed136SGlenn Strauss 	PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR,
40bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
41bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_TRIGGER,
42bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_SIGHUP,
439030cfaeSGlenn Strauss 	PLUGIN_FUNC_HANDLE_WAITPID,
44bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_SUBREQUEST,
45bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
46cb1a3c62SGlenn Strauss 	PLUGIN_FUNC_HANDLE_RESPONSE_START,
47bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_HANDLE_DOCROOT,
486adaad54SJan Kneschke 	PLUGIN_FUNC_HANDLE_PHYSICAL,
49bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_CONNECTION_RESET,
50bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_INIT,
51bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_CLEANUP,
52bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_SET_DEFAULTS,
53f1e9bcb0SGlenn Strauss 	PLUGIN_FUNC_WORKER_INIT,
54bcdc6a3bSJan Kneschke 
55bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_SIZEOF
56bcdc6a3bSJan Kneschke } plugin_t;
57bcdc6a3bSJan Kneschke 
58bcdc6a3bSJan Kneschke static plugin *plugin_init(void) {
59bcdc6a3bSJan Kneschke 	plugin *p;
60bcdc6a3bSJan Kneschke 
61bcdc6a3bSJan Kneschke 	p = calloc(1, sizeof(*p));
62566cf8deSStefan Bühler 	force_assert(NULL != p);
63bcdc6a3bSJan Kneschke 
64bcdc6a3bSJan Kneschke 	return p;
65bcdc6a3bSJan Kneschke }
66bcdc6a3bSJan Kneschke 
67bcdc6a3bSJan Kneschke static void plugin_free(plugin *p) {
68b66fa2cbSStefan Bühler   #if !defined(LIGHTTPD_STATIC)
69*e2de4e58SGlenn Strauss     if (p->lib) {
70*e2de4e58SGlenn Strauss      #if defined(HAVE_VALGRIND_VALGRIND_H)
71*e2de4e58SGlenn Strauss      /*if (!RUNNING_ON_VALGRIND) */
72b66fa2cbSStefan Bühler      #endif
73b66fa2cbSStefan Bühler       #if defined(__WIN32)
74*e2de4e58SGlenn Strauss         FreeLibrary(p->lib);
75bcdc6a3bSJan Kneschke       #else
76bcdc6a3bSJan Kneschke         dlclose(p->lib);
77bcdc6a3bSJan Kneschke       #endif
78bcdc6a3bSJan Kneschke     }
794c91a14cSJan Kneschke   #endif
80bcdc6a3bSJan Kneschke 
81bcdc6a3bSJan Kneschke     free(p);
82bcdc6a3bSJan Kneschke }
83bcdc6a3bSJan Kneschke 
84bcdc6a3bSJan Kneschke static int plugins_register(server *srv, plugin *p) {
85bcdc6a3bSJan Kneschke 	plugin **ps;
86d28bac32SGlenn Strauss 	if (srv->plugins.used == srv->plugins.size) {
87bcdc6a3bSJan Kneschke 		srv->plugins.size += 4;
88bcdc6a3bSJan Kneschke 		srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
89566cf8deSStefan Bühler 		force_assert(NULL != srv->plugins.ptr);
90bcdc6a3bSJan Kneschke 	}
91bcdc6a3bSJan Kneschke 
92bcdc6a3bSJan Kneschke 	ps = srv->plugins.ptr;
93bcdc6a3bSJan Kneschke 	ps[srv->plugins.used++] = p;
94bcdc6a3bSJan Kneschke 
95bcdc6a3bSJan Kneschke 	return 0;
96bcdc6a3bSJan Kneschke }
97bcdc6a3bSJan Kneschke 
98bcdc6a3bSJan Kneschke /**
99bcdc6a3bSJan Kneschke  *
100bcdc6a3bSJan Kneschke  *
101bcdc6a3bSJan Kneschke  *
102bcdc6a3bSJan Kneschke  */
103bcdc6a3bSJan Kneschke 
104b66fa2cbSStefan Bühler #if defined(LIGHTTPD_STATIC)
105b66fa2cbSStefan Bühler 
106b66fa2cbSStefan Bühler /* pre-declare functions, as there is no header for them */
1074c91a14cSJan Kneschke #define PLUGIN_INIT(x)\
108b66fa2cbSStefan Bühler 	int x ## _plugin_init(plugin *p);
109bcdc6a3bSJan Kneschke 
110a5e280fdSJan Kneschke #include "plugin-static.h"
1114c91a14cSJan Kneschke 
112b66fa2cbSStefan Bühler #undef PLUGIN_INIT
113b66fa2cbSStefan Bühler 
114b66fa2cbSStefan Bühler /* build NULL-terminated table of name + init-function */
115b66fa2cbSStefan Bühler 
116b66fa2cbSStefan Bühler typedef struct {
117b66fa2cbSStefan Bühler 	const char* name;
118b66fa2cbSStefan Bühler 	int (*plugin_init)(plugin *p);
119b66fa2cbSStefan Bühler } plugin_load_functions;
120b66fa2cbSStefan Bühler 
121b66fa2cbSStefan Bühler static const plugin_load_functions load_functions[] = {
122b66fa2cbSStefan Bühler #define PLUGIN_INIT(x) \
123b66fa2cbSStefan Bühler 	{ #x, &x ## _plugin_init },
124b66fa2cbSStefan Bühler 
125b66fa2cbSStefan Bühler #include "plugin-static.h"
126b66fa2cbSStefan Bühler 
127b66fa2cbSStefan Bühler 	{ NULL, NULL }
128b66fa2cbSStefan Bühler #undef PLUGIN_INIT
129b66fa2cbSStefan Bühler };
130b66fa2cbSStefan Bühler 
131b66fa2cbSStefan Bühler int plugins_load(server *srv) {
132b66fa2cbSStefan Bühler 	plugin *p;
133b66fa2cbSStefan Bühler 	size_t i, j;
134b66fa2cbSStefan Bühler 
135b66fa2cbSStefan Bühler 	for (i = 0; i < srv->srvconf.modules->used; i++) {
136601c572cSGlenn Strauss 		data_string *ds = (data_string *)srv->srvconf.modules->data[i];
137601c572cSGlenn Strauss 		char *module = ds->value.ptr;
138b66fa2cbSStefan Bühler 
139b66fa2cbSStefan Bühler 		for (j = 0; j < i; j++) {
140601c572cSGlenn Strauss 			if (buffer_is_equal(&ds->value, &((data_string *) srv->srvconf.modules->data[j])->value)) {
141b66fa2cbSStefan Bühler 				log_error_write(srv, __FILE__, __LINE__, "sbs",
142601c572cSGlenn Strauss 					"Cannot load plugin", &ds->value,
143b66fa2cbSStefan Bühler 					"more than once, please fix your config (lighttpd may not accept such configs in future releases)");
144b66fa2cbSStefan Bühler 				continue;
145b66fa2cbSStefan Bühler 			}
146b66fa2cbSStefan Bühler 		}
147b66fa2cbSStefan Bühler 
148b66fa2cbSStefan Bühler 		for (j = 0; load_functions[j].name; ++j) {
149b66fa2cbSStefan Bühler 			if (0 == strcmp(load_functions[j].name, module)) {
150b66fa2cbSStefan Bühler 				p = plugin_init();
151b66fa2cbSStefan Bühler 				if ((*load_functions[j].plugin_init)(p)) {
152b66fa2cbSStefan Bühler 					log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin init failed" );
153b66fa2cbSStefan Bühler 					plugin_free(p);
154b66fa2cbSStefan Bühler 					return -1;
155b66fa2cbSStefan Bühler 				}
156b66fa2cbSStefan Bühler 				plugins_register(srv, p);
157b66fa2cbSStefan Bühler 				break;
158b66fa2cbSStefan Bühler 			}
159b66fa2cbSStefan Bühler 		}
160b66fa2cbSStefan Bühler 		if (!load_functions[j].name) {
161b66fa2cbSStefan Bühler 			log_error_write(srv, __FILE__, __LINE__, "ss", module, " plugin not found" );
162b66fa2cbSStefan Bühler 			return -1;
163b66fa2cbSStefan Bühler 		}
164b66fa2cbSStefan Bühler 	}
165b66fa2cbSStefan Bühler 
1664c91a14cSJan Kneschke 	return 0;
1674c91a14cSJan Kneschke }
168b66fa2cbSStefan Bühler #else /* defined(LIGHTTPD_STATIC) */
169bcdc6a3bSJan Kneschke int plugins_load(server *srv) {
170bcdc6a3bSJan Kneschke 	plugin *p;
171bcdc6a3bSJan Kneschke 	int (*init)(plugin *pl);
172614bb753SStefan Bühler 	size_t i, j;
173bcdc6a3bSJan Kneschke 
174bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->srvconf.modules->used; i++) {
175601c572cSGlenn Strauss 		data_string *ds = (data_string *)srv->srvconf.modules->data[i];
176601c572cSGlenn Strauss 		char *module = ds->value.ptr;
177bcdc6a3bSJan Kneschke 
178614bb753SStefan Bühler 		for (j = 0; j < i; j++) {
179601c572cSGlenn Strauss 			if (buffer_is_equal(&ds->value, &((data_string *) srv->srvconf.modules->data[j])->value)) {
180b66fa2cbSStefan Bühler 				log_error_write(srv, __FILE__, __LINE__, "sbs",
181601c572cSGlenn Strauss 					"Cannot load plugin", &ds->value,
182b66fa2cbSStefan Bühler 					"more than once, please fix your config (lighttpd may not accept such configs in future releases)");
1836e724c05SStefan Bühler 				continue;
184614bb753SStefan Bühler 			}
185614bb753SStefan Bühler 		}
186614bb753SStefan Bühler 
1876afad87dSStefan Bühler 		buffer_copy_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
18815dc40cdSJan Kneschke 
18952861d77SStefan Bühler 		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("/"));
190b66fa2cbSStefan Bühler 		buffer_append_string(srv->tmp_buf, module);
191bcdc6a3bSJan Kneschke #if defined(__WIN32) || defined(__CYGWIN__)
19252861d77SStefan Bühler 		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".dll"));
193bcdc6a3bSJan Kneschke #else
19452861d77SStefan Bühler 		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".so"));
195bcdc6a3bSJan Kneschke #endif
196bcdc6a3bSJan Kneschke 
197bcdc6a3bSJan Kneschke 		p = plugin_init();
198bcdc6a3bSJan Kneschke #ifdef __WIN32
199bcdc6a3bSJan Kneschke 		if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
200bcdc6a3bSJan Kneschke 			LPVOID lpMsgBuf;
201bcdc6a3bSJan Kneschke 			FormatMessage(
202bcdc6a3bSJan Kneschke 				FORMAT_MESSAGE_ALLOCATE_BUFFER |
203bcdc6a3bSJan Kneschke 					FORMAT_MESSAGE_FROM_SYSTEM,
204bcdc6a3bSJan Kneschke 				NULL,
205bcdc6a3bSJan Kneschke 				GetLastError(),
206bcdc6a3bSJan Kneschke 				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
207bcdc6a3bSJan Kneschke 				(LPTSTR) &lpMsgBuf,
208bcdc6a3bSJan Kneschke 				0, NULL);
209bcdc6a3bSJan Kneschke 
210bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
211bcdc6a3bSJan Kneschke 				lpMsgBuf, srv->tmp_buf);
212bcdc6a3bSJan Kneschke 
213bcdc6a3bSJan Kneschke 			plugin_free(p);
214bcdc6a3bSJan Kneschke 
215bcdc6a3bSJan Kneschke 			return -1;
216bcdc6a3bSJan Kneschke 
217bcdc6a3bSJan Kneschke 		}
218bcdc6a3bSJan Kneschke #else
21953ab644eSMarcus Rückert 		if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) {
2206b5c314cSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
2216b5c314cSJan Kneschke 				srv->tmp_buf, dlerror());
222bcdc6a3bSJan Kneschke 
223bcdc6a3bSJan Kneschke 			plugin_free(p);
224bcdc6a3bSJan Kneschke 
225bcdc6a3bSJan Kneschke 			return -1;
226bcdc6a3bSJan Kneschke 		}
227bcdc6a3bSJan Kneschke 
228bcdc6a3bSJan Kneschke #endif
229b66fa2cbSStefan Bühler 		buffer_copy_string(srv->tmp_buf, module);
23052861d77SStefan Bühler 		buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("_plugin_init"));
231bcdc6a3bSJan Kneschke 
232bcdc6a3bSJan Kneschke #ifdef __WIN32
233bcdc6a3bSJan Kneschke 		init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
234bcdc6a3bSJan Kneschke 
235bcdc6a3bSJan Kneschke 		if (init == NULL) {
236bcdc6a3bSJan Kneschke 			LPVOID lpMsgBuf;
237bcdc6a3bSJan Kneschke 			FormatMessage(
238bcdc6a3bSJan Kneschke 				FORMAT_MESSAGE_ALLOCATE_BUFFER |
239bcdc6a3bSJan Kneschke 					FORMAT_MESSAGE_FROM_SYSTEM,
240bcdc6a3bSJan Kneschke 				NULL,
241bcdc6a3bSJan Kneschke 				GetLastError(),
242bcdc6a3bSJan Kneschke 				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
243bcdc6a3bSJan Kneschke 				(LPTSTR) &lpMsgBuf,
244bcdc6a3bSJan Kneschke 				0, NULL);
245bcdc6a3bSJan Kneschke 
246bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
247bcdc6a3bSJan Kneschke 
248bcdc6a3bSJan Kneschke 			plugin_free(p);
249bcdc6a3bSJan Kneschke 			return -1;
250bcdc6a3bSJan Kneschke 		}
251bcdc6a3bSJan Kneschke 
252bcdc6a3bSJan Kneschke #else
2530ed6b729SJan Kneschke #if 1
2545a9992b1SStefan Bühler 		init = (int (*)(plugin *))(intptr_t)dlsym(p->lib, srv->tmp_buf->ptr);
2550ed6b729SJan Kneschke #else
256bcdc6a3bSJan Kneschke 		*(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr);
2570ed6b729SJan Kneschke #endif
258eefb94bbSGlenn Strauss 		if (NULL == init) {
259eefb94bbSGlenn Strauss 			const char *error = dlerror();
260eefb94bbSGlenn Strauss 			if (error != NULL) {
261eefb94bbSGlenn Strauss 				log_error_write(srv, __FILE__, __LINE__, "ss", "dlsym:", error);
262eefb94bbSGlenn Strauss 			} else {
263eefb94bbSGlenn Strauss 				log_error_write(srv, __FILE__, __LINE__, "ss", "dlsym symbol not found:", srv->tmp_buf->ptr);
264eefb94bbSGlenn Strauss 			}
265bcdc6a3bSJan Kneschke 
266bcdc6a3bSJan Kneschke 			plugin_free(p);
267bcdc6a3bSJan Kneschke 			return -1;
268bcdc6a3bSJan Kneschke 		}
269bcdc6a3bSJan Kneschke 
270bcdc6a3bSJan Kneschke #endif
271bcdc6a3bSJan Kneschke 		if ((*init)(p)) {
272b66fa2cbSStefan Bühler 			log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin init failed" );
273bcdc6a3bSJan Kneschke 
274bcdc6a3bSJan Kneschke 			plugin_free(p);
275bcdc6a3bSJan Kneschke 			return -1;
276bcdc6a3bSJan Kneschke 		}
277bcdc6a3bSJan Kneschke #if 0
278b66fa2cbSStefan Bühler 		log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin loaded" );
279bcdc6a3bSJan Kneschke #endif
280bcdc6a3bSJan Kneschke 		plugins_register(srv, p);
281bcdc6a3bSJan Kneschke 	}
282bcdc6a3bSJan Kneschke 
283bcdc6a3bSJan Kneschke 	return 0;
284bcdc6a3bSJan Kneschke }
285b66fa2cbSStefan Bühler #endif /* defined(LIGHTTPD_STATIC) */
286bcdc6a3bSJan Kneschke 
287bcdc6a3bSJan Kneschke #define PLUGIN_TO_SLOT(x, y) \
288bcdc6a3bSJan Kneschke 	handler_t plugins_call_##y(server *srv, connection *con) {\
28913f957d2SGlenn Strauss 		plugin ** const slot = ((plugin ***)(srv->plugin_slots))[x];\
29062e97967SGlenn Strauss 		const uint32_t used = srv->plugins.used;\
29113f957d2SGlenn Strauss 		handler_t rc = HANDLER_GO_ON;\
29213f957d2SGlenn Strauss 		if (slot) {\
29313f957d2SGlenn Strauss 			const plugin *p;\
29462e97967SGlenn Strauss 			for (uint32_t i = 0; i < used && (p = slot[i]) && (rc = p->y(srv, con, p->data)) == HANDLER_GO_ON; ++i) ;\
295bcdc6a3bSJan Kneschke 		}\
29613f957d2SGlenn Strauss 		return rc;\
297bcdc6a3bSJan Kneschke 	}
298bcdc6a3bSJan Kneschke 
299bcdc6a3bSJan Kneschke /**
300bcdc6a3bSJan Kneschke  * plugins that use
301bcdc6a3bSJan Kneschke  *
302bcdc6a3bSJan Kneschke  * - server *srv
303bcdc6a3bSJan Kneschke  * - connection *con
304bcdc6a3bSJan Kneschke  * - void *p_d (plugin_data *)
305bcdc6a3bSJan Kneschke  */
306bcdc6a3bSJan Kneschke 
307bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean)
308bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw)
309cb7ed136SGlenn Strauss PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_ENV, handle_request_env)
310bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done)
311cb7ed136SGlenn Strauss PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT, handle_connection_accept)
312cb7ed136SGlenn Strauss PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR, handle_connection_shut_wr)
313bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
314bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest)
315bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start)
316cb1a3c62SGlenn Strauss PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_START, handle_response_start)
317bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
3186adaad54SJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
319bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset)
320bcdc6a3bSJan Kneschke 
321bcdc6a3bSJan Kneschke #undef PLUGIN_TO_SLOT
322bcdc6a3bSJan Kneschke 
323bcdc6a3bSJan Kneschke #define PLUGIN_TO_SLOT(x, y) \
324bcdc6a3bSJan Kneschke 	handler_t plugins_call_##y(server *srv) {\
32513f957d2SGlenn Strauss 		plugin ** const slot = ((plugin ***)(srv->plugin_slots))[x];\
32662e97967SGlenn Strauss 		const uint32_t used = srv->plugins.used; \
32713f957d2SGlenn Strauss 		handler_t rc = HANDLER_GO_ON;\
32813f957d2SGlenn Strauss 		if (slot) {\
32913f957d2SGlenn Strauss 			const plugin *p;\
33062e97967SGlenn Strauss 			for (uint32_t i = 0; i < used && (p = slot[i]) && (rc = p->y(srv, p->data)) == HANDLER_GO_ON; ++i) ;\
331bcdc6a3bSJan Kneschke 		}\
33213f957d2SGlenn Strauss 		return rc;\
333bcdc6a3bSJan Kneschke 	}
334bcdc6a3bSJan Kneschke 
335bcdc6a3bSJan Kneschke /**
336bcdc6a3bSJan Kneschke  * plugins that use
337bcdc6a3bSJan Kneschke  *
338bcdc6a3bSJan Kneschke  * - server *srv
339bcdc6a3bSJan Kneschke  * - void *p_d (plugin_data *)
340bcdc6a3bSJan Kneschke  */
341bcdc6a3bSJan Kneschke 
342bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
343bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
344bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
345bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults)
346f1e9bcb0SGlenn Strauss PLUGIN_TO_SLOT(PLUGIN_FUNC_WORKER_INIT, worker_init)
347bcdc6a3bSJan Kneschke 
348bcdc6a3bSJan Kneschke #undef PLUGIN_TO_SLOT
349bcdc6a3bSJan Kneschke 
3509030cfaeSGlenn Strauss handler_t plugins_call_handle_waitpid(server *srv, pid_t pid, int status) {
3519030cfaeSGlenn Strauss 	plugin ** const slot =
3529030cfaeSGlenn Strauss 	  ((plugin ***)(srv->plugin_slots))[PLUGIN_FUNC_HANDLE_WAITPID];
3539030cfaeSGlenn Strauss 	if (!slot) return HANDLER_GO_ON;
35462e97967SGlenn Strauss 	for (uint32_t i = 0; i < srv->plugins.used && slot[i]; ++i) {
3559030cfaeSGlenn Strauss 		plugin *p = slot[i];
3569030cfaeSGlenn Strauss 		handler_t r = p->handle_waitpid(srv, p->data, pid, status);
3579030cfaeSGlenn Strauss 		if (r != HANDLER_GO_ON) return r;
3589030cfaeSGlenn Strauss 	}
3599030cfaeSGlenn Strauss 	return HANDLER_GO_ON;
3609030cfaeSGlenn Strauss }
3619030cfaeSGlenn Strauss 
362bcdc6a3bSJan Kneschke #if 0
363bcdc6a3bSJan Kneschke /**
364bcdc6a3bSJan Kneschke  *
365bcdc6a3bSJan Kneschke  * special handler
366bcdc6a3bSJan Kneschke  *
367bcdc6a3bSJan Kneschke  */
368bcdc6a3bSJan Kneschke handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
36962e97967SGlenn Strauss 	plugin ** const ps = srv->plugins.ptr;
37062e97967SGlenn Strauss 	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
371bcdc6a3bSJan Kneschke 		plugin *p = ps[i];
372bcdc6a3bSJan Kneschke 		if (p->handle_fdevent) {
373bcdc6a3bSJan Kneschke 			handler_t r;
374bcdc6a3bSJan Kneschke 			switch(r = p->handle_fdevent(srv, fdc, p->data)) {
375bcdc6a3bSJan Kneschke 			case HANDLER_GO_ON:
376bcdc6a3bSJan Kneschke 				break;
377bcdc6a3bSJan Kneschke 			case HANDLER_FINISHED:
378bcdc6a3bSJan Kneschke 			case HANDLER_COMEBACK:
379bcdc6a3bSJan Kneschke 			case HANDLER_WAIT_FOR_EVENT:
380bcdc6a3bSJan Kneschke 			case HANDLER_ERROR:
381bcdc6a3bSJan Kneschke 				return r;
382bcdc6a3bSJan Kneschke 			default:
383bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "d", r);
384bcdc6a3bSJan Kneschke 				break;
385bcdc6a3bSJan Kneschke 			}
386bcdc6a3bSJan Kneschke 		}
387bcdc6a3bSJan Kneschke 	}
388bcdc6a3bSJan Kneschke 
389bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
390bcdc6a3bSJan Kneschke }
391bcdc6a3bSJan Kneschke #endif
392bcdc6a3bSJan Kneschke /**
393bcdc6a3bSJan Kneschke  *
394bcdc6a3bSJan Kneschke  * - call init function of all plugins to init the plugin-internals
395bcdc6a3bSJan Kneschke  * - added each plugin that supports has callback to the corresponding slot
396bcdc6a3bSJan Kneschke  *
397bcdc6a3bSJan Kneschke  * - is only called once.
398bcdc6a3bSJan Kneschke  */
399bcdc6a3bSJan Kneschke 
400bcdc6a3bSJan Kneschke handler_t plugins_call_init(server *srv) {
40162e97967SGlenn Strauss 	plugin ** const ps = srv->plugins.ptr;
402bcdc6a3bSJan Kneschke 
403bcdc6a3bSJan Kneschke 	/* fill slots */
404bcdc6a3bSJan Kneschke 
405bcdc6a3bSJan Kneschke 	srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
406566cf8deSStefan Bühler 	force_assert(NULL != srv->plugin_slots);
407bcdc6a3bSJan Kneschke 
40862e97967SGlenn Strauss 	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
409bcdc6a3bSJan Kneschke 		/* check which calls are supported */
410bcdc6a3bSJan Kneschke 
411bcdc6a3bSJan Kneschke 		plugin *p = ps[i];
412bcdc6a3bSJan Kneschke 
413bcdc6a3bSJan Kneschke #define PLUGIN_TO_SLOT(x, y) \
414bcdc6a3bSJan Kneschke 	if (p->y) { \
415bcdc6a3bSJan Kneschke 		plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
416bcdc6a3bSJan Kneschke 		if (!slot) { \
417bcdc6a3bSJan Kneschke 			slot = calloc(srv->plugins.used, sizeof(*slot));\
418566cf8deSStefan Bühler 			force_assert(NULL != slot); \
419bcdc6a3bSJan Kneschke 			((plugin ***)(srv->plugin_slots))[x] = slot; \
420bcdc6a3bSJan Kneschke 		} \
42162e97967SGlenn Strauss 		for (uint32_t j = 0; j < srv->plugins.used; ++j) { \
422bcdc6a3bSJan Kneschke 			if (slot[j]) continue;\
423bcdc6a3bSJan Kneschke 			slot[j] = p;\
424bcdc6a3bSJan Kneschke 			break;\
425bcdc6a3bSJan Kneschke 		}\
426bcdc6a3bSJan Kneschke 	}
427bcdc6a3bSJan Kneschke 
428bcdc6a3bSJan Kneschke 
429bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
430bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
431cb7ed136SGlenn Strauss 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_ENV, handle_request_env);
432bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
433cb7ed136SGlenn Strauss 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT, handle_connection_accept);
434cb7ed136SGlenn Strauss 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR, handle_connection_shut_wr);
435bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
436bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
437bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup);
4389030cfaeSGlenn Strauss 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_WAITPID, handle_waitpid);
439bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest);
440bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start);
441cb1a3c62SGlenn Strauss 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_START, handle_response_start);
442bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot);
4436adaad54SJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical);
444bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset);
445bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
446bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
447f1e9bcb0SGlenn Strauss 		PLUGIN_TO_SLOT(PLUGIN_FUNC_WORKER_INIT, worker_init);
448bcdc6a3bSJan Kneschke #undef PLUGIN_TO_SLOT
449bcdc6a3bSJan Kneschke 
450bcdc6a3bSJan Kneschke 		if (p->init) {
451bcdc6a3bSJan Kneschke 			if (NULL == (p->data = p->init())) {
452*e2de4e58SGlenn Strauss 				log_error_write(srv, __FILE__, __LINE__, "ss",
453bcdc6a3bSJan Kneschke 						"plugin-init failed for module", p->name);
454bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
455bcdc6a3bSJan Kneschke 			}
456bcdc6a3bSJan Kneschke 
457bcdc6a3bSJan Kneschke 			/* used for con->mode, DIRECT == 0, plugins above that */
458bcdc6a3bSJan Kneschke 			((plugin_data *)(p->data))->id = i + 1;
459bcdc6a3bSJan Kneschke 
460bcdc6a3bSJan Kneschke 			if (p->version != LIGHTTPD_VERSION_ID) {
461*e2de4e58SGlenn Strauss 				log_error_write(srv, __FILE__, __LINE__, "ss",
462bcdc6a3bSJan Kneschke 						"plugin-version doesn't match lighttpd-version for", p->name);
463bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
464bcdc6a3bSJan Kneschke 			}
465bcdc6a3bSJan Kneschke 		}
4668af9e71cSGlenn Strauss 
4678af9e71cSGlenn Strauss 		if (p->priv_defaults && HANDLER_ERROR==p->priv_defaults(srv, p->data)) {
4688af9e71cSGlenn Strauss 			return HANDLER_ERROR;
4698af9e71cSGlenn Strauss 		}
470bcdc6a3bSJan Kneschke 	}
471bcdc6a3bSJan Kneschke 
472bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
473bcdc6a3bSJan Kneschke }
474bcdc6a3bSJan Kneschke 
475bcdc6a3bSJan Kneschke void plugins_free(server *srv) {
47662e97967SGlenn Strauss 	if (srv->plugin_slots) {
47762e97967SGlenn Strauss 		plugins_call_cleanup(srv);
47862e97967SGlenn Strauss 		for (int i = 0; i < PLUGIN_FUNC_SIZEOF; ++i) {
47962e97967SGlenn Strauss 			plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
48062e97967SGlenn Strauss 			if (slot) free(slot);
48162e97967SGlenn Strauss 		}
48262e97967SGlenn Strauss 		free(srv->plugin_slots);
48362e97967SGlenn Strauss 		srv->plugin_slots = NULL;
48462e97967SGlenn Strauss 	}
485bcdc6a3bSJan Kneschke 
48662e97967SGlenn Strauss 	for (uint32_t i = 0; i < srv->plugins.used; ++i) {
487bcdc6a3bSJan Kneschke 		plugin *p = ((plugin **)srv->plugins.ptr)[i];
488bcdc6a3bSJan Kneschke 
489bcdc6a3bSJan Kneschke 		plugin_free(p);
490bcdc6a3bSJan Kneschke 	}
491bcdc6a3bSJan Kneschke 	free(srv->plugins.ptr);
492bcdc6a3bSJan Kneschke 	srv->plugins.ptr = NULL;
493b37a9585SmOo 	srv->plugins.used = 0;
49462e97967SGlenn Strauss 	srv->plugins.size = 0;
495bcdc6a3bSJan Kneschke }
496