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>