summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPGRADE.txt9
-rw-r--r--apps/app_dial.c21
-rw-r--r--apps/app_followme.c6
-rw-r--r--apps/app_queue.c16
-rw-r--r--configs/ccss.conf.sample6
-rw-r--r--include/asterisk/app.h22
-rw-r--r--include/asterisk/ccss.h19
-rw-r--r--include/asterisk/channel.h75
-rw-r--r--main/app.c67
-rw-r--r--main/ccss.c34
-rw-r--r--main/channel.c97
-rw-r--r--main/dial.c6
-rw-r--r--main/features.c36
-rw-r--r--main/rtp_engine.c12
14 files changed, 366 insertions, 60 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt
index d4c059bae..6c76841f0 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -35,6 +35,11 @@ res_ais:
Dialplan Functions:
- MAILBOX_EXISTS has been deprecated. Use VM_INFO with the 'exists' parameter
instead.
+ - Macro has been deprecated in favor of GoSub. For redirecting and connected
+ line purposes use the following variables instead of their macro equivalents:
+ REDIRECTING_SEND_SUB, REDIRECTING_SEND_SUB_ARGS,
+ CONNECTED_LINE_SEND_SUB, CONNECTED_LINE_SEND_SUB_ARGS.
+
func_enum:
- ENUM query functions now return a count of -1 on lookup error to
@@ -62,6 +67,10 @@ AMI:
- DBDelTree now correctly returns an error when 0 rows are deleted just as
the DBDel action does.
+CCSS:
+ - Macro is deprecated. Use cc_callback_sub instead of cc_callback_macro
+ in channel configurations.
+
app_meetme:
- The 'c' option (announce user count) will now work even if the 'q' (quiet)
option is enabled.
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 03eae32ea..20747c0f6 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -956,7 +956,8 @@ static void do_forward(struct chanlist *o,
ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, &c->redirecting);
ast_channel_unlock(c);
- if (ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) {
+ if (ast_channel_redirecting_sub(c, in, &redirecting, 0) &&
+ ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) {
ast_channel_update_redirecting(in, &redirecting, NULL);
}
ast_party_redirecting_free(&redirecting);
@@ -1105,7 +1106,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "%s answered %s\n", ast_channel_name(c), ast_channel_name(in));
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
if (o->pending_connected_update) {
- if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
+ if (ast_channel_connected_line_sub(c, in, &o->connected, 0) &&
+ ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL);
}
} else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
@@ -1175,7 +1177,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "%s answered %s\n", ast_channel_name(c), ast_channel_name(in));
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
if (o->pending_connected_update) {
- if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
+ if (ast_channel_connected_line_sub(c, in, &o->connected, 0) &&
+ ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL);
}
} else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
@@ -1308,7 +1311,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_party_connected_line_free(&connected);
o->pending_connected_update = 1;
} else {
- if (ast_channel_connected_line_macro(c, in, f, 1, 1)) {
+ if (ast_channel_connected_line_sub(c, in, f, 1) &&
+ ast_channel_connected_line_macro(c, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
}
}
@@ -1329,7 +1333,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "Redirecting update to %s prevented.\n", ast_channel_name(in));
} else if (single) {
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(c), ast_channel_name(in));
- if (ast_channel_redirecting_macro(c, in, f, 1, 1)) {
+ if (ast_channel_redirecting_sub(c, in, f, 1) &&
+ ast_channel_redirecting_macro(c, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
}
pa->sentringing = 0;
@@ -1488,12 +1493,14 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
break;
case AST_CONTROL_CONNECTED_LINE:
- if (ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
+ if (ast_channel_connected_line_sub(in, o->chan, f, 1) &&
+ ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
}
break;
case AST_CONTROL_REDIRECTING:
- if (ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
+ if (ast_channel_redirecting_sub(in, o->chan, f, 1) &&
+ ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
}
break;
diff --git a/apps/app_followme.c b/apps/app_followme.c
index 1bf9547a9..dc824f573 100644
--- a/apps/app_followme.c
+++ b/apps/app_followme.c
@@ -1304,7 +1304,8 @@ static int app_exec(struct ast_channel *chan, const char *data)
/* Update connected line to caller if available. */
if (targs.pending_out_connected_update) {
- if (ast_channel_connected_line_macro(outbound, caller, &targs.connected_out, 1, 0)) {
+ if (ast_channel_connected_line_sub(outbound, caller, &targs.connected_out, 0) &&
+ ast_channel_connected_line_macro(outbound, caller, &targs.connected_out, 1, 0)) {
ast_channel_update_connected_line(caller, &targs.connected_out, NULL);
}
}
@@ -1329,7 +1330,8 @@ static int app_exec(struct ast_channel *chan, const char *data)
/* Update connected line to winner if changed. */
if (targs.pending_in_connected_update) {
- if (ast_channel_connected_line_macro(caller, outbound, &targs.connected_in, 0, 0)) {
+ if (ast_channel_connected_line_sub(caller, outbound, &targs.connected_in, 0) &&
+ ast_channel_connected_line_macro(caller, outbound, &targs.connected_in, 0, 0)) {
ast_channel_update_connected_line(outbound, &targs.connected_in, NULL);
}
}
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 0add6c209..834e09082 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3645,7 +3645,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
if (o->pending_connected_update) {
- if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
+ if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
+ ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL);
}
} else if (!o->dial_callerid_absent) {
@@ -3744,8 +3745,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, &o->chan->redirecting);
ast_channel_unlock(o->chan);
- res = ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0);
- if (res) {
+ if ((res = ast_channel_redirecting_sub(o->chan, in, &redirecting, 0)) &&
+ (res = ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0))) {
ast_channel_update_redirecting(in, &redirecting, NULL);
}
ast_party_redirecting_free(&redirecting);
@@ -3774,7 +3775,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
if (o->pending_connected_update) {
- if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
+ if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
+ ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL);
}
} else if (!o->dial_callerid_absent) {
@@ -3858,7 +3860,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_party_connected_line_free(&connected);
o->pending_connected_update = 1;
} else {
- if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
+ if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&
+ ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
}
}
@@ -3879,7 +3882,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "Redirecting update to %s prevented\n", inchan_name);
} else if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name);
- if (ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
+ if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&
+ ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
}
}
diff --git a/configs/ccss.conf.sample b/configs/ccss.conf.sample
index 2636f7ec9..21b0b0668 100644
--- a/configs/ccss.conf.sample
+++ b/configs/ccss.conf.sample
@@ -187,6 +187,12 @@
;
;cc_callback_macro=
;
+; Alternatively, the administrator may run a subroutine. By default
+; there is no callback subroutine configured. The subroutine should
+; be specified in the format: [[context,]exten,]priority
+;
+;cc_callback_sub=
+;
; When using an ISDN phone and a generic CC agent, Asterisk is unable
; to determine the dialstring that should be used when calling back
; the original caller. Furthermore, if you desire to use any dialstring-
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index 87f7c80ed..359c2b1a6 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -131,10 +131,30 @@ int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int
* \retval 0 success
* \retval -1 failure
*/
-int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel
+int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel
*macro_chan, const char * const macro_name, const char * const macro_args);
/*!
+ * \since 11
+ * \brief Run a subroutine on a channel, placing a second channel into autoservice.
+ *
+ * This is a shorthand method that makes it very easy to run a subroutine on any given
+ * channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case
+ * there is no channel to place into autoservice. It is very important that the
+ * autoservice_chan parameter is not locked prior to calling ast_app_run_sub. A
+ * deadlock could result, otherwise.
+ *
+ * \param autoservice_chan A channel to place into autoservice while the subroutine is run
+ * \param sub_chan The channel to run the subroutine on
+ * \param name The name of the subroutine to run
+ * \param args The arguments to pass to the subroutien
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel
+ *sub_chan, const char * const name, const char * const args);
+
+/*!
* \brief Set voicemail function callbacks
* \param[in] has_voicemail_func set function pointer
* \param[in] inboxcount2_func set function pointer
diff --git a/include/asterisk/ccss.h b/include/asterisk/ccss.h
index ae85e044f..acb3148c7 100644
--- a/include/asterisk/ccss.h
+++ b/include/asterisk/ccss.h
@@ -386,11 +386,28 @@ const char *ast_get_cc_callback_macro(struct ast_cc_config_params *config);
* \since 1.8
* \brief Set the callback_macro name
* \param config The configuration to set the callback_macro on
- * \param value The new callback macro we want to change to
+ * \param value The new callback macro we want to change to
* \retval void
*/
void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value);
+/*!
+ * \since 11
+ * \brief Get the name of the callback subroutine
+ * \param config The configuration to retrieve the callback_sub from
+ * \return The callback_sub name
+ */
+const char *ast_get_cc_callback_sub(struct ast_cc_config_params *config);
+
+/*!
+ * \since 11
+ * \brief Set the callback subroutine name
+ * \param config The configuration to set the callback_sub on
+ * \param value The new callback subroutine we want to change to
+ * \retval void
+ */
+void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char * const value);
+
/* END CONFIGURATION FUNCTIONS */
/* BEGIN AGENT/MONITOR REGISTRATION API */
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 7b4313b2b..20fcc4344 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -3418,30 +3418,56 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
* \since 1.8
* \brief Run a connected line interception macro and update a channel's connected line
* information
+ * \deprecated You should use the ast_channel_connected_line_sub() function instead.
*
* Whenever we want to update a channel's connected line information, we may need to run
* a macro so that an administrator can manipulate the information before sending it
* out. This function both runs the macro and sends the update to the channel.
*
* \param autoservice_chan Channel to place into autoservice while the macro is running.
- * It is perfectly safe for this to be NULL
+ * It is perfectly safe for this to be NULL
* \param macro_chan The channel to run the macro on. Also the channel from which we
- * determine which macro we need to run.
+ * determine which macro we need to run.
* \param connected_info Either an ast_party_connected_line or ast_frame pointer of type
- * AST_CONTROL_CONNECTED_LINE
- * \param caller If true, then run CONNECTED_LINE_CALLER_SEND_MACRO, otherwise run
- * CONNECTED_LINE_CALLEE_SEND_MACRO
+ * AST_CONTROL_CONNECTED_LINE
+ * \param is_caller If true, then run CONNECTED_LINE_CALLER_SEND_MACRO with arguments from
+ * CONNECTED_LINE_CALLER_SEND_MACRO_ARGS, otherwise run CONNECTED_LINE_CALLEE_SEND_MACRO
+ * with arguments from CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS
* \param frame If true, then connected_info is an ast_frame pointer, otherwise it is an
- * ast_party_connected_line pointer.
+ * ast_party_connected_line pointer.
* \retval 0 Success
* \retval -1 Either the macro does not exist, or there was an error while attempting to
- * run the macro
+ * run the macro
*
* \todo Have multiple return codes based on the MACRO_RESULT
* \todo Make constants so that caller and frame can be more expressive than just '1' and
- * '0'
+ * '0'
+ */
+int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int frame);
+
+/*!
+ * \since 11
+ * \brief Run a connected line interception subroutine and update a channel's connected line
+ * information
+ *
+ * Whenever we want to update a channel's connected line information, we may need to run
+ * a subroutine so that an administrator can manipulate the information before sending it
+ * out. This function both runs the subroutine specified by CONNECTED_LINE_SEND_SUB and
+ * sends the update to the channel.
+ *
+ * \param autoservice_chan Channel to place into autoservice while the sub is running.
+ * It is perfectly safe for this to be NULL
+ * \param sub_chan The channel to run the subroutine on. Also the channel from which we
+ * determine which subroutine we need to run.
+ * \param connected_info Either an ast_party_connected_line or ast_frame pointer of type
+ * AST_CONTROL_CONNECTED_LINE
+ * \param frame If true, then connected_info is an ast_frame pointer, otherwise it is an
+ * ast_party_connected_line pointer.
+ * \retval 0 Success
+ * \retval -1 Either the subroutine does not exist, or there was an error while attempting to
+ * run the subroutine
*/
-int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame);
+int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame);
/*!
* \brief Insert into an astdata tree, the channel structure.
@@ -3467,6 +3493,7 @@ int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct as
/*!
* \since 1.8
* \brief Run a redirecting interception macro and update a channel's redirecting information
+ * \deprecated You should use the ast_channel_redirecting_sub() function instead.
*
* \details
* Whenever we want to update a channel's redirecting information, we may need to run
@@ -3479,8 +3506,9 @@ int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct as
* determine which macro we need to run.
* \param redirecting_info Either an ast_party_redirecting or ast_frame pointer of type
* AST_CONTROL_REDIRECTING
- * \param is_caller If true, then run REDIRECTING_CALLER_SEND_MACRO, otherwise run
- * REDIRECTING_CALLEE_SEND_MACRO
+ * \param is_caller If true, then run REDIRECTING_CALLER_SEND_MACRO with arguments from
+ * REDIRECTING_CALLER_SEND_MACRO_ARGS, otherwise run REDIRECTING_CALLEE_SEND_MACRO with
+ * arguments from REDIRECTING_CALLEE_SEND_MACRO_ARGS
* \param is_frame If true, then redirecting_info is an ast_frame pointer, otherwise it is an
* ast_party_redirecting pointer.
*
@@ -3494,6 +3522,31 @@ int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct as
*/
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame);
+/*!
+ * \since 11
+ * \brief Run a redirecting interception subroutine and update a channel's redirecting information
+ *
+ * \details
+ * Whenever we want to update a channel's redirecting information, we may need to run
+ * a subroutine so that an administrator can manipulate the information before sending it
+ * out. This function both runs the subroutine specified by REDIRECTING_SEND_SUB and
+ * sends the update to the channel.
+ *
+ * \param autoservice_chan Channel to place into autoservice while the subroutine is running.
+ * It is perfectly safe for this to be NULL
+ * \param sub_chan The channel to run the subroutine on. Also the channel from which we
+ * determine which subroutine we need to run.
+ * \param redirecting_info Either an ast_party_redirecting or ast_frame pointer of type
+ * AST_CONTROL_REDIRECTING
+ * \param is_frame If true, then redirecting_info is an ast_frame pointer, otherwise it is an
+ * ast_party_redirecting pointer.
+ *
+ * \retval 0 Success
+ * \retval -1 Either the subroutine does not exist, or there was an error while attempting to
+ * run the subroutine
+ */
+int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame);
+
#include "asterisk/ccss.h"
/*!
diff --git a/main/app.c b/main/app.c
index d9f56a4aa..f937b0e30 100644
--- a/main/app.c
+++ b/main/app.c
@@ -247,28 +247,79 @@ int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int
return res;
}
-int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char * const macro_name, const char * const macro_args)
+static int app_exec_dialplan(struct ast_channel *autoservice_chan, struct ast_channel *exec_chan, const char * const args, int use_gosub)
{
- struct ast_app *macro_app;
+
+ struct ast_app *app;
int res;
- char buf[1024];
+ char * app_type = use_gosub ? "GoSub" : "Macro";
- macro_app = pbx_findapp("Macro");
- if (!macro_app) {
- ast_log(LOG_WARNING, "Cannot run macro '%s' because the 'Macro' application in not available\n", macro_name);
+ app = pbx_findapp(app_type);
+ if (!app) {
+ ast_log(LOG_WARNING, "Cannot run '%s' because the '%s' application is not available\n", args, app_type);
return -1;
}
- snprintf(buf, sizeof(buf), "%s%s%s", macro_name, ast_strlen_zero(macro_args) ? "" : ",", S_OR(macro_args, ""));
if (autoservice_chan) {
ast_autoservice_start(autoservice_chan);
}
- res = pbx_exec(macro_chan, macro_app, buf);
+ res = pbx_exec(exec_chan, app, args);
+ if (use_gosub && !res) {
+ struct ast_pbx_args gosub_args = {{0}};
+ struct ast_pbx *pbx = ast_channel_pbx(exec_chan);
+ /* supress warning about a pbx already being on the channel */
+ ast_channel_pbx_set(exec_chan, NULL);
+ gosub_args.no_hangup_chan = 1;
+ ast_pbx_run_args(exec_chan, &gosub_args);
+ if (ast_channel_pbx(exec_chan)) {
+ ast_free(ast_channel_pbx(exec_chan));
+ }
+ ast_channel_pbx_set(exec_chan, pbx);
+ }
if (autoservice_chan) {
ast_autoservice_stop(autoservice_chan);
}
return res;
}
+int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char * const name, const char * const args)
+{
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s%s%s", name, ast_strlen_zero(args) ? "" : ",", S_OR(args, ""));
+ return app_exec_dialplan(autoservice_chan, macro_chan, buf, 0);
+}
+
+int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char * const location, const char * const args)
+{
+ char buf[1024];
+ size_t offset = snprintf(buf, sizeof(buf), "%s", location);
+ /* need to bump the priority by one if we already have a pbx */
+ if (ast_channel_pbx(sub_chan)) {
+ int iprio;
+ const char * priority = location;
+ const char * next = strchr(priority,',');
+ /* jump to the priority portion of the location */
+ if (next) {
+ priority = next + 1;
+ }
+ next = strchr(priority,',');
+ if (next) {
+ priority = next + 1;
+ }
+ /* if the priority isn't numeric, it's as if we never took this branch... */
+ if (sscanf(priority, "%d", &iprio)) {
+ offset = priority - location;
+ iprio++;
+ if (offset < sizeof(buf)) {
+ offset += snprintf(buf + offset, sizeof(buf) - offset, "%d", iprio);
+ }
+ }
+ }
+ if (offset < sizeof(buf)) {
+ snprintf(buf + offset, sizeof(buf) - offset, "%s%s%s", ast_strlen_zero(args) ? "" : "(", S_OR(args, ""), ast_strlen_zero(args) ? "" : ")");
+ }
+ return app_exec_dialplan(autoservice_chan, sub_chan, buf, 1);
+}
+
static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
static int (*ast_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL;
diff --git a/main/ccss.c b/main/ccss.c
index f1965986d..ad3e82ec0 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -156,6 +156,7 @@ struct ast_cc_config_params {
unsigned int cc_max_agents;
unsigned int cc_max_monitors;
char cc_callback_macro[AST_MAX_EXTENSION];
+ char cc_callback_sub[AST_MAX_EXTENSION];
char cc_agent_dialstring[AST_MAX_EXTENSION];
};
@@ -654,6 +655,7 @@ static const struct ast_cc_config_params cc_default_params = {
.cc_max_agents = CC_MAX_AGENTS_DEFAULT,
.cc_max_monitors = CC_MAX_MONITORS_DEFAULT,
.cc_callback_macro = "",
+ .cc_callback_sub = "",
.cc_agent_dialstring = "",
};
@@ -751,6 +753,8 @@ int ast_cc_get_param(struct ast_cc_config_params *params, const char * const nam
if (!strcasecmp(name, "cc_callback_macro")) {
value = ast_get_cc_callback_macro(params);
+ } else if (!strcasecmp(name, "cc_callback_sub")) {
+ value = ast_get_cc_callback_sub(params);
} else if (!strcasecmp(name, "cc_agent_policy")) {
value = agent_policy_to_str(ast_get_cc_agent_policy(params));
} else if (!strcasecmp(name, "cc_monitor_policy")) {
@@ -800,6 +804,9 @@ int ast_cc_set_param(struct ast_cc_config_params *params, const char * const nam
} else if (!strcasecmp(name, "cc_callback_macro")) {
ast_set_cc_callback_macro(params, value);
return 0;
+ } else if (!strcasecmp(name, "cc_callback_sub")) {
+ ast_set_cc_callback_sub(params, value);
+ return 0;
}
if (!sscanf(value, "%30u", &value_as_uint) == 1) {
@@ -836,6 +843,7 @@ int ast_cc_is_config_param(const char * const name)
!strcasecmp(name, "cc_max_agents") ||
!strcasecmp(name, "cc_max_monitors") ||
!strcasecmp(name, "cc_callback_macro") ||
+ !strcasecmp(name, "cc_callback_sub") ||
!strcasecmp(name, "cc_agent_dialstring") ||
!strcasecmp(name, "cc_recall_timer"));
}
@@ -978,8 +986,14 @@ const char *ast_get_cc_callback_macro(struct ast_cc_config_params *config)
return config->cc_callback_macro;
}
+const char *ast_get_cc_callback_sub(struct ast_cc_config_params *config)
+{
+ return config->cc_callback_sub;
+}
+
void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value)
{
+ ast_log(LOG_WARNING, "Usage of cc_callback_macro is deprecated. Please use cc_callback_sub instead.\n");
if (ast_strlen_zero(value)) {
config->cc_callback_macro[0] = '\0';
} else {
@@ -987,6 +1001,15 @@ void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char *
}
}
+void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char * const value)
+{
+ if (ast_strlen_zero(value)) {
+ config->cc_callback_sub[0] = '\0';
+ } else {
+ ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
+ }
+}
+
struct cc_monitor_backend {
AST_LIST_ENTRY(cc_monitor_backend) next;
const struct ast_cc_monitor_callbacks *callbacks;
@@ -2651,6 +2674,7 @@ static void *generic_recall(void *data)
int reason;
struct ast_channel *chan;
const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
+ const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
struct ast_format tmp_fmt;
struct ast_format_cap *tmp_cap = ast_format_cap_alloc_nolock();
@@ -2700,6 +2724,16 @@ static void *generic_recall(void *data)
return NULL;
}
}
+
+ if (!ast_strlen_zero(callback_sub)) {
+ ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback subroutine configured for agent %s\n",
+ agent->core_id, agent->device_name);
+ if (ast_app_run_sub(NULL, chan, callback_sub, NULL)) {
+ ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
+ ast_hangup(chan);
+ return NULL;
+ }
+ }
ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name);
ast_pbx_start(chan);
return NULL;
diff --git a/main/channel.c b/main/channel.c
index 95fb9259a..f4717cc3d 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3819,7 +3819,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_party_connected_line_free(&connected);
break;
}
- if (ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) {
+ if (ast_channel_connected_line_sub(NULL, chan, &connected, 0) &&
+ ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) {
ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE,
read_action_payload->payload,
read_action_payload->payload_size);
@@ -5237,7 +5238,8 @@ static void call_forward_inherit(struct ast_channel *new_chan, struct ast_channe
ast_channel_lock(orig);
ast_party_redirecting_copy(&redirecting, &orig->redirecting);
ast_channel_unlock(orig);
- if (ast_channel_redirecting_macro(orig, parent, &redirecting, 1, 0)) {
+ if (ast_channel_redirecting_sub(orig, parent, &redirecting, 0) &&
+ ast_channel_redirecting_macro(orig, parent, &redirecting, 1, 0)) {
ast_channel_update_redirecting(parent, &redirecting, NULL);
}
ast_party_redirecting_free(&redirecting);
@@ -7128,12 +7130,14 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
break;
case AST_CONTROL_REDIRECTING:
- if (ast_channel_redirecting_macro(who, other, f, other == c0, 1)) {
+ if (ast_channel_redirecting_sub(who, other, f, 1) &&
+ ast_channel_redirecting_macro(who, other, f, other == c0, 1)) {
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
}
break;
case AST_CONTROL_CONNECTED_LINE:
- if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
+ if (ast_channel_connected_line_sub(who, other, f, 1) &&
+ ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
}
break;
@@ -9362,6 +9366,7 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame)
{
+ static int deprecation_warning = 0;
const char *macro;
const char *macro_args;
int retval;
@@ -9379,6 +9384,10 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc
return -1;
}
+ if (!deprecation_warning) {
+ deprecation_warning = 1;
+ ast_log(LOG_WARNING, "Usage of CONNECTED_LINE_CALLE[ER]_SEND_MACRO is deprecated. Please use CONNECTED_LINE_SEND_SUB instead.\n");
+ }
if (is_frame) {
const struct ast_frame *frame = connected_info;
@@ -9401,6 +9410,7 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
{
+ static int deprecation_warning = 0;
const char *macro;
const char *macro_args;
int retval;
@@ -9418,6 +9428,10 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a
return -1;
}
+ if (!deprecation_warning) {
+ deprecation_warning = 1;
+ ast_log(LOG_WARNING, "Usage of REDIRECTING_CALLE[ER]_SEND_MACRO is deprecated. Please use REDIRECTING_SEND_SUB instead.\n");
+ }
if (is_frame) {
const struct ast_frame *frame = redirecting_info;
@@ -9439,6 +9453,81 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a
return retval;
}
+int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int is_frame)
+{
+ const char *sub;
+ const char *sub_args;
+ int retval;
+
+ ast_channel_lock(sub_chan);
+ sub = pbx_builtin_getvar_helper(sub_chan, "CONNECTED_LINE_SEND_SUB");
+ sub = ast_strdupa(S_OR(sub, ""));
+ sub_args = pbx_builtin_getvar_helper(sub_chan, "CONNECTED_LINE_SEND_SUB_ARGS");
+ sub_args = ast_strdupa(S_OR(sub_args, ""));
+
+ if (ast_strlen_zero(sub)) {
+ ast_channel_unlock(sub_chan);
+ return -1;
+ }
+
+ if (is_frame) {
+ const struct ast_frame *frame = connected_info;
+
+ ast_connected_line_parse_data(frame->data.ptr, frame->datalen, &sub_chan->connected);
+ } else {
+ const struct ast_party_connected_line *connected = connected_info;
+
+ ast_party_connected_line_copy(&sub_chan->connected, connected);
+ }
+ ast_channel_unlock(sub_chan);
+
+ if (!(retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args))) {
+ ast_channel_lock(sub_chan);
+ ast_channel_update_connected_line(sub_chan, &sub_chan->connected, NULL);
+ ast_channel_unlock(sub_chan);
+ }
+
+ return retval;
+}
+
+int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame)
+{
+ const char *sub;
+ const char *sub_args;
+ int retval;
+
+ ast_channel_lock(sub_chan);
+ sub = pbx_builtin_getvar_helper(sub_chan, "REDIRECTING_SEND_SUB");
+ sub = ast_strdupa(S_OR(sub, ""));
+ sub_args = pbx_builtin_getvar_helper(sub_chan, "REDIRECTING_SEND_SUB_ARGS");
+ sub_args = ast_strdupa(S_OR(sub_args, ""));
+
+ if (ast_strlen_zero(sub)) {
+ ast_channel_unlock(sub_chan);
+ return -1;
+ }
+
+ if (is_frame) {
+ const struct ast_frame *frame = redirecting_info;
+
+ ast_redirecting_parse_data(frame->data.ptr, frame->datalen, &sub_chan->redirecting);
+ } else {
+ const struct ast_party_redirecting *redirecting = redirecting_info;
+
+ ast_party_redirecting_copy(&sub_chan->redirecting, redirecting);
+ }
+ ast_channel_unlock(sub_chan);
+
+ retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args);
+ if (!retval) {
+ ast_channel_lock(sub_chan);
+ ast_channel_update_redirecting(sub_chan, &sub_chan->redirecting, NULL);
+ ast_channel_unlock(sub_chan);
+ }
+
+ return retval;
+}
+
static void *channel_cc_params_copy(void *data)
{
const struct ast_cc_config_params *src = data;
diff --git a/main/dial.c b/main/dial.c
index 3455ca329..fe8a74faf 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -437,13 +437,15 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
break;
case AST_CONTROL_CONNECTED_LINE:
ast_verb(3, "%s connected line has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
- if (ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
+ if (ast_channel_connected_line_sub(channel->owner, chan, fr, 1) &&
+ ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
}
break;
case AST_CONTROL_REDIRECTING:
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
- if (ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
+ if (ast_channel_redirecting_sub(channel->owner, chan, fr, 1) &&
+ ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
}
break;
diff --git a/main/features.c b/main/features.c
index 9f257f7a0..6f3d0f9cb 100644
--- a/main/features.c
+++ b/main/features.c
@@ -2408,7 +2408,8 @@ static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_chann
* Party B was the caller to party C and is the last known mode
* for party B.
*/
- if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
+ if (ast_channel_connected_line_sub(transferee, transferer, connected_line, 0) &&
+ ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
ast_channel_update_connected_line(transferer, connected_line, NULL);
}
ast_party_connected_line_free(connected_line);
@@ -2816,7 +2817,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_party_connected_line_copy(&connected_line, &transferer->connected);
ast_channel_unlock(transferer);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
+ if (ast_channel_connected_line_sub(newchan, xferchan, &connected_line, 0) &&
+ ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
ast_channel_update_connected_line(xferchan, &connected_line, NULL);
}
@@ -2825,7 +2827,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
ast_channel_unlock(xferchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
+ if (ast_channel_connected_line_sub(xferchan, newchan, &connected_line, 0) &&
+ ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
ast_channel_update_connected_line(newchan, &connected_line, NULL);
}
@@ -3614,7 +3617,8 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
ast_party_connected_line_free(&connected);
} else {
ast_autoservice_start(transferee);
- if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
+ if (ast_channel_connected_line_sub(chan, caller, f, 1) &&
+ ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
f->data.ptr, f->datalen);
}
@@ -3623,7 +3627,8 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
} else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
if (!caller_hungup) {
ast_autoservice_start(transferee);
- if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
+ if (ast_channel_redirecting_sub(chan, caller, f, 1) &&
+ ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
f->data.ptr, f->datalen);
}
@@ -4151,16 +4156,16 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a
ast_indicate(other, f->subclass.integer);
break;
case AST_CONTROL_CONNECTED_LINE:
- if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
- break;
+ if (ast_channel_connected_line_sub(who, other, f, 1) &&
+ ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
+ ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
}
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
break;
case AST_CONTROL_REDIRECTING:
- if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
- break;
+ if (ast_channel_redirecting_sub(who, other, f, 1) &&
+ ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
+ ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
}
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
break;
case AST_CONTROL_AOC:
case AST_CONTROL_HOLD:
@@ -5172,7 +5177,8 @@ static int parked_call_exec(struct ast_channel *chan, const char *data)
ast_connected_line_copy_from_caller(&connected, &chan->caller);
ast_channel_unlock(chan);
connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- if (ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) {
+ if (ast_channel_connected_line_sub(chan, peer, &connected, 0) &&
+ ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) {
ast_channel_update_connected_line(peer, &connected, NULL);
}
@@ -5187,7 +5193,8 @@ static int parked_call_exec(struct ast_channel *chan, const char *data)
ast_connected_line_copy_from_caller(&connected, &peer->caller);
ast_channel_unlock(peer);
connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- if (ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) {
+ if (ast_channel_connected_line_sub(peer, chan, &connected, 0) &&
+ ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) {
ast_channel_update_connected_line(chan, &connected, NULL);
}
@@ -7319,7 +7326,8 @@ int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
ast_party_connected_line_copy(&connected_caller, &target->connected);
ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
+ if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0) &&
+ ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
ast_channel_update_connected_line(chan, &connected_caller, NULL);
}
ast_party_connected_line_free(&connected_caller);
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index d60790c41..e739c7014 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -917,12 +917,14 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
}
ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
- if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
+ if (ast_channel_connected_line_sub(who, other, fr, 1) &&
+ ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
}
ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
- if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
+ if (ast_channel_redirecting_sub(who, other, fr, 1) &&
+ ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
}
ast_frfree(fr);
@@ -1206,12 +1208,14 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
}
ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
- if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
+ if (ast_channel_connected_line_sub(who, other, fr, 1) &&
+ ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
}
ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
- if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
+ if (ast_channel_redirecting_sub(who, other, fr, 1) &&
+ ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
}
ast_frfree(fr);