From 7422581b6d4921cebfcf177fc63b2ef852fdef58 Mon Sep 17 00:00:00 2001 From: Jason Parker Date: Mon, 8 Jul 2013 14:42:57 +0000 Subject: [PATCH] Move channel driver Registry manager events to core. This also shuffles the stasis system topic and related handling. (closes issue ASTERISK-21488) Review: https://reviewboard.asterisk.org/r/2631/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393804 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 11 +- channels/chan_sip.c | 13 ++- include/asterisk.h | 21 ---- include/asterisk/manager.h | 8 ++ include/asterisk/stasis_system.h | 71 +++++++++++++ main/asterisk.c | 42 +------- main/file.c | 1 + main/manager.c | 4 + main/manager_system.c | 81 +++++++++++++++ main/sounds_index.c | 1 + main/stasis_system.c | 170 +++++++++++++++++++++++++++++++ res/res_stun_monitor.c | 3 +- 12 files changed, 359 insertions(+), 67 deletions(-) create mode 100644 include/asterisk/stasis_system.h create mode 100644 main/manager_system.c create mode 100644 main/stasis_system.c diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 23006364cc..38b94ac331 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -103,6 +103,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/security_events.h" #include "asterisk/stasis_endpoints.h" #include "asterisk/bridging.h" +#include "asterisk/stasis.h" +#include "asterisk/stasis_system.h" #include "iax2/include/iax2.h" #include "iax2/include/firmware.h" @@ -8376,6 +8378,11 @@ static int complete_transfer(int callno, struct iax_ies *ies) return 0; } +static void iax2_publish_registry(const char *username, const char *domain, const char *status, const char *cause) +{ + ast_system_publish_registry("IAX2", username, domain, status, cause); +} + /*! \brief Acknowledgment received for OUR registration */ static int iax2_ack_registry(struct iax_ies *ies, struct sockaddr_in *sin, int callno) { @@ -8437,7 +8444,7 @@ static int iax2_ack_registry(struct iax_ies *ies, struct sockaddr_in *sin, int c } snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); ast_verb(3, "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); - manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); + iax2_publish_registry(reg->username, ast_inet_ntoa(sin->sin_addr), "Registered", NULL); } reg->regstate = REG_STATE_REGISTERED; return 0; @@ -11179,8 +11186,8 @@ immediatedial: if (iaxs[fr->callno]->reg) { if (authdebug) { ast_log(LOG_NOTICE, "Registration of '%s' rejected: '%s' from: '%s'\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "", ast_inet_ntoa(sin.sin_addr)); - manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : ""); } + iax2_publish_registry(iaxs[fr->callno]->reg->username, ast_inet_ntoa(sin.sin_addr), "Rejected", S_OR(ies.cause, "")); iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; } /* Send ack immediately, before we destroy */ diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9373a64351..3c1f97b050 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -294,7 +294,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/sip_api.h" #include "asterisk/app.h" #include "asterisk/bridging.h" +#include "asterisk/stasis.h" #include "asterisk/stasis_endpoints.h" +#include "asterisk/stasis_system.h" #include "asterisk/stasis_channels.h" #include "asterisk/features_config.h" @@ -15076,6 +15078,11 @@ static const char *regstate2str(enum sipregistrystate regstate) return map_x_s(regstatestrings, regstate, "Unknown"); } +static void sip_publish_registry(const char *username, const char *domain, const char *status) +{ + ast_system_publish_registry("SIP", username, domain, status, NULL); +} + /*! \brief Update registration with SIP Proxy. * Called from the scheduler when the previous registration expires, * so we don't have to cancel the pending event. @@ -15176,7 +15183,7 @@ static int sip_reg_timeout(const void *data) transmit_register(r, SIP_REGISTER, NULL, NULL); ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts); } - manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); + sip_publish_registry(r->username, r->hostname, regstate2str(r->regstate)); registry_unref(r, "unreffing registry_unref r"); return 0; } @@ -23692,7 +23699,7 @@ static int handle_response_register(struct sip_pvt *p, int resp, const char *res r->regstate = REG_STATE_UNREGISTERED; transmit_register(r, SIP_REGISTER, NULL, NULL); } - manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); + sip_publish_registry(r->username, r->hostname, regstate2str(r->regstate)); break; case 479: /* SER: Not able to process the URI - address is wrong in register*/ ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username, p->registry->hostname); @@ -23711,7 +23718,7 @@ static int handle_response_register(struct sip_pvt *p, int resp, const char *res r->regstate = REG_STATE_REGISTERED; r->regtime = ast_tvnow(); /* Reset time of last successful registration */ - manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); + sip_publish_registry(r->username, r->hostname, regstate2str(r->regstate)); r->regattempts = 0; ast_debug(1, "Registration successful\n"); if (r->timeout > -1) { diff --git a/include/asterisk.h b/include/asterisk.h index 87ebec032a..35628d231a 100644 --- a/include/asterisk.h +++ b/include/asterisk.h @@ -216,27 +216,6 @@ int64_t ast_mark(int, int start1_stop0); #define ast_mark(a, b) do { } while (0) #endif /* LOW_MEMORY */ -/*! - * \since 12 - * \brief A \ref stasis topic which publishes messages regarding system changes - * - * \retval \ref stasis_topic for system level changes - * \retval NULL on error - */ -struct stasis_topic *ast_system_topic(void); - -/*! - * \since 12 - * \brief A \ref stasis_message_type for network changes - * - * \retval NULL on error - * \retval \ref stasis_message_type for network changes - * - * \note Messages of this type should always be issued on and expected from - * the \ref ast_system_topic \ref stasis topic - */ -struct stasis_message_type *ast_network_change_type(void); - /*! \brief * Definition of various structures that many asterisk files need, * but only because they need to know that the type exists. diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index c44d6d0349..bdf257810e 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -439,6 +439,14 @@ ast_manager_event_blob_create( /*! GCC warns about blank or NULL format strings. So, shenanigans! */ #define NO_EXTRA_FIELDS "%s", "" +/*! + * \since 12 + * \brief Initialize support for AMI system events. + * \retval 0 on success + * \retval non-zero on error + */ +int manager_system_init(void); + /*! * \brief Initialize support for AMI channel events. * \retval 0 on success. diff --git a/include/asterisk/stasis_system.h b/include/asterisk/stasis_system.h new file mode 100644 index 0000000000..07e16a25df --- /dev/null +++ b/include/asterisk/stasis_system.h @@ -0,0 +1,71 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013, Digium, Inc. + * + * Jason Parker + * + * 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. + */ + +#ifndef _ASTERISK_STASIS_SYSTEM_H +#define _ASTERISK_STASIS_SYSTEM_H + +#include "asterisk/json.h" +#include "asterisk/stasis.h" + +/*! + * \since 12 + * \brief Publish a channel driver outgoing registration message + * + * \param channeltype The channel driver that published the message + * \param username The username that was used to register + * \param domain The domain that was used to register + * \param status The result of the registration + * \param cause The reason for the result + */ +void ast_system_publish_registry(const char *channeltype, const char *username, const char *domain, const char *status, const char *cause); + +/*! + * \since 12 + * \brief A \ref stasis topic which publishes messages regarding system changes + * + * \retval \ref stasis_topic for system level changes + * \retval NULL on error + */ +struct stasis_topic *ast_system_topic(void); + +/*! + * \since 12 + * \brief A \ref stasis_message_type for network changes + * + * \retval NULL on error + * \retval \ref stasis_message_type for network changes + * + * \note Messages of this type should always be issued on and expected from + * the \ref ast_system_topic \ref stasis topic + */ +struct stasis_message_type *ast_network_change_type(void); + +/*! + * \brief A \ref stasis_message_type for outbound registration. + * \since 12 + */ +struct stasis_message_type *ast_system_registry_type(void); + +/*! + * \brief Initialize the stasis system topic and message types + * \retval 0 on success + * \retval -1 on failure + */ +int ast_stasis_system_init(void); + +#endif /* _ASTERISK_STASIS_SYSTEM_H */ diff --git a/main/asterisk.c b/main/asterisk.c index b8cf43e37b..c7c67e7955 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -243,6 +243,7 @@ int daemon(int, int); /* defined in libresolv of all places */ #include "asterisk/stasis.h" #include "asterisk/json.h" #include "asterisk/stasis_endpoints.h" +#include "asterisk/stasis_system.h" #include "asterisk/security_events.h" #include "../defaults.h" @@ -448,12 +449,6 @@ static struct { unsigned int need_quit_handler:1; } sig_flags; -/*! \brief The \ref stasis topic for system level changes */ -static struct stasis_topic *system_topic; - -/*!\ brief The \ref stasis_message_type for network changes */ -STASIS_MESSAGE_TYPE_DEFN(ast_network_change_type); - #if !defined(LOW_MEMORY) struct file_version { AST_RWLIST_ENTRY(file_version) list; @@ -461,9 +456,6 @@ struct file_version { char *version; }; -/*! \brief The \ref stasis topic for system level changes */ -static struct stasis_topic *system_topic; - static AST_RWLIST_HEAD_STATIC(file_versions, file_version); void ast_register_file_version(const char *file, const char *version) @@ -1098,36 +1090,6 @@ static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct #endif /* ! LOW_MEMORY */ -struct stasis_topic *ast_system_topic(void) -{ - return system_topic; -} - -/*! \brief Cleanup the \ref stasis system level items */ -static void stasis_system_topic_cleanup(void) -{ - ao2_cleanup(system_topic); - system_topic = NULL; - STASIS_MESSAGE_TYPE_CLEANUP(ast_network_change_type); -} - -/*! \brief Initialize the system level items for \ref stasis */ -static int stasis_system_topic_init(void) -{ - ast_register_cleanup(stasis_system_topic_cleanup); - - system_topic = stasis_topic_create("ast_system"); - if (!system_topic) { - return 1; - } - - if (STASIS_MESSAGE_TYPE_INIT(ast_network_change_type) != 0) { - return -1; - } - - return 0; -} - static void publish_fully_booted(void) { RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref); @@ -4218,7 +4180,7 @@ int main(int argc, char *argv[]) exit(1); } - if (stasis_system_topic_init()) { + if (ast_stasis_system_init()) { printf("Stasis system-level information initialization failed.\n%s", term_quit()); exit(1); } diff --git a/main/file.c b/main/file.c index cb495b3100..a351fd4ec1 100644 --- a/main/file.c +++ b/main/file.c @@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/test.h" #include "asterisk/stasis.h" #include "asterisk/json.h" +#include "asterisk/stasis_system.h" /*! \brief * The following variable controls the layout of localized sound files. diff --git a/main/manager.c b/main/manager.c index b1c7b5361a..b8b067dea6 100644 --- a/main/manager.c +++ b/main/manager.c @@ -7827,6 +7827,10 @@ static int __init_manager(int reload, int by_external_config) ast_log(AST_LOG_ERROR, "Failed to initialize manager subscriptions\n"); return -1; } + if (manager_system_init()) { + ast_log(AST_LOG_ERROR, "Failed to initialize manager system handling\n"); + return -1; + } if (manager_channels_init()) { ast_log(AST_LOG_ERROR, "Failed to initialize manager channel handling\n"); return -1; diff --git a/main/manager_system.c b/main/manager_system.c new file mode 100644 index 0000000000..4fef11da4c --- /dev/null +++ b/main/manager_system.c @@ -0,0 +1,81 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013, Digium, Inc. + * + * Jason Parker + * + * 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. + */ + +/*! \file + * + * \brief System AMI event handling + * + * \author Jason Parker + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/stasis.h" +#include "asterisk/stasis_message_router.h" +#include "asterisk/stasis_system.h" + +/*! \brief The \ref stasis subscription returned by the forwarding of the system topic + * to the manager topic + */ +static struct stasis_subscription *topic_forwarder; + +static void manager_system_shutdown(void) +{ + stasis_unsubscribe(topic_forwarder); + topic_forwarder = NULL; +} + +int manager_system_init(void) +{ + int ret = 0; + struct stasis_topic *manager_topic; + struct stasis_topic *system_topic; + struct stasis_message_router *message_router; + + manager_topic = ast_manager_get_topic(); + if (!manager_topic) { + return -1; + } + message_router = ast_manager_get_message_router(); + if (!message_router) { + return -1; + } + system_topic = ast_system_topic(); + if (!system_topic) { + return -1; + } + + topic_forwarder = stasis_forward_all(system_topic, manager_topic); + if (!topic_forwarder) { + return -1; + } + + ast_register_atexit(manager_system_shutdown); + + /* If somehow we failed to add any routes, just shut down the whole + * thing and fail it. + */ + if (ret) { + manager_system_shutdown(); + return -1; + } + + return 0; +} diff --git a/main/sounds_index.c b/main/sounds_index.c index a627f68ce8..ff9a45802d 100644 --- a/main/sounds_index.c +++ b/main/sounds_index.c @@ -36,6 +36,7 @@ #include "asterisk/cli.h" #include "asterisk/_private.h" #include "asterisk/stasis_message_router.h" +#include "asterisk/stasis_system.h" /*** MODULEINFO core diff --git a/main/stasis_system.c b/main/stasis_system.c new file mode 100644 index 0000000000..15451ed1bf --- /dev/null +++ b/main/stasis_system.c @@ -0,0 +1,170 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013, Digium, Inc. + * + * Jason Parker + * + * 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. + */ + +/*! \file + * + * \brief Stasis Messages and Data Types for System events + * + * \author Jason Parker + */ + +/*** MODULEINFO + core + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/astobj2.h" +#include "asterisk/stasis.h" +#include "asterisk/stasis_system.h" + +/*** DOCUMENTATION + + + Raised when an outbound registration completes. + + + The type of channel that was registered (or not). + + + The username portion of the registration. + + + The address portion of the registration. + + + The status of the registration request. + + + + + + + + + What caused the rejection of the request, if available. + + + + + ***/ + +/*! \brief The \ref stasis topic for system level changes */ +static struct stasis_topic *system_topic; + +static struct ast_manager_event_blob *system_registry_to_ami(struct stasis_message *message); + +STASIS_MESSAGE_TYPE_DEFN(ast_network_change_type); +STASIS_MESSAGE_TYPE_DEFN(ast_system_registry_type, + .to_ami = system_registry_to_ami, + ); + +void ast_system_publish_registry(const char *channeltype, const char *username, const char *domain, const char *status, const char *cause) +{ + RAII_VAR(struct ast_json *, registry, NULL, ast_json_unref); + RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup); + RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + + registry = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s}", + "type", "registry", + "channeltype", channeltype, + "username", username, + "domain", domain, + "status", status, + "cause", S_OR(cause, "")); + + if (!(payload = ast_json_payload_create(registry))) { + return; + } + + if (!(message = stasis_message_create(ast_system_registry_type(), payload))) { + return; + } + + stasis_publish(ast_system_topic(), message); +} + +static struct ast_manager_event_blob *system_registry_to_ami(struct stasis_message *message) +{ + struct ast_json_payload *payload = stasis_message_data(message); + const char *channeltype; + const char *username; + const char *domain; + const char *status; + const char *cause; + RAII_VAR(struct ast_str *, cause_string, ast_str_create(32), ast_free); + + if (!cause_string) { + return NULL; + } + + channeltype = ast_json_string_get(ast_json_object_get(payload->json, "channeltype")); + username = ast_json_string_get(ast_json_object_get(payload->json, "username")); + domain = ast_json_string_get(ast_json_object_get(payload->json, "domain")); + status = ast_json_string_get(ast_json_object_get(payload->json, "status")); + cause = ast_json_string_get(ast_json_object_get(payload->json, "cause")); + + if (!ast_strlen_zero(cause)) { + ast_str_set(&cause_string, 0, "Cause: %s\r\n", cause); + } + + return ast_manager_event_blob_create(EVENT_FLAG_SYSTEM, "Registry", + "ChannelType: %s\r\n" + "Username: %s\r\n" + "Domain: %s\r\n" + "Status: %s\r\n" + "%s", + channeltype, username, domain, status, ast_str_buffer(cause_string)); +} + +struct stasis_topic *ast_system_topic(void) +{ + return system_topic; +} + +/*! \brief Cleanup the \ref stasis system level items */ +static void stasis_system_cleanup(void) +{ + ao2_cleanup(system_topic); + system_topic = NULL; + STASIS_MESSAGE_TYPE_CLEANUP(ast_network_change_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_system_registry_type); +} + +/*! \brief Initialize the system level items for \ref stasis */ +int ast_stasis_system_init(void) +{ + ast_register_cleanup(stasis_system_cleanup); + + system_topic = stasis_topic_create("ast_system"); + if (!system_topic) { + return 1; + } + + if (STASIS_MESSAGE_TYPE_INIT(ast_network_change_type) != 0) { + return -1; + } + + if (STASIS_MESSAGE_TYPE_INIT(ast_system_registry_type) != 0) { + return -1; + } + + return 0; +} diff --git a/res/res_stun_monitor.c b/res/res_stun_monitor.c index 58b52a6cb2..42ba106e33 100644 --- a/res/res_stun_monitor.c +++ b/res/res_stun_monitor.c @@ -39,8 +39,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/lock.h" #include "asterisk/acl.h" #include "asterisk/cli.h" -#include "asterisk/stasis.h" #include "asterisk/json.h" +#include "asterisk/stasis.h" +#include "asterisk/stasis_system.h" #include "asterisk/astobj2.h" #include