aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/app.c22
-rw-r--r--main/channel.c48
-rw-r--r--main/dial.c5
-rw-r--r--main/features.c59
4 files changed, 124 insertions, 10 deletions
diff --git a/main/app.c b/main/app.c
index 72af3e085..eacefabd0 100644
--- a/main/app.c
+++ b/main/app.c
@@ -203,6 +203,28 @@ 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)
+{
+ struct ast_app *macro_app;
+ int res;
+ char buf[1024];
+
+ 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);
+ 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);
+ if (autoservice_chan) {
+ ast_autoservice_stop(autoservice_chan);
+ }
+ return res;
+}
+
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/channel.c b/main/channel.c
index bd997def6..d9ce2efbf 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5008,13 +5008,19 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
int bridge_exit = 0;
switch (f->subclass) {
+ case AST_CONTROL_REDIRECTING:
+ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
+ break;
+ case AST_CONTROL_CONNECTED_LINE:
+ if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
+ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
+ }
+ break;
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_T38:
case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_CONNECTED_LINE:
- case AST_CONTROL_REDIRECTING:
ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
if (jb_in_use) {
ast_jb_empty_and_reset(c0, c1);
@@ -6503,6 +6509,44 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
}
+int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
+{
+ const char *macro;
+ const char *macro_args;
+ union {
+ const struct ast_frame *frame;
+ const struct ast_party_connected_line *connected;
+ } pointer;
+ int retval;
+
+ if (frame) {
+ pointer.frame = connected_info;
+ } else {
+ pointer.connected = connected_info;
+ }
+
+ ast_channel_lock(macro_chan);
+ macro = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"), ""));
+ macro_args = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARGS" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"), ""));
+ ast_channel_unlock(macro_chan);
+
+ if (ast_strlen_zero(macro)) {
+ return -1;
+ }
+
+ if (frame) {
+ ast_connected_line_parse_data(pointer.frame->data.ptr, pointer.frame->datalen, &macro_chan->connected);
+ } else {
+ ast_party_connected_line_copy(&macro_chan->connected, pointer.connected);
+ }
+
+ if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) {
+ ast_channel_update_connected_line(macro_chan, &macro_chan->connected);
+ }
+
+ return retval;
+}
+
/* DO NOT PUT ADDITIONAL FUNCTIONS BELOW THIS BOUNDARY
*
* ONLY FUNCTIONS FOR PROVIDING BACKWARDS ABI COMPATIBILITY BELONG HERE
diff --git a/main/dial.c b/main/dial.c
index d38b4829d..1f65f50c7 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dial.h"
#include "asterisk/pbx.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/app.h"
/*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
struct ast_dial {
@@ -430,7 +431,9 @@ 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", channel->owner->name, chan->name);
- ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
+ if (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", channel->owner->name, chan->name);
diff --git a/main/features.c b/main/features.c
index 6e3570e63..6c15f258d 100644
--- a/main/features.c
+++ b/main/features.c
@@ -1377,6 +1377,9 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
/* Set the channel's new extension, since it exists, using transferer context */
ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
+ if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
+ ast_channel_update_connected_line(transferee, &transferer->connected);
+ }
set_c_e_p(transferee, transferer_real_context, xferto, 0);
}
check_goto_on_transfer(transferer);
@@ -1635,13 +1638,43 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
/* Due to a limitation regarding when callerID is set on a Local channel,
* we use the transferer's connected line information here.
*/
+
+ /* xferchan is transferee, and newchan is the transfer target
+ * So...in a transfer, who is the caller and who is the callee?
+ *
+ * When the call is originally made, it is clear who is caller and callee.
+ * When a transfer occurs, it is my humble opinion that the transferee becomes
+ * the caller, and the transfer target is the callee.
+ *
+ * The problem is that these macros were set with the intention of the original
+ * caller and callee taking those roles. A transfer can totally mess things up,
+ * to be technical. What sucks even more is that you can't effectively change
+ * the macros in the dialplan during the call from the transferer to the transfer
+ * target because the transferee is stuck with whatever role he originally had.
+ *
+ * I think the answer here is just to make sure that it is well documented that
+ * during a transfer, the transferee is the "caller" and the transfer target
+ * is the "callee."
+ *
+ * This means that if party A calls party B, and party A transfers party B to
+ * party C, then B has switched roles for the call. Now party B will have the
+ * caller macro called on his channel instead of the callee macro.
+ *
+ * Luckily, the method by which the bridge is launched here ensures that the
+ * transferee is the "chan" on the bridge and the transfer target is the "peer,"
+ * so my idea for the roles post-transfer does not require extensive code changes.
+ */
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(xferchan, &connected_line);
+ if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
+ ast_channel_update_connected_line(xferchan, &connected_line);
+ }
ast_channel_lock(xferchan);
ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
ast_channel_unlock(xferchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(newchan, &connected_line);
+ if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
+ ast_channel_update_connected_line(newchan, &connected_line);
+ }
ast_party_connected_line_free(&connected_line);
if (ast_stream_and_wait(newchan, xfersound, ""))
@@ -1749,12 +1782,16 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_connected_line_copy_from_caller(&connected_line, &newchan->cid);
ast_channel_unlock(newchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(xferchan, &connected_line);
+ if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
+ ast_channel_update_connected_line(xferchan, &connected_line);
+ }
ast_channel_lock(xferchan);
ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
ast_channel_unlock(xferchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(newchan, &connected_line);
+ if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
+ ast_channel_update_connected_line(newchan, &connected_line);
+ }
ast_party_connected_line_free(&connected_line);
@@ -2370,7 +2407,9 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
ready=1;
break;
} else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {
- ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
+ ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ }
} else if (f->subclass != -1) {
ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
}
@@ -2766,9 +2805,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
case -1:
ast_indicate(other, f->subclass);
break;
+ case AST_CONTROL_CONNECTED_LINE:
+ if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
+ break;
+ }
+ /* The implied "else" falls through purposely */
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
- case AST_CONTROL_CONNECTED_LINE:
ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
break;
case AST_CONTROL_OPTION:
@@ -4546,7 +4589,9 @@ int ast_pickup_call(struct ast_channel *chan)
connected_caller = cur->connected;
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- ast_channel_update_connected_line(chan, &connected_caller);
+ if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
+ ast_channel_update_connected_line(chan, &connected_caller);
+ }
ast_party_connected_line_collect_caller(&connected_caller, &chan->cid);
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;