func_hangupcause.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999-2012, Digium, Inc.
  5. *
  6. * Kinsey Moore <kmoore@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 Functions related to retreiving per-channel hangupcause information
  21. *
  22. * \author Kinsey Moore <kmoore@digium.com>
  23. * \ingroup functions
  24. *
  25. * See Also:
  26. * \arg \ref AstCREDITS
  27. */
  28. /*** MODULEINFO
  29. <support_level>core</support_level>
  30. ***/
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  33. #include "asterisk/module.h"
  34. #include "asterisk/channel.h"
  35. #include "asterisk/pbx.h"
  36. #include "asterisk/utils.h"
  37. #include "asterisk/app.h"
  38. /*** DOCUMENTATION
  39. <function name="HANGUPCAUSE" language="en_US">
  40. <synopsis>
  41. Gets per-channel hangupcause information from the channel.
  42. </synopsis>
  43. <syntax>
  44. <parameter name="channel" required="true">
  45. <para>The name of the channel for which to retreive cause information.</para>
  46. </parameter>
  47. <parameter name="type" required="true">
  48. <para>Parameter describing which type of information is requested. Types are:</para>
  49. <enumlist>
  50. <enum name="tech"><para>Technology-specific cause information</para></enum>
  51. <enum name="ast"><para>Translated Asterisk cause code</para></enum>
  52. </enumlist>
  53. </parameter>
  54. </syntax>
  55. <description>
  56. <para>Gets technology-specific or translated Asterisk cause code information
  57. from the channel for the specified channel that resulted from a dial.</para>
  58. </description>
  59. <see-also>
  60. <ref type="function">HANGUPCAUSE_KEYS</ref>
  61. <ref type="application">HangupCauseClear</ref>
  62. </see-also>
  63. </function>
  64. <function name="HANGUPCAUSE_KEYS" language="en_US">
  65. <synopsis>
  66. Gets the list of channels for which hangup causes are available.
  67. </synopsis>
  68. <description>
  69. <para>Returns a comma-separated list of channel names to be used with the HANGUPCAUSE function.</para>
  70. </description>
  71. <see-also>
  72. <ref type="function">HANGUPCAUSE</ref>
  73. <ref type="application">HangupCauseClear</ref>
  74. </see-also>
  75. </function>
  76. <application name="HangupCauseClear" language="en_US">
  77. <synopsis>
  78. Clears hangup cause information from the channel that is available through HANGUPCAUSE.
  79. </synopsis>
  80. <description>
  81. <para>Clears all channel-specific hangup cause information from the channel.
  82. This is never done automatically (i.e. for new Dial()s).</para>
  83. </description>
  84. <see-also>
  85. <ref type="function">HANGUPCAUSE</ref>
  86. <ref type="function">HANGUPCAUSE_KEYS</ref>
  87. </see-also>
  88. </application>
  89. ***/
  90. /*!
  91. * \internal
  92. * \brief Read values from the hangupcause ao2 container.
  93. *
  94. * \param chan Asterisk channel to read
  95. * \param cmd Not used
  96. * \param data HANGUPCAUSE function argument string
  97. * \param buf Buffer to fill with read value.
  98. * \param len Length of the buffer
  99. *
  100. * \retval 0 on success.
  101. * \retval -1 on error.
  102. */
  103. static int hangupcause_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  104. {
  105. char *parms;
  106. struct ast_control_pvt_cause_code *cause_code;
  107. int res = 0;
  108. AST_DECLARE_APP_ARGS(args,
  109. AST_APP_ARG(channel); /*!< Channel name */
  110. AST_APP_ARG(type); /*!< Type of information requested (ast or tech) */
  111. );
  112. /* Ensure that the buffer is empty */
  113. *buf = 0;
  114. if (!chan) {
  115. return -1;
  116. }
  117. parms = ast_strdupa(data);
  118. AST_STANDARD_APP_ARGS(args, parms);
  119. if (args.argc != 2) {
  120. /* Must have two arguments. */
  121. ast_log(LOG_WARNING, "The HANGUPCAUSE function must have 2 parameters, not %u\n", args.argc);
  122. return -1;
  123. }
  124. ast_channel_lock(chan);
  125. cause_code = ast_channel_dialed_causes_find(chan, args.channel);
  126. ast_channel_unlock(chan);
  127. if (!cause_code) {
  128. ast_log(LOG_WARNING, "Unable to find information for channel %s\n", args.channel);
  129. return -1;
  130. }
  131. if (!strcmp(args.type, "ast")) {
  132. ast_copy_string(buf, ast_cause2str(cause_code->ast_cause), len);
  133. } else if (!strcmp(args.type, "tech")) {
  134. ast_copy_string(buf, cause_code->code, len);
  135. } else {
  136. ast_log(LOG_WARNING, "Information type not recognized (%s)\n", args.type);
  137. res = -1;
  138. }
  139. ao2_ref(cause_code, -1);
  140. return res;
  141. }
  142. /*!
  143. * \internal
  144. * \brief Read keys from the hangupcause ao2 container.
  145. *
  146. * \param chan Asterisk channel to read
  147. * \param cmd Not used
  148. * \param data HANGUPCAUSE_KEYS function argument string
  149. * \param buf Buffer to fill with read value.
  150. * \param len Length of the buffer
  151. *
  152. * \retval 0 on success.
  153. * \retval -1 on error.
  154. */
  155. static int hangupcause_keys_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
  156. {
  157. struct ast_str *chanlist;
  158. /* Ensure that the buffer is empty */
  159. *buf = 0;
  160. if (!chan) {
  161. return -1;
  162. }
  163. ast_channel_lock(chan);
  164. chanlist = ast_channel_dialed_causes_channels(chan);
  165. ast_channel_unlock(chan);
  166. if (chanlist && ast_str_strlen(chanlist)) {
  167. ast_copy_string(buf, ast_str_buffer(chanlist), len);
  168. }
  169. ast_free(chanlist);
  170. return 0;
  171. }
  172. /*!
  173. * \internal
  174. * \brief Remove all keys from the hangupcause ao2 container.
  175. *
  176. * \param chan Asterisk channel to read
  177. * \param data Not used
  178. *
  179. * \retval 0 on success.
  180. * \retval -1 on error.
  181. */
  182. static int hangupcause_clear_exec(struct ast_channel *chan, const char *data) {
  183. ast_channel_lock(chan);
  184. ast_channel_dialed_causes_clear(chan);
  185. ast_channel_unlock(chan);
  186. return 0;
  187. }
  188. static struct ast_custom_function hangupcause_function = {
  189. .name = "HANGUPCAUSE",
  190. .read = hangupcause_read,
  191. };
  192. static struct ast_custom_function hangupcause_keys_function = {
  193. .name = "HANGUPCAUSE_KEYS",
  194. .read = hangupcause_keys_read,
  195. };
  196. static const char app[] = "HangupCauseClear";
  197. /*!
  198. * \internal
  199. * \brief Unload the function module
  200. *
  201. * \retval 0 on success.
  202. * \retval -1 on error.
  203. */
  204. static int unload_module(void)
  205. {
  206. int res;
  207. res = ast_custom_function_unregister(&hangupcause_function);
  208. res |= ast_custom_function_unregister(&hangupcause_keys_function);
  209. res |= ast_unregister_application(app);
  210. return res;
  211. }
  212. /*!
  213. * \internal
  214. * \brief Load and initialize the function module.
  215. *
  216. * \retval AST_MODULE_LOAD_SUCCESS on success.
  217. * \retval AST_MODULE_LOAD_DECLINE on error.
  218. */
  219. static int load_module(void)
  220. {
  221. int res;
  222. res = ast_custom_function_register(&hangupcause_function);
  223. res |= ast_custom_function_register(&hangupcause_keys_function);
  224. res |= ast_register_application_xml(app, hangupcause_clear_exec);
  225. return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
  226. }
  227. /* Do not wrap the following line. */
  228. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "HANGUPCAUSE related functions and applications");