diff options
author | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-05-17 15:36:31 +0000 |
---|---|---|
committer | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-05-17 15:36:31 +0000 |
commit | 82c8ef7415d9fa1cab877da20d671ba9093c8895 (patch) | |
tree | e0f98e5d12f079b7d8f94c031808eaea340b8065 /apps/app_dial.c | |
parent | 17d3dd99a4716c14fe7a9ee5835049cdf2c6855a (diff) |
Enhancements to connected line and redirecting work.
From reviewboard:
Digium has a commercial customer who has made extensive use of the connected party and
redirecting information present in later versions of Asterisk Business Edition and which
is to be in the upcoming 1.8 release. Through their use of the feature, new problems and solutions
have come about. This patch adds several enhancements to maximize usage of the connected party
and redirecting information functionality.
First, Asterisk trunk already had connected line interception macros. These macros allow you to
manipulate connected line information before it was sent out to its target. This patch adds the
same feature except for redirecting information instead.
Second, the ast_callerid and ast_party_id structures have been enhanced to provide a "tag." This
tag can be set with func_callerid, func_connectedline, func_redirecting, and in the case of DAHDI,
mISDN, and SIP channels, can be set in a configuration file. The idea behind the callerid tag is
that it can be set to whatever value the administrator likes. Later, when running connected line
and redirecting macros, the admin can read the tag off the appropriate structure to determine what
action to take. You can think of this sort of like a channel variable, except that instead of having
the variable associated with a channel, the variable is associated with a specific identity within
Asterisk.
Third, app_dial has two new options, s and u. The s option lets a dialplan writer force a specific
caller ID tag to be placed on the outgoing channel. The u option allows the dialplan writer to force
a specific calling presentation value on the outgoing channel.
Fourth, there is a new control frame subclass called AST_CONTROL_READ_ACTION added. This was added
to correct a very specific situation. In the case of SIP semi-attended (blond) transfers, the party
being transferred would not have the opportunity to run a connected line interception macro to
possibly alter the transfer target's connected line information. The issue here was that during a
blond transfer, the SIP transfer code has no bridged channel on which to queue the connected line
update. The way this was corrected was to add this new control frame subclass. Now, we queue an
AST_CONTROL_READ_ACTION frame on the channel on which the connected line interception macro should
be run. When ast_read is called to read the frame, ast_read responds by calling a callback function
associated with the specific read action the control frame describes. In this case, the action taken
is to run the connected line interception macro on the transferee's channel.
Review: https://reviewboard.asterisk.org/r/652/
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@263541 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_dial.c')
-rw-r--r-- | apps/app_dial.c | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index b1de21d5f..1a9ca8900 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -335,6 +335,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <para>Hang up the call <replaceable>x</replaceable> seconds <emphasis>after</emphasis> the called party has answered the call.</para> </option> + <option name="s"> + <argument name="x" required="true" /> + <para>Force the outgoing callerid tag parameter to be set to the string <replaceable>x</replaceable></para> + </option> <option name="t"> <para>Allow the called party to transfer the calling party by sending the DTMF sequence defined in <filename>features.conf</filename>. This setting does not perform policy enforcement on @@ -384,6 +388,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") so you will not be able to set timeouts via the TIMEOUT() function in this routine.</para> </note> </option> + <option name="u"> + <argument name = "x" required="true"> + <para>Force the outgoing callerid presentation indicator parameter to be set + to one of the values passed in <replaceable>x</replaceable>: + <literal>allowed_not_screened</literal> + <literal>allowed_passed_screen</literal> + <literal>allowed_failed_screen</literal> + <literal>allowed</literal> + <literal>prohib_not_screened</literal> + <literal>prohib_passed_screen</literal> + <literal>prohib_failed_screen</literal> + <literal>prohib</literal> + <literal>unavailable</literal></para> + </argument> + </option> <option name="w"> <para>Allow the called party to enable recording of the call by sending the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para> @@ -537,6 +556,8 @@ enum { #define OPT_PEER_H ((uint64_t)1 << 35) #define OPT_CALLEE_GO_ON ((uint64_t)1 << 36) #define OPT_CANCEL_TIMEOUT ((uint64_t)1 << 37) +#define OPT_FORCE_CID_TAG ((uint64_t)1 << 38) +#define OPT_FORCE_CID_PRES ((uint64_t)1 << 39) enum { OPT_ARG_ANNOUNCE = 0, @@ -553,6 +574,8 @@ enum { OPT_ARG_OPERMODE, OPT_ARG_SCREEN_NOINTRO, OPT_ARG_FORCECLID, + OPT_ARG_FORCE_CID_TAG, + OPT_ARG_FORCE_CID_PRES, /* note: this entry _MUST_ be the last one in the enum */ OPT_ARG_ARRAY_SIZE, }; @@ -586,6 +609,8 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY), AST_APP_OPTION_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK), AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP), + AST_APP_OPTION_ARG('s', OPT_FORCE_CID_TAG, OPT_ARG_FORCE_CID_TAG), + AST_APP_OPTION_ARG('u', OPT_FORCE_CID_PRES, OPT_ARG_FORCE_CID_PRES), AST_APP_OPTION('t', OPT_CALLEE_TRANSFER), AST_APP_OPTION('T', OPT_CALLER_TRANSFER), AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB), @@ -854,8 +879,20 @@ static void do_forward(struct chanlist *o, ast_string_field_set(c, accountcode, in->accountcode); } ast_party_connected_line_copy(&c->connected, &original->connected); - - ast_channel_update_redirecting(in, &c->redirecting); + /* + * We must unlock c before calling ast_channel_redirecting_macro, because + * we put c into autoservice there. That is pretty much a guaranteed + * deadlock. This is why the handling of c's lock may seem a bit unusual + * here. + */ + ast_channel_unlock(c); + if (ast_channel_redirecting_macro(c, in, &c->redirecting, 1, 0)) { + while (ast_channel_trylock(c)) { + CHANNEL_DEADLOCK_AVOIDANCE(in); + } + ast_channel_update_redirecting(in, &c->redirecting); + ast_channel_unlock(c); + } ast_clear_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE); if (ast_test_flag64(peerflags, OPT_CANCEL_TIMEOUT)) { @@ -863,7 +900,6 @@ static void do_forward(struct chanlist *o, } ast_channel_unlock(in); - ast_channel_unlock(c); if (ast_call(c, tmpchan, 0)) { ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan); @@ -1194,7 +1230,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, ast_verb(3, "Redirecting update to %s prevented.\n", in->name); } else { ast_verb(3, "%s redirecting info has changed, passing it to %s\n", c->name, in->name); - ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); + if (ast_channel_redirecting_macro(c, in, f, 1, 1)) { + ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); + } pa->sentringing = 0; } break; @@ -1335,6 +1373,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, if (ast_channel_connected_line_macro(in, outgoing->chan, f, 0, 1)) { ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); } + } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) { + if (ast_channel_redirecting_macro(in, outgoing->chan, f, 0, 1)) { + ast_indicate_data(outgoing->chan, f->subclass.integer, f->data.ptr, f->datalen); + } } } ast_frfree(f); @@ -1702,7 +1744,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast struct cause_args num = { chan, 0, 0, 0 }; int cause; char numsubst[256]; - char *cid_num = NULL, *cid_name = NULL; + char *cid_num = NULL, *cid_name = NULL, *cid_tag = NULL, *cid_pres = NULL; struct ast_bridge_config config = { { 0, } }; struct timeval calldurationlimit = { 0, }; @@ -1805,6 +1847,10 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast if (ast_test_flag64(&opts, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &cid_name, &cid_num); + if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) + cid_tag = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_TAG]); + if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) + cid_pres = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_PRES]); if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr) ast_cdr_reset(chan->cdr, NULL); if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) @@ -1993,11 +2039,20 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast if (ast_test_flag64(peerflags, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) { struct ast_party_connected_line connected; + int pres; ast_party_connected_line_set_init(&connected, &tmp->chan->connected); connected.id.number = cid_num; connected.id.name = cid_name; - connected.id.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; + connected.id.tag = cid_tag; + if (cid_pres) { + pres = ast_parse_caller_presentation(cid_pres); + if (pres >= 0) { + connected.id.number_presentation = pres; + } + } else { + connected.id.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; + } ast_channel_set_connected_line(tmp->chan, &connected); } else { ast_connected_line_copy_from_caller(&tc->connected, &chan->cid); |