From 04a912330985d1197e58209b1ec98774e6cce68e Mon Sep 17 00:00:00 2001 From: Jonathan Rose Date: Thu, 3 Jul 2014 17:20:00 +0000 Subject: pbx_config: Add manager actions to add/remove extensions Adds two new manager commands to pbx_config - DialplanExtensionAdd and DialplanExtensionRemove which allow manager users to create and delete extensions respectively. Review: https://reviewboard.asterisk.org/r/3650/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@417910 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 4 ++ main/pbx.c | 4 +- pbx/pbx_config.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 2cdac47f2..12272c308 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,10 @@ AMI res_manager_presence_state.so. If the high frequency of these events is problematic for you, do not load these modules. + * Added DialplanExtensionAdd and DialplanExtensionRemove AMI commands. They + work in basically the same way as the 'dialplan add extension' and + 'dialplan remove extension' CLI commands respectively. + * New AMI action LoggerRotate reloads and rotates logger in the same manner as CLI command 'logger rotate' diff --git a/main/pbx.c b/main/pbx.c index 3c7b127e6..2f0c06405 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -10046,8 +10046,8 @@ static int ast_add_extension2_lockopt(struct ast_context *con, ast_unlock_context(con); } if (res < 0) { - errno = EEXIST; /* XXX do we care ? */ - return 0; /* XXX should we return -1 maybe ? */ + errno = EEXIST; + return -1; } } else { /* diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c index 478d3ce54..8301f25da 100644 --- a/pbx/pbx_config.c +++ b/pbx/pbx_config.c @@ -27,6 +27,59 @@ core ***/ +/*** DOCUMENTATION + + + Add an extension to the dialplan + + + + + Context where the extension will be created. The context will + be created if it does not already exist. + + + Name of the extension that will be created (may include callerid match by separating + with '/') + + + Priority being added to this extension. Must be either hint or a + numerical value. + + + The application to use for this extension at the requested priority + + + Arguments to the application. + + + If set to 'yes', '1', 'true' or any of the other values we evaluate as true, then + if an extension already exists at the requested context, extension, and priority it will + be overwritten. Otherwise, the existing extension will remain and the action will fail. + + + + + + + Remove an extension from the dialplan + + + + + Context of the extension being removed + + + Name of the extension being removed (may include callerid match by separating with '/') + + + If provided, only remove this priority from the extension instead of all + priorities in the extension. + + + + ***/ + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -432,6 +485,54 @@ static char *handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int c return ret; } +static int manager_dialplan_extension_remove(struct mansession *s, const struct message *m) +{ + const char *context = astman_get_header(m, "Context"); + const char *extension = astman_get_header(m, "Extension"); + const char *priority = astman_get_header(m, "Priority"); + + int ipriority; + char *exten; + char *cidmatch = NULL; + + if (ast_strlen_zero(context) || ast_strlen_zero(extension)) { + astman_send_error(s, m, "Context and Extension must be provided " + "for DialplanExtensionRemove"); + return 0; + } + + exten = ast_strdupa(extension); + + if (strchr(exten, '/')) { + cidmatch = exten; + strsep(&cidmatch, "/"); + } + + if (ast_strlen_zero(priority)) { + ipriority = 0; + } else if (!strcmp("hint", priority)) { + ipriority = PRIORITY_HINT; + } else if ((sscanf(priority, "%30d", &ipriority) != 1) || ipriority <= 0) { + astman_send_error(s, m, "The priority specified was invalid."); + return 0; + } + + if (!ast_context_remove_extension_callerid(context, exten, ipriority, + /* Do not substitute S_OR; it is not the same thing */ + !ast_strlen_zero(cidmatch) ? cidmatch : (ipriority ? "" : NULL), + !ast_strlen_zero(cidmatch) ? 1 : 0, registrar)) { + if (ipriority) { + astman_send_ack(s, m, "Removed the requested priority from the extension"); + } else { + astman_send_ack(s, m, "Removed the requested extension"); + } + } else { + astman_send_error(s, m, "Failed to remove requested extension"); + } + + return 0; +} + static char *complete_dialplan_remove_extension(struct ast_cli_args *a) { char *ret = NULL; @@ -1055,6 +1156,88 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd, return CLI_SUCCESS; } +static int manager_dialplan_extension_add(struct mansession *s, const struct message *m) +{ + const char *context = astman_get_header(m, "Context"); + const char *extension = astman_get_header(m, "Extension"); + const char *priority = astman_get_header(m, "Priority"); + const char *application = astman_get_header(m, "Application"); + const char *application_data = astman_get_header(m, "ApplicationData"); + int replace = ast_true(astman_get_header(m, "Replace")); + int ipriority; + char *exten; + char *cidmatch = NULL; + struct ast_context *add_context; + + if (ast_strlen_zero(context) || ast_strlen_zero(extension) || + ast_strlen_zero(priority) || ast_strlen_zero(application)) { + astman_send_error(s, m, "Context, Extension, Priority, and " + "Application must be defined for DialplanExtensionAdd."); + return 0; + } + + /* Priority conversion/validation */ + if (!strcmp(priority, "hint")) { + ipriority = PRIORITY_HINT; + } else if ((sscanf(priority, "%30d", &ipriority) != 1) || (ipriority < 0)) { + astman_send_error(s, m, "The priority specified was invalid."); + return 0; + } + + /* Split extension from cidmatch */ + exten = ast_strdupa(extension); + + if (strchr(exten, '/')) { + cidmatch = exten; + strsep(&cidmatch, "/"); + } + + if (ast_wrlock_contexts()) { + astman_send_error(s, m, "Failed to lock contexts list. Try again later."); + return 0; + } + + add_context = ast_context_find_or_create(NULL, NULL, context, registrar); + if (!add_context) { + astman_send_error(s, m, "Could not find or create context specified " + "for the extension."); + ast_unlock_contexts(); + return 0; + } + + if (ast_add_extension2(add_context, replace, exten, ipriority, NULL, cidmatch, + application, ast_strdup(application_data), ast_free_ptr, registrar)) { + ast_unlock_contexts(); + switch (errno) { + case ENOMEM: + astman_send_error(s, m, "Out of Memory"); + break; + + case EBUSY: + astman_send_error(s, m, "Failed to lock context(s) list"); + break; + + case ENOENT: + astman_send_error(s, m, "Context does not exist"); + break; + + case EEXIST: + astman_send_error(s, m, "That extension and priority already exist at that context"); + break; + + default: + astman_send_error(s, m, "Failed to add extension"); + break; + } + return 0; + } + ast_unlock_contexts(); + + astman_send_ack(s, m, "Added requested extension"); + + return 0; +} + static char *complete_dialplan_remove_context(struct ast_cli_args *a) { struct ast_context *c = NULL; @@ -1393,6 +1576,9 @@ static struct ast_cli_entry cli_pbx_config[] = { static struct ast_cli_entry cli_dialplan_save = AST_CLI_DEFINE(handle_cli_dialplan_save, "Save dialplan"); +#define AMI_EXTENSION_ADD "DialplanExtensionAdd" +#define AMI_EXTENSION_REMOVE "DialplanExtensionRemove" + /*! * Standard module functions ... */ @@ -1404,6 +1590,8 @@ static int unload_module(void) ast_free(overrideswitch_config); } ast_cli_unregister_multiple(cli_pbx_config, ARRAY_LEN(cli_pbx_config)); + ast_manager_unregister(AMI_EXTENSION_ADD); + ast_manager_unregister(AMI_EXTENSION_REMOVE); ast_context_destroy(NULL, registrar); return 0; } @@ -1870,10 +2058,22 @@ static int pbx_load_module(void) static int load_module(void) { + int res; + if (static_config && !write_protect_config) ast_cli_register(&cli_dialplan_save); ast_cli_register_multiple(cli_pbx_config, ARRAY_LEN(cli_pbx_config)); + res = ast_manager_register_xml_core(AMI_EXTENSION_ADD, + EVENT_FLAG_SYSTEM, manager_dialplan_extension_add); + res |= ast_manager_register_xml_core(AMI_EXTENSION_REMOVE, + EVENT_FLAG_SYSTEM, manager_dialplan_extension_remove); + + if (res) { + unload_module(); + return AST_MODULE_LOAD_DECLINE; + } + if (pbx_load_module()) return AST_MODULE_LOAD_DECLINE; -- cgit v1.2.3