message.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2010, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Out-of-call text message support
  21. *
  22. * \author Russell Bryant <russell@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/_private.h"
  30. #include "asterisk/module.h"
  31. #include "asterisk/datastore.h"
  32. #include "asterisk/pbx.h"
  33. #include "asterisk/manager.h"
  34. #include "asterisk/strings.h"
  35. #include "asterisk/astobj2.h"
  36. #include "asterisk/vector.h"
  37. #include "asterisk/app.h"
  38. #include "asterisk/taskprocessor.h"
  39. #include "asterisk/message.h"
  40. /*** DOCUMENTATION
  41. <function name="MESSAGE" language="en_US">
  42. <synopsis>
  43. Create a message or read fields from a message.
  44. </synopsis>
  45. <syntax argsep="/">
  46. <parameter name="argument" required="true">
  47. <para>Field of the message to get or set.</para>
  48. <enumlist>
  49. <enum name="to">
  50. <para>Read-only. The destination of the message. When processing an
  51. incoming message, this will be set to the destination listed as
  52. the recipient of the message that was received by Asterisk.</para>
  53. </enum>
  54. <enum name="from">
  55. <para>Read-only. The source of the message. When processing an
  56. incoming message, this will be set to the source of the message.</para>
  57. </enum>
  58. <enum name="custom_data">
  59. <para>Write-only. Mark or unmark all message headers for an outgoing
  60. message. The following values can be set:</para>
  61. <enumlist>
  62. <enum name="mark_all_outbound">
  63. <para>Mark all headers for an outgoing message.</para>
  64. </enum>
  65. <enum name="clear_all_outbound">
  66. <para>Unmark all headers for an outgoing message.</para>
  67. </enum>
  68. </enumlist>
  69. </enum>
  70. <enum name="body">
  71. <para>Read/Write. The message body. When processing an incoming
  72. message, this includes the body of the message that Asterisk
  73. received. When MessageSend() is executed, the contents of this
  74. field are used as the body of the outgoing message. The body
  75. will always be UTF-8.</para>
  76. </enum>
  77. </enumlist>
  78. </parameter>
  79. </syntax>
  80. <description>
  81. <para>This function will read from or write a value to a text message.
  82. It is used both to read the data out of an incoming message, as well as
  83. modify or create a message that will be sent outbound.</para>
  84. </description>
  85. <see-also>
  86. <ref type="application">MessageSend</ref>
  87. </see-also>
  88. </function>
  89. <function name="MESSAGE_DATA" language="en_US">
  90. <synopsis>
  91. Read or write custom data attached to a message.
  92. </synopsis>
  93. <syntax argsep="/">
  94. <parameter name="argument" required="true">
  95. <para>Field of the message to get or set.</para>
  96. </parameter>
  97. </syntax>
  98. <description>
  99. <para>This function will read from or write a value to a text message.
  100. It is used both to read the data out of an incoming message, as well as
  101. modify a message that will be sent outbound.</para>
  102. <note>
  103. <para>If you want to set an outbound message to carry data in the
  104. current message, do
  105. Set(MESSAGE_DATA(<replaceable>key</replaceable>)=${MESSAGE_DATA(<replaceable>key</replaceable>)}).</para>
  106. </note>
  107. </description>
  108. <see-also>
  109. <ref type="application">MessageSend</ref>
  110. </see-also>
  111. </function>
  112. <application name="MessageSend" language="en_US">
  113. <synopsis>
  114. Send a text message.
  115. </synopsis>
  116. <syntax>
  117. <parameter name="to" required="true">
  118. <para>A To URI for the message.</para>
  119. <xi:include xpointer="xpointer(/docs/info[@name='MessageToInfo'])" />
  120. </parameter>
  121. <parameter name="from" required="false">
  122. <para>A From URI for the message if needed for the
  123. message technology being used to send this message. This can be a
  124. SIP(S) URI, such as <literal>Alice &lt;sip:alice@atlanta.com&gt;</literal>,
  125. a string in the format <literal>alice@atlanta.com</literal>, or simply
  126. a username such as <literal>alice</literal>.</para>
  127. </parameter>
  128. </syntax>
  129. <description>
  130. <para>Send a text message. The body of the message that will be
  131. sent is what is currently set to <literal>MESSAGE(body)</literal>.
  132. The technology chosen for sending the message is determined
  133. based on a prefix to the <literal>to</literal> parameter.</para>
  134. <para>This application sets the following channel variables:</para>
  135. <variablelist>
  136. <variable name="MESSAGE_SEND_STATUS">
  137. <para>This is the message delivery status returned by this application.</para>
  138. <value name="INVALID_PROTOCOL">
  139. No handler for the technology part of the URI was found.
  140. </value>
  141. <value name="INVALID_URI">
  142. The protocol handler reported that the URI was not valid.
  143. </value>
  144. <value name="SUCCESS">
  145. Successfully passed on to the protocol handler, but delivery has not necessarily been guaranteed.
  146. </value>
  147. <value name="FAILURE">
  148. The protocol handler reported that it was unabled to deliver the message for some reason.
  149. </value>
  150. </variable>
  151. </variablelist>
  152. </description>
  153. </application>
  154. <manager name="MessageSend" language="en_US">
  155. <synopsis>
  156. Send an out of call message to an endpoint.
  157. </synopsis>
  158. <syntax>
  159. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  160. <parameter name="To" required="true">
  161. <para>The URI the message is to be sent to.</para>
  162. <xi:include xpointer="xpointer(/docs/info[@name='MessageToInfo'])" />
  163. </parameter>
  164. <parameter name="From">
  165. <para>A From URI for the message if needed for the
  166. message technology being used to send this message.</para>
  167. <xi:include xpointer="xpointer(/docs/info[@name='MessageFromInfo'])" />
  168. </parameter>
  169. <parameter name="Body">
  170. <para>The message body text. This must not contain any newlines as that
  171. conflicts with the AMI protocol.</para>
  172. </parameter>
  173. <parameter name="Base64Body">
  174. <para>Text bodies requiring the use of newlines have to be base64 encoded
  175. in this field. Base64Body will be decoded before being sent out.
  176. Base64Body takes precedence over Body.</para>
  177. </parameter>
  178. <parameter name="Variable">
  179. <para>Message variable to set, multiple Variable: headers are
  180. allowed. The header value is a comma separated list of
  181. name=value pairs.</para>
  182. </parameter>
  183. </syntax>
  184. </manager>
  185. ***/
  186. struct msg_data {
  187. AST_DECLARE_STRING_FIELDS(
  188. AST_STRING_FIELD(name);
  189. AST_STRING_FIELD(value);
  190. );
  191. unsigned int send; /* Whether to send out on outbound messages */
  192. };
  193. AST_LIST_HEAD_NOLOCK(outhead, msg_data);
  194. /*!
  195. * \brief A message.
  196. */
  197. struct ast_msg {
  198. AST_DECLARE_STRING_FIELDS(
  199. /*! Where the message is going */
  200. AST_STRING_FIELD(to);
  201. /*! Where we "say" the message came from */
  202. AST_STRING_FIELD(from);
  203. /*! The text to send */
  204. AST_STRING_FIELD(body);
  205. /*! The dialplan context for the message */
  206. AST_STRING_FIELD(context);
  207. /*! The dialplan extension for the message */
  208. AST_STRING_FIELD(exten);
  209. /*! An endpoint associated with this message */
  210. AST_STRING_FIELD(endpoint);
  211. /*! The technology of the endpoint associated with this message */
  212. AST_STRING_FIELD(tech);
  213. );
  214. /*! Technology/dialplan specific variables associated with the message */
  215. struct ao2_container *vars;
  216. };
  217. /*! \brief Lock for \c msg_techs vector */
  218. static ast_rwlock_t msg_techs_lock;
  219. /*! \brief Vector of message technologies */
  220. AST_VECTOR(, const struct ast_msg_tech *) msg_techs;
  221. /*! \brief Lock for \c msg_handlers vector */
  222. static ast_rwlock_t msg_handlers_lock;
  223. /*! \brief Vector of received message handlers */
  224. AST_VECTOR(, const struct ast_msg_handler *) msg_handlers;
  225. static struct ast_taskprocessor *msg_q_tp;
  226. static const char app_msg_send[] = "MessageSend";
  227. static void msg_ds_destroy(void *data);
  228. static const struct ast_datastore_info msg_datastore = {
  229. .type = "message",
  230. .destroy = msg_ds_destroy,
  231. };
  232. static int msg_func_read(struct ast_channel *chan, const char *function,
  233. char *data, char *buf, size_t len);
  234. static int msg_func_write(struct ast_channel *chan, const char *function,
  235. char *data, const char *value);
  236. static struct ast_custom_function msg_function = {
  237. .name = "MESSAGE",
  238. .read = msg_func_read,
  239. .write = msg_func_write,
  240. };
  241. static int msg_data_func_read(struct ast_channel *chan, const char *function,
  242. char *data, char *buf, size_t len);
  243. static int msg_data_func_write(struct ast_channel *chan, const char *function,
  244. char *data, const char *value);
  245. static struct ast_custom_function msg_data_function = {
  246. .name = "MESSAGE_DATA",
  247. .read = msg_data_func_read,
  248. .write = msg_data_func_write,
  249. };
  250. static struct ast_frame *chan_msg_read(struct ast_channel *chan);
  251. static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr);
  252. static int chan_msg_indicate(struct ast_channel *chan, int condition,
  253. const void *data, size_t datalen);
  254. static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit);
  255. static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
  256. unsigned int duration);
  257. /*!
  258. * \internal
  259. * \brief A bare minimum channel technology
  260. *
  261. * This will not be registered as we never want anything to try
  262. * to create Message channels other than internally in this file.
  263. */
  264. static const struct ast_channel_tech msg_chan_tech_hack = {
  265. .type = "Message",
  266. .description = "Internal Text Message Processing",
  267. .read = chan_msg_read,
  268. .write = chan_msg_write,
  269. .indicate = chan_msg_indicate,
  270. .send_digit_begin = chan_msg_send_digit_begin,
  271. .send_digit_end = chan_msg_send_digit_end,
  272. };
  273. /*!
  274. * \internal
  275. * \brief ast_channel_tech read callback
  276. *
  277. * This should never be called. However, we say that about chan_iax2's
  278. * read callback, too, and it seems to randomly get called for some
  279. * reason. If it does, a simple NULL frame will suffice.
  280. */
  281. static struct ast_frame *chan_msg_read(struct ast_channel *chan)
  282. {
  283. return &ast_null_frame;
  284. }
  285. /*!
  286. * \internal
  287. * \brief ast_channel_tech write callback
  288. *
  289. * Throw all frames away. We don't care about any of them.
  290. */
  291. static int chan_msg_write(struct ast_channel *chan, struct ast_frame *fr)
  292. {
  293. return 0;
  294. }
  295. /*!
  296. * \internal
  297. * \brief ast_channel_tech indicate callback
  298. *
  299. * The indicate callback is here just so it can return success.
  300. * We don't want any callers of ast_indicate() to think something
  301. * has failed. We also don't want ast_indicate() itself to try
  302. * to generate inband tones since we didn't tell it that we took
  303. * care of it ourselves.
  304. */
  305. static int chan_msg_indicate(struct ast_channel *chan, int condition,
  306. const void *data, size_t datalen)
  307. {
  308. return 0;
  309. }
  310. /*!
  311. * \internal
  312. * \brief ast_channel_tech send_digit_begin callback
  313. *
  314. * This is here so that just in case a digit comes at a message channel
  315. * that the Asterisk core doesn't waste any time trying to generate
  316. * inband DTMF in audio. It's a waste of resources.
  317. */
  318. static int chan_msg_send_digit_begin(struct ast_channel *chan, char digit)
  319. {
  320. return 0;
  321. }
  322. /*!
  323. * \internal
  324. * \brief ast_channel_tech send_digit_end callback
  325. *
  326. * This is here so that just in case a digit comes at a message channel
  327. * that the Asterisk core doesn't waste any time trying to generate
  328. * inband DTMF in audio. It's a waste of resources.
  329. */
  330. static int chan_msg_send_digit_end(struct ast_channel *chan, char digit,
  331. unsigned int duration)
  332. {
  333. return 0;
  334. }
  335. static void msg_ds_destroy(void *data)
  336. {
  337. struct ast_msg *msg = data;
  338. ao2_ref(msg, -1);
  339. }
  340. static int msg_data_cmp_fn(void *obj, void *arg, int flags)
  341. {
  342. const struct msg_data *one = obj, *two = arg;
  343. return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP : 0;
  344. }
  345. static void msg_data_destructor(void *obj)
  346. {
  347. struct msg_data *data = obj;
  348. ast_string_field_free_memory(data);
  349. }
  350. static void msg_destructor(void *obj)
  351. {
  352. struct ast_msg *msg = obj;
  353. ast_string_field_free_memory(msg);
  354. ao2_cleanup(msg->vars);
  355. }
  356. struct ast_msg *ast_msg_alloc(void)
  357. {
  358. struct ast_msg *msg;
  359. if (!(msg = ao2_alloc(sizeof(*msg), msg_destructor))) {
  360. return NULL;
  361. }
  362. if (ast_string_field_init(msg, 128)) {
  363. ao2_ref(msg, -1);
  364. return NULL;
  365. }
  366. msg->vars = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
  367. NULL, msg_data_cmp_fn);
  368. if (!msg->vars) {
  369. ao2_ref(msg, -1);
  370. return NULL;
  371. }
  372. ast_string_field_set(msg, context, "default");
  373. return msg;
  374. }
  375. struct ast_msg *ast_msg_ref(struct ast_msg *msg)
  376. {
  377. ao2_ref(msg, 1);
  378. return msg;
  379. }
  380. struct ast_msg *ast_msg_destroy(struct ast_msg *msg)
  381. {
  382. ao2_ref(msg, -1);
  383. return NULL;
  384. }
  385. int ast_msg_set_to(struct ast_msg *msg, const char *fmt, ...)
  386. {
  387. va_list ap;
  388. va_start(ap, fmt);
  389. ast_string_field_build_va(msg, to, fmt, ap);
  390. va_end(ap);
  391. return 0;
  392. }
  393. int ast_msg_set_from(struct ast_msg *msg, const char *fmt, ...)
  394. {
  395. va_list ap;
  396. va_start(ap, fmt);
  397. ast_string_field_build_va(msg, from, fmt, ap);
  398. va_end(ap);
  399. return 0;
  400. }
  401. int ast_msg_set_body(struct ast_msg *msg, const char *fmt, ...)
  402. {
  403. va_list ap;
  404. va_start(ap, fmt);
  405. ast_string_field_build_va(msg, body, fmt, ap);
  406. va_end(ap);
  407. return 0;
  408. }
  409. int ast_msg_set_context(struct ast_msg *msg, const char *fmt, ...)
  410. {
  411. va_list ap;
  412. va_start(ap, fmt);
  413. ast_string_field_build_va(msg, context, fmt, ap);
  414. va_end(ap);
  415. return 0;
  416. }
  417. int ast_msg_set_exten(struct ast_msg *msg, const char *fmt, ...)
  418. {
  419. va_list ap;
  420. va_start(ap, fmt);
  421. ast_string_field_build_va(msg, exten, fmt, ap);
  422. va_end(ap);
  423. return 0;
  424. }
  425. int ast_msg_set_tech(struct ast_msg *msg, const char *fmt, ...)
  426. {
  427. va_list ap;
  428. va_start(ap, fmt);
  429. ast_string_field_build_va(msg, tech, fmt, ap);
  430. va_end(ap);
  431. return 0;
  432. }
  433. int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt, ...)
  434. {
  435. va_list ap;
  436. va_start(ap, fmt);
  437. ast_string_field_build_va(msg, endpoint, fmt, ap);
  438. va_end(ap);
  439. return 0;
  440. }
  441. const char *ast_msg_get_body(const struct ast_msg *msg)
  442. {
  443. return msg->body;
  444. }
  445. const char *ast_msg_get_from(const struct ast_msg *msg)
  446. {
  447. return msg->from;
  448. }
  449. const char *ast_msg_get_to(const struct ast_msg *msg)
  450. {
  451. return msg->to;
  452. }
  453. const char *ast_msg_get_tech(const struct ast_msg *msg)
  454. {
  455. return msg->tech;
  456. }
  457. const char *ast_msg_get_endpoint(const struct ast_msg *msg)
  458. {
  459. return msg->endpoint;
  460. }
  461. static struct msg_data *msg_data_alloc(void)
  462. {
  463. struct msg_data *data;
  464. if (!(data = ao2_alloc(sizeof(*data), msg_data_destructor))) {
  465. return NULL;
  466. }
  467. if (ast_string_field_init(data, 32)) {
  468. ao2_ref(data, -1);
  469. return NULL;
  470. }
  471. return data;
  472. }
  473. static struct msg_data *msg_data_find(struct ao2_container *vars, const char *name)
  474. {
  475. struct msg_data tmp = {
  476. .name = name,
  477. };
  478. return ao2_find(vars, &tmp, OBJ_POINTER);
  479. }
  480. static int msg_set_var_full(struct ast_msg *msg, const char *name, const char *value, unsigned int outbound)
  481. {
  482. struct msg_data *data;
  483. if (!(data = msg_data_find(msg->vars, name))) {
  484. if (ast_strlen_zero(value)) {
  485. return 0;
  486. }
  487. if (!(data = msg_data_alloc())) {
  488. return -1;
  489. };
  490. ast_string_field_set(data, name, name);
  491. ast_string_field_set(data, value, value);
  492. data->send = outbound;
  493. ao2_link(msg->vars, data);
  494. } else {
  495. if (ast_strlen_zero(value)) {
  496. ao2_unlink(msg->vars, data);
  497. } else {
  498. ast_string_field_set(data, value, value);
  499. data->send = outbound;
  500. }
  501. }
  502. ao2_ref(data, -1);
  503. return 0;
  504. }
  505. int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value)
  506. {
  507. return msg_set_var_full(msg, name, value, 1);
  508. }
  509. int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
  510. {
  511. return msg_set_var_full(msg, name, value, 0);
  512. }
  513. const char *ast_msg_get_var(struct ast_msg *msg, const char *name)
  514. {
  515. struct msg_data *data;
  516. const char *val = NULL;
  517. if (!(data = msg_data_find(msg->vars, name))) {
  518. return NULL;
  519. }
  520. /* Yep, this definitely looks like val would be a dangling pointer
  521. * after the ref count is decremented. As long as the message structure
  522. * is used in a thread safe manner, this will not be the case though.
  523. * The ast_msg holds a reference to this object in the msg->vars container. */
  524. val = data->value;
  525. ao2_ref(data, -1);
  526. return val;
  527. }
  528. struct ast_msg_var_iterator {
  529. struct ao2_iterator iter;
  530. struct msg_data *current_used;
  531. };
  532. struct ast_msg_var_iterator *ast_msg_var_iterator_init(const struct ast_msg *msg)
  533. {
  534. struct ast_msg_var_iterator *iter;
  535. iter = ast_calloc(1, sizeof(*iter));
  536. if (!iter) {
  537. return NULL;
  538. }
  539. iter->iter = ao2_iterator_init(msg->vars, 0);
  540. return iter;
  541. }
  542. int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
  543. {
  544. struct msg_data *data;
  545. if (!iter) {
  546. return 0;
  547. }
  548. /* Skip any that aren't marked for sending out */
  549. while ((data = ao2_iterator_next(&iter->iter)) && !data->send) {
  550. ao2_ref(data, -1);
  551. }
  552. if (!data) {
  553. return 0;
  554. }
  555. if (data->send) {
  556. *name = data->name;
  557. *value = data->value;
  558. }
  559. /* Leave the refcount to be cleaned up by the caller with
  560. * ast_msg_var_unref_current after they finish with the pointers to the data */
  561. iter->current_used = data;
  562. return 1;
  563. }
  564. void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
  565. {
  566. ao2_cleanup(iter->current_used);
  567. iter->current_used = NULL;
  568. }
  569. void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
  570. {
  571. if (iter) {
  572. ao2_iterator_destroy(&iter->iter);
  573. ast_msg_var_unref_current(iter);
  574. ast_free(iter);
  575. }
  576. }
  577. static struct ast_channel *create_msg_q_chan(void)
  578. {
  579. struct ast_channel *chan;
  580. struct ast_datastore *ds;
  581. chan = ast_channel_alloc(1, AST_STATE_UP,
  582. NULL, NULL, NULL,
  583. NULL, NULL, NULL, NULL, 0,
  584. "%s", "Message/ast_msg_queue");
  585. if (!chan) {
  586. return NULL;
  587. }
  588. ast_channel_tech_set(chan, &msg_chan_tech_hack);
  589. ast_channel_unlock(chan);
  590. ast_channel_unlink(chan);
  591. if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
  592. ast_hangup(chan);
  593. return NULL;
  594. }
  595. ast_channel_lock(chan);
  596. ast_channel_datastore_add(chan, ds);
  597. ast_channel_unlock(chan);
  598. return chan;
  599. }
  600. /*!
  601. * \internal
  602. * \brief Run the dialplan for message processing
  603. *
  604. * \pre The message has already been set up on the msg datastore
  605. * on this channel.
  606. */
  607. static void msg_route(struct ast_channel *chan, struct ast_msg *msg)
  608. {
  609. struct ast_pbx_args pbx_args;
  610. ast_explicit_goto(chan, msg->context, S_OR(msg->exten, "s"), 1);
  611. memset(&pbx_args, 0, sizeof(pbx_args));
  612. pbx_args.no_hangup_chan = 1,
  613. ast_pbx_run_args(chan, &pbx_args);
  614. }
  615. /*!
  616. * \internal
  617. * \brief Clean up ast_channel after each message
  618. *
  619. * Reset various bits of state after routing each message so the same ast_channel
  620. * can just be reused.
  621. */
  622. static void chan_cleanup(struct ast_channel *chan)
  623. {
  624. struct ast_datastore *msg_ds, *ds;
  625. struct varshead *headp;
  626. struct ast_var_t *vardata;
  627. struct ast_frame *cur;
  628. ast_channel_lock(chan);
  629. /*
  630. * Remove the msg datastore. Free its data but keep around the datastore
  631. * object and just reuse it.
  632. */
  633. if ((msg_ds = ast_channel_datastore_find(chan, &msg_datastore, NULL)) && msg_ds->data) {
  634. ast_channel_datastore_remove(chan, msg_ds);
  635. ao2_ref(msg_ds->data, -1);
  636. msg_ds->data = NULL;
  637. }
  638. /*
  639. * Destroy all other datastores.
  640. */
  641. while ((ds = AST_LIST_REMOVE_HEAD(ast_channel_datastores(chan), entry))) {
  642. ast_datastore_free(ds);
  643. }
  644. /*
  645. * Destroy all channel variables.
  646. */
  647. headp = ast_channel_varshead(chan);
  648. while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
  649. ast_var_delete(vardata);
  650. }
  651. /*
  652. * Remove frames from read queue
  653. */
  654. while ((cur = AST_LIST_REMOVE_HEAD(ast_channel_readq(chan), frame_list))) {
  655. ast_frfree(cur);
  656. }
  657. /*
  658. * Restore msg datastore.
  659. */
  660. if (msg_ds) {
  661. ast_channel_datastore_add(chan, msg_ds);
  662. }
  663. /*
  664. * Clear softhangup flags.
  665. */
  666. ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ALL);
  667. /*
  668. * Flush the alert pipe in case we miscounted somewhere when
  669. * messing with frames on the read queue, we had to flush the
  670. * read queue above, or we had an "Exceptionally long queue
  671. * length" event.
  672. */
  673. ast_channel_internal_alert_flush(chan);
  674. ast_channel_unlock(chan);
  675. }
  676. static void destroy_msg_q_chan(void *data)
  677. {
  678. struct ast_channel **chan = data;
  679. if (!*chan) {
  680. return;
  681. }
  682. ast_channel_release(*chan);
  683. }
  684. AST_THREADSTORAGE_CUSTOM(msg_q_chan, NULL, destroy_msg_q_chan);
  685. /*! \internal \brief Handle a message bound for the dialplan */
  686. static int dialplan_handle_msg_cb(struct ast_msg *msg)
  687. {
  688. struct ast_channel **chan_p, *chan;
  689. struct ast_datastore *ds;
  690. if (!(chan_p = ast_threadstorage_get(&msg_q_chan, sizeof(struct ast_channel *)))) {
  691. return -1;
  692. }
  693. if (!*chan_p) {
  694. if (!(*chan_p = create_msg_q_chan())) {
  695. return -1;
  696. }
  697. }
  698. chan = *chan_p;
  699. ast_channel_lock(chan);
  700. if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
  701. ast_channel_unlock(chan);
  702. return -1;
  703. }
  704. ao2_ref(msg, +1);
  705. ds->data = msg;
  706. ast_channel_unlock(chan);
  707. msg_route(chan, msg);
  708. chan_cleanup(chan);
  709. return 0;
  710. }
  711. /*! \internal \brief Determine if a message has a destination in the dialplan */
  712. static int dialplan_has_destination_cb(const struct ast_msg *msg)
  713. {
  714. if (ast_strlen_zero(msg->context)) {
  715. return 0;
  716. }
  717. return ast_exists_extension(NULL, msg->context, S_OR(msg->exten, "s"), 1, NULL);
  718. }
  719. static struct ast_msg_handler dialplan_msg_handler = {
  720. .name = "dialplan",
  721. .handle_msg = dialplan_handle_msg_cb,
  722. .has_destination = dialplan_has_destination_cb,
  723. };
  724. /*!
  725. * \internal
  726. * \brief Message queue task processor callback
  727. *
  728. * \retval 0 success
  729. * \retval non-zero failure
  730. *
  731. * \note Even though this returns a value, the taskprocessor code ignores the value.
  732. */
  733. static int msg_q_cb(void *data)
  734. {
  735. struct ast_msg *msg = data;
  736. int res = 1;
  737. int i;
  738. ast_rwlock_rdlock(&msg_handlers_lock);
  739. for (i = 0; i < AST_VECTOR_SIZE(&msg_handlers); i++) {
  740. const struct ast_msg_handler *handler = AST_VECTOR_GET(&msg_handlers, i);
  741. if (!handler->has_destination(msg)) {
  742. ast_debug(5, "Handler %s doesn't want message, moving on\n", handler->name);
  743. continue;
  744. }
  745. ast_debug(5, "Dispatching message to %s handler\n", handler->name);
  746. res &= handler->handle_msg(msg);
  747. }
  748. ast_rwlock_unlock(&msg_handlers_lock);
  749. if (res != 0) {
  750. ast_log(LOG_WARNING, "No handler processed message from %s to %s\n",
  751. S_OR(msg->from, "<unknown>"), S_OR(msg->to, "<unknown>"));
  752. }
  753. ao2_ref(msg, -1);
  754. return res;
  755. }
  756. int ast_msg_has_destination(const struct ast_msg *msg)
  757. {
  758. int i;
  759. int result = 0;
  760. ast_rwlock_rdlock(&msg_handlers_lock);
  761. for (i = 0; i < AST_VECTOR_SIZE(&msg_handlers); i++) {
  762. const struct ast_msg_handler *handler = AST_VECTOR_GET(&msg_handlers, i);
  763. ast_debug(5, "Seeing if %s can handle message\n", handler->name);
  764. if (handler->has_destination(msg)) {
  765. ast_debug(5, "%s can handle message\n", handler->name);
  766. result = 1;
  767. break;
  768. }
  769. }
  770. ast_rwlock_unlock(&msg_handlers_lock);
  771. return result;
  772. }
  773. int ast_msg_queue(struct ast_msg *msg)
  774. {
  775. int res;
  776. res = ast_taskprocessor_push(msg_q_tp, msg_q_cb, msg);
  777. if (res == -1) {
  778. ao2_ref(msg, -1);
  779. }
  780. return res;
  781. }
  782. /*!
  783. * \internal
  784. * \brief Find or create a message datastore on a channel
  785. *
  786. * \pre chan is locked
  787. *
  788. * \param chan the relevant channel
  789. *
  790. * \return the channel's message datastore, or NULL on error
  791. */
  792. static struct ast_datastore *msg_datastore_find_or_create(struct ast_channel *chan)
  793. {
  794. struct ast_datastore *ds;
  795. if ((ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
  796. return ds;
  797. }
  798. if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
  799. return NULL;
  800. }
  801. if (!(ds->data = ast_msg_alloc())) {
  802. ast_datastore_free(ds);
  803. return NULL;
  804. }
  805. ast_channel_datastore_add(chan, ds);
  806. return ds;
  807. }
  808. static int msg_func_read(struct ast_channel *chan, const char *function,
  809. char *data, char *buf, size_t len)
  810. {
  811. struct ast_datastore *ds;
  812. struct ast_msg *msg;
  813. if (!chan) {
  814. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
  815. return -1;
  816. }
  817. ast_channel_lock(chan);
  818. if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
  819. ast_channel_unlock(chan);
  820. ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
  821. return -1;
  822. }
  823. msg = ds->data;
  824. ao2_ref(msg, +1);
  825. ast_channel_unlock(chan);
  826. ao2_lock(msg);
  827. if (!strcasecmp(data, "to")) {
  828. ast_copy_string(buf, msg->to, len);
  829. } else if (!strcasecmp(data, "from")) {
  830. ast_copy_string(buf, msg->from, len);
  831. } else if (!strcasecmp(data, "body")) {
  832. ast_copy_string(buf, msg->body, len);
  833. } else {
  834. ast_log(LOG_WARNING, "Invalid argument to MESSAGE(): '%s'\n", data);
  835. }
  836. ao2_unlock(msg);
  837. ao2_ref(msg, -1);
  838. return 0;
  839. }
  840. static int msg_func_write(struct ast_channel *chan, const char *function,
  841. char *data, const char *value)
  842. {
  843. struct ast_datastore *ds;
  844. struct ast_msg *msg;
  845. if (!chan) {
  846. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
  847. return -1;
  848. }
  849. ast_channel_lock(chan);
  850. if (!(ds = msg_datastore_find_or_create(chan))) {
  851. ast_channel_unlock(chan);
  852. return -1;
  853. }
  854. msg = ds->data;
  855. ao2_ref(msg, +1);
  856. ast_channel_unlock(chan);
  857. ao2_lock(msg);
  858. if (!strcasecmp(data, "to")) {
  859. ast_msg_set_to(msg, "%s", value);
  860. } else if (!strcasecmp(data, "from")) {
  861. ast_msg_set_from(msg, "%s", value);
  862. } else if (!strcasecmp(data, "body")) {
  863. ast_msg_set_body(msg, "%s", value);
  864. } else if (!strcasecmp(data, "custom_data")) {
  865. int outbound = -1;
  866. if (!strcasecmp(value, "mark_all_outbound")) {
  867. outbound = 1;
  868. } else if (!strcasecmp(value, "clear_all_outbound")) {
  869. outbound = 0;
  870. } else {
  871. ast_log(LOG_WARNING, "'%s' is not a valid value for custom_data\n", value);
  872. }
  873. if (outbound != -1) {
  874. struct msg_data *hdr_data;
  875. struct ao2_iterator iter = ao2_iterator_init(msg->vars, 0);
  876. while ((hdr_data = ao2_iterator_next(&iter))) {
  877. hdr_data->send = outbound;
  878. ao2_ref(hdr_data, -1);
  879. }
  880. ao2_iterator_destroy(&iter);
  881. }
  882. } else {
  883. ast_log(LOG_WARNING, "'%s' is not a valid write argument.\n", data);
  884. }
  885. ao2_unlock(msg);
  886. ao2_ref(msg, -1);
  887. return 0;
  888. }
  889. static int msg_data_func_read(struct ast_channel *chan, const char *function,
  890. char *data, char *buf, size_t len)
  891. {
  892. struct ast_datastore *ds;
  893. struct ast_msg *msg;
  894. const char *val;
  895. if (!chan) {
  896. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
  897. return -1;
  898. }
  899. ast_channel_lock(chan);
  900. if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
  901. ast_channel_unlock(chan);
  902. ast_log(LOG_ERROR, "No MESSAGE data found on the channel to read.\n");
  903. return -1;
  904. }
  905. msg = ds->data;
  906. ao2_ref(msg, +1);
  907. ast_channel_unlock(chan);
  908. ao2_lock(msg);
  909. if ((val = ast_msg_get_var(msg, data))) {
  910. ast_copy_string(buf, val, len);
  911. }
  912. ao2_unlock(msg);
  913. ao2_ref(msg, -1);
  914. return 0;
  915. }
  916. static int msg_data_func_write(struct ast_channel *chan, const char *function,
  917. char *data, const char *value)
  918. {
  919. struct ast_datastore *ds;
  920. struct ast_msg *msg;
  921. if (!chan) {
  922. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
  923. return -1;
  924. }
  925. ast_channel_lock(chan);
  926. if (!(ds = msg_datastore_find_or_create(chan))) {
  927. ast_channel_unlock(chan);
  928. return -1;
  929. }
  930. msg = ds->data;
  931. ao2_ref(msg, +1);
  932. ast_channel_unlock(chan);
  933. ao2_lock(msg);
  934. ast_msg_set_var_outbound(msg, data, value);
  935. ao2_unlock(msg);
  936. ao2_ref(msg, -1);
  937. return 0;
  938. }
  939. /*!
  940. * \internal \brief Find a \c ast_msg_tech by its technology name
  941. *
  942. * \param tech_name The name of the message technology
  943. *
  944. * \note \c msg_techs should be locked via \c msg_techs_lock prior to
  945. * calling this function
  946. *
  947. * \retval NULL if no \c ast_msg_tech has been registered
  948. * \retval \c ast_msg_tech if registered
  949. */
  950. static const struct ast_msg_tech *msg_find_by_tech_name(const char *tech_name)
  951. {
  952. const struct ast_msg_tech *current;
  953. int i;
  954. for (i = 0; i < AST_VECTOR_SIZE(&msg_techs); i++) {
  955. current = AST_VECTOR_GET(&msg_techs, i);
  956. if (!strcmp(current->name, tech_name)) {
  957. return current;
  958. }
  959. }
  960. return NULL;
  961. }
  962. /*!
  963. * \internal \brief Find a \c ast_msg_handler by its technology name
  964. *
  965. * \param tech_name The name of the message technology
  966. *
  967. * \note \c msg_handlers should be locked via \c msg_handlers_lock
  968. * prior to calling this function
  969. *
  970. * \retval NULL if no \c ast_msg_handler has been registered
  971. * \retval \c ast_msg_handler if registered
  972. */
  973. static const struct ast_msg_handler *msg_handler_find_by_tech_name(const char *tech_name)
  974. {
  975. const struct ast_msg_handler *current;
  976. int i;
  977. for (i = 0; i < AST_VECTOR_SIZE(&msg_handlers); i++) {
  978. current = AST_VECTOR_GET(&msg_handlers, i);
  979. if (!strcmp(current->name, tech_name)) {
  980. return current;
  981. }
  982. }
  983. return NULL;
  984. }
  985. /*!
  986. * \internal
  987. * \brief MessageSend() application
  988. */
  989. static int msg_send_exec(struct ast_channel *chan, const char *data)
  990. {
  991. struct ast_datastore *ds;
  992. struct ast_msg *msg;
  993. char *tech_name;
  994. const struct ast_msg_tech *msg_tech;
  995. char *parse;
  996. int res = -1;
  997. AST_DECLARE_APP_ARGS(args,
  998. AST_APP_ARG(to);
  999. AST_APP_ARG(from);
  1000. );
  1001. if (ast_strlen_zero(data)) {
  1002. ast_log(LOG_WARNING, "An argument is required to MessageSend()\n");
  1003. pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
  1004. return 0;
  1005. }
  1006. parse = ast_strdupa(data);
  1007. AST_STANDARD_APP_ARGS(args, parse);
  1008. if (ast_strlen_zero(args.to)) {
  1009. ast_log(LOG_WARNING, "A 'to' URI is required for MessageSend()\n");
  1010. pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_URI");
  1011. return 0;
  1012. }
  1013. ast_channel_lock(chan);
  1014. if (!(ds = ast_channel_datastore_find(chan, &msg_datastore, NULL))) {
  1015. ast_channel_unlock(chan);
  1016. ast_log(LOG_WARNING, "No message data found on channel to send.\n");
  1017. pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "FAILURE");
  1018. return 0;
  1019. }
  1020. msg = ds->data;
  1021. ao2_ref(msg, +1);
  1022. ast_channel_unlock(chan);
  1023. tech_name = ast_strdupa(args.to);
  1024. tech_name = strsep(&tech_name, ":");
  1025. ast_rwlock_rdlock(&msg_techs_lock);
  1026. msg_tech = msg_find_by_tech_name(tech_name);
  1027. if (!msg_tech) {
  1028. ast_log(LOG_WARNING, "No message technology '%s' found.\n", tech_name);
  1029. pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", "INVALID_PROTOCOL");
  1030. goto exit_cleanup;
  1031. }
  1032. /*
  1033. * The message lock is held here to safely allow the technology
  1034. * implementation to access the message fields without worrying
  1035. * that they could change.
  1036. */
  1037. ao2_lock(msg);
  1038. res = msg_tech->msg_send(msg, S_OR(args.to, ""), S_OR(args.from, ""));
  1039. ao2_unlock(msg);
  1040. pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", res ? "FAILURE" : "SUCCESS");
  1041. exit_cleanup:
  1042. ast_rwlock_unlock(&msg_techs_lock);
  1043. ao2_ref(msg, -1);
  1044. return 0;
  1045. }
  1046. static int action_messagesend(struct mansession *s, const struct message *m)
  1047. {
  1048. const char *to = ast_strdupa(astman_get_header(m, "To"));
  1049. const char *from = astman_get_header(m, "From");
  1050. const char *body = astman_get_header(m, "Body");
  1051. const char *base64body = astman_get_header(m, "Base64Body");
  1052. char base64decoded[1301] = { 0, };
  1053. char *tech_name = NULL;
  1054. struct ast_variable *vars = NULL;
  1055. struct ast_variable *data = NULL;
  1056. const struct ast_msg_tech *msg_tech;
  1057. struct ast_msg *msg;
  1058. int res = -1;
  1059. if (ast_strlen_zero(to)) {
  1060. astman_send_error(s, m, "No 'To' address specified.");
  1061. return 0;
  1062. }
  1063. if (!ast_strlen_zero(base64body)) {
  1064. ast_base64decode((unsigned char *) base64decoded, base64body, sizeof(base64decoded) - 1);
  1065. body = base64decoded;
  1066. }
  1067. tech_name = ast_strdupa(to);
  1068. tech_name = strsep(&tech_name, ":");
  1069. ast_rwlock_rdlock(&msg_techs_lock);
  1070. msg_tech = msg_find_by_tech_name(tech_name);
  1071. if (!msg_tech) {
  1072. ast_rwlock_unlock(&msg_techs_lock);
  1073. astman_send_error(s, m, "Message technology not found.");
  1074. return 0;
  1075. }
  1076. if (!(msg = ast_msg_alloc())) {
  1077. ast_rwlock_unlock(&msg_techs_lock);
  1078. astman_send_error(s, m, "Internal failure\n");
  1079. return 0;
  1080. }
  1081. data = astman_get_variables_order(m, ORDER_NATURAL);
  1082. for (vars = data; vars; vars = vars->next) {
  1083. ast_msg_set_var_outbound(msg, vars->name, vars->value);
  1084. }
  1085. ast_msg_set_body(msg, "%s", body);
  1086. res = msg_tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
  1087. ast_rwlock_unlock(&msg_techs_lock);
  1088. ast_variables_destroy(vars);
  1089. ao2_ref(msg, -1);
  1090. if (res) {
  1091. astman_send_error(s, m, "Message failed to send.");
  1092. } else {
  1093. astman_send_ack(s, m, "Message successfully sent");
  1094. }
  1095. return 0;
  1096. }
  1097. int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
  1098. {
  1099. char *tech_name = NULL;
  1100. const struct ast_msg_tech *msg_tech;
  1101. int res = -1;
  1102. if (ast_strlen_zero(to)) {
  1103. ao2_ref(msg, -1);
  1104. return -1;
  1105. }
  1106. tech_name = ast_strdupa(to);
  1107. tech_name = strsep(&tech_name, ":");
  1108. ast_rwlock_rdlock(&msg_techs_lock);
  1109. msg_tech = msg_find_by_tech_name(tech_name);
  1110. if (!msg_tech) {
  1111. ast_log(LOG_ERROR, "Unknown message tech: %s\n", tech_name);
  1112. ast_rwlock_unlock(&msg_techs_lock);
  1113. return -1;
  1114. }
  1115. res = msg_tech->msg_send(msg, S_OR(to, ""), S_OR(from, ""));
  1116. ast_rwlock_unlock(&msg_techs_lock);
  1117. ao2_ref(msg, -1);
  1118. return res;
  1119. }
  1120. /*!
  1121. * \brief Structure used to transport a message through the frame core
  1122. * \since 13.22.0
  1123. * \since 15.5.0
  1124. */
  1125. struct ast_msg_data {
  1126. /*! The length of this structure plus the actual length of the allocated buffer */
  1127. size_t length;
  1128. enum ast_msg_data_source_type source;
  1129. /*! These are indices into the buffer where teh attribute starts */
  1130. int attribute_value_offsets[__AST_MSG_DATA_ATTR_LAST];
  1131. /*! The buffer containing the NULL separated attributes */
  1132. char buf[0];
  1133. };
  1134. #define ATTRIBUTE_UNSET -1
  1135. struct ast_msg_data *ast_msg_data_alloc(enum ast_msg_data_source_type source,
  1136. struct ast_msg_data_attribute attributes[], size_t count)
  1137. {
  1138. struct ast_msg_data *msg;
  1139. size_t len = sizeof(*msg);
  1140. size_t i;
  1141. size_t current_offset = 0;
  1142. enum ast_msg_data_attribute_type attr_type;
  1143. if (!attributes) {
  1144. ast_assert(attributes != NULL);
  1145. return NULL;
  1146. }
  1147. if (!count) {
  1148. ast_assert(count > 0);
  1149. return NULL;
  1150. }
  1151. /* Calculate the length required for the buffer */
  1152. for (i=0; i < count; i++) {
  1153. if (!attributes[i].value) {
  1154. ast_assert(attributes[i].value != NULL);
  1155. return NULL;
  1156. }
  1157. len += (strlen(attributes[i].value) + 1);
  1158. }
  1159. msg = ast_calloc(1, len);
  1160. if (!msg) {
  1161. return NULL;
  1162. }
  1163. msg->source = source;
  1164. msg->length = len;
  1165. /* Mark all of the attributes as unset */
  1166. for (attr_type = 0; attr_type < __AST_MSG_DATA_ATTR_LAST; attr_type++) {
  1167. msg->attribute_value_offsets[attr_type] = ATTRIBUTE_UNSET;
  1168. }
  1169. /* Set the ones we have and increment the offset */
  1170. for (i=0; i < count; i++) {
  1171. len = (strlen(attributes[i].value) + 1);
  1172. strcpy(msg->buf + current_offset, attributes[i].value); /* Safe */
  1173. msg->attribute_value_offsets[attributes[i].type] = current_offset;
  1174. current_offset += len;
  1175. }
  1176. return msg;
  1177. }
  1178. struct ast_msg_data *ast_msg_data_dup(struct ast_msg_data *msg)
  1179. {
  1180. struct ast_msg_data *dest;
  1181. if (!msg) {
  1182. ast_assert(msg != NULL);
  1183. return NULL;
  1184. }
  1185. dest = ast_malloc(msg->length);
  1186. if (!dest) {
  1187. return NULL;
  1188. }
  1189. memcpy(dest, msg, msg->length);
  1190. return dest;
  1191. }
  1192. size_t ast_msg_data_get_length(struct ast_msg_data *msg)
  1193. {
  1194. if (!msg) {
  1195. ast_assert(msg != NULL);
  1196. return 0;
  1197. }
  1198. return msg->length;
  1199. }
  1200. enum ast_msg_data_source_type ast_msg_data_get_source_type(struct ast_msg_data *msg)
  1201. {
  1202. if (!msg) {
  1203. ast_assert(msg != NULL);
  1204. return AST_MSG_DATA_SOURCE_TYPE_UNKNOWN;
  1205. }
  1206. return msg->source;
  1207. }
  1208. const char *ast_msg_data_get_attribute(struct ast_msg_data *msg,
  1209. enum ast_msg_data_attribute_type attribute_type)
  1210. {
  1211. if (!msg) {
  1212. ast_assert(msg != NULL);
  1213. return "";
  1214. }
  1215. if (msg->attribute_value_offsets[attribute_type] > ATTRIBUTE_UNSET) {
  1216. return msg->buf + msg->attribute_value_offsets[attribute_type];
  1217. }
  1218. return "";
  1219. }
  1220. int ast_msg_data_queue_frame(struct ast_channel *channel, struct ast_msg_data *msg)
  1221. {
  1222. struct ast_frame f;
  1223. if (!channel) {
  1224. ast_assert(channel != NULL);
  1225. return -1;
  1226. }
  1227. if (!msg) {
  1228. ast_assert(msg != NULL);
  1229. return -1;
  1230. }
  1231. memset(&f, 0, sizeof(f));
  1232. f.frametype = AST_FRAME_TEXT_DATA;
  1233. f.data.ptr = msg;
  1234. f.datalen = msg->length;
  1235. return ast_queue_frame(channel, &f);
  1236. }
  1237. int ast_msg_tech_register(const struct ast_msg_tech *tech)
  1238. {
  1239. const struct ast_msg_tech *match;
  1240. ast_rwlock_wrlock(&msg_techs_lock);
  1241. match = msg_find_by_tech_name(tech->name);
  1242. if (match) {
  1243. ast_log(LOG_ERROR, "Message technology already registered for '%s'\n",
  1244. tech->name);
  1245. ast_rwlock_unlock(&msg_techs_lock);
  1246. return -1;
  1247. }
  1248. if (AST_VECTOR_APPEND(&msg_techs, tech)) {
  1249. ast_log(LOG_ERROR, "Failed to register message technology for '%s'\n",
  1250. tech->name);
  1251. ast_rwlock_unlock(&msg_techs_lock);
  1252. return -1;
  1253. }
  1254. ast_verb(3, "Message technology '%s' registered.\n", tech->name);
  1255. ast_rwlock_unlock(&msg_techs_lock);
  1256. return 0;
  1257. }
  1258. /*!
  1259. * \brief Comparison callback for \c ast_msg_tech vector removal
  1260. *
  1261. * \param vec_elem The element in the vector being compared
  1262. * \param srch The element being looked up
  1263. *
  1264. * \retval non-zero The items are equal
  1265. * \retval 0 The items are not equal
  1266. */
  1267. static int msg_tech_cmp(const struct ast_msg_tech *vec_elem, const struct ast_msg_tech *srch)
  1268. {
  1269. return !strcmp(vec_elem->name, srch->name);
  1270. }
  1271. int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
  1272. {
  1273. int match;
  1274. ast_rwlock_wrlock(&msg_techs_lock);
  1275. match = AST_VECTOR_REMOVE_CMP_UNORDERED(&msg_techs, tech, msg_tech_cmp,
  1276. AST_VECTOR_ELEM_CLEANUP_NOOP);
  1277. ast_rwlock_unlock(&msg_techs_lock);
  1278. if (match) {
  1279. ast_log(LOG_ERROR, "No '%s' message technology found.\n", tech->name);
  1280. return -1;
  1281. }
  1282. ast_verb(2, "Message technology '%s' unregistered.\n", tech->name);
  1283. return 0;
  1284. }
  1285. int ast_msg_handler_register(const struct ast_msg_handler *handler)
  1286. {
  1287. const struct ast_msg_handler *match;
  1288. ast_rwlock_wrlock(&msg_handlers_lock);
  1289. match = msg_handler_find_by_tech_name(handler->name);
  1290. if (match) {
  1291. ast_log(LOG_ERROR, "Message handler already registered for '%s'\n",
  1292. handler->name);
  1293. ast_rwlock_unlock(&msg_handlers_lock);
  1294. return -1;
  1295. }
  1296. if (AST_VECTOR_APPEND(&msg_handlers, handler)) {
  1297. ast_log(LOG_ERROR, "Failed to register message handler for '%s'\n",
  1298. handler->name);
  1299. ast_rwlock_unlock(&msg_handlers_lock);
  1300. return -1;
  1301. }
  1302. ast_verb(2, "Message handler '%s' registered.\n", handler->name);
  1303. ast_rwlock_unlock(&msg_handlers_lock);
  1304. return 0;
  1305. }
  1306. /*!
  1307. * \brief Comparison callback for \c ast_msg_handler vector removal
  1308. *
  1309. * \param vec_elem The element in the vector being compared
  1310. * \param srch The element being looked up
  1311. *
  1312. * \retval non-zero The items are equal
  1313. * \retval 0 The items are not equal
  1314. */
  1315. static int msg_handler_cmp(const struct ast_msg_handler *vec_elem, const struct ast_msg_handler *srch)
  1316. {
  1317. return !strcmp(vec_elem->name, srch->name);
  1318. }
  1319. int ast_msg_handler_unregister(const struct ast_msg_handler *handler)
  1320. {
  1321. int match;
  1322. ast_rwlock_wrlock(&msg_handlers_lock);
  1323. match = AST_VECTOR_REMOVE_CMP_UNORDERED(&msg_handlers, handler, msg_handler_cmp,
  1324. AST_VECTOR_ELEM_CLEANUP_NOOP);
  1325. ast_rwlock_unlock(&msg_handlers_lock);
  1326. if (match) {
  1327. ast_log(LOG_ERROR, "No '%s' message handler found.\n", handler->name);
  1328. return -1;
  1329. }
  1330. ast_verb(3, "Message handler '%s' unregistered.\n", handler->name);
  1331. return 0;
  1332. }
  1333. void ast_msg_shutdown(void)
  1334. {
  1335. if (msg_q_tp) {
  1336. msg_q_tp = ast_taskprocessor_unreference(msg_q_tp);
  1337. }
  1338. }
  1339. /*!
  1340. * \internal
  1341. * \brief Clean up other resources on Asterisk shutdown
  1342. *
  1343. * \note This does not include the msg_q_tp object, which must be disposed
  1344. * of prior to Asterisk checking for channel destruction in its shutdown
  1345. * sequence. The atexit handlers are executed after this occurs.
  1346. */
  1347. static void message_shutdown(void)
  1348. {
  1349. ast_msg_handler_unregister(&dialplan_msg_handler);
  1350. ast_custom_function_unregister(&msg_function);
  1351. ast_custom_function_unregister(&msg_data_function);
  1352. ast_unregister_application(app_msg_send);
  1353. ast_manager_unregister("MessageSend");
  1354. AST_VECTOR_FREE(&msg_techs);
  1355. ast_rwlock_destroy(&msg_techs_lock);
  1356. AST_VECTOR_FREE(&msg_handlers);
  1357. ast_rwlock_destroy(&msg_handlers_lock);
  1358. }
  1359. /*
  1360. * \internal
  1361. * \brief Initialize stuff during Asterisk startup.
  1362. *
  1363. * Cleanup isn't a big deal in this function. If we return non-zero,
  1364. * Asterisk is going to exit.
  1365. *
  1366. * \retval 0 success
  1367. * \retval non-zero failure
  1368. */
  1369. int ast_msg_init(void)
  1370. {
  1371. int res;
  1372. msg_q_tp = ast_taskprocessor_get("ast_msg_queue", TPS_REF_DEFAULT);
  1373. if (!msg_q_tp) {
  1374. return -1;
  1375. }
  1376. ast_rwlock_init(&msg_techs_lock);
  1377. if (AST_VECTOR_INIT(&msg_techs, 8)) {
  1378. return -1;
  1379. }
  1380. ast_rwlock_init(&msg_handlers_lock);
  1381. if (AST_VECTOR_INIT(&msg_handlers, 4)) {
  1382. return -1;
  1383. }
  1384. res = ast_msg_handler_register(&dialplan_msg_handler);
  1385. res |= __ast_custom_function_register(&msg_function, NULL);
  1386. res |= __ast_custom_function_register(&msg_data_function, NULL);
  1387. res |= ast_register_application2(app_msg_send, msg_send_exec, NULL, NULL, NULL);
  1388. res |= ast_manager_register_xml_core("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend);
  1389. ast_register_cleanup(message_shutdown);
  1390. return res;
  1391. }