diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | include/asterisk/features_config.h | 15 | ||||
-rw-r--r-- | main/features_config.c | 15 | ||||
-rw-r--r-- | main/manager.c | 62 |
4 files changed, 96 insertions, 0 deletions
@@ -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 @@ -117,6 +117,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 */ struct ast_features_pickup_config { 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() <ref type="managerEvent">AttendedTransfer</ref> </see-also> </manager> + <manager name="CancelAtxfer" language="en_US"> + <synopsis> + Cancel an attended transfer. + </synopsis> + <syntax> + <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> + <parameter name="Channel" required="true"> + <para>The transferer channel.</para> + </parameter> + </syntax> + <description> + <para>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. + </para> + </description> + <see-also> + <ref type="managerEvent">AttendedTransfer</ref> + </see-also> + </manager> <manager name="Originate" language="en_US"> <synopsis> 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); |