Annotation of embedaddon/lighttpd/src/plugin.c, revision 1.1.1.1
1.1 misho 1: #include "plugin.h"
2: #include "log.h"
3:
4: #include <string.h>
5: #include <stdlib.h>
6:
7: #include <stdio.h>
8:
9: #ifdef HAVE_VALGRIND_VALGRIND_H
10: # include <valgrind/valgrind.h>
11: #endif
12:
13: #ifndef __WIN32
14: # include <dlfcn.h>
15: #endif
16: /*
17: *
18: * if you change this enum to add a new callback, be sure
19: * - that PLUGIN_FUNC_SIZEOF is the last entry
20: * - that you add PLUGIN_TO_SLOT twice:
21: * 1. as callback-dispatcher
22: * 2. in plugins_call_init()
23: *
24: */
25:
26: typedef struct {
27: PLUGIN_DATA;
28: } plugin_data;
29:
30: typedef enum {
31: PLUGIN_FUNC_UNSET,
32: PLUGIN_FUNC_HANDLE_URI_CLEAN,
33: PLUGIN_FUNC_HANDLE_URI_RAW,
34: PLUGIN_FUNC_HANDLE_REQUEST_DONE,
35: PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
36: PLUGIN_FUNC_HANDLE_TRIGGER,
37: PLUGIN_FUNC_HANDLE_SIGHUP,
38: PLUGIN_FUNC_HANDLE_SUBREQUEST,
39: PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
40: PLUGIN_FUNC_HANDLE_JOBLIST,
41: PLUGIN_FUNC_HANDLE_DOCROOT,
42: PLUGIN_FUNC_HANDLE_PHYSICAL,
43: PLUGIN_FUNC_CONNECTION_RESET,
44: PLUGIN_FUNC_INIT,
45: PLUGIN_FUNC_CLEANUP,
46: PLUGIN_FUNC_SET_DEFAULTS,
47:
48: PLUGIN_FUNC_SIZEOF
49: } plugin_t;
50:
51: static plugin *plugin_init(void) {
52: plugin *p;
53:
54: p = calloc(1, sizeof(*p));
55:
56: return p;
57: }
58:
59: static void plugin_free(plugin *p) {
60: int use_dlclose = 1;
61: if (p->name) buffer_free(p->name);
62: #ifdef HAVE_VALGRIND_VALGRIND_H
63: /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
64: #endif
65:
66: #ifndef LIGHTTPD_STATIC
67: if (use_dlclose && p->lib) {
68: #ifdef __WIN32
69: FreeLibrary(p->lib);
70: #else
71: dlclose(p->lib);
72: #endif
73: }
74: #endif
75:
76: free(p);
77: }
78:
79: static int plugins_register(server *srv, plugin *p) {
80: plugin **ps;
81: if (0 == srv->plugins.size) {
82: srv->plugins.size = 4;
83: srv->plugins.ptr = malloc(srv->plugins.size * sizeof(*ps));
84: srv->plugins.used = 0;
85: } else if (srv->plugins.used == srv->plugins.size) {
86: srv->plugins.size += 4;
87: srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
88: }
89:
90: ps = srv->plugins.ptr;
91: ps[srv->plugins.used++] = p;
92:
93: return 0;
94: }
95:
96: /**
97: *
98: *
99: *
100: */
101:
102: #ifdef LIGHTTPD_STATIC
103: int plugins_load(server *srv) {
104: plugin *p;
105: #define PLUGIN_INIT(x)\
106: p = plugin_init(); \
107: if (x ## _plugin_init(p)) { \
108: log_error_write(srv, __FILE__, __LINE__, "ss", #x, "plugin init failed" ); \
109: plugin_free(p); \
110: return -1;\
111: }\
112: plugins_register(srv, p);
113:
114: #include "plugin-static.h"
115:
116: return 0;
117: }
118: #else
119: int plugins_load(server *srv) {
120: plugin *p;
121: int (*init)(plugin *pl);
122: const char *error;
123: size_t i, j;
124:
125: for (i = 0; i < srv->srvconf.modules->used; i++) {
126: data_string *d = (data_string *)srv->srvconf.modules->data[i];
127: char *modules = d->value->ptr;
128:
129: for (j = 0; j < i; j++) {
130: if (buffer_is_equal(d->value, ((data_string *) srv->srvconf.modules->data[j])->value)) {
131: log_error_write(srv, __FILE__, __LINE__, "sbs", "Cannot load plugin", d->value, "more than once, please fix your config (we may not accept such configs in future releases");
132: continue;
133: }
134: }
135:
136: buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
137:
138: buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("/"));
139: buffer_append_string(srv->tmp_buf, modules);
140: #if defined(__WIN32) || defined(__CYGWIN__)
141: buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".dll"));
142: #else
143: buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".so"));
144: #endif
145:
146: p = plugin_init();
147: #ifdef __WIN32
148: if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
149: LPVOID lpMsgBuf;
150: FormatMessage(
151: FORMAT_MESSAGE_ALLOCATE_BUFFER |
152: FORMAT_MESSAGE_FROM_SYSTEM,
153: NULL,
154: GetLastError(),
155: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
156: (LPTSTR) &lpMsgBuf,
157: 0, NULL );
158:
159: log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
160: lpMsgBuf, srv->tmp_buf);
161:
162: plugin_free(p);
163:
164: return -1;
165:
166: }
167: #else
168: if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) {
169: log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
170: srv->tmp_buf, dlerror());
171:
172: plugin_free(p);
173:
174: return -1;
175: }
176:
177: #endif
178: buffer_reset(srv->tmp_buf);
179: buffer_copy_string(srv->tmp_buf, modules);
180: buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("_plugin_init"));
181:
182: #ifdef __WIN32
183: init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
184:
185: if (init == NULL) {
186: LPVOID lpMsgBuf;
187: FormatMessage(
188: FORMAT_MESSAGE_ALLOCATE_BUFFER |
189: FORMAT_MESSAGE_FROM_SYSTEM,
190: NULL,
191: GetLastError(),
192: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
193: (LPTSTR) &lpMsgBuf,
194: 0, NULL );
195:
196: log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
197:
198: plugin_free(p);
199: return -1;
200: }
201:
202: #else
203: #if 1
204: init = (int (*)(plugin *))(intptr_t)dlsym(p->lib, srv->tmp_buf->ptr);
205: #else
206: *(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr);
207: #endif
208: if ((error = dlerror()) != NULL) {
209: log_error_write(srv, __FILE__, __LINE__, "s", error);
210:
211: plugin_free(p);
212: return -1;
213: }
214:
215: #endif
216: if ((*init)(p)) {
217: log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
218:
219: plugin_free(p);
220: return -1;
221: }
222: #if 0
223: log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
224: #endif
225: plugins_register(srv, p);
226: }
227:
228: return 0;
229: }
230: #endif
231:
232: #define PLUGIN_TO_SLOT(x, y) \
233: handler_t plugins_call_##y(server *srv, connection *con) {\
234: plugin **slot;\
235: size_t j;\
236: if (!srv->plugin_slots) return HANDLER_GO_ON;\
237: slot = ((plugin ***)(srv->plugin_slots))[x];\
238: if (!slot) return HANDLER_GO_ON;\
239: for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
240: plugin *p = slot[j];\
241: handler_t r;\
242: switch(r = p->y(srv, con, p->data)) {\
243: case HANDLER_GO_ON:\
244: break;\
245: case HANDLER_FINISHED:\
246: case HANDLER_COMEBACK:\
247: case HANDLER_WAIT_FOR_EVENT:\
248: case HANDLER_WAIT_FOR_FD:\
249: case HANDLER_ERROR:\
250: return r;\
251: default:\
252: log_error_write(srv, __FILE__, __LINE__, "sbs", #x, p->name, "unknown state");\
253: return HANDLER_ERROR;\
254: }\
255: }\
256: return HANDLER_GO_ON;\
257: }
258:
259: /**
260: * plugins that use
261: *
262: * - server *srv
263: * - connection *con
264: * - void *p_d (plugin_data *)
265: */
266:
267: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean)
268: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw)
269: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done)
270: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
271: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest)
272: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start)
273: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist)
274: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
275: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
276: PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset)
277:
278: #undef PLUGIN_TO_SLOT
279:
280: #define PLUGIN_TO_SLOT(x, y) \
281: handler_t plugins_call_##y(server *srv) {\
282: plugin **slot;\
283: size_t j;\
284: if (!srv->plugin_slots) return HANDLER_GO_ON;\
285: slot = ((plugin ***)(srv->plugin_slots))[x];\
286: if (!slot) return HANDLER_GO_ON;\
287: for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
288: plugin *p = slot[j];\
289: handler_t r;\
290: switch(r = p->y(srv, p->data)) {\
291: case HANDLER_GO_ON:\
292: break;\
293: case HANDLER_FINISHED:\
294: case HANDLER_COMEBACK:\
295: case HANDLER_WAIT_FOR_EVENT:\
296: case HANDLER_WAIT_FOR_FD:\
297: case HANDLER_ERROR:\
298: return r;\
299: default:\
300: log_error_write(srv, __FILE__, __LINE__, "sbsd", #x, p->name, "unknown state:", r);\
301: return HANDLER_ERROR;\
302: }\
303: }\
304: return HANDLER_GO_ON;\
305: }
306:
307: /**
308: * plugins that use
309: *
310: * - server *srv
311: * - void *p_d (plugin_data *)
312: */
313:
314: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
315: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
316: PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
317: PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults)
318:
319: #undef PLUGIN_TO_SLOT
320:
321: #if 0
322: /**
323: *
324: * special handler
325: *
326: */
327: handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
328: size_t i;
329: plugin **ps;
330:
331: ps = srv->plugins.ptr;
332:
333: for (i = 0; i < srv->plugins.used; i++) {
334: plugin *p = ps[i];
335: if (p->handle_fdevent) {
336: handler_t r;
337: switch(r = p->handle_fdevent(srv, fdc, p->data)) {
338: case HANDLER_GO_ON:
339: break;
340: case HANDLER_FINISHED:
341: case HANDLER_COMEBACK:
342: case HANDLER_WAIT_FOR_EVENT:
343: case HANDLER_ERROR:
344: return r;
345: default:
346: log_error_write(srv, __FILE__, __LINE__, "d", r);
347: break;
348: }
349: }
350: }
351:
352: return HANDLER_GO_ON;
353: }
354: #endif
355: /**
356: *
357: * - call init function of all plugins to init the plugin-internals
358: * - added each plugin that supports has callback to the corresponding slot
359: *
360: * - is only called once.
361: */
362:
363: handler_t plugins_call_init(server *srv) {
364: size_t i;
365: plugin **ps;
366:
367: ps = srv->plugins.ptr;
368:
369: /* fill slots */
370:
371: srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
372:
373: for (i = 0; i < srv->plugins.used; i++) {
374: size_t j;
375: /* check which calls are supported */
376:
377: plugin *p = ps[i];
378:
379: #define PLUGIN_TO_SLOT(x, y) \
380: if (p->y) { \
381: plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
382: if (!slot) { \
383: slot = calloc(srv->plugins.used, sizeof(*slot));\
384: ((plugin ***)(srv->plugin_slots))[x] = slot; \
385: } \
386: for (j = 0; j < srv->plugins.used; j++) { \
387: if (slot[j]) continue;\
388: slot[j] = p;\
389: break;\
390: }\
391: }
392:
393:
394: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
395: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
396: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
397: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
398: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
399: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup);
400: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest);
401: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start);
402: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist);
403: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot);
404: PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical);
405: PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset);
406: PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
407: PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
408: #undef PLUGIN_TO_SLOT
409:
410: if (p->init) {
411: if (NULL == (p->data = p->init())) {
412: log_error_write(srv, __FILE__, __LINE__, "sb",
413: "plugin-init failed for module", p->name);
414: return HANDLER_ERROR;
415: }
416:
417: /* used for con->mode, DIRECT == 0, plugins above that */
418: ((plugin_data *)(p->data))->id = i + 1;
419:
420: if (p->version != LIGHTTPD_VERSION_ID) {
421: log_error_write(srv, __FILE__, __LINE__, "sb",
422: "plugin-version doesn't match lighttpd-version for", p->name);
423: return HANDLER_ERROR;
424: }
425: } else {
426: p->data = NULL;
427: }
428: }
429:
430: return HANDLER_GO_ON;
431: }
432:
433: void plugins_free(server *srv) {
434: size_t i;
435: plugins_call_cleanup(srv);
436:
437: for (i = 0; i < srv->plugins.used; i++) {
438: plugin *p = ((plugin **)srv->plugins.ptr)[i];
439:
440: plugin_free(p);
441: }
442:
443: for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
444: plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
445:
446: if (slot) free(slot);
447: }
448:
449: free(srv->plugin_slots);
450: srv->plugin_slots = NULL;
451:
452: free(srv->plugins.ptr);
453: srv->plugins.ptr = NULL;
454: srv->plugins.used = 0;
455: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>