/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2013, Digium, Inc. * * Jonathan Rose * * 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 Confbridge manager events for stasis messages * * \author Jonathan Rose */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/channel.h" #include "asterisk/bridging.h" #include "asterisk/stasis.h" #include "asterisk/stasis_channels.h" #include "asterisk/stasis_bridging.h" #include "asterisk/manager.h" #include "asterisk/stasis_message_router.h" #include "include/confbridge.h" /*** DOCUMENTATION Raised when a conference starts. The name of the Confbridge conference. ConfbridgeEnd ConfBridge Raised when a conference ends. The name of the Confbridge conference. ConfbridgeStart ConfBridge Raised when a channel joins a Confbridge conference. The name of the Confbridge conference. ConfbridgeLeave ConfBridge Raised when a channel leaves a Confbridge conference. The name of the Confbridge conference. ConfbridgeJoin ConfBridge Raised when a conference starts recording. The name of the Confbridge conference. ConfbridgeStopRecord ConfBridge Raised when a conference that was recording stops recording. The name of the Confbridge conference. ConfbridgeRecord ConfBridge Raised when a Confbridge participant mutes. The name of the Confbridge conference. ConfbridgeUnmute ConfBridge Raised when a confbridge participant unmutes. The name of the Confbridge conference. ConfbridgeMute ConfBridge Raised when a confbridge participant unmutes. The name of the Confbridge conference. ConfBridge ***/ static struct stasis_message_router *bridge_state_router; static struct stasis_message_router *channel_state_router; static void append_event_header(struct ast_str **fields_string, const char *header, const char *value) { struct ast_str *working_str = *fields_string; if (!working_str) { working_str = ast_str_create(128); if (!working_str) { return; } *fields_string = working_str; } ast_str_append(&working_str, 0, "%s: %s\r\n", header, value); } static void stasis_confbridge_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message) { struct ast_bridge_blob *blob = stasis_message_data(message); const char *type = ast_bridge_blob_json_type(blob); const char *conference_name; RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free); RAII_VAR(struct ast_str *, channel_text, NULL, ast_free); RAII_VAR(struct ast_str *, extra_text, NULL, ast_free); char *event; if (!blob || !type) { ast_assert(0); return; } if (!strcmp("confbridge_start", type)) { event = "ConfbridgeStart"; } else if (!strcmp("confbridge_end", type)) { event = "ConfbridgeEnd"; } else if (!strcmp("confbridge_leave", type)) { event = "ConfbridgeLeave"; } else if (!strcmp("confbridge_join", type)) { event = "ConfbridgeJoin"; } else if (!strcmp("confbridge_record", type)) { event = "ConfbridgeRecord"; } else if (!strcmp("confbridge_stop_record", type)) { event = "ConfbridgeStopRecord"; } else if (!strcmp("confbridge_mute", type)) { event = "ConfbridgeMute"; } else if (!strcmp("confbridge_unmute", type)) { event = "ConfbridgeUnmute"; } else if (!strcmp("confbridge_talking", type)) { const char *talking_status = ast_json_string_get(ast_json_object_get(blob->blob, "talking_status")); event = "ConfbridgeTalking"; if (!talking_status) { return; } append_event_header(&extra_text, "TalkingStatus", talking_status); } else { return; } conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference")); if (!conference_name) { ast_assert(0); return; } bridge_text = ast_manager_build_bridge_state_string(blob->bridge, ""); if (blob->channel) { channel_text = ast_manager_build_channel_state_string(blob->channel); } manager_event(EVENT_FLAG_CALL, event, "Conference: %s\r\n" "%s" "%s" "%s", conference_name, ast_str_buffer(bridge_text), channel_text ? ast_str_buffer(channel_text) : "", extra_text ? ast_str_buffer(extra_text) : ""); } static struct stasis_message_type *confbridge_msg_type; struct stasis_message_type *confbridge_message_type(void) { return confbridge_msg_type; } void manager_confbridge_shutdown(void) { ao2_cleanup(confbridge_msg_type); confbridge_msg_type = NULL; if (bridge_state_router) { stasis_message_router_unsubscribe(bridge_state_router); bridge_state_router = NULL; } if (channel_state_router) { stasis_message_router_unsubscribe(channel_state_router); channel_state_router = NULL; } } int manager_confbridge_init(void) { if (!(confbridge_msg_type = stasis_message_type_create("confbridge"))) { return -1; } bridge_state_router = stasis_message_router_create( stasis_caching_get_topic(ast_bridge_topic_all_cached())); if (!bridge_state_router) { return -1; } if (stasis_message_router_add(bridge_state_router, confbridge_message_type(), stasis_confbridge_cb, NULL)) { manager_confbridge_shutdown(); return -1; } channel_state_router = stasis_message_router_create( stasis_caching_get_topic(ast_channel_topic_all_cached())); if (!channel_state_router) { manager_confbridge_shutdown(); return -1; } if (stasis_message_router_add(channel_state_router, confbridge_message_type(), stasis_confbridge_cb, NULL)) { manager_confbridge_shutdown(); return -1; } return 0; }