func_channel: Read/Write after_bridge_goto option

Allows reading and setting of a channel's after_bridge_goto datastore

(closes issue ASTERISK-21875)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2628/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393005 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Jonathan Rose 12 years ago
parent 609c42c854
commit d014ad2261

@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/bridging.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
@ -118,6 +119,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<enum name="checkhangup">
<para>R/O Whether the channel is hanging up (1/0)</para>
</enum>
<enum name="after_bridge_goto">
<para>R/W the parseable goto string indicating where the channel is
expected to return to in the PBX after exiting the next bridge it joins
on the condition that it doesn't hang up. The parseable goto string uses
the same syntax as the <literal>Goto</literal> application.</para>
</enum>
<enum name="hangup_handler_pop">
<para>W/O Replace the most recently added hangup handler
with a new hangup handler on the channel if supplied. The
@ -475,6 +482,8 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
struct ast_str *tmp_str = ast_str_alloca(1024);
locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
} else if (!strcasecmp(data, "after_bridge_goto")) {
ast_after_bridge_goto_read(chan, buf, len);
} else if (!strcasecmp(data, "amaflags")) {
ast_channel_lock(chan);
snprintf(buf, len, "%d", ast_channel_amaflags(chan));
@ -516,7 +525,13 @@ static int func_channel_write_real(struct ast_channel *chan, const char *functio
locked_string_field_set(chan, accountcode, value);
else if (!strcasecmp(data, "userfield"))
locked_string_field_set(chan, userfield, value);
else if (!strcasecmp(data, "amaflags")) {
else if (!strcasecmp(data, "after_bridge_goto")) {
if (ast_strlen_zero(value)) {
ast_after_bridge_goto_discard(chan);
} else {
ast_after_bridge_set_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
}
} else if (!strcasecmp(data, "amaflags")) {
ast_channel_lock(chan);
if (isdigit(*value)) {
int amaflags;

@ -1634,6 +1634,16 @@ void ast_after_bridge_goto_run(struct ast_channel *chan);
*/
void ast_after_bridge_goto_discard(struct ast_channel *chan);
/*!
* \brief Read after bridge goto if it exists
* \since 12.0.0
*
* \param chan Channel to read the after bridge goto parseable goto string from
* \param buffer Buffer to write the after bridge goto data to
* \param buf_size size of the buffer being written to
*/
void ast_after_bridge_goto_read(struct ast_channel *chan, char *buffer, size_t buf_size);
/*! Reason the the after bridge callback will not be called. */
enum ast_after_bridge_cb_reason {
/*! The datastore is being destroyed. Likely due to hangup. */

@ -3414,6 +3414,47 @@ void ast_after_bridge_goto_discard(struct ast_channel *chan)
}
}
void ast_after_bridge_goto_read(struct ast_channel *chan, char *buffer, size_t buf_size)
{
struct ast_datastore *datastore;
struct after_bridge_goto_ds *after_bridge;
char *current_pos = buffer;
size_t remaining_size = buf_size;
SCOPED_CHANNELLOCK(lock, chan);
datastore = ast_channel_datastore_find(chan, &after_bridge_goto_info, NULL);
if (!datastore) {
buffer[0] = '\0';
return;
}
after_bridge = datastore->data;
if (after_bridge->parseable_goto) {
snprintf(buffer, buf_size, "%s", after_bridge->parseable_goto);
return;
}
if (!ast_strlen_zero(after_bridge->context)) {
snprintf(current_pos, remaining_size, "%s,", after_bridge->context);
remaining_size = remaining_size - strlen(current_pos);
current_pos += strlen(current_pos);
}
if (after_bridge->run_h_exten) {
snprintf(current_pos, remaining_size, "h,");
remaining_size = remaining_size - strlen(current_pos);
current_pos += strlen(current_pos);
} else if (!ast_strlen_zero(after_bridge->exten)) {
snprintf(current_pos, remaining_size, "%s,", after_bridge->exten);
remaining_size = remaining_size - strlen(current_pos);
current_pos += strlen(current_pos);
}
snprintf(current_pos, remaining_size, "%d", after_bridge->priority);
}
int ast_after_bridge_goto_setup(struct ast_channel *chan)
{
struct ast_datastore *datastore;
@ -3479,6 +3520,10 @@ int ast_after_bridge_goto_setup(struct ast_channel *chan)
after_bridge->exten, after_bridge->priority + 1);
}
if (!goto_failed) {
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
}
ast_debug(1, "Setup after bridge goto location to %s,%s,%d.\n",
ast_channel_context(chan),
ast_channel_exten(chan),

Loading…
Cancel
Save