diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/app.c | 22 | ||||
-rw-r--r-- | main/channel.c | 48 | ||||
-rw-r--r-- | main/dial.c | 5 | ||||
-rw-r--r-- | main/features.c | 59 |
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, ¯o_chan->connected); + } else { + ast_party_connected_line_copy(¯o_chan->connected, pointer.connected); + } + + if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) { + ast_channel_update_connected_line(macro_chan, ¯o_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; |