mirror of
https://github.com/emqx/neuron.git
synced 2026-10-24 18:51:30 +08:00
710 lines
21 KiB
C
710 lines
21 KiB
C
/**
|
|
* NEURON IIoT System for Industry 4.0
|
|
* Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
**/
|
|
|
|
#define NEURON_LOG_LABEL "plugin_manager"
|
|
|
|
#include <dlfcn.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <nng/nng.h>
|
|
#include <nng/supplemental/util/platform.h>
|
|
|
|
#include "adapter/adapter_internal.h"
|
|
#include "config.h"
|
|
#include "dummy/dummy.h"
|
|
#include "neu_panic.h"
|
|
#include "neu_vector.h"
|
|
#include "plugin_manager.h"
|
|
#include "restful/rest.h"
|
|
|
|
typedef struct plugin_reg_entity {
|
|
plugin_id_t plugin_id;
|
|
plugin_kind_e plugin_kind;
|
|
adapter_type_e adapter_type;
|
|
const char * plugin_name;
|
|
const char * plugin_lib_name;
|
|
} plugin_reg_entity_t;
|
|
|
|
struct plugin_manager {
|
|
nng_mtx * mtx;
|
|
plugin_id_t new_plugin_id;
|
|
// for cache availabale id
|
|
vector_t available_ids;
|
|
vector_t system_plugins;
|
|
vector_t custom_plugins;
|
|
};
|
|
|
|
/*
|
|
* manage builtin static plugins
|
|
*/
|
|
static const plugin_reg_entity_t builtin_static_plugins[] = {
|
|
{
|
|
.plugin_id = { 1 },
|
|
.plugin_kind = PLUGIN_KIND_STATIC,
|
|
.adapter_type = ADAPTER_TYPE_WEBSERVER,
|
|
.plugin_name = DEFAULT_DASHBOARD_PLUGIN_NAME,
|
|
.plugin_lib_name = DEFAULT_DASHBOARD_PLUGIN_LIB_NAME,
|
|
},
|
|
{
|
|
.plugin_id = { 2 },
|
|
.plugin_kind = PLUGIN_KIND_STATIC,
|
|
.adapter_type = ADAPTER_TYPE_APP,
|
|
.plugin_name = DEFAULT_DUMMY_PLUGIN_NAME,
|
|
.plugin_lib_name = DEFAULT_DUMMY_PLUGIN_LIB_NAME,
|
|
},
|
|
};
|
|
#define BUILTIN_STATIC_PLUGIN_COUNT \
|
|
(sizeof(builtin_static_plugins) / sizeof(builtin_static_plugins[0]))
|
|
|
|
#define MIN_DYNAMIC_PLUGIN_ID (BUILTIN_STATIC_PLUGIN_COUNT + 1)
|
|
|
|
/*
|
|
* manage dynamic plugins
|
|
*/
|
|
#define SYSTEM_PLUGIN_COUNT_DEFAULT 8
|
|
static int init_system_plugins(vector_t *plugins_vec)
|
|
{
|
|
int rv = 0;
|
|
|
|
rv = vector_init(plugins_vec, SYSTEM_PLUGIN_COUNT_DEFAULT,
|
|
sizeof(plugin_reg_entity_t));
|
|
return rv;
|
|
}
|
|
|
|
static void uninit_system_plugins(vector_t *plugins_vec)
|
|
{
|
|
vector_uninit(plugins_vec);
|
|
}
|
|
|
|
#define CUSTOM_PLUGIN_COUNT_DEFAULT 16
|
|
static int init_custom_plugins(vector_t *plugins_vec)
|
|
{
|
|
int rv = 0;
|
|
|
|
rv = vector_init(plugins_vec, CUSTOM_PLUGIN_COUNT_DEFAULT,
|
|
sizeof(plugin_reg_entity_t));
|
|
return rv;
|
|
}
|
|
|
|
static void uninit_custom_plugins(vector_t *plugins_vec)
|
|
{
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
VECTOR_FOR_EACH(plugins_vec, iter)
|
|
{
|
|
reg_entity = (plugin_reg_entity_t *) iterator_get(&iter);
|
|
free((void *) reg_entity->plugin_name);
|
|
free((void *) reg_entity->plugin_lib_name);
|
|
}
|
|
vector_uninit(plugins_vec);
|
|
}
|
|
|
|
// Return SIZE_MAX if can't find a plugin
|
|
static size_t find_plugin_by_id(vector_t *plugins, plugin_id_t id)
|
|
{
|
|
size_t index = SIZE_MAX;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
VECTOR_FOR_EACH(plugins, iter)
|
|
{
|
|
reg_entity = (plugin_reg_entity_t *) iterator_get(&iter);
|
|
if (reg_entity->plugin_id.id_val == id.id_val) {
|
|
index = iterator_index(plugins, &iter);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// Return SIZE_MAX if can't find a plugin
|
|
static size_t find_static_plugin_by_id(plugin_id_t id)
|
|
{
|
|
size_t i;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
for (i = 0; i < BUILTIN_STATIC_PLUGIN_COUNT; i++) {
|
|
reg_entity = (plugin_reg_entity_t *) &builtin_static_plugins[i];
|
|
if (reg_entity->plugin_id.id_val == id.id_val) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return SIZE_MAX;
|
|
}
|
|
|
|
// Return SIZE_MAX if can't find a plugin
|
|
static size_t find_plugin_by_name(vector_t *plugins, const char *plugin_name)
|
|
{
|
|
size_t index = SIZE_MAX;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
VECTOR_FOR_EACH(plugins, iter)
|
|
{
|
|
reg_entity = (plugin_reg_entity_t *) iterator_get(&iter);
|
|
if (strcmp(reg_entity->plugin_name, plugin_name) == 0) {
|
|
index = iterator_index(plugins, &iter);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// Return SIZE_MAX if can't find a plugin
|
|
static size_t find_static_plugin_by_name(const char *plugin_name)
|
|
{
|
|
size_t i;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
for (i = 0; i < BUILTIN_STATIC_PLUGIN_COUNT; i++) {
|
|
reg_entity = (plugin_reg_entity_t *) &builtin_static_plugins[i];
|
|
if (strcmp(reg_entity->plugin_name, plugin_name) == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return SIZE_MAX;
|
|
}
|
|
|
|
static plugin_id_t plugin_manager_get_plugin_id(plugin_manager_t *plugin_mng,
|
|
const plugin_reg_param_t *param)
|
|
{
|
|
size_t index;
|
|
plugin_id_t plugin_id;
|
|
vector_t * plugins;
|
|
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
plugin_id = plugin_mng->new_plugin_id;
|
|
plugin_mng->new_plugin_id.id_val++;
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
|
|
plugins = &plugin_mng->system_plugins;
|
|
if (param->plugin_kind == PLUGIN_KIND_CUSTOM) {
|
|
plugins = &plugin_mng->custom_plugins;
|
|
}
|
|
|
|
// Check if there is a plugin with same name
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
index = find_plugin_by_name(plugins, param->plugin_name);
|
|
if (index != SIZE_MAX) {
|
|
plugin_id.id_val = 0;
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
return plugin_id;
|
|
}
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
|
|
// TODO: get unique id for plugin
|
|
return plugin_id;
|
|
}
|
|
|
|
static void reg_entity_init(plugin_reg_entity_t * reg_entity,
|
|
plugin_id_t plugin_id,
|
|
const plugin_reg_param_t *param)
|
|
{
|
|
reg_entity->plugin_id = plugin_id;
|
|
reg_entity->plugin_kind = param->plugin_kind;
|
|
reg_entity->adapter_type = param->adapter_type;
|
|
reg_entity->plugin_name = strdup(param->plugin_name);
|
|
reg_entity->plugin_lib_name = strdup(param->plugin_lib_name);
|
|
return;
|
|
}
|
|
|
|
static void reg_entity_uninit(plugin_reg_entity_t *reg_entity)
|
|
{
|
|
reg_entity->plugin_id.id_val = 0;
|
|
reg_entity->adapter_type = 0;
|
|
if (reg_entity->plugin_name != NULL) {
|
|
free((void *) reg_entity->plugin_name);
|
|
}
|
|
if (reg_entity->plugin_lib_name != NULL) {
|
|
free((void *) reg_entity->plugin_lib_name);
|
|
}
|
|
return;
|
|
}
|
|
|
|
plugin_manager_t *plugin_manager_create()
|
|
{
|
|
int rv, rv1;
|
|
plugin_manager_t *plugin_mng;
|
|
|
|
plugin_mng = (plugin_manager_t *) malloc(sizeof(plugin_manager_t));
|
|
if (plugin_mng == NULL) {
|
|
log_error("Out of memory for create plugin manager");
|
|
return NULL;
|
|
}
|
|
|
|
rv = nng_mtx_alloc(&plugin_mng->mtx);
|
|
if (rv != 0) {
|
|
log_error("Failed to initialize mutex in plugin manager");
|
|
return NULL;
|
|
}
|
|
|
|
plugin_mng->new_plugin_id.id_val = MIN_DYNAMIC_PLUGIN_ID;
|
|
rv = init_system_plugins(&plugin_mng->system_plugins);
|
|
rv1 = init_custom_plugins(&plugin_mng->custom_plugins);
|
|
if (rv != 0 || rv1 != 0) {
|
|
log_error("Failed to initialize register table of plugins");
|
|
return NULL;
|
|
}
|
|
|
|
rv = vector_init(&plugin_mng->available_ids, CUSTOM_PLUGIN_COUNT_DEFAULT,
|
|
sizeof(plugin_id_t));
|
|
if (rv != 0) {
|
|
log_error("Failed to initialize vector of available ids");
|
|
return NULL;
|
|
}
|
|
|
|
return plugin_mng;
|
|
}
|
|
|
|
void plugin_manager_destroy(plugin_manager_t *plugin_mng)
|
|
{
|
|
if (plugin_mng == NULL) {
|
|
return;
|
|
}
|
|
|
|
vector_uninit(&plugin_mng->available_ids);
|
|
uninit_custom_plugins(&plugin_mng->custom_plugins);
|
|
uninit_system_plugins(&plugin_mng->system_plugins);
|
|
nng_mtx_free(plugin_mng->mtx);
|
|
free(plugin_mng);
|
|
}
|
|
|
|
/* If there already has same plugin registered, then return 0
|
|
*/
|
|
int plugin_manager_reg_plugin(plugin_manager_t * plugin_mng,
|
|
const plugin_reg_param_t *param,
|
|
plugin_id_t * p_plugin_id)
|
|
{
|
|
int rv;
|
|
int retry_count;
|
|
vector_t * plugins;
|
|
plugin_reg_entity_t reg_entity;
|
|
|
|
if (plugin_mng == NULL || param == NULL || p_plugin_id == NULL) {
|
|
log_error("Register plugin with NULL pointer");
|
|
return -1;
|
|
}
|
|
|
|
if (param->plugin_kind == PLUGIN_KIND_STATIC) {
|
|
size_t index;
|
|
/* static plugin had already been registered */
|
|
p_plugin_id->id_val = 0;
|
|
index = find_static_plugin_by_name(param->plugin_name);
|
|
if (index != SIZE_MAX) {
|
|
*p_plugin_id = builtin_static_plugins[index].plugin_id;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
plugins = &plugin_mng->system_plugins;
|
|
if (param->plugin_kind == PLUGIN_KIND_CUSTOM) {
|
|
plugins = &plugin_mng->custom_plugins;
|
|
}
|
|
|
|
*p_plugin_id = plugin_manager_get_plugin_id(plugin_mng, param);
|
|
if (p_plugin_id->id_val == 0) {
|
|
// There has same registered plugin
|
|
log_warn("A plugin with same name has already been registered");
|
|
return NEU_ERR_PLUGIN_LIBRARY_NAME_CONFLICT;
|
|
}
|
|
|
|
reg_entity_init(®_entity, *p_plugin_id, param);
|
|
|
|
rv = -1;
|
|
retry_count = 3;
|
|
useconds_t sleep_time = 300;
|
|
while (retry_count-- > 0 && rv != 0) {
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
rv = vector_push_back(plugins, ®_entity);
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
if (rv != 0) {
|
|
usleep(sleep_time);
|
|
sleep_time *= 2;
|
|
}
|
|
}
|
|
if (rv == 0) {
|
|
log_info("Register the plugin: %s", reg_entity.plugin_name);
|
|
} else {
|
|
log_error("Failed to register plugin: %s", reg_entity.plugin_name);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
int plugin_manager_unreg_plugin(plugin_manager_t *plugin_mng,
|
|
plugin_id_t plugin_id)
|
|
{
|
|
size_t index;
|
|
vector_t * plugins;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
if (plugin_id.id_val <= BUILTIN_STATIC_PLUGIN_COUNT) {
|
|
/* Don't to unregister the static plugin */
|
|
return 0;
|
|
}
|
|
|
|
int i;
|
|
vector_t *plugins_array[2] = { &plugin_mng->system_plugins,
|
|
&plugin_mng->custom_plugins };
|
|
for (i = 0; i < 2; i++) {
|
|
plugins = plugins_array[i];
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
index = find_plugin_by_id(plugins, plugin_id);
|
|
if (index != SIZE_MAX) {
|
|
reg_entity = (plugin_reg_entity_t *) vector_get(plugins, index);
|
|
log_info("Unregister the plugin: %s", reg_entity->plugin_name);
|
|
reg_entity_uninit(reg_entity);
|
|
vector_erase(plugins, index);
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
return 0;
|
|
}
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
}
|
|
|
|
log_warn("Can't find plugin with plugin_id: %d", plugin_id.id_val);
|
|
return -1;
|
|
}
|
|
|
|
void plugin_manager_unreg_all_plugins(plugin_manager_t *plugin_mng)
|
|
{
|
|
vector_t * plugins;
|
|
plugin_reg_entity_t *reg_entity;
|
|
int i;
|
|
|
|
vector_t *plugins_array[2] = { &plugin_mng->system_plugins,
|
|
&plugin_mng->custom_plugins };
|
|
for (i = 0; i < 2; i++) {
|
|
plugins = plugins_array[i];
|
|
VECTOR_FOR_EACH(plugins, iter)
|
|
{
|
|
reg_entity = (plugin_reg_entity_t *) iterator_get(&iter);
|
|
reg_entity_uninit(reg_entity);
|
|
}
|
|
vector_clear(plugins);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int plugin_manager_update_plugin(plugin_manager_t * plugin_mng,
|
|
const plugin_reg_param_t *param)
|
|
{
|
|
int rv = 0;
|
|
size_t index;
|
|
vector_t *plugins;
|
|
|
|
if (param->plugin_kind == PLUGIN_KIND_STATIC) {
|
|
/* Can't to be updated for static plugin */
|
|
return -1;
|
|
}
|
|
|
|
plugins = &plugin_mng->system_plugins;
|
|
if (param->plugin_kind == PLUGIN_KIND_CUSTOM) {
|
|
plugins = &plugin_mng->custom_plugins;
|
|
}
|
|
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
index = find_plugin_by_name(plugins, (const char *) param->plugin_name);
|
|
if (index != SIZE_MAX) {
|
|
plugin_id_t plugin_id;
|
|
plugin_reg_entity_t *old_reg_entity;
|
|
plugin_reg_entity_t reg_entity;
|
|
|
|
old_reg_entity = (plugin_reg_entity_t *) vector_get(plugins, index);
|
|
plugin_id = old_reg_entity->plugin_id;
|
|
reg_entity_uninit(old_reg_entity);
|
|
|
|
reg_entity_init(®_entity, plugin_id, param);
|
|
vector_assign(plugins, index, ®_entity);
|
|
log_info("Update the plugin: %s", reg_entity.plugin_name);
|
|
} else {
|
|
// Nothing to update
|
|
log_error("Failed to update the plugin: %s", param->plugin_name);
|
|
rv = -1;
|
|
}
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
return rv;
|
|
}
|
|
|
|
void reg_info_from_reg_entity(plugin_reg_info_t * reg_info,
|
|
plugin_reg_entity_t *reg_entity)
|
|
{
|
|
reg_info->plugin_id = reg_entity->plugin_id;
|
|
reg_info->plugin_kind = reg_entity->plugin_kind;
|
|
reg_info->adapter_type = reg_entity->adapter_type;
|
|
reg_info->plugin_name = reg_entity->plugin_name;
|
|
reg_info->plugin_lib_name = reg_entity->plugin_lib_name;
|
|
return;
|
|
}
|
|
|
|
int plugin_manager_get_reg_info(plugin_manager_t * plugin_mng,
|
|
plugin_id_t plugin_id,
|
|
plugin_reg_info_t *reg_info)
|
|
{
|
|
size_t index;
|
|
vector_t * plugins;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
if (plugin_mng == NULL || reg_info == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
index = find_static_plugin_by_id(plugin_id);
|
|
if (index != SIZE_MAX) {
|
|
reg_entity = (plugin_reg_entity_t *) &builtin_static_plugins[index];
|
|
reg_info_from_reg_entity(reg_info, reg_entity);
|
|
return 0;
|
|
}
|
|
|
|
int i;
|
|
vector_t *plugins_array[2] = { &plugin_mng->system_plugins,
|
|
&plugin_mng->custom_plugins };
|
|
for (i = 0; i < 2; i++) {
|
|
plugins = plugins_array[i];
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
index = find_plugin_by_id(plugins, plugin_id);
|
|
if (index != SIZE_MAX) {
|
|
reg_entity = (plugin_reg_entity_t *) vector_get(plugins, index);
|
|
reg_info_from_reg_entity(reg_info, reg_entity);
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
return 0;
|
|
}
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int plugin_manager_get_reg_info_by_name(plugin_manager_t * plugin_mng,
|
|
const char * plugin_name,
|
|
plugin_reg_info_t *reg_info)
|
|
{
|
|
size_t index;
|
|
vector_t * plugins;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
if (plugin_mng == NULL || plugin_name == NULL || reg_info == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
index = find_static_plugin_by_name(plugin_name);
|
|
if (index != SIZE_MAX) {
|
|
reg_entity = (plugin_reg_entity_t *) &builtin_static_plugins[index];
|
|
reg_info_from_reg_entity(reg_info, reg_entity);
|
|
return 0;
|
|
}
|
|
|
|
int i;
|
|
vector_t *plugins_array[2] = { &plugin_mng->system_plugins,
|
|
&plugin_mng->custom_plugins };
|
|
for (i = 0; i < 2; i++) {
|
|
plugins = plugins_array[i];
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
index = find_plugin_by_name(plugins, plugin_name);
|
|
if (index != SIZE_MAX) {
|
|
reg_entity = (plugin_reg_entity_t *) vector_get(plugins, index);
|
|
reg_info_from_reg_entity(reg_info, reg_entity);
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
return 0;
|
|
}
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
vector_t *plugin_manager_get_all_plugins(plugin_manager_t *plugin_mng)
|
|
{
|
|
size_t count;
|
|
vector_t * plugin_info_vec;
|
|
vector_t * plugins;
|
|
plugin_reg_info_t reg_info;
|
|
plugin_reg_entity_t *reg_entity;
|
|
|
|
if (plugin_mng == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
count = BUILTIN_STATIC_PLUGIN_COUNT;
|
|
count += plugin_mng->system_plugins.size + plugin_mng->custom_plugins.size;
|
|
plugin_info_vec = vector_new(count, sizeof(plugin_reg_info_t));
|
|
if (plugin_info_vec == NULL) {
|
|
log_error("No memory to new vector of plugin infos");
|
|
return NULL;
|
|
}
|
|
|
|
size_t i;
|
|
for (i = 0; i < BUILTIN_STATIC_PLUGIN_COUNT; i++) {
|
|
reg_entity = (plugin_reg_entity_t *) &builtin_static_plugins[i];
|
|
reg_info_from_reg_entity(®_info, reg_entity);
|
|
vector_push_back(plugin_info_vec, ®_info);
|
|
}
|
|
|
|
vector_t *plugins_array[2] = { &plugin_mng->system_plugins,
|
|
&plugin_mng->custom_plugins };
|
|
for (i = 0; i < 2; i++) {
|
|
plugins = plugins_array[i];
|
|
nng_mtx_lock(plugin_mng->mtx);
|
|
VECTOR_FOR_EACH(plugins, iter)
|
|
{
|
|
reg_entity = (plugin_reg_entity_t *) iterator_get(&iter);
|
|
reg_info_from_reg_entity(®_info, reg_entity);
|
|
vector_push_back(plugin_info_vec, ®_info);
|
|
}
|
|
nng_mtx_unlock(plugin_mng->mtx);
|
|
}
|
|
|
|
return plugin_info_vec;
|
|
}
|
|
|
|
void plugin_manager_dump(plugin_manager_t *plugin_mng)
|
|
{
|
|
// TODO: dump system plugins and custom plugins
|
|
(void) plugin_mng;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* load plugin and unload plugin
|
|
*/
|
|
|
|
static void *load_dyn_plugin_library(char *driver_path, char *plugin_lib_name,
|
|
neu_plugin_module_t **p_plugin_module)
|
|
{
|
|
void *lib_handle;
|
|
|
|
if (driver_path == NULL) {
|
|
lib_handle = dlopen(plugin_lib_name, RTLD_NOW | RTLD_NODELETE);
|
|
} else {
|
|
char lib_path[128] = { 0 };
|
|
snprintf(lib_path, sizeof(lib_path) - 1, "%s%s", driver_path,
|
|
plugin_lib_name);
|
|
lib_handle = dlopen(lib_path, RTLD_NOW | RTLD_NODELETE);
|
|
}
|
|
|
|
if (lib_handle == NULL) {
|
|
log_error("Failed to open dynamic library %s: %s", plugin_lib_name,
|
|
dlerror());
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void *module_info;
|
|
module_info = dlsym(lib_handle, "neu_plugin_module");
|
|
if (module_info == NULL) {
|
|
dlclose(lib_handle);
|
|
log_error("Failed to get neu_plugin_module from %s", plugin_lib_name);
|
|
return NULL;
|
|
}
|
|
|
|
if (p_plugin_module != NULL) {
|
|
*p_plugin_module = (neu_plugin_module_t *) module_info;
|
|
}
|
|
return lib_handle;
|
|
}
|
|
|
|
static int unload_dyn_plugin_library(void *lib_handle)
|
|
{
|
|
return dlclose(lib_handle);
|
|
}
|
|
|
|
typedef struct plugin_module_map {
|
|
const char * plugin_lib_name;
|
|
const neu_plugin_module_t *plugin_module;
|
|
} plugin_module_map_t;
|
|
|
|
static const plugin_module_map_t plugin_module_maps[] = {
|
|
{
|
|
DEFAULT_DASHBOARD_PLUGIN_LIB_NAME,
|
|
&default_dashboard_plugin_module,
|
|
|
|
},
|
|
{
|
|
DEFAULT_DUMMY_PLUGIN_LIB_NAME,
|
|
&default_dummy_plugin_module,
|
|
},
|
|
};
|
|
#define PLUGIN_MODULE_MAPS_COUNT \
|
|
(sizeof(plugin_module_maps) / sizeof(plugin_module_maps[0]))
|
|
|
|
// return index of plugin in static plugin list
|
|
static void *load_static_plugin(char * plugin_lib_name,
|
|
neu_plugin_module_t **p_plugin_module)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < PLUGIN_MODULE_MAPS_COUNT; i++) {
|
|
if (strcmp(plugin_lib_name, plugin_module_maps[i].plugin_lib_name) ==
|
|
0) {
|
|
if (p_plugin_module != NULL) {
|
|
*p_plugin_module =
|
|
(neu_plugin_module_t *) plugin_module_maps[i].plugin_module;
|
|
}
|
|
return (void *) (i + 1); // the pointer must not be NULL
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static int unload_static_plugin(void *lib_handle)
|
|
{
|
|
/* do nothing */
|
|
(void) lib_handle;
|
|
return 0;
|
|
}
|
|
|
|
// if plugin is static plugin then return index of plugin in static plugin list
|
|
void *load_plugin_library(char *plugin_lib_name, plugin_kind_e plugin_kind,
|
|
neu_plugin_module_t **p_plugin_module)
|
|
{
|
|
char *path = NULL;
|
|
void *result = NULL;
|
|
|
|
path = neu_config_get_value(2, "driver", "path");
|
|
|
|
switch (plugin_kind) {
|
|
case PLUGIN_KIND_STATIC:
|
|
result = load_static_plugin(plugin_lib_name, p_plugin_module);
|
|
break;
|
|
case PLUGIN_KIND_SYSTEM:
|
|
case PLUGIN_KIND_CUSTOM:
|
|
result =
|
|
load_dyn_plugin_library(path, plugin_lib_name, p_plugin_module);
|
|
break;
|
|
}
|
|
|
|
if (path != NULL) {
|
|
free(path);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int unload_plugin_library(void *lib_handle, plugin_kind_e plugin_kind)
|
|
{
|
|
if (plugin_kind == PLUGIN_KIND_STATIC) {
|
|
return unload_static_plugin(lib_handle);
|
|
} else {
|
|
return unload_dyn_plugin_library(lib_handle);
|
|
}
|
|
}
|