Skip to content

Commit f5680a7

Browse files
InterLinked1gtjoseph
authored andcommitted
res_cliexec: Add dialplan exec CLI command.
Adds a CLI command similar to "dialplan eval function" except for applications: "dialplan exec application", useful for quickly testing certain application behavior directly from the CLI without writing any dialplan. ASTERISK-30062 #close Change-Id: I42e9fa9b60746c21450d40f99a026d48d2486dde
1 parent 938383a commit f5680a7

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

doc/CHANGES-staging/res_cliexec.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Subject: res_cliexec
2+
3+
A new CLI command, dialplan exec application, has
4+
been added which allows dialplan applications to be
5+
executed at the CLI, useful for some quick testing
6+
without needing to write dialplan.

res/res_cliexec.c

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Asterisk -- An open source telephony toolkit.
3+
*
4+
* Copyright (C) 2022, Naveen Albert
5+
*
6+
* Naveen Albert <asterisk@phreaknet.org>
7+
*
8+
* See http://www.asterisk.org for more information about
9+
* the Asterisk project. Please do not directly contact
10+
* any of the maintainers of this project for assistance;
11+
* the project provides a web site, mailing lists and IRC
12+
* channels for your use.
13+
*
14+
* This program is free software, distributed under the terms of
15+
* the GNU General Public License Version 2. See the LICENSE file
16+
* at the top of the source tree.
17+
*/
18+
19+
/*!
20+
* \file
21+
* \author Naveen Albert <asterisk@phreaknet.org>
22+
*
23+
* \brief Execute dialplan applications from the CLI
24+
*
25+
*/
26+
27+
/*** MODULEINFO
28+
<defaultenabled>no</defaultenabled>
29+
<support_level>extended</support_level>
30+
***/
31+
32+
#include "asterisk.h"
33+
34+
#include "asterisk/channel.h"
35+
#include "asterisk/pbx.h"
36+
#include "asterisk/module.h"
37+
#include "asterisk/cli.h"
38+
#include "asterisk/utils.h"
39+
#include "asterisk/frame.h"
40+
#include "asterisk/format_cache.h"
41+
42+
static const struct ast_channel_tech mock_channel_tech = {
43+
};
44+
45+
static int cli_chan = 0;
46+
47+
/*! \brief CLI support for executing application */
48+
static char *handle_exec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
49+
{
50+
struct ast_channel *c = NULL;
51+
RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
52+
char *app_name, *app_args;
53+
int ret = 0;
54+
struct ast_app *app;
55+
56+
switch (cmd) {
57+
case CLI_INIT:
58+
e->command = "dialplan exec application";
59+
e->usage =
60+
"Usage: dialplan exec application <appname> [<args>]\n"
61+
" Execute a single dialplan application call for\n"
62+
" testing. A mock channel is used to execute\n"
63+
" the application, so it may not make\n"
64+
" sense to use all applications, and only\n"
65+
" global variables should be used.\n"
66+
" The ulaw, alaw, and h264 codecs are available.\n";
67+
return NULL;
68+
case CLI_GENERATE:
69+
return NULL;
70+
}
71+
72+
if (a->argc != e->args + 1 && a->argc != e->args + 2) {
73+
return CLI_SHOWUSAGE;
74+
}
75+
76+
app_name = (char *) a->argv[3];
77+
app_args = a->argc == e->args + 2 ? (char *) a->argv[4] : NULL;
78+
79+
if (!app_name) {
80+
return CLI_FAILURE;
81+
}
82+
83+
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
84+
if (!caps) {
85+
ast_log(LOG_WARNING, "Could not allocate an empty format capabilities structure\n");
86+
return CLI_FAILURE;
87+
}
88+
89+
if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
90+
ast_log(LOG_WARNING, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
91+
return CLI_FAILURE;
92+
}
93+
94+
if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
95+
ast_log(LOG_WARNING, "Failed to append an alaw format to capabilities for channel nativeformats\n");
96+
return CLI_FAILURE;
97+
}
98+
99+
if (ast_format_cap_append(caps, ast_format_h264, 0)) {
100+
ast_log(LOG_WARNING, "Failed to append an h264 format to capabilities for channel nativeformats\n");
101+
return CLI_FAILURE;
102+
}
103+
104+
c = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "CLIExec/%d", ++cli_chan);
105+
if (!c) {
106+
ast_cli(a->fd, "Unable to allocate mock channel for application execution.\n");
107+
return CLI_FAILURE;
108+
}
109+
ast_channel_tech_set(c, &mock_channel_tech);
110+
ast_channel_nativeformats_set(c, caps);
111+
ast_channel_set_writeformat(c, ast_format_slin);
112+
ast_channel_set_rawwriteformat(c, ast_format_slin);
113+
ast_channel_set_readformat(c, ast_format_slin);
114+
ast_channel_set_rawreadformat(c, ast_format_slin);
115+
ast_channel_unlock(c);
116+
117+
app = pbx_findapp(app_name);
118+
if (!app) {
119+
ast_log(LOG_WARNING, "Could not find application (%s)\n", app_name);
120+
ast_hangup(c);
121+
return CLI_FAILURE;
122+
} else {
123+
struct ast_str *substituted_args = ast_str_create(16);
124+
125+
if (substituted_args) {
126+
ast_str_substitute_variables(&substituted_args, 0, c, app_args);
127+
ast_cli(a->fd, "Executing: %s(%s)\n", app_name, ast_str_buffer(substituted_args));
128+
ret = pbx_exec(c, app, ast_str_buffer(substituted_args));
129+
ast_free(substituted_args);
130+
} else {
131+
ast_log(LOG_WARNING, "Could not substitute application argument variables for %s\n", app_name);
132+
ast_cli(a->fd, "Executing: %s(%s)\n", app_name, app_args);
133+
ret = pbx_exec(c, app, app_args);
134+
}
135+
}
136+
137+
ast_hangup(c); /* no need to unref separately */
138+
139+
ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret);
140+
141+
return CLI_SUCCESS;
142+
}
143+
144+
static struct ast_cli_entry cli_cliorig[] = {
145+
AST_CLI_DEFINE(handle_exec, "Execute a dialplan application"),
146+
};
147+
148+
static int unload_module(void)
149+
{
150+
return ast_cli_unregister_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
151+
}
152+
153+
static int load_module(void)
154+
{
155+
int res;
156+
res = ast_cli_register_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
157+
return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
158+
}
159+
160+
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Simple dialplan execution from the CLI");

0 commit comments

Comments
 (0)