Asterisk - The Open Source Telephony Project GIT-master-0bf3178
app_originate.c
Go to the documentation of this file.
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 */
31
32/*** MODULEINFO
33 <support_level>core</support_level>
34 ***/
35
36#include "asterisk.h"
37
38#include "asterisk/file.h"
39#include "asterisk/channel.h"
40#include "asterisk/pbx.h"
41#include "asterisk/module.h"
42#include "asterisk/app.h"
44
45static const char app_originate[] = "Originate";
46
47/*** DOCUMENTATION
48 <application name="Originate" language="en_US">
49 <synopsis>
50 Originate a call.
51 </synopsis>
52 <syntax>
53 <parameter name="tech_data" required="true">
54 <para>Channel technology and data for creating the outbound channel.
55 For example, SIP/1234.</para>
56 </parameter>
57 <parameter name="type" required="true">
58 <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>
59 </parameter>
60 <parameter name="arg1" required="true">
61 <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>
62 </parameter>
63 <parameter name="arg2" required="false">
64 <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>
65 </parameter>
66 <parameter name="arg3" required="false">
67 <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>
68 </parameter>
69 <parameter name="timeout" required="false">
70 <para>Timeout in seconds. Default is 30 seconds.</para>
71 </parameter>
72 <parameter name="options" required="false">
73 <optionlist>
74 <option name="a">
75 <para>Originate asynchronously. In other words, continue in the dialplan
76 without waiting for the originated channel to answer.</para>
77 </option>
78 <option name="b" argsep="^">
79 <para>Before originating the outgoing call, Gosub to the specified
80 location using the newly created channel.</para>
81 <argument name="context" required="false" />
82 <argument name="exten" required="false" />
83 <argument name="priority" required="true" hasparams="optional" argsep="^">
84 <argument name="arg1" multiple="true" required="true" />
85 <argument name="argN" />
86 </argument>
87 </option>
88 <option name="B" argsep="^">
89 <para>Before originating the outgoing call, Gosub to the specified
90 location using the current channel.</para>
91 <argument name="context" required="false" />
92 <argument name="exten" required="false" />
93 <argument name="priority" required="true" hasparams="optional" argsep="^">
94 <argument name="arg1" multiple="true" required="true" />
95 <argument name="argN" />
96 </argument>
97 </option>
98 <option name="C">
99 <para>Comma-separated list of codecs to use for this call.
100 Default is <literal>slin</literal>.</para>
101 </option>
102 <option name="c">
103 <para>The caller ID number to use for the called channel. Default is
104 the current channel's Caller ID number.</para>
105 </option>
106 <option name="n">
107 <para>The caller ID name to use for the called channel. Default is
108 the current channel's Caller ID name.</para>
109 </option>
110 <option name="v" argsep="^">
111 <para>A series of channel variables to set on the destination channel.</para>
112 <argument name="var1" multiple="true" argsep="=">
113 <argument name="name" required="true" />
114 <argument name="value" required="true" />
115 </argument>
116 </option>
117 </optionlist>
118 </parameter>
119 </syntax>
120 <description>
121 <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, unless the async option is used. At that point, this application will exit with the status variable set and dialplan processing will continue.</para>
122 <para>This application sets the following channel variable before exiting:</para>
123 <variablelist>
124 <variable name="ORIGINATE_STATUS">
125 <para>This indicates the result of the call origination.</para>
126 <value name="FAILED"/>
127 <value name="SUCCESS"/>
128 <value name="BUSY"/>
129 <value name="CONGESTION"/>
130 <value name="HANGUP"/>
131 <value name="RINGING"/>
132 <value name="UNKNOWN">
133 In practice, you should never see this value. Please report it to the issue tracker if you ever see it.
134 </value>
135 </variable>
136 </variablelist>
137 </description>
138 </application>
139 ***/
140
141
142enum {
145 OPT_ASYNC = (1 << 2),
146 OPT_CALLER_NUM = (1 << 3),
147 OPT_CALLER_NAME = (1 << 4),
148 OPT_CODECS = (1 << 5),
149 OPT_VARIABLES = (1 << 6),
150};
151
152enum {
159 /* note: this entry _MUST_ be the last one in the enum */
161};
162
172
173static int originate_exec(struct ast_channel *chan, const char *data)
174{
176 AST_APP_ARG(tech_data);
178 AST_APP_ARG(arg1);
179 AST_APP_ARG(arg2);
180 AST_APP_ARG(arg3);
181 AST_APP_ARG(timeout);
183 );
184 struct ast_flags64 opts = { 0, };
185 char *opt_args[OPT_ARG_ARRAY_SIZE];
186 char *predial_callee = NULL;
187 char *parse, *cnum = NULL, *cname = NULL;
188
189 struct ast_variable *vars = NULL;
190 char *chantech, *chandata;
191 int res = -1;
192 int continue_in_dialplan = 0;
193 int outgoing_status = 0;
194 unsigned int timeout = 30;
195 static const char default_exten[] = "s";
196 struct ast_format_cap *capabilities;
198
200 if (!capabilities) {
201 goto return_cleanup;
202 }
203
204 ast_format_cap_append(capabilities, ast_format_slin, 0);
205
206 if (ast_strlen_zero(data)) {
207 ast_log(LOG_ERROR, "Originate() requires arguments\n");
208 goto return_cleanup;
209 }
210
211 parse = ast_strdupa(data);
212
214
215 if (args.argc < 3) {
216 ast_log(LOG_ERROR, "Incorrect number of arguments\n");
217 goto return_cleanup;
218 }
219
220 if (!ast_strlen_zero(args.timeout)) {
221 if(sscanf(args.timeout, "%u", &timeout) != 1) {
222 ast_log(LOG_NOTICE, "Invalid timeout: '%s'. Setting timeout to 30 seconds\n", args.timeout);
223 timeout = 30;
224 }
225 }
226
227 chandata = ast_strdupa(args.tech_data);
228 chantech = strsep(&chandata, "/");
229
230 if (ast_strlen_zero(chandata) || ast_strlen_zero(chantech)) {
231 ast_log(LOG_ERROR, "Channel Tech/Data invalid: '%s'\n", args.tech_data);
232 goto return_cleanup;
233 }
234
235 if (!ast_strlen_zero(args.options) &&
236 ast_app_parse_options64(originate_exec_options, &opts, opt_args, args.options)) {
237 ast_log(LOG_ERROR, "Invalid options: '%s'\n", args.options);
238 goto return_cleanup;
239 }
240
241 /* PREDIAL: Run gosub on the caller's channel */
245 ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0);
246 }
247
251 predial_callee = opt_args[OPT_ARG_PREDIAL_CALLEE];
252 }
253
254 if (strcasecmp(args.type, "exten") && strcasecmp(args.type, "app")) {
255 ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
256 args.type);
257 goto return_cleanup;
258 }
259
260 if (ast_test_flag64(&opts, OPT_CODECS)) {
261 if (!ast_strlen_zero(opt_args[OPT_ARG_CODECS])) {
264 }
265 }
266
267 if (ast_test_flag64(&opts, OPT_CALLER_NUM)) {
268 if (!ast_strlen_zero(opt_args[OPT_ARG_CALLER_NUM])) {
269 cnum = opt_args[OPT_ARG_CALLER_NUM];
270 } else if (ast_channel_caller(chan)->id.number.str) {
271 cnum = ast_channel_caller(chan)->id.number.str;
272 }
273 }
274
275 if (ast_test_flag64(&opts, OPT_CALLER_NAME)) {
276 if (!ast_strlen_zero(opt_args[OPT_ARG_CALLER_NAME])) {
277 cname = opt_args[OPT_ARG_CALLER_NAME];
278 } else if (ast_channel_caller(chan)->id.name.str) {
279 cname = ast_channel_caller(chan)->id.name.str;
280 }
281 }
282
283 /* Assign variables */
285 && !ast_strlen_zero(opt_args[OPT_ARG_VARIABLES])) {
286 char *vartext;
287 char *text = opt_args[OPT_ARG_VARIABLES];
288 while ((vartext = ast_strsep(&text, '^', 0))) {
289 struct ast_variable *var;
290 char *varname, *varvalue;
291 if (!(varname = ast_strsep(&vartext, '=', 0))) {
292 ast_log(LOG_ERROR, "Variable syntax error: %s\n", vartext);
293 goto return_cleanup;
294 }
295 if (!(varvalue = ast_strsep(&vartext, '=', 0))) {
296 varvalue = ""; /* empty values are allowed */
297 }
298 var = ast_variable_new(varname, varvalue, "");
299 if (!var) {
300 ast_log(LOG_ERROR, "Failed to allocate variable: %s\n", varname);
301 goto return_cleanup;
302 }
303 ast_debug(1, "Appending variable '%s' with value '%s'", varname, varvalue);
305 }
306 }
307
308 if (!strcasecmp(args.type, "exten")) {
309 const char *cid_num = cnum;
310 const char *cid_name = cname;
311 int priority = 1; /* Initialized in case priority not specified */
312 const char *exten = args.arg2;
313
314 if (args.argc == 5) {
315 /* Context/Exten/Priority all specified */
316 if (sscanf(args.arg3, "%30d", &priority) != 1) {
317 ast_log(LOG_ERROR, "Invalid priority: '%s'\n", args.arg3);
318 goto return_cleanup;
319 }
320 } else if (args.argc == 3) {
321 /* Exten not specified */
322 exten = default_exten;
323 }
324
325 ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
326 chantech, chandata, args.arg1, exten, priority);
327
328 res = ast_pbx_outgoing_exten_predial(chantech, capabilities, chandata,
329 timeout * 1000, args.arg1, exten, priority, &outgoing_status,
331 cid_num, cid_name, vars, NULL, NULL, 0, NULL,
332 predial_callee);
333 } else {
334 const char *cid_num = cnum;
335 const char *cid_name = cname;
336 ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
337 chantech, chandata, args.arg1, S_OR(args.arg2, ""));
338
339 res = ast_pbx_outgoing_app_predial(chantech, capabilities, chandata,
340 timeout * 1000, args.arg1, args.arg2, &outgoing_status,
342 cid_num, cid_name, vars, NULL, NULL, NULL,
343 predial_callee);
344 }
345
346 /*
347 * Getting here means that we have passed the various validation checks and
348 * have at least attempted the dial. If we have a reason (outgoing_status),
349 * we clear our error indicator so that we ultimately report the right thing
350 * to the caller.
351 */
352 if (res && outgoing_status) {
353 res = 0;
354 }
355
356 /* We need to exit cleanly if we've gotten this far */
357 continue_in_dialplan = 1;
358
359return_cleanup:
360 if (res) {
361 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
362 } else {
363 switch (outgoing_status) {
364 case 0:
366 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "SUCCESS");
367 break;
368 case AST_CONTROL_BUSY:
369 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "BUSY");
370 break;
372 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "CONGESTION");
373 break;
375 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
376 break;
378 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "RINGING");
379 break;
380 default:
381 ast_log(LOG_WARNING, "Unknown originate status result of '%d'\n",
382 outgoing_status);
383 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "UNKNOWN");
384 break;
385 }
386 }
387 if (vars) {
389 }
390 ao2_cleanup(capabilities);
392
393 return continue_in_dialplan ? 0 : -1;
394}
395
396static int unload_module(void)
397{
399}
400
401static int load_module(void)
402{
403 int res;
404
406
408}
409
@ OPT_ARG_VARIABLES
@ OPT_ARG_CALLER_NAME
@ OPT_ARG_PREDIAL_CALLEE
@ OPT_ARG_CODECS
@ OPT_ARG_CALLER_NUM
@ OPT_ARG_PREDIAL_CALLER
@ OPT_ARG_ARRAY_SIZE
static const char app_originate[]
Definition: app_originate.c:45
static int originate_exec(struct ast_channel *chan, const char *data)
static const struct ast_app_option originate_exec_options[128]
@ OPT_VARIABLES
@ OPT_CODECS
@ OPT_PREDIAL_CALLER
@ OPT_ASYNC
@ OPT_CALLER_NUM
@ OPT_CALLER_NAME
@ OPT_PREDIAL_CALLEE
static int load_module(void)
static int unload_module(void)
char * text
Definition: app_queue.c:1668
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static int priority
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
Generic File Format Support. Should be included by clients of the file handling routines....
Media Format Cache API.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
Parse an "allow" or "deny" list and modify a format capabilities structure accordingly.
Definition: format_cap.c:320
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:523
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static const char name[]
Definition: format_mp3.c:68
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define END_OPTIONS
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define BEGIN_OPTIONS
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
Run a subroutine on a channel, placing an optional second channel into autoservice.
Definition: main/app.c:297
int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3071
char * strsep(char **str, const char *delims)
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
@ AST_CONTROL_BUSY
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
Core PBX routines and definitions.
int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition: pbx.c:7926
@ AST_OUTGOING_NO_WAIT
Definition: pbx.h:1140
@ AST_OUTGOING_WAIT
Definition: pbx.h:1141
int ast_pbx_outgoing_app_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition: pbx.c:7990
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
Main Channel structure associated with a channel.
Structure used to handle a large number of boolean flags == used only in app_dial?
Definition: utils.h:204
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_party_id id
Caller party ID.
Definition: channel.h:422
struct ast_party_name name
Subscriber name.
Definition: channel.h:342
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
char * str
Subscriber name (Malloced)
Definition: channel.h:266
char * str
Subscriber phone number (Malloced)
Definition: channel.h:293
Structure for variables, used for configurations and for channel variables.
Number structure.
Definition: app_followme.c:154
const char * args
static struct test_options options
#define ast_test_flag64(p, flag)
Definition: utils.h:120
void ast_replace_subargument_delimiter(char *s)
Replace '^' in a string with ','.
Definition: utils.c:2343