PageRenderTime 78ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llplugin/llplugininstance.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 186 lines | 95 code | 22 blank | 69 comment | 15 complexity | c7443ec3099f1d629c4dedfd56c0d514 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llplugininstance.cpp
  3. * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
  4. *
  5. * @cond
  6. * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. * @endcond
  27. */
  28. #include "linden_common.h"
  29. #include "llplugininstance.h"
  30. #include "llapr.h"
  31. #if LL_WINDOWS
  32. #include "direct.h" // needed for _chdir()
  33. #endif
  34. /** Virtual destructor. */
  35. LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
  36. {
  37. }
  38. /**
  39. * TODO:DOC describe how it's used
  40. */
  41. const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoint";
  42. /**
  43. * Constructor.
  44. *
  45. * @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is?
  46. */
  47. LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) :
  48. mDSOHandle(NULL),
  49. mPluginUserData(NULL),
  50. mPluginSendMessageFunction(NULL)
  51. {
  52. mOwner = owner;
  53. }
  54. /**
  55. * Destructor.
  56. */
  57. LLPluginInstance::~LLPluginInstance()
  58. {
  59. if(mDSOHandle != NULL)
  60. {
  61. apr_dso_unload(mDSOHandle);
  62. mDSOHandle = NULL;
  63. }
  64. }
  65. /**
  66. * Dynamically loads the plugin and runs the plugin's init function.
  67. *
  68. * @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h
  69. * @return 0 if successful, APR error code or error code from the plugin's init function on failure.
  70. */
  71. int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_file)
  72. {
  73. pluginInitFunction init_function = NULL;
  74. if ( plugin_dir.length() )
  75. {
  76. #if LL_WINDOWS
  77. // VWR-21275:
  78. // *SOME* Windows systems fail to load the Qt plugins if the current working
  79. // directory is not the same as the directory with the Qt DLLs in.
  80. // This should not cause any run time issues since we are changing the cwd for the
  81. // plugin shell process and not the viewer.
  82. // Changing back to the previous directory is not necessary since the plugin shell
  83. // quits once the plugin exits.
  84. _chdir( plugin_dir.c_str() );
  85. #endif
  86. };
  87. int result = apr_dso_load(&mDSOHandle,
  88. plugin_file.c_str(),
  89. gAPRPoolp);
  90. if(result != APR_SUCCESS)
  91. {
  92. char buf[1024];
  93. apr_dso_error(mDSOHandle, buf, sizeof(buf));
  94. LL_WARNS("Plugin") << "apr_dso_load of " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL;
  95. }
  96. if(result == APR_SUCCESS)
  97. {
  98. result = apr_dso_sym((apr_dso_handle_sym_t*)&init_function,
  99. mDSOHandle,
  100. PLUGIN_INIT_FUNCTION_NAME);
  101. if(result != APR_SUCCESS)
  102. {
  103. LL_WARNS("Plugin") << "apr_dso_sym failed with error " << result << LL_ENDL;
  104. }
  105. }
  106. if(result == APR_SUCCESS)
  107. {
  108. result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData);
  109. if(result != APR_SUCCESS)
  110. {
  111. LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL;
  112. }
  113. }
  114. return (int)result;
  115. }
  116. /**
  117. * Sends a message to the plugin.
  118. *
  119. * @param[in] message Message
  120. */
  121. void LLPluginInstance::sendMessage(const std::string &message)
  122. {
  123. if(mPluginSendMessageFunction)
  124. {
  125. LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL;
  126. mPluginSendMessageFunction(message.c_str(), &mPluginUserData);
  127. }
  128. else
  129. {
  130. LL_WARNS("Plugin") << "dropping message: \"" << message << "\"" << LL_ENDL;
  131. }
  132. }
  133. /**
  134. * Idle. TODO:DOC what's the purpose of this?
  135. *
  136. */
  137. void LLPluginInstance::idle(void)
  138. {
  139. }
  140. // static
  141. void LLPluginInstance::staticReceiveMessage(const char *message_string, void **user_data)
  142. {
  143. // TODO: validate that the user_data argument is still a valid LLPluginInstance pointer
  144. // we could also use a key that's looked up in a map (instead of a direct pointer) for safety, but that's probably overkill
  145. LLPluginInstance *self = (LLPluginInstance*)*user_data;
  146. self->receiveMessage(message_string);
  147. }
  148. /**
  149. * Plugin receives message from plugin loader shell.
  150. *
  151. * @param[in] message_string Message
  152. */
  153. void LLPluginInstance::receiveMessage(const char *message_string)
  154. {
  155. if(mOwner)
  156. {
  157. LL_DEBUGS("Plugin") << "processing incoming message: \"" << message_string << "\"" << LL_ENDL;
  158. mOwner->receivePluginMessage(message_string);
  159. }
  160. else
  161. {
  162. LL_WARNS("Plugin") << "dropping incoming message: \"" << message_string << "\"" << LL_ENDL;
  163. }
  164. }