00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 370951 $");
00034
00035 #include "asterisk/channel.h"
00036 #include "asterisk/pbx.h"
00037 #include "asterisk/module.h"
00038 #include "asterisk/cli.h"
00039 #include "asterisk/utils.h"
00040 #include "asterisk/frame.h"
00041
00042
00043 #define TIMEOUT 30
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 static char *orig_app(int fd, const char *chan, const char *app, const char *appdata)
00055 {
00056 char *chantech;
00057 char *chandata;
00058 int reason = 0;
00059 struct ast_format_cap *cap;
00060 struct ast_format tmpfmt;
00061
00062 if (ast_strlen_zero(app))
00063 return CLI_SHOWUSAGE;
00064
00065 chandata = ast_strdupa(chan);
00066
00067 chantech = strsep(&chandata, "/");
00068 if (!chandata) {
00069 ast_cli(fd, "*** No data provided after channel type! ***\n");
00070 return CLI_SHOWUSAGE;
00071 }
00072
00073 if (!(cap = ast_format_cap_alloc_nolock())) {
00074 return CLI_FAILURE;
00075 }
00076 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
00077 ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL);
00078 cap = ast_format_cap_destroy(cap);
00079
00080 return CLI_SUCCESS;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 static char *orig_exten(int fd, const char *chan, const char *data)
00092 {
00093 char *chantech;
00094 char *chandata;
00095 char *exten = NULL;
00096 char *context = NULL;
00097 int reason = 0;
00098 struct ast_format_cap *cap;
00099 struct ast_format tmpfmt;
00100
00101 chandata = ast_strdupa(chan);
00102
00103 chantech = strsep(&chandata, "/");
00104 if (!chandata) {
00105 ast_cli(fd, "*** No data provided after channel type! ***\n");
00106 return CLI_SHOWUSAGE;
00107 }
00108
00109 if (!ast_strlen_zero(data)) {
00110 context = ast_strdupa(data);
00111 exten = strsep(&context, "@");
00112 }
00113
00114 if (ast_strlen_zero(exten))
00115 exten = "s";
00116 if (ast_strlen_zero(context))
00117 context = "default";
00118 if (!(cap = ast_format_cap_alloc_nolock())) {
00119 return CLI_FAILURE;
00120 }
00121 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
00122 ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0);
00123 cap = ast_format_cap_destroy(cap);
00124
00125 return CLI_SUCCESS;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135 static char *handle_orig(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00136 {
00137 static const char * const choices[] = { "application", "extension", NULL };
00138 char *res = NULL;
00139 switch (cmd) {
00140 case CLI_INIT:
00141 e->command = "channel originate";
00142 e->usage =
00143 " There are two ways to use this command. A call can be originated between a\n"
00144 "channel and a specific application, or between a channel and an extension in\n"
00145 "the dialplan. This is similar to call files or the manager originate action.\n"
00146 "Calls originated with this command are given a timeout of 30 seconds.\n\n"
00147
00148 "Usage1: channel originate <tech/data> application <appname> [appdata]\n"
00149 " This will originate a call between the specified channel tech/data and the\n"
00150 "given application. Arguments to the application are optional. If the given\n"
00151 "arguments to the application include spaces, all of the arguments to the\n"
00152 "application need to be placed in quotation marks.\n\n"
00153
00154 "Usage2: channel originate <tech/data> extension [exten@][context]\n"
00155 " This will originate a call between the specified channel tech/data and the\n"
00156 "given extension. If no context is specified, the 'default' context will be\n"
00157 "used. If no extension is given, the 's' extension will be used.\n";
00158 return NULL;
00159 case CLI_GENERATE:
00160
00161 ast_module_ref(ast_module_info->self);
00162 if (a->pos == 3) {
00163 res = ast_cli_complete(a->word, choices, a->n);
00164 } else if (a->pos == 4) {
00165 if (!strcasecmp("application", a->argv[3])) {
00166 res = ast_complete_applications(a->line, a->word, a->n);
00167 }
00168 }
00169 ast_module_unref(ast_module_info->self);
00170 return res;
00171 }
00172
00173 if (ast_strlen_zero(a->argv[2]) || ast_strlen_zero(a->argv[3]))
00174 return CLI_SHOWUSAGE;
00175
00176
00177 ast_module_ref(ast_module_info->self);
00178
00179 if (!strcasecmp("application", a->argv[3])) {
00180 res = orig_app(a->fd, a->argv[2], a->argv[4], a->argv[5]);
00181 } else if (!strcasecmp("extension", a->argv[3])) {
00182 res = orig_exten(a->fd, a->argv[2], a->argv[4]);
00183 } else {
00184 res = CLI_SHOWUSAGE;
00185 }
00186
00187 ast_module_unref(ast_module_info->self);
00188
00189 return res;
00190 }
00191
00192 static char *handle_redirect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00193 {
00194 const char *name, *dest;
00195 struct ast_channel *chan;
00196 int res;
00197
00198 switch (cmd) {
00199 case CLI_INIT:
00200 e->command = "channel redirect";
00201 e->usage = ""
00202 "Usage: channel redirect <channel> <[[context,]exten,]priority>\n"
00203 " Redirect an active channel to a specified extension.\n";
00204
00205
00206
00207
00208
00209 return NULL;
00210 case CLI_GENERATE:
00211 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
00212 }
00213
00214 if (a->argc != e->args + 2) {
00215 return CLI_SHOWUSAGE;
00216 }
00217
00218 name = a->argv[2];
00219 dest = a->argv[3];
00220
00221 if (!(chan = ast_channel_get_by_name(name))) {
00222 ast_cli(a->fd, "Channel '%s' not found\n", name);
00223 return CLI_FAILURE;
00224 }
00225
00226 res = ast_async_parseable_goto(chan, dest);
00227
00228 chan = ast_channel_unref(chan);
00229
00230 if (!res) {
00231 ast_cli(a->fd, "Channel '%s' successfully redirected to %s\n", name, dest);
00232 } else {
00233 ast_cli(a->fd, "Channel '%s' failed to be redirected to %s\n", name, dest);
00234 }
00235
00236 return res ? CLI_FAILURE : CLI_SUCCESS;
00237 }
00238
00239 static struct ast_cli_entry cli_cliorig[] = {
00240 AST_CLI_DEFINE(handle_orig, "Originate a call"),
00241 AST_CLI_DEFINE(handle_redirect, "Redirect a call"),
00242 };
00243
00244 static int unload_module(void)
00245 {
00246 return ast_cli_unregister_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
00247 }
00248
00249 static int load_module(void)
00250 {
00251 int res;
00252 res = ast_cli_register_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
00253 return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
00254 }
00255
00256 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call origination and redirection from the CLI");