Thu Apr 28 2011 17:15:14

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