diff options
Diffstat (limited to 'plugin.c')
-rw-r--r-- | plugin.c | 109 |
1 files changed, 104 insertions, 5 deletions
@@ -1,20 +1,112 @@ #include <string.h> #include <stdio.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <dlfcn.h> #include "websocksy.h" #include "plugin.h" +//cheap out because i dont want the overhead of allocating here +#define MAX_PLUGIN_PATH 4096 + static size_t framing_functions = 0; static ws_framing* framing_function = NULL; static char** framing_function_name = NULL; +static size_t attached_libraries = 0; +static void** attached_library = NULL; + +static void* plugin_attach(char* path){ + void* module = dlopen(path, RTLD_LAZY); + + if(!module){ + fprintf(stderr, "Failed to load module %s\n", dlerror()); + return NULL; + } + + attached_library = realloc(attached_library, (attached_libraries + 1) * sizeof(void*)); + if(!attached_library){ + fprintf(stderr, "Failed to allocate memory\n"); + dlclose(module); + return NULL; + } + + attached_library[attached_libraries] = module; + attached_libraries++; + + return module; +} + int plugin_framing_load(char* path){ - //TODO load plugins + DIR* directory = opendir(path); + struct dirent* file = NULL; + char plugin_path[MAX_PLUGIN_PATH] = ""; + size_t path_len; + + if(strlen(path) >= sizeof(plugin_path) - 20){ + fprintf(stderr, "Plugin path length exceeds limit\n"); + return 1; + } + + strncpy(plugin_path, path, sizeof(plugin_path) - 2); + if(path[strlen(path) - 1] != '/'){ + plugin_path[strlen(path)] = '/'; + plugin_path[strlen(path) + 1] = 0; + } + path_len = strlen(plugin_path); + + if(!directory){ + fprintf(stderr, "Failed to open directory %s: %s\n", path, strerror(errno)); + return 0; + } + + for(file = readdir(directory); file; file = readdir(directory)){ + //skip backends + if(!strncmp(file->d_name, "backend_", 8)){ + continue; + } + //skip file not ending in .so + if(strlen(file->d_name) < 4 || strcmp(file->d_name + strlen(file->d_name) - 3, ".so")){ + continue; + } + strncpy(plugin_path + path_len, file->d_name, sizeof(plugin_path) - path_len - 2); + if(!plugin_attach(plugin_path)){ + return 1; + } + } + + closedir(directory); return 0; } -int plugin_backend_load(char* backend_requested, ws_backend* backend){ - //TODO load backend +int plugin_backend_load(char* path, char* backend_requested, ws_backend* backend){ + char plugin_path[MAX_PLUGIN_PATH] = ""; + void* handle = NULL; + + if(strlen(path) >= sizeof(plugin_path) - 30){ + fprintf(stderr, "Plugin path length exceeds limit\n"); + return 1; + } + + snprintf(plugin_path, sizeof(plugin_path), "%s%sbackend_%s.so", path, (path[strlen(path) - 1] == '/') ? "" : "/", backend_requested); + + handle = plugin_attach(plugin_path); + if(!handle){ + return 1; + } + + //read backend functions into the structure + backend->init = (ws_backend_init) dlsym(handle, "init"); + backend->config = (ws_backend_configure) dlsym(handle, "configure"); + backend->query = (ws_backend_query) dlsym(handle, "query"); + backend->cleanup = (ws_backend_cleanup) dlsym(handle, "cleanup"); + + if(!backend->init || !backend->query){ + fprintf(stderr, "Backend module %s is missing required symbols\n", plugin_path); + return 1; + } return 0; } @@ -63,8 +155,8 @@ ws_framing plugin_framing(char* name){ void plugin_cleanup(){ size_t u; - //TODO dlclose all plugins - + + //free allocated buffers for(u = 0; u < framing_functions; u++){ free(framing_function_name[u]); } @@ -74,4 +166,11 @@ void plugin_cleanup(){ framing_function_name = 0; framing_function = NULL; framing_functions = 0; + + //dlclose all plugins + for(u = 0; u < attached_libraries; u++){ + dlclose(attached_library[u]); + } + free(attached_library); + attached_libraries = 0; } |