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>