app_sendtext.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@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 App to transmit a text message
  21. *
  22. * \author Mark Spencer <markster@digium.com>
  23. * \author Naveen Albert <asterisk@phreaknet.org>
  24. *
  25. * \note Requires support of sending text messages from channel driver
  26. *
  27. * \ingroup applications
  28. */
  29. /*** MODULEINFO
  30. <support_level>core</support_level>
  31. ***/
  32. #include "asterisk.h"
  33. #include "asterisk/file.h"
  34. #include "asterisk/channel.h"
  35. #include "asterisk/pbx.h"
  36. #include "asterisk/module.h"
  37. #include "asterisk/app.h"
  38. #include "asterisk/message.h"
  39. /*** DOCUMENTATION
  40. <application name="SendText" language="en_US">
  41. <synopsis>
  42. Send a Text Message on a channel.
  43. </synopsis>
  44. <syntax>
  45. <parameter name="text" required="false" />
  46. </syntax>
  47. <description>
  48. <para>Sends <replaceable>text</replaceable> to the current channel.</para>
  49. <note><para><literal>current channel</literal> could be the caller or callee depending
  50. on the context in which this application is called.</para></note>
  51. <para>
  52. </para>
  53. <para>The following variables can be set:</para>
  54. <variablelist>
  55. <variable name="SENDTEXT_FROM_DISPLAYNAME">
  56. <para>If set and this channel supports enhanced messaging, this value will be
  57. used as the <literal>From</literal> display name.</para>
  58. </variable>
  59. <variable name="SENDTEXT_TO_DISPLAYNAME">
  60. <para>If set and this channel supports enhanced messaging, this value will be
  61. used as the <literal>To</literal> display name.</para>
  62. </variable>
  63. <variable name="SENDTEXT_CONTENT_TYPE">
  64. <para>If set and this channel supports enhanced messaging, this value will be
  65. used as the message <literal>Content-Type</literal>. If not specified, the
  66. default of <literal>text/plain</literal> will be used.</para>
  67. <para><emphasis>Warning:</emphasis> Messages of types other than
  68. <literal>text/&#42;</literal> cannot be sent via channel drivers that do not
  69. support Enhanced Messaging. An attempt to do so will be ignored and will result
  70. in the <literal>SENDTEXTSTATUS</literal> variable being set to
  71. <literal>UNSUPPORTED</literal>.</para>
  72. </variable>
  73. <variable name="SENDTEXT_BODY">
  74. <para>If set this value will be used as the message body and any text supplied
  75. as a function parameter will be ignored.
  76. </para>
  77. </variable>
  78. </variablelist>
  79. <para>
  80. </para>
  81. <para>Result of transmission will be stored in the following variables:</para>
  82. <variablelist>
  83. <variable name="SENDTEXTTYPE">
  84. <value name="NONE">
  85. No message sent.
  86. </value>
  87. <value name="BASIC">
  88. Message body sent without attributes because the channel driver
  89. doesn't support enhanced messaging.
  90. </value>
  91. <value name="ENHANCED">
  92. The message was sent using enhanced messaging.
  93. </value>
  94. </variable>
  95. <variable name="SENDTEXTSTATUS">
  96. <value name="SUCCESS">
  97. Transmission succeeded.
  98. </value>
  99. <value name="FAILURE">
  100. Transmission failed.
  101. </value>
  102. <value name="UNSUPPORTED">
  103. Text transmission not supported by channel.
  104. </value>
  105. </variable>
  106. </variablelist>
  107. <para>
  108. </para>
  109. <note><para>The text encoding and transmission method is completely at the
  110. discretion of the channel driver. chan_pjsip will use in-dialog SIP MESSAGE
  111. messages always.</para></note>
  112. <para>
  113. </para>
  114. <para>Examples:
  115. </para>
  116. <example title="Send a simple message">
  117. same => n,SendText(Your Text Here)
  118. </example>
  119. <para>If the channel driver supports enhanced messaging (currently only chan_pjsip),
  120. you can set additional variables:</para>
  121. <example title="Alter the From display name">
  122. same => n,Set(SENDTEXT_FROM_DISPLAYNAME=Really From Bob)
  123. same => n,SendText(Your Text Here)
  124. </example>
  125. <example title="Send a JSON String">
  126. same => n,Set(SENDTEXT_CONTENT_TYPE=text/json)
  127. same => n,SendText({"foo":a, "bar":23})
  128. </example>
  129. <example title="Send a JSON String (alternate)">
  130. same => n,Set(SENDTEXT_CONTENT_TYPE=text/json)
  131. same => n,Set(SENDTEXT_BODY={"foo":a, "bar":23})
  132. same => n,SendText()
  133. </example>
  134. </description>
  135. <see-also>
  136. <ref type="application">ReceiveText</ref>
  137. </see-also>
  138. </application>
  139. <application name="ReceiveText" language="en_US">
  140. <since>
  141. <version>16.24.0</version>
  142. <version>18.10.0</version>
  143. <version>19.2.0</version>
  144. </since>
  145. <synopsis>
  146. Receive a Text Message on a channel.
  147. </synopsis>
  148. <syntax>
  149. <parameter name="timeout" required="false">
  150. <para>Time in seconds to wait for text. Default is 0 (forever).</para>
  151. </parameter>
  152. </syntax>
  153. <description>
  154. <para>Waits for <replaceable>timeout</replaceable> seconds on the current channel
  155. to receive text.</para>
  156. <para>Result of transmission will be stored in the following variables:</para>
  157. <variablelist>
  158. <variable name="RECEIVETEXTMESSAGE">
  159. <para>The received text message.</para>
  160. </variable>
  161. <variable name="RECEIVETEXTSTATUS">
  162. <value name="SUCCESS">
  163. Transmission succeeded.
  164. </value>
  165. <value name="FAILURE">
  166. Transmission failed or timed out.
  167. </value>
  168. </variable>
  169. </variablelist>
  170. <example title="Receive message on channel">
  171. same => n,ReceiveText()
  172. same => n,NoOp(${RECEIVETEXTMESSAGE})
  173. </example>
  174. </description>
  175. <see-also>
  176. <ref type="application">SendText</ref>
  177. </see-also>
  178. </application>
  179. ***/
  180. static const char * const app = "SendText";
  181. static const char * const app2 = "ReceiveText";
  182. static int sendtext_exec(struct ast_channel *chan, const char *data)
  183. {
  184. char *status;
  185. char *msg_type;
  186. struct ast_str *str;
  187. const char *from;
  188. const char *to;
  189. const char *content_type;
  190. const char *body;
  191. int rc = 0;
  192. ast_channel_lock(chan);
  193. from = pbx_builtin_getvar_helper(chan, "SENDTEXT_FROM_DISPLAYNAME");
  194. to = pbx_builtin_getvar_helper(chan, "SENDTEXT_TO_DISPLAYNAME");
  195. content_type = pbx_builtin_getvar_helper(chan, "SENDTEXT_CONTENT_TYPE");
  196. body = S_OR(pbx_builtin_getvar_helper(chan, "SENDTEXT_BODY"), data);
  197. body = S_OR(body, "");
  198. if (!(str = ast_str_alloca(strlen(body) + 1))) {
  199. rc = -1;
  200. goto cleanup;
  201. }
  202. ast_str_get_encoded_str(&str, -1, body);
  203. body = ast_str_buffer(str);
  204. msg_type = "NONE";
  205. status = "UNSUPPORTED";
  206. if (ast_channel_tech(chan)->send_text_data) {
  207. struct ast_msg_data *msg;
  208. struct ast_msg_data_attribute attrs[] =
  209. {
  210. {
  211. .type = AST_MSG_DATA_ATTR_FROM,
  212. .value = (char *)S_OR(from, ""),
  213. },
  214. {
  215. .type = AST_MSG_DATA_ATTR_TO,
  216. .value = (char *)S_OR(to, ""),
  217. },
  218. {
  219. .type = AST_MSG_DATA_ATTR_CONTENT_TYPE,
  220. .value = (char *)S_OR(content_type, ""),
  221. },
  222. {
  223. .type = AST_MSG_DATA_ATTR_BODY,
  224. .value = (char *)S_OR(body, ""),
  225. },
  226. };
  227. msg_type = "ENHANCED";
  228. msg = ast_msg_data_alloc(AST_MSG_DATA_SOURCE_TYPE_IN_DIALOG, attrs, ARRAY_LEN(attrs));
  229. if (msg) {
  230. if (ast_sendtext_data(chan, msg) == 0) {
  231. status = "SUCCESS";
  232. } else {
  233. status = "FAILURE";
  234. }
  235. ast_free(msg);
  236. } else {
  237. rc = -1;
  238. goto cleanup;
  239. }
  240. } else if (ast_channel_tech(chan)->send_text) {
  241. if (!ast_strlen_zero(content_type) && !ast_begins_with(content_type, "text/")) {
  242. rc = -1;
  243. goto cleanup;
  244. }
  245. msg_type = "BASIC";
  246. if (ast_sendtext(chan, body) == 0) {
  247. status = "SUCCESS";
  248. } else {
  249. status = "FAILURE";
  250. }
  251. }
  252. pbx_builtin_setvar_helper(chan, "SENDTEXTTYPE", msg_type);
  253. pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
  254. cleanup:
  255. pbx_builtin_setvar_helper(chan, "SENDTEXT_FROM_DISPLAYNAME", NULL);
  256. pbx_builtin_setvar_helper(chan, "SENDTEXT_TO_DISPLAYNAME", NULL);
  257. pbx_builtin_setvar_helper(chan, "SENDTEXT_CONTENT_TYPE", NULL);
  258. pbx_builtin_setvar_helper(chan, "SENDTEXT_BODY", NULL);
  259. ast_channel_unlock(chan);
  260. return rc;
  261. }
  262. static int recvtext_exec(struct ast_channel *chan, const char *data)
  263. {
  264. double timeout = 0, timeout_ms = 0;
  265. char *parse, *buf;
  266. AST_DECLARE_APP_ARGS(args,
  267. AST_APP_ARG(timeout);
  268. );
  269. parse = ast_strdupa(data);
  270. AST_STANDARD_APP_ARGS(args, parse);
  271. if (!ast_strlen_zero(args.timeout)) {
  272. if (sscanf(args.timeout, "%30lg", &timeout) != 1) {
  273. ast_log(LOG_WARNING, "Invalid timeout provided: %s. No timeout set.\n", args.timeout);
  274. return -1;
  275. }
  276. timeout_ms = timeout * 1000.0;
  277. }
  278. buf = ast_recvtext(chan, timeout_ms);
  279. pbx_builtin_setvar_helper(chan, "RECEIVETEXTSTATUS", buf ? "SUCCESS" : "FAILURE");
  280. if (buf) {
  281. pbx_builtin_setvar_helper(chan, "RECEIVETEXTMESSAGE", buf);
  282. ast_free(buf);
  283. }
  284. return 0;
  285. }
  286. static int unload_module(void)
  287. {
  288. int res;
  289. res = ast_unregister_application(app);
  290. res |= ast_unregister_application(app2);
  291. return res;
  292. }
  293. static int load_module(void)
  294. {
  295. int res;
  296. res = ast_register_application_xml(app, sendtext_exec);
  297. res |= ast_register_application_xml(app2, recvtext_exec);
  298. return res;
  299. }
  300. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send and Receive Text Applications");