36 #include "asterisk/res_pjsip.h"
37 #include "asterisk/res_pjsip_session.h"
38 #include "asterisk/res_pjsip_cli.h"
45 static int cli_channel_iterate(
void *endpoint,
ao2_callback_fn callback,
void *arg)
47 return ast_sip_for_each_channel(endpoint, callback, arg);
50 static int cli_channelstats_iterate(
void *endpoint,
ao2_callback_fn callback,
void *arg)
52 return ast_sip_for_each_channel(endpoint, callback, arg);
55 static int cli_channel_sort(
const void *obj,
const void *arg,
int flags)
59 const char *right_key = arg;
67 cmp = strcmp(left_obj->
base->
name, right_key);
70 cmp = strncmp(left_obj->
base->
name, right_key, strlen(right_key));
80 static int cli_channelstats_sort(
const void *obj,
const void *arg,
int flags)
84 const char *right_key = arg;
87 switch (flags & OBJ_SEARCH_MASK) {
96 cmp = strcmp(left_obj->
base->
name, right_key);
99 cmp = strncmp(left_obj->
base->
name, right_key, strlen(right_key));
109 static int cli_channel_compare(
void *obj,
void *arg,
int flags)
113 const char *right_key = arg;
116 switch (flags & OBJ_SEARCH_MASK) {
121 if (strcmp(left_obj->
base->
name, right_key) == 0) {
126 if (strncmp(left_obj->
base->
name, right_key, strlen(right_key)) == 0) {
138 static int cli_channelstats_compare(
void *obj,
void *arg,
int flags)
142 const char *right_key = arg;
145 switch (flags & OBJ_SEARCH_MASK) {
153 if (strcmp(left_obj->
base->
name, right_key) == 0) {
158 if (strncmp(left_obj->
base->
name, right_key, strlen(right_key)) == 0) {
170 static int cli_message_to_snapshot(
void *obj,
void *arg,
int flags)
175 if (!strcmp(snapshot->
base->
type,
"PJSIP")) {
183 static int cli_filter_channels(
void *obj,
void *arg,
int flags)
186 regex_t *regexbuf = arg;
188 if (!regexec(regexbuf, channel->
base->
name, 0, NULL, 0)
189 || !regexec(regexbuf, channel->
dialplan->
appl, 0, NULL, 0)) {
202 if (!parent_container) {
207 if (!child_container) {
213 if (!ast_strlen_zero(regex)) {
214 if (regcomp(®exbuf, regex, REG_EXTENDED | REG_NOSUB)) {
222 return child_container;
225 static struct ao2_container *cli_channel_get_container(
const char *regex)
227 return get_container(regex, cli_channel_sort, cli_channel_compare);
230 static struct ao2_container *cli_channelstats_get_container(
const char *regex)
232 return get_container(regex, cli_channelstats_sort, cli_channelstats_compare);
235 static const char *cli_channel_get_id(
const void *obj)
242 static void *cli_channel_retrieve_by_id(
const char *
id)
247 static int cli_channel_print_header(
void *obj,
void *arg,
int flags)
250 int indent = CLI_INDENT_TO_SPACES(context->
indent_level);
251 int filler = CLI_LAST_TABSTOP - indent - 13;
256 "%*s: <ChannelId%*.*s> <State.....> <Time.....>\n",
257 indent,
"Channel", filler, filler, CLI_HEADER_FILLER);
261 filler = CLI_LAST_TABSTOP - indent - 38;
263 "%*s: <DialedExten%*.*s> CLCID: <ConnectedLineCID.......>\n",
264 indent,
"Exten", filler, filler, CLI_HEADER_FILLER);
271 static int cli_channel_print_body(
void *obj,
void *arg,
int flags)
275 char *print_name = NULL;
279 char *print_time = alloca(32);
284 print_name = alloca(print_name_len);
290 flexwidth = CLI_LAST_TABSTOP - indent;
296 flexwidth, flexwidth,
304 flexwidth = CLI_LAST_TABSTOP - indent - 25;
307 "%*s: %-*.*s CLCID: \"%s\" <%s>\n",
309 flexwidth, flexwidth,
323 static int cli_channelstats_print_header(
void *obj,
void *arg,
int flags)
330 " ...........Receive......... .........Transmit..........\n"
331 " BridgeId ChannelId ........ UpTime.. Codec. Count Lost Pct Jitter Count Lost Pct Jitter RTT....\n"
332 " =================");
337 static int cli_channelstats_print_body(
void *obj,
void *arg,
int flags)
347 char *print_name = NULL;
348 char *print_time = alloca(32);
349 char codec_in_use[7];
359 ast_channel_lock(channel);
361 cpvt = ast_channel_tech_pvt(channel);
362 session = cpvt ? cpvt->
session : NULL;
368 ast_channel_unlock(channel);
369 ao2_cleanup(channel);
378 ast_channel_unlock(channel);
379 ao2_cleanup(channel);
384 if (!media || media->
type != AST_MEDIA_TYPE_AUDIO || !media->
rtp) {
386 ast_channel_unlock(channel);
387 ao2_cleanup(channel);
391 codec_in_use[0] =
'\0';
393 if (ast_channel_rawreadformat(channel)) {
398 ast_channel_unlock(channel);
406 if (stats_res == -1) {
410 " %8.8s %-18.18s %-8.8s %-6.6s %6u%s %6u%s %3u %7.3f %6u%s %6u%s %3u %7.3f %7.3f\n",
415 stats.rxcount > 100000 ? stats.rxcount / 1000 : stats.rxcount,
416 stats.rxcount > 100000 ?
"K":
" ",
417 stats.rxploss > 100000 ? stats.rxploss / 1000 : stats.rxploss,
418 stats.rxploss > 100000 ?
"K":
" ",
419 stats.rxcount ? (stats.rxploss * 100) / stats.rxcount : 0,
420 MIN(stats.rxjitter, 999.999),
421 stats.txcount > 100000 ? stats.txcount / 1000 : stats.txcount,
422 stats.txcount > 100000 ?
"K":
" ",
423 stats.txploss > 100000 ? stats.txploss / 1000 : stats.txploss,
424 stats.txploss > 100000 ?
"K":
" ",
425 stats.txcount ? (stats.txploss * 100) / stats.txcount : 0,
426 MIN(stats.txjitter, 999.999),
427 MIN(stats.normdevrtt, 999.999)
431 ao2_cleanup(channel);
437 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"List PJSIP Channels",
438 .
command =
"pjsip list channels",
439 .
usage =
"Usage: pjsip list channels [ like <pattern> ]\n"
440 " List the active PJSIP channels\n"
441 " Optional regular expression pattern is used to filter the list.\n"),
442 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Channels",
443 .
command =
"pjsip show channels",
444 .
usage =
"Usage: pjsip show channels [ like <pattern> ]\n"
445 " List(detailed) the active PJSIP channels\n"
446 " Optional regular expression pattern is used to filter the list.\n"),
447 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Channel",
448 .
command =
"pjsip show channel",
449 .
usage =
"Usage: pjsip show channel\n"
450 " List(detailed) the active PJSIP channel\n"),
452 AST_CLI_DEFINE(ast_sip_cli_traverse_objects,
"Show PJSIP Channel Stats",
453 .
command =
"pjsip show channelstats",
454 .
usage =
"Usage: pjsip show channelstats [ like <pattern> ]\n"
455 " List(detailed) the active PJSIP channel stats\n"
456 " Optional regular expression pattern is used to filter the list.\n"),
465 if (!channel_formatter) {
466 ast_log(LOG_ERROR,
"Unable to allocate memory for channel_formatter\n");
469 channel_formatter->
name =
"channel";
470 channel_formatter->
print_header = cli_channel_print_header;
471 channel_formatter->
print_body = cli_channel_print_body;
472 channel_formatter->
get_container = cli_channel_get_container;
473 channel_formatter->
iterate = cli_channel_iterate;
475 channel_formatter->
get_id = cli_channel_get_id;
478 if (!channelstats_formatter) {
479 ao2_ref(channel_formatter, -1);
480 ast_log(LOG_ERROR,
"Unable to allocate memory for channelstats_formatter\n");
483 channelstats_formatter->
name =
"channelstat";
484 channelstats_formatter->
print_header = cli_channelstats_print_header;
485 channelstats_formatter->
print_body = cli_channelstats_print_body;
486 channelstats_formatter->
get_container = cli_channelstats_get_container;
487 channelstats_formatter->
iterate = cli_channelstats_iterate;
488 channelstats_formatter->
retrieve_by_id = cli_channel_retrieve_by_id;
489 channelstats_formatter->
get_id = cli_channel_get_id;
491 ast_sip_register_cli_formatter(channel_formatter);
492 ast_sip_register_cli_formatter(channelstats_formatter);
501 ast_sip_unregister_cli_formatter(channel_formatter);
502 ast_sip_unregister_cli_formatter(channelstats_formatter);
struct ast_str * output_buffer
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
struct ao2_container *(* get_container)(const char *regex)
Main Channel structure associated with a channel.
struct ast_channel_snapshot_base * base
Asterisk main include file. File version handling, generic pbx functions.
CLI Formatter Registry Entry.
int( ao2_callback_fn)(void *obj, void *arg, int flags)
Type of a generic callback function.
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
The arg parameter is a search key, but is not an object.
Time-related functions and macros.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
descriptor for a cli entry.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Structure representing a snapshot of channel state.
int(* iterate)(void *container, ao2_callback_fn callback, void *args)
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
CLI Formatter Context passed to all formatters.
const ast_string_field type
struct ast_channel_snapshot_dialplan * dialplan
A structure describing a SIP session.
struct ast_sip_session_media_state * active_media_state
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
struct ast_stream * ast_stream_topology_get_first_stream_by_type(const struct ast_stream_topology *topology, enum ast_media_type type)
Gets the first active stream of a specific type from the topology.
General Asterisk PBX channel definitions.
const ast_string_field appl
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
void pjsip_channel_cli_unregister(void)
Unregisters the channel cli commands.
const ast_string_field exten
struct timeval creationtime
void *(* retrieve_by_id)(const char *id)
PJSIP Channel Driver shared data structures.
enum ast_channel_state state
const char *(* get_id)(const void *obj)
int pjsip_channel_cli_register(void)
Registers the channel cli commands.
The arg parameter is an object of the same type.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_channel_snapshot_bridge * bridge
ao2_callback_fn * print_header
int( ao2_sort_fn)(const void *obj_left, const void *obj_right, int flags)
Type of generic container sort function.
Search option field mask.
void ast_format_duration_hh_mm_ss(int duration, char *buf, size_t length)
Formats a duration into HH:MM:SS.
ao2_callback_fn * print_body
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
struct ast_channel_snapshot_connected * connected
PJSIP CLI functions header file.
const ast_string_field name
#define ao2_link(container, obj)
Add an object to a container.