From 909ee4bfb9180a87e02504acb47f27b47cb5adea Mon Sep 17 00:00:00 2001 From: Kinsey Moore Date: Mon, 1 Jul 2013 13:16:09 +0000 Subject: Refactor extraneous channel events This change removes JitterBufStats, ChannelReload, and ChannelUpdate and refactors the following events to travel over Stasis-Core: * LocalBridge * DAHDIChannel * AlarmClear * SpanAlarmClear * Alarm * SpanAlarm * DNDState * MCID * SIPQualifyPeerDone * SessionTimeout Review: https://reviewboard.asterisk.org/r/2627/ (closes issue ASTERISK-21476) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393284 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_dahdi.c | 283 +++++++++++++++++++++++++++++++++++---------- channels/chan_gtalk.c | 7 +- channels/chan_iax2.c | 33 ------ channels/chan_sip.c | 150 +++++++++++++++--------- channels/sig_analog.c | 64 +++++----- channels/sig_pri.c | 270 +++++++++++++++++++++++++++++++----------- channels/sip/include/sip.h | 2 - 7 files changed, 556 insertions(+), 253 deletions(-) (limited to 'channels') diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 24337e385..b22e73800 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -131,6 +131,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/data.h" #include "asterisk/features_config.h" #include "asterisk/bridging.h" +#include "asterisk/stasis_channels.h" /*** DOCUMENTATION @@ -296,6 +297,85 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Similar to the CLI command "pri show spans". + + + Raised when an alarm is cleared on a DAHDI channel. + + + The DAHDI channel on which the alarm was cleared. + This is not an Asterisk channel identifier. + + + + + + + Raised when an alarm is cleared on a DAHDI span. + + + The span on which the alarm was cleared. + + + + + + + Raised when the Do Not Disturb state is changed on a DAHDI channel. + + + The DAHDI channel on which DND status changed. + This is not an Asterisk channel identifier. + + + + + + + + + + + + + Raised when an alarm is set on a DAHDI channel. + + + The channel on which the alarm occurred. + This is not an Asterisk channel identifier. + + + A textual description of the alarm that occurred. + + + + + + + Raised when an alarm is set on a DAHDI span. + + + The span on which the alarm occurred. + + + A textual description of the alarm that occurred. + + + + + + + Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel. + + + + The DAHDI span associated with this channel. + + + The DAHDI channel associated with this channel. + + + + ***/ #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */ @@ -2270,6 +2350,50 @@ static void my_deadlock_avoidance_private(void *pvt) DEADLOCK_AVOIDANCE(&p->lock); } +static struct ast_manager_event_blob *dahdichannel_to_ami(struct stasis_message *msg) +{ + RAII_VAR(struct ast_str *, channel_string, NULL, ast_free); + struct ast_channel_blob *obj = stasis_message_data(msg); + struct ast_json *span, *channel; + + channel_string = ast_manager_build_channel_state_string(obj->snapshot); + if (!channel_string) { + return NULL; + } + + span = ast_json_object_get(obj->blob, "span"); + channel = ast_json_object_get(obj->blob, "channel"); + + return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DAHDIChannel", + "%s" + "DAHDISpan: %d\r\n" + "DAHDIChannel: %s\r\n", + ast_str_buffer(channel_string), + (unsigned int)ast_json_integer_get(span), + ast_json_string_get(channel)); +} + +STASIS_MESSAGE_TYPE_DEFN_LOCAL(dahdichannel_type, + .to_ami = dahdichannel_to_ami, + ); + +/*! \brief Sends a DAHDIChannel channel blob used to produce DAHDIChannel AMI messages */ +static void publish_dahdichannel(struct ast_channel *chan, int span, const char *dahdi_channel) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + + ast_assert(dahdi_channel != NULL); + + blob = ast_json_pack("{s: i, s: s}", + "span", span, + "channel", dahdi_channel); + if (!blob) { + return; + } + + ast_channel_publish_blob(chan, dahdichannel_type(), blob); +} + /*! * \internal * \brief Post an AMI DAHDI channel association event. @@ -2294,20 +2418,7 @@ static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *cha /* Real channel */ snprintf(ch_name, sizeof(ch_name), "%d", p->channel); } - /*** DOCUMENTATION - - Raised when a DAHDI channel is created or an underlying technology is associated with a DAHDI channel. - - ***/ - ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel", - "Channel: %s\r\n" - "Uniqueid: %s\r\n" - "DAHDISpan: %d\r\n" - "DAHDIChannel: %s\r\n", - ast_channel_name(chan), - ast_channel_uniqueid(chan), - p->span, - ch_name); + publish_dahdichannel(chan, p->span, ch_name); } #ifdef HAVE_PRI @@ -3956,6 +4067,37 @@ static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f) } } +static void publish_channel_alarm_clear(int channel) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free); + if (!dahdi_chan) { + return; + } + + ast_str_set(&dahdi_chan, 0, "%d", channel); + ast_log(LOG_NOTICE, "Alarm cleared on channel DAHDI/%d\n", channel); + body = ast_json_pack("{s: s}", "DAHDIChannel", ast_str_buffer(dahdi_chan)); + if (!body) { + return; + } + + ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body); +} + +static void publish_span_alarm_clear(int span) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + + ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", span); + body = ast_json_pack("{s: i}", "Span", span); + if (!body) { + return; + } + + ast_manager_publish_event("SpanAlarmClear", EVENT_FLAG_SYSTEM, body); +} + static void handle_clear_alarms(struct dahdi_pvt *p) { #if defined(HAVE_PRI) @@ -3965,22 +4107,10 @@ static void handle_clear_alarms(struct dahdi_pvt *p) #endif /* defined(HAVE_PRI) */ if (report_alarms & REPORT_CHANNEL_ALARMS) { - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); - /*** DOCUMENTATION - - Raised when an alarm is cleared on a DAHDI channel. - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel); + publish_channel_alarm_clear(p->channel); } if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { - ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span); - /*** DOCUMENTATION - - Raised when an alarm is cleared on a DAHDI span. - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span); + publish_span_alarm_clear(p->span); } } @@ -8037,6 +8167,39 @@ static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame } } +static void publish_span_alarm(int span, const char *alarm_txt) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + + body = ast_json_pack("{s: i, s: s}", + "Span", span, + "Alarm", alarm_txt); + if (!body) { + return; + } + + ast_manager_publish_event("SpanAlarm", EVENT_FLAG_SYSTEM, body); +} + +static void publish_channel_alarm(int channel, const char *alarm_txt) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + RAII_VAR(struct ast_str *, dahdi_chan, ast_str_create(32), ast_free); + if (!dahdi_chan) { + return; + } + + ast_str_set(&dahdi_chan, 0, "%d", channel); + body = ast_json_pack("{s: s, s: s}", + "DAHDIChannel", ast_str_buffer(dahdi_chan), + "Alarm", alarm_txt); + if (!body) { + return; + } + + ast_manager_publish_event("Alarm", EVENT_FLAG_SYSTEM, body); +} + static void handle_alarms(struct dahdi_pvt *p, int alms) { const char *alarm_str; @@ -8050,28 +8213,12 @@ static void handle_alarms(struct dahdi_pvt *p, int alms) alarm_str = alarm2str(alms); if (report_alarms & REPORT_CHANNEL_ALARMS) { ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); - /*** DOCUMENTATION - - Raised when an alarm is set on a DAHDI channel. - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "Alarm", - "Alarm: %s\r\n" - "Channel: %d\r\n", - alarm_str, p->channel); + publish_channel_alarm(p->channel, alarm_str); } if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) { ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str); - /*** DOCUMENTATION - - Raised when an alarm is set on a DAHDI span. - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm", - "Alarm: %s\r\n" - "Span: %d\r\n", - alarm_str, p->span); + publish_span_alarm(p->span, alarm_str); } } @@ -10083,6 +10230,26 @@ static int dahdi_wink(struct dahdi_pvt *p, int idx) return 0; } +static void publish_dnd_state(int channel, const char *status) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free); + if (!dahdichan) { + return; + } + + ast_str_set(&dahdichan, 0, "%d", channel); + + body = ast_json_pack("{s: s, s: s}", + "DAHDIChannel", ast_str_buffer(dahdichan), + "Status", status); + if (!body) { + return; + } + + ast_manager_publish_event("DNDState", EVENT_FLAG_SYSTEM, body); +} + /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5) * \param flag on 1 to enable, 0 to disable, -1 return dnd value @@ -10107,24 +10274,7 @@ static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag) ast_verb(3, "%s DND on channel %d\n", flag? "Enabled" : "Disabled", dahdichan->channel); - /*** DOCUMENTATION - - Raised when the Do Not Disturb state is changed on a DAHDI channel. - - - - - - - - - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "DNDState", - "Channel: DAHDI/%d\r\n" - "Status: %s\r\n", dahdichan->channel, - flag? "enabled" : "disabled"); - + publish_dnd_state(dahdichan->channel, flag ? "enabled" : "disabled"); return 0; } @@ -17154,6 +17304,7 @@ static int __unload_module(void) ast_cond_destroy(&ss_thread_complete); dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities); + STASIS_MESSAGE_TYPE_CLEANUP(dahdichannel_type); return 0; } @@ -19154,6 +19305,10 @@ static int load_module(void) int y; #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */ + if (STASIS_MESSAGE_TYPE_INIT(dahdichannel_type)) { + return AST_MODULE_LOAD_FAILURE; + } + if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) { return AST_MODULE_LOAD_FAILURE; } diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 49e7ce8ff..a0aa0b95d 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -86,6 +86,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/jabber.h" #include "asterisk/jingle.h" #include "asterisk/features.h" +#include "asterisk/stasis_channels.h" #define GOOGLE_CONFIG "gtalk.conf" @@ -546,8 +547,6 @@ static int gtalk_answer(struct ast_channel *ast) ast_debug(1, "Answer!\n"); ast_mutex_lock(&p->lock); gtalk_invite(p, p->them, p->us,p->sid, 0); - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n", - ast_channel_name(ast), "GTALK", p->sid); ast_mutex_unlock(&p->lock); return res; } @@ -1216,9 +1215,7 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i, ast_hangup(tmp); tmp = NULL; } else { - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", - "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n", - i->owner ? ast_channel_name(i->owner) : "", "Gtalk", i->sid); + send_channel_update(i->owner, i->sid); } return tmp; } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 46d1f7d06..23006364c 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1392,17 +1392,6 @@ static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, reload_config(1); } - -/*! \brief Send manager event at call setup to link between Asterisk channel name - and IAX2 call identifiers */ -static void iax2_ami_channelupdate(struct chan_iax2_pvt *pvt) -{ - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", - "Channel: %s\r\nChanneltype: IAX2\r\nIAX2-callno-local: %d\r\nIAX2-callno-remote: %d\r\nIAX2-peer: %s\r\n", - pvt->owner ? ast_channel_name(pvt->owner) : "", - pvt->callno, pvt->peercallno, pvt->peer ? pvt->peer : ""); -} - static const struct ast_datastore_info iax2_variable_datastore_info = { .type = "IAX2_VARIABLE", .duplicate = iax2_dup_variable_datastore, @@ -5552,10 +5541,6 @@ static int iax2_answer(struct ast_channel *c) { unsigned short callno = PTR_TO_CALLNO(ast_channel_tech_pvt(c)); ast_debug(1, "Answering IAX2 call\n"); - ast_mutex_lock(&iaxsl[callno]); - if (iaxs[callno]) - iax2_ami_channelupdate(iaxs[callno]); - ast_mutex_unlock(&iaxsl[callno]); return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); } @@ -5678,7 +5663,6 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab } return NULL; } - iax2_ami_channelupdate(i); if (!tmp) { return NULL; } @@ -9367,23 +9351,6 @@ static void log_jitterstats(unsigned short callno) iaxs[callno]->remote_rr.dropped, iaxs[callno]->remote_rr.ooo, iaxs[callno]->remote_rr.packets); - manager_event(EVENT_FLAG_REPORTING, "JitterBufStats", "Owner: %s\r\nPing: %d\r\nLocalJitter: %d\r\nLocalJBDelay: %d\r\nLocalTotalLost: %d\r\nLocalLossPercent: %d\r\nLocalDropped: %d\r\nLocalooo: %d\r\nLocalReceived: %d\r\nRemoteJitter: %d\r\nRemoteJBDelay: %d\r\nRemoteTotalLost: %d\r\nRemoteLossPercent: %d\r\nRemoteDropped: %d\r\nRemoteooo: %d\r\nRemoteReceived: %d\r\n", - ast_channel_name(iaxs[callno]->owner), - iaxs[callno]->pingtime, - localjitter, - localdelay, - locallost, - locallosspct, - localdropped, - localooo, - localpackets, - iaxs[callno]->remote_rr.jitter, - iaxs[callno]->remote_rr.delay, - iaxs[callno]->remote_rr.losscnt, - iaxs[callno]->remote_rr.losspct/1000, - iaxs[callno]->remote_rr.dropped, - iaxs[callno]->remote_rr.ooo, - iaxs[callno]->remote_rr.packets); } ast_mutex_unlock(&iaxsl[callno]); } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 4b795521e..9a5f086ad 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -295,6 +295,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/app.h" #include "asterisk/bridging.h" #include "asterisk/stasis_endpoints.h" +#include "asterisk/stasis_channels.h" #include "asterisk/features_config.h" /*** DOCUMENTATION @@ -563,7 +564,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Qualify a SIP peer. - SIPqualifypeerdone + SIPQualifyPeerDone @@ -621,6 +622,37 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Specifying a prefix of sip: will send the message as a SIP MESSAGE request. + + + Raised when SIPQualifyPeer has finished qualifying the specified peer. + + + The name of the peer. + + + This is only included if an ActionID Header was sent with the action request, in which case it will be that ActionID. + + + + SIPqualifypeer + + + + + + Raised when a SIP session times out. + + + + The source of the session timeout. + + + + + + + + ***/ static int min_expiry = DEFAULT_MIN_EXPIRY; /*!< Minimum accepted registration time */ @@ -1042,6 +1074,11 @@ static struct sip_auth_container *authl = NULL; /*! \brief Global authentication container protection while adjusting the references. */ AST_MUTEX_DEFINE_STATIC(authl_lock); +static struct ast_manager_event_blob *session_timeout_to_ami(struct stasis_message *msg); +STASIS_MESSAGE_TYPE_DEFN_LOCAL(session_timeout_type, + .to_ami = session_timeout_to_ami, + ); + /* --- Sockets and networking --------------*/ /*! \brief Main socket for UDP SIP communication. @@ -8212,13 +8249,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit append_history(i, "NewChan", "Channel %s - from %s", ast_channel_name(tmp), i->callid); } - /* Inform manager user about new channel and their SIP call ID */ - if (sip_cfg.callevents) { - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", - "Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\n", - ast_channel_name(tmp), ast_channel_uniqueid(tmp), "SIP", i->callid, i->fullcontact); - } - return tmp; } @@ -20007,6 +20037,21 @@ static int manager_sip_peer_status(struct mansession *s, const struct message *m return 0; } +static void publish_qualify_peer_done(const char *id, const char *peer) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + + if (ast_strlen_zero(id)) { + body = ast_json_pack("{s: s}", "Peer", peer); + } else { + body = ast_json_pack("{s: s, s: s}", "Peer", peer, "ActionID", id); + } + if (!body) { + return; + } + + ast_manager_publish_event("SIPQualifyPeerDone", EVENT_FLAG_CALL, body); +} /*! \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[]) @@ -20019,41 +20064,15 @@ static char *_sip_qualify_peer(int type, int fd, struct mansession *s, const str load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; if ((peer = sip_find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) { - const char *id = astman_get_header(m,"ActionID"); - char idText[256] = ""; if (type != 0) { astman_send_ack(s, m, "SIP peer found - will qualify"); } - if (!ast_strlen_zero(id)) { - snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); - } - sip_poke_peer(peer, 1); - /*** DOCUMENTATION - - Raised when SIPqualifypeer has finished qualifying the specified peer. - - - The name of the peer. - - - This is only included if an ActionID Header was sent with the action request, in which case it will be that ActionID. - - - - SIPqualifypeer - - - ***/ - manager_event(EVENT_FLAG_CALL, "SIPqualifypeerdone", - "Peer: %s\r\n" - "%s", - argv[3], - idText); + publish_qualify_peer_done(id, argv[3]); sip_unref_peer(peer, "qualify: done with peer"); } else if (type == 0) { @@ -20887,7 +20906,6 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_ ast_cli(a->fd, " From: Domain: %s\n", default_fromdomain); } ast_cli(a->fd, " Record SIP history: %s\n", AST_CLI_ONOFF(recordhistory)); - ast_cli(a->fd, " Call Events: %s\n", AST_CLI_ONOFF(sip_cfg.callevents)); ast_cli(a->fd, " Auth. Failure Events: %s\n", AST_CLI_ONOFF(global_authfailureevents)); ast_cli(a->fd, " T.38 support: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT))); @@ -23140,11 +23158,6 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest if (!req->ignore && p->owner) { if (!reinvite) { ast_queue_control(p->owner, AST_CONTROL_ANSWER); - if (sip_cfg.callevents) { - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", - "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", - ast_channel_name(p->owner), "SIP", ast_channel_uniqueid(p->owner), p->callid, p->fullcontact, p->peername); - } } else { /* RE-invite */ if (p->t38.state == T38_DISABLED || p->t38.state == T38_REJECTED) { ast_queue_control(p->owner, AST_CONTROL_UPDATE_RTP_PEER); @@ -28458,6 +28471,39 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, int cache_only) return 0; } +static struct ast_manager_event_blob *session_timeout_to_ami(struct stasis_message *msg) +{ + RAII_VAR(struct ast_str *, channel_string, NULL, ast_free); + struct ast_channel_blob *obj = stasis_message_data(msg); + const char *source = ast_json_string_get(ast_json_object_get(obj->blob, "source")); + + channel_string = ast_manager_build_channel_state_string(obj->snapshot); + if (!channel_string) { + return NULL; + } + + return ast_manager_event_blob_create(EVENT_FLAG_CALL, "SessionTimeout", + "%s" + "Source: %s\r\n", + ast_str_buffer(channel_string), source); +} + +/*! \brief Sends a session timeout channel blob used to produce SessionTimeout AMI messages */ +static void send_session_timeout(struct ast_channel *chan, const char *source) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + + ast_assert(chan != NULL); + ast_assert(source != NULL); + + blob = ast_json_pack("{s: s}", "source", source); + if (!blob) { + return; + } + + ast_channel_publish_blob(chan, session_timeout_type(), blob); +} + /*! * \brief helper function for the monitoring thread -- seems to be called with the assumption that the dialog is locked * @@ -28533,8 +28579,8 @@ static int check_rtp_timeout(struct sip_pvt *dialog, time_t t) } ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", ast_channel_name(dialog->owner), (long) (t - dialog->lastrtprx)); - manager_event(EVENT_FLAG_CALL, "SessionTimeout", "Source: RTPTimeout\r\n" - "Channel: %s\r\nUniqueid: %s\r\n", ast_channel_name(dialog->owner), ast_channel_uniqueid(dialog->owner)); + send_session_timeout(dialog->owner, "RTPTimeout"); + /* Issue a softhangup */ ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); ast_channel_unlock(dialog->owner); @@ -28813,8 +28859,7 @@ static int proc_session_timer(const void *vp) sip_pvt_lock(p); } - manager_event(EVENT_FLAG_CALL, "SessionTimeout", "Source: SIPSessionTimer\r\n" - "Channel: %s\r\nUniqueid: %s\r\n", ast_channel_name(p->owner), ast_channel_uniqueid(p->owner)); + send_session_timeout(p->owner, "SIPSessionTimer"); ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); ast_channel_unlock(p->owner); sip_pvt_unlock(p); @@ -29551,10 +29596,6 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_ callid = ast_callid_unref(callid); } - if (sip_cfg.callevents) - manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", - "Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", - p->owner? ast_channel_name(p->owner) : "", "SIP", p->callid, p->fullcontact, p->peername); sip_pvt_unlock(p); if (!tmpc) { dialog_unlink_all(p); @@ -31160,7 +31201,6 @@ static int reload_config(enum channelreloadreason reason) /* Misc settings for the channel */ global_relaxdtmf = FALSE; - sip_cfg.callevents = DEFAULT_CALLEVENTS; global_authfailureevents = FALSE; global_t1 = DEFAULT_TIMER_T1; global_timer_b = 64 * DEFAULT_TIMER_T1; @@ -31641,8 +31681,6 @@ static int reload_config(enum channelreloadreason reason) ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); global_qualifyfreq = DEFAULT_QUALIFYFREQ; } - } else if (!strcasecmp(v->name, "callevents")) { - sip_cfg.callevents = ast_true(v->value); } else if (!strcasecmp(v->name, "authfailureevents")) { global_authfailureevents = ast_true(v->value); } else if (!strcasecmp(v->name, "maxcallbitrate")) { @@ -32079,8 +32117,6 @@ static int reload_config(enum channelreloadreason reason) notify_types = NULL; } - /* Done, tell the manager */ - manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "ChannelType: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\n", channelreloadreason2txt(reason), registry_count, peer_count); run_end = time(0); ast_debug(4, "SIP reload_config done...Runtime= %d sec\n", (int)(run_end-run_start)); @@ -34059,6 +34095,10 @@ static int load_module(void) { ast_verbose("SIP channel loading...\n"); + if (STASIS_MESSAGE_TYPE_INIT(session_timeout_type)) { + return AST_MODULE_LOAD_FAILURE; + } + if (!(sip_tech.capabilities = ast_format_cap_alloc())) { return AST_MODULE_LOAD_FAILURE; } @@ -34425,6 +34465,8 @@ static int unload_module(void) ast_format_cap_destroy(sip_tech.capabilities); sip_cfg.caps = ast_format_cap_destroy(sip_cfg.caps); + STASIS_MESSAGE_TYPE_CLEANUP(session_timeout_type); + return 0; } diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 9660d3fe6..276e0fd3e 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -2622,6 +2622,19 @@ int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *chan) return ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, p); } +static void analog_publish_channel_alarm_clear(int channel) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + + ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", channel); + body = ast_json_pack("{s: i}", "Channel", channel); + if (!body) { + return; + } + + ast_manager_publish_event("AlarmClear", EVENT_FLAG_SYSTEM, body); +} + static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_channel *ast) { int res, x; @@ -3086,14 +3099,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ break; case ANALOG_EVENT_NOALARM: analog_set_alarm(p, 0); - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); - /*** DOCUMENTATION - - Raised when an Alarm is cleared on an Analog channel. - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", - "Channel: %d\r\n", p->channel); + analog_publish_channel_alarm_clear(p->channel); break; case ANALOG_EVENT_WINKFLASH: if (p->inalarm) { @@ -3735,9 +3741,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event) break; case ANALOG_EVENT_NOALARM: analog_set_alarm(i, 0); - ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); - manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", - "Channel: %d\r\n", i->channel); + analog_publish_channel_alarm_clear(i->channel); break; case ANALOG_EVENT_ALARM: analog_set_alarm(i, 1); @@ -3940,6 +3944,26 @@ int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void return 0; } +static void analog_publish_dnd_state(int channel, const char *status) +{ + RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); + RAII_VAR(struct ast_str *, dahdichan, ast_str_create(32), ast_free); + if (!dahdichan) { + return; + } + + ast_str_set(&dahdichan, 0, "DAHDI/%d", channel); + + body = ast_json_pack("{s: s, s: s}", + "Channel", ast_str_buffer(dahdichan), + "Status", status); + if (!body) { + return; + } + + ast_manager_publish_event("DNDState", EVENT_FLAG_SYSTEM, body); +} + int analog_dnd(struct analog_pvt *p, int flag) { if (flag == -1) { @@ -3951,23 +3975,7 @@ int analog_dnd(struct analog_pvt *p, int flag) ast_verb(3, "%s DND on channel %d\n", flag ? "Enabled" : "Disabled", p->channel); - /*** DOCUMENTATION - - Raised when the Do Not Disturb state is changed on an Analog channel. - - - - - - - - - - ***/ - manager_event(EVENT_FLAG_SYSTEM, "DNDState", - "Channel: DAHDI/%d\r\n" - "Status: %s\r\n", p->channel, - flag ? "enabled" : "disabled"); + analog_publish_dnd_state(p->channel, flag ? "enabled" : "disabled"); return 0; } diff --git a/channels/sig_pri.c b/channels/sig_pri.c index d5d6f4976..5f0792878 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -26,6 +26,68 @@ /*** MODULEINFO core ***/ +/*** DOCUMENTATION + + + Published when a malicious call ID request arrives. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ***/ #include "asterisk.h" @@ -51,6 +113,7 @@ #include "asterisk/features.h" #include "asterisk/aoc.h" #include "asterisk/bridging.h" +#include "asterisk/stasis_channels.h" #include "sig_pri.h" #ifndef PRI_EVENT_FACILITY @@ -2270,9 +2333,74 @@ static int sig_pri_msn_match(const char *msn_patterns, const char *exten) } #if defined(HAVE_PRI_MCID) +static void party_number_json_to_ami(struct ast_str **msg, const char *prefix, struct ast_json *number) +{ + const char *num_txt, *pres_txt; + int plan, pres; + if (!number) { + ast_str_append(msg, 0, + "%sNumValid: 0\r\n" + "%sNum: \r\n" + "%ston: 0\r\n", + prefix, prefix, prefix); + return; + } + + num_txt = ast_json_string_get(ast_json_object_get(number, "number")); + plan = ast_json_integer_get(ast_json_object_get(number, "plan")); + pres = ast_json_integer_get(ast_json_object_get(number, "presentation")); + pres_txt = ast_json_string_get(ast_json_object_get(number, "presentation_txt")); + + ast_str_append(msg, 0, "%sNumValid: 1\r\n", prefix); + ast_str_append(msg, 0, "%sNum: %s\r\n", prefix, num_txt); + ast_str_append(msg, 0, "%ston: %d\r\n", prefix, plan); + ast_str_append(msg, 0, "%sNumPlan: %d\r\n", prefix, plan); + ast_str_append(msg, 0, "%sNumPres: %d (%s)\r\n", prefix, pres, pres_txt); +} + +static void party_name_json_to_ami(struct ast_str **msg, const char *prefix, struct ast_json *name) +{ + const char *name_txt, *pres_txt, *charset; + int pres; + if (!name) { + ast_str_append(msg, 0, + "%sNameValid: 0\r\n" + "%sName: \r\n", + prefix, prefix); + return; + } + + name_txt = ast_json_string_get(ast_json_object_get(name, "name")); + charset = ast_json_string_get(ast_json_object_get(name, "character_set")); + pres = ast_json_integer_get(ast_json_object_get(name, "presentation")); + pres_txt = ast_json_string_get(ast_json_object_get(name, "presentation_txt")); + + ast_str_append(msg, 0, "%sNameValid: 1\r\n", prefix); + ast_str_append(msg, 0, "%sName: %s\r\n", prefix, name_txt); + ast_str_append(msg, 0, "%sNameCharSet: %s\r\n", prefix, charset); + ast_str_append(msg, 0, "%sNamePres: %d (%s)\r\n", prefix, pres, pres_txt); +} + +static void party_subaddress_json_to_ami(struct ast_str **msg, const char *prefix, struct ast_json *subaddress) +{ + const char *subaddress_txt, *type_txt; + int odd; + if (!subaddress) { + return; + } + + subaddress_txt = ast_json_string_get(ast_json_object_get(subaddress, "subaddress")); + type_txt = ast_json_string_get(ast_json_object_get(subaddress, "type")); + odd = ast_json_is_true(ast_json_object_get(subaddress, "odd")) ? 1 : 0; + + ast_str_append(msg, 0, "%sSubaddr: %s\r\n", prefix, subaddress_txt); + ast_str_append(msg, 0, "%sSubaddrType: %s\r\n", prefix, type_txt); + ast_str_append(msg, 0, "%sSubaddrOdd: %d\r\n", prefix, odd); +} + /*! * \internal - * \brief Append the given party id to the event string. + * \brief Append the given JSON party id to the event string. * \since 1.8 * * \param msg Event message string being built. @@ -2281,58 +2409,72 @@ static int sig_pri_msn_match(const char *msn_patterns, const char *exten) * * \return Nothing */ -static void sig_pri_event_party_id(struct ast_str **msg, const char *prefix, struct ast_party_id *party) +static void party_json_to_ami(struct ast_str **msg, const char *prefix, struct ast_json *party) { - int pres; + struct ast_json *presentation = ast_json_object_get(party, "presentation"); + struct ast_json *presentation_txt = ast_json_object_get(party, "presentation_txt"); + struct ast_json *name = ast_json_object_get(party, "name"); + struct ast_json *number = ast_json_object_get(party, "number"); + struct ast_json *subaddress = ast_json_object_get(party, "subaddress"); /* Combined party presentation */ - pres = ast_party_id_presentation(party); - ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, pres, - ast_describe_caller_presentation(pres)); + ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, + (uint32_t)ast_json_integer_get(presentation), + ast_json_string_get(presentation_txt)); /* Party number */ - ast_str_append(msg, 0, "%sNumValid: %d\r\n", prefix, - (unsigned) party->number.valid); - ast_str_append(msg, 0, "%sNum: %s\r\n", prefix, - S_COR(party->number.valid, party->number.str, "")); - ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number.plan); - if (party->number.valid) { - ast_str_append(msg, 0, "%sNumPlan: %d\r\n", prefix, party->number.plan); - ast_str_append(msg, 0, "%sNumPres: %d (%s)\r\n", prefix, - party->number.presentation, - ast_describe_caller_presentation(party->number.presentation)); - } + party_number_json_to_ami(msg, prefix, number); /* Party name */ - ast_str_append(msg, 0, "%sNameValid: %d\r\n", prefix, - (unsigned) party->name.valid); - ast_str_append(msg, 0, "%sName: %s\r\n", prefix, - S_COR(party->name.valid, party->name.str, "")); - if (party->name.valid) { - ast_str_append(msg, 0, "%sNameCharSet: %s\r\n", prefix, - ast_party_name_charset_describe(party->name.char_set)); - ast_str_append(msg, 0, "%sNamePres: %d (%s)\r\n", prefix, - party->name.presentation, - ast_describe_caller_presentation(party->name.presentation)); - } + party_name_json_to_ami(msg, prefix, name); -#if defined(HAVE_PRI_SUBADDR) /* Party subaddress */ - if (party->subaddress.valid) { - static const char subaddress[] = "Subaddr"; + party_subaddress_json_to_ami(msg, prefix, subaddress); +} + +static struct ast_manager_event_blob *mcid_to_ami(struct stasis_message *msg) +{ + RAII_VAR(struct ast_str *, channel_string, NULL, ast_free); + RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free); + struct ast_channel_blob *obj = stasis_message_data(msg); - ast_str_append(msg, 0, "%s%s: %s\r\n", prefix, subaddress, - S_OR(party->subaddress.str, "")); - ast_str_append(msg, 0, "%s%sType: %d\r\n", prefix, subaddress, - party->subaddress.type); - ast_str_append(msg, 0, "%s%sOdd: %d\r\n", prefix, subaddress, - party->subaddress.odd_even_indicator); + if (obj->snapshot) { + channel_string = ast_manager_build_channel_state_string(obj->snapshot); + if (!channel_string) { + return NULL; + } } -#endif /* defined(HAVE_PRI_SUBADDR) */ + + party_json_to_ami(&party_string, "MCallerID", ast_json_object_get(obj->blob, "caller")); + party_json_to_ami(&party_string, "MConnectedID", ast_json_object_get(obj->blob, "connected")); + + return ast_manager_event_blob_create(EVENT_FLAG_CALL, "MCID", + "%s" + "%s", + S_COR(obj->snapshot, ast_str_buffer(channel_string), ""), ast_str_buffer(party_string)); +} + +STASIS_MESSAGE_TYPE_DEFN_LOCAL(mcid_type, + .to_ami = mcid_to_ami, + ); + +static void send_mcid(struct ast_channel *chan, struct ast_party_id *caller, struct ast_party_id *connected) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + + ast_assert(caller != NULL); + ast_assert(connected != NULL); + + blob = ast_json_pack("{s: o, s: o}", + "caller", ast_json_party_id(caller), + "connected", ast_json_party_id(connected)); + if (!blob) { + return; + } + + ast_channel_publish_blob(chan, mcid_type(), blob); } -#endif /* defined(HAVE_PRI_MCID) */ -#if defined(HAVE_PRI_MCID) /*! * \internal * \brief Handle the MCID event. @@ -2350,15 +2492,12 @@ static void sig_pri_event_party_id(struct ast_str **msg, const char *prefix, str */ static void sig_pri_mcid_event(struct sig_pri_span *pri, const struct pri_subcmd_mcid_req *mcid, struct ast_channel *owner) { - struct ast_channel *chans[1]; - struct ast_str *msg; - struct ast_party_id party; - - msg = ast_str_create(4096); - if (!msg) { - return; - } + struct ast_party_id caller_party; + struct ast_party_id connected_party; + /* Always use libpri's called party information. */ + ast_party_id_init(&connected_party); + sig_pri_party_id_convert(&connected_party, &mcid->answerer, pri); if (owner) { /* * The owner channel is present. @@ -2366,31 +2505,18 @@ static void sig_pri_mcid_event(struct sig_pri_span *pri, const struct pri_subcmd */ ast_queue_control(owner, AST_CONTROL_MCID); - ast_str_append(&msg, 0, "Channel: %s\r\n", ast_channel_name(owner)); - ast_str_append(&msg, 0, "UniqueID: %s\r\n", ast_channel_uniqueid(owner)); - - sig_pri_event_party_id(&msg, "CallerID", &ast_channel_connected(owner)->id); + send_mcid(owner, &ast_channel_connected(owner)->id, &connected_party); } else { /* * Since we no longer have an owner channel, * we have to use the caller information supplied by libpri. */ - ast_party_id_init(&party); - sig_pri_party_id_convert(&party, &mcid->originator, pri); - sig_pri_event_party_id(&msg, "CallerID", &party); - ast_party_id_free(&party); + ast_party_id_init(&caller_party); + sig_pri_party_id_convert(&caller_party, &mcid->originator, pri); + send_mcid(owner, &caller_party, &connected_party); + ast_party_id_free(&caller_party); } - - /* Always use libpri's called party information. */ - ast_party_id_init(&party); - sig_pri_party_id_convert(&party, &mcid->answerer, pri); - sig_pri_event_party_id(&msg, "ConnectedID", &party); - ast_party_id_free(&party); - - chans[0] = owner; - ast_manager_event_multichan(EVENT_FLAG_CALL, "MCID", owner ? 1 : 0, chans, "%s", - ast_str_buffer(msg)); - ast_free(msg); + ast_party_id_free(&connected_party); } #endif /* defined(HAVE_PRI_MCID) */ @@ -10003,6 +10129,12 @@ void sig_pri_cc_monitor_destructor(void *monitor_pvt) */ int sig_pri_load(const char *cc_type_name) { +#if defined(HAVE_PRI_MCID) + if (STASIS_MESSAGE_TYPE_INIT(mcid_type)) { + return -1; + } +#endif /* defined(HAVE_PRI_MCID) */ + #if defined(HAVE_PRI_CCSS) sig_pri_cc_type_name = cc_type_name; sig_pri_cc_monitors = ao2_container_alloc(37, sig_pri_cc_monitor_instance_hash_fn, @@ -10028,6 +10160,10 @@ void sig_pri_unload(void) sig_pri_cc_monitors = NULL; } #endif /* defined(HAVE_PRI_CCSS) */ + +#if defined(HAVE_PRI_MCID) + STASIS_MESSAGE_TYPE_CLEANUP(mcid_type); +#endif /* defined(HAVE_PRI_MCID) */ } #endif /* HAVE_PRI */ diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 8b4672b25..302943941 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -219,7 +219,6 @@ #define DEFAULT_QUALIFY FALSE /*!< Don't monitor devices */ #define DEFAULT_KEEPALIVE 0 /*!< Don't send keep alive packets */ #define DEFAULT_KEEPALIVE_INTERVAL 60 /*!< Send keep alive packets at 60 second intervals */ -#define DEFAULT_CALLEVENTS FALSE /*!< Extra manager SIP call events */ #define DEFAULT_ALWAYSAUTHREJECT TRUE /*!< Don't reject authentication requests always */ #define DEFAULT_AUTH_OPTIONS FALSE #define DEFAULT_AUTH_MESSAGE TRUE @@ -744,7 +743,6 @@ struct sip_settings { int accept_outofcall_message; /*!< Accept MESSAGE outside of a call */ int compactheaders; /*!< send compact sip headers */ int allow_external_domains; /*!< Accept calls to external SIP domains? */ - int callevents; /*!< Whether we send manager events or not */ int regextenonqualify; /*!< Whether to add/remove regexten when qualifying peers */ int legacy_useroption_parsing; /*!< Whether to strip useroptions in URI via semicolons */ int send_diversion; /*!< Whether to Send SIP Diversion headers */ -- cgit v1.2.3