mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
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
This commit is contained in:
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
|
|
||||||
#include "asterisk/module.h"
|
#include "asterisk/module.h"
|
||||||
#include "asterisk/channel.h"
|
#include "asterisk/channel.h"
|
||||||
|
#include "asterisk/bridging.h"
|
||||||
#include "asterisk/pbx.h"
|
#include "asterisk/pbx.h"
|
||||||
#include "asterisk/utils.h"
|
#include "asterisk/utils.h"
|
||||||
#include "asterisk/app.h"
|
#include "asterisk/app.h"
|
||||||
@@ -118,6 +119,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
<enum name="checkhangup">
|
<enum name="checkhangup">
|
||||||
<para>R/O Whether the channel is hanging up (1/0)</para>
|
<para>R/O Whether the channel is hanging up (1/0)</para>
|
||||||
</enum>
|
</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">
|
<enum name="hangup_handler_pop">
|
||||||
<para>W/O Replace the most recently added hangup handler
|
<para>W/O Replace the most recently added hangup handler
|
||||||
with a new hangup handler on the channel if supplied. The
|
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);
|
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);
|
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")) {
|
} else if (!strcasecmp(data, "amaflags")) {
|
||||||
ast_channel_lock(chan);
|
ast_channel_lock(chan);
|
||||||
snprintf(buf, len, "%d", ast_channel_amaflags(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);
|
locked_string_field_set(chan, accountcode, value);
|
||||||
else if (!strcasecmp(data, "userfield"))
|
else if (!strcasecmp(data, "userfield"))
|
||||||
locked_string_field_set(chan, userfield, value);
|
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);
|
ast_channel_lock(chan);
|
||||||
if (isdigit(*value)) {
|
if (isdigit(*value)) {
|
||||||
int amaflags;
|
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);
|
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. */
|
/*! Reason the the after bridge callback will not be called. */
|
||||||
enum ast_after_bridge_cb_reason {
|
enum ast_after_bridge_cb_reason {
|
||||||
/*! The datastore is being destroyed. Likely due to hangup. */
|
/*! 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)
|
int ast_after_bridge_goto_setup(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
struct ast_datastore *datastore;
|
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);
|
after_bridge->exten, after_bridge->priority + 1);
|
||||||
}
|
}
|
||||||
if (!goto_failed) {
|
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_debug(1, "Setup after bridge goto location to %s,%s,%d.\n",
|
||||||
ast_channel_context(chan),
|
ast_channel_context(chan),
|
||||||
ast_channel_exten(chan),
|
ast_channel_exten(chan),
|
||||||
|
Reference in New Issue
Block a user