lleventdispatcher.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. /**
  2. * @file lleventdispatcher.cpp
  3. * @author Nat Goodspeed
  4. * @date 2009-06-18
  5. * @brief Implementation for lleventdispatcher.
  6. *
  7. * $LicenseInfo:firstyear=2009&license=viewergpl$
  8. *
  9. * Copyright (c) 2010-2022, Linden Research, Inc.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #if LL_WINDOWS
  35. // 'this' used in initializer list: yes, intentionally
  36. # pragma warning (disable : 4355)
  37. #endif
  38. #include <sstream>
  39. #include "linden_common.h"
  40. #include "lleventdispatcher.h"
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // DispatchError
  43. ///////////////////////////////////////////////////////////////////////////////
  44. struct DispatchError : public std::runtime_error
  45. {
  46. LL_INLINE DispatchError(const std::string& what)
  47. : std::runtime_error(what)
  48. {
  49. }
  50. LL_INLINE DispatchError(const char* what)
  51. : std::runtime_error(what)
  52. {
  53. }
  54. };
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // LLSDArgsSource
  57. ///////////////////////////////////////////////////////////////////////////////
  58. // Stores an LLSD array, producing its elements one at a time. Throws if the
  59. // consumer requests more elements than the array contains.
  60. class LLSDArgsSource
  61. {
  62. protected:
  63. LOG_CLASS(LLSDArgsSource);
  64. public:
  65. LLSDArgsSource(const std::string function, const LLSD& args);
  66. ~LLSDArgsSource();
  67. LLSD next();
  68. void done() const;
  69. private:
  70. std::string mFunction;
  71. LLSD mArgs;
  72. size_t mIndex;
  73. };
  74. LLSDArgsSource::LLSDArgsSource(const std::string function, const LLSD& args)
  75. : mFunction(function),
  76. mArgs(args),
  77. mIndex(0)
  78. {
  79. if (!(mArgs.isUndefined() || mArgs.isArray()))
  80. {
  81. std::ostringstream s;
  82. s << mFunction << " needs an args array instead of " << mArgs;
  83. llwarns << s.str() << llendl;
  84. throw DispatchError(s.str());
  85. }
  86. }
  87. LLSDArgsSource::~LLSDArgsSource()
  88. {
  89. done();
  90. }
  91. LLSD LLSDArgsSource::next()
  92. {
  93. if (mIndex >= mArgs.size())
  94. {
  95. std::ostringstream s;
  96. s << mFunction << " requires more arguments than the "
  97. << mArgs.size() << " provided: " << mArgs;
  98. llwarns << s.str() << llendl;
  99. throw DispatchError(s.str());
  100. }
  101. return mArgs[mIndex++];
  102. }
  103. void LLSDArgsSource::done() const
  104. {
  105. if (mIndex < mArgs.size())
  106. {
  107. std::ostringstream s;
  108. s << mFunction << " only consumed " << mIndex << " of the "
  109. << mArgs.size() << " arguments provided: " << mArgs;
  110. llwarns << s.str() << llendl;
  111. throw DispatchError(s.str());
  112. }
  113. }
  114. ///////////////////////////////////////////////////////////////////////////////
  115. // LLSDArgsMapper
  116. ///////////////////////////////////////////////////////////////////////////////
  117. // From a formal parameters description and a map of arguments, construct an
  118. // arguments array.
  119. //
  120. // That is, given:
  121. // - an LLSD array of length n containing parameter-name strings,
  122. // corresponding to the arguments of a function of interest
  123. // - an LLSD collection specifying default parameter values, either:
  124. // - an LLSD array of length m <= n, matching the rightmost m params, or
  125. // - an LLSD map explicitly stating default name=value pairs
  126. // - an LLSD map of parameter names and actual values for a particular
  127. // function call
  128. // construct an LLSD array of actual argument values for this function call.
  129. //
  130. // The parameter-names array and the defaults collection describe the function
  131. // being called. The map might vary with every call, providing argument values
  132. // for the described parameters.
  133. //
  134. // The array of parameter names must match the number of parameters expected
  135. // by the function of interest.
  136. //
  137. // If you pass a map of default parameter values, it provides default values
  138. // as you might expect. It is an error to specify a default value for a name
  139. // not listed in the parameters array.
  140. //
  141. // If you pass an array of default parameter values, it is mapped to the
  142. // rightmost m of the n parameter names. It is an error if the default-values
  143. // array is longer than the parameter-names array. Consider the following
  144. // parameter names: ["a", "b", "c", "d"].
  145. //
  146. // - An empty array of default values (or an isUndefined() value) asserts that
  147. // every one of the above parameter names is required.
  148. // - An array of four default values [1, 2, 3, 4] asserts that every one of
  149. // the above parameters is optional. If the current parameter map is empty,
  150. // they will be passed to the function as [1, 2, 3, 4].
  151. // - An array of two default values [11, 12] asserts that parameters "a" and
  152. // "b" are required, while "c" and "d" are optional, having default values
  153. // "c"=11 and "d"=12.
  154. //
  155. // The arguments array is constructed as follows:
  156. //
  157. // - Arguments-map keys not found in the parameter-names array are ignored.
  158. // - Entries from the map provide values for an improper subset of the
  159. // parameters named in the parameter-names array. This results in a
  160. // tentative values array with "holes." (size of map) + (number of holes) =
  161. // (size of names array)
  162. // - Holes are filled with the default values.
  163. // - Any remaining holes constitute an error.
  164. class LLSDArgsMapper
  165. {
  166. protected:
  167. LOG_CLASS(LLSDArgsMapper);
  168. public:
  169. // Accept description of function: function name, param names, param
  170. // default values
  171. LLSDArgsMapper(const std::string& function, const LLSD& names,
  172. const LLSD& defaults);
  173. // Given arguments map, return LLSD::Array of parameter values, or throws.
  174. LLSD map(const LLSD& argsmap) const;
  175. private:
  176. static std::string formatlist(const LLSD&);
  177. private:
  178. // The function-name string is purely descriptive. We want error messages
  179. // to be able to indicate which function's LLSDArgsMapper has the problem.
  180. std::string mFunction;
  181. // Store the names array pretty much as given.
  182. LLSD mNames;
  183. // Though we are handed an array of name strings, it is more useful to us
  184. // to store it as a map from name string to position index. Of course that
  185. // is easy to generate from the incoming names array, but why do it more
  186. // than once ?
  187. typedef std::map<LLSD::String, size_t> idx_map_t;
  188. idx_map_t mIndexes;
  189. // Generated array of default values, aligned with the array of param names.
  190. LLSD mDefaults;
  191. // Indicate whether we have a default value for each param.
  192. typedef std::vector<char> default_vec_t;
  193. default_vec_t mHasDefault;
  194. };
  195. LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
  196. const LLSD& names, const LLSD& defaults)
  197. : mFunction(function),
  198. mNames(names),
  199. mHasDefault(names.size())
  200. {
  201. if (!(mNames.isUndefined() || mNames.isArray()))
  202. {
  203. std::ostringstream s;
  204. s << function << " names must be an array, not " << names;
  205. llwarns << s.str() << llendl;
  206. throw DispatchError(s.str());
  207. }
  208. size_t nparams = mNames.size();
  209. // From mNames generate mIndexes.
  210. for (size_t ni = 0, nend = mNames.size(); ni < nend; ++ni)
  211. {
  212. mIndexes[mNames[ni]] = ni;
  213. }
  214. // Presize mDefaults() array so we don't have to resize it more than once.
  215. // All entries are initialized to LLSD(); but since mHasDefault is still
  216. // all 0, they are all "holes" for now.
  217. if (nparams)
  218. {
  219. mDefaults[nparams - 1] = LLSD();
  220. }
  221. if (defaults.isUndefined() || defaults.isArray())
  222. {
  223. size_t ndefaults = defaults.size();
  224. // defaults is a (possibly empty) array. Right-align it with names.
  225. if (ndefaults > nparams)
  226. {
  227. std::ostringstream s;
  228. s << function << " names array " << names
  229. << " shorter than defaults array " << defaults;
  230. llwarns << s.str() << llendl;
  231. throw DispatchError(s.str());
  232. }
  233. // Offset by which we slide defaults array right to right-align with
  234. // mNames array
  235. size_t offset = nparams - ndefaults;
  236. // Fill rightmost mDefaults entries from defaults, and mark them as
  237. // filled
  238. for (size_t i = 0, iend = ndefaults; i < iend; ++i)
  239. {
  240. mDefaults[i + offset] = defaults[i];
  241. mHasDefault[i + offset] = 1;
  242. }
  243. }
  244. else if (defaults.isMap())
  245. {
  246. // 'defaults' is a map. Use it to populate the mDefaults array.
  247. LLSD bogus;
  248. for (LLSD::map_const_iterator it = defaults.beginMap(),
  249. end = defaults.endMap();
  250. it != end; ++it)
  251. {
  252. idx_map_t::const_iterator ixit = mIndexes.find(it->first);
  253. if (ixit == mIndexes.end())
  254. {
  255. bogus.append(it->first);
  256. continue;
  257. }
  258. size_t pos = ixit->second;
  259. // Store default value at that position in the mDefaults array.
  260. mDefaults[pos] = it->second;
  261. // Do not forget to record the fact that we have filled this
  262. // position.
  263. mHasDefault[pos] = 1;
  264. }
  265. if (bogus.size())
  266. {
  267. std::ostringstream s;
  268. s << function << " defaults specified for nonexistent params "
  269. << formatlist(bogus);
  270. llwarns << s.str() << llendl;
  271. throw DispatchError(s.str());
  272. }
  273. }
  274. else
  275. {
  276. std::ostringstream s;
  277. s << function << " defaults must be a map or an array, not "
  278. << defaults;
  279. llwarns << s.str() << llendl;
  280. throw DispatchError(s.str());
  281. }
  282. }
  283. LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
  284. {
  285. if (!(argsmap.isUndefined() || argsmap.isMap() || argsmap.isArray()))
  286. {
  287. std::ostringstream s;
  288. s << mFunction << " map() needs a map or array, not " << argsmap;
  289. llwarns << s.str() << llendl;
  290. throw DispatchError(s.str());
  291. }
  292. // Initialize the args array. Indexing a non-const LLSD array grows it
  293. // to appropriate size, but we don't want to resize this one on each
  294. // new operation. Just make it as big as we need before we start
  295. // stuffing values into it.
  296. LLSD args(LLSD::emptyArray());
  297. if (mDefaults.size() == 0)
  298. {
  299. // If this function requires no arguments, fast exit (do not try to
  300. // assign to args[-1]).
  301. return args;
  302. }
  303. args[mDefaults.size() - 1] = LLSD();
  304. // Get a vector of chars to indicate holes. It's tempting to just scan
  305. // for LLSD::isUndefined() values after filling the args array from
  306. // the map, but it's plausible for caller to explicitly pass
  307. // isUndefined() as the value of some parameter name. That's legal
  308. // since isUndefined() has well-defined conversions (default value)
  309. // for LLSD data types. So use a whole separate array for detecting
  310. // holes. (Avoid std::vector<bool> which is known to be odd -- can we
  311. // iterate?)
  312. default_vec_t filled(args.size());
  313. if (argsmap.isArray())
  314. {
  315. // Fill args from array. If there are too many args in passed array,
  316. // ignore the rest.
  317. size_t size = argsmap.size();
  318. if (size > args.size())
  319. {
  320. // We do not just use std::min() because we want to sneak in this
  321. // warning if caller passes too many args.
  322. llwarns << mFunction << " needs " << args.size()
  323. << " params, ignoring last " << (size - args.size())
  324. << " of passed " << size << ": " << argsmap << llendl;
  325. size = args.size();
  326. }
  327. for (size_t i = 0; i < size; ++i)
  328. {
  329. // Copy the actual argument from argsmap
  330. args[i] = argsmap[i];
  331. // Note that it has been filled
  332. filled[i] = 1;
  333. }
  334. }
  335. else
  336. {
  337. // argsmap is in fact a map. Walk the map.
  338. for (LLSD::map_const_iterator it = argsmap.beginMap(),
  339. end = argsmap.endMap();
  340. it != end; ++it)
  341. {
  342. // it->first is a parameter-name string, with it->second its
  343. // value. Look up the name's position index in mIndexes.
  344. idx_map_t::const_iterator ixit = mIndexes.find(it->first);
  345. if (ixit == mIndexes.end())
  346. {
  347. // Allow for a map containing more params than were passed in
  348. // our names array. Caller typically receives a map containing
  349. // the function name, cruft such as reqid, etc. Ignore keys
  350. // not defined in mIndexes.
  351. LL_DEBUGS("LLSDArgsMapper") << mFunction << " ignoring "
  352. << it->first << "=" << it->second
  353. << LL_ENDL;
  354. continue;
  355. }
  356. size_t pos = ixit->second;
  357. // Store the value at that position in the args array.
  358. args[pos] = it->second;
  359. // Do not forget to record the fact that we have filled this
  360. // position.
  361. filled[pos] = 1;
  362. }
  363. }
  364. // Fill any remaining holes from mDefaults.
  365. LLSD unfilled(LLSD::emptyArray());
  366. for (size_t i = 0, iend = args.size(); i < iend; ++i)
  367. {
  368. if (!filled[i])
  369. {
  370. // If there is no default value for this parameter, that is an
  371. // error.
  372. if (!mHasDefault[i])
  373. {
  374. unfilled.append(mNames[i]);
  375. }
  376. else
  377. {
  378. args[i] = mDefaults[i];
  379. }
  380. }
  381. }
  382. // If any required args (args without defaults) were left unfilled by
  383. // argsmap, that is a problem.
  384. if (unfilled.size())
  385. {
  386. std::ostringstream s;
  387. s << mFunction << " missing required arguments "
  388. << formatlist(unfilled) << " from " << argsmap;
  389. llwarns << s.str() << llendl;
  390. throw DispatchError(s.str());
  391. }
  392. // Done
  393. return args;
  394. }
  395. std::string LLSDArgsMapper::formatlist(const LLSD& list)
  396. {
  397. std::ostringstream out;
  398. const char* delim = "";
  399. for (LLSD::array_const_iterator it = list.beginArray(),
  400. end = list.endArray();
  401. it != end; ++it)
  402. {
  403. out << delim << it->asString();
  404. delim = ", ";
  405. }
  406. return out.str();
  407. }
  408. ///////////////////////////////////////////////////////////////////////////////
  409. // LLEventDispatcher
  410. ///////////////////////////////////////////////////////////////////////////////
  411. LLEventDispatcher::LLEventDispatcher(const std::string& desc,
  412. const std::string& key)
  413. : mDesc(desc),
  414. mKey(key)
  415. {
  416. }
  417. // DispatchEntry subclass used for callables accepting(const LLSD&)
  418. struct LLEventDispatcher::LLSDDispatchEntry
  419. : public LLEventDispatcher::DispatchEntry
  420. {
  421. LLSDDispatchEntry(const std::string& desc, const Callable& func,
  422. const LLSD& required)
  423. : DispatchEntry(desc),
  424. mFunc(func),
  425. mRequired(required)
  426. {
  427. }
  428. void call(const std::string& desc, const LLSD& event) const override
  429. {
  430. // Validate the syntax of the event itself.
  431. std::string mismatch(llsd_matches(mRequired, event));
  432. if (!mismatch.empty())
  433. {
  434. std::ostringstream s;
  435. s << desc << ": bad request: " << mismatch;
  436. llwarns << s.str() << llendl;
  437. throw DispatchError(s.str());
  438. }
  439. // Event syntax looks good, go for it!
  440. mFunc(event);
  441. }
  442. LL_INLINE LLSD addMetadata(LLSD meta) const override
  443. {
  444. meta["required"] = mRequired;
  445. return meta;
  446. }
  447. Callable mFunc;
  448. LLSD mRequired;
  449. };
  450. // DispatchEntry subclass for passing LLSD to functions accepting arbitrary
  451. // argument types (convertible via LLSDParam)
  452. struct LLEventDispatcher::ParamsDispatchEntry
  453. : public LLEventDispatcher::DispatchEntry
  454. {
  455. LL_INLINE ParamsDispatchEntry(const std::string& desc,
  456. const invoker_function& func)
  457. : DispatchEntry(desc),
  458. mInvoker(func)
  459. {
  460. }
  461. LL_INLINE void call(const std::string& desc,
  462. const LLSD& event) const override
  463. {
  464. LLSDArgsSource src(desc, event);
  465. mInvoker(boost::bind(&LLSDArgsSource::next, boost::ref(src)));
  466. }
  467. invoker_function mInvoker;
  468. };
  469. // DispatchEntry subclass for dispatching LLSD::Array to functions accepting
  470. // arbitrary argument types (convertible via LLSDParam)
  471. struct LLEventDispatcher::ArrayParamsDispatchEntry
  472. : public LLEventDispatcher::ParamsDispatchEntry
  473. {
  474. ArrayParamsDispatchEntry(const std::string& desc,
  475. const invoker_function& func,
  476. size_t arity)
  477. : ParamsDispatchEntry(desc, func),
  478. mArity(arity)
  479. {
  480. }
  481. LLSD addMetadata(LLSD meta) const override
  482. {
  483. LLSD array(LLSD::emptyArray());
  484. // Resize to number of arguments required
  485. if (mArity)
  486. {
  487. array[mArity - 1] = LLSD();
  488. }
  489. llassert_always(array.size() == mArity);
  490. meta["required"] = array;
  491. return meta;
  492. }
  493. size_t mArity;
  494. };
  495. // DispatchEntry subclass for dispatching LLSD::Map to functions accepting
  496. // arbitrary argument types (convertible via LLSDParam)
  497. struct LLEventDispatcher::MapParamsDispatchEntry
  498. : public LLEventDispatcher::ParamsDispatchEntry
  499. {
  500. MapParamsDispatchEntry(const std::string& name, const std::string& desc,
  501. const invoker_function& func,
  502. const LLSD& params, const LLSD& defaults)
  503. : ParamsDispatchEntry(desc, func),
  504. mMapper(name, params, defaults),
  505. mRequired(LLSD::emptyMap())
  506. {
  507. // Build the set of all param keys, then delete the ones that are
  508. // optional. What's left are the ones that are required.
  509. for (LLSD::array_const_iterator it = params.beginArray(),
  510. end = params.endArray();
  511. it != end; ++it)
  512. {
  513. mRequired[it->asString()] = LLSD();
  514. }
  515. if (defaults.isArray() || defaults.isUndefined())
  516. {
  517. // Right-align the params and defaults arrays.
  518. size_t offset = params.size() - defaults.size();
  519. // Now the name of every defaults[i] is at params[i + offset].
  520. for (size_t i = 0, count = defaults.size(); i < count; ++i)
  521. {
  522. // Erase this optional param from mRequired.
  523. mRequired.erase(params[i + offset].asString());
  524. // Instead, make an entry in mOptional with the default
  525. // param's name and value.
  526. mOptional[params[i + offset].asString()] = defaults[i];
  527. }
  528. }
  529. else if (defaults.isMap())
  530. {
  531. // If defaults is already a map, then it's already in the form we
  532. // intend to deliver in metadata
  533. mOptional = defaults;
  534. // Just delete from mRequired every key appearing in mOptional.
  535. for (LLSD::map_const_iterator it = mOptional.beginMap(),
  536. end = mOptional.endMap();
  537. it != end; ++it)
  538. {
  539. mRequired.erase(it->first);
  540. }
  541. }
  542. }
  543. LL_INLINE void call(const std::string& desc,
  544. const LLSD& event) const override
  545. {
  546. // Just convert from LLSD::Map to LLSD::Array using mMapper, then pass
  547. // to base-class call() method.
  548. ParamsDispatchEntry::call(desc, mMapper.map(event));
  549. }
  550. LL_INLINE LLSD addMetadata(LLSD meta) const override
  551. {
  552. meta["required"] = mRequired;
  553. meta["optional"] = mOptional;
  554. return meta;
  555. }
  556. LLSDArgsMapper mMapper;
  557. LLSD mRequired;
  558. LLSD mOptional;
  559. };
  560. void LLEventDispatcher::addArrayParamsDispatchEntry(const std::string& name,
  561. const std::string& desc,
  562. const invoker_function& invoker,
  563. size_t arity)
  564. {
  565. mDispatch.emplace(name,
  566. DispatchMap::mapped_type(new ArrayParamsDispatchEntry(desc,
  567. invoker,
  568. arity)));
  569. }
  570. void LLEventDispatcher::addMapParamsDispatchEntry(const std::string& name,
  571. const std::string& desc,
  572. const invoker_function& invoker,
  573. const LLSD& params,
  574. const LLSD& defaults)
  575. {
  576. mDispatch.emplace(name,
  577. DispatchMap::mapped_type(new MapParamsDispatchEntry(name,
  578. desc,
  579. invoker,
  580. params,
  581. defaults)));
  582. }
  583. // Registers a callable by name
  584. void LLEventDispatcher::add(const std::string& name, const std::string& desc,
  585. const Callable& callable, const LLSD& required)
  586. {
  587. mDispatch.emplace(name,
  588. DispatchMap::mapped_type(new LLSDDispatchEntry(desc,
  589. callable,
  590. required)));
  591. }
  592. void LLEventDispatcher::addFail(const std::string& name,
  593. const std::string& classname) const
  594. {
  595. llerrs << "LLEventDispatcher(" << *this << ")::add(" << name
  596. << "): " << classname << " is not a subclass of LLEventDispatcher"
  597. << llendl;
  598. }
  599. // Unregisters a callable
  600. bool LLEventDispatcher::remove(const std::string& name)
  601. {
  602. DispatchMap::iterator found = mDispatch.find(name);
  603. if (found == mDispatch.end())
  604. {
  605. return false;
  606. }
  607. mDispatch.erase(found);
  608. return true;
  609. }
  610. // Calls a registered callable with an explicitly-specified name.
  611. void LLEventDispatcher::operator()(const std::string& name, const LLSD& event) const
  612. {
  613. std::string error = try_call_log("", name, event);
  614. if (!error.empty())
  615. {
  616. callFail(event, error);
  617. }
  618. }
  619. // Extracts the key value from the incoming event, and calls the callable whose
  620. // name is specified by that map key.
  621. void LLEventDispatcher::operator()(const LLSD& event) const
  622. {
  623. std::string error = try_call_log(mKey, event[mKey], event);
  624. if (!error.empty())
  625. {
  626. callFail(event, error);
  627. }
  628. }
  629. void LLEventDispatcher::callFail(const LLSD& event, const std::string& msg) const
  630. {
  631. static LLSD::String key("reply");
  632. if (event.has(key))
  633. {
  634. // If the passed event has a "reply" key, send a reply to that
  635. // LLEventPump.
  636. gEventPumps.sendReply(llsd::map("error", msg), event, key);
  637. }
  638. }
  639. bool LLEventDispatcher::try_call(const LLSD& event) const
  640. {
  641. return try_call_log(mKey, event[mKey], event).empty();
  642. }
  643. bool LLEventDispatcher::try_call(const std::string& name, const LLSD& event) const
  644. {
  645. return try_call_log(std::string(), name, event).empty();
  646. }
  647. std::string LLEventDispatcher::try_call_log(const std::string& key,
  648. const std::string& name,
  649. const LLSD& event) const
  650. {
  651. std::string error = try_call(key, name, event);
  652. if (!error.empty())
  653. {
  654. llwarns << error << llendl;
  655. }
  656. return error;
  657. }
  658. // This internal method returns an empty string when the call succeeded, or a
  659. // non-empty error message otherwise.
  660. std::string LLEventDispatcher::try_call(const std::string& key,
  661. const std::string& name,
  662. const LLSD& event) const
  663. {
  664. std::string report = "LLEventDispatcher(" + mDesc + ")";
  665. DispatchMap::const_iterator it = mDispatch.find(name);
  666. if (it == mDispatch.end())
  667. {
  668. if (key.empty())
  669. {
  670. return report + ": '" + name + "' not found";
  671. }
  672. return report + ": bad '" + key + "' value '" + name + "'";
  673. }
  674. try
  675. {
  676. // Found the name, so it is plausible to even attempt the call.
  677. it->second->call(report + " calling '" + name + "'", event);
  678. }
  679. catch (const DispatchError& err)
  680. {
  681. return err.what();
  682. }
  683. // Call successful.
  684. return "";
  685. }
  686. LLSD LLEventDispatcher::getMetadata(const std::string& name) const
  687. {
  688. DispatchMap::const_iterator found = mDispatch.find(name);
  689. if (found == mDispatch.end())
  690. {
  691. return LLSD();
  692. }
  693. LLSD meta;
  694. meta["name"] = name;
  695. meta["desc"] = found->second->mDesc;
  696. return found->second->addMetadata(meta);
  697. }
  698. LLDispatchListener::LLDispatchListener(const std::string& pumpname,
  699. const std::string& key)
  700. : LLEventDispatcher(pumpname, key),
  701. mPump(pumpname, true), // allow tweaking for uniqueness
  702. mBoundListener(mPump.listen("self",
  703. boost::bind(&LLDispatchListener::process, this,
  704. _1)))
  705. {
  706. }
  707. bool LLDispatchListener::process(const LLSD& event)
  708. {
  709. (*this)(event);
  710. return false;
  711. }
  712. LLEventDispatcher::DispatchEntry::DispatchEntry(const std::string& desc)
  713. : mDesc(desc)
  714. {
  715. }
  716. ///////////////////////////////////////////////////////////////////////////////
  717. // LLEventAPI
  718. ///////////////////////////////////////////////////////////////////////////////
  719. LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc,
  720. const std::string& field)
  721. : lbase(name, field),
  722. ibase(name),
  723. mDesc(desc)
  724. {
  725. }
  726. LLEventAPI::Response::Response(const LLSD& seed, const LLSD& request,
  727. const LLSD::String& reply_key)
  728. : mResp(seed),
  729. mReq(request),
  730. mKey(reply_key)
  731. {
  732. }
  733. LLEventAPI::Response::~Response()
  734. {
  735. // When you instantiate a stack Response object, if the original request
  736. // requested a reply, send it when we leave this block, no matter how.
  737. gEventPumps.sendReply(mResp, mReq, mKey);
  738. }
  739. void LLEventAPI::Response::warn(const std::string& warning)
  740. {
  741. llwarns << warning << llendl;
  742. mResp["warnings"].append(warning);
  743. }
  744. void LLEventAPI::Response::error(const std::string& error)
  745. {
  746. // Use llwarns rather than llerrs: we do not want the viewer to shut down
  747. // altogether.
  748. llwarns << error << llendl;
  749. mResp["error"] = error;
  750. }