Newer
Older
* Asterisk -- An open source telephony toolkit.
* Copyright (C) 1999 - 2014, Digium, Inc.
* Mark Spencer <markster@digium.com>
* 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.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/* Doxygenified Copyright Header */
/*!
Russell Bryant
committed
* \mainpage Asterisk -- The Open Source Telephony Project
* \par Welcome
*
* This documentation created by the Doxygen project clearly explains the
* internals of the Asterisk software. This documentation contains basic
* examples, developer documentation, support information, and information
* for upgrading.
* \section community Community
* Asterisk is a big project and has a busy community. Look at the
* resources for questions and stick around to help answer questions.
* \li \ref asterisk_community_resources
*
* \par Developer Documentation for Asterisk
* This is the main developer documentation for Asterisk. It is
* generated by running "make progdocs" from the Asterisk source tree.
* In addition to the information available on the Asterisk source code,
* please see the appendices for information on coding guidelines,
* release management, commit policies, and more.
*
Russell Bryant
committed
* \arg \ref AsteriskArchitecture
*
* \par Additional documentation
Russell Bryant
committed
* \arg \ref Licensing
* \arg \ref channel_drivers
* \arg \ref applications
* \section copyright Copyright and Author
* Copyright (C) 1999 - 2014, Digium, Inc.
* Asterisk is a <a href="http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy">registered trademark</a>
* of <a rel="nofollow" href="http://www.digium.com">Digium, Inc</a>.
*
* \author Mark Spencer <markster@digium.com>
*
* 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.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
*/
/*!
* \page asterisk_community_resources Asterisk Community Resources
* \par Websites
* \li http://www.asterisk.org Asterisk Homepage
* \li http://wiki.asterisk.org Asterisk Wiki
*
* \par Mailing Lists
* \par
* All lists: http://lists.digium.com/mailman/listinfo
* \li aadk-commits SVN commits to the AADK repository
* \li asterisk-addons-commits SVN commits to the Asterisk addons project
* \li asterisk-announce [no description available]
* \li asterisk-biz Commercial and Business-Oriented Asterisk Discussion
* \li Asterisk-BSD Asterisk on BSD discussion
* \li asterisk-bugs [no description available]
* \li asterisk-commits SVN commits to the Asterisk project
* \li asterisk-dev Asterisk Developers Mailing List
* \li asterisk-doc Discussions regarding The Asterisk Documentation Project
* \li asterisk-embedded Asterisk Embedded Development
* \li asterisk-gui Asterisk GUI project discussion
* \li asterisk-gui-commits SVN commits to the Asterisk-GUI project
* \li asterisk-ha-clustering Asterisk High Availability and Clustering List - Non-Commercial Discussion
* \li Asterisk-i18n Discussion of Asterisk internationalization
* \li asterisk-r2 [no description available]
* \li asterisk-scf-commits Commits to the Asterisk SCF project code repositories
* \li asterisk-scf-committee Asterisk SCF Steering Committee discussions
* \li asterisk-scf-dev Asterisk SCF Developers Mailing List
* \li asterisk-scf-wiki-changes Changes to the Asterisk SCF space on wiki.asterisk.org
* \li asterisk-security Asterisk Security Discussion
* \li asterisk-speech-rec Use of speech recognition in Asterisk
* \li asterisk-ss7 [no description available]
* \li asterisk-users Asterisk Users Mailing List - Non-Commercial Discussion
* \li asterisk-video Development discussion of video media support in Asterisk
* \li asterisk-wiki-changes Changes to the Asterisk space on wiki.asterisk.org
* \li asterisknow AsteriskNOW Discussion
* \li dahdi-commits SVN commits to the DAHDI project
* \li digium-announce Digium Product Announcements
* \li Dundi Distributed Universal Number Discovery
* \li libiax2-commits SVN commits to the libiax2 project
* \li libpri-commits SVN commits to the libpri project
* \li libss7-commits SVN commits to the libss7 project
* \li svn-commits SVN commits to the Digium repositories
* \li Test-results Results from automated testing
* \li thirdparty-commits SVN commits to the Digium third-party software repository
* \li zaptel-commits SVN commits to the Zaptel project
*
* \par Forums
* \li Forums are located at http://forums.asterisk.org/
*
* \par IRC
* \par
* Use http://www.freenode.net IRC server to connect with Asterisk
* developers and users in realtime.
* \li \verbatim #asterisk \endverbatim Asterisk Users Room
* \li \verbatim #asterisk-dev \endverbatim Asterisk Developers Room
*
* \par More
* \par
* If you would like to add a resource to this list please create an issue
* on the issue tracker with a patch.
*/
/*! \file
* \brief Top level source file for Asterisk - the Open Source PBX.
* Implementation of PBX core functions and CLI interface.
/*! \li \ref asterisk.c uses the configuration file \ref asterisk.conf
* \addtogroup configuration_file
*/
/*! \page asterisk.conf asterisk.conf
* \verbinclude asterisk.conf.sample
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
Kevin P. Fleming
committed
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/_private.h"
#undef sched_setscheduler
#undef setpriority
#include <sys/time.h>
#include <fcntl.h>
#include <signal.h>
#include <sched.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <ctype.h>
#include <sys/resource.h>
#include <grp.h>
#include <pwd.h>
#include <sys/stat.h>
Joshua Colp
committed
#if defined(HAVE_SYSINFO)
Dwayne M. Hubbard
committed
#include <sys/sysinfo.h>
Michiel van Baak
committed
#elif defined(HAVE_SYSCTL)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#if defined(__FreeBSD__)
#include <vm/vm_param.h>
#endif
Michiel van Baak
committed
#include <sys/swap.h>
Dwayne M. Hubbard
committed
#endif
#include <histedit.h>
Kevin P. Fleming
committed
int daemon(int, int); /* defined in libresolv of all places */
#ifdef linux
#include <sys/prctl.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#endif /* linux */
/* we define here the variables so to better agree on the prototype */
#include "asterisk/paths.h"
#include "asterisk/network.h"
Kevin P. Fleming
committed
#include "asterisk/cli.h"
#include "asterisk/channel.h"
#include "asterisk/translate.h"
#include "asterisk/pickup.h"
#include "asterisk/features.h"
#include "asterisk/acl.h"
Kevin P. Fleming
committed
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/image.h"
#include "asterisk/tdd.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cdr.h"
#include "asterisk/cel.h"
Kevin P. Fleming
committed
#include "asterisk/pbx.h"
#include "asterisk/enum.h"
#include "asterisk/http.h"
#include "asterisk/udptl.h"
Kevin P. Fleming
committed
#include "asterisk/app.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/io.h"
Kevin P. Fleming
committed
#include "asterisk/config.h"
#include "asterisk/linkedlists.h"
Kevin P. Fleming
committed
#include "asterisk/devicestate.h"
#include "asterisk/presencestate.h"
#include "asterisk/dsp.h"
#include "asterisk/buildinfo.h"
#include "asterisk/xmldoc.h"
#include "asterisk/poll-compat.h"
David Vossel
committed
#include "asterisk/rtp_engine.h"
#include "asterisk/format.h"
#include "asterisk/stasis.h"
#include "asterisk/json.h"
#include "asterisk/stasis_system.h"
#include "asterisk/security_events.h"
#include "asterisk/codec.h"
#include "asterisk/format_cache.h"
#include "asterisk/astdb.h"
#include "asterisk/options.h"
Kevin P. Fleming
committed
#include "../defaults.h"
Mark Spencer
committed
Matthew Jordan
committed
/*** DOCUMENTATION
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
<managerEvent language="en_US" name="FullyBooted">
<managerEventInstance class="EVENT_FLAG_SYSTEM">
<synopsis>Raised when all Asterisk initialization procedures have finished.</synopsis>
<syntax>
<parameter name="Status">
<para>Informational message</para>
</parameter>
</syntax>
</managerEventInstance>
</managerEvent>
<managerEvent language="en_US" name="Shutdown">
<managerEventInstance class="EVENT_FLAG_SYSTEM">
<synopsis>Raised when Asterisk is shutdown or restarted.</synopsis>
<syntax>
<parameter name="Shutdown">
<para>Whether the shutdown is proceeding cleanly (all channels
were hungup successfully) or uncleanly (channels will be
terminated)</para>
<enumlist>
<enum name="Uncleanly"/>
<enum name="Cleanly"/>
</enumlist>
</parameter>
<parameter name="Restart">
<para>Whether or not a restart will occur.</para>
<enumlist>
<enum name="True"/>
<enum name="False"/>
</enumlist>
</parameter>
</syntax>
</managerEventInstance>
</managerEvent>
Matthew Jordan
committed
***/
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#define PF_LOCAL PF_UNIX
#endif
#define AST_MAX_CONNECTS 128
#define NUM_MSGS 64
/*! Default minimum DTMF digit length - 80ms */
#define AST_MIN_DTMF_DURATION 80
/*! \brief Welcome message when starting a CLI interface */
ast_verbose("Asterisk %s, Copyright (C) 1999 - 2014, Digium, Inc. and others.\n" \
Russell Bryant
committed
"Created by Mark Spencer <markster@digium.com>\n" \
"Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
"This is free software, with components licensed under the GNU General Public\n" \
"License version 2 and other licenses; you are welcome to redistribute it under\n" \
"certain conditions. Type 'core show license' for details.\n" \
"=========================================================================\n", ast_get_version()) \
/*! \defgroup main_options Main Configuration Options
* \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
* \arg \ref Config_ast "asterisk.conf"
* \note Some of them can be changed in the CLI
Russell Bryant
committed
struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
Russell Bryant
committed
/*! Maximum active system verbosity level. */
int ast_verb_sys_level;
int option_verbose; /*!< Verbosity level */
int option_debug; /*!< Debug level */
int ast_pjproject_max_log_level = -1;/* Default to -1 to know if we have read the level from pjproject yet. */
int ast_option_pjproject_log_level;
double ast_option_maxload; /*!< Max load avg on system */
int ast_option_maxcalls; /*!< Max number of active calls */
int ast_option_maxfiles; /*!< Max number of open file handles (files, sockets) */
unsigned int option_dtmfminduration; /*!< Minimum duration of DTMF. */
Joshua Colp
committed
#if defined(HAVE_SYSINFO)
Dwayne M. Hubbard
committed
long option_minmemfree; /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
Dwayne M. Hubbard
committed
#endif
unsigned int ast_option_rtpptdynamic;
/* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
pid_t ast_mainpid;
int fd; /*!< File descriptor */
int p[2]; /*!< Pipe */
pthread_t t; /*!< Thread of handler */
Joshua Colp
committed
int mute; /*!< Is the console muted for logs */
int uid; /*!< Remote user ID. */
int gid; /*!< Remote group ID. */
int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
/*! Verbosity level of this console. */
int option_verbose;
Russell Bryant
committed
struct ast_atexit {
void (*func)(void);
AST_LIST_ENTRY(ast_atexit) list;
Russell Bryant
committed
};
static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
Tilghman Lesher
committed
struct timeval ast_startuptime;
struct timeval ast_lastreloadtime;
static History *el_hist;
static EditLine *el;
char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
static int ast_el_add_history(const char *);
static int ast_el_read_history(const char *);
static int ast_el_write_history(const char *);
static void ast_el_read_default_histfile(void);
static void ast_el_write_default_histfile(void);
static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup);
#define DEFAULT_MONITOR_DIR DEFAULT_SPOOL_DIR "/monitor"
#define DEFAULT_RECORDING_DIR DEFAULT_SPOOL_DIR "/recording"
struct _cfg_paths {
char config_dir[PATH_MAX];
char module_dir[PATH_MAX];
char spool_dir[PATH_MAX];
char monitor_dir[PATH_MAX];
char var_dir[PATH_MAX];
char data_dir[PATH_MAX];
char log_dir[PATH_MAX];
char agi_dir[PATH_MAX];
char run_dir[PATH_MAX];
char key_dir[PATH_MAX];
char config_file[PATH_MAX];
char db_path[PATH_MAX];
char sbin_dir[PATH_MAX];
char pid_path[PATH_MAX];
char socket_path[PATH_MAX];
char run_user[PATH_MAX];
char run_group[PATH_MAX];
char system_name[128];
};
static struct _cfg_paths cfg_paths;
const char *ast_config_AST_CONFIG_DIR = cfg_paths.config_dir;
const char *ast_config_AST_CONFIG_FILE = cfg_paths.config_file;
const char *ast_config_AST_MODULE_DIR = cfg_paths.module_dir;
const char *ast_config_AST_SPOOL_DIR = cfg_paths.spool_dir;
const char *ast_config_AST_MONITOR_DIR = cfg_paths.monitor_dir;
const char *ast_config_AST_RECORDING_DIR = cfg_paths.recording_dir;
const char *ast_config_AST_VAR_DIR = cfg_paths.var_dir;
const char *ast_config_AST_DATA_DIR = cfg_paths.data_dir;
const char *ast_config_AST_LOG_DIR = cfg_paths.log_dir;
const char *ast_config_AST_AGI_DIR = cfg_paths.agi_dir;
const char *ast_config_AST_KEY_DIR = cfg_paths.key_dir;
const char *ast_config_AST_RUN_DIR = cfg_paths.run_dir;
const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
const char *ast_config_AST_DB = cfg_paths.db_path;
const char *ast_config_AST_PID = cfg_paths.pid_path;
const char *ast_config_AST_SOCKET = cfg_paths.socket_path;
const char *ast_config_AST_RUN_USER = cfg_paths.run_user;
const char *ast_config_AST_RUN_GROUP = cfg_paths.run_group;
const char *ast_config_AST_SYSTEM_NAME = cfg_paths.system_name;
static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
extern unsigned int ast_FD_SETSIZE;
static char *_argv[256];
typedef enum {
/*! Normal operation */
NOT_SHUTTING_DOWN,
/*! Committed to shutting down. Final phase */
SHUTTING_DOWN_FINAL,
/*! Committed to shutting down. Initial phase */
SHUTTING_DOWN,
/*!
* Valid values for quit_handler() niceness below.
* These shutdown/restart levels can be cancelled.
*
* Remote console exit right now
*/
SHUTDOWN_FAST,
/*! core stop/restart now */
SHUTDOWN_NORMAL,
/*! core stop/restart gracefully */
SHUTDOWN_NICE,
/*! core stop/restart when convenient */
SHUTDOWN_REALLY_NICE
} shutdown_nice_t;
static shutdown_nice_t shuttingdown = NOT_SHUTTING_DOWN;
/*! Prevent new channel allocation for shutdown. */
static int shutdown_pending;
static pthread_t consolethread = AST_PTHREADT_NULL;
Tilghman Lesher
committed
static int canary_pid = 0;
static char canary_filename[128];
Matthew Jordan
committed
static int multi_thread_safe;
static int sig_alert_pipe[2] = { -1, -1 };
static struct {
unsigned int need_reload:1;
unsigned int need_quit:1;
unsigned int need_quit_handler:1;
#if !defined(LOW_MEMORY)
struct registered_file {
AST_RWLIST_ENTRY(registered_file) list;
Kevin P. Fleming
committed
const char *file;
static AST_RWLIST_HEAD_STATIC(registered_files, registered_file);
void ast_register_file_version(const char *file, const char *version)
{
struct registered_file *reg;
reg = ast_calloc(1, sizeof(*reg));
if (!reg) {
reg->file = file;
AST_RWLIST_WRLOCK(®istered_files);
AST_RWLIST_INSERT_HEAD(®istered_files, reg, list);
AST_RWLIST_UNLOCK(®istered_files);
}
void ast_unregister_file_version(const char *file)
{
struct registered_file *find;
AST_RWLIST_WRLOCK(®istered_files);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(®istered_files, find, list) {
if (!strcasecmp(find->file, file)) {
AST_RWLIST_REMOVE_CURRENT(list);
AST_RWLIST_UNLOCK(®istered_files);
Tilghman Lesher
committed
ast_free(find);
char *ast_complete_source_filename(const char *partial, int n)
{
struct registered_file *find;
size_t len = strlen(partial);
int count = 0;
char *res = NULL;
AST_RWLIST_RDLOCK(®istered_files);
AST_RWLIST_TRAVERSE(®istered_files, find, list) {
if (!strncasecmp(find->file, partial, len) && ++count > n) {
res = ast_strdup(find->file);
break;
}
}
AST_RWLIST_UNLOCK(®istered_files);
return res;
}
const char *ast_file_version_find(const char *file)
{
struct registered_file *iterator;
AST_RWLIST_RDLOCK(®istered_files);
AST_RWLIST_TRAVERSE(®istered_files, iterator, list) {
if (!strcasecmp(iterator->file, file)) {
break;
}
}
AST_RWLIST_UNLOCK(®istered_files);
if (iterator) {
return ast_get_version();
return NULL;
AST_RWLIST_ENTRY(thread_list_t) list;
char *name;
pthread_t id;
static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
void ast_register_thread(char *name)
struct thread_list_t *new = ast_calloc(1, sizeof(*new));
if (!new)
return;
Matthew Jordan
committed
ast_assert(multi_thread_safe);
new->lwp = ast_get_tid();
new->name = name; /* steal the allocated memory for the thread name */
AST_RWLIST_WRLOCK(&thread_list);
AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
AST_RWLIST_UNLOCK(&thread_list);
}
void ast_unregister_thread(void *id)
{
struct thread_list_t *x;
AST_RWLIST_WRLOCK(&thread_list);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
AST_RWLIST_REMOVE_CURRENT(list);
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&thread_list);
Tilghman Lesher
committed
ast_free(x->name);
ast_free(x);
/*! \brief Give an overview of core settings */
static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char buf[BUFSIZ];
Tilghman Lesher
committed
struct ast_tm tm;
struct rlimit limits;
char pbx_uuid[AST_UUID_STR_LEN];
switch (cmd) {
case CLI_INIT:
e->command = "core show settings";
e->usage = "Usage: core show settings\n"
" Show core misc settings";
return NULL;
case CLI_GENERATE:
return NULL;
}
ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid));
ast_cli(a->fd, "\nPBX Core settings\n");
ast_cli(a->fd, "-----------------\n");
Russell Bryant
committed
ast_cli(a->fd, " Version: %s\n", ast_get_version());
ast_cli(a->fd, " Build Options: %s\n", S_OR(ast_get_build_opts(), "(none)"));
if (ast_option_maxcalls)
ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", ast_option_maxcalls, ast_active_channels());
ast_cli(a->fd, " Maximum calls: Not set\n");
if (getrlimit(RLIMIT_NOFILE, &limits)) {
ast_cli(a->fd, " Maximum open file handles: Error because of %s\n", strerror(errno));
} else if (limits.rlim_cur == RLIM_INFINITY) {
ast_cli(a->fd, " Maximum open file handles: Unlimited\n");
} else if (limits.rlim_cur < ast_option_maxfiles) {
ast_cli(a->fd, " Maximum open file handles: %d (is) %d (requested)\n", (int) limits.rlim_cur, ast_option_maxfiles);
} else {
ast_cli(a->fd, " Maximum open file handles: %d\n", (int) limits.rlim_cur);
}
ast_cli(a->fd, " Root console verbosity: %d\n", option_verbose);
ast_cli(a->fd, " Current console verbosity: %d\n", ast_verb_console_get());
ast_cli(a->fd, " Debug level: %d\n", option_debug);
ast_cli(a->fd, " Maximum load average: %lf\n", ast_option_maxload);
Joshua Colp
committed
#if defined(HAVE_SYSINFO)
ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
Dwayne M. Hubbard
committed
#endif
if (ast_localtime(&ast_startuptime, &tm, NULL)) {
Tilghman Lesher
committed
ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
ast_cli(a->fd, " Startup time: %s\n", buf);
if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
Tilghman Lesher
committed
ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
ast_cli(a->fd, " Last reload time: %s\n", buf);
ast_cli(a->fd, " System: %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
ast_cli(a->fd, " Entity ID: %s\n", eid_str);
ast_cli(a->fd, " PBX UUID: %s\n", pbx_uuid);
ast_cli(a->fd, " Default language: %s\n", ast_defaultlanguage);
ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration);
#if !defined(LOW_MEMORY)
ast_cli(a->fd, " Cache media frames: %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled");
#endif
if (ast_option_rtpptdynamic == AST_RTP_PT_LAST_REASSIGN) {
ast_cli(a->fd, " RTP dynamic payload types: %u,%u-%u\n",
ast_option_rtpptdynamic,
AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
} else if (ast_option_rtpptdynamic < AST_RTP_PT_LAST_REASSIGN) {
ast_cli(a->fd, " RTP dynamic payload types: %u-%u,%u-%u\n",
ast_option_rtpptdynamic, AST_RTP_PT_LAST_REASSIGN,
AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
} else {
ast_cli(a->fd, " RTP dynamic payload types: %u-%u\n",
AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
}
ast_cli(a->fd, "\n* Subsystems\n");
ast_cli(a->fd, " -------------\n");
ast_cli(a->fd, " Manager (AMI): %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
ast_cli(a->fd, " Web Manager (AMI/HTTP): %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
ast_cli(a->fd, " Call data records: %s\n", ast_cdr_is_enabled() ? "Enabled" : "Disabled");
ast_cli(a->fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
/*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
ast_cli(a->fd, "\n* Directories\n");
ast_cli(a->fd, " -------------\n");
ast_cli(a->fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
ast_cli(a->fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
ast_cli(a->fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
ast_cli(a->fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
ast_cli(a->fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
ast_cli(a->fd, " Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
ast_cli(a->fd, " PID file: %s\n", ast_config_AST_PID);
ast_cli(a->fd, " VarLib directory: %s\n", ast_config_AST_VAR_DIR);
ast_cli(a->fd, " Data directory: %s\n", ast_config_AST_DATA_DIR);
ast_cli(a->fd, " ASTDB: %s\n", ast_config_AST_DB);
ast_cli(a->fd, " IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
ast_cli(a->fd, " AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
ast_cli(a->fd, "\n\n");
return CLI_SUCCESS;
static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int count = 0;
struct thread_list_t *cur;
switch (cmd) {
case CLI_INIT:
e->command = "core show threads";
"Usage: core show threads\n"
" List threads currently active in the system.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
AST_RWLIST_RDLOCK(&thread_list);
AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
ast_cli(a->fd, "%d threads listed.\n", count);
return CLI_SUCCESS;
Michiel van Baak
committed
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
#if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
/*
* swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
* to be based on the new swapctl(2) system call.
*/
static int swapmode(int *used, int *total)
{
struct swapent *swdev;
int nswap, rnswap, i;
nswap = swapctl(SWAP_NSWAP, 0, 0);
if (nswap == 0)
return 0;
swdev = ast_calloc(nswap, sizeof(*swdev));
if (swdev == NULL)
return 0;
rnswap = swapctl(SWAP_STATS, swdev, nswap);
if (rnswap == -1) {
ast_free(swdev);
return 0;
}
/* if rnswap != nswap, then what? */
/* Total things up */
*total = *used = 0;
for (i = 0; i < nswap; i++) {
if (swdev[i].se_flags & SWF_ENABLE) {
*used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
*total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
}
}
ast_free(swdev);
return 1;
}
#elif defined(HAVE_SYSCTL) && !defined(HAVE_SYSINFO)
Michiel van Baak
committed
static int swapmode(int *used, int *total)
{
Michiel van Baak
committed
return 1;
}
#endif
#if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
Dwayne M. Hubbard
committed
/*! \brief Give an overview of system statistics */
static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Dwayne M. Hubbard
committed
{
Tilghman Lesher
committed
uint64_t physmem, freeram;
uint64_t freeswap = 0;
Tilghman Lesher
committed
int nprocs = 0;
Michiel van Baak
committed
long uptime = 0;
Michiel van Baak
committed
#if defined(HAVE_SYSINFO)
Dwayne M. Hubbard
committed
struct sysinfo sys_info;
#elif defined(HAVE_SYSCTL)
static int pageshift;
struct vmtotal vmtotal;
struct timeval boottime;
time_t now;
int mib[2], pagesize, usedswap = 0;
size_t len;
#endif
switch (cmd) {
case CLI_INIT:
e->command = "core show sysinfo";
e->usage =
"Usage: core show sysinfo\n"
" List current system information.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
#if defined(HAVE_SYSINFO)
sysinfo(&sys_info);
Tilghman Lesher
committed
uptime = sys_info.uptime / 3600;
Michiel van Baak
committed
physmem = sys_info.totalram * sys_info.mem_unit;
freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
nprocs = sys_info.procs;
Michiel van Baak
committed
#elif defined(HAVE_SYSCTL)
/* calculate the uptime by looking at boottime */
time(&now);
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
len = sizeof(boottime);
if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
uptime = now - boottime.tv_sec;
}
uptime = uptime/3600;
/* grab total physical memory */
mib[0] = CTL_HW;
#if defined(HW_PHYSMEM64)
Michiel van Baak
committed
mib[1] = HW_PHYSMEM64;
#else
mib[1] = HW_PHYSMEM;
#endif
Michiel van Baak
committed
len = sizeof(physmem);
sysctl(mib, 2, &physmem, &len, NULL, 0);
pagesize = getpagesize();
pageshift = 0;
while (pagesize > 1) {
pageshift++;
pagesize >>= 1;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift -= 10;
/* grab vm totals */
mib[0] = CTL_VM;
mib[1] = VM_METER;
len = sizeof(vmtotal);
sysctl(mib, 2, &vmtotal, &len, NULL, 0);
freeram = (vmtotal.t_free << pageshift);
/* generate swap usage and totals */
Tilghman Lesher
committed
swapmode(&usedswap, &totalswap);
Michiel van Baak
committed
freeswap = (totalswap - usedswap);
/* grab number of processes */
Michiel van Baak
committed
mib[0] = CTL_KERN;
mib[1] = KERN_NPROCS;
len = sizeof(nprocs);
sysctl(mib, 2, &nprocs, &len, NULL, 0);
Michiel van Baak
committed
#endif
ast_cli(a->fd, "\nSystem Statistics\n");
ast_cli(a->fd, "-----------------\n");
ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
Tilghman Lesher
committed
ast_cli(a->fd, " Total RAM: %" PRIu64 " KiB\n", physmem / 1024);
ast_cli(a->fd, " Free RAM: %" PRIu64 " KiB\n", freeram);
Michiel van Baak
committed
#if defined(HAVE_SYSINFO)
Tilghman Lesher
committed
ast_cli(a->fd, " Buffer RAM: %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
Michiel van Baak
committed
#endif
#if defined(HAVE_SWAPCTL) || defined(HAVE_SYSINFO)
ast_cli(a->fd, " Total Swap Space: %d KiB\n", totalswap);
Tilghman Lesher
committed
ast_cli(a->fd, " Free Swap Space: %" PRIu64 " KiB\n\n", freeswap);
#endif
Michiel van Baak
committed
ast_cli(a->fd, " Number of Processes: %d \n\n", nprocs);
return CLI_SUCCESS;
Dwayne M. Hubbard
committed
}
Dwayne M. Hubbard
committed
struct profile_entry {
const char *name;
uint64_t scale; /* if non-zero, values are scaled by this */
int64_t mark;
int64_t value;
int64_t events;
};
struct profile_data {
int entries;
int max_size;
struct profile_entry e[0];
};
static struct profile_data *prof_data;
/*! \brief allocates a counter with a given name and scale.
* \return Returns the identifier of the counter.
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
*/
int ast_add_profile(const char *name, uint64_t scale)
{
int l = sizeof(struct profile_data);
int n = 10; /* default entries */
if (prof_data == NULL) {
prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
if (prof_data == NULL)
return -1;
prof_data->entries = 0;
prof_data->max_size = n;
}
if (prof_data->entries >= prof_data->max_size) {
void *p;
n = prof_data->max_size + 20;
p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
if (p == NULL)
return -1;
prof_data = p;
prof_data->max_size = n;
}
n = prof_data->entries++;
prof_data->e[n].name = ast_strdup(name);
prof_data->e[n].value = 0;
prof_data->e[n].events = 0;
prof_data->e[n].mark = 0;
prof_data->e[n].scale = scale;
return n;
}
int64_t ast_profile(int i, int64_t delta)
{
if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
return 0;
if (prof_data->e[i].scale > 1)
delta /= prof_data->e[i].scale;
prof_data->e[i].value += delta;
prof_data->e[i].events++;
return prof_data->e[i].value;
}
/* The RDTSC instruction was introduced on the Pentium processor and is not
* implemented on certain clones, like the Cyrix 586. Hence, the previous
* expectation of __i386__ was in error. */
#if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
#if defined(__FreeBSD__)
#include <machine/cpufunc.h>
#elif defined(linux)
uint64_t rv;
__asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
return (rv);
}
#endif
#else /* supply a dummy function on other platforms */
rdtsc(void)
{
return 0;
}
#endif
int64_t ast_mark(int i, int startstop)
{
if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
return 0;
if (startstop == 1)
prof_data->e[i].mark = rdtsc();
else {
prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
if (prof_data->e[i].scale > 1)
prof_data->e[i].mark /= prof_data->e[i].scale;
prof_data->e[i].value += prof_data->e[i].mark;
prof_data->e[i].events++;
}
return prof_data->e[i].mark;
}
#define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
max = prof_data->entries;\
if (a->argc > 3) { /* specific entries */ \
if (isdigit(a->argv[3][0])) { \