diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_dial.c | 67 | ||||
-rw-r--r-- | apps/app_queue.c | 21 |
2 files changed, 80 insertions, 8 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); diff --git a/apps/app_queue.c b/apps/app_queue.c index 97eefe7b5..6a544de8c 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3204,6 +3204,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte { const char *queue = qe->parent->name; struct callattempt *o, *start = NULL, *prev = NULL; + int res; int status; int numbusies = prebusies; int numnochan = 0; @@ -3373,7 +3374,21 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte ast_party_caller_copy(&o->chan->cid, &in->cid); ast_party_connected_line_copy(&o->chan->connected, &original->connected); - ast_channel_update_redirecting(in, &o->chan->redirecting); + /* + * We must unlock o->chan before calling + * ast_channel_redirecting_macro, because we put o->chan into + * autoservice there. That is pretty much a guaranteed + * deadlock. This is why the handling of o->chan's lock may + * seem a bit unusual here. + */ + ast_channel_unlock(o->chan); + res = ast_channel_redirecting_macro(o->chan, in, &o->chan->redirecting, 1, 0); + while (ast_channel_trylock(o->chan)) { + CHANNEL_DEADLOCK_AVOIDANCE(in); + } + if (res) { + ast_channel_update_redirecting(in, &o->chan->redirecting); + } update_connectedline = 1; @@ -3486,7 +3501,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte ast_verb(3, "Redirecting update to %s prevented\n", inchan_name); } else { ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name); - ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); + if (ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) { + ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); + } } break; default: |