Sat Apr 26 2014 22:01:27

Asterisk developer's documentation


app_originate.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2008, Roberto Casas.
00005  * Copyright (C) 2008, Digium, Inc.
00006  *
00007  * Roberto Casas <roberto.casas@diaple.com>
00008  * Russell Bryant <russell@digium.com>
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*!
00022  * \file
00023  * \brief Originate application
00024  *
00025  * \author Roberto Casas <roberto.casas@diaple.com>
00026  * \author Russell Bryant <russell@digium.com>
00027  *
00028  * \ingroup applications
00029  *
00030  * \todo Make a way to be able to set variables (and functions) on the outbound
00031  *       channel, similar to the Variable headers for the AMI Originate, and the
00032  *       Set options for call files.
00033  */
00034 
00035 /*** MODULEINFO
00036    <support_level>core</support_level>
00037  ***/
00038 
00039 #include "asterisk.h"
00040 
00041 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 370951 $")
00042 
00043 #include "asterisk/file.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/pbx.h"
00046 #include "asterisk/module.h"
00047 #include "asterisk/app.h"
00048 
00049 static const char app_originate[] = "Originate";
00050 
00051 /*** DOCUMENTATION
00052    <application name="Originate" language="en_US">
00053       <synopsis>
00054          Originate a call.
00055       </synopsis>
00056       <syntax>
00057          <parameter name="tech_data" required="true">
00058             <para>Channel technology and data for creating the outbound channel.
00059                       For example, SIP/1234.</para>
00060          </parameter>
00061          <parameter name="type" required="true">
00062             <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>
00063          </parameter>
00064          <parameter name="arg1" required="true">
00065             <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>
00066          </parameter>
00067          <parameter name="arg2" required="false">
00068             <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>
00069          </parameter>
00070          <parameter name="arg3" required="false">
00071             <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>
00072          </parameter>
00073          <parameter name="timeout" required="false">
00074             <para>Timeout in seconds. Default is 30 seconds.</para>
00075          </parameter>
00076       </syntax>
00077       <description>
00078       <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>
00079 
00080       <para>This application sets the following channel variable before exiting:</para>
00081       <variablelist>
00082          <variable name="ORIGINATE_STATUS">
00083             <para>This indicates the result of the call origination.</para>
00084             <value name="FAILED"/>
00085             <value name="SUCCESS"/>
00086             <value name="BUSY"/>
00087             <value name="CONGESTION"/>
00088             <value name="HANGUP"/>
00089             <value name="RINGING"/>
00090             <value name="UNKNOWN">
00091             In practice, you should never see this value.  Please report it to the issue tracker if you ever see it.
00092             </value>
00093          </variable>
00094       </variablelist>
00095       </description>
00096    </application>
00097  ***/
00098 
00099 static int originate_exec(struct ast_channel *chan, const char *data)
00100 {
00101    AST_DECLARE_APP_ARGS(args,
00102       AST_APP_ARG(tech_data);
00103       AST_APP_ARG(type);
00104       AST_APP_ARG(arg1);
00105       AST_APP_ARG(arg2);
00106       AST_APP_ARG(arg3);
00107       AST_APP_ARG(timeout);
00108    );
00109    char *parse;
00110    char *chantech, *chandata;
00111    int res = -1;
00112    int outgoing_status = 0;
00113    unsigned int timeout = 30;
00114    static const char default_exten[] = "s";
00115    struct ast_format tmpfmt;
00116    struct ast_format_cap *cap_slin = ast_format_cap_alloc_nolock();
00117 
00118    ast_autoservice_start(chan);
00119    if (!cap_slin) {
00120       goto return_cleanup;
00121    }
00122    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
00123    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR12, 0));
00124    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0));
00125    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR24, 0));
00126    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR32, 0));
00127    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR44, 0));
00128    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR48, 0));
00129    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR96, 0));
00130    ast_format_cap_add(cap_slin, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR192, 0));
00131 
00132    if (ast_strlen_zero(data)) {
00133       ast_log(LOG_ERROR, "Originate() requires arguments\n");
00134       goto return_cleanup;
00135    }
00136 
00137    parse = ast_strdupa(data);
00138 
00139    AST_STANDARD_APP_ARGS(args, parse);
00140 
00141    if (args.argc < 3) {
00142       ast_log(LOG_ERROR, "Incorrect number of arguments\n");
00143       goto return_cleanup;
00144    }
00145 
00146    if (!ast_strlen_zero(args.timeout)) {
00147       if(sscanf(args.timeout, "%u", &timeout) != 1) {
00148          ast_log(LOG_NOTICE, "Invalid timeout: '%s'. Setting timeout to 30 seconds\n", args.timeout);
00149          timeout = 30;
00150       }
00151    }
00152 
00153    chandata = ast_strdupa(args.tech_data);
00154    chantech = strsep(&chandata, "/");
00155 
00156    if (ast_strlen_zero(chandata) || ast_strlen_zero(chantech)) {
00157       ast_log(LOG_ERROR, "Channel Tech/Data invalid: '%s'\n", args.tech_data);
00158       goto return_cleanup;
00159    }
00160 
00161    if (!strcasecmp(args.type, "exten")) {
00162       int priority = 1; /* Initialized in case priority not specified */
00163       const char *exten = args.arg2;
00164 
00165       if (args.argc == 5) {
00166          /* Context/Exten/Priority all specified */
00167          if (sscanf(args.arg3, "%30d", &priority) != 1) {
00168             ast_log(LOG_ERROR, "Invalid priority: '%s'\n", args.arg3);
00169             goto return_cleanup;
00170          }
00171       } else if (args.argc == 3) {
00172          /* Exten not specified */
00173          exten = default_exten;
00174       }
00175 
00176       ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
00177             chantech, chandata, args.arg1, exten, priority);
00178 
00179       ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
00180             timeout * 1000, args.arg1, exten, priority, &outgoing_status, 0, NULL,
00181             NULL, NULL, NULL, NULL, 0);
00182    } else if (!strcasecmp(args.type, "app")) {
00183       ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
00184             chantech, chandata, args.arg1, S_OR(args.arg2, ""));
00185 
00186       ast_pbx_outgoing_app(chantech, cap_slin, chandata,
00187             timeout * 1000, args.arg1, args.arg2, &outgoing_status, 0, NULL,
00188             NULL, NULL, NULL, NULL);
00189    } else {
00190       ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
00191             args.type);
00192       goto return_cleanup;
00193    }
00194 
00195    res = 0;
00196 
00197 return_cleanup:
00198    if (res) {
00199       pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
00200    } else {
00201       switch (outgoing_status) {
00202       case 0:
00203       case AST_CONTROL_ANSWER:
00204          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "SUCCESS");
00205          break;
00206       case AST_CONTROL_BUSY:
00207          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "BUSY");
00208          break;
00209       case AST_CONTROL_CONGESTION:
00210          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "CONGESTION");
00211          break;
00212       case AST_CONTROL_HANGUP:
00213          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
00214          break;
00215       case AST_CONTROL_RINGING:
00216          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "RINGING");
00217          break;
00218       default:
00219          ast_log(LOG_WARNING, "Unknown originate status result of '%d'\n",
00220                outgoing_status);
00221          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "UNKNOWN");
00222          break;
00223       }
00224    }
00225    cap_slin = ast_format_cap_destroy(cap_slin);
00226    ast_autoservice_stop(chan);
00227 
00228    return res;
00229 }
00230 
00231 static int unload_module(void)
00232 {
00233    return ast_unregister_application(app_originate);
00234 }
00235 
00236 static int load_module(void)
00237 {
00238    int res;
00239 
00240    res = ast_register_application_xml(app_originate, originate_exec);
00241 
00242    return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
00243 }
00244 
00245 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Originate call");