Annotation of embedaddon/lighttpd/src/plugin.c, revision 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>