Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
8  * Russell Bryant <[email protected]>
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 <[email protected]>
26  * \author Russell Bryant <[email protected]>
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"
43 #include "asterisk/format_cache.h"
44 
45 static 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 
142 enum {
143  OPT_PREDIAL_CALLEE = (1 << 0),
144  OPT_PREDIAL_CALLER = (1 << 1),
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 
152 enum {
159  /* note: this entry _MUST_ be the last one in the enum */
161 };
162 
172 
173 static int originate_exec(struct ast_channel *chan, const char *data)
174 {
176  AST_APP_ARG(tech_data);
177  AST_APP_ARG(type);
178  AST_APP_ARG(arg1);
179  AST_APP_ARG(arg2);
180  AST_APP_ARG(arg3);
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 
199  ast_autoservice_start(chan);
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 
213  AST_STANDARD_APP_ARGS(args, parse);
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 */
243  && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLER])) {
244  ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLER]);
245  ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0);
246  }
247 
249  && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLEE])) {
250  ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLEE]);
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])) {
263  ast_format_cap_update_by_allow_disallow(capabilities, opt_args[OPT_ARG_CODECS], 1);
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 */
284  if (ast_test_flag64(&opts, OPT_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);
304  ast_variable_list_append(&vars, var);
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 
359 return_cleanup:
360  if (res) {
361  pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
362  } else {
363  switch (outgoing_status) {
364  case 0:
365  case AST_CONTROL_ANSWER:
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;
374  case AST_CONTROL_HANGUP:
375  pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
376  break;
377  case AST_CONTROL_RINGING:
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) {
388  ast_variables_destroy(vars);
389  }
390  ao2_cleanup(capabilities);
391  ast_autoservice_stop(chan);
392 
393  return continue_in_dialplan ? 0 : -1;
394 }
395 
396 static int unload_module(void)
397 {
399 }
400 
401 static int load_module(void)
402 {
403  int res;
404 
406 
408 }
409 
static int load_module(void)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static const char type[]
Definition: chan_ooh323.c:109
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
#define BEGIN_OPTIONS
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
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:7961
char * str
Subscriber name (Malloced)
Definition: channel.h:265
char * text
Definition: app_queue.c:1508
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const char * args
static int originate_exec(struct ast_channel *chan, const char *data)
#define NULL
Definition: resample.c:96
Structure used to handle a large number of boolean flags == used only in app_dial?
Definition: utils.h:204
static int priority
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static const char app_originate[]
Definition: app_originate.c:45
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:164
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
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
Number structure.
Definition: app_followme.c:154
struct ast_party_id id
Caller party ID.
Definition: channel.h:421
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
void ast_replace_subargument_delimiter(char *s)
Replace &#39;^&#39; in a string with &#39;,&#39;.
Definition: main/utils.c:2095
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: main/utils.c:1656
#define ast_variable_new(name, value, filename)
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Core PBX routines and definitions.
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:2911
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
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:525
#define LOG_ERROR
Definition: logger.h:285
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
static const struct ast_app_option originate_exec_options[128]
#define LOG_NOTICE
Definition: logger.h:263
static int unload_module(void)
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static const char name[]
Definition: cdr_mysql.c:74
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
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...
char * strsep(char **str, const char *delims)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
#define END_OPTIONS
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:370
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:8025
union ast_frame::@263 data
static struct test_options options
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define ast_variable_list_append(head, new_var)
Media Format Cache API.
#define AST_APP_ARG(name)
Define an application argument.
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343
#define ast_test_flag64(p, flag)
Definition: utils.h:120