// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include #include #include #include #ifdef _WIN32 #ifndef _WINSOCKAPI_ #include #endif #else #include #endif #include #include #include #include "../include/plugin_manager_impl.hpp" #ifdef ANDROID #include "../../configuration/include/internal_android.hpp" #else #include "../../configuration/include/internal.hpp" #endif // ANDROID #include "../../utility/include/utility.hpp" namespace vsomeip_v3 { std::shared_ptr plugin_manager_impl::the_plugin_manager__ = std::make_shared(); std::shared_ptr plugin_manager_impl::get() { return the_plugin_manager__; } plugin_manager_impl::plugin_manager_impl() : plugins_loaded_(false) { } plugin_manager_impl::~plugin_manager_impl() { handles_.clear(); plugins_.clear(); } void plugin_manager_impl::load_plugins() { { std::lock_guard its_lock_start_stop(loader_mutex_); if (plugins_loaded_) { return; } plugins_loaded_ = true; } // Get plug-ins libraries from environment std::vector plugins; const char *its_plugins = getenv(VSOMEIP_ENV_LOAD_PLUGINS); if (nullptr != its_plugins) { std::string token; std::stringstream ss(its_plugins); while(std::getline(ss, token, ',')) { plugins.push_back(token); } } std::lock_guard its_lock_start_stop(plugins_mutex_); // Load plug-in info from libraries parsed before for (const auto& plugin_name : plugins) { void* handle = load_library(plugin_name); plugin_init_func its_init_func = reinterpret_cast( load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL)); if (its_init_func) { create_plugin_func its_create_func = (*its_init_func)(); if (its_create_func) { auto its_plugin = (*its_create_func)(); if (its_plugin) { handles_[its_plugin->get_plugin_type()][plugin_name] = handle; switch (its_plugin->get_plugin_type()) { case plugin_type_e::APPLICATION_PLUGIN: if (its_plugin->get_plugin_version() == VSOMEIP_APPLICATION_PLUGIN_VERSION) { add_plugin(its_plugin, plugin_name); } else { VSOMEIP_ERROR << "Plugin version mismatch. " << "Ignoring application plugin " << its_plugin->get_plugin_name(); } break; case plugin_type_e::PRE_CONFIGURATION_PLUGIN: if (its_plugin->get_plugin_version() == VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION) { add_plugin(its_plugin, plugin_name); } else { VSOMEIP_ERROR << "Plugin version mismatch. Ignoring " << "pre-configuration plugin " << its_plugin->get_plugin_name(); } break; default: break; } } } } } } std::shared_ptr plugin_manager_impl::get_plugin(plugin_type_e _type, std::string _name) { std::lock_guard its_lock_start_stop(plugins_mutex_); auto its_type = plugins_.find(_type); if (its_type != plugins_.end()) { auto its_name = its_type->second.find(_name); if (its_name != its_type->second.end()) { return its_name->second; } } return load_plugin(_name, _type, 1); } std::shared_ptr plugin_manager_impl::load_plugin(const std::string& _library, plugin_type_e _type, uint32_t _version) { void* handle = load_library(_library); plugin_init_func its_init_func = reinterpret_cast( load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL)); if (its_init_func) { create_plugin_func its_create_func = (*its_init_func)(); if (its_create_func) { handles_[_type][_library] = handle; auto its_plugin = (*its_create_func)(); if (its_plugin) { if (its_plugin->get_plugin_type() == _type && its_plugin->get_plugin_version() == _version) { add_plugin(its_plugin, _library); return its_plugin; } else { VSOMEIP_ERROR << "Plugin version mismatch. Ignoring plugin " << its_plugin->get_plugin_name(); } } } } return nullptr; } bool plugin_manager_impl::unload_plugin(plugin_type_e _type) { std::lock_guard its_lock_start_stop(plugins_mutex_); const auto found_handle = handles_.find(_type); if (found_handle != handles_.end()) { for (const auto& its_name : found_handle->second) { #ifdef _WIN32 FreeLibrary((HMODULE)its_name.second); #else if (dlclose(its_name.second)) { VSOMEIP_ERROR << "Unloading failed: (" << dlerror() << ")"; } #endif } } else { VSOMEIP_ERROR << "plugin_manager_impl::unload_plugin didn't find plugin" << " type:" << (int)_type; return false; } return plugins_.erase(_type); } void plugin_manager_impl::add_plugin(const std::shared_ptr &_plugin, const std::string& _name) { plugins_[_plugin->get_plugin_type()][_name] = _plugin; } void * plugin_manager_impl::load_library(const std::string &_path) { #ifdef _WIN32 return LoadLibrary(_path.c_str()); #else return dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL); #endif } void * plugin_manager_impl::load_symbol(void * _handle, const std::string &_symbol) { void * its_symbol = 0; #ifdef _WIN32 HINSTANCE hDLL = (HINSTANCE)_handle; if (hDLL != NULL) { typedef UINT(CALLBACK* LPFNDLLFUNC1)(DWORD, UINT); LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, _symbol.c_str()); if (!lpfnDllFunc1) { FreeLibrary(hDLL); std::cerr << "Loading symbol \"" << _symbol << "\" failed (" << GetLastError() << ")" << std::endl; } else { its_symbol = lpfnDllFunc1; } } #else if (0 != _handle) { dlerror(); // Clear previous error its_symbol = dlsym(_handle, _symbol.c_str()); const char *dlsym_error = dlerror(); if (dlsym_error) { VSOMEIP_INFO << "Cannot load symbol : " << _symbol << " : " << dlsym_error; dlclose(_handle); } } else { VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")"; } #endif return (its_symbol); } } // namespace vsomeip_v3