From 2a1d7f97d66b53803208aaccadb0052127f743d6 Mon Sep 17 00:00:00 2001 From: Thomas Sevestre Date: Fri, 25 Aug 2017 13:19:00 +0000 Subject: features, manager : Add CancelAtxfer AMI action Add action to cancel feature attended transfer with AMI interface ASTERISK-27215 #close Change-Id: Iab8a81362b5a1757e2608f70b014ef863200cb42 --- CHANGES | 4 +++ include/asterisk/features_config.h | 15 +++++++++ main/features_config.c | 15 +++++++++ main/manager.c | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/CHANGES b/CHANGES index 2cc8ad10a..175d0f0d8 100644 --- a/CHANGES +++ b/CHANGES @@ -72,6 +72,10 @@ app_queue ------------------ * Add priority to callers in AMI QueueStatus response. +AMI +------------------ + * Added a new CancelAtxfer action that cancels an attended transfer. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 14.5.0 to Asterisk 14.6.0 ------------ ------------------------------------------------------------------------------ diff --git a/include/asterisk/features_config.h b/include/asterisk/features_config.h index baaff183b..1bce50bba 100644 --- a/include/asterisk/features_config.h +++ b/include/asterisk/features_config.h @@ -116,6 +116,21 @@ struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_ch */ char *ast_get_chan_features_xferfailsound(struct ast_channel *chan); +/*! + * \brief Get the transfer configuration option atxferabort + * + * \note The channel should be locked before calling this function. + * \note The returned value has to be freed. + * + * If no channel is provided, then option is pulled from the global + * transfer configuration. + * + * \param chan The channel to get configuration options for + * \retval NULL Failed to get configuration + * \retval non-NULL The atxferabort + */ +char *ast_get_chan_features_atxferabort(struct ast_channel *chan); + /*! * \brief Configuration relating to call pickup */ diff --git a/main/features_config.c b/main/features_config.c index 8307b1209..72cd0404f 100644 --- a/main/features_config.c +++ b/main/features_config.c @@ -1173,6 +1173,21 @@ char *ast_get_chan_features_xferfailsound(struct ast_channel *chan) return res; } +char *ast_get_chan_features_atxferabort(struct ast_channel *chan) +{ + char *res; + struct ast_features_xfer_config *cfg = ast_get_chan_features_xfer_config(chan); + + if (!cfg) { + return NULL; + } + + res = ast_strdup(cfg->atxferabort); + ao2_ref(cfg, -1); + + return res; +} + struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan) { RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup); diff --git a/main/manager.c b/main/manager.c index c5c75076c..8639a75ac 100644 --- a/main/manager.c +++ b/main/manager.c @@ -630,6 +630,25 @@ ASTERISK_REGISTER_FILE() AttendedTransfer + + + Cancel an attended transfer. + + + + + The transferer channel. + + + + Cancel an attended transfer. Note, this uses the configured cancel attended transfer + feature option (atxferabort) to cancel the transfer. If not available this action will fail. + + + + AttendedTransfer + + Originate a call. @@ -4964,6 +4983,47 @@ static int action_atxfer(struct mansession *s, const struct message *m) return 0; } +static int action_cancel_atxfer(struct mansession *s, const struct message *m) +{ + const char *name = astman_get_header(m, "Channel"); + struct ast_channel *chan = NULL; + char *feature_code; + const char *digit; + + if (ast_strlen_zero(name)) { + astman_send_error(s, m, "No channel specified"); + return 0; + } + + if (!(chan = ast_channel_get_by_name(name))) { + astman_send_error(s, m, "Channel specified does not exist"); + return 0; + } + + ast_channel_lock(chan); + feature_code = ast_get_chan_features_atxferabort(chan); + ast_channel_unlock(chan); + + if (!feature_code) { + astman_send_error(s, m, "No disconnect feature code found"); + ast_channel_unref(chan); + return 0; + } + + for (digit = feature_code; *digit; ++digit) { + struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit }; + ast_queue_frame(chan, &f); + } + ast_free(feature_code); + + chan = ast_channel_unref(chan); + + astman_send_ack(s, m, "CancelAtxfer successfully queued"); + + return 0; +} + + static int check_blacklist(const char *cmd) { char *cmd_copy, *cur_cmd; @@ -8707,6 +8767,7 @@ static void manager_shutdown(void) ast_manager_unregister("ListCategories"); ast_manager_unregister("Redirect"); ast_manager_unregister("Atxfer"); + ast_manager_unregister("CancelAtxfer"); ast_manager_unregister("Originate"); ast_manager_unregister("Command"); ast_manager_unregister("ExtensionState"); @@ -8922,6 +8983,7 @@ static int __init_manager(int reload, int by_external_config) ast_manager_register_xml_core("ListCategories", EVENT_FLAG_CONFIG, action_listcategories); ast_manager_register_xml_core("Redirect", EVENT_FLAG_CALL, action_redirect); ast_manager_register_xml_core("Atxfer", EVENT_FLAG_CALL, action_atxfer); + ast_manager_register_xml_core("CancelAtxfer", EVENT_FLAG_CALL, action_cancel_atxfer); ast_manager_register_xml_core("Originate", EVENT_FLAG_ORIGINATE, action_originate); ast_manager_register_xml_core("Command", EVENT_FLAG_COMMAND, action_command); ast_manager_register_xml_core("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate); -- cgit v1.2.3