2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2008, Roberto Casas.
5 * Copyright (C) 2008, Digium, Inc.
7 * Roberto Casas <roberto.casas@diaple.com>
8 * Russell Bryant <russell@digium.com>
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.
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.
23 * \brief Originate application
25 * \author Roberto Casas <roberto.casas@diaple.com>
26 * \author Russell Bryant <russell@digium.com>
28 * \ingroup applications
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.
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39 #include "asterisk/file.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/module.h"
43 #include "asterisk/app.h"
45 static const char app_originate[] = "Originate";
48 <application name="Originate" language="en_US">
53 <parameter name="tech_data" required="true">
54 <para>Channel technology and data for creating the outbound channel.
55 For example, SIP/1234.</para>
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>
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>
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>
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>
71 <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>
73 <para>This application sets the following channel variable before exiting:</para>
75 <variable name="ORIGINATE_STATUS">
76 <para>This indicates the result of the call origination.</para>
77 <value name="FAILED"/>
78 <value name="SUCCESS"/>
80 <value name="CONGESTION"/>
81 <value name="HANGUP"/>
82 <value name="RINGING"/>
83 <value name="UNKNOWN">
84 In practice, you should never see this value. Please report it to the issue tracker if you ever see it.
92 static int originate_exec(struct ast_channel *chan, void *data)
94 AST_DECLARE_APP_ARGS(args,
95 AST_APP_ARG(tech_data);
102 char *chantech, *chandata;
104 int outgoing_res = 0;
105 int outgoing_status = 0;
106 static const unsigned int timeout = 30;
107 static const char default_exten[] = "s";
109 ast_autoservice_start(chan);
111 if (ast_strlen_zero(data)) {
112 ast_log(LOG_ERROR, "Originate() requires arguments\n");
116 parse = ast_strdupa(data);
118 AST_STANDARD_APP_ARGS(args, parse);
121 ast_log(LOG_ERROR, "Incorrect number of arguments\n");
125 chandata = ast_strdupa(args.tech_data);
126 chantech = strsep(&chandata, "/");
128 if (ast_strlen_zero(chandata) || ast_strlen_zero(chantech)) {
129 ast_log(LOG_ERROR, "Channel Tech/Data invalid: '%s'\n", args.tech_data);
133 if (!strcasecmp(args.type, "exten")) {
134 int priority = 1; /* Initialized in case priority not specified */
135 const char *exten = args.arg2;
137 if (args.argc == 5) {
138 /* Context/Exten/Priority all specified */
139 if (sscanf(args.arg3, "%d", &priority) != 1) {
140 ast_log(LOG_ERROR, "Invalid priority: '%s'\n", args.arg3);
143 } else if (args.argc == 3) {
144 /* Exten not specified */
145 exten = default_exten;
148 ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
149 chantech, chandata, args.arg1, exten, priority);
151 outgoing_res = ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata,
152 timeout * 1000, args.arg1, exten, priority, &outgoing_status, 0, NULL,
153 NULL, NULL, NULL, NULL);
154 } else if (!strcasecmp(args.type, "app")) {
155 ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
156 chantech, chandata, args.arg1, S_OR(args.arg2, ""));
158 outgoing_res = ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata,
159 timeout * 1000, args.arg1, args.arg2, &outgoing_status, 0, NULL,
160 NULL, NULL, NULL, NULL);
162 ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
171 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
173 switch (outgoing_status) {
175 case AST_CONTROL_ANSWER:
176 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "SUCCESS");
178 case AST_CONTROL_BUSY:
179 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "BUSY");
181 case AST_CONTROL_CONGESTION:
182 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "CONGESTION");
184 case AST_CONTROL_HANGUP:
185 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
187 case AST_CONTROL_RINGING:
188 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "RINGING");
191 ast_log(LOG_WARNING, "Unknown originate status result of '%d'\n",
193 pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "UNKNOWN");
198 ast_autoservice_stop(chan);
203 static int unload_module(void)
205 return ast_unregister_application(app_originate);
208 static int load_module(void)
212 res = ast_register_application_xml(app_originate, originate_exec);
214 return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
217 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Originate call");