ECPluginFactory.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include <cstring>
  19. #include <climits>
  20. #include "ECPluginFactory.h"
  21. #include <kopano/ECConfig.h>
  22. #include <kopano/ECLogger.h>
  23. #include <kopano/ecversion.h>
  24. namespace KC {
  25. ECPluginFactory::ECPluginFactory(ECConfig *config, ECStatsCollector *lpStatsCollector,
  26. bool bHosted, bool bDistributed) :
  27. m_config(config)
  28. {
  29. ECPluginSharedData::GetSingleton(&m_shareddata, m_config, lpStatsCollector, bHosted, bDistributed);
  30. }
  31. ECPluginFactory::~ECPluginFactory() {
  32. #ifndef VALGRIND
  33. if(m_dl)
  34. dlclose(m_dl);
  35. #endif
  36. if (m_shareddata)
  37. m_shareddata->Release();
  38. }
  39. ECRESULT ECPluginFactory::CreateUserPlugin(UserPlugin **lppPlugin) {
  40. UserPlugin *lpPlugin = NULL;
  41. if(m_dl == NULL) {
  42. const char *pluginpath = m_config->GetSetting("plugin_path");
  43. const char *pluginname = m_config->GetSetting("user_plugin");
  44. char filename[PATH_MAX + 1];
  45. if (pluginpath == nullptr || strcmp(pluginpath, "") == 0)
  46. pluginpath = "";
  47. if (!pluginname || !strcmp(pluginname, "")) {
  48. ec_log_crit("User plugin is unavailable.");
  49. ec_log_crit("Please correct your configuration file and set the \"plugin_path\" and \"user_plugin\" options.");
  50. return KCERR_NOT_FOUND;
  51. }
  52. snprintf(filename, PATH_MAX + 1, "%s%c%splugin.%s",
  53. pluginpath, PATH_SEPARATOR, pluginname, SHARED_OBJECT_EXTENSION);
  54. m_dl = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
  55. if (!m_dl) {
  56. ec_log_crit("Failed to load \"%s\": %s", filename, dlerror());
  57. ec_log_crit("Please correct your configuration file and set the \"plugin_path\" and \"user_plugin\" options.");
  58. goto out;
  59. }
  60. int (*fngetUserPluginInstance)() = (int (*)()) dlsym(m_dl, "getUserPluginVersion");
  61. if (fngetUserPluginInstance == NULL) {
  62. ec_log_crit("Failed to load getUserPluginVersion from plugin: %s", dlerror());
  63. goto out;
  64. }
  65. int version = fngetUserPluginInstance();
  66. if (version != PROJECT_VERSION_REVISION) {
  67. ec_log_crit("Version of the plugin \"%s\" is not the same for the server. Expected %d, plugin %d", filename, PROJECT_VERSION_REVISION, version);
  68. goto out;
  69. }
  70. m_getUserPluginInstance = (UserPlugin* (*)(std::mutex &, ECPluginSharedData *)) dlsym(m_dl, "getUserPluginInstance");
  71. if (m_getUserPluginInstance == NULL) {
  72. ec_log_crit("Failed to load getUserPluginInstance from plugin: %s", dlerror());
  73. goto out;
  74. }
  75. m_deleteUserPluginInstance = (void (*)(UserPlugin *)) dlsym(m_dl, "deleteUserPluginInstance");
  76. if (m_deleteUserPluginInstance == NULL) {
  77. ec_log_crit("Failed to load deleteUserPluginInstance from plugin: %s", dlerror());
  78. goto out;
  79. }
  80. }
  81. try {
  82. lpPlugin = m_getUserPluginInstance(m_plugin_lock, m_shareddata);
  83. lpPlugin->InitPlugin();
  84. }
  85. catch (exception &e) {
  86. ec_log_crit("Cannot instantiate user plugin: %s", e.what());
  87. return KCERR_NOT_FOUND;
  88. }
  89. *lppPlugin = lpPlugin;
  90. return erSuccess;
  91. out:
  92. if (m_dl)
  93. dlclose(m_dl);
  94. m_dl = NULL;
  95. return KCERR_NOT_FOUND;
  96. }
  97. void ECPluginFactory::SignalPlugins(int signal)
  98. {
  99. m_shareddata->Signal(signal);
  100. }
  101. // Returns a plugin local to this thread. Works the same as GetThreadLocalDatabase
  102. extern pthread_key_t plugin_key;
  103. ECRESULT GetThreadLocalPlugin(ECPluginFactory *lpPluginFactory,
  104. UserPlugin **lppPlugin)
  105. {
  106. ECRESULT er;
  107. UserPlugin *lpPlugin = NULL;
  108. lpPlugin = (UserPlugin *)pthread_getspecific(plugin_key);
  109. if (lpPlugin == NULL) {
  110. er = lpPluginFactory->CreateUserPlugin(&lpPlugin);
  111. if (er != erSuccess) {
  112. lpPlugin = NULL;
  113. ec_log_crit("Unable to instantiate user plugin");
  114. return er;
  115. }
  116. pthread_setspecific(plugin_key, (void *)lpPlugin);
  117. }
  118. *lppPlugin = lpPlugin;
  119. return erSuccess;
  120. }
  121. } /* namespace */