1999-12-19 22:38:55 +00:00
|
|
|
/*
|
2005-09-14 20:46:50 +00:00
|
|
|
* Asterisk -- An open source telephony toolkit.
|
1999-12-19 22:38:55 +00:00
|
|
|
*
|
2006-02-14 22:44:20 +00:00
|
|
|
* Copyright (C) 1999 - 2006, Digium, Inc.
|
1999-12-19 22:38:55 +00:00
|
|
|
*
|
2004-09-03 03:44:35 +00:00
|
|
|
* Mark Spencer <markster@digium.com>
|
1999-12-19 22:38:55 +00:00
|
|
|
*
|
2005-09-14 20:46:50 +00:00
|
|
|
* See http://www.asterisk.org for more information about
|
|
|
|
* the Asterisk project. Please do not directly contact
|
|
|
|
* any of the maintainers of this project for assistance;
|
|
|
|
* the project provides a web site, mailing lists and IRC
|
|
|
|
* channels for your use.
|
|
|
|
*
|
1999-12-19 22:38:55 +00:00
|
|
|
* This program is free software, distributed under the terms of
|
2005-09-14 20:46:50 +00:00
|
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
|
|
* at the top of the source tree.
|
|
|
|
*/
|
|
|
|
|
2005-10-24 20:12:06 +00:00
|
|
|
/*! \file
|
2005-09-14 20:46:50 +00:00
|
|
|
*
|
2005-10-24 20:12:06 +00:00
|
|
|
* \brief Standard Command Line Interface
|
2005-12-30 21:18:06 +00:00
|
|
|
*
|
2012-03-22 19:51:16 +00:00
|
|
|
* \author Mark Spencer <markster@digium.com>
|
1999-12-19 22:38:55 +00:00
|
|
|
*/
|
|
|
|
|
2012-10-18 14:17:40 +00:00
|
|
|
/*! \li \ref cli.c uses the configuration file \ref cli_permissions.conf
|
|
|
|
* \addtogroup configuration_file Configuration Files
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \page cli_permissions.conf cli_permissions.conf
|
|
|
|
* \verbinclude cli_permissions.conf.sample
|
|
|
|
*/
|
|
|
|
|
2012-06-15 16:20:16 +00:00
|
|
|
/*** MODULEINFO
|
|
|
|
<support_level>core</support_level>
|
|
|
|
***/
|
|
|
|
|
2006-06-07 18:54:56 +00:00
|
|
|
#include "asterisk.h"
|
|
|
|
|
2007-11-20 22:18:21 +00:00
|
|
|
#include "asterisk/_private.h"
|
2007-11-20 23:16:15 +00:00
|
|
|
#include "asterisk/paths.h" /* use ast_config_AST_MODULE_DIR */
|
2005-04-22 13:11:34 +00:00
|
|
|
#include <signal.h>
|
|
|
|
#include <ctype.h>
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
#include <regex.h>
|
2008-12-01 18:52:14 +00:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <grp.h>
|
2005-04-22 13:11:34 +00:00
|
|
|
|
2005-04-21 06:02:45 +00:00
|
|
|
#include "asterisk/cli.h"
|
2006-03-28 22:25:08 +00:00
|
|
|
#include "asterisk/linkedlists.h"
|
2005-04-21 06:02:45 +00:00
|
|
|
#include "asterisk/module.h"
|
|
|
|
#include "asterisk/pbx.h"
|
|
|
|
#include "asterisk/channel.h"
|
|
|
|
#include "asterisk/utils.h"
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
#include "asterisk/app.h"
|
2005-04-21 06:02:45 +00:00
|
|
|
#include "asterisk/lock.h"
|
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
|
|
|
#include "asterisk/threadstorage.h"
|
2010-08-12 20:17:17 +00:00
|
|
|
#include "asterisk/translate.h"
|
2013-07-25 04:06:32 +00:00
|
|
|
#include "asterisk/bridge.h"
|
2013-07-08 19:19:55 +00:00
|
|
|
#include "asterisk/stasis_channels.h"
|
2013-07-25 04:18:05 +00:00
|
|
|
#include "asterisk/stasis_bridges.h"
|
2016-03-10 22:58:49 +00:00
|
|
|
#include "asterisk/vector.h"
|
2017-02-22 14:32:23 +00:00
|
|
|
#include "asterisk/stream.h"
|
2005-11-05 18:58:27 +00:00
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
/*!
|
|
|
|
* \brief List of restrictions per user.
|
|
|
|
*/
|
|
|
|
struct cli_perm {
|
|
|
|
unsigned int permit:1; /*!< 1=Permit 0=Deny */
|
|
|
|
char *command; /*!< Command name (to apply restrictions) */
|
|
|
|
AST_LIST_ENTRY(cli_perm) list;
|
|
|
|
};
|
|
|
|
|
|
|
|
AST_LIST_HEAD_NOLOCK(cli_perm_head, cli_perm);
|
|
|
|
|
|
|
|
/*! \brief list of users to apply restrictions. */
|
|
|
|
struct usergroup_cli_perm {
|
|
|
|
int uid; /*!< User ID (-1 disabled) */
|
|
|
|
int gid; /*!< Group ID (-1 disabled) */
|
|
|
|
struct cli_perm_head *perms; /*!< List of permissions. */
|
|
|
|
AST_LIST_ENTRY(usergroup_cli_perm) list;/*!< List mechanics */
|
|
|
|
};
|
|
|
|
/*! \brief CLI permissions config file. */
|
|
|
|
static const char perms_config[] = "cli_permissions.conf";
|
|
|
|
/*! \brief Default permissions value 1=Permit 0=Deny */
|
|
|
|
static int cli_default_perm = 1;
|
|
|
|
|
|
|
|
/*! \brief mutex used to prevent a user from running the 'cli reload permissions' command while
|
|
|
|
* it is already running. */
|
|
|
|
AST_MUTEX_DEFINE_STATIC(permsconfiglock);
|
|
|
|
/*! \brief List of users and permissions. */
|
2009-06-15 17:34:30 +00:00
|
|
|
static AST_RWLIST_HEAD_STATIC(cli_perms, usergroup_cli_perm);
|
2008-12-01 18:52:14 +00:00
|
|
|
|
2007-07-23 14:21:41 +00:00
|
|
|
/*!
|
2010-03-23 14:22:27 +00:00
|
|
|
* \brief map a debug or verbose level to a module name
|
2007-07-23 14:21:41 +00:00
|
|
|
*/
|
2010-03-23 14:22:27 +00:00
|
|
|
struct module_level {
|
2007-07-23 14:21:41 +00:00
|
|
|
unsigned int level;
|
2010-03-23 14:22:27 +00:00
|
|
|
AST_RWLIST_ENTRY(module_level) entry;
|
|
|
|
char module[0];
|
2007-07-23 14:21:41 +00:00
|
|
|
};
|
|
|
|
|
2010-03-23 14:22:27 +00:00
|
|
|
AST_RWLIST_HEAD(module_level_list, module_level);
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2010-03-23 14:22:27 +00:00
|
|
|
/*! list of module names and their debug levels */
|
2013-04-19 05:20:02 +00:00
|
|
|
static struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE;
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2006-10-19 01:00:57 +00:00
|
|
|
AST_THREADSTORAGE(ast_cli_buf);
|
2006-07-23 15:19:16 +00:00
|
|
|
|
2016-03-10 22:58:49 +00:00
|
|
|
AST_RWLOCK_DEFINE_STATIC(shutdown_commands_lock);
|
|
|
|
static AST_VECTOR(, struct ast_cli_entry *) shutdown_commands;
|
|
|
|
|
2006-07-26 07:48:48 +00:00
|
|
|
/*! \brief Initial buffer size for resulting strings in ast_cli() */
|
2006-08-08 06:36:47 +00:00
|
|
|
#define AST_CLI_INITLEN 256
|
2006-07-23 15:19:16 +00:00
|
|
|
|
2007-02-13 05:57:52 +00:00
|
|
|
void ast_cli(int fd, const char *fmt, ...)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2006-02-09 16:59:50 +00:00
|
|
|
int res;
|
2006-12-15 23:10:42 +00:00
|
|
|
struct ast_str *buf;
|
1999-12-19 22:38:55 +00:00
|
|
|
va_list ap;
|
2005-07-15 22:06:15 +00:00
|
|
|
|
2006-12-15 23:10:42 +00:00
|
|
|
if (!(buf = ast_str_thread_get(&ast_cli_buf, AST_CLI_INITLEN)))
|
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
|
|
|
return;
|
2006-07-23 15:19:16 +00:00
|
|
|
|
1999-12-19 22:38:55 +00:00
|
|
|
va_start(ap, fmt);
|
2006-12-15 23:10:42 +00:00
|
|
|
res = ast_str_set_va(&buf, 0, fmt, ap);
|
1999-12-19 22:38:55 +00:00
|
|
|
va_end(ap);
|
2006-07-23 15:19:16 +00:00
|
|
|
|
2008-12-13 08:36:35 +00:00
|
|
|
if (res != AST_DYNSTR_BUILD_FAILED) {
|
|
|
|
ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
|
|
|
|
}
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2012-03-22 19:51:16 +00:00
|
|
|
unsigned int ast_debug_get_by_module(const char *module)
|
2007-07-23 14:21:41 +00:00
|
|
|
{
|
2010-03-23 14:22:27 +00:00
|
|
|
struct module_level *ml;
|
2007-07-23 14:21:41 +00:00
|
|
|
unsigned int res = 0;
|
|
|
|
|
2010-03-23 14:22:27 +00:00
|
|
|
AST_RWLIST_RDLOCK(&debug_modules);
|
|
|
|
AST_LIST_TRAVERSE(&debug_modules, ml, entry) {
|
|
|
|
if (!strcasecmp(ml->module, module)) {
|
|
|
|
res = ml->level;
|
2007-07-23 14:21:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-03-23 14:22:27 +00:00
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
2007-07-23 14:21:41 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
/*! \internal
|
|
|
|
* \brief Check if the user with 'uid' and 'gid' is allow to execute 'command',
|
|
|
|
* if command starts with '_' then not check permissions, just permit
|
|
|
|
* to run the 'command'.
|
|
|
|
* if uid == -1 or gid == -1 do not check permissions.
|
|
|
|
* if uid == -2 and gid == -2 is because rasterisk client didn't send
|
|
|
|
* the credentials, so the cli_default_perm will be applied.
|
|
|
|
* \param uid User ID.
|
|
|
|
* \param gid Group ID.
|
|
|
|
* \param command Command name to check permissions.
|
|
|
|
* \retval 1 if has permission
|
|
|
|
* \retval 0 if it is not allowed.
|
|
|
|
*/
|
|
|
|
static int cli_has_permissions(int uid, int gid, const char *command)
|
|
|
|
{
|
|
|
|
struct usergroup_cli_perm *user_perm;
|
|
|
|
struct cli_perm *perm;
|
|
|
|
/* set to the default permissions general option. */
|
|
|
|
int isallowg = cli_default_perm, isallowu = -1, ispattern;
|
|
|
|
regex_t regexbuf;
|
|
|
|
|
|
|
|
/* if uid == -1 or gid == -1 do not check permissions.
|
|
|
|
if uid == -2 and gid == -2 is because rasterisk client didn't send
|
|
|
|
the credentials, so the cli_default_perm will be applied. */
|
|
|
|
if ((uid == CLI_NO_PERMS && gid == CLI_NO_PERMS) || command[0] == '_') {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gid < 0 && uid < 0) {
|
|
|
|
return cli_default_perm;
|
|
|
|
}
|
|
|
|
|
|
|
|
AST_RWLIST_RDLOCK(&cli_perms);
|
|
|
|
AST_LIST_TRAVERSE(&cli_perms, user_perm, list) {
|
|
|
|
if (user_perm->gid != gid && user_perm->uid != uid) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
AST_LIST_TRAVERSE(user_perm->perms, perm, list) {
|
|
|
|
if (strcasecmp(perm->command, "all") && strncasecmp(perm->command, command, strlen(perm->command))) {
|
|
|
|
/* if the perm->command is a pattern, check it against command. */
|
|
|
|
ispattern = !regcomp(®exbuf, perm->command, REG_EXTENDED | REG_NOSUB | REG_ICASE);
|
|
|
|
if (ispattern && regexec(®exbuf, command, 0, NULL, 0)) {
|
|
|
|
regfree(®exbuf);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!ispattern) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
regfree(®exbuf);
|
|
|
|
}
|
|
|
|
if (user_perm->uid == uid) {
|
|
|
|
/* this is a user definition. */
|
|
|
|
isallowu = perm->permit;
|
|
|
|
} else {
|
|
|
|
/* otherwise is a group definition. */
|
|
|
|
isallowg = perm->permit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AST_RWLIST_UNLOCK(&cli_perms);
|
|
|
|
if (isallowu > -1) {
|
|
|
|
/* user definition override group definition. */
|
|
|
|
isallowg = isallowu;
|
|
|
|
}
|
|
|
|
|
|
|
|
return isallowg;
|
|
|
|
}
|
|
|
|
|
2007-08-01 15:28:02 +00:00
|
|
|
static AST_RWLIST_HEAD_STATIC(helpers, ast_cli_entry);
|
1999-12-19 22:38:55 +00:00
|
|
|
|
2006-11-15 16:39:38 +00:00
|
|
|
static char *handle_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-11-10 17:01:06 +00:00
|
|
|
{
|
2006-11-14 16:31:57 +00:00
|
|
|
/* "module load <mod>" */
|
2006-11-15 16:39:38 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "module load";
|
|
|
|
e->usage =
|
|
|
|
"Usage: module load <module name>\n"
|
|
|
|
" Loads the specified module into Asterisk.\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case CLI_GENERATE:
|
2017-10-30 22:30:18 +00:00
|
|
|
if (a->pos != e->args) {
|
2006-11-15 16:39:38 +00:00
|
|
|
return NULL;
|
2017-10-30 22:30:18 +00:00
|
|
|
}
|
|
|
|
return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOAD);
|
2006-11-10 17:01:06 +00:00
|
|
|
}
|
2017-10-30 22:30:18 +00:00
|
|
|
if (a->argc != e->args + 1) {
|
2006-11-15 16:39:38 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
2017-10-30 22:30:18 +00:00
|
|
|
}
|
2006-11-15 16:39:38 +00:00
|
|
|
if (ast_load_resource(a->argv[e->args])) {
|
|
|
|
ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
|
|
|
|
return CLI_FAILURE;
|
|
|
|
}
|
2010-05-12 19:59:16 +00:00
|
|
|
ast_cli(a->fd, "Loaded %s\n", a->argv[e->args]);
|
2006-11-15 16:39:38 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-11-10 17:01:06 +00:00
|
|
|
}
|
|
|
|
|
2006-11-15 15:02:56 +00:00
|
|
|
static char *handle_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-11-10 17:01:06 +00:00
|
|
|
{
|
2006-11-15 15:02:56 +00:00
|
|
|
int x;
|
2006-11-14 16:55:27 +00:00
|
|
|
|
2006-11-15 15:02:56 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "module reload";
|
|
|
|
e->usage =
|
|
|
|
"Usage: module reload [module ...]\n"
|
|
|
|
" Reloads configuration files for all listed modules which support\n"
|
|
|
|
" reloading, or for all supported modules if none are listed.\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case CLI_GENERATE:
|
2017-10-30 22:30:18 +00:00
|
|
|
return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RELOAD);
|
2006-11-15 15:02:56 +00:00
|
|
|
}
|
|
|
|
if (a->argc == e->args) {
|
2006-11-14 16:55:27 +00:00
|
|
|
ast_module_reload(NULL);
|
2006-11-15 15:02:56 +00:00
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
for (x = e->args; x < a->argc; x++) {
|
2013-05-24 20:44:07 +00:00
|
|
|
enum ast_module_reload_result res = ast_module_reload(a->argv[x]);
|
2007-01-23 00:11:32 +00:00
|
|
|
switch (res) {
|
2013-05-24 20:44:07 +00:00
|
|
|
case AST_MODULE_RELOAD_NOT_FOUND:
|
2006-11-15 15:02:56 +00:00
|
|
|
ast_cli(a->fd, "No such module '%s'\n", a->argv[x]);
|
|
|
|
break;
|
2013-05-24 20:44:07 +00:00
|
|
|
case AST_MODULE_RELOAD_NOT_IMPLEMENTED:
|
|
|
|
ast_cli(a->fd, "The module '%s' does not support reloads\n", a->argv[x]);
|
|
|
|
break;
|
|
|
|
case AST_MODULE_RELOAD_QUEUED:
|
|
|
|
ast_cli(a->fd, "Asterisk cannot reload a module yet; request queued\n");
|
|
|
|
break;
|
|
|
|
case AST_MODULE_RELOAD_ERROR:
|
|
|
|
ast_cli(a->fd, "The module '%s' reported a reload failure\n", a->argv[x]);
|
|
|
|
break;
|
|
|
|
case AST_MODULE_RELOAD_IN_PROGRESS:
|
|
|
|
ast_cli(a->fd, "A module reload request is already in progress; please be patient\n");
|
|
|
|
break;
|
|
|
|
case AST_MODULE_RELOAD_UNINITIALIZED:
|
|
|
|
ast_cli(a->fd, "The module '%s' was not properly initialized. Before reloading"
|
|
|
|
" the module, you must run \"module load %s\" and fix whatever is"
|
|
|
|
" preventing the module from being initialized.\n", a->argv[x], a->argv[x]);
|
|
|
|
break;
|
|
|
|
case AST_MODULE_RELOAD_SUCCESS:
|
|
|
|
ast_cli(a->fd, "Module '%s' reloaded successfully.\n", a->argv[x]);
|
2006-11-15 15:02:56 +00:00
|
|
|
break;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
2006-11-14 16:55:27 +00:00
|
|
|
}
|
2006-11-15 15:02:56 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
|
|
|
|
2010-08-12 20:44:39 +00:00
|
|
|
static char *handle_core_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "core reload";
|
|
|
|
e->usage =
|
|
|
|
"Usage: core reload\n"
|
|
|
|
" Execute a global reload.\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->argc != e->args) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_module_reload(NULL);
|
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
2014-01-14 18:14:02 +00:00
|
|
|
|
2012-03-22 19:51:16 +00:00
|
|
|
/*!
|
2014-01-14 18:14:02 +00:00
|
|
|
* \brief Find the module level setting
|
|
|
|
*
|
|
|
|
* \param module Module name to look for.
|
|
|
|
* \param mll List to search.
|
|
|
|
*
|
|
|
|
* \retval level struct found on success.
|
|
|
|
* \retval NULL not found.
|
2007-07-23 14:21:41 +00:00
|
|
|
*/
|
2014-01-14 18:14:02 +00:00
|
|
|
static struct module_level *find_module_level(const char *module, struct module_level_list *mll)
|
2007-07-23 14:21:41 +00:00
|
|
|
{
|
2010-03-23 14:22:27 +00:00
|
|
|
struct module_level *ml;
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2010-03-23 14:22:27 +00:00
|
|
|
AST_LIST_TRAVERSE(mll, ml, entry) {
|
|
|
|
if (!strcasecmp(ml->module, module))
|
|
|
|
return ml;
|
2007-07-23 14:21:41 +00:00
|
|
|
}
|
|
|
|
|
2010-03-23 14:22:27 +00:00
|
|
|
return NULL;
|
2007-07-23 14:21:41 +00:00
|
|
|
}
|
|
|
|
|
2008-12-10 17:09:15 +00:00
|
|
|
static char *complete_number(const char *partial, unsigned int min, unsigned int max, int n)
|
|
|
|
{
|
|
|
|
int i, count = 0;
|
|
|
|
unsigned int prospective[2];
|
|
|
|
unsigned int part = strtoul(partial, NULL, 10);
|
2017-07-28 01:58:22 +00:00
|
|
|
char next[13];
|
2008-12-10 17:09:15 +00:00
|
|
|
|
|
|
|
if (part < min || part > max) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
|
|
if (i == 0) {
|
|
|
|
prospective[0] = prospective[1] = part;
|
|
|
|
} else if (part == 0 && !ast_strlen_zero(partial)) {
|
|
|
|
break;
|
|
|
|
} else if (i < 11) {
|
|
|
|
prospective[0] = prospective[1] = part * 10 + (i - 1);
|
|
|
|
} else {
|
|
|
|
prospective[0] = (part * 10 + (i - 11)) * 10;
|
|
|
|
prospective[1] = prospective[0] + 9;
|
|
|
|
}
|
|
|
|
if (i < 11 && (prospective[0] < min || prospective[0] > max)) {
|
|
|
|
continue;
|
|
|
|
} else if (prospective[1] < min || prospective[0] > max) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (++count > n) {
|
|
|
|
if (i < 11) {
|
|
|
|
snprintf(next, sizeof(next), "%u", prospective[0]);
|
|
|
|
} else {
|
|
|
|
snprintf(next, sizeof(next), "%u...", prospective[0] / 10);
|
|
|
|
}
|
|
|
|
return ast_strdup(next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
static void status_debug_verbose(struct ast_cli_args *a, const char *what, int old_val, int cur_val)
|
|
|
|
{
|
|
|
|
char was_buf[30];
|
|
|
|
const char *was;
|
|
|
|
|
|
|
|
if (old_val) {
|
|
|
|
snprintf(was_buf, sizeof(was_buf), "%d", old_val);
|
|
|
|
was = was_buf;
|
|
|
|
} else {
|
|
|
|
was = "OFF";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_val == cur_val) {
|
|
|
|
ast_cli(a->fd, "%s is still %s.\n", what, was);
|
|
|
|
} else {
|
|
|
|
char now_buf[30];
|
|
|
|
const char *now;
|
|
|
|
|
|
|
|
if (cur_val) {
|
|
|
|
snprintf(now_buf, sizeof(now_buf), "%d", cur_val);
|
|
|
|
now = now_buf;
|
|
|
|
} else {
|
|
|
|
now = "OFF";
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_cli(a->fd, "%s was %s and is now %s.\n", what, was, now);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-09-18 19:54:18 +00:00
|
|
|
{
|
2007-06-05 22:59:36 +00:00
|
|
|
int oldval;
|
2006-09-29 22:36:29 +00:00
|
|
|
int newlevel;
|
|
|
|
int atleast = 0;
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
|
2010-03-23 14:22:27 +00:00
|
|
|
struct module_level *ml;
|
2006-11-15 14:11:28 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
2014-01-14 18:14:02 +00:00
|
|
|
e->command = "core set debug";
|
2006-11-15 14:11:28 +00:00
|
|
|
e->usage =
|
2014-01-14 18:14:02 +00:00
|
|
|
"Usage: core set debug [atleast] <level> [module]\n"
|
|
|
|
" core set debug off\n"
|
|
|
|
"\n"
|
|
|
|
" Sets level of debug messages to be displayed or\n"
|
2010-03-23 14:22:27 +00:00
|
|
|
" sets a module name to display debug messages from.\n"
|
2014-01-14 18:14:02 +00:00
|
|
|
" 0 or off means no messages should be displayed.\n"
|
|
|
|
" Equivalent to -d[d[...]] on startup\n";
|
2006-11-15 14:11:28 +00:00
|
|
|
return NULL;
|
2006-09-29 22:36:29 +00:00
|
|
|
|
2006-11-14 16:55:27 +00:00
|
|
|
case CLI_GENERATE:
|
2014-01-14 18:14:02 +00:00
|
|
|
if (!strcasecmp(argv3, "atleast")) {
|
|
|
|
atleast = 1;
|
|
|
|
}
|
|
|
|
if (a->pos == 3 || (a->pos == 4 && atleast)) {
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
|
2008-12-10 17:09:15 +00:00
|
|
|
int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
|
2014-01-14 18:14:02 +00:00
|
|
|
|
2008-12-10 17:09:15 +00:00
|
|
|
if (a->n < 21 && numbermatch == 0) {
|
|
|
|
return complete_number(pos, 0, 0x7fffffff, a->n);
|
|
|
|
} else if (pos[0] == '0') {
|
|
|
|
if (a->n == 0) {
|
|
|
|
return ast_strdup("0");
|
|
|
|
}
|
|
|
|
} else if (a->n == (21 - numbermatch)) {
|
|
|
|
if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
|
|
|
|
return ast_strdup("off");
|
|
|
|
} else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
|
|
|
|
return ast_strdup("atleast");
|
|
|
|
}
|
|
|
|
} else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
|
|
|
|
return ast_strdup("atleast");
|
|
|
|
}
|
2015-03-14 01:37:24 +00:00
|
|
|
} else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel"))
|
2014-01-14 18:14:02 +00:00
|
|
|
|| (a->pos == 5 && atleast)) {
|
2017-10-30 22:30:18 +00:00
|
|
|
return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RUNNING);
|
2008-12-10 17:09:15 +00:00
|
|
|
}
|
2006-11-17 11:12:13 +00:00
|
|
|
return NULL;
|
2006-11-14 16:55:27 +00:00
|
|
|
}
|
|
|
|
/* all the above return, so we proceed with the handler.
|
|
|
|
* we are guaranteed to be called with argc >= e->args;
|
|
|
|
*/
|
2006-09-29 22:36:29 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (a->argc <= e->args) {
|
2006-11-15 14:11:28 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
2006-11-17 12:26:15 +00:00
|
|
|
}
|
2014-01-14 18:14:02 +00:00
|
|
|
|
|
|
|
if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
|
2006-11-14 16:55:27 +00:00
|
|
|
newlevel = 0;
|
2014-01-14 18:14:02 +00:00
|
|
|
} else {
|
|
|
|
if (!strcasecmp(a->argv[e->args], "atleast")) {
|
|
|
|
atleast = 1;
|
|
|
|
}
|
|
|
|
if (a->argc != e->args + atleast + 1 && a->argc != e->args + atleast + 2) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
|
|
|
if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (a->argc == e->args + atleast + 2) {
|
|
|
|
/* We have specified a module name. */
|
|
|
|
char *mod = ast_strdupa(a->argv[e->args + atleast + 1]);
|
|
|
|
int mod_len = strlen(mod);
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (3 < mod_len && !strcasecmp(mod + mod_len - 3, ".so")) {
|
|
|
|
mod[mod_len - 3] = '\0';
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
AST_RWLIST_WRLOCK(&debug_modules);
|
|
|
|
|
|
|
|
ml = find_module_level(mod, &debug_modules);
|
|
|
|
if (!newlevel) {
|
|
|
|
if (!ml) {
|
|
|
|
/* Specified off for a nonexistent entry. */
|
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
|
|
|
ast_cli(a->fd, "Core debug is still 0 for '%s'.\n", mod);
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
AST_RWLIST_REMOVE(&debug_modules, ml, entry);
|
|
|
|
if (AST_RWLIST_EMPTY(&debug_modules)) {
|
|
|
|
ast_clear_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
|
|
|
|
}
|
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
2014-05-09 22:49:26 +00:00
|
|
|
ast_cli(a->fd, "Core debug was %u and has been set to 0 for '%s'.\n",
|
2014-01-14 18:14:02 +00:00
|
|
|
ml->level, mod);
|
|
|
|
ast_free(ml);
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ml) {
|
|
|
|
if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
|
2014-05-09 22:49:26 +00:00
|
|
|
ast_cli(a->fd, "Core debug is still %u for '%s'.\n", ml->level, mod);
|
2014-01-14 18:14:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
oldval = ml->level;
|
|
|
|
ml->level = newlevel;
|
|
|
|
} else {
|
|
|
|
ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
|
|
|
|
if (!ml) {
|
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
|
|
|
return CLI_FAILURE;
|
|
|
|
}
|
|
|
|
oldval = ml->level;
|
|
|
|
ml->level = newlevel;
|
|
|
|
strcpy(ml->module, mod);
|
|
|
|
AST_RWLIST_INSERT_TAIL(&debug_modules, ml, entry);
|
|
|
|
}
|
|
|
|
ast_set_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
|
|
|
|
|
2014-05-09 22:49:26 +00:00
|
|
|
ast_cli(a->fd, "Core debug was %d and has been set to %u for '%s'.\n",
|
2014-01-14 18:14:02 +00:00
|
|
|
oldval, ml->level, ml->module);
|
|
|
|
|
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
2006-11-14 16:55:27 +00:00
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
/* Update global debug level */
|
|
|
|
if (!newlevel) {
|
|
|
|
/* Specified level was 0 or off. */
|
|
|
|
AST_RWLIST_WRLOCK(&debug_modules);
|
|
|
|
while ((ml = AST_RWLIST_REMOVE_HEAD(&debug_modules, entry))) {
|
|
|
|
ast_free(ml);
|
2010-03-23 14:22:27 +00:00
|
|
|
}
|
2014-01-14 18:14:02 +00:00
|
|
|
ast_clear_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
|
|
|
|
AST_RWLIST_UNLOCK(&debug_modules);
|
|
|
|
}
|
|
|
|
oldval = option_debug;
|
|
|
|
if (!atleast || newlevel > option_debug) {
|
|
|
|
option_debug = newlevel;
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
/* Report debug level status */
|
|
|
|
status_debug_verbose(a, "Core debug", oldval, option_debug);
|
2010-10-11 16:44:32 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
int oldval;
|
|
|
|
int newlevel;
|
|
|
|
int atleast = 0;
|
|
|
|
int silent = 0;
|
|
|
|
const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "core set verbose";
|
|
|
|
e->usage =
|
|
|
|
"Usage: core set verbose [atleast] <level> [silent]\n"
|
|
|
|
" core set verbose off\n"
|
|
|
|
"\n"
|
|
|
|
" Sets level of verbose messages to be displayed.\n"
|
|
|
|
" 0 or off means no verbose messages should be displayed.\n"
|
|
|
|
" The silent option means the command does not report what\n"
|
|
|
|
" happened to the verbose level.\n"
|
|
|
|
" Equivalent to -v[v[...]] on startup\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case CLI_GENERATE:
|
|
|
|
if (!strcasecmp(argv3, "atleast")) {
|
|
|
|
atleast = 1;
|
2007-07-23 14:21:41 +00:00
|
|
|
}
|
2014-01-14 18:14:02 +00:00
|
|
|
if (a->pos == 3 || (a->pos == 4 && atleast)) {
|
|
|
|
const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
|
|
|
|
int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (a->n < 21 && numbermatch == 0) {
|
|
|
|
return complete_number(pos, 0, 0x7fffffff, a->n);
|
|
|
|
} else if (pos[0] == '0') {
|
|
|
|
if (a->n == 0) {
|
|
|
|
return ast_strdup("0");
|
|
|
|
}
|
|
|
|
} else if (a->n == (21 - numbermatch)) {
|
|
|
|
if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
|
|
|
|
return ast_strdup("off");
|
|
|
|
} else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
|
|
|
|
return ast_strdup("atleast");
|
|
|
|
}
|
|
|
|
} else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
|
|
|
|
return ast_strdup("atleast");
|
2007-07-23 14:21:41 +00:00
|
|
|
}
|
2014-01-14 18:14:02 +00:00
|
|
|
} else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off"))
|
|
|
|
|| (a->pos == 5 && atleast)) {
|
|
|
|
const char *pos = S_OR(a->argv[a->pos], "");
|
|
|
|
|
|
|
|
if (a->n == 0 && !strncasecmp(pos, "silent", strlen(pos))) {
|
|
|
|
return ast_strdup("silent");
|
2010-10-11 16:44:32 +00:00
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
}
|
2014-01-14 18:14:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* all the above return, so we proceed with the handler.
|
|
|
|
* we are guaranteed to be called with argc >= e->args;
|
|
|
|
*/
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (a->argc <= e->args) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
|
|
|
|
newlevel = 0;
|
|
|
|
} else {
|
|
|
|
if (!strcasecmp(a->argv[e->args], "atleast")) {
|
|
|
|
atleast = 1;
|
|
|
|
}
|
|
|
|
if (a->argc == e->args + atleast + 2
|
|
|
|
&& !strcasecmp(a->argv[e->args + atleast + 1], "silent")) {
|
|
|
|
silent = 1;
|
|
|
|
}
|
|
|
|
if (a->argc != e->args + atleast + silent + 1) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
|
|
|
if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
/* Update verbose level */
|
|
|
|
oldval = ast_verb_console_get();
|
|
|
|
if (!atleast || newlevel > oldval) {
|
|
|
|
ast_verb_console_set(newlevel);
|
|
|
|
} else {
|
|
|
|
newlevel = oldval;
|
|
|
|
}
|
2007-07-23 14:21:41 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
if (silent) {
|
|
|
|
/* Be silent after setting the level. */
|
2007-07-23 14:21:41 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
/* Report verbose level status */
|
|
|
|
status_debug_verbose(a, "Console verbose", oldval, newlevel);
|
|
|
|
|
2006-11-15 14:11:28 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
static char *handle_logger_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-05-26 19:48:17 +00:00
|
|
|
{
|
2007-10-11 19:03:06 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "logger mute";
|
2012-03-22 19:51:16 +00:00
|
|
|
e->usage =
|
2007-10-11 19:03:06 +00:00
|
|
|
"Usage: logger mute\n"
|
|
|
|
" Disables logging output to the current console, making it possible to\n"
|
|
|
|
" gather information without being disturbed by scrolling lines.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-10-13 05:53:19 +00:00
|
|
|
if (a->argc < 2 || a->argc > 3)
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
2007-10-13 05:53:19 +00:00
|
|
|
|
2007-10-13 08:38:50 +00:00
|
|
|
if (a->argc == 3 && !strcasecmp(a->argv[2], "silent"))
|
2007-10-13 05:53:19 +00:00
|
|
|
ast_console_toggle_mute(a->fd, 1);
|
|
|
|
else
|
|
|
|
ast_console_toggle_mute(a->fd, 0);
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-05-26 19:48:17 +00:00
|
|
|
}
|
|
|
|
|
2006-11-15 15:02:56 +00:00
|
|
|
static char *handle_unload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-11-10 17:01:06 +00:00
|
|
|
{
|
2006-11-14 16:38:35 +00:00
|
|
|
/* "module unload mod_1 [mod_2 .. mod_N]" */
|
2006-11-10 17:01:06 +00:00
|
|
|
int x;
|
|
|
|
int force = AST_FORCE_SOFT;
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *s;
|
2006-11-15 15:02:56 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "module unload";
|
|
|
|
e->usage =
|
|
|
|
"Usage: module unload [-f|-h] <module_1> [<module_2> ... ]\n"
|
|
|
|
" Unloads the specified module from Asterisk. The -f\n"
|
|
|
|
" option causes the module to be unloaded even if it is\n"
|
|
|
|
" in use (may cause a crash) and the -h module causes the\n"
|
|
|
|
" module to be unloaded even if the module says it cannot, \n"
|
|
|
|
" which almost always will cause a crash.\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case CLI_GENERATE:
|
2017-10-30 22:30:18 +00:00
|
|
|
return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD);
|
2006-11-15 15:02:56 +00:00
|
|
|
}
|
|
|
|
if (a->argc < e->args + 1)
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
x = e->args; /* first argument */
|
|
|
|
s = a->argv[x];
|
|
|
|
if (s[0] == '-') {
|
|
|
|
if (s[1] == 'f')
|
|
|
|
force = AST_FORCE_FIRM;
|
|
|
|
else if (s[1] == 'h')
|
|
|
|
force = AST_FORCE_HARD;
|
|
|
|
else
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
if (a->argc < e->args + 2) /* need at least one module name */
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
x++; /* skip this argument */
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; x < a->argc; x++) {
|
|
|
|
if (ast_unload_resource(a->argv[x], force)) {
|
|
|
|
ast_cli(a->fd, "Unable to unload resource %s\n", a->argv[x]);
|
|
|
|
return CLI_FAILURE;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
2010-05-12 19:59:16 +00:00
|
|
|
ast_cli(a->fd, "Unloaded %s\n", a->argv[x]);
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
2010-05-12 19:59:16 +00:00
|
|
|
|
2006-11-15 15:02:56 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
|
|
|
|
2014-07-25 16:47:17 +00:00
|
|
|
#define MODLIST_FORMAT "%-30s %-40.40s %-10d %-11s %13s\n"
|
|
|
|
#define MODLIST_FORMAT2 "%-30s %-40.40s %-10s %-11s %13s\n"
|
1999-12-19 22:38:55 +00:00
|
|
|
|
2004-06-09 01:45:08 +00:00
|
|
|
AST_MUTEX_DEFINE_STATIC(climodentrylock);
|
1999-12-19 22:38:55 +00:00
|
|
|
static int climodentryfd = -1;
|
|
|
|
|
2014-07-25 16:47:17 +00:00
|
|
|
static int modlist_modentry(const char *module, const char *description,
|
|
|
|
int usecnt, const char *status, const char *like,
|
|
|
|
enum ast_module_support_level support_level)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2004-10-14 04:38:29 +00:00
|
|
|
/* Comparing the like with the module */
|
2005-08-22 18:43:32 +00:00
|
|
|
if (strcasestr(module, like) ) {
|
2014-07-25 16:47:17 +00:00
|
|
|
ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt,
|
|
|
|
status, ast_module_support_level_to_string(support_level));
|
2004-10-14 04:38:29 +00:00
|
|
|
return 1;
|
2012-03-22 19:51:16 +00:00
|
|
|
}
|
1999-12-19 22:38:55 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-07-18 19:47:20 +00:00
|
|
|
static void print_uptimestr(int fd, struct timeval timeval, const char *prefix, int printsec)
|
2003-05-02 15:37:34 +00:00
|
|
|
{
|
2006-01-18 00:05:09 +00:00
|
|
|
int x; /* the main part - years, weeks, etc. */
|
2006-12-16 09:56:31 +00:00
|
|
|
struct ast_str *out;
|
2006-01-18 00:05:09 +00:00
|
|
|
|
2003-05-02 15:37:34 +00:00
|
|
|
#define SECOND (1)
|
2004-06-22 17:42:14 +00:00
|
|
|
#define MINUTE (SECOND*60)
|
|
|
|
#define HOUR (MINUTE*60)
|
2003-05-02 15:37:34 +00:00
|
|
|
#define DAY (HOUR*24)
|
|
|
|
#define WEEK (DAY*7)
|
|
|
|
#define YEAR (DAY*365)
|
2015-06-04 12:14:13 +00:00
|
|
|
#define NEEDCOMMA(x) ((x) ? ", " : "") /* define if we need a comma */
|
2007-07-18 19:47:20 +00:00
|
|
|
if (timeval.tv_sec < 0) /* invalid, nothing to show */
|
2006-01-18 00:05:09 +00:00
|
|
|
return;
|
2006-12-16 09:56:31 +00:00
|
|
|
|
2006-01-18 00:05:09 +00:00
|
|
|
if (printsec) { /* plain seconds output */
|
2016-02-18 04:58:01 +00:00
|
|
|
ast_cli(fd, "%s%lu\n", prefix, (u_long)timeval.tv_sec);
|
2006-12-16 09:56:31 +00:00
|
|
|
return;
|
2006-01-18 00:05:09 +00:00
|
|
|
}
|
2006-12-16 09:56:31 +00:00
|
|
|
out = ast_str_alloca(256);
|
2007-07-18 19:47:20 +00:00
|
|
|
if (timeval.tv_sec > YEAR) {
|
|
|
|
x = (timeval.tv_sec / YEAR);
|
|
|
|
timeval.tv_sec -= (x * YEAR);
|
2015-06-04 12:14:13 +00:00
|
|
|
ast_str_append(&out, 0, "%d year%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
2007-07-18 19:47:20 +00:00
|
|
|
if (timeval.tv_sec > WEEK) {
|
|
|
|
x = (timeval.tv_sec / WEEK);
|
|
|
|
timeval.tv_sec -= (x * WEEK);
|
2015-06-04 12:14:13 +00:00
|
|
|
ast_str_append(&out, 0, "%d week%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
2007-07-18 19:47:20 +00:00
|
|
|
if (timeval.tv_sec > DAY) {
|
|
|
|
x = (timeval.tv_sec / DAY);
|
|
|
|
timeval.tv_sec -= (x * DAY);
|
2015-06-04 12:14:13 +00:00
|
|
|
ast_str_append(&out, 0, "%d day%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
2007-07-18 19:47:20 +00:00
|
|
|
if (timeval.tv_sec > HOUR) {
|
|
|
|
x = (timeval.tv_sec / HOUR);
|
|
|
|
timeval.tv_sec -= (x * HOUR);
|
2015-06-04 12:14:13 +00:00
|
|
|
ast_str_append(&out, 0, "%d hour%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
2007-07-18 19:47:20 +00:00
|
|
|
if (timeval.tv_sec > MINUTE) {
|
|
|
|
x = (timeval.tv_sec / MINUTE);
|
|
|
|
timeval.tv_sec -= (x * MINUTE);
|
2015-06-04 12:14:13 +00:00
|
|
|
ast_str_append(&out, 0, "%d minute%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
2007-07-18 19:47:20 +00:00
|
|
|
x = timeval.tv_sec;
|
2015-06-04 12:14:13 +00:00
|
|
|
if (x > 0 || ast_str_strlen(out) == 0) {
|
|
|
|
/* if there is nothing, print 0 seconds */
|
|
|
|
ast_str_append(&out, 0, "%d second%s", x, ESS(x));
|
|
|
|
}
|
2016-02-18 04:58:01 +00:00
|
|
|
ast_cli(fd, "%s%s\n", prefix, ast_str_buffer(out));
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
static struct ast_cli_entry *cli_next(struct ast_cli_entry *e)
|
|
|
|
{
|
|
|
|
if (e) {
|
|
|
|
return AST_LIST_NEXT(e, list);
|
|
|
|
} else {
|
|
|
|
return AST_LIST_FIRST(&helpers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-15 14:11:28 +00:00
|
|
|
static char * handle_showuptime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2003-05-02 15:37:34 +00:00
|
|
|
{
|
2007-07-18 19:47:20 +00:00
|
|
|
struct timeval curtime = ast_tvnow();
|
2006-11-14 16:09:08 +00:00
|
|
|
int printsec;
|
|
|
|
|
2006-11-15 14:11:28 +00:00
|
|
|
switch (cmd) {
|
2008-03-04 23:04:29 +00:00
|
|
|
case CLI_INIT:
|
2007-06-27 22:27:09 +00:00
|
|
|
e->command = "core show uptime [seconds]";
|
2006-11-15 14:11:28 +00:00
|
|
|
e->usage =
|
2006-11-14 16:09:08 +00:00
|
|
|
"Usage: core show uptime [seconds]\n"
|
|
|
|
" Shows Asterisk uptime information.\n"
|
|
|
|
" The seconds word returns the uptime in seconds only.\n";
|
2006-11-15 14:11:28 +00:00
|
|
|
return NULL;
|
2005-02-05 16:49:14 +00:00
|
|
|
|
2006-11-14 16:09:08 +00:00
|
|
|
case CLI_GENERATE:
|
2007-06-27 22:27:09 +00:00
|
|
|
return NULL;
|
2006-11-14 16:09:08 +00:00
|
|
|
}
|
|
|
|
/* regular handler */
|
2007-06-27 22:27:09 +00:00
|
|
|
if (a->argc == e->args && !strcasecmp(a->argv[e->args-1],"seconds"))
|
2006-11-14 16:09:08 +00:00
|
|
|
printsec = 1;
|
2007-06-27 22:27:09 +00:00
|
|
|
else if (a->argc == e->args-1)
|
2006-11-14 16:09:08 +00:00
|
|
|
printsec = 0;
|
|
|
|
else
|
2006-11-15 14:11:28 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
2016-02-18 04:58:01 +00:00
|
|
|
if (ast_startuptime.tv_sec) {
|
|
|
|
print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime: ", printsec);
|
|
|
|
}
|
|
|
|
if (ast_lastreloadtime.tv_sec) {
|
|
|
|
print_uptimestr(a->fd, ast_tvsub(curtime, ast_lastreloadtime), "Last reload: ", printsec);
|
|
|
|
}
|
2006-11-15 14:11:28 +00:00
|
|
|
return CLI_SUCCESS;
|
2003-05-02 15:37:34 +00:00
|
|
|
}
|
|
|
|
|
2006-11-15 14:11:28 +00:00
|
|
|
static char *handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *like;
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
|
2006-11-15 14:11:28 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
2006-11-17 22:02:15 +00:00
|
|
|
e->command = "module show [like]";
|
2006-11-15 14:11:28 +00:00
|
|
|
e->usage =
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
"Usage: module show [like keyword]\n"
|
|
|
|
" Shows Asterisk modules currently in use, and usage statistics.\n";
|
2006-11-15 14:11:28 +00:00
|
|
|
return NULL;
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
|
|
|
|
case CLI_GENERATE:
|
2017-10-30 22:30:18 +00:00
|
|
|
if (a->pos == e->args) {
|
|
|
|
return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOADED);
|
|
|
|
} else {
|
2006-11-15 14:11:28 +00:00
|
|
|
return NULL;
|
2017-10-30 22:30:18 +00:00
|
|
|
}
|
2004-10-14 04:38:29 +00:00
|
|
|
}
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
/* all the above return, so we proceed with the handler.
|
|
|
|
* we are guaranteed to have argc >= e->args
|
|
|
|
*/
|
2006-11-17 22:02:15 +00:00
|
|
|
if (a->argc == e->args - 1)
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
like = "";
|
2006-11-17 22:02:15 +00:00
|
|
|
else if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args-1], "like") )
|
|
|
|
like = a->argv[e->args];
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
else
|
2006-11-15 14:11:28 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2003-08-13 15:25:16 +00:00
|
|
|
ast_mutex_lock(&climodentrylock);
|
2006-11-15 14:11:28 +00:00
|
|
|
climodentryfd = a->fd; /* global, protected by climodentrylock */
|
2014-07-25 16:47:17 +00:00
|
|
|
ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count", "Status", "Support Level");
|
2006-11-15 14:11:28 +00:00
|
|
|
ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
|
1999-12-19 22:38:55 +00:00
|
|
|
climodentryfd = -1;
|
2003-08-13 15:25:16 +00:00
|
|
|
ast_mutex_unlock(&climodentrylock);
|
2007-11-28 20:27:40 +00:00
|
|
|
return CLI_SUCCESS;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2005-08-08 01:45:29 +00:00
|
|
|
#undef MODLIST_FORMAT
|
|
|
|
#undef MODLIST_FORMAT2
|
1999-12-19 22:38:55 +00:00
|
|
|
|
2007-12-07 16:11:05 +00:00
|
|
|
static char *handle_showcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
2017-02-11 15:57:03 +00:00
|
|
|
static const char * const completions[] = { "seconds", NULL };
|
2007-12-07 16:11:05 +00:00
|
|
|
struct timeval curtime = ast_tvnow();
|
|
|
|
int showuptime, printsec;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "core show calls [uptime]";
|
|
|
|
e->usage =
|
2017-02-11 15:57:03 +00:00
|
|
|
"Usage: core show calls [uptime [seconds]]\n"
|
2007-12-07 16:11:05 +00:00
|
|
|
" Lists number of currently active calls and total number of calls\n"
|
|
|
|
" processed through PBX since last restart. If 'uptime' is specified\n"
|
|
|
|
" the system uptime is also displayed. If 'seconds' is specified in\n"
|
|
|
|
" addition to 'uptime', the system uptime is displayed in seconds.\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
case CLI_GENERATE:
|
|
|
|
if (a->pos != e->args)
|
|
|
|
return NULL;
|
2017-02-11 15:57:03 +00:00
|
|
|
return ast_cli_complete(a->word, completions, a->n);
|
2007-12-07 16:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* regular handler */
|
|
|
|
if (a->argc >= e->args && !strcasecmp(a->argv[e->args-1],"uptime")) {
|
|
|
|
showuptime = 1;
|
|
|
|
|
|
|
|
if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
|
|
|
|
printsec = 1;
|
|
|
|
else if (a->argc == e->args)
|
|
|
|
printsec = 0;
|
|
|
|
else
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
} else if (a->argc == e->args-1) {
|
|
|
|
showuptime = 0;
|
|
|
|
printsec = 0;
|
|
|
|
} else
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
|
2013-08-05 14:35:00 +00:00
|
|
|
if (ast_option_maxcalls) {
|
2007-12-07 16:11:05 +00:00
|
|
|
ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
|
2013-08-05 14:35:00 +00:00
|
|
|
ast_active_calls(), ast_option_maxcalls, ESS(ast_active_calls()),
|
|
|
|
((double)ast_active_calls() / (double)ast_option_maxcalls) * 100.0);
|
2007-12-07 16:11:05 +00:00
|
|
|
} else {
|
|
|
|
ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
|
|
|
|
}
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2007-12-07 16:11:05 +00:00
|
|
|
ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
|
|
|
|
|
|
|
|
if (ast_startuptime.tv_sec && showuptime) {
|
2016-02-18 04:58:01 +00:00
|
|
|
print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime: ", printsec);
|
2007-12-07 16:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-11-15 17:05:55 +00:00
|
|
|
static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2005-08-08 01:45:29 +00:00
|
|
|
#define FORMAT_STRING "%-20.20s %-20.20s %-7.7s %-30.30s\n"
|
|
|
|
#define FORMAT_STRING2 "%-20.20s %-20.20s %-7.7s %-30.30s\n"
|
2009-06-26 15:28:53 +00:00
|
|
|
#define CONCISE_FORMAT_STRING "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
|
|
|
|
#define VERBOSE_FORMAT_STRING "%-20.20s %-20.20s %-16.16s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
|
|
|
|
#define VERBOSE_FORMAT_STRING2 "%-20.20s %-20.20s %-16.16s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
|
2005-08-08 01:45:29 +00:00
|
|
|
|
2017-11-16 23:25:04 +00:00
|
|
|
struct ao2_container *channels;
|
2013-07-08 19:19:55 +00:00
|
|
|
struct ao2_iterator it_chans;
|
2018-10-10 14:28:18 +00:00
|
|
|
struct ast_channel_snapshot *cs;
|
2007-01-29 17:49:04 +00:00
|
|
|
int numchans = 0, concise = 0, verbose = 0, count = 0;
|
2004-06-11 00:18:30 +00:00
|
|
|
|
2006-11-15 17:05:55 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
2007-01-29 17:49:04 +00:00
|
|
|
e->command = "core show channels [concise|verbose|count]";
|
2006-11-15 17:05:55 +00:00
|
|
|
e->usage =
|
2007-01-29 17:49:04 +00:00
|
|
|
"Usage: core show channels [concise|verbose|count]\n"
|
2006-11-15 17:05:55 +00:00
|
|
|
" Lists currently defined channels and some information about them. If\n"
|
|
|
|
" 'concise' is specified, the format is abridged and in a more easily\n"
|
|
|
|
" machine parsable format. If 'verbose' is specified, the output includes\n"
|
2007-01-29 17:49:04 +00:00
|
|
|
" more and longer fields. If 'count' is specified only the channel and call\n"
|
2007-11-26 19:24:23 +00:00
|
|
|
" count is output.\n"
|
|
|
|
" The 'concise' option is deprecated and will be removed from future versions\n"
|
|
|
|
" of Asterisk.\n";
|
2006-11-15 17:05:55 +00:00
|
|
|
return NULL;
|
2004-06-11 00:18:30 +00:00
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
2006-11-15 17:05:55 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
if (a->argc == e->args) {
|
2009-05-21 21:13:09 +00:00
|
|
|
if (!strcasecmp(a->argv[e->args-1],"concise"))
|
2006-11-15 17:05:55 +00:00
|
|
|
concise = 1;
|
2009-05-21 21:13:09 +00:00
|
|
|
else if (!strcasecmp(a->argv[e->args-1],"verbose"))
|
2006-11-15 17:05:55 +00:00
|
|
|
verbose = 1;
|
2009-05-21 21:13:09 +00:00
|
|
|
else if (!strcasecmp(a->argv[e->args-1],"count"))
|
2007-01-29 17:49:04 +00:00
|
|
|
count = 1;
|
2006-11-15 17:05:55 +00:00
|
|
|
else
|
|
|
|
return CLI_SHOWUSAGE;
|
2006-11-17 11:12:13 +00:00
|
|
|
} else if (a->argc != e->args - 1)
|
2006-11-15 17:05:55 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
2005-08-08 01:45:29 +00:00
|
|
|
|
2018-10-10 14:28:18 +00:00
|
|
|
channels = ast_channel_cache_by_name();
|
2013-07-08 19:19:55 +00:00
|
|
|
|
2007-01-29 17:49:04 +00:00
|
|
|
if (!count) {
|
|
|
|
if (!concise && !verbose)
|
2009-05-21 21:13:09 +00:00
|
|
|
ast_cli(a->fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
|
2007-01-29 17:49:04 +00:00
|
|
|
else if (verbose)
|
2012-03-22 19:51:16 +00:00
|
|
|
ast_cli(a->fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
|
2013-05-21 18:00:22 +00:00
|
|
|
"CallerID", "Duration", "Accountcode", "PeerAccount", "BridgeID");
|
2007-01-29 17:49:04 +00:00
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
|
2013-07-08 19:19:55 +00:00
|
|
|
it_chans = ao2_iterator_init(channels, 0);
|
2018-10-10 14:28:18 +00:00
|
|
|
for (; (cs = ao2_iterator_next(&it_chans)); ao2_ref(cs, -1)) {
|
2017-07-28 01:58:22 +00:00
|
|
|
char durbuf[16] = "-";
|
2006-11-15 17:17:07 +00:00
|
|
|
|
2007-01-29 17:49:04 +00:00
|
|
|
if (!count) {
|
2018-11-07 17:18:34 +00:00
|
|
|
if ((concise || verbose) && !ast_tvzero(cs->base->creationtime)) {
|
|
|
|
int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);
|
2007-01-29 17:49:04 +00:00
|
|
|
if (verbose) {
|
|
|
|
int durh = duration / 3600;
|
|
|
|
int durm = (duration % 3600) / 60;
|
|
|
|
int durs = duration % 60;
|
|
|
|
snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
|
|
|
|
} else {
|
|
|
|
snprintf(durbuf, sizeof(durbuf), "%d", duration);
|
2012-03-22 19:51:16 +00:00
|
|
|
}
|
2007-01-29 17:49:04 +00:00
|
|
|
}
|
|
|
|
if (concise) {
|
2018-11-07 17:18:34 +00:00
|
|
|
ast_cli(a->fd, CONCISE_FORMAT_STRING, cs->base->name, cs->dialplan->context, cs->dialplan->exten, cs->dialplan->priority, ast_state2str(cs->state),
|
|
|
|
S_OR(cs->dialplan->appl, "(None)"),
|
|
|
|
cs->dialplan->data,
|
|
|
|
cs->caller->number,
|
|
|
|
cs->base->accountcode,
|
|
|
|
cs->peer->account,
|
2013-07-08 19:19:55 +00:00
|
|
|
cs->amaflags,
|
2007-01-29 17:49:04 +00:00
|
|
|
durbuf,
|
2018-11-07 17:18:34 +00:00
|
|
|
cs->bridge->id,
|
|
|
|
cs->base->uniqueid);
|
2007-01-29 17:49:04 +00:00
|
|
|
} else if (verbose) {
|
2018-11-07 17:18:34 +00:00
|
|
|
ast_cli(a->fd, VERBOSE_FORMAT_STRING, cs->base->name, cs->dialplan->context, cs->dialplan->exten, cs->dialplan->priority, ast_state2str(cs->state),
|
|
|
|
S_OR(cs->dialplan->appl, "(None)"),
|
|
|
|
S_OR(cs->dialplan->data, "(Empty)"),
|
|
|
|
cs->caller->number,
|
2007-01-29 17:49:04 +00:00
|
|
|
durbuf,
|
2018-11-07 17:18:34 +00:00
|
|
|
cs->base->accountcode,
|
|
|
|
cs->peer->account,
|
|
|
|
cs->bridge->id);
|
2005-08-08 01:45:29 +00:00
|
|
|
} else {
|
2007-01-29 17:49:04 +00:00
|
|
|
char locbuf[40] = "(None)";
|
|
|
|
char appdata[40] = "(None)";
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2018-11-07 17:18:34 +00:00
|
|
|
if (!ast_strlen_zero(cs->dialplan->context) && !ast_strlen_zero(cs->dialplan->exten)) {
|
|
|
|
snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->dialplan->exten, cs->dialplan->context, cs->dialplan->priority);
|
2015-10-22 14:44:43 +00:00
|
|
|
}
|
2018-11-07 17:18:34 +00:00
|
|
|
if (!ast_strlen_zero(cs->dialplan->appl)) {
|
|
|
|
snprintf(appdata, sizeof(appdata), "%s(%s)", cs->dialplan->appl, S_OR(cs->dialplan->data, ""));
|
2015-10-22 14:44:43 +00:00
|
|
|
}
|
2018-11-07 17:18:34 +00:00
|
|
|
ast_cli(a->fd, FORMAT_STRING, cs->base->name, locbuf, ast_state2str(cs->state), appdata);
|
2007-01-29 17:49:04 +00:00
|
|
|
}
|
2005-08-08 01:45:29 +00:00
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
2013-07-08 19:19:55 +00:00
|
|
|
ao2_iterator_destroy(&it_chans);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
2005-08-08 01:45:29 +00:00
|
|
|
if (!concise) {
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
numchans = ast_active_channels();
|
2009-05-21 21:13:09 +00:00
|
|
|
ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
|
2013-08-05 14:35:00 +00:00
|
|
|
if (ast_option_maxcalls)
|
2009-05-21 21:13:09 +00:00
|
|
|
ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
|
2013-08-05 14:35:00 +00:00
|
|
|
ast_active_calls(), ast_option_maxcalls, ESS(ast_active_calls()),
|
|
|
|
((double)ast_active_calls() / (double)ast_option_maxcalls) * 100.0);
|
2005-05-18 01:49:13 +00:00
|
|
|
else
|
2009-05-21 21:13:09 +00:00
|
|
|
ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
|
2007-12-07 16:11:05 +00:00
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
|
2005-05-18 01:49:13 +00:00
|
|
|
}
|
2017-11-16 23:25:04 +00:00
|
|
|
ao2_ref(channels, -1);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
2006-11-15 17:05:55 +00:00
|
|
|
return CLI_SUCCESS;
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2005-08-08 01:45:29 +00:00
|
|
|
#undef FORMAT_STRING
|
|
|
|
#undef FORMAT_STRING2
|
|
|
|
#undef CONCISE_FORMAT_STRING
|
|
|
|
#undef VERBOSE_FORMAT_STRING
|
|
|
|
#undef VERBOSE_FORMAT_STRING2
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
static char *handle_softhangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2001-05-09 03:11:22 +00:00
|
|
|
{
|
2017-02-11 15:57:03 +00:00
|
|
|
struct ast_channel *c = NULL;
|
|
|
|
static const char * const completions[] = { "all", NULL };
|
|
|
|
char *complete;
|
2007-10-11 19:03:06 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
2008-09-28 23:32:14 +00:00
|
|
|
e->command = "channel request hangup";
|
2007-10-11 19:03:06 +00:00
|
|
|
e->usage =
|
2010-05-19 15:12:18 +00:00
|
|
|
"Usage: channel request hangup <channel>|<all>\n"
|
2007-10-11 19:03:06 +00:00
|
|
|
" Request that a channel be hung up. The hangup takes effect\n"
|
2010-05-19 15:12:18 +00:00
|
|
|
" the next time the driver reads or writes from the channel.\n"
|
|
|
|
" If 'all' is specified instead of a channel name, all channels\n"
|
|
|
|
" will see the hangup request.\n";
|
2007-10-11 19:03:06 +00:00
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
2017-02-11 15:57:03 +00:00
|
|
|
if (a->pos != e->args) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
complete = ast_cli_complete(a->word, completions, a->n);
|
|
|
|
if (!complete) {
|
|
|
|
complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
|
|
|
|
}
|
|
|
|
return complete;
|
2007-10-11 19:03:06 +00:00
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
|
|
|
if (a->argc != 4) {
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
|
|
|
|
2010-05-19 15:12:18 +00:00
|
|
|
if (!strcasecmp(a->argv[3], "all")) {
|
|
|
|
struct ast_channel_iterator *iter = NULL;
|
2010-05-19 15:39:39 +00:00
|
|
|
if (!(iter = ast_channel_iterator_all_new())) {
|
2010-05-19 15:12:18 +00:00
|
|
|
return CLI_FAILURE;
|
|
|
|
}
|
|
|
|
for (; iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
|
|
|
|
ast_channel_lock(c);
|
2012-01-09 22:15:50 +00:00
|
|
|
ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
|
2010-05-19 15:12:18 +00:00
|
|
|
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
|
|
|
|
ast_channel_unlock(c);
|
|
|
|
}
|
|
|
|
ast_channel_iterator_destroy(iter);
|
|
|
|
} else if ((c = ast_channel_get_by_name(a->argv[3]))) {
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
ast_channel_lock(c);
|
2012-01-09 22:15:50 +00:00
|
|
|
ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
|
2005-06-06 02:29:18 +00:00
|
|
|
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
|
2006-04-29 14:50:18 +00:00
|
|
|
ast_channel_unlock(c);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
c = ast_channel_unref(c);
|
|
|
|
} else {
|
2008-10-17 17:31:07 +00:00
|
|
|
ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SUCCESS;
|
2001-05-09 03:11:22 +00:00
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
/*! \brief handles CLI command 'cli show permissions' */
|
|
|
|
static char *handle_cli_show_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
struct usergroup_cli_perm *cp;
|
|
|
|
struct cli_perm *perm;
|
|
|
|
struct passwd *pw = NULL;
|
|
|
|
struct group *gr = NULL;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "cli show permissions";
|
|
|
|
e->usage =
|
|
|
|
"Usage: cli show permissions\n"
|
|
|
|
" Shows CLI configured permissions.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
AST_RWLIST_RDLOCK(&cli_perms);
|
|
|
|
AST_LIST_TRAVERSE(&cli_perms, cp, list) {
|
|
|
|
if (cp->uid >= 0) {
|
|
|
|
pw = getpwuid(cp->uid);
|
|
|
|
if (pw) {
|
|
|
|
ast_cli(a->fd, "user: %s [uid=%d]\n", pw->pw_name, cp->uid);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gr = getgrgid(cp->gid);
|
|
|
|
if (gr) {
|
|
|
|
ast_cli(a->fd, "group: %s [gid=%d]\n", gr->gr_name, cp->gid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_cli(a->fd, "Permissions:\n");
|
|
|
|
if (cp->perms) {
|
|
|
|
AST_LIST_TRAVERSE(cp->perms, perm, list) {
|
|
|
|
ast_cli(a->fd, "\t%s -> %s\n", perm->permit ? "permit" : "deny", perm->command);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_cli(a->fd, "\n");
|
|
|
|
}
|
|
|
|
AST_RWLIST_UNLOCK(&cli_perms);
|
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief handles CLI command 'cli reload permissions' */
|
|
|
|
static char *handle_cli_reload_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "cli reload permissions";
|
|
|
|
e->usage =
|
|
|
|
"Usage: cli reload permissions\n"
|
|
|
|
" Reload the 'cli_permissions.conf' file.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_cli_perms_init(1);
|
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief handles CLI command 'cli check permissions' */
|
|
|
|
static char *handle_cli_check_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
struct passwd *pw = NULL;
|
|
|
|
struct group *gr;
|
|
|
|
int gid = -1, uid = -1;
|
|
|
|
char command[AST_MAX_ARGS] = "";
|
|
|
|
struct ast_cli_entry *ce = NULL;
|
|
|
|
int found = 0;
|
|
|
|
char *group, *tmp;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "cli check permissions";
|
|
|
|
e->usage =
|
|
|
|
"Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
|
|
|
|
" Check permissions config for a user@group or list the allowed commands for the specified user.\n"
|
|
|
|
" The username or the groupname may be omitted.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
if (a->pos >= 4) {
|
|
|
|
return ast_cli_generator(a->line + strlen("cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->argc < 4) {
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = ast_strdupa(a->argv[3]);
|
|
|
|
group = strchr(tmp, '@');
|
|
|
|
if (group) {
|
|
|
|
gr = getgrnam(&group[1]);
|
|
|
|
if (!gr) {
|
|
|
|
ast_cli(a->fd, "Unknown group '%s'\n", &group[1]);
|
|
|
|
return CLI_FAILURE;
|
|
|
|
}
|
|
|
|
group[0] = '\0';
|
|
|
|
gid = gr->gr_gid;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!group && ast_strlen_zero(tmp)) {
|
|
|
|
ast_cli(a->fd, "You didn't supply a username\n");
|
|
|
|
} else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
|
|
|
|
ast_cli(a->fd, "Unknown user '%s'\n", tmp);
|
|
|
|
return CLI_FAILURE;
|
|
|
|
} else if (pw) {
|
|
|
|
uid = pw->pw_uid;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->argc == 4) {
|
|
|
|
while ((ce = cli_next(ce))) {
|
|
|
|
/* Hide commands that start with '_' */
|
|
|
|
if (ce->_full_cmd[0] == '_') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (cli_has_permissions(uid, gid, ce->_full_cmd)) {
|
|
|
|
ast_cli(a->fd, "%30.30s %s\n", ce->_full_cmd, S_OR(ce->summary, "<no description available>"));
|
|
|
|
found++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
ast_cli(a->fd, "You are not allowed to run any command on Asterisk\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ast_join(command, sizeof(command), a->argv + 4);
|
|
|
|
ast_cli(a->fd, "%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ? "User" : "Group", tmp,
|
|
|
|
group && uid >= 0 ? "@" : "",
|
|
|
|
group ? &group[1] : "",
|
|
|
|
cli_has_permissions(uid, gid, command) ? "allowed" : "not allowed", command);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-18 22:17:31 +00:00
|
|
|
static char *__ast_cli_generator(const char *text, const char *word, int state, int lock);
|
2001-05-09 03:11:22 +00:00
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
static char *handle_commandmatchesarray(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2003-01-30 15:03:20 +00:00
|
|
|
{
|
2004-10-14 04:12:05 +00:00
|
|
|
char *buf, *obuf;
|
2004-04-06 07:42:01 +00:00
|
|
|
int buflen = 2048;
|
2003-01-30 15:03:20 +00:00
|
|
|
int len = 0;
|
|
|
|
char **matches;
|
2004-10-14 04:12:05 +00:00
|
|
|
int x, matchlen;
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "_command matchesarray";
|
2012-03-22 19:51:16 +00:00
|
|
|
e->usage =
|
2007-10-11 19:03:06 +00:00
|
|
|
"Usage: _command matchesarray \"<line>\" text \n"
|
|
|
|
" This function is used internally to help with command completion and should.\n"
|
|
|
|
" never be called by the user directly.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-01-30 15:03:20 +00:00
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
if (a->argc != 4)
|
|
|
|
return CLI_SHOWUSAGE;
|
2006-02-09 16:59:50 +00:00
|
|
|
if (!(buf = ast_malloc(buflen)))
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_FAILURE;
|
2003-01-30 15:03:20 +00:00
|
|
|
buf[len] = '\0';
|
2007-10-11 19:03:06 +00:00
|
|
|
matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
|
2003-01-30 15:03:20 +00:00
|
|
|
if (matches) {
|
|
|
|
for (x=0; matches[x]; x++) {
|
2004-10-14 04:12:05 +00:00
|
|
|
matchlen = strlen(matches[x]) + 1;
|
|
|
|
if (len + matchlen >= buflen) {
|
|
|
|
buflen += matchlen * 3;
|
|
|
|
obuf = buf;
|
2012-03-22 19:51:16 +00:00
|
|
|
if (!(buf = ast_realloc(obuf, buflen)))
|
2006-02-09 16:59:50 +00:00
|
|
|
/* Memory allocation failure... Just free old buffer and be done */
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(obuf);
|
2004-04-06 07:42:01 +00:00
|
|
|
}
|
2004-10-14 04:12:05 +00:00
|
|
|
if (buf)
|
|
|
|
len += sprintf( buf + len, "%s ", matches[x]);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(matches[x]);
|
2003-04-08 13:45:36 +00:00
|
|
|
matches[x] = NULL;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(matches);
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
|
2003-01-30 15:03:20 +00:00
|
|
|
if (buf) {
|
2007-10-11 19:03:06 +00:00
|
|
|
ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(buf);
|
2003-01-30 15:03:20 +00:00
|
|
|
} else
|
2007-10-11 19:03:06 +00:00
|
|
|
ast_cli(a->fd, "NULL\n");
|
2003-01-30 15:03:20 +00:00
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SUCCESS;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
struct channel_set_debug_args {
|
|
|
|
int fd;
|
|
|
|
int is_off;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int channel_set_debug(void *obj, void *arg, void *data, int flags)
|
|
|
|
{
|
|
|
|
struct ast_channel *chan = obj;
|
|
|
|
struct channel_set_debug_args *args = data;
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
2012-02-20 23:43:27 +00:00
|
|
|
if (!(ast_channel_fin(chan) & DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
if (args->is_off) {
|
2012-02-20 23:43:27 +00:00
|
|
|
ast_channel_fin_set(chan, ast_channel_fin(chan) & ~DEBUGCHAN_FLAG);
|
|
|
|
ast_channel_fout_set(chan, ast_channel_fout(chan) & ~DEBUGCHAN_FLAG);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
} else {
|
2012-02-20 23:43:27 +00:00
|
|
|
ast_channel_fin_set(chan, ast_channel_fin(chan) | DEBUGCHAN_FLAG);
|
|
|
|
ast_channel_fout_set(chan, ast_channel_fout(chan) | DEBUGCHAN_FLAG);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
|
|
|
ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
|
2012-01-09 22:15:50 +00:00
|
|
|
ast_channel_name(chan));
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-11-15 16:13:30 +00:00
|
|
|
static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-11-10 17:01:06 +00:00
|
|
|
{
|
|
|
|
struct ast_channel *c = NULL;
|
2017-02-11 15:57:03 +00:00
|
|
|
static const char * const completions_all[] = { "all", NULL };
|
|
|
|
static const char * const completions_off[] = { "off", NULL };
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
struct channel_set_debug_args args = {
|
|
|
|
.fd = a->fd,
|
|
|
|
};
|
2006-11-10 17:01:06 +00:00
|
|
|
|
2006-11-15 16:13:30 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "core set debug channel";
|
|
|
|
e->usage =
|
|
|
|
"Usage: core set debug channel <all|channel> [off]\n"
|
|
|
|
" Enables/disables debugging on all or on a specific channel.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
2017-02-11 15:57:03 +00:00
|
|
|
if (a->pos == 4) {
|
|
|
|
char *complete = ast_cli_complete(a->word, completions_all, a->n);
|
|
|
|
if (!complete) {
|
|
|
|
complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
|
|
|
|
}
|
|
|
|
return complete;
|
|
|
|
} else if (a->pos == 5) {
|
|
|
|
return ast_cli_complete(a->word, completions_off, a->n);
|
|
|
|
}
|
2017-12-18 18:23:46 +00:00
|
|
|
|
|
|
|
return NULL;
|
2006-11-15 16:13:30 +00:00
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
if (cmd == (CLI_HANDLER + 1000)) {
|
|
|
|
/* called from handle_nodebugchan_deprecated */
|
|
|
|
args.is_off = 1;
|
|
|
|
} else if (a->argc == e->args + 2) {
|
|
|
|
/* 'core set debug channel {all|chan_id}' */
|
2006-11-15 16:13:30 +00:00
|
|
|
if (!strcasecmp(a->argv[e->args + 1], "off"))
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
args.is_off = 1;
|
2006-11-15 16:13:30 +00:00
|
|
|
else
|
|
|
|
return CLI_SHOWUSAGE;
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
} else if (a->argc != e->args + 1) {
|
2006-11-15 16:13:30 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
2006-11-10 17:01:06 +00:00
|
|
|
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
if (!strcasecmp("all", a->argv[e->args])) {
|
|
|
|
if (args.is_off) {
|
2006-11-10 17:01:06 +00:00
|
|
|
global_fin &= ~DEBUGCHAN_FLAG;
|
|
|
|
global_fout &= ~DEBUGCHAN_FLAG;
|
|
|
|
} else {
|
|
|
|
global_fin |= DEBUGCHAN_FLAG;
|
|
|
|
global_fout |= DEBUGCHAN_FLAG;
|
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
ast_channel_callback(channel_set_debug, NULL, &args, OBJ_NODATA | OBJ_MULTIPLE);
|
2006-11-10 17:01:06 +00:00
|
|
|
} else {
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
|
|
|
|
channel_set_debug(c, NULL, &args, 0);
|
|
|
|
ast_channel_unref(c);
|
|
|
|
} else {
|
2006-11-15 16:13:30 +00:00
|
|
|
ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
|
2006-11-10 17:01:06 +00:00
|
|
|
}
|
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
|
|
|
ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");
|
|
|
|
|
2007-11-28 20:27:40 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-11-10 17:01:06 +00:00
|
|
|
}
|
|
|
|
|
2006-11-15 16:13:30 +00:00
|
|
|
static char *handle_nodebugchan_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-09-18 19:54:18 +00:00
|
|
|
{
|
2006-11-15 16:13:30 +00:00
|
|
|
char *res;
|
2009-05-21 21:13:09 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
2006-11-15 16:13:30 +00:00
|
|
|
e->command = "no debug channel";
|
2009-05-21 21:13:09 +00:00
|
|
|
return NULL;
|
|
|
|
case CLI_HANDLER:
|
|
|
|
/* exit out of switch statement */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->argc != e->args + 1)
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
|
|
|
|
/* add a 'magic' value to the CLI_HANDLER command so that
|
|
|
|
* handle_core_set_debug_channel() will act as if 'off'
|
|
|
|
* had been specified as part of the command
|
|
|
|
*/
|
|
|
|
res = handle_core_set_debug_channel(e, CLI_HANDLER + 1000, a);
|
|
|
|
|
2006-11-15 16:13:30 +00:00
|
|
|
return res;
|
2006-09-18 19:54:18 +00:00
|
|
|
}
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
struct ast_channel *chan;
|
2004-08-03 17:48:18 +00:00
|
|
|
struct timeval now;
|
2004-12-26 11:08:34 +00:00
|
|
|
char cdrtime[256];
|
2013-07-08 19:19:55 +00:00
|
|
|
struct ast_str *obuf;/*!< Buffer for CDR variables. */
|
2011-11-11 18:02:52 +00:00
|
|
|
struct ast_str *output;/*!< Accumulation buffer for all output. */
|
2004-08-03 17:48:18 +00:00
|
|
|
long elapsed_seconds=0;
|
2004-09-03 03:44:35 +00:00
|
|
|
int hour=0, min=0, sec=0;
|
2013-07-08 19:19:55 +00:00
|
|
|
struct ast_var_t *var;
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
struct ast_str *write_transpath = ast_str_alloca(256);
|
|
|
|
struct ast_str *read_transpath = ast_str_alloca(256);
|
2015-11-09 09:01:41 +00:00
|
|
|
struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
struct ast_bridge *bridge;
|
2015-03-13 01:12:35 +00:00
|
|
|
ast_callid callid;
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
char callid_buf[32];
|
2017-02-22 14:32:23 +00:00
|
|
|
int stream_num;
|
2007-10-11 19:03:06 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "core show channel";
|
2012-03-22 19:51:16 +00:00
|
|
|
e->usage =
|
2007-10-11 19:03:06 +00:00
|
|
|
"Usage: core show channel <channel>\n"
|
|
|
|
" Shows lots of information about the specified channel.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
|
|
|
|
}
|
2012-03-22 19:51:16 +00:00
|
|
|
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
if (a->argc != 4) {
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SHOWUSAGE;
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
|
|
|
|
2011-11-11 18:02:52 +00:00
|
|
|
obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
|
|
|
|
if (!obuf) {
|
|
|
|
return CLI_FAILURE;
|
|
|
|
}
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
|
|
|
|
chan = ast_channel_get_by_name(a->argv[3]);
|
|
|
|
if (!chan) {
|
|
|
|
ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
|
2017-12-19 02:12:47 +00:00
|
|
|
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-12-19 02:12:47 +00:00
|
|
|
output = ast_str_create(8192);
|
|
|
|
if (!output) {
|
|
|
|
ast_channel_unref(chan);
|
|
|
|
|
|
|
|
return CLI_FAILURE;
|
|
|
|
}
|
|
|
|
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
now = ast_tvnow();
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
|
|
|
if (!ast_tvzero(ast_channel_creationtime(chan))) {
|
|
|
|
elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
|
2005-06-06 02:29:18 +00:00
|
|
|
hour = elapsed_seconds / 3600;
|
|
|
|
min = (elapsed_seconds % 3600) / 60;
|
|
|
|
sec = elapsed_seconds % 60;
|
|
|
|
snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
} else {
|
2005-07-10 22:56:21 +00:00
|
|
|
strcpy(cdrtime, "N/A");
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
|
|
|
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
|
|
|
|
ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
|
|
|
|
|
|
|
|
bridge = ast_channel_get_bridge(chan);
|
2014-09-05 19:39:04 +00:00
|
|
|
callid_buf[0] = '\0';
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
callid = ast_channel_callid(chan);
|
|
|
|
if (callid) {
|
|
|
|
ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
|
|
|
|
}
|
|
|
|
|
2011-11-11 18:02:52 +00:00
|
|
|
ast_str_append(&output, 0,
|
2005-06-06 02:29:18 +00:00
|
|
|
" -- General --\n"
|
|
|
|
" Name: %s\n"
|
|
|
|
" Type: %s\n"
|
|
|
|
" UniqueID: %s\n"
|
2009-06-26 15:28:53 +00:00
|
|
|
" LinkedID: %s\n"
|
2005-06-06 02:29:18 +00:00
|
|
|
" Caller ID: %s\n"
|
|
|
|
" Caller ID Name: %s\n"
|
2011-04-11 22:28:43 +00:00
|
|
|
"Connected Line ID: %s\n"
|
|
|
|
"Connected Line ID Name: %s\n"
|
Add private representation of caller, connected and redirecting party ids.
This patch adds the feature "Private representation of caller, connected
and redirecting party ids", as previously discussed with us (DATUS) and
Digium.
1. Feature motivation
Until now it is quite difficult to modify a party number or name which can
only be seen by exactly one particular instantiated technology channel
subscriber. One example where a modified party number or name on one
channel is spread over several channels are supplementary services like
call transfer or pickup. To implement these features Asterisk internally
copies caller and connected ids from one channel to another. Another
example are extension subscriptions. The monitoring entities (watchers)
are notified of state changes and - if desired - of party numbers or names
which represent the involving call parties. One major feature where a
private representation of party names is essentially needed, i.e. where a
party name shall be exclusively signaled to only one particular user, is a
private user-specific name resolution for party numbers. A lookup in a
private destination-dependent telephone book shall provide party names
which cannot be seen by any other user at any time.
2. Feature Description
This feature comes along with the implementation of additional private
party id elements for caller id, connected id and redirecting ids inside
Asterisk channels.
The private party id elements can be read or set by the user using
Asterisk dialplan functions.
When a technology channel is initiating a call, receives an internal
connected-line update event, or receives an internal redirecting update
event, it merges the corresponding public id with the private id to create
an effective party id. The effective party id is then used for protocol
signaling.
The channel technologies which initially support the private id
representation with this patch are SIP (chan_sip), mISDN (chan_misdn) and
PRI (chan_dahdi).
Once a private name or number on a channel is set and (implicitly) made
valid, it is generally used for any further protocol signaling until it is
rewritten or invalidated.
To simplify the invalidation of private ids all internally generated
connected/redirecting update events and also all connected/redirecting
update events which are generated by technology channels -- receiving
regarding protocol information - automatically trigger the invalidation of
private ids.
If not using the private party id representation feature at all, i.e. if
using only the 'regular' caller-id, connected and redirecting related
functions, the current characteristic of Asterisk is not affected by the
new extended functionality.
3. User interface Description
To grant access to the private name and number representation from the
Asterisk dialplan, the CALLERID, CONNECTEDLINE and REDIRECTING dialplan
functions are extended by the following data types. The formats of these
data types are equal to the corresponding regular 'non-private' already
existing data types:
CALLERID:
priv-all
priv-name priv-name-valid priv-name-charset priv-name-pres
priv-num priv-num-valid priv-num-plan priv-num-pres
priv-subaddr priv-subaddr-valid priv-subaddr-type priv-subaddr-odd
priv-tag
CONNECTEDLINE:
priv-name priv-name-valid priv-name-pres priv-name-charset
priv-num priv-num-valid priv-num-pres priv-num-plan
priv-subaddr priv-subaddr-valid priv-subaddr-type priv-subaddr-odd
priv-tag
REDIRECTING:
priv-orig-name priv-orig-name-valid priv-orig-name-pres priv-orig-name-charset
priv-orig-num priv-orig-num-valid priv-orig-num-pres priv-orig-num-plan
priv-orig-subaddr priv-orig-subaddr-valid priv-orig-subaddr-type priv-orig-subaddr-odd
priv-orig-tag
priv-from-name priv-from-name-valid priv-from-name-pres priv-from-name-charset
priv-from-num priv-from-num-valid priv-from-num-pres priv-from-num-plan
priv-from-subaddr priv-from-subaddr-valid priv-from-subaddr-type priv-from-subaddr-odd
priv-from-tag
priv-to-name priv-to-name-valid priv-to-name-pres priv-to-name-charset
priv-to-num priv-to-num-valid priv-to-num-pres priv-to-num-plan
priv-to-subaddr priv-to-subaddr-valid priv-to-subaddr-type priv-to-subaddr-odd
priv-to-tag
Reported by: Thomas Arimont
Review: https://reviewboard.asterisk.org/r/2030/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@371120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-08-10 19:54:55 +00:00
|
|
|
"Eff. Connected Line ID: %s\n"
|
|
|
|
"Eff. Connected Line ID Name: %s\n"
|
2005-06-06 02:29:18 +00:00
|
|
|
" DNID Digits: %s\n"
|
2007-03-02 16:59:22 +00:00
|
|
|
" Language: %s\n"
|
2014-05-09 22:49:26 +00:00
|
|
|
" State: %s (%u)\n"
|
2006-01-07 17:54:22 +00:00
|
|
|
" NativeFormats: %s\n"
|
|
|
|
" WriteFormat: %s\n"
|
|
|
|
" ReadFormat: %s\n"
|
2010-08-12 20:17:17 +00:00
|
|
|
" WriteTranscode: %s %s\n"
|
|
|
|
" ReadTranscode: %s %s\n"
|
2005-06-06 02:29:18 +00:00
|
|
|
" Time to Hangup: %ld\n"
|
|
|
|
" Elapsed Time: %s\n"
|
2013-05-21 18:00:22 +00:00
|
|
|
" Bridge ID: %s\n"
|
2005-06-06 02:29:18 +00:00
|
|
|
" -- PBX --\n"
|
|
|
|
" Context: %s\n"
|
|
|
|
" Extension: %s\n"
|
|
|
|
" Priority: %d\n"
|
2006-09-29 13:46:33 +00:00
|
|
|
" Call Group: %llu\n"
|
|
|
|
" Pickup Group: %llu\n"
|
2005-06-06 02:29:18 +00:00
|
|
|
" Application: %s\n"
|
|
|
|
" Data: %s\n"
|
2012-05-17 16:28:20 +00:00
|
|
|
" Call Identifer: %s\n",
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
ast_channel_name(chan),
|
|
|
|
ast_channel_tech(chan)->type,
|
|
|
|
ast_channel_uniqueid(chan),
|
|
|
|
ast_channel_linkedid(chan),
|
|
|
|
S_COR(ast_channel_caller(chan)->id.number.valid,
|
|
|
|
ast_channel_caller(chan)->id.number.str, "(N/A)"),
|
|
|
|
S_COR(ast_channel_caller(chan)->id.name.valid,
|
|
|
|
ast_channel_caller(chan)->id.name.str, "(N/A)"),
|
|
|
|
S_COR(ast_channel_connected(chan)->id.number.valid,
|
|
|
|
ast_channel_connected(chan)->id.number.str, "(N/A)"),
|
|
|
|
S_COR(ast_channel_connected(chan)->id.name.valid,
|
|
|
|
ast_channel_connected(chan)->id.name.str, "(N/A)"),
|
|
|
|
S_COR(ast_channel_connected_effective_id(chan).number.valid,
|
|
|
|
ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
|
|
|
|
S_COR(ast_channel_connected_effective_id(chan).name.valid,
|
|
|
|
ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
|
|
|
|
S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
|
|
|
|
ast_channel_language(chan),
|
|
|
|
ast_state2str(ast_channel_state(chan)),
|
|
|
|
ast_channel_state(chan),
|
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
|
|
|
ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
|
|
|
|
ast_format_get_name(ast_channel_writeformat(chan)),
|
|
|
|
ast_format_get_name(ast_channel_readformat(chan)),
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
ast_str_strlen(write_transpath) ? "Yes" : "No",
|
|
|
|
ast_str_buffer(write_transpath),
|
|
|
|
ast_str_strlen(read_transpath) ? "Yes" : "No",
|
|
|
|
ast_str_buffer(read_transpath),
|
2015-03-23 00:05:48 +00:00
|
|
|
(long)ast_channel_whentohangup(chan)->tv_sec,
|
2013-05-21 18:00:22 +00:00
|
|
|
cdrtime,
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
bridge ? bridge->uniqueid : "(Not bridged)",
|
|
|
|
ast_channel_context(chan),
|
|
|
|
ast_channel_exten(chan),
|
|
|
|
ast_channel_priority(chan),
|
|
|
|
ast_channel_callgroup(chan),
|
|
|
|
ast_channel_pickupgroup(chan),
|
|
|
|
S_OR(ast_channel_appl(chan), "(N/A)"),
|
|
|
|
S_OR(ast_channel_data(chan), "(Empty)"),
|
|
|
|
S_OR(callid_buf, "(None)")
|
|
|
|
);
|
2017-02-22 14:32:23 +00:00
|
|
|
|
2013-07-08 19:19:55 +00:00
|
|
|
ast_str_append(&output, 0, " Variables:\n");
|
|
|
|
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
|
2013-07-08 19:19:55 +00:00
|
|
|
ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
|
2011-11-11 18:02:52 +00:00
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
2014-09-01 15:25:26 +00:00
|
|
|
if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
|
|
|
|
&& ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
|
2013-07-08 19:19:55 +00:00
|
|
|
ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
|
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
2017-02-22 14:32:23 +00:00
|
|
|
ast_str_append(&output, 0, " -- Streams --\n");
|
|
|
|
for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
|
|
|
|
struct ast_stream *stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num);
|
2018-04-13 20:14:47 +00:00
|
|
|
struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
|
2017-02-22 14:32:23 +00:00
|
|
|
|
|
|
|
ast_str_append(&output, 0,
|
|
|
|
"Name: %s\n"
|
|
|
|
" Type: %s\n"
|
|
|
|
" State: %s\n"
|
2017-10-25 22:31:33 +00:00
|
|
|
" Group: %d\n"
|
2018-04-13 20:14:47 +00:00
|
|
|
" Formats: %s\n"
|
|
|
|
" Metadata:\n",
|
2017-02-22 14:32:23 +00:00
|
|
|
ast_stream_get_name(stream),
|
|
|
|
ast_codec_media_type2str(ast_stream_get_type(stream)),
|
|
|
|
ast_stream_state2str(ast_stream_get_state(stream)),
|
2017-10-25 22:31:33 +00:00
|
|
|
ast_stream_get_group(stream),
|
2017-02-22 14:32:23 +00:00
|
|
|
ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf)
|
|
|
|
);
|
2018-04-13 20:14:47 +00:00
|
|
|
|
|
|
|
if (metadata) {
|
|
|
|
struct ast_variable *v;
|
|
|
|
for(v = metadata; v; v = v->next) {
|
|
|
|
ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
|
|
|
|
}
|
|
|
|
ast_variables_destroy(metadata);
|
|
|
|
}
|
2017-02-22 14:32:23 +00:00
|
|
|
}
|
|
|
|
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
2011-11-11 18:02:52 +00:00
|
|
|
ast_cli(a->fd, "%s", ast_str_buffer(output));
|
|
|
|
ast_free(output);
|
stasis: Reduce creation of channel snapshots to improve performance
During some performance testing of Asterisk with AGI, ARI, and lots of Local
channels, we noticed that there's quite a hit in performance during channel
creation and releasing to the dialplan (ARI continue). After investigating
the performance spike that occurs during channel creation, we discovered
that we create a lot of channel snapshots that are technically unnecessary.
This includes creating snapshots during:
* AGI execution
* Returning objects for ARI commands
* During some Local channel operations
* During some dialling operations
* During variable setting
* During some bridging operations
And more.
This patch does the following:
- It removes a number of fields from channel snapshots. These fields were
rarely used, were expensive to have on the snapshot, and hurt performance.
This included formats, translation paths, Log Call ID, callgroup, pickup
group, and all channel variables. As a result, AMI Status,
"core show channel", "core show channelvar", and "pjsip show channel" were
modified to either hit the live channel or not show certain pieces of data.
While this is unfortunate, the performance gain from this patch is worth
the loss in behaviour.
- It adds a mechanism to publish a cached snapshot + blob. A large number of
publications were changed to use this, including:
- During Dial begin
- During Variable assignment (if no AMI variables are emitted - if AMI
variables are set, we have to make snapshots when a variable is changed)
- During channel pickup
- When a channel is put on hold/unhold
- When a DTMF digit is begun/ended
- When creating a bridge snapshot
- When an AOC event is raised
- During Local channel optimization/Local bridging
- When endpoint snapshots are generated
- All AGI events
- All ARI responses that return a channel
- Events in the AgentPool, MeetMe, and some in Queue
- Additionally, some extraneous channel snapshots were being made that were
unnecessary. These were removed.
- The result of ast_hashtab_hash_string is now cached in stasis_cache. This
reduces a large number of calls to ast_hashtab_hash_string, which reduced
the amount of time spent in this function in gprof by around 50%.
#ASTERISK-23811 #close
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3568/
........
Merged revisions 416211 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-06-13 18:24:49 +00:00
|
|
|
|
|
|
|
ao2_cleanup(bridge);
|
|
|
|
ast_channel_unref(chan);
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
return CLI_SUCCESS;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
/*
|
|
|
|
* helper function to generate CLI matches from a fixed set of values.
|
|
|
|
* A NULL word is acceptable.
|
|
|
|
*/
|
2009-05-21 21:13:09 +00:00
|
|
|
char *ast_cli_complete(const char *word, const char * const choices[], int state)
|
2005-08-08 01:45:29 +00:00
|
|
|
{
|
2006-03-28 22:25:08 +00:00
|
|
|
int i, which = 0, len;
|
|
|
|
len = ast_strlen_zero(word) ? 0 : strlen(word);
|
2005-11-29 04:25:28 +00:00
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
for (i = 0; choices[i]; i++) {
|
2018-03-14 17:38:01 +00:00
|
|
|
if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state) {
|
|
|
|
if (state != -1) {
|
|
|
|
return ast_strdup(choices[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ast_cli_completion_add(ast_strdup(choices[i]))) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2005-08-08 01:45:29 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-02-16 17:37:03 +00:00
|
|
|
char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2013-07-08 19:19:55 +00:00
|
|
|
int wordlen = strlen(word), which = 0;
|
2017-11-16 23:25:04 +00:00
|
|
|
struct ao2_container *cached_channels;
|
2013-07-08 19:19:55 +00:00
|
|
|
char *ret = NULL;
|
|
|
|
struct ao2_iterator iter;
|
2018-10-10 14:28:18 +00:00
|
|
|
struct ast_channel_snapshot *snapshot;
|
2005-06-06 02:29:18 +00:00
|
|
|
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
if (pos != rpos) {
|
2004-08-07 19:27:54 +00:00
|
|
|
return NULL;
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
2005-11-29 04:25:28 +00:00
|
|
|
|
2018-10-10 14:28:18 +00:00
|
|
|
cached_channels = ast_channel_cache_all();
|
2005-11-29 04:25:28 +00:00
|
|
|
|
2013-07-08 19:19:55 +00:00
|
|
|
iter = ao2_iterator_init(cached_channels, 0);
|
2018-10-10 14:28:18 +00:00
|
|
|
for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
|
2018-11-07 17:18:34 +00:00
|
|
|
if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
|
2018-03-14 17:38:01 +00:00
|
|
|
if (state != -1) {
|
2018-11-07 17:18:34 +00:00
|
|
|
ret = ast_strdup(snapshot->base->name);
|
2018-10-10 14:28:18 +00:00
|
|
|
ao2_ref(snapshot, -1);
|
2018-03-14 17:38:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-11-07 17:18:34 +00:00
|
|
|
if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
|
2018-10-10 14:28:18 +00:00
|
|
|
ao2_ref(snapshot, -1);
|
2018-03-14 17:38:01 +00:00
|
|
|
break;
|
|
|
|
}
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
}
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2013-07-08 19:19:55 +00:00
|
|
|
ao2_iterator_destroy(&iter);
|
2017-11-16 23:25:04 +00:00
|
|
|
ao2_ref(cached_channels, -1);
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
|
2013-07-08 19:19:55 +00:00
|
|
|
return ret;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
static char *group_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
{
|
|
|
|
#define FORMAT_STRING "%-25s %-20s %-20s\n"
|
|
|
|
|
2007-04-25 19:27:42 +00:00
|
|
|
struct ast_group_info *gi = NULL;
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
int numchans = 0;
|
|
|
|
regex_t regexbuf;
|
|
|
|
int havepattern = 0;
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "group show channels";
|
2012-03-22 19:51:16 +00:00
|
|
|
e->usage =
|
2007-10-11 19:03:06 +00:00
|
|
|
"Usage: group show channels [pattern]\n"
|
|
|
|
" Lists all currently active channels with channel group(s) specified.\n"
|
|
|
|
" Optional regular expression pattern is matched to group names for each\n"
|
|
|
|
" channel.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->argc < 3 || a->argc > 4)
|
|
|
|
return CLI_SHOWUSAGE;
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
if (a->argc == 4) {
|
|
|
|
if (regcomp(®exbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
|
|
|
|
return CLI_SHOWUSAGE;
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
havepattern = 1;
|
|
|
|
}
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
|
2007-04-25 19:27:42 +00:00
|
|
|
|
2007-06-13 18:23:12 +00:00
|
|
|
ast_app_group_list_rdlock();
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2007-04-25 19:27:42 +00:00
|
|
|
gi = ast_app_group_list_head();
|
|
|
|
while (gi) {
|
|
|
|
if (!havepattern || !regexec(®exbuf, gi->group, 0, NULL, 0)) {
|
2012-01-09 22:15:50 +00:00
|
|
|
ast_cli(a->fd, FORMAT_STRING, ast_channel_name(gi->chan), gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
|
2007-04-25 19:27:42 +00:00
|
|
|
numchans++;
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
}
|
2009-04-22 21:15:55 +00:00
|
|
|
gi = AST_LIST_NEXT(gi, group_list);
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
}
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2007-04-25 19:27:42 +00:00
|
|
|
ast_app_group_list_unlock();
|
2012-03-22 19:51:16 +00:00
|
|
|
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
if (havepattern)
|
|
|
|
regfree(®exbuf);
|
|
|
|
|
2007-10-11 19:03:06 +00:00
|
|
|
ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
|
|
|
|
return CLI_SUCCESS;
|
This is the first round of removing applications that were marked as deprecated
in the 1.2 release. They are being removed from the trunk and will not be in
the next major release. The following is a list of the applications that are
being removed in this commit:
Curl, Cut, Sort, DBPut, DBGet, ENUMLookup, Eval
GetGroupCount, SetGroup, CheckGroup, GetGroupMatchCount
MD5, MD5Check, Math, SetCIDName, SetCIDNum, SetRDNIS, SetCallerID
TXTCIDName, AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetAccount
SetLanguage, SetVar (renamed to Set)
These changes also include moving the "group show channels" cli command from
app_groupcount.c to cli.c.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 15:36:55 +00:00
|
|
|
#undef FORMAT_STRING
|
|
|
|
}
|
|
|
|
|
2010-06-02 18:53:38 +00:00
|
|
|
static char *handle_cli_wait_fullybooted(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "core waitfullybooted";
|
|
|
|
e->usage =
|
|
|
|
"Usage: core waitfullybooted\n"
|
|
|
|
" Wait until Asterisk has fully booted.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
|
|
|
|
usleep(100);
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_cli(a->fd, "Asterisk has fully booted.\n");
|
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-12-03 20:01:01 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_MALLOC_TRIM
|
|
|
|
|
2018-12-03 22:41:56 +00:00
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Attempt to reclaim unused heap memory.
|
|
|
|
*
|
|
|
|
* Users have reported that asterisk will sometimes be killed because it can't allocate
|
|
|
|
* more than around 3G of memory on a 32 bit system.
|
|
|
|
*
|
|
|
|
* Using malloc_trim() will help us to determine if it's because there's a leak or because
|
|
|
|
* the heap is so fragmented that there isn't enough contiguous memory available.
|
|
|
|
*
|
|
|
|
* \note malloc_trim() is a GNU extension and is therefore not portable.
|
|
|
|
*/
|
|
|
|
static char *handle_cli_malloc_trim(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
{
|
|
|
|
extern int malloc_trim(size_t __pad) __THROW;
|
2018-12-03 20:01:01 +00:00
|
|
|
|
2018-12-03 22:41:56 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case CLI_INIT:
|
|
|
|
e->command = "malloc trim";
|
|
|
|
e->usage =
|
|
|
|
"Usage: malloc trim\n"
|
|
|
|
" Try to give excess memory back to the OS.\n";
|
|
|
|
return NULL;
|
|
|
|
case CLI_GENERATE:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (malloc_trim(0)) {
|
|
|
|
ast_cli(a->fd, "Returned some memory to the OS.\n");
|
|
|
|
} else {
|
|
|
|
ast_cli(a->fd, "No memory returned to the OS.\n");
|
2018-12-03 20:01:01 +00:00
|
|
|
}
|
2018-12-03 22:41:56 +00:00
|
|
|
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-12-03 20:01:01 +00:00
|
|
|
#endif
|
|
|
|
|
2006-11-17 22:53:57 +00:00
|
|
|
static char *handle_help(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
|
|
|
|
2006-09-18 19:54:18 +00:00
|
|
|
static struct ast_cli_entry cli_cli[] = {
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_commandmatchesarray, "Returns command matches array"),
|
2007-10-15 13:44:53 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_nodebugchan_deprecated, "Disable debugging on channel(s)"),
|
2006-11-10 17:01:06 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_chanlist, "Display information on channels"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-12-07 16:11:05 +00:00
|
|
|
AST_CLI_DEFINE(handle_showcalls, "Display information on calls"),
|
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_showchan, "Display information on a specific channel"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2008-11-12 06:46:04 +00:00
|
|
|
AST_CLI_DEFINE(handle_core_set_debug_channel, "Enable/disable debugging on a channel"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2014-01-14 18:14:02 +00:00
|
|
|
AST_CLI_DEFINE(handle_debug, "Set level of debug chattiness"),
|
|
|
|
AST_CLI_DEFINE(handle_verbose, "Set level of verbose chattiness"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(group_show_channels, "Display active channels with group(s)"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_help, "Display help list, or specific help on a command"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_logger_mute, "Toggle logging output to a console"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_modlist, "List modules and info"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2008-11-12 06:46:04 +00:00
|
|
|
AST_CLI_DEFINE(handle_load, "Load a module by name"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2010-08-12 20:44:39 +00:00
|
|
|
AST_CLI_DEFINE(handle_reload, "Reload configuration for a module"),
|
|
|
|
|
|
|
|
AST_CLI_DEFINE(handle_core_reload, "Global reload"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2008-11-12 06:46:04 +00:00
|
|
|
AST_CLI_DEFINE(handle_unload, "Unload a module by name"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_showuptime, "Show uptime information"),
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2007-10-22 20:05:18 +00:00
|
|
|
AST_CLI_DEFINE(handle_softhangup, "Request a hangup on a given channel"),
|
2008-12-01 18:52:14 +00:00
|
|
|
|
|
|
|
AST_CLI_DEFINE(handle_cli_reload_permissions, "Reload CLI permissions config"),
|
|
|
|
|
|
|
|
AST_CLI_DEFINE(handle_cli_show_permissions, "Show CLI permissions"),
|
|
|
|
|
|
|
|
AST_CLI_DEFINE(handle_cli_check_permissions, "Try a permissions config for a user"),
|
2010-06-02 18:53:38 +00:00
|
|
|
|
|
|
|
AST_CLI_DEFINE(handle_cli_wait_fullybooted, "Wait for Asterisk to be fully booted"),
|
2018-12-03 20:01:01 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_MALLOC_TRIM
|
|
|
|
AST_CLI_DEFINE(handle_cli_malloc_trim, "Return excess memory to the OS"),
|
|
|
|
#endif
|
|
|
|
|
2006-09-18 19:54:18 +00:00
|
|
|
};
|
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
/*!
|
|
|
|
* Some regexp characters in cli arguments are reserved and used as separators.
|
|
|
|
*/
|
2006-11-17 21:50:55 +00:00
|
|
|
static const char cli_rsvd[] = "[]{}|*%";
|
2006-11-17 11:12:13 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* initialize the _full_cmd string and related parameters,
|
|
|
|
* return 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
static int set_full_cmd(struct ast_cli_entry *e)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char buf[80];
|
|
|
|
|
|
|
|
ast_join(buf, sizeof(buf), e->cmda);
|
2007-06-14 23:01:01 +00:00
|
|
|
e->_full_cmd = ast_strdup(buf);
|
2006-11-17 11:12:13 +00:00
|
|
|
if (!e->_full_cmd) {
|
|
|
|
ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
|
|
|
|
for (i = 0; e->cmda[i]; i++)
|
|
|
|
;
|
|
|
|
e->args = i;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
/*! \brief cleanup (free) cli_perms linkedlist. */
|
2008-12-04 19:31:48 +00:00
|
|
|
static void destroy_user_perms(void)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2008-12-01 18:52:14 +00:00
|
|
|
struct cli_perm *perm;
|
|
|
|
struct usergroup_cli_perm *user_perm;
|
|
|
|
|
|
|
|
AST_RWLIST_WRLOCK(&cli_perms);
|
|
|
|
while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
|
|
|
|
while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
|
|
|
|
ast_free(perm->command);
|
|
|
|
ast_free(perm);
|
|
|
|
}
|
|
|
|
ast_free(user_perm);
|
|
|
|
}
|
|
|
|
AST_RWLIST_UNLOCK(&cli_perms);
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 19:31:48 +00:00
|
|
|
int ast_cli_perms_init(int reload)
|
|
|
|
{
|
2008-12-01 18:52:14 +00:00
|
|
|
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
|
|
|
|
struct ast_config *cfg;
|
|
|
|
char *cat = NULL;
|
|
|
|
struct ast_variable *v;
|
|
|
|
struct usergroup_cli_perm *user_group, *cp_entry;
|
|
|
|
struct cli_perm *perm = NULL;
|
|
|
|
struct passwd *pw;
|
|
|
|
struct group *gr;
|
|
|
|
|
|
|
|
if (ast_mutex_trylock(&permsconfiglock)) {
|
|
|
|
ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
|
|
|
|
if (!cfg) {
|
|
|
|
ast_mutex_unlock(&permsconfiglock);
|
|
|
|
return 1;
|
|
|
|
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
|
|
|
|
ast_mutex_unlock(&permsconfiglock);
|
|
|
|
return 0;
|
2008-10-03 22:10:18 +00:00
|
|
|
}
|
2008-12-01 18:52:14 +00:00
|
|
|
|
|
|
|
/* free current structures. */
|
|
|
|
destroy_user_perms();
|
|
|
|
|
|
|
|
while ((cat = ast_category_browse(cfg, cat))) {
|
|
|
|
if (!strcasecmp(cat, "general")) {
|
|
|
|
/* General options */
|
|
|
|
for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
|
|
|
|
if (!strcasecmp(v->name, "default_perm")) {
|
|
|
|
cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* users or groups */
|
|
|
|
gr = NULL, pw = NULL;
|
|
|
|
if (cat[0] == '@') {
|
|
|
|
/* This is a group */
|
|
|
|
gr = getgrnam(&cat[1]);
|
|
|
|
if (!gr) {
|
|
|
|
ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* This is a user */
|
|
|
|
pw = getpwnam(cat);
|
|
|
|
if (!pw) {
|
|
|
|
ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
user_group = NULL;
|
|
|
|
/* Check for duplicates */
|
|
|
|
AST_RWLIST_WRLOCK(&cli_perms);
|
|
|
|
AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
|
|
|
|
if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
|
2012-03-22 19:51:16 +00:00
|
|
|
/* if it is duplicated, just added this new settings, to
|
2008-12-01 18:52:14 +00:00
|
|
|
the current list. */
|
|
|
|
user_group = cp_entry;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AST_RWLIST_UNLOCK(&cli_perms);
|
|
|
|
|
|
|
|
if (!user_group) {
|
|
|
|
/* alloc space for the new user config. */
|
|
|
|
user_group = ast_calloc(1, sizeof(*user_group));
|
|
|
|
if (!user_group) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
user_group->uid = (pw ? pw->pw_uid : -1);
|
|
|
|
user_group->gid = (gr ? gr->gr_gid : -1);
|
|
|
|
user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
|
|
|
|
if (!user_group->perms) {
|
|
|
|
ast_free(user_group);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
|
|
|
|
if (ast_strlen_zero(v->value)) {
|
|
|
|
/* we need to check this condition cause it could break security. */
|
|
|
|
ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!strcasecmp(v->name, "permit")) {
|
|
|
|
perm = ast_calloc(1, sizeof(*perm));
|
|
|
|
if (perm) {
|
|
|
|
perm->permit = 1;
|
|
|
|
perm->command = ast_strdup(v->value);
|
|
|
|
}
|
|
|
|
} else if (!strcasecmp(v->name, "deny")) {
|
|
|
|
perm = ast_calloc(1, sizeof(*perm));
|
|
|
|
if (perm) {
|
|
|
|
perm->permit = 0;
|
|
|
|
perm->command = ast_strdup(v->value);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* up to now, only 'permit' and 'deny' are possible values. */
|
|
|
|
ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (perm) {
|
|
|
|
/* Added the permission to the user's list. */
|
|
|
|
AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
|
|
|
|
perm = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AST_RWLIST_WRLOCK(&cli_perms);
|
|
|
|
AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
|
|
|
|
AST_RWLIST_UNLOCK(&cli_perms);
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_config_destroy(cfg);
|
|
|
|
ast_mutex_unlock(&permsconfiglock);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-03 19:17:24 +00:00
|
|
|
static void cli_shutdown(void)
|
|
|
|
{
|
|
|
|
ast_cli_unregister_multiple(cli_cli, ARRAY_LEN(cli_cli));
|
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
/*! \brief initialize the _full_cmd string in * each of the builtins. */
|
|
|
|
void ast_builtins_init(void)
|
|
|
|
{
|
2016-03-10 22:58:49 +00:00
|
|
|
AST_VECTOR_INIT(&shutdown_commands, 0);
|
2008-12-05 10:31:25 +00:00
|
|
|
ast_cli_register_multiple(cli_cli, ARRAY_LEN(cli_cli));
|
2015-03-26 22:24:26 +00:00
|
|
|
ast_register_cleanup(cli_shutdown);
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
/*!
|
|
|
|
* match a word in the CLI entry.
|
|
|
|
* returns -1 on mismatch, 0 on match of an optional word,
|
|
|
|
* 1 on match of a full word.
|
2006-11-17 21:50:55 +00:00
|
|
|
*
|
|
|
|
* The pattern can be
|
2009-01-29 23:15:20 +00:00
|
|
|
* any_word match for equal
|
|
|
|
* [foo|bar|baz] optionally, one of these words
|
|
|
|
* {foo|bar|baz} exactly, one of these words
|
|
|
|
* % any word
|
2006-11-17 11:12:13 +00:00
|
|
|
*/
|
|
|
|
static int word_match(const char *cmd, const char *cli_word)
|
|
|
|
{
|
|
|
|
int l;
|
|
|
|
char *pos;
|
|
|
|
|
|
|
|
if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
|
|
|
|
return -1;
|
|
|
|
if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
|
|
|
|
return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
|
|
|
|
l = strlen(cmd);
|
2006-11-17 21:50:55 +00:00
|
|
|
/* wildcard match - will extend in the future */
|
|
|
|
if (l > 0 && cli_word[0] == '%') {
|
|
|
|
return 1; /* wildcard */
|
|
|
|
}
|
2011-04-15 15:20:46 +00:00
|
|
|
|
|
|
|
/* Start a search for the command entered against the cli word in question */
|
2006-11-17 11:12:13 +00:00
|
|
|
pos = strcasestr(cli_word, cmd);
|
2011-04-15 15:20:46 +00:00
|
|
|
while (pos) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
*Check if the word matched with is surrounded by reserved characters on both sides
|
|
|
|
* and isn't at the beginning of the cli_word since that would make it check in a location we shouldn't know about.
|
|
|
|
* If it is surrounded by reserved chars and isn't at the beginning, it's a match.
|
|
|
|
*/
|
|
|
|
if (pos != cli_word && strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l])) {
|
|
|
|
return 1; /* valid match */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ok, that one didn't match, strcasestr to the next appearance of the command and start over.*/
|
|
|
|
pos = strcasestr(pos + 1, cmd);
|
|
|
|
}
|
|
|
|
/* If no matches were found over the course of the while loop, we hit the end of the string. It's a mismatch. */
|
|
|
|
return -1;
|
2006-11-17 11:12:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*! \brief if word is a valid prefix for token, returns the pos-th
|
|
|
|
* match as a malloced string, or NULL otherwise.
|
|
|
|
* Always tell in *actual how many matches we got.
|
|
|
|
*/
|
|
|
|
static char *is_prefix(const char *word, const char *token,
|
|
|
|
int pos, int *actual)
|
|
|
|
{
|
|
|
|
int lw;
|
|
|
|
char *s, *t1;
|
|
|
|
|
|
|
|
*actual = 0;
|
|
|
|
if (ast_strlen_zero(token))
|
|
|
|
return NULL;
|
|
|
|
if (ast_strlen_zero(word))
|
|
|
|
word = ""; /* dummy */
|
|
|
|
lw = strlen(word);
|
|
|
|
if (strcspn(word, cli_rsvd) != lw)
|
|
|
|
return NULL; /* no match if word has reserved chars */
|
|
|
|
if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
|
|
|
|
if (strncasecmp(token, word, lw)) /* no match */
|
|
|
|
return NULL;
|
|
|
|
*actual = 1;
|
2007-06-14 23:01:01 +00:00
|
|
|
return (pos != 0) ? NULL : ast_strdup(token);
|
2006-11-17 11:12:13 +00:00
|
|
|
}
|
|
|
|
/* now handle regexp match */
|
2006-11-17 21:50:55 +00:00
|
|
|
|
|
|
|
/* Wildcard always matches, so we never do is_prefix on them */
|
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
t1 = ast_strdupa(token + 1); /* copy, skipping first char */
|
|
|
|
while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
|
2006-11-17 21:50:55 +00:00
|
|
|
if (*s == '%') /* wildcard */
|
|
|
|
continue;
|
2006-11-17 11:12:13 +00:00
|
|
|
if (strncasecmp(s, word, lw)) /* no match */
|
|
|
|
continue;
|
|
|
|
(*actual)++;
|
|
|
|
if (pos-- == 0)
|
2007-06-14 23:01:01 +00:00
|
|
|
return ast_strdup(s);
|
2006-11-17 11:12:13 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
/*!
|
2008-11-12 06:46:04 +00:00
|
|
|
* \internal
|
2006-03-28 22:25:08 +00:00
|
|
|
* \brief locate a cli command in the 'helpers' list (which must be locked).
|
2008-11-12 06:46:04 +00:00
|
|
|
* The search compares word by word taking care of regexps in e->cmda
|
|
|
|
* This function will return NULL when nothing is matched, or the ast_cli_entry that matched.
|
|
|
|
* \param cmds
|
|
|
|
* \param match_type has 3 possible values:
|
2006-03-28 22:25:08 +00:00
|
|
|
* 0 returns if the search key is equal or longer than the entry.
|
2013-07-08 19:19:55 +00:00
|
|
|
* note that trailing optional arguments are skipped.
|
2006-03-28 22:25:08 +00:00
|
|
|
* -1 true if the mismatch is on the last word XXX not true!
|
|
|
|
* 1 true only on complete, exact match.
|
2006-11-17 11:12:13 +00:00
|
|
|
*
|
2006-03-28 22:25:08 +00:00
|
|
|
*/
|
2009-05-21 21:13:09 +00:00
|
|
|
static struct ast_cli_entry *find_cli(const char * const cmds[], int match_type)
|
1999-12-27 19:20:20 +00:00
|
|
|
{
|
2006-03-28 22:25:08 +00:00
|
|
|
int matchlen = -1; /* length of longest match so far */
|
|
|
|
struct ast_cli_entry *cand = NULL, *e=NULL;
|
|
|
|
|
2007-10-15 13:44:53 +00:00
|
|
|
while ( (e = cli_next(e)) ) {
|
2006-11-17 11:12:13 +00:00
|
|
|
/* word-by word regexp comparison */
|
2009-05-21 21:13:09 +00:00
|
|
|
const char * const *src = cmds;
|
|
|
|
const char * const *dst = e->cmda;
|
2006-11-17 11:12:13 +00:00
|
|
|
int n = 0;
|
|
|
|
for (;; dst++, src += n) {
|
|
|
|
n = word_match(*src, *dst);
|
|
|
|
if (n < 0)
|
2006-03-28 22:25:08 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-11-17 11:12:13 +00:00
|
|
|
if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
|
|
|
|
/* no more words in 'e' */
|
|
|
|
if (ast_strlen_zero(*src)) /* exact match, cannot do better */
|
2006-03-28 22:25:08 +00:00
|
|
|
break;
|
2006-11-17 11:12:13 +00:00
|
|
|
/* Here, cmds has more words than the entry 'e' */
|
2006-03-28 22:25:08 +00:00
|
|
|
if (match_type != 0) /* but we look for almost exact match... */
|
|
|
|
continue; /* so we skip this one. */
|
|
|
|
/* otherwise we like it (case 0) */
|
2006-11-17 11:12:13 +00:00
|
|
|
} else { /* still words in 'e' */
|
|
|
|
if (ast_strlen_zero(*src))
|
|
|
|
continue; /* cmds is shorter than 'e', not good */
|
|
|
|
/* Here we have leftover words in cmds and 'e',
|
|
|
|
* but there is a mismatch. We only accept this one if match_type == -1
|
|
|
|
* and this is the last word for both.
|
|
|
|
*/
|
|
|
|
if (match_type != -1 || !ast_strlen_zero(src[1]) ||
|
|
|
|
!ast_strlen_zero(dst[1])) /* not the one we look for */
|
2006-03-28 22:25:08 +00:00
|
|
|
continue;
|
2006-11-17 11:12:13 +00:00
|
|
|
/* good, we are in case match_type == -1 and mismatch on last word */
|
2006-03-28 22:25:08 +00:00
|
|
|
}
|
2006-11-17 11:12:13 +00:00
|
|
|
if (src - cmds > matchlen) { /* remember the candidate */
|
|
|
|
matchlen = src - cmds;
|
2006-03-28 22:25:08 +00:00
|
|
|
cand = e;
|
2006-11-15 16:13:30 +00:00
|
|
|
}
|
1999-12-27 19:20:20 +00:00
|
|
|
}
|
2008-11-12 06:46:04 +00:00
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
return e ? e : cand;
|
1999-12-27 19:20:20 +00:00
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static char *find_best(const char *argv[])
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
|
|
|
static char cmdline[80];
|
|
|
|
int x;
|
2006-03-28 22:25:08 +00:00
|
|
|
/* See how close we get, then print the candidate */
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
|
|
|
|
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_RDLOCK(&helpers);
|
2009-05-21 21:13:09 +00:00
|
|
|
for (x = 0; argv[x]; x++) {
|
1999-12-19 22:38:55 +00:00
|
|
|
myargv[x] = argv[x];
|
|
|
|
if (!find_cli(myargv, -1))
|
|
|
|
break;
|
|
|
|
}
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2006-03-28 22:25:08 +00:00
|
|
|
ast_join(cmdline, sizeof(cmdline), myargv);
|
1999-12-19 22:38:55 +00:00
|
|
|
return cmdline;
|
|
|
|
}
|
|
|
|
|
2012-12-03 19:17:24 +00:00
|
|
|
static int cli_is_registered(struct ast_cli_entry *e)
|
|
|
|
{
|
|
|
|
struct ast_cli_entry *cur = NULL;
|
|
|
|
|
|
|
|
while ((cur = cli_next(cur))) {
|
|
|
|
if (cur == e) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-10 22:58:49 +00:00
|
|
|
static void remove_shutdown_command(struct ast_cli_entry *e)
|
|
|
|
{
|
|
|
|
ast_rwlock_wrlock(&shutdown_commands_lock);
|
|
|
|
AST_VECTOR_REMOVE_ELEM_UNORDERED(&shutdown_commands, e, AST_VECTOR_ELEM_CLEANUP_NOOP);
|
|
|
|
ast_rwlock_unlock(&shutdown_commands_lock);
|
|
|
|
}
|
|
|
|
|
2015-05-04 21:41:08 +00:00
|
|
|
int ast_cli_unregister(struct ast_cli_entry *e)
|
1999-12-27 19:20:20 +00:00
|
|
|
{
|
2006-02-14 22:44:20 +00:00
|
|
|
if (e->inuse) {
|
|
|
|
ast_log(LOG_WARNING, "Can't remove command that is in use\n");
|
|
|
|
} else {
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_WRLOCK(&helpers);
|
|
|
|
AST_RWLIST_REMOVE(&helpers, e, list);
|
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2016-03-10 22:58:49 +00:00
|
|
|
remove_shutdown_command(e);
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(e->_full_cmd);
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
e->_full_cmd = NULL;
|
2007-11-28 20:27:40 +00:00
|
|
|
if (e->handler) {
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
/* this is a new-style entry. Reset fields and free memory. */
|
2008-12-02 00:37:21 +00:00
|
|
|
char *cmda = (char *) e->cmda;
|
|
|
|
memset(cmda, '\0', sizeof(e->cmda));
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(e->command);
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
e->command = NULL;
|
|
|
|
e->usage = NULL;
|
|
|
|
}
|
1999-12-27 19:20:20 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-04 21:41:08 +00:00
|
|
|
int __ast_cli_register(struct ast_cli_entry *e, struct ast_module *module)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2006-02-14 22:44:20 +00:00
|
|
|
struct ast_cli_entry *cur;
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
int i, lf, ret = -1;
|
|
|
|
|
2007-11-28 20:27:40 +00:00
|
|
|
struct ast_cli_args a; /* fake argument */
|
|
|
|
char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
|
|
|
|
char *s;
|
|
|
|
|
2012-12-03 19:17:24 +00:00
|
|
|
AST_RWLIST_WRLOCK(&helpers);
|
|
|
|
|
|
|
|
if (cli_is_registered(e)) {
|
|
|
|
ast_log(LOG_WARNING, "Command '%s' already registered (the same ast_cli_entry)\n",
|
|
|
|
S_OR(e->_full_cmd, e->command));
|
|
|
|
ret = 0; /* report success */
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2008-10-09 14:17:33 +00:00
|
|
|
memset(&a, '\0', sizeof(a));
|
2015-05-04 21:41:08 +00:00
|
|
|
|
|
|
|
e->module = module;
|
|
|
|
/* No module reference needed here, the module called us. */
|
2007-11-28 20:27:40 +00:00
|
|
|
e->handler(e, CLI_INIT, &a);
|
2015-05-04 21:41:08 +00:00
|
|
|
|
2007-11-28 20:27:40 +00:00
|
|
|
/* XXX check that usage and command are filled up */
|
|
|
|
s = ast_skip_blanks(e->command);
|
|
|
|
s = e->command = ast_strdup(s);
|
|
|
|
for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
|
|
|
|
*dst++ = s; /* store string */
|
|
|
|
s = ast_skip_nonblanks(s);
|
|
|
|
if (*s == '\0') /* we are done */
|
|
|
|
break;
|
|
|
|
*s++ = '\0';
|
|
|
|
s = ast_skip_blanks(s);
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
}
|
2007-11-28 20:27:40 +00:00
|
|
|
*dst++ = NULL;
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
if (find_cli(e->cmda, 1)) {
|
2012-12-03 19:17:24 +00:00
|
|
|
ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n",
|
|
|
|
S_OR(e->_full_cmd, e->command));
|
2006-03-28 22:25:08 +00:00
|
|
|
goto done;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2012-12-03 19:17:24 +00:00
|
|
|
if (set_full_cmd(e)) {
|
|
|
|
ast_log(LOG_WARNING, "Error registering CLI Command '%s'\n",
|
|
|
|
S_OR(e->_full_cmd, e->command));
|
2007-10-01 14:55:10 +00:00
|
|
|
goto done;
|
2012-12-03 19:17:24 +00:00
|
|
|
}
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
lf = e->cmdlen;
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
|
2006-11-17 11:12:13 +00:00
|
|
|
int len = cur->cmdlen;
|
2006-03-28 22:25:08 +00:00
|
|
|
if (lf < len)
|
|
|
|
len = lf;
|
2006-11-17 11:12:13 +00:00
|
|
|
if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
|
2012-03-22 19:51:16 +00:00
|
|
|
AST_RWLIST_INSERT_BEFORE_CURRENT(e, list);
|
1999-12-19 22:38:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_TRAVERSE_SAFE_END;
|
2005-11-29 04:25:28 +00:00
|
|
|
|
2006-02-14 22:44:20 +00:00
|
|
|
if (!cur)
|
2012-03-22 19:51:16 +00:00
|
|
|
AST_RWLIST_INSERT_TAIL(&helpers, e, list);
|
2006-03-28 22:25:08 +00:00
|
|
|
ret = 0; /* success */
|
2005-11-29 04:25:28 +00:00
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
done:
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2012-12-03 19:17:24 +00:00
|
|
|
if (ret) {
|
|
|
|
ast_free(e->command);
|
|
|
|
e->command = NULL;
|
|
|
|
}
|
2006-09-18 19:54:18 +00:00
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
return ret;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2005-05-15 03:03:48 +00:00
|
|
|
/*
|
|
|
|
* register/unregister an array of entries.
|
|
|
|
*/
|
2015-05-04 21:41:08 +00:00
|
|
|
int __ast_cli_register_multiple(struct ast_cli_entry *e, int len, struct ast_module *module)
|
2005-05-15 03:03:48 +00:00
|
|
|
{
|
2007-02-13 22:02:20 +00:00
|
|
|
int i, res = 0;
|
2005-05-15 03:03:48 +00:00
|
|
|
|
2015-05-04 21:41:08 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
res |= __ast_cli_register(e + i, module);
|
|
|
|
}
|
2007-02-13 22:02:20 +00:00
|
|
|
|
|
|
|
return res;
|
2005-05-15 03:03:48 +00:00
|
|
|
}
|
|
|
|
|
2007-02-13 22:02:20 +00:00
|
|
|
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
|
2005-05-15 03:03:48 +00:00
|
|
|
{
|
2007-02-13 22:02:20 +00:00
|
|
|
int i, res = 0;
|
2005-05-15 03:03:48 +00:00
|
|
|
|
2005-11-29 04:25:28 +00:00
|
|
|
for (i = 0; i < len; i++)
|
2007-02-13 22:02:20 +00:00
|
|
|
res |= ast_cli_unregister(e + i);
|
|
|
|
|
|
|
|
return res;
|
2005-05-15 03:03:48 +00:00
|
|
|
}
|
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
|
2008-01-09 20:30:54 +00:00
|
|
|
/*! \brief helper for final part of handle_help
|
|
|
|
* if locked = 1, assume the list is already locked
|
2006-03-28 22:25:08 +00:00
|
|
|
*/
|
2009-05-21 21:13:09 +00:00
|
|
|
static char *help1(int fd, const char * const match[], int locked)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2006-03-28 22:25:08 +00:00
|
|
|
char matchstr[80] = "";
|
2007-10-15 13:44:53 +00:00
|
|
|
struct ast_cli_entry *e = NULL;
|
2006-03-28 22:25:08 +00:00
|
|
|
int len = 0;
|
|
|
|
int found = 0;
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
ast_join(matchstr, sizeof(matchstr), match);
|
|
|
|
len = strlen(matchstr);
|
|
|
|
}
|
|
|
|
if (!locked)
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_RDLOCK(&helpers);
|
2007-10-15 13:44:53 +00:00
|
|
|
while ( (e = cli_next(e)) ) {
|
2001-05-09 03:11:22 +00:00
|
|
|
/* Hide commands that start with '_' */
|
2006-03-28 22:25:08 +00:00
|
|
|
if (e->_full_cmd[0] == '_')
|
2001-05-09 03:11:22 +00:00
|
|
|
continue;
|
2006-03-28 22:25:08 +00:00
|
|
|
if (match && strncasecmp(matchstr, e->_full_cmd, len))
|
|
|
|
continue;
|
2012-10-01 17:05:37 +00:00
|
|
|
ast_cli(fd, "%-30s -- %s\n", e->_full_cmd,
|
|
|
|
S_OR(e->summary, "<no description available>"));
|
2006-03-28 22:25:08 +00:00
|
|
|
found++;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2006-11-17 22:53:57 +00:00
|
|
|
if (!locked)
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2008-01-09 20:30:54 +00:00
|
|
|
if (!found && matchstr[0])
|
2006-03-28 22:25:08 +00:00
|
|
|
ast_cli(fd, "No such command '%s'.\n", matchstr);
|
2006-11-17 22:53:57 +00:00
|
|
|
return CLI_SUCCESS;
|
2006-03-28 22:25:08 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 22:53:57 +00:00
|
|
|
static char *handle_help(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
2006-03-28 22:25:08 +00:00
|
|
|
{
|
1999-12-19 22:38:55 +00:00
|
|
|
char fullcmd[80];
|
2006-11-17 22:53:57 +00:00
|
|
|
struct ast_cli_entry *my_e;
|
2008-01-09 20:13:14 +00:00
|
|
|
char *res = CLI_SUCCESS;
|
2006-03-28 22:25:08 +00:00
|
|
|
|
2006-11-17 22:53:57 +00:00
|
|
|
if (cmd == CLI_INIT) {
|
2008-11-12 06:46:04 +00:00
|
|
|
e->command = "core show help";
|
2006-11-17 22:53:57 +00:00
|
|
|
e->usage =
|
2008-11-12 06:46:04 +00:00
|
|
|
"Usage: core show help [topic]\n"
|
2006-11-17 22:53:57 +00:00
|
|
|
" When called with a topic as an argument, displays usage\n"
|
|
|
|
" information on the given command. If called without a\n"
|
|
|
|
" topic, it provides a list of commands.\n";
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
} else if (cmd == CLI_GENERATE) {
|
2008-11-12 06:46:04 +00:00
|
|
|
/* skip first 14 or 15 chars, "core show help " */
|
2006-11-17 22:53:57 +00:00
|
|
|
int l = strlen(a->line);
|
|
|
|
|
2008-11-12 06:46:04 +00:00
|
|
|
if (l > 15) {
|
|
|
|
l = 15;
|
|
|
|
}
|
2006-11-17 22:53:57 +00:00
|
|
|
/* XXX watch out, should stop to the non-generator parts */
|
|
|
|
return __ast_cli_generator(a->line + l, a->word, a->n, 0);
|
|
|
|
}
|
2008-11-12 06:46:04 +00:00
|
|
|
if (a->argc == e->args) {
|
2006-11-17 22:53:57 +00:00
|
|
|
return help1(a->fd, NULL, 0);
|
2008-11-12 06:46:04 +00:00
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_RDLOCK(&helpers);
|
2008-11-12 06:46:04 +00:00
|
|
|
my_e = find_cli(a->argv + 3, 1); /* try exact match first */
|
2008-01-09 20:13:14 +00:00
|
|
|
if (!my_e) {
|
2008-11-12 06:46:04 +00:00
|
|
|
res = help1(a->fd, a->argv + 3, 1 /* locked */);
|
2008-01-09 20:13:14 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
|
|
|
return res;
|
|
|
|
}
|
2006-11-17 22:53:57 +00:00
|
|
|
if (my_e->usage)
|
|
|
|
ast_cli(a->fd, "%s", my_e->usage);
|
2006-03-28 22:25:08 +00:00
|
|
|
else {
|
2008-11-12 06:46:04 +00:00
|
|
|
ast_join(fullcmd, sizeof(fullcmd), a->argv + 3);
|
2006-11-17 22:53:57 +00:00
|
|
|
ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2008-01-09 20:13:14 +00:00
|
|
|
return res;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static char *parse_args(const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2008-08-10 20:23:50 +00:00
|
|
|
char *duplicate, *cur;
|
2005-06-10 20:25:23 +00:00
|
|
|
int x = 0;
|
|
|
|
int quoted = 0;
|
|
|
|
int escaped = 0;
|
|
|
|
int whitespace = 1;
|
2006-11-16 14:58:24 +00:00
|
|
|
int dummy = 0;
|
2005-06-10 20:25:23 +00:00
|
|
|
|
2006-11-16 14:58:24 +00:00
|
|
|
if (trailingwhitespace == NULL)
|
|
|
|
trailingwhitespace = &dummy;
|
2005-09-25 03:13:00 +00:00
|
|
|
*trailingwhitespace = 0;
|
2006-03-28 22:25:08 +00:00
|
|
|
if (s == NULL) /* invalid, though! */
|
|
|
|
return NULL;
|
|
|
|
/* make a copy to store the parsed string */
|
2008-08-10 20:23:50 +00:00
|
|
|
if (!(duplicate = ast_strdup(s)))
|
2005-06-10 20:25:23 +00:00
|
|
|
return NULL;
|
|
|
|
|
2008-08-10 20:23:50 +00:00
|
|
|
cur = duplicate;
|
2013-08-15 16:37:06 +00:00
|
|
|
|
|
|
|
/* Remove leading spaces from the command */
|
|
|
|
while (isspace(*s)) {
|
|
|
|
cur++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
/* scan the original string copying into cur when needed */
|
|
|
|
for (; *s ; s++) {
|
|
|
|
if (x >= max - 1) {
|
|
|
|
ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*s == '"' && !escaped) {
|
2005-06-10 20:25:23 +00:00
|
|
|
quoted = !quoted;
|
2006-03-28 22:25:08 +00:00
|
|
|
if (quoted && whitespace) {
|
|
|
|
/* start a quoted string from previous whitespace: new argument */
|
2005-06-10 20:25:23 +00:00
|
|
|
argv[x++] = cur;
|
|
|
|
whitespace = 0;
|
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
} else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
|
2005-06-10 20:25:23 +00:00
|
|
|
/* If we are not already in whitespace, and not in a quoted string or
|
|
|
|
processing an escape sequence, and just entered whitespace, then
|
|
|
|
finalize the previous argument and remember that we are in whitespace
|
|
|
|
*/
|
|
|
|
if (!whitespace) {
|
2006-03-28 22:25:08 +00:00
|
|
|
*cur++ = '\0';
|
2005-06-10 20:25:23 +00:00
|
|
|
whitespace = 1;
|
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
} else if (*s == '\\' && !escaped) {
|
2005-06-10 20:25:23 +00:00
|
|
|
escaped = 1;
|
|
|
|
} else {
|
|
|
|
if (whitespace) {
|
2006-03-28 22:25:08 +00:00
|
|
|
/* we leave whitespace, and are not quoted. So it's a new argument */
|
2005-06-10 20:25:23 +00:00
|
|
|
argv[x++] = cur;
|
|
|
|
whitespace = 0;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
*cur++ = *s;
|
2005-06-10 20:25:23 +00:00
|
|
|
escaped = 0;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
}
|
2005-06-10 20:25:23 +00:00
|
|
|
/* Null terminate */
|
2006-03-28 22:25:08 +00:00
|
|
|
*cur++ = '\0';
|
|
|
|
/* XXX put a NULL in the last argument, because some functions that take
|
|
|
|
* the array may want a null-terminated array.
|
|
|
|
* argc still reflects the number of non-NULL entries.
|
|
|
|
*/
|
2005-06-10 20:25:23 +00:00
|
|
|
argv[x] = NULL;
|
|
|
|
*argc = x;
|
2005-09-25 03:13:00 +00:00
|
|
|
*trailingwhitespace = whitespace;
|
2008-08-10 20:23:50 +00:00
|
|
|
return duplicate;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
char **ast_cli_completion_matches(const char *text, const char *word)
|
2013-09-10 18:05:47 +00:00
|
|
|
{
|
2017-11-07 23:07:35 +00:00
|
|
|
struct ast_vector_string *vec = ast_cli_completion_vector(text, word);
|
|
|
|
char **match_list;
|
2013-09-10 18:05:47 +00:00
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
if (!vec) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AST_VECTOR_APPEND(vec, NULL)) {
|
|
|
|
/* We failed to NULL terminate the elements */
|
|
|
|
AST_VECTOR_CALLBACK_VOID(vec, ast_free);
|
|
|
|
AST_VECTOR_PTR_FREE(vec);
|
|
|
|
|
|
|
|
return NULL;
|
2013-09-10 18:05:47 +00:00
|
|
|
}
|
2017-11-07 23:07:35 +00:00
|
|
|
|
|
|
|
match_list = AST_VECTOR_STEAL_ELEMENTS(vec);
|
|
|
|
AST_VECTOR_PTR_FREE(vec);
|
|
|
|
|
|
|
|
return match_list;
|
2013-09-10 18:05:47 +00:00
|
|
|
}
|
|
|
|
|
2017-11-09 05:42:10 +00:00
|
|
|
AST_THREADSTORAGE_RAW(completion_storage);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Add a value to the vector.
|
|
|
|
*
|
|
|
|
* \param vec Vector to add \a value to. Must be from threadstorage.
|
|
|
|
* \param value The value to add.
|
|
|
|
*
|
|
|
|
* \retval 0 Success
|
|
|
|
* \retval -1 Failure
|
|
|
|
*/
|
|
|
|
static int cli_completion_vector_add(struct ast_vector_string *vec, char *value)
|
|
|
|
{
|
|
|
|
if (!value) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
|
|
|
|
if (vec) {
|
|
|
|
ast_threadstorage_set_ptr(&completion_storage, NULL);
|
|
|
|
|
|
|
|
AST_VECTOR_CALLBACK_VOID(vec, ast_free);
|
|
|
|
AST_VECTOR_FREE(vec);
|
|
|
|
}
|
|
|
|
ast_free(value);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ast_cli_completion_add(char *value)
|
|
|
|
{
|
|
|
|
return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value);
|
|
|
|
}
|
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
struct ast_vector_string *ast_cli_completion_vector(const char *text, const char *word)
|
2003-01-30 15:03:20 +00:00
|
|
|
{
|
2017-11-07 23:07:35 +00:00
|
|
|
char *retstr, *prevstr;
|
|
|
|
size_t max_equal;
|
|
|
|
size_t which = 0;
|
|
|
|
struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
|
2003-01-30 15:03:20 +00:00
|
|
|
|
2017-11-09 05:42:10 +00:00
|
|
|
/* Recursion into this function is a coding error. */
|
|
|
|
ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
|
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
if (!vec) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-11-09 05:42:10 +00:00
|
|
|
if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
|
|
|
|
ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
|
|
|
|
ast_free(vec);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
|
2017-11-09 05:42:10 +00:00
|
|
|
if (cli_completion_vector_add(vec, retstr)) {
|
|
|
|
ast_threadstorage_set_ptr(&completion_storage, NULL);
|
2017-11-07 23:07:35 +00:00
|
|
|
|
|
|
|
goto vector_cleanup;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
2017-11-07 23:07:35 +00:00
|
|
|
|
|
|
|
++which;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
|
|
|
|
2017-11-09 05:42:10 +00:00
|
|
|
ast_threadstorage_set_ptr(&completion_storage, NULL);
|
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
if (!AST_VECTOR_SIZE(vec)) {
|
|
|
|
AST_VECTOR_PTR_FREE(vec);
|
|
|
|
|
|
|
|
return NULL;
|
2013-09-10 18:05:47 +00:00
|
|
|
}
|
2003-01-30 15:03:20 +00:00
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
prevstr = AST_VECTOR_GET(vec, 0);
|
|
|
|
max_equal = strlen(prevstr);
|
|
|
|
which = 1;
|
|
|
|
|
2006-03-28 22:25:08 +00:00
|
|
|
/* Find the longest substring that is common to all results
|
|
|
|
* (it is a candidate for completion), and store a copy in entry 0.
|
|
|
|
*/
|
2017-11-07 23:07:35 +00:00
|
|
|
while (which < AST_VECTOR_SIZE(vec)) {
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
retstr = AST_VECTOR_GET(vec, which);
|
|
|
|
/* Check for and remove duplicate strings. */
|
|
|
|
if (!strcasecmp(prevstr, retstr)) {
|
|
|
|
AST_VECTOR_REMOVE(vec, which, 1);
|
|
|
|
ast_free(retstr);
|
|
|
|
|
2003-01-30 15:03:20 +00:00
|
|
|
continue;
|
2017-11-07 23:07:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (i < max_equal && toupper(prevstr[i]) == toupper(retstr[i])) {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2003-01-30 15:03:20 +00:00
|
|
|
max_equal = i;
|
2017-11-07 23:07:35 +00:00
|
|
|
prevstr = retstr;
|
|
|
|
++which;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
/* Insert longest match to position 0. */
|
|
|
|
retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
|
|
|
|
if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
|
|
|
|
ast_free(retstr);
|
2017-11-09 05:42:10 +00:00
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
goto vector_cleanup;
|
2012-05-18 14:43:44 +00:00
|
|
|
}
|
2003-01-30 15:03:20 +00:00
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
return vec;
|
2003-01-30 15:03:20 +00:00
|
|
|
|
2017-11-07 23:07:35 +00:00
|
|
|
vector_cleanup:
|
|
|
|
AST_VECTOR_CALLBACK_VOID(vec, ast_free);
|
|
|
|
AST_VECTOR_PTR_FREE(vec);
|
|
|
|
|
|
|
|
return NULL;
|
2003-01-30 15:03:20 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 22:53:57 +00:00
|
|
|
/*! \brief returns true if there are more words to match */
|
2009-05-21 21:13:09 +00:00
|
|
|
static int more_words (const char * const *dst)
|
2006-11-17 22:53:57 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; dst[i]; i++) {
|
|
|
|
if (dst[i][0] != '[')
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-03-22 19:51:16 +00:00
|
|
|
|
2006-11-17 11:12:13 +00:00
|
|
|
/*
|
|
|
|
* generate the entry at position 'state'
|
|
|
|
*/
|
2006-01-18 22:17:31 +00:00
|
|
|
static char *__ast_cli_generator(const char *text, const char *word, int state, int lock)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *argv[AST_MAX_ARGS];
|
2007-10-15 13:44:53 +00:00
|
|
|
struct ast_cli_entry *e = NULL;
|
2006-03-28 22:25:08 +00:00
|
|
|
int x = 0, argindex, matchlen;
|
1999-12-19 22:38:55 +00:00
|
|
|
int matchnum=0;
|
2006-03-28 22:25:08 +00:00
|
|
|
char *ret = NULL;
|
2005-08-14 01:48:14 +00:00
|
|
|
char matchstr[80] = "";
|
2006-05-19 19:35:16 +00:00
|
|
|
int tws = 0;
|
2006-12-12 09:40:45 +00:00
|
|
|
/* Split the argument into an array of words */
|
2008-08-10 20:23:50 +00:00
|
|
|
char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
|
1999-12-19 22:38:55 +00:00
|
|
|
|
2008-08-10 20:23:50 +00:00
|
|
|
if (!duplicate) /* malloc error */
|
2006-03-28 22:25:08 +00:00
|
|
|
return NULL;
|
2006-12-12 09:40:45 +00:00
|
|
|
|
|
|
|
/* Compute the index of the last argument (could be an empty string) */
|
2006-03-28 22:25:08 +00:00
|
|
|
argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
|
2006-12-12 09:40:45 +00:00
|
|
|
|
|
|
|
/* rebuild the command, ignore terminating white space and flatten space */
|
2006-03-28 22:25:08 +00:00
|
|
|
ast_join(matchstr, sizeof(matchstr)-1, argv);
|
|
|
|
matchlen = strlen(matchstr);
|
2006-05-19 19:35:16 +00:00
|
|
|
if (tws) {
|
|
|
|
strcat(matchstr, " "); /* XXX */
|
|
|
|
if (matchlen)
|
|
|
|
matchlen++;
|
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
if (lock)
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_RDLOCK(&helpers);
|
2007-10-15 13:44:53 +00:00
|
|
|
while ( (e = cli_next(e)) ) {
|
2006-11-17 11:12:13 +00:00
|
|
|
/* XXX repeated code */
|
|
|
|
int src = 0, dst = 0, n = 0;
|
2006-12-12 09:40:45 +00:00
|
|
|
|
2007-11-28 15:48:00 +00:00
|
|
|
if (e->command[0] == '_')
|
|
|
|
continue;
|
|
|
|
|
2006-12-12 09:40:45 +00:00
|
|
|
/*
|
|
|
|
* Try to match words, up to and excluding the last word, which
|
|
|
|
* is either a blank or something that we want to extend.
|
|
|
|
*/
|
|
|
|
for (;src < argindex; dst++, src += n) {
|
2006-11-17 11:12:13 +00:00
|
|
|
n = word_match(argv[src], e->cmda[dst]);
|
|
|
|
if (n < 0)
|
2006-11-13 12:04:05 +00:00
|
|
|
break;
|
2006-11-17 11:12:13 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 22:53:57 +00:00
|
|
|
if (src != argindex && more_words(e->cmda + dst)) /* not a match */
|
2006-11-17 11:12:13 +00:00
|
|
|
continue;
|
|
|
|
ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
|
|
|
|
matchnum += n; /* this many matches here */
|
|
|
|
if (ret) {
|
2006-12-12 09:40:45 +00:00
|
|
|
/*
|
|
|
|
* argv[src] is a valid prefix of the next word in this
|
|
|
|
* command. If this is also the correct entry, return it.
|
|
|
|
*/
|
2006-11-17 11:12:13 +00:00
|
|
|
if (matchnum > state)
|
|
|
|
break;
|
2007-06-06 21:20:11 +00:00
|
|
|
ast_free(ret);
|
2006-11-17 11:12:13 +00:00
|
|
|
ret = NULL;
|
|
|
|
} else if (ast_strlen_zero(e->cmda[dst])) {
|
2006-12-12 09:40:45 +00:00
|
|
|
/*
|
|
|
|
* This entry is a prefix of the command string entered
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
* (only one entry in the list should have this property).
|
|
|
|
* Run the generator if one is available. In any case we are done.
|
|
|
|
*/
|
2007-11-28 20:27:40 +00:00
|
|
|
if (e->handler) { /* new style command */
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
struct ast_cli_args a = {
|
|
|
|
.line = matchstr, .word = word,
|
|
|
|
.pos = argindex,
|
2008-09-06 12:03:11 +00:00
|
|
|
.n = state - matchnum,
|
|
|
|
.argv = argv,
|
|
|
|
.argc = x};
|
2017-12-30 00:24:02 +00:00
|
|
|
|
|
|
|
/* If the command is in a module it must be running. */
|
|
|
|
if (!e->module || ast_module_running_ref(e->module)) {
|
|
|
|
ret = e->handler(e, CLI_GENERATE, &a);
|
|
|
|
ast_module_unref(e->module);
|
|
|
|
}
|
Bring in the improved internal API for the CLI.
WATCH OUT: this changes the binary interface (ABI) for modules,
so e.g. users of g729 codecs need a rebuilt module (but read below).
The new way to write CLI handlers is described in detail in cli.h,
and there are a few converted handlers in cli.c, look for NEW_CLI.
After converting a couple of commands i am convinced that
it is reasonably convenient to use, and it makes it easier to fix the
pending CLI issues.
On passing, note a bug with the current 'complete' architecture:
if a command is a prefix of multiple CLI entries, we miss some
of the possible options. As an example, "core set debug" can
continue with "channel" from one CLI entry, and "off" or "atleast"
from another one.
We address this problem in a separate commit
(when i have figured out a fix, that is).
ABI issues:
I asked Kevin if it was ok to make this change and he said yes.
While it would have been possible to make the change without breaking
the module ABI, the code would have been more convoluted.
I am happy to restore the old ABI (while still being able
to use the "new style" handlers) if there is demand.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-14 15:23:35 +00:00
|
|
|
}
|
|
|
|
if (ret)
|
|
|
|
break;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
}
|
2006-03-28 22:25:08 +00:00
|
|
|
if (lock)
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2008-08-10 20:23:50 +00:00
|
|
|
ast_free(duplicate);
|
2006-03-28 22:25:08 +00:00
|
|
|
return ret;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2006-01-18 22:17:31 +00:00
|
|
|
char *ast_cli_generator(const char *text, const char *word, int state)
|
2001-05-09 03:11:22 +00:00
|
|
|
{
|
|
|
|
return __ast_cli_generator(text, word, state, 1);
|
|
|
|
}
|
|
|
|
|
2016-03-10 22:58:49 +00:00
|
|
|
static int allowed_on_shutdown(struct ast_cli_entry *e)
|
|
|
|
{
|
|
|
|
int found = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
ast_rwlock_rdlock(&shutdown_commands_lock);
|
|
|
|
for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) {
|
|
|
|
if (e == AST_VECTOR_GET(&shutdown_commands, i)) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_rwlock_unlock(&shutdown_commands_lock);
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
int ast_cli_command_full(int uid, int gid, int fd, const char *s)
|
1999-12-19 22:38:55 +00:00
|
|
|
{
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *args[AST_MAX_ARGS + 1];
|
2016-03-10 22:58:49 +00:00
|
|
|
struct ast_cli_entry *e = NULL;
|
1999-12-19 22:38:55 +00:00
|
|
|
int x;
|
2008-08-10 20:23:50 +00:00
|
|
|
char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
|
2008-12-01 18:52:14 +00:00
|
|
|
char tmp[AST_MAX_ARGS + 1];
|
2015-04-17 03:34:59 +00:00
|
|
|
char *retval = CLI_FAILURE;
|
2007-11-28 22:32:57 +00:00
|
|
|
struct ast_cli_args a = {
|
|
|
|
.fd = fd, .argc = x, .argv = args+1 };
|
2006-11-16 14:58:24 +00:00
|
|
|
|
2008-08-10 20:23:50 +00:00
|
|
|
if (duplicate == NULL)
|
2015-04-17 03:34:59 +00:00
|
|
|
return RESULT_FAILURE;
|
2005-11-29 04:25:28 +00:00
|
|
|
|
2006-11-16 14:58:24 +00:00
|
|
|
if (x < 1) /* We need at least one entry, otherwise ignore */
|
|
|
|
goto done;
|
|
|
|
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_RDLOCK(&helpers);
|
2006-11-16 14:58:24 +00:00
|
|
|
e = find_cli(args + 1, 0);
|
|
|
|
if (e)
|
|
|
|
ast_atomic_fetchadd_int(&e->inuse, 1);
|
2007-08-01 15:28:02 +00:00
|
|
|
AST_RWLIST_UNLOCK(&helpers);
|
2006-11-16 14:58:24 +00:00
|
|
|
if (e == NULL) {
|
2008-11-12 06:46:04 +00:00
|
|
|
ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
|
2006-11-16 14:58:24 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2008-12-01 18:52:14 +00:00
|
|
|
|
2016-03-10 22:58:49 +00:00
|
|
|
if (ast_shutting_down() && !allowed_on_shutdown(e)) {
|
|
|
|
ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
ast_join(tmp, sizeof(tmp), args + 1);
|
|
|
|
/* Check if the user has rights to run this command. */
|
|
|
|
if (!cli_has_permissions(uid, gid, tmp)) {
|
|
|
|
ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
|
2015-04-17 03:34:59 +00:00
|
|
|
goto done;
|
2008-12-01 18:52:14 +00:00
|
|
|
}
|
|
|
|
|
2006-11-16 14:58:24 +00:00
|
|
|
/*
|
|
|
|
* Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
|
|
|
|
* Remember that the array returned by parse_args is NULL-terminated.
|
|
|
|
*/
|
|
|
|
args[0] = (char *)e;
|
|
|
|
|
2017-12-30 00:24:02 +00:00
|
|
|
/* If the command is in a module it must be running. */
|
|
|
|
if (!e->module || ast_module_running_ref(e->module)) {
|
|
|
|
retval = e->handler(e, CLI_HANDLER, &a);
|
|
|
|
ast_module_unref(e->module);
|
|
|
|
}
|
2007-11-28 20:27:40 +00:00
|
|
|
|
|
|
|
if (retval == CLI_SHOWUSAGE) {
|
2006-11-16 14:58:24 +00:00
|
|
|
ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
|
2015-04-17 03:34:59 +00:00
|
|
|
} else if (retval == CLI_FAILURE) {
|
|
|
|
ast_cli(fd, "Command '%s' failed.\n", s);
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2016-03-10 22:58:49 +00:00
|
|
|
|
2006-11-16 14:58:24 +00:00
|
|
|
done:
|
2016-03-10 22:58:49 +00:00
|
|
|
if (e) {
|
|
|
|
ast_atomic_fetchadd_int(&e->inuse, -1);
|
|
|
|
}
|
2008-08-10 20:23:50 +00:00
|
|
|
ast_free(duplicate);
|
2015-04-17 03:34:59 +00:00
|
|
|
return retval == CLI_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE;
|
1999-12-19 22:38:55 +00:00
|
|
|
}
|
2007-10-21 22:52:20 +00:00
|
|
|
|
2008-12-01 18:52:14 +00:00
|
|
|
int ast_cli_command_multiple_full(int uid, int gid, int fd, size_t size, const char *s)
|
2007-10-21 22:52:20 +00:00
|
|
|
{
|
|
|
|
char cmd[512];
|
|
|
|
int x, y = 0, count = 0;
|
|
|
|
|
|
|
|
for (x = 0; x < size; x++) {
|
|
|
|
cmd[y] = s[x];
|
|
|
|
y++;
|
|
|
|
if (s[x] == '\0') {
|
2008-12-01 18:52:14 +00:00
|
|
|
ast_cli_command_full(uid, gid, fd, cmd);
|
2007-10-21 22:52:20 +00:00
|
|
|
y = 0;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
2016-02-18 04:58:01 +00:00
|
|
|
|
|
|
|
void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix)
|
|
|
|
{
|
|
|
|
print_uptimestr(fd, ast_tv(seconds, 0), prefix, 0);
|
|
|
|
}
|
2016-03-10 22:58:49 +00:00
|
|
|
|
|
|
|
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
|
|
|
|
ast_rwlock_wrlock(&shutdown_commands_lock);
|
|
|
|
res = AST_VECTOR_APPEND(&shutdown_commands, e);
|
|
|
|
ast_rwlock_unlock(&shutdown_commands_lock);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|