11 #ifdef HAVE_VALGRIND_VALGRIND_H
12 # include <valgrind/valgrind.h>
15 #if !defined(__WIN32) && !defined(LIGHTTPD_STATIC)
20 * if you change this enum to add a new callback, be sure
21 * - that PLUGIN_FUNC_SIZEOF is the last entry
22 * - that you add PLUGIN_TO_SLOT twice:
23 * 1. as callback-dispatcher
24 * 2. in plugins_call_init()
35 PLUGIN_FUNC_HANDLE_URI_CLEAN
,
36 PLUGIN_FUNC_HANDLE_URI_RAW
,
37 PLUGIN_FUNC_HANDLE_REQUEST_DONE
,
38 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE
,
39 PLUGIN_FUNC_HANDLE_TRIGGER
,
40 PLUGIN_FUNC_HANDLE_SIGHUP
,
41 PLUGIN_FUNC_HANDLE_SUBREQUEST
,
42 PLUGIN_FUNC_HANDLE_SUBREQUEST_START
,
43 PLUGIN_FUNC_HANDLE_JOBLIST
,
44 PLUGIN_FUNC_HANDLE_DOCROOT
,
45 PLUGIN_FUNC_HANDLE_PHYSICAL
,
46 PLUGIN_FUNC_CONNECTION_RESET
,
49 PLUGIN_FUNC_SET_DEFAULTS
,
54 static plugin
*plugin_init(void) {
57 p
= calloc(1, sizeof(*p
));
58 force_assert(NULL
!= p
);
63 static void plugin_free(plugin
*p
) {
64 #if !defined(LIGHTTPD_STATIC)
68 if (p
->name
) buffer_free(p
->name
);
69 #if defined(HAVE_VALGRIND_VALGRIND_H) && !defined(LIGHTTPD_STATIC)
70 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
73 #if !defined(LIGHTTPD_STATIC)
74 if (use_dlclose
&& p
->lib
) {
76 ) FreeLibrary(p
->lib
);
86 static int plugins_register(server
*srv
, plugin
*p
) {
88 if (0 == srv
->plugins
.size
) {
89 srv
->plugins
.size
= 4;
90 srv
->plugins
.ptr
= malloc(srv
->plugins
.size
* sizeof(*ps
));
91 force_assert(NULL
!= srv
->plugins
.ptr
);
92 srv
->plugins
.used
= 0;
93 } else if (srv
->plugins
.used
== srv
->plugins
.size
) {
94 srv
->plugins
.size
+= 4;
95 srv
->plugins
.ptr
= realloc(srv
->plugins
.ptr
, srv
->plugins
.size
* sizeof(*ps
));
96 force_assert(NULL
!= srv
->plugins
.ptr
);
99 ps
= srv
->plugins
.ptr
;
100 ps
[srv
->plugins
.used
++] = p
;
111 #if defined(LIGHTTPD_STATIC)
113 /* pre-declare functions, as there is no header for them */
114 #define PLUGIN_INIT(x)\
115 int x ## _plugin_init(plugin *p);
117 #include "plugin-static.h"
121 /* build NULL-terminated table of name + init-function */
125 int (*plugin_init
)(plugin
*p
);
126 } plugin_load_functions
;
128 static const plugin_load_functions load_functions
[] = {
129 #define PLUGIN_INIT(x) \
130 { #x, &x ## _plugin_init },
132 #include "plugin-static.h"
138 int plugins_load(server
*srv
) {
142 for (i
= 0; i
< srv
->srvconf
.modules
->used
; i
++) {
143 data_string
*d
= (data_string
*)srv
->srvconf
.modules
->data
[i
];
144 char *module
= d
->value
->ptr
;
146 for (j
= 0; j
< i
; j
++) {
147 if (buffer_is_equal(d
->value
, ((data_string
*) srv
->srvconf
.modules
->data
[j
])->value
)) {
148 log_error_write(srv
, __FILE__
, __LINE__
, "sbs",
149 "Cannot load plugin", d
->value
,
150 "more than once, please fix your config (lighttpd may not accept such configs in future releases)");
155 for (j
= 0; load_functions
[j
].name
; ++j
) {
156 if (0 == strcmp(load_functions
[j
].name
, module
)) {
158 if ((*load_functions
[j
].plugin_init
)(p
)) {
159 log_error_write(srv
, __FILE__
, __LINE__
, "ss", module
, "plugin init failed" );
163 plugins_register(srv
, p
);
167 if (!load_functions
[j
].name
) {
168 log_error_write(srv
, __FILE__
, __LINE__
, "ss", module
, " plugin not found" );
175 #else /* defined(LIGHTTPD_STATIC) */
176 int plugins_load(server
*srv
) {
178 int (*init
)(plugin
*pl
);
182 for (i
= 0; i
< srv
->srvconf
.modules
->used
; i
++) {
183 data_string
*d
= (data_string
*)srv
->srvconf
.modules
->data
[i
];
184 char *module
= d
->value
->ptr
;
186 for (j
= 0; j
< i
; j
++) {
187 if (buffer_is_equal(d
->value
, ((data_string
*) srv
->srvconf
.modules
->data
[j
])->value
)) {
188 log_error_write(srv
, __FILE__
, __LINE__
, "sbs",
189 "Cannot load plugin", d
->value
,
190 "more than once, please fix your config (lighttpd may not accept such configs in future releases)");
195 buffer_copy_buffer(srv
->tmp_buf
, srv
->srvconf
.modules_dir
);
197 buffer_append_string_len(srv
->tmp_buf
, CONST_STR_LEN("/"));
198 buffer_append_string(srv
->tmp_buf
, module
);
199 #if defined(__WIN32) || defined(__CYGWIN__)
200 buffer_append_string_len(srv
->tmp_buf
, CONST_STR_LEN(".dll"));
202 buffer_append_string_len(srv
->tmp_buf
, CONST_STR_LEN(".so"));
207 if (NULL
== (p
->lib
= LoadLibrary(srv
->tmp_buf
->ptr
))) {
210 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
211 FORMAT_MESSAGE_FROM_SYSTEM
,
214 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
218 log_error_write(srv
, __FILE__
, __LINE__
, "ssb", "LoadLibrary() failed",
219 lpMsgBuf
, srv
->tmp_buf
);
227 if (NULL
== (p
->lib
= dlopen(srv
->tmp_buf
->ptr
, RTLD_NOW
|RTLD_GLOBAL
))) {
228 log_error_write(srv
, __FILE__
, __LINE__
, "sbs", "dlopen() failed for:",
229 srv
->tmp_buf
, dlerror());
237 buffer_reset(srv
->tmp_buf
);
238 buffer_copy_string(srv
->tmp_buf
, module
);
239 buffer_append_string_len(srv
->tmp_buf
, CONST_STR_LEN("_plugin_init"));
242 init
= GetProcAddress(p
->lib
, srv
->tmp_buf
->ptr
);
247 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
248 FORMAT_MESSAGE_FROM_SYSTEM
,
251 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
255 log_error_write(srv
, __FILE__
, __LINE__
, "sbs", "getprocaddress failed:", srv
->tmp_buf
, lpMsgBuf
);
263 init
= (int (*)(plugin
*))(intptr_t)dlsym(p
->lib
, srv
->tmp_buf
->ptr
);
265 *(void **)(&init
) = dlsym(p
->lib
, srv
->tmp_buf
->ptr
);
267 if ((error
= dlerror()) != NULL
) {
268 log_error_write(srv
, __FILE__
, __LINE__
, "s", error
);
276 log_error_write(srv
, __FILE__
, __LINE__
, "ss", module
, "plugin init failed" );
282 log_error_write(srv
, __FILE__
, __LINE__
, "ss", module
, "plugin loaded" );
284 plugins_register(srv
, p
);
289 #endif /* defined(LIGHTTPD_STATIC) */
291 #define PLUGIN_TO_SLOT(x, y) \
292 handler_t plugins_call_##y(server *srv, connection *con) {\
295 if (!srv->plugin_slots) return HANDLER_GO_ON;\
296 slot = ((plugin ***)(srv->plugin_slots))[x];\
297 if (!slot) return HANDLER_GO_ON;\
298 for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
299 plugin *p = slot[j];\
301 switch(r = p->y(srv, con, p->data)) {\
304 case HANDLER_FINISHED:\
305 case HANDLER_COMEBACK:\
306 case HANDLER_WAIT_FOR_EVENT:\
307 case HANDLER_WAIT_FOR_FD:\
311 log_error_write(srv, __FILE__, __LINE__, "sbs", #x, p->name, "unknown state");\
312 return HANDLER_ERROR;\
315 return HANDLER_GO_ON;\
323 * - void *p_d (plugin_data *)
326 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN
, handle_uri_clean
)
327 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW
, handle_uri_raw
)
328 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE
, handle_request_done
)
329 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE
, handle_connection_close
)
330 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST
, handle_subrequest
)
331 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START
, handle_subrequest_start
)
332 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST
, handle_joblist
)
333 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT
, handle_docroot
)
334 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL
, handle_physical
)
335 PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET
, connection_reset
)
337 #undef PLUGIN_TO_SLOT
339 #define PLUGIN_TO_SLOT(x, y) \
340 handler_t plugins_call_##y(server *srv) {\
343 if (!srv->plugin_slots) return HANDLER_GO_ON;\
344 slot = ((plugin ***)(srv->plugin_slots))[x];\
345 if (!slot) return HANDLER_GO_ON;\
346 for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
347 plugin *p = slot[j];\
349 switch(r = p->y(srv, p->data)) {\
352 case HANDLER_FINISHED:\
353 case HANDLER_COMEBACK:\
354 case HANDLER_WAIT_FOR_EVENT:\
355 case HANDLER_WAIT_FOR_FD:\
359 log_error_write(srv, __FILE__, __LINE__, "sbsd", #x, p->name, "unknown state:", r);\
360 return HANDLER_ERROR;\
363 return HANDLER_GO_ON;\
370 * - void *p_d (plugin_data *)
373 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER
, handle_trigger
)
374 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP
, handle_sighup
)
375 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP
, cleanup
)
376 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS
, set_defaults
)
378 #undef PLUGIN_TO_SLOT
386 handler_t
plugins_call_handle_fdevent(server
*srv
, const fd_conn
*fdc
) {
390 ps
= srv
->plugins
.ptr
;
392 for (i
= 0; i
< srv
->plugins
.used
; i
++) {
394 if (p
->handle_fdevent
) {
396 switch(r
= p
->handle_fdevent(srv
, fdc
, p
->data
)) {
399 case HANDLER_FINISHED
:
400 case HANDLER_COMEBACK
:
401 case HANDLER_WAIT_FOR_EVENT
:
405 log_error_write(srv
, __FILE__
, __LINE__
, "d", r
);
411 return HANDLER_GO_ON
;
416 * - call init function of all plugins to init the plugin-internals
417 * - added each plugin that supports has callback to the corresponding slot
419 * - is only called once.
422 handler_t
plugins_call_init(server
*srv
) {
426 ps
= srv
->plugins
.ptr
;
430 srv
->plugin_slots
= calloc(PLUGIN_FUNC_SIZEOF
, sizeof(ps
));
431 force_assert(NULL
!= srv
->plugin_slots
);
433 for (i
= 0; i
< srv
->plugins
.used
; i
++) {
435 /* check which calls are supported */
439 #define PLUGIN_TO_SLOT(x, y) \
441 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
443 slot = calloc(srv->plugins.used, sizeof(*slot));\
444 force_assert(NULL != slot); \
445 ((plugin ***)(srv->plugin_slots))[x] = slot; \
447 for (j = 0; j < srv->plugins.used; j++) { \
448 if (slot[j]) continue;\
455 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN
, handle_uri_clean
);
456 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW
, handle_uri_raw
);
457 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE
, handle_request_done
);
458 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE
, handle_connection_close
);
459 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER
, handle_trigger
);
460 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP
, handle_sighup
);
461 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST
, handle_subrequest
);
462 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START
, handle_subrequest_start
);
463 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST
, handle_joblist
);
464 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT
, handle_docroot
);
465 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL
, handle_physical
);
466 PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET
, connection_reset
);
467 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP
, cleanup
);
468 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS
, set_defaults
);
469 #undef PLUGIN_TO_SLOT
472 if (NULL
== (p
->data
= p
->init())) {
473 log_error_write(srv
, __FILE__
, __LINE__
, "sb",
474 "plugin-init failed for module", p
->name
);
475 return HANDLER_ERROR
;
478 /* used for con->mode, DIRECT == 0, plugins above that */
479 ((plugin_data
*)(p
->data
))->id
= i
+ 1;
481 if (p
->version
!= LIGHTTPD_VERSION_ID
) {
482 log_error_write(srv
, __FILE__
, __LINE__
, "sb",
483 "plugin-version doesn't match lighttpd-version for", p
->name
);
484 return HANDLER_ERROR
;
491 return HANDLER_GO_ON
;
494 void plugins_free(server
*srv
) {
496 plugins_call_cleanup(srv
);
498 for (i
= 0; i
< srv
->plugins
.used
; i
++) {
499 plugin
*p
= ((plugin
**)srv
->plugins
.ptr
)[i
];
504 for (i
= 0; srv
->plugin_slots
&& i
< PLUGIN_FUNC_SIZEOF
; i
++) {
505 plugin
**slot
= ((plugin
***)(srv
->plugin_slots
))[i
];
507 if (slot
) free(slot
);
510 free(srv
->plugin_slots
);
511 srv
->plugin_slots
= NULL
;
513 free(srv
->plugins
.ptr
);
514 srv
->plugins
.ptr
= NULL
;
515 srv
->plugins
.used
= 0;