Merge "res_musiconhold: Start playlist after initial announcement"
[asterisk/asterisk.git] / apps / app_originate.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2008, Roberto Casas.
5  * Copyright (C) 2008, Digium, Inc.
6  *
7  * Roberto Casas <roberto.casas@diaple.com>
8  * Russell Bryant <russell@digium.com>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20
21 /*!
22  * \file
23  * \brief Originate application
24  *
25  * \author Roberto Casas <roberto.casas@diaple.com>
26  * \author Russell Bryant <russell@digium.com>
27  *
28  * \ingroup applications
29  *
30  * \todo Make a way to be able to set variables (and functions) on the outbound
31  *       channel, similar to the Variable headers for the AMI Originate, and the
32  *       Set options for call files.
33  */
34
35 /*** MODULEINFO
36         <support_level>core</support_level>
37  ***/
38
39 #include "asterisk.h"
40
41 #include "asterisk/file.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/module.h"
45 #include "asterisk/app.h"
46 #include "asterisk/format_cache.h"
47
48 static const char app_originate[] = "Originate";
49
50 /*** DOCUMENTATION
51         <application name="Originate" language="en_US">
52                 <synopsis>
53                         Originate a call.
54                 </synopsis>
55                 <syntax>
56                         <parameter name="tech_data" required="true">
57                                 <para>Channel technology and data for creating the outbound channel.
58                       For example, SIP/1234.</para>
59                         </parameter>
60                         <parameter name="type" required="true">
61                                 <para>This should be <literal>app</literal> or <literal>exten</literal>, depending on whether the outbound channel should be connected to an application or extension.</para>
62                         </parameter>
63                         <parameter name="arg1" required="true">
64                                 <para>If the type is <literal>app</literal>, then this is the application name.  If the type is <literal>exten</literal>, then this is the context that the channel will be sent to.</para>
65                         </parameter>
66                         <parameter name="arg2" required="false">
67                                 <para>If the type is <literal>app</literal>, then this is the data passed as arguments to the application.  If the type is <literal>exten</literal>, then this is the extension that the channel will be sent to.</para>
68                         </parameter>
69                         <parameter name="arg3" required="false">
70                                 <para>If the type is <literal>exten</literal>, then this is the priority that the channel is sent to.  If the type is <literal>app</literal>, then this parameter is ignored.</para>
71                         </parameter>
72                         <parameter name="timeout" required="false">
73                                 <para>Timeout in seconds. Default is 30 seconds.</para>
74                         </parameter>
75                         <parameter name="options" required="false">
76                                 <optionlist>
77                                 <option name="b" argsep="^">
78                                         <para>Before originating the outgoing call, Gosub to the specified
79                                         location using the newly created channel.</para>
80                                         <argument name="context" required="false" />
81                                         <argument name="exten" required="false" />
82                                         <argument name="priority" required="true" hasparams="optional" argsep="^">
83                                                 <argument name="arg1" multiple="true" required="true" />
84                                                 <argument name="argN" />
85                                         </argument>
86                                 </option>
87                                 <option name="B" argsep="^">
88                                         <para>Before originating the outgoing call, Gosub to the specified
89                                         location using the current channel.</para>
90                                         <argument name="context" required="false" />
91                                         <argument name="exten" required="false" />
92                                         <argument name="priority" required="true" hasparams="optional" argsep="^">
93                                                 <argument name="arg1" multiple="true" required="true" />
94                                                 <argument name="argN" />
95                                         </argument>
96                                 </option>
97                                 </optionlist>
98                         </parameter>
99                 </syntax>
100                 <description>
101                 <para>This application originates an outbound call and connects it to a specified extension or application.  This application will block until the outgoing call fails or gets answered.  At that point, this application will exit with the status variable set and dialplan processing will continue.</para>
102
103                 <para>This application sets the following channel variable before exiting:</para>
104                 <variablelist>
105                         <variable name="ORIGINATE_STATUS">
106                                 <para>This indicates the result of the call origination.</para>
107                                 <value name="FAILED"/>
108                                 <value name="SUCCESS"/>
109                                 <value name="BUSY"/>
110                                 <value name="CONGESTION"/>
111                                 <value name="HANGUP"/>
112                                 <value name="RINGING"/>
113                                 <value name="UNKNOWN">
114                                 In practice, you should never see this value.  Please report it to the issue tracker if you ever see it.
115                                 </value>
116                         </variable>
117                 </variablelist>
118                 </description>
119         </application>
120  ***/
121
122
123 enum {
124         OPT_PREDIAL_CALLEE =    (1 << 0),
125         OPT_PREDIAL_CALLER =    (1 << 1),
126 };
127
128 enum {
129         OPT_ARG_PREDIAL_CALLEE,
130         OPT_ARG_PREDIAL_CALLER,
131         /* note: this entry _MUST_ be the last one in the enum */
132         OPT_ARG_ARRAY_SIZE,
133 };
134
135 AST_APP_OPTIONS(originate_exec_options, BEGIN_OPTIONS
136         AST_APP_OPTION_ARG('b', OPT_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE),
137         AST_APP_OPTION_ARG('B', OPT_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER),
138 END_OPTIONS );
139
140
141 static int originate_exec(struct ast_channel *chan, const char *data)
142 {
143         AST_DECLARE_APP_ARGS(args,
144                 AST_APP_ARG(tech_data);
145                 AST_APP_ARG(type);
146                 AST_APP_ARG(arg1);
147                 AST_APP_ARG(arg2);
148                 AST_APP_ARG(arg3);
149                 AST_APP_ARG(timeout);
150                 AST_APP_ARG(options);
151         );
152         struct ast_flags64 opts = { 0, };
153         char *opt_args[OPT_ARG_ARRAY_SIZE];
154         char *predial_callee = NULL;
155         char *parse;
156         char *chantech, *chandata;
157         int res = -1;
158         int continue_in_dialplan = 0;
159         int outgoing_status = 0;
160         unsigned int timeout = 30;
161         static const char default_exten[] = "s";
162         struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
163
164         ast_autoservice_start(chan);
165         if (!cap_slin) {
166                 goto return_cleanup;
167         }
168
169         ast_format_cap_append(cap_slin, ast_format_slin, 0);
170         ast_format_cap_append(cap_slin, ast_format_slin12, 0);
171         ast_format_cap_append(cap_slin, ast_format_slin16, 0);
172         ast_format_cap_append(cap_slin, ast_format_slin24, 0);
173         ast_format_cap_append(cap_slin, ast_format_slin32, 0);
174         ast_format_cap_append(cap_slin, ast_format_slin44, 0);
175         ast_format_cap_append(cap_slin, ast_format_slin48, 0);
176         ast_format_cap_append(cap_slin, ast_format_slin96, 0);
177         ast_format_cap_append(cap_slin, ast_format_slin192, 0);
178
179         if (ast_strlen_zero(data)) {
180                 ast_log(LOG_ERROR, "Originate() requires arguments\n");
181                 goto return_cleanup;
182         }
183
184         parse = ast_strdupa(data);
185
186         AST_STANDARD_APP_ARGS(args, parse);
187
188         if (args.argc < 3) {
189                 ast_log(LOG_ERROR, "Incorrect number of arguments\n");
190                 goto return_cleanup;
191         }
192
193         if (!ast_strlen_zero(args.timeout)) {
194                 if(sscanf(args.timeout, "%u", &timeout) != 1) {
195                         ast_log(LOG_NOTICE, "Invalid timeout: '%s'. Setting timeout to 30 seconds\n", args.timeout);
196                         timeout = 30;
197                 }
198         }
199
200         chandata = ast_strdupa(args.tech_data);
201         chantech = strsep(&chandata, "/");
202
203         if (ast_strlen_zero(chandata) || ast_strlen_zero(chantech)) {
204                 ast_log(LOG_ERROR, "Channel Tech/Data invalid: '%s'\n", args.tech_data);
205                 goto return_cleanup;
206         }
207
208         if (!ast_strlen_zero(args.options) &&
209                 ast_app_parse_options64(originate_exec_options, &opts, opt_args, args.options)) {
210                 ast_log(LOG_ERROR, "Invalid options: '%s'\n", args.options);
211                 goto return_cleanup;
212         }
213
214         /* PREDIAL: Run gosub on the caller's channel */
215         if (ast_test_flag64(&opts, OPT_PREDIAL_CALLER)
216                 && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLER])) {
217                 ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLER]);
218                 ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0);
219         }
220
221         if (ast_test_flag64(&opts, OPT_PREDIAL_CALLEE)
222                 && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLEE])) {
223                 ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLEE]);
224                 predial_callee = opt_args[OPT_ARG_PREDIAL_CALLEE];
225         }
226
227         if (strcasecmp(args.type, "exten") && strcasecmp(args.type, "app")) {
228                 ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
229                                 args.type);
230                 goto return_cleanup;
231         }
232
233         if (!strcasecmp(args.type, "exten")) {
234                 int priority = 1; /* Initialized in case priority not specified */
235                 const char *exten = args.arg2;
236
237                 if (args.argc == 5) {
238                         /* Context/Exten/Priority all specified */
239                         if (sscanf(args.arg3, "%30d", &priority) != 1) {
240                                 ast_log(LOG_ERROR, "Invalid priority: '%s'\n", args.arg3);
241                                 goto return_cleanup;
242                         }
243                 } else if (args.argc == 3) {
244                         /* Exten not specified */
245                         exten = default_exten;
246                 }
247
248                 ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
249                                 chantech, chandata, args.arg1, exten, priority);
250
251                 res = ast_pbx_outgoing_exten_predial(chantech, cap_slin, chandata,
252                                 timeout * 1000, args.arg1, exten, priority, &outgoing_status,
253                                 AST_OUTGOING_WAIT, NULL, NULL, NULL, NULL, NULL, 0, NULL,
254                                 predial_callee);
255         } else {
256                 ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
257                                 chantech, chandata, args.arg1, S_OR(args.arg2, ""));
258
259                 res = ast_pbx_outgoing_app_predial(chantech, cap_slin, chandata,
260                                 timeout * 1000, args.arg1, args.arg2, &outgoing_status,
261                                 AST_OUTGOING_WAIT, NULL, NULL, NULL, NULL, NULL, NULL,
262                                 predial_callee);
263         }
264
265         /*
266          * Getting here means that we have passed the various validation checks and
267          * have at least attempted the dial. If we have a reason (outgoing_status),
268          * we clear our error indicator so that we ultimately report the right thing
269          * to the caller.
270          */
271         if (res && outgoing_status) {
272                 res = 0;
273         }
274
275         /* We need to exit cleanly if we've gotten this far */
276         continue_in_dialplan = 1;
277
278 return_cleanup:
279         if (res) {
280                 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
281         } else {
282                 switch (outgoing_status) {
283                 case 0:
284                 case AST_CONTROL_ANSWER:
285                         pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "SUCCESS");
286                         break;
287                 case AST_CONTROL_BUSY:
288                         pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "BUSY");
289                         break;
290                 case AST_CONTROL_CONGESTION:
291                         pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "CONGESTION");
292                         break;
293                 case AST_CONTROL_HANGUP:
294                         pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
295                         break;
296                 case AST_CONTROL_RINGING:
297                         pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "RINGING");
298                         break;
299                 default:
300                         ast_log(LOG_WARNING, "Unknown originate status result of '%d'\n",
301                                         outgoing_status);
302                         pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "UNKNOWN");
303                         break;
304                 }
305         }
306         ao2_cleanup(cap_slin);
307         ast_autoservice_stop(chan);
308
309         return continue_in_dialplan ? 0 : -1;
310 }
311
312 static int unload_module(void)
313 {
314         return ast_unregister_application(app_originate);
315 }
316
317 static int load_module(void)
318 {
319         int res;
320
321         res = ast_register_application_xml(app_originate, originate_exec);
322
323         return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
324 }
325
326 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Originate call");