From e462f0063f3e7fd2a2d8f0603d9c7cf8de46a88f Mon Sep 17 00:00:00 2001 From: Corey Farrell Date: Mon, 4 Jan 2016 21:23:01 -0500 Subject: main/pbx: Move hangup handler routines to pbx_hangup_handler.c. This is the sixth patch in a series meant to reduce the bulk of pbx.c. This moves hangup handler management functions to their own source. Change-Id: Ib25a75aa57fc7d5c4294479e5cc46775912fb104 --- main/asterisk.c | 5 + main/pbx.c | 244 ------------------------------------- main/pbx_hangup_handler.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+), 244 deletions(-) create mode 100644 main/pbx_hangup_handler.c (limited to 'main') diff --git a/main/asterisk.c b/main/asterisk.c index 82220b4df..c576c16f6 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -4668,6 +4668,11 @@ static void asterisk_daemon(int isroot, const char *runuser, const char *rungrou exit(1); } + if (load_pbx_hangup_handler()) { + printf("Failed: load_pbx_hangup_handler\n%s", term_quit()); + exit(1); + } + if (ast_local_init()) { printf("Failed: ast_local_init\n%s", term_quit()); exit(1); diff --git a/main/pbx.c b/main/pbx.c index 7dadddd50..08ae5b6c3 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -4060,248 +4060,6 @@ void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context) ast_channel_unlock(chan); } -/*! - * \internal - * \brief Publish a hangup handler related message to \ref stasis - */ -static void publish_hangup_handler_message(const char *action, struct ast_channel *chan, const char *handler) -{ - RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); - - blob = ast_json_pack("{s: s, s: s}", - "type", action, - "handler", S_OR(handler, "")); - if (!blob) { - return; - } - - ast_channel_publish_blob(chan, ast_channel_hangup_handler_type(), blob); -} - -int ast_pbx_hangup_handler_run(struct ast_channel *chan) -{ - struct ast_hangup_handler_list *handlers; - struct ast_hangup_handler *h_handler; - - ast_channel_lock(chan); - handlers = ast_channel_hangup_handlers(chan); - if (AST_LIST_EMPTY(handlers)) { - ast_channel_unlock(chan); - return 0; - } - - /* - * Make sure that the channel is marked as hungup since we are - * going to run the hangup handlers on it. - */ - ast_softhangup_nolock(chan, AST_SOFTHANGUP_HANGUP_EXEC); - - for (;;) { - handlers = ast_channel_hangup_handlers(chan); - h_handler = AST_LIST_REMOVE_HEAD(handlers, node); - if (!h_handler) { - break; - } - - publish_hangup_handler_message("run", chan, h_handler->args); - ast_channel_unlock(chan); - - ast_app_exec_sub(NULL, chan, h_handler->args, 1); - ast_free(h_handler); - - ast_channel_lock(chan); - } - ast_channel_unlock(chan); - return 1; -} - -void ast_pbx_hangup_handler_init(struct ast_channel *chan) -{ - struct ast_hangup_handler_list *handlers; - - handlers = ast_channel_hangup_handlers(chan); - AST_LIST_HEAD_INIT_NOLOCK(handlers); -} - -void ast_pbx_hangup_handler_destroy(struct ast_channel *chan) -{ - struct ast_hangup_handler_list *handlers; - struct ast_hangup_handler *h_handler; - - ast_channel_lock(chan); - - /* Get rid of each of the hangup handlers on the channel */ - handlers = ast_channel_hangup_handlers(chan); - while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) { - ast_free(h_handler); - } - - ast_channel_unlock(chan); -} - -int ast_pbx_hangup_handler_pop(struct ast_channel *chan) -{ - struct ast_hangup_handler_list *handlers; - struct ast_hangup_handler *h_handler; - - ast_channel_lock(chan); - handlers = ast_channel_hangup_handlers(chan); - h_handler = AST_LIST_REMOVE_HEAD(handlers, node); - if (h_handler) { - publish_hangup_handler_message("pop", chan, h_handler->args); - } - ast_channel_unlock(chan); - if (h_handler) { - ast_free(h_handler); - return 1; - } - return 0; -} - -void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler) -{ - struct ast_hangup_handler_list *handlers; - struct ast_hangup_handler *h_handler; - const char *expanded_handler; - - if (ast_strlen_zero(handler)) { - return; - } - - expanded_handler = ast_app_expand_sub_args(chan, handler); - if (!expanded_handler) { - return; - } - h_handler = ast_malloc(sizeof(*h_handler) + 1 + strlen(expanded_handler)); - if (!h_handler) { - ast_free((char *) expanded_handler); - return; - } - strcpy(h_handler->args, expanded_handler);/* Safe */ - ast_free((char *) expanded_handler); - - ast_channel_lock(chan); - - handlers = ast_channel_hangup_handlers(chan); - AST_LIST_INSERT_HEAD(handlers, h_handler, node); - publish_hangup_handler_message("push", chan, h_handler->args); - ast_channel_unlock(chan); -} - -#define HANDLER_FORMAT "%-30s %s\n" - -/*! - * \internal - * \brief CLI output the hangup handler headers. - * \since 11.0 - * - * \param fd CLI file descriptor to use. - * - * \return Nothing - */ -static void ast_pbx_hangup_handler_headers(int fd) -{ - ast_cli(fd, HANDLER_FORMAT, "Channel", "Handler"); -} - -/*! - * \internal - * \brief CLI output the channel hangup handlers. - * \since 11.0 - * - * \param fd CLI file descriptor to use. - * \param chan Channel to show hangup handlers. - * - * \return Nothing - */ -static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan) -{ - struct ast_hangup_handler_list *handlers; - struct ast_hangup_handler *h_handler; - int first = 1; - - ast_channel_lock(chan); - handlers = ast_channel_hangup_handlers(chan); - AST_LIST_TRAVERSE(handlers, h_handler, node) { - ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args); - first = 0; - } - ast_channel_unlock(chan); -} - -/* - * \brief 'show hanguphandlers ' CLI command implementation function... - */ -static char *handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) -{ - struct ast_channel *chan; - - switch (cmd) { - case CLI_INIT: - e->command = "core show hanguphandlers"; - e->usage = - "Usage: core show hanguphandlers \n" - " Show hangup handlers of a specified channel.\n"; - return NULL; - case CLI_GENERATE: - return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args); - } - - if (a->argc < 4) { - return CLI_SHOWUSAGE; - } - - chan = ast_channel_get_by_name(a->argv[3]); - if (!chan) { - ast_cli(a->fd, "Channel does not exist.\n"); - return CLI_FAILURE; - } - - ast_pbx_hangup_handler_headers(a->fd); - ast_pbx_hangup_handler_show(a->fd, chan); - - ast_channel_unref(chan); - - return CLI_SUCCESS; -} - -/* - * \brief 'show hanguphandlers all' CLI command implementation function... - */ -static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) -{ - struct ast_channel_iterator *iter; - struct ast_channel *chan; - - switch (cmd) { - case CLI_INIT: - e->command = "core show hanguphandlers all"; - e->usage = - "Usage: core show hanguphandlers all\n" - " Show hangup handlers for all channels.\n"; - return NULL; - case CLI_GENERATE: - return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args); - } - - if (a->argc < 4) { - return CLI_SHOWUSAGE; - } - - iter = ast_channel_iterator_all_new(); - if (!iter) { - return CLI_FAILURE; - } - - ast_pbx_hangup_handler_headers(a->fd); - for (; (chan = ast_channel_iterator_next(iter)); ast_channel_unref(chan)) { - ast_pbx_hangup_handler_show(a->fd, chan); - } - ast_channel_iterator_destroy(iter); - - return CLI_SUCCESS; -} - /*! helper function to set extension and priority */ void set_ext_pri(struct ast_channel *c, const char *exten, int pri) { @@ -6142,8 +5900,6 @@ static struct ast_cli_entry pbx_cli[] = { #ifdef AST_DEVMODE AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"), #endif - AST_CLI_DEFINE(handle_show_hangup_all, "Show hangup handlers of all channels"), - AST_CLI_DEFINE(handle_show_hangup_channel, "Show hangup handlers of a specified channel"), AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"), AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"), AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."), diff --git a/main/pbx_hangup_handler.c b/main/pbx_hangup_handler.c new file mode 100644 index 000000000..3b8254732 --- /dev/null +++ b/main/pbx_hangup_handler.c @@ -0,0 +1,300 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2016, CFWare, LLC + * + * Corey Farrell + * + * 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 PBX Hangup Handler management routines. + * + * \author Corey Farrell + */ + +/*** MODULEINFO + core + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/_private.h" +#include "asterisk/app.h" +#include "asterisk/cli.h" +#include "asterisk/linkedlists.h" +#include "asterisk/pbx.h" +#include "asterisk/stasis_channels.h" +#include "asterisk/utils.h" + +/*! + * \internal + * \brief Publish a hangup handler related message to \ref stasis + */ +static void publish_hangup_handler_message(const char *action, struct ast_channel *chan, const char *handler) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + + blob = ast_json_pack("{s: s, s: s}", + "type", action, + "handler", S_OR(handler, "")); + if (!blob) { + return; + } + + ast_channel_publish_blob(chan, ast_channel_hangup_handler_type(), blob); +} + +int ast_pbx_hangup_handler_run(struct ast_channel *chan) +{ + struct ast_hangup_handler_list *handlers; + struct ast_hangup_handler *h_handler; + + ast_channel_lock(chan); + handlers = ast_channel_hangup_handlers(chan); + if (AST_LIST_EMPTY(handlers)) { + ast_channel_unlock(chan); + return 0; + } + + /* + * Make sure that the channel is marked as hungup since we are + * going to run the hangup handlers on it. + */ + ast_softhangup_nolock(chan, AST_SOFTHANGUP_HANGUP_EXEC); + + for (;;) { + handlers = ast_channel_hangup_handlers(chan); + h_handler = AST_LIST_REMOVE_HEAD(handlers, node); + if (!h_handler) { + break; + } + + publish_hangup_handler_message("run", chan, h_handler->args); + ast_channel_unlock(chan); + + ast_app_exec_sub(NULL, chan, h_handler->args, 1); + ast_free(h_handler); + + ast_channel_lock(chan); + } + ast_channel_unlock(chan); + return 1; +} + +void ast_pbx_hangup_handler_init(struct ast_channel *chan) +{ + struct ast_hangup_handler_list *handlers; + + handlers = ast_channel_hangup_handlers(chan); + AST_LIST_HEAD_INIT_NOLOCK(handlers); +} + +void ast_pbx_hangup_handler_destroy(struct ast_channel *chan) +{ + struct ast_hangup_handler_list *handlers; + struct ast_hangup_handler *h_handler; + + ast_channel_lock(chan); + + /* Get rid of each of the hangup handlers on the channel */ + handlers = ast_channel_hangup_handlers(chan); + while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) { + ast_free(h_handler); + } + + ast_channel_unlock(chan); +} + +int ast_pbx_hangup_handler_pop(struct ast_channel *chan) +{ + struct ast_hangup_handler_list *handlers; + struct ast_hangup_handler *h_handler; + + ast_channel_lock(chan); + handlers = ast_channel_hangup_handlers(chan); + h_handler = AST_LIST_REMOVE_HEAD(handlers, node); + if (h_handler) { + publish_hangup_handler_message("pop", chan, h_handler->args); + } + ast_channel_unlock(chan); + if (h_handler) { + ast_free(h_handler); + return 1; + } + return 0; +} + +void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler) +{ + struct ast_hangup_handler_list *handlers; + struct ast_hangup_handler *h_handler; + const char *expanded_handler; + + if (ast_strlen_zero(handler)) { + return; + } + + expanded_handler = ast_app_expand_sub_args(chan, handler); + if (!expanded_handler) { + return; + } + h_handler = ast_malloc(sizeof(*h_handler) + 1 + strlen(expanded_handler)); + if (!h_handler) { + ast_free((char *) expanded_handler); + return; + } + strcpy(h_handler->args, expanded_handler);/* Safe */ + ast_free((char *) expanded_handler); + + ast_channel_lock(chan); + + handlers = ast_channel_hangup_handlers(chan); + AST_LIST_INSERT_HEAD(handlers, h_handler, node); + publish_hangup_handler_message("push", chan, h_handler->args); + ast_channel_unlock(chan); +} + +#define HANDLER_FORMAT "%-30s %s\n" + +/*! + * \internal + * \brief CLI output the hangup handler headers. + * \since 11.0 + * + * \param fd CLI file descriptor to use. + * + * \return Nothing + */ +static void ast_pbx_hangup_handler_headers(int fd) +{ + ast_cli(fd, HANDLER_FORMAT, "Channel", "Handler"); +} + +/*! + * \internal + * \brief CLI output the channel hangup handlers. + * \since 11.0 + * + * \param fd CLI file descriptor to use. + * \param chan Channel to show hangup handlers. + * + * \return Nothing + */ +static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan) +{ + struct ast_hangup_handler_list *handlers; + struct ast_hangup_handler *h_handler; + int first = 1; + + ast_channel_lock(chan); + handlers = ast_channel_hangup_handlers(chan); + AST_LIST_TRAVERSE(handlers, h_handler, node) { + ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args); + first = 0; + } + ast_channel_unlock(chan); +} + +/* + * \brief 'show hanguphandlers ' CLI command implementation function... + */ +static char *handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + struct ast_channel *chan; + + switch (cmd) { + case CLI_INIT: + e->command = "core show hanguphandlers"; + e->usage = + "Usage: core show hanguphandlers \n" + " Show hangup handlers of a specified channel.\n"; + return NULL; + case CLI_GENERATE: + return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args); + } + + if (a->argc < 4) { + return CLI_SHOWUSAGE; + } + + chan = ast_channel_get_by_name(a->argv[3]); + if (!chan) { + ast_cli(a->fd, "Channel does not exist.\n"); + return CLI_FAILURE; + } + + ast_pbx_hangup_handler_headers(a->fd); + ast_pbx_hangup_handler_show(a->fd, chan); + + ast_channel_unref(chan); + + return CLI_SUCCESS; +} + +/* + * \brief 'show hanguphandlers all' CLI command implementation function... + */ +static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + struct ast_channel_iterator *iter; + struct ast_channel *chan; + + switch (cmd) { + case CLI_INIT: + e->command = "core show hanguphandlers all"; + e->usage = + "Usage: core show hanguphandlers all\n" + " Show hangup handlers for all channels.\n"; + return NULL; + case CLI_GENERATE: + return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args); + } + + if (a->argc < 4) { + return CLI_SHOWUSAGE; + } + + iter = ast_channel_iterator_all_new(); + if (!iter) { + return CLI_FAILURE; + } + + ast_pbx_hangup_handler_headers(a->fd); + for (; (chan = ast_channel_iterator_next(iter)); ast_channel_unref(chan)) { + ast_pbx_hangup_handler_show(a->fd, chan); + } + ast_channel_iterator_destroy(iter); + + return CLI_SUCCESS; +} + +static struct ast_cli_entry cli[] = { + AST_CLI_DEFINE(handle_show_hangup_all, "Show hangup handlers of all channels"), + AST_CLI_DEFINE(handle_show_hangup_channel, "Show hangup handlers of a specified channel"), +}; + +static void unload_pbx_hangup_handler(void) +{ + ast_cli_unregister_multiple(cli, ARRAY_LEN(cli)); +} + +int load_pbx_hangup_handler(void) +{ + ast_cli_register_multiple(cli, ARRAY_LEN(cli)); + ast_register_cleanup(unload_pbx_hangup_handler); + + return 0; +} -- cgit v1.2.3