PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llplugin/llpluginmessage.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 438 lines | 181 code | 59 blank | 198 comment | 10 complexity | 9a6639ec8495221b3154b087d1ad3f9e MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpluginmessage.cpp
  3. * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
  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 "llpluginmessage.h"
  30. #include "llsdserialize.h"
  31. #include "u64.h"
  32. /**
  33. * Constructor.
  34. */
  35. LLPluginMessage::LLPluginMessage()
  36. {
  37. }
  38. /**
  39. * Constructor.
  40. *
  41. * @param[in] p Existing message
  42. */
  43. LLPluginMessage::LLPluginMessage(const LLPluginMessage &p)
  44. {
  45. mMessage = p.mMessage;
  46. }
  47. /**
  48. * Constructor.
  49. *
  50. * @param[in] message_class Message class
  51. * @param[in] message_name Message name
  52. */
  53. LLPluginMessage::LLPluginMessage(const std::string &message_class, const std::string &message_name)
  54. {
  55. setMessage(message_class, message_name);
  56. }
  57. /**
  58. * Destructor.
  59. */
  60. LLPluginMessage::~LLPluginMessage()
  61. {
  62. }
  63. /**
  64. * Reset all internal state.
  65. */
  66. void LLPluginMessage::clear()
  67. {
  68. mMessage = LLSD::emptyMap();
  69. mMessage["params"] = LLSD::emptyMap();
  70. }
  71. /**
  72. * Sets the message class and name. Also has the side-effect of clearing any key-value pairs in the message.
  73. *
  74. * @param[in] message_class Message class
  75. * @param[in] message_name Message name
  76. */
  77. void LLPluginMessage::setMessage(const std::string &message_class, const std::string &message_name)
  78. {
  79. clear();
  80. mMessage["class"] = message_class;
  81. mMessage["name"] = message_name;
  82. }
  83. /**
  84. * Sets a key/value pair in the message, where the value is a string.
  85. *
  86. * @param[in] key Key
  87. * @param[in] value String value
  88. */
  89. void LLPluginMessage::setValue(const std::string &key, const std::string &value)
  90. {
  91. mMessage["params"][key] = value;
  92. }
  93. /**
  94. * Sets a key/value pair in the message, where the value is LLSD.
  95. *
  96. * @param[in] key Key
  97. * @param[in] value LLSD value
  98. */
  99. void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value)
  100. {
  101. mMessage["params"][key] = value;
  102. }
  103. /**
  104. * Sets a key/value pair in the message, where the value is signed 32-bit.
  105. *
  106. * @param[in] key Key
  107. * @param[in] value 32-bit signed value
  108. */
  109. void LLPluginMessage::setValueS32(const std::string &key, S32 value)
  110. {
  111. mMessage["params"][key] = value;
  112. }
  113. /**
  114. * Sets a key/value pair in the message, where the value is unsigned 32-bit. The value is stored as a string beginning with "0x".
  115. *
  116. * @param[in] key Key
  117. * @param[in] value 32-bit unsigned value
  118. */
  119. void LLPluginMessage::setValueU32(const std::string &key, U32 value)
  120. {
  121. std::stringstream temp;
  122. temp << "0x" << std::hex << value;
  123. setValue(key, temp.str());
  124. }
  125. /**
  126. * Sets a key/value pair in the message, where the value is a bool.
  127. *
  128. * @param[in] key Key
  129. * @param[in] value Boolean value
  130. */
  131. void LLPluginMessage::setValueBoolean(const std::string &key, bool value)
  132. {
  133. mMessage["params"][key] = value;
  134. }
  135. /**
  136. * Sets a key/value pair in the message, where the value is a double.
  137. *
  138. * @param[in] key Key
  139. * @param[in] value Boolean value
  140. */
  141. void LLPluginMessage::setValueReal(const std::string &key, F64 value)
  142. {
  143. mMessage["params"][key] = value;
  144. }
  145. /**
  146. * Sets a key/value pair in the message, where the value is a pointer. The pointer is stored as a string.
  147. *
  148. * @param[in] key Key
  149. * @param[in] value Pointer value
  150. */
  151. void LLPluginMessage::setValuePointer(const std::string &key, void* value)
  152. {
  153. std::stringstream temp;
  154. // iostreams should output pointer values in hex with an initial 0x by default.
  155. temp << value;
  156. setValue(key, temp.str());
  157. }
  158. /**
  159. * Gets the message class.
  160. *
  161. * @return Message class
  162. */
  163. std::string LLPluginMessage::getClass(void) const
  164. {
  165. return mMessage["class"];
  166. }
  167. /**
  168. * Gets the message name.
  169. *
  170. * @return Message name
  171. */
  172. std::string LLPluginMessage::getName(void) const
  173. {
  174. return mMessage["name"];
  175. }
  176. /**
  177. * Returns true if the specified key exists in this message (useful for optional parameters).
  178. *
  179. * @param[in] key Key
  180. *
  181. * @return True if key exists, false otherwise.
  182. */
  183. bool LLPluginMessage::hasValue(const std::string &key) const
  184. {
  185. bool result = false;
  186. if(mMessage["params"].has(key))
  187. {
  188. result = true;
  189. }
  190. return result;
  191. }
  192. /**
  193. * Gets the value of a key as a string. If the key does not exist, an empty string will be returned.
  194. *
  195. * @param[in] key Key
  196. *
  197. * @return String value of key if key exists, empty string if key does not exist.
  198. */
  199. std::string LLPluginMessage::getValue(const std::string &key) const
  200. {
  201. std::string result;
  202. if(mMessage["params"].has(key))
  203. {
  204. result = mMessage["params"][key].asString();
  205. }
  206. return result;
  207. }
  208. /**
  209. * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned.
  210. *
  211. * @param[in] key Key
  212. *
  213. * @return LLSD value of key if key exists, null LLSD if key does not exist.
  214. */
  215. LLSD LLPluginMessage::getValueLLSD(const std::string &key) const
  216. {
  217. LLSD result;
  218. if(mMessage["params"].has(key))
  219. {
  220. result = mMessage["params"][key];
  221. }
  222. return result;
  223. }
  224. /**
  225. * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned.
  226. *
  227. * @param[in] key Key
  228. *
  229. * @return Signed 32-bit int value of key if key exists, 0 if key does not exist.
  230. */
  231. S32 LLPluginMessage::getValueS32(const std::string &key) const
  232. {
  233. S32 result = 0;
  234. if(mMessage["params"].has(key))
  235. {
  236. result = mMessage["params"][key].asInteger();
  237. }
  238. return result;
  239. }
  240. /**
  241. * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned.
  242. *
  243. * @param[in] key Key
  244. *
  245. * @return Unsigned 32-bit int value of key if key exists, 0 if key does not exist.
  246. */
  247. U32 LLPluginMessage::getValueU32(const std::string &key) const
  248. {
  249. U32 result = 0;
  250. if(mMessage["params"].has(key))
  251. {
  252. std::string value = mMessage["params"][key].asString();
  253. result = (U32)strtoul(value.c_str(), NULL, 16);
  254. }
  255. return result;
  256. }
  257. /**
  258. * Gets the value of a key as a bool. If the key does not exist, false will be returned.
  259. *
  260. * @param[in] key Key
  261. *
  262. * @return Boolean value of key if it exists, false otherwise.
  263. */
  264. bool LLPluginMessage::getValueBoolean(const std::string &key) const
  265. {
  266. bool result = false;
  267. if(mMessage["params"].has(key))
  268. {
  269. result = mMessage["params"][key].asBoolean();
  270. }
  271. return result;
  272. }
  273. /**
  274. * Gets the value of a key as a double. If the key does not exist, 0 will be returned.
  275. *
  276. * @param[in] key Key
  277. *
  278. * @return Value as a double if key exists, 0 otherwise.
  279. */
  280. F64 LLPluginMessage::getValueReal(const std::string &key) const
  281. {
  282. F64 result = 0.0f;
  283. if(mMessage["params"].has(key))
  284. {
  285. result = mMessage["params"][key].asReal();
  286. }
  287. return result;
  288. }
  289. /**
  290. * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned.
  291. *
  292. * @param[in] key Key
  293. *
  294. * @return Pointer value if key exists, NULL otherwise.
  295. */
  296. void* LLPluginMessage::getValuePointer(const std::string &key) const
  297. {
  298. void* result = NULL;
  299. if(mMessage["params"].has(key))
  300. {
  301. std::string value = mMessage["params"][key].asString();
  302. result = (void*)llstrtou64(value.c_str(), NULL, 16);
  303. }
  304. return result;
  305. }
  306. /**
  307. * Flatten the message into a string.
  308. *
  309. * @return Message as a string.
  310. */
  311. std::string LLPluginMessage::generate(void) const
  312. {
  313. std::ostringstream result;
  314. // Pretty XML may be slightly easier to deal with while debugging...
  315. // LLSDSerialize::toXML(mMessage, result);
  316. LLSDSerialize::toPrettyXML(mMessage, result);
  317. return result.str();
  318. }
  319. /**
  320. * Parse an incoming message into component parts. Clears all existing state before starting the parse.
  321. *
  322. * @return Returns -1 on failure, otherwise returns the number of key/value pairs in the incoming message.
  323. */
  324. int LLPluginMessage::parse(const std::string &message)
  325. {
  326. // clear any previous state
  327. clear();
  328. std::istringstream input(message);
  329. S32 parse_result = LLSDSerialize::fromXML(mMessage, input);
  330. return (int)parse_result;
  331. }
  332. /**
  333. * Destructor
  334. */
  335. LLPluginMessageListener::~LLPluginMessageListener()
  336. {
  337. // TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted?
  338. }
  339. /**
  340. * Destructor
  341. */
  342. LLPluginMessageDispatcher::~LLPluginMessageDispatcher()
  343. {
  344. }
  345. /**
  346. * Add a message listener. TODO:DOC need more info on what uses this. when are multiple listeners needed?
  347. *
  348. * @param[in] listener Message listener
  349. */
  350. void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener *listener)
  351. {
  352. mListeners.insert(listener);
  353. }
  354. /**
  355. * Remove a message listener.
  356. *
  357. * @param[in] listener Message listener
  358. */
  359. void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListener *listener)
  360. {
  361. mListeners.erase(listener);
  362. }
  363. /**
  364. * Distribute a message to all message listeners.
  365. *
  366. * @param[in] message Message
  367. */
  368. void LLPluginMessageDispatcher::dispatchPluginMessage(const LLPluginMessage &message)
  369. {
  370. for (listener_set_t::iterator it = mListeners.begin();
  371. it != mListeners.end();
  372. )
  373. {
  374. LLPluginMessageListener* listener = *it;
  375. listener->receivePluginMessage(message);
  376. // In case something deleted an entry.
  377. it = mListeners.upper_bound(listener);
  378. }
  379. }