Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 <since>
50 <version>1.6.1.0</version>
51 </since>
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="a">
78 <para>Originate asynchronously. In other words, continue in the dialplan
79 without waiting for the originated channel to answer.</para>
80 </option>
81 <option name="b" argsep="^">
82 <para>Before originating the outgoing call, Gosub to the specified
83 location using the newly created channel.</para>
84 <argument name="context" required="false" />
85 <argument name="exten" required="false" />
86 <argument name="priority" required="true" hasparams="optional" argsep="^">
87 <argument name="arg1" multiple="true" required="true" />
88 <argument name="argN" />
89 </argument>
90 </option>
91 <option name="B" argsep="^">
92 <para>Before originating the outgoing call, Gosub to the specified
93 location using the current channel.</para>
94 <argument name="context" required="false" />
95 <argument name="exten" required="false" />
96 <argument name="priority" required="true" hasparams="optional" argsep="^">
97 <argument name="arg1" multiple="true" required="true" />
98 <argument name="argN" />
99 </argument>
100 </option>
101 <option name="C">
102 <para>Comma-separated list of codecs to use for this call.
103 Default is <literal>slin</literal>.</para>
104 </option>
105 <option name="c">
106 <para>The caller ID number to use for the called channel. Default is
107 the current channel's Caller ID number.</para>
108 </option>
109 <option name="n">
110 <para>The caller ID name to use for the called channel. Default is
111 the current channel's Caller ID name.</para>
112 </option>
113 <option name="v" argsep="^">
114 <para>A series of channel variables to set on the destination channel.</para>
115 <argument name="var1" multiple="true" argsep="=">
116 <argument name="name" required="true" />
117 <argument name="value" required="true" />
118 </argument>
119 </option>
120 </optionlist>
121 </parameter>
122 </syntax>
123 <description>
124 <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>
125 <para>This application sets the following channel variable before exiting:</para>
126 <variablelist>
127 <variable name="ORIGINATE_STATUS">
128 <para>This indicates the result of the call origination.</para>
129 <value name="FAILED"/>
130 <value name="SUCCESS"/>
131 <value name="BUSY"/>
132 <value name="CONGESTION"/>
133 <value name="HANGUP"/>
134 <value name="RINGING"/>
135 <value name="UNKNOWN">
136 In practice, you should never see this value. Please report it to the issue tracker if you ever see it.
137 </value>
138 </variable>
139 </variablelist>
140 </description>
141 </application>
142 ***/
143
144
145enum {
148 OPT_ASYNC = (1 << 2),
149 OPT_CALLER_NUM = (1 << 3),
150 OPT_CALLER_NAME = (1 << 4),
151 OPT_CODECS = (1 << 5),
152 OPT_VARIABLES = (1 << 6),
153};
154
155enum {
162 /* note: this entry _MUST_ be the last one in the enum */
164};
165
175
176static int originate_exec(struct ast_channel *chan, const char *data)
177{
179 AST_APP_ARG(tech_data);
181 AST_APP_ARG(arg1);
182 AST_APP_ARG(arg2);
183 AST_APP_ARG(arg3);
184 AST_APP_ARG(timeout);
186 );
187 struct ast_flags64 opts = { 0, };
188 char *opt_args[OPT_ARG_ARRAY_SIZE];
189 char *predial_callee = NULL;
190 char *parse, *cnum = NULL, *cname = NULL;
191
192 struct ast_variable *vars = NULL;
193 char *chantech, *chandata;
194 int res = -1;
195 int continue_in_dialplan = 0;
196 int outgoing_status = 0;
197 unsigned int timeout = 30;
198 static const char default_exten[] = "s";
199 struct ast_format_cap *capabilities;
201
203 if (!capabilities) {
204 goto return_cleanup;
205 }
206
207 ast_format_cap_append(capabilities, ast_format_slin, 0);
208
209 if (ast_strlen_zero(data)) {
210 ast_log(LOG_ERROR, "Originate() requires arguments\n");
211 goto return_cleanup;
212 }
213
214 parse = ast_strdupa(data);
215
217
218 if (args.argc < 3) {
219 ast_log(LOG_ERROR, "Incorrect number of arguments\n");
220 goto return_cleanup;
221 }
222
223 if (!ast_strlen_zero(args.timeout)) {
224 if(sscanf(args.timeout, "%u", &timeout) != 1) {
225 ast_log(LOG_NOTICE, "Invalid timeout: '%s'. Setting timeout to 30 seconds\n", args.timeout);
226 timeout = 30;
227 }
228 }
229
230 chandata = ast_strdupa(args.tech_data);
231 chantech = strsep(&chandata, "/");
232
233 if (ast_strlen_zero(chandata) || ast_strlen_zero(chantech)) {
234 ast_log(LOG_ERROR, "Channel Tech/Data invalid: '%s'\n", args.tech_data);
235 goto return_cleanup;
236 }
237
238 if (!ast_strlen_zero(args.options) &&
239 ast_app_parse_options64(originate_exec_options, &opts, opt_args, args.options)) {
240 ast_log(LOG_ERROR, "Invalid options: '%s'\n", args.options);
241 goto return_cleanup;
242 }
243
244 /* PREDIAL: Run gosub on the caller's channel */
248 ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0);
249 }
250
254 predial_callee = opt_args[OPT_ARG_PREDIAL_CALLEE];
255 }
256
257 if (strcasecmp(args.type, "exten") && strcasecmp(args.type, "app")) {
258 ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
259 args.type);
260 goto return_cleanup;
261 }
262
263 if (ast_test_flag64(&opts, OPT_CODECS)) {
264 if (!ast_strlen_zero(opt_args[OPT_ARG_CODECS])) {
267 }
268 }
269
270 if (ast_test_flag64(&opts, OPT_CALLER_NUM)) {
271 if (!ast_strlen_zero(opt_args[OPT_ARG_CALLER_NUM])) {
272 cnum = opt_args[OPT_ARG_CALLER_NUM];
273 } else if (ast_channel_caller(chan)->id.number.str) {
274 cnum = ast_channel_caller(chan)->id.number.str;
275 }
276 }
277
278 if (ast_test_flag64(&opts, OPT_CALLER_NAME)) {
279 if (!ast_strlen_zero(opt_args[OPT_ARG_CALLER_NAME])) {
280 cname = opt_args[OPT_ARG_CALLER_NAME];
281 } else if (ast_channel_caller(chan)->id.name.str) {
282 cname = ast_channel_caller(chan)->id.name.str;
283 }
284 }
285
286 /* Assign variables */
288 && !ast_strlen_zero(opt_args[OPT_ARG_VARIABLES])) {
289 char *vartext;
290 char *text = opt_args[OPT_ARG_VARIABLES];
291 while ((vartext = ast_strsep(&text, '^', 0))) {
292 struct ast_variable *var;
293 char *varname, *varvalue;
294 if (!(varname = ast_strsep(&vartext, '=', 0))) {
295 ast_log(LOG_ERROR, "Variable syntax error: %s\n", vartext);
296 goto return_cleanup;
297 }
298 if (!(varvalue = ast_strsep(&vartext, '=', 0))) {
299 varvalue = ""; /* empty values are allowed */
300 }
301 var = ast_variable_new(varname, varvalue, "");
302 if (!var) {
303 ast_log(LOG_ERROR, "Failed to allocate variable: %s\n", varname);
304 goto return_cleanup;
305 }
306 ast_debug(1, "Appending variable '%s' with value '%s'", varname, varvalue);
308 }
309 }
310
311 if (!strcasecmp(args.type, "exten")) {
312 const char *cid_num = cnum;
313 const char *cid_name = cname;
314 int priority = 1; /* Initialized in case priority not specified */
315 const char *exten = args.arg2;
316
317 if (args.argc == 5) {
318 /* Context/Exten/Priority all specified */
319 if (sscanf(args.arg3, "%30d", &priority) != 1) {
320 ast_log(LOG_ERROR, "Invalid priority: '%s'\n", args.arg3);
321 goto return_cleanup;
322 }
323 } else if (args.argc == 3) {
324 /* Exten not specified */
325 exten = default_exten;
326 }
327
328 ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
329 chantech, chandata, args.arg1, exten, priority);
330
331 res = ast_pbx_outgoing_exten_predial(chantech, capabilities, chandata,
332 timeout * 1000, args.arg1, exten, priority, &outgoing_status,
334 cid_num, cid_name, vars, NULL, NULL, 0, NULL,
335 predial_callee);
336 } else {
337 const char *cid_num = cnum;
338 const char *cid_name = cname;
339 ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
340 chantech, chandata, args.arg1, S_OR(args.arg2, ""));
341
342 res = ast_pbx_outgoing_app_predial(chantech, capabilities, chandata,
343 timeout * 1000, args.arg1, args.arg2, &outgoing_status,
345 cid_num, cid_name, vars, NULL, NULL, NULL,
346 predial_callee);
347 }
348
349 /*
350 * Getting here means that we have passed the various validation checks and
351 * have at least attempted the dial. If we have a reason (outgoing_status),
352 * we clear our error indicator so that we ultimately report the right thing
353 * to the caller.
354 */
355 if (res && outgoing_status) {
356 res = 0;
357 }
358
359 /* We need to exit cleanly if we've gotten this far */
360 continue_in_dialplan = 1;
361
362return_cleanup:
363 if (res) {
364 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
365 } else {
366 switch (outgoing_status) {
367 case 0:
369 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "SUCCESS");
370 break;
371 case AST_CONTROL_BUSY:
372 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "BUSY");
373 break;
375 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "CONGESTION");
376 break;
378 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
379 break;
381 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "RINGING");
382 break;
383 default:
384 ast_log(LOG_WARNING, "Unknown originate status result of '%d'\n",
385 outgoing_status);
386 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "UNKNOWN");
387 break;
388 }
389 }
390 if (vars) {
392 }
393 ao2_cleanup(capabilities);
395
396 return continue_in_dialplan ? 0 : -1;
397}
398
399static int unload_module(void)
400{
402}
403
404static int load_module(void)
405{
406 int res;
407
409
411}
412
@ 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:1809
#define var
Definition: ast_expr2f.c:605
char * strsep(char **str, const char *delims)
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
#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:7941
@ AST_OUTGOING_NO_WAIT
Definition: pbx.h:1141
@ AST_OUTGOING_WAIT
Definition: pbx.h:1142
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:8005
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:157
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