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