From 3da07b3ec00daa9f8d93328e5e7ddf6dcb960c0b Mon Sep 17 00:00:00 2001 From: Jonathan Rose Date: Thu, 26 Jul 2012 15:31:05 +0000 Subject: [PATCH] chan_sip: Add SIPpeerstatus command to AMI This patch was submitted by mnicholson a while back. It adds a new AMI action which allows users to request SIP peer status on demand similar to existing PeerStatus events and to the output you would see from CLI with sip show peer Review: https://reviewboard.asterisk.org/r/1098/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@370518 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 3 ++ channels/chan_sip.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/CHANGES b/CHANGES index a64b38e47f..7e0dae3cd6 100644 --- a/CHANGES +++ b/CHANGES @@ -428,6 +428,9 @@ AMI (Asterisk Manager Interface) detected, and "a" if it is set and nat is not detected. "Y" and "N" are still returned if auto_force_rport is not enabled. + * Added SIPpeerstatus manager command which will generate PeerStatus events + similar to the existing PeerStatus events found in chan_sip on demand. + * Hangup now can take a regular expression as the Channel option. If you want to hangup multiple channels, use /regex/ as the Channel option. Existing behavior to hanging up a single channel is unchanged, but if you pass a regex, diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3c645c4814..951bb1584c 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -572,6 +572,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") via multiple Variable: name=value sequences. + + + Show the status of one or all of the sip peers. + + + + + The peer name you want to check. + + + + Retrieves the status of one or all of the sip peers. If no peer name is specified, status + for all of the sip peers will be retrieved. + + The from parameter can be a configured peer name or in the form of "display-name" <URI>. @@ -18789,6 +18804,92 @@ static char *sip_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args return _sip_show_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); } +static void send_manager_peer_status(struct mansession *s, struct sip_peer *peer, const char *idText) +{ + char time[128] = ""; + char status[128] = ""; + if (peer->maxms) { + if (peer->lastms < 0) { + snprintf(status, sizeof(status), "PeerStatus: Unreachable\r\n"); + } else if (peer->lastms > peer->maxms) { + snprintf(status, sizeof(status), "PeerStatus: Lagged\r\n"); + snprintf(time, sizeof(time), "Time: %d\r\n", peer->lastms); + } else if (peer->lastms) { + snprintf(status, sizeof(status), "PeerStatus: Reachable\r\n"); + snprintf(time, sizeof(time), "Time: %d\r\n", peer->lastms); + } else { + snprintf(status, sizeof(status), "PeerStatus: Unknown\r\n"); + } + } else { + snprintf(status, sizeof(status), "PeerStatus: Unmonitored\r\n"); + } + + astman_append(s, + "Event: PeerStatus\r\n" + "Privilege: System\r\n" + "ChannelType: SIP\r\n" + "Peer: SIP/%s\r\n" + "%s" + "%s" + "%s" + "\r\n", + peer->name, status, time, idText); +} + +/*! \brief Show SIP peers in the manager API */ +static int manager_sip_peer_status(struct mansession *s, const struct message *m) +{ + const char *id = astman_get_header(m,"ActionID"); + const char *peer_name = astman_get_header(m,"Peer"); + char idText[256] = ""; + struct sip_peer *peer = NULL; + + if (!ast_strlen_zero(id)) { + snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); + } + + if (!ast_strlen_zero(peer_name)) { + /* strip SIP/ from the begining of the peer name */ + if (strlen(peer_name) >= 4 && !strncasecmp("SIP/", peer_name, 4)) { + peer_name += 4; + } + + peer = sip_find_peer(peer_name, NULL, TRUE, FINDPEERS, FALSE, 0); + if (!peer) { + astman_send_error(s, m, "No such peer"); + return 0; + } + } + + astman_send_ack(s, m, "Peer status will follow"); + + if (!peer) { + struct ao2_iterator i = ao2_iterator_init(peers, 0); + while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table for SIPpeerstatus"))) { + ao2_lock(peer); + send_manager_peer_status(s, peer, idText); + ao2_unlock(peer); + sip_unref_peer(peer, "unref peer for SIPpeerstatus"); + } + ao2_iterator_destroy(&i); + } else { + ao2_lock(peer); + send_manager_peer_status(s, peer, idText); + ao2_unlock(peer); + sip_unref_peer(peer, "unref peer for SIPpeerstatus"); + } + + + astman_append(s, + "Event: SIPpeerstatusComplete\r\n" + "%s" + "\r\n", + idText); + + return 0; +} + + /*! \brief Send qualify message to peer from cli or manager. Mostly for debugging. */ static char *_sip_qualify_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]) { @@ -32789,6 +32890,7 @@ static int load_module(void) ast_manager_register_xml("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer); ast_manager_register_xml("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry); ast_manager_register_xml("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify); + ast_manager_register_xml("SIPpeerstatus", EVENT_FLAG_SYSTEM, manager_sip_peer_status); sip_poke_all_peers(); sip_keepalive_all_peers(); sip_send_all_registers(); @@ -32898,6 +33000,7 @@ static int unload_module(void) ast_manager_unregister("SIPqualifypeer"); ast_manager_unregister("SIPshowregistry"); ast_manager_unregister("SIPnotify"); + ast_manager_unregister("SIPpeerstatus"); /* Kill TCP/TLS server threads */ if (sip_tcp_desc.master) {