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: 419044 $")
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 #include "asterisk/format_cache.h"
00049 
00050 static const char app_originate[] = "Originate";
00051 
00052 /*** DOCUMENTATION
00053    <application name="Originate" language="en_US">
00054       <synopsis>
00055          Originate a call.
00056       </synopsis>
00057       <syntax>
00058          <parameter name="tech_data" required="true">
00059             <para>Channel technology and data for creating the outbound channel.
00060                       For example, SIP/1234.</para>
00061          </parameter>
00062          <parameter name="type" required="true">
00063             <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>
00064          </parameter>
00065          <parameter name="arg1" required="true">
00066             <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>
00067          </parameter>
00068          <parameter name="arg2" required="false">
00069             <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>
00070          </parameter>
00071          <parameter name="arg3" required="false">
00072             <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>
00073          </parameter>
00074          <parameter name="timeout" required="false">
00075             <para>Timeout in seconds. Default is 30 seconds.</para>
00076          </parameter>
00077       </syntax>
00078       <description>
00079       <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>
00080 
00081       <para>This application sets the following channel variable before exiting:</para>
00082       <variablelist>
00083          <variable name="ORIGINATE_STATUS">
00084             <para>This indicates the result of the call origination.</para>
00085             <value name="FAILED"/>
00086             <value name="SUCCESS"/>
00087             <value name="BUSY"/>
00088             <value name="CONGESTION"/>
00089             <value name="HANGUP"/>
00090             <value name="RINGING"/>
00091             <value name="UNKNOWN">
00092             In practice, you should never see this value.  Please report it to the issue tracker if you ever see it.
00093             </value>
00094          </variable>
00095       </variablelist>
00096       </description>
00097    </application>
00098  ***/
00099 
00100 static int originate_exec(struct ast_channel *chan, const char *data)
00101 {
00102    AST_DECLARE_APP_ARGS(args,
00103       AST_APP_ARG(tech_data);
00104       AST_APP_ARG(type);
00105       AST_APP_ARG(arg1);
00106       AST_APP_ARG(arg2);
00107       AST_APP_ARG(arg3);
00108       AST_APP_ARG(timeout);
00109    );
00110    char *parse;
00111    char *chantech, *chandata;
00112    int res = -1;
00113    int outgoing_status = 0;
00114    unsigned int timeout = 30;
00115    static const char default_exten[] = "s";
00116    struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
00117 
00118    ast_autoservice_start(chan);
00119    if (!cap_slin) {
00120       goto return_cleanup;
00121    }
00122 
00123    ast_format_cap_append(cap_slin, ast_format_slin, 0);
00124    ast_format_cap_append(cap_slin, ast_format_slin12, 0);
00125    ast_format_cap_append(cap_slin, ast_format_slin16, 0);
00126    ast_format_cap_append(cap_slin, ast_format_slin24, 0);
00127    ast_format_cap_append(cap_slin, ast_format_slin32, 0);
00128    ast_format_cap_append(cap_slin, ast_format_slin44, 0);
00129    ast_format_cap_append(cap_slin, ast_format_slin48, 0);
00130    ast_format_cap_append(cap_slin, ast_format_slin96, 0);
00131    ast_format_cap_append(cap_slin, ast_format_slin192, 0);
00132 
00133    if (ast_strlen_zero(data)) {
00134       ast_log(LOG_ERROR, "Originate() requires arguments\n");
00135       goto return_cleanup;
00136    }
00137 
00138    parse = ast_strdupa(data);
00139 
00140    AST_STANDARD_APP_ARGS(args, parse);
00141 
00142    if (args.argc < 3) {
00143       ast_log(LOG_ERROR, "Incorrect number of arguments\n");
00144       goto return_cleanup;
00145    }
00146 
00147    if (!ast_strlen_zero(args.timeout)) {
00148       if(sscanf(args.timeout, "%u", &timeout) != 1) {
00149          ast_log(LOG_NOTICE, "Invalid timeout: '%s'. Setting timeout to 30 seconds\n", args.timeout);
00150          timeout = 30;
00151       }
00152    }
00153 
00154    chandata = ast_strdupa(args.tech_data);
00155    chantech = strsep(&chandata, "/");
00156 
00157    if (ast_strlen_zero(chandata) || ast_strlen_zero(chantech)) {
00158       ast_log(LOG_ERROR, "Channel Tech/Data invalid: '%s'\n", args.tech_data);
00159       goto return_cleanup;
00160    }
00161 
00162    if (!strcasecmp(args.type, "exten")) {
00163       int priority = 1; /* Initialized in case priority not specified */
00164       const char *exten = args.arg2;
00165 
00166       if (args.argc == 5) {
00167          /* Context/Exten/Priority all specified */
00168          if (sscanf(args.arg3, "%30d", &priority) != 1) {
00169             ast_log(LOG_ERROR, "Invalid priority: '%s'\n", args.arg3);
00170             goto return_cleanup;
00171          }
00172       } else if (args.argc == 3) {
00173          /* Exten not specified */
00174          exten = default_exten;
00175       }
00176 
00177       ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
00178             chantech, chandata, args.arg1, exten, priority);
00179 
00180       ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
00181             timeout * 1000, args.arg1, exten, priority, &outgoing_status, 1, NULL,
00182             NULL, NULL, NULL, NULL, 0, NULL);
00183    } else if (!strcasecmp(args.type, "app")) {
00184       ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
00185             chantech, chandata, args.arg1, S_OR(args.arg2, ""));
00186 
00187       ast_pbx_outgoing_app(chantech, cap_slin, chandata,
00188             timeout * 1000, args.arg1, args.arg2, &outgoing_status, 1, NULL,
00189             NULL, NULL, NULL, NULL, NULL);
00190    } else {
00191       ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
00192             args.type);
00193       goto return_cleanup;
00194    }
00195 
00196    res = 0;
00197 
00198 return_cleanup:
00199    if (res) {
00200       pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "FAILED");
00201    } else {
00202       switch (outgoing_status) {
00203       case 0:
00204       case AST_CONTROL_ANSWER:
00205          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "SUCCESS");
00206          break;
00207       case AST_CONTROL_BUSY:
00208          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "BUSY");
00209          break;
00210       case AST_CONTROL_CONGESTION:
00211          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "CONGESTION");
00212          break;
00213       case AST_CONTROL_HANGUP:
00214          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "HANGUP");
00215          break;
00216       case AST_CONTROL_RINGING:
00217          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "RINGING");
00218          break;
00219       default:
00220          ast_log(LOG_WARNING, "Unknown originate status result of '%d'\n",
00221                outgoing_status);
00222          pbx_builtin_setvar_helper(chan, "ORIGINATE_STATUS", "UNKNOWN");
00223          break;
00224       }
00225    }
00226    ao2_cleanup(cap_slin);
00227    ast_autoservice_stop(chan);
00228 
00229    return res;
00230 }
00231 
00232 static int unload_module(void)
00233 {
00234    return ast_unregister_application(app_originate);
00235 }
00236 
00237 static int load_module(void)
00238 {
00239    int res;
00240 
00241    res = ast_register_application_xml(app_originate, originate_exec);
00242 
00243    return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
00244 }
00245 
00246 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Originate call");

Generated on Thu Apr 16 06:27:10 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6