diff options
-rw-r--r-- | apps/app_dial.c | 67 | ||||
-rw-r--r-- | apps/app_queue.c | 21 | ||||
-rw-r--r-- | channels/chan_dahdi.c | 10 | ||||
-rw-r--r-- | channels/chan_local.c | 3 | ||||
-rw-r--r-- | channels/chan_misdn.c | 62 | ||||
-rw-r--r-- | channels/chan_sip.c | 45 | ||||
-rw-r--r-- | channels/misdn/chan_misdn_config.h | 2 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.h | 5 | ||||
-rw-r--r-- | channels/misdn_config.c | 7 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 2 | ||||
-rw-r--r-- | configs/misdn.conf.sample | 13 | ||||
-rw-r--r-- | funcs/func_callerid.c | 12 | ||||
-rw-r--r-- | funcs/func_connectedline.c | 9 | ||||
-rw-r--r-- | funcs/func_redirecting.c | 13 | ||||
-rw-r--r-- | include/asterisk/channel.h | 44 | ||||
-rw-r--r-- | include/asterisk/frame.h | 18 | ||||
-rw-r--r-- | main/channel.c | 217 | ||||
-rw-r--r-- | main/dial.c | 4 | ||||
-rw-r--r-- | main/features.c | 13 | ||||
-rw-r--r-- | main/rtp_engine.c | 20 |
20 files changed, 538 insertions, 49 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: diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index b072d86ce..d8e7496ce 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -1049,6 +1049,11 @@ struct dahdi_pvt { int cid_ani2; /*! \brief Caller ID number from an incoming call. */ char cid_num[AST_MAX_EXTENSION]; + /*! + * \brief Caller ID tag from incoming call + * \note the "cid_tag" string read in from chan_dahdi.conf + */ + char cid_tag[AST_MAX_EXTENSION]; /*! \brief Caller ID Q.931 TON/NPI field values. Set by PRI. Zero otherwise. */ int cid_ton; /*! \brief Caller ID name from an incoming call. */ @@ -1386,6 +1391,7 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void) .context = "default", .cid_num = "", .cid_name = "", + .cid_tag = "", .mohinterpret = "default", .mohsuggest = "", .parkinglot = "", @@ -9024,6 +9030,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb tmp->cid.cid_pres = i->callingpres; tmp->cid.cid_ton = i->cid_ton; tmp->cid.cid_ani2 = i->cid_ani2; + tmp->cid.cid_tag = ast_strdup(i->cid_tag); #if defined(HAVE_SS7) tmp->transfercapability = transfercapability; pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); @@ -11995,6 +12002,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp->cid_num[0] = '\0'; tmp->cid_name[0] = '\0'; } + ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag)); tmp->cid_subaddr[0] = '\0'; ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { @@ -16781,6 +16789,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); } else if (!strcasecmp(v->name, "cid_number")) { ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); + } else if (!strcasecmp(v->name, "cid_tag")) { + ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag)); } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { confp->chan.dahditrcallerid = ast_true(v->value); } else if (!strcasecmp(v->name, "restrictcid")) { diff --git a/channels/chan_local.c b/channels/chan_local.c index 337aadc7c..1f09c9cb5 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -433,6 +433,9 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da if (the_other_channel) { unsigned char frame_data[1024]; if (condition == AST_CONTROL_CONNECTED_LINE) { + if (isoutbound) { + ast_connected_line_copy_to_caller(&the_other_channel->cid, &this_channel->connected); + } f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected); } else { f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting); diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index f363c7c13..082373d97 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -5978,6 +5978,10 @@ static int read_config(struct chan_list *ch) ast_mutex_init(&ch->overlap_tv_lock); } /* ORIG MISDN END */ + misdn_cfg_get(port, MISDN_CFG_INCOMING_CALLERID_TAG, bc->incoming_cid_tag, sizeof(bc->incoming_cid_tag)); + if (!ast_strlen_zero(bc->incoming_cid_tag)) { + chan_misdn_log(1, port, " --> * Setting incoming caller id tag to \"%s\"\n", bc->incoming_cid_tag); + } ch->overlap_dial_task = -1; if (ch->faxdetect || ch->ast_dsp) { @@ -6003,10 +6007,11 @@ static int read_config(struct chan_list *ch) * \param ast Current Asterisk channel * \param id Party id information to send to the other side * \param source Why are we sending this update + * \param cid_tag Caller ID tag to set in the connected line * * \return Nothing */ -static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source) +static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag) { struct ast_party_connected_line connected; @@ -6016,6 +6021,7 @@ static void misdn_queue_connected_line_update(struct ast_channel *ast, const str | misdn_to_ast_plan(id->number_plan); connected.id.number_presentation = misdn_to_ast_pres(id->presentation) | misdn_to_ast_screen(id->screening); + connected.id.tag = cid_tag; connected.source = source; ast_channel_queue_connected_line_update(ast, &connected); } @@ -6168,10 +6174,11 @@ static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct as * * \param ast Current Asterisk channel * \param redirect Associated B channel redirecting info + * \param tag Caller ID tag to set in the redirecting party fields * * \return Nothing */ -static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect) +static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag) { struct ast_party_redirecting redirecting; @@ -6184,6 +6191,7 @@ static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct redirecting.from.number_presentation = misdn_to_ast_pres(redirect->from.presentation) | misdn_to_ast_screen(redirect->from.screening); + redirecting.from.tag = tag; redirecting.to.number = (char *) redirect->to.number; redirecting.to.number_type = @@ -6192,6 +6200,7 @@ static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct redirecting.to.number_presentation = misdn_to_ast_pres(redirect->to.presentation) | misdn_to_ast_screen(redirect->to.screening); + redirecting.to.tag = tag; redirecting.reason = misdn_to_ast_reason(redirect->reason); redirecting.count = redirect->count; @@ -6281,6 +6290,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout) struct chan_list *ch; struct misdn_bchannel *newbc; char *dest_cp; + int append_msn = 0; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(intf); /* The interface token is discarded. */ @@ -6392,6 +6402,14 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout) chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number); } + misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn)); + if (append_msn) { + strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1); + strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1); + } + + ast->cid.cid_tag = ast_strdup(newbc->incoming_cid_tag); + misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type)); if (number_type < 0) { newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type); @@ -8791,7 +8809,7 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel ++bc->redirecting.count; bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION; - misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting); + misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag); ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number); /* Send back positive ACK */ @@ -8855,7 +8873,7 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel bc->redirecting.to.presentation = 1;/* restricted */ bc->redirecting.to.screening = 0;/* unscreened */ } - misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting); + misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag); bc->div_leg_3_rx_wanted = 1; } break; @@ -8900,7 +8918,7 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel /* We have no place to put the OriginalCalled number */ } #endif - misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting); + misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag); } break; default: @@ -8950,7 +8968,7 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel ++bc->redirecting.count; bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION; - misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting); + misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag); ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number); misdn_lib_send_event(bc, EVENT_DISCONNECT); @@ -9072,7 +9090,8 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel misdn_queue_connected_line_update(ch->ast, &party_id, (bc->fac_in.u.EctInform.Status == 0 /* alerting */) ? AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING - : AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER); + : AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, + bc->incoming_cid_tag); } break; #if 0 /* We don't handle this yet */ @@ -9707,6 +9726,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) int exceed; int ai; int im; + int append_msn = 0; if (ch) { switch (ch->state) { @@ -9780,12 +9800,22 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number); + misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn)); + if (append_msn) { + strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1); + strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1); + } + + ast_channel_lock(chan); + chan->cid.cid_tag = ast_strdup(bc->incoming_cid_tag); + ast_channel_unlock(chan); + if (!ast_strlen_zero(bc->redirecting.from.number)) { /* Add configured prefix to redirecting.from.number */ misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number)); /* Update asterisk channel redirecting information */ - misdn_copy_redirecting_to_ast(chan, &bc->redirecting); + misdn_copy_redirecting_to_ast(chan, &bc->redirecting, bc->incoming_cid_tag); } pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability)); @@ -10124,11 +10154,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } #endif /* defined(AST_MISDN_ENHANCEMENTS) */ - /* Add configured prefix to connected.number */ - misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number)); + if (!ast_strlen_zero(bc->connected.number)) { + /* Add configured prefix to connected.number */ + misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number)); - /* Update the connected line information on the other channel */ - misdn_queue_connected_line_update(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER); + /* Update the connected line information on the other channel */ + misdn_queue_connected_line_update(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag); + } ch->l3id = bc->l3_id; ch->addr = bc->addr; @@ -10511,7 +10543,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN; break; } - misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting); + misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag); ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting); } } @@ -10530,7 +10562,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) bc->redirecting.to_changed = 0; if (ch && ch->ast) { misdn_queue_connected_line_update(ch->ast, &bc->redirecting.to, - AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING); + AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, bc->incoming_cid_tag); } } break; @@ -10539,7 +10571,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) bc->redirecting.to_changed = 0; if (ch && ch->ast) { misdn_queue_connected_line_update(ch->ast, &bc->redirecting.to, - AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER); + AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag); } } break; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 6fe3e1c6f..d0a876659 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4741,6 +4741,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) ast_string_field_set(dialog, context, peer->context); ast_string_field_set(dialog, cid_num, peer->cid_num); ast_string_field_set(dialog, cid_name, peer->cid_name); + ast_string_field_set(dialog, cid_tag, peer->cid_tag); ast_string_field_set(dialog, mwi_from, peer->mwi_from); ast_string_field_set(dialog, parkinglot, peer->parkinglot); ast_string_field_set(dialog, engine, peer->engine); @@ -6281,6 +6282,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit ast_channel_lock(tmp); sip_pvt_lock(i); ast_channel_cc_params_init(tmp, i->cc_params); + tmp->cid.cid_tag = ast_strdup(i->cid_tag); ast_channel_unlock(tmp); tmp->tech = ( ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INFO || ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO) ? &sip_tech_info : &sip_tech; @@ -13395,7 +13397,11 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c params++; /* Check if we have a reason parameter */ if ((reason_param = strcasestr(params, "reason="))) { + char *end; reason_param+=7; + if ((end = strchr(reason_param, ';'))) { + *end = '\0'; + } /* Remove enclosing double-quotes */ if (*reason_param == '"') ast_strip_quoted(reason_param, "\"", "\""); @@ -14118,6 +14124,8 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of, } if (!ast_strlen_zero(peer->cid_name)) ast_string_field_set(p, cid_name, peer->cid_name); + if (!ast_strlen_zero(peer->cid_tag)) + ast_string_field_set(p, cid_tag, peer->cid_tag); if (peer->callingpres) p->callingpres = peer->callingpres; } @@ -17527,6 +17535,7 @@ static void change_redirecting_information(struct sip_pvt *p, struct sip_request ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name); redirecting->from.name = redirecting_from_name; } + redirecting->from.tag = (char *) p->cid_tag; if (!ast_strlen_zero(redirecting_to_number)) { if (redirecting->to.number) { ast_free(redirecting->to.number); @@ -17541,6 +17550,7 @@ static void change_redirecting_information(struct sip_pvt *p, struct sip_request ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number); redirecting->to.name = redirecting_to_name; } + redirecting->to.tag = (char *) p->cid_tag; redirecting->reason = reason; } @@ -17888,6 +17898,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest ast_party_connected_line_init(&connected); connected.id.number = (char *) p->cid_num; connected.id.name = (char *) p->cid_name; + connected.id.tag = (char *) p->cid_tag; connected.id.number_presentation = p->callingpres; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(p->owner, &connected); @@ -17932,6 +17943,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest ast_party_connected_line_init(&connected); connected.id.number = (char *) p->cid_num; connected.id.name = (char *) p->cid_name; + connected.id.tag = (char *) p->cid_tag; connected.id.number_presentation = p->callingpres; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(p->owner, &connected); @@ -17977,6 +17989,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest ast_party_connected_line_init(&connected); connected.id.number = (char *) p->cid_num; connected.id.name = (char *) p->cid_name; + connected.id.tag = (char *) p->cid_tag; connected.id.number_presentation = p->callingpres; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(p->owner, &connected); @@ -20121,6 +20134,7 @@ static int handle_request_update(struct sip_pvt *p, struct sip_request *req) ast_party_connected_line_init(&connected); connected.id.number = (char *) p->cid_num; connected.id.name = (char *) p->cid_name; + connected.id.tag = (char *) p->cid_tag; connected.id.number_presentation = p->callingpres; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; ast_channel_queue_connected_line_update(p->owner, &connected); @@ -20448,6 +20462,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int ast_party_connected_line_init(&connected); connected.id.number = (char *) p->cid_num; connected.id.name = (char *) p->cid_name; + connected.id.tag = (char *) p->cid_tag; connected.id.number_presentation = p->callingpres; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; ast_channel_queue_connected_line_update(p->owner, &connected); @@ -21073,11 +21088,30 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual * ast_channel_queue_connected_line_update(target.chan2, &connected_to_target); } else { /* Since target.chan1 isn't actually connected to another channel, there is no way for us - * to queue a frame so that its connected line status will be updated. Instead, we have to - * change it directly. Since we are not the channel thread, we cannot run a connected line - * interception macro on target.chan1 + * to queue a frame so that its connected line status will be updated. + * + * Instead, we use the somewhat hackish approach of using a special control frame type that + * instructs ast_read to perform a specific action. In this case, the frame we queue tells + * ast_read to call the connected line interception macro configured for target.chan1. + */ + struct ast_control_read_action_payload *frame_payload; + int payload_size; + int frame_size; + unsigned char connected_line_data[1024]; + payload_size = ast_connected_line_build_data(connected_line_data, sizeof(connected_line_data), &connected_to_target); + frame_size = payload_size + sizeof(*frame_payload); + if (payload_size != -1 && (frame_payload = alloca(frame_size))) { + frame_payload->payload_size = payload_size; + memcpy(frame_payload->payload, connected_line_data, payload_size); + frame_payload->action = AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO; + ast_queue_control_data(target.chan1, AST_CONTROL_READ_ACTION, frame_payload, frame_size); + } + /* In addition to queueing the read action frame so that target.chan1's connected line info + * will be updated, we also are going to queue a plain old connected line update on target.chan1. This + * way, either Dial or Queue can apply this connected line update to the outgoing ringing channel. */ - ast_channel_update_connected_line(target.chan1, &connected_to_target); + ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee); + } ast_channel_unref(current->chan1); } @@ -24718,6 +24752,7 @@ static void set_peer_defaults(struct sip_peer *peer) ast_string_field_set(peer, md5secret, ""); ast_string_field_set(peer, cid_num, ""); ast_string_field_set(peer, cid_name, ""); + ast_string_field_set(peer, cid_tag, ""); ast_string_field_set(peer, fromdomain, ""); ast_string_field_set(peer, fromuser, ""); ast_string_field_set(peer, regexten, ""); @@ -24933,6 +24968,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str ast_string_field_set(peer, cid_name, ""); } else if (!strcasecmp(v->name, "cid_number")) { ast_string_field_set(peer, cid_num, v->value); + } else if (!strcasecmp(v->name, "cid_tag")) { + ast_string_field_set(peer, cid_tag, v->value); } else if (!strcasecmp(v->name, "context")) { ast_string_field_set(peer, context, v->value); ast_set_flag(&peer->flags[1], SIP_PAGE2_HAVEPEERCONTEXT); diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h index e1fe16766..270b505ba 100644 --- a/channels/misdn/chan_misdn_config.h +++ b/channels/misdn/chan_misdn_config.h @@ -42,6 +42,8 @@ enum misdn_cfg_elements { MISDN_CFG_LANGUAGE, /* char[] */ MISDN_CFG_MUSICCLASS, /* char[] */ MISDN_CFG_CALLERID, /* char[] */ + MISDN_CFG_INCOMING_CALLERID_TAG, /* char[] */ + MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, /* int (bool) */ MISDN_CFG_METHOD, /* char[] */ MISDN_CFG_DIALPLAN, /* int */ MISDN_CFG_LOCALDIALPLAN, /* int */ diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 89565327e..a04476068 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -349,6 +349,11 @@ struct misdn_bchannel { */ struct misdn_party_id caller; + /*! \brief Incoming Caller ID string tag for special purpose + * \note The element can be set to "incoming_cid_tag" in /etc/asterisk/misdn.conf for incoming calls + */ + char incoming_cid_tag[MISDN_MAX_NAME_LEN]; + /*! \brief Connected-Party/Connected-Line ID information struct * \note The number_type element can be set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls */ diff --git a/channels/misdn_config.c b/channels/misdn_config.c index 82d3547f7..e14f2adee 100644 --- a/channels/misdn_config.c +++ b/channels/misdn_config.c @@ -134,6 +134,13 @@ static const struct misdn_cfg_spec port_spec[] = { "Sets the musiconhold class." }, { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE, "Set the outgoing caller id to the value." }, + { "incoming_cid_tag", MISDN_CFG_INCOMING_CALLERID_TAG, MISDN_CTYPE_STR, "", NONE, + "Set the incoming caller id string tag to the value." }, + { "append_msn_to_cid_tag", MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, MISDN_CTYPE_BOOL, "no", NONE, + "Automatically appends incoming or outgoing MSN to the incoming caller\n" + "\tid string tag. An underscore '_' is used as delimiter. Incoming calls\n" + "\twill have the dialed number appended, and outgoing calls will have the\n" + "\tcaller number appended to the tag." }, { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE, "Set the method to use for channel selection:\n" "\t standard - Use the first free channel starting from the lowest number.\n" diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index 2ee19b6d7..ade534ede 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -926,6 +926,7 @@ struct sip_pvt { AST_STRING_FIELD(peermd5secret); AST_STRING_FIELD(cid_num); /*!< Caller*ID number */ AST_STRING_FIELD(cid_name); /*!< Caller*ID name */ + AST_STRING_FIELD(cid_tag); /*!< Caller*ID tag */ AST_STRING_FIELD(mwi_from); /*!< Name to place in the From header in outgoing NOTIFY requests */ AST_STRING_FIELD(fullcontact); /*!< The Contact: that the UA registers with us */ /* we only store the part in <brackets> in this field. */ @@ -1130,6 +1131,7 @@ struct sip_peer { AST_STRING_FIELD(fullcontact); /*!< Contact registered with us (not in sip.conf) */ AST_STRING_FIELD(cid_num); /*!< Caller ID num */ AST_STRING_FIELD(cid_name); /*!< Caller ID name */ + AST_STRING_FIELD(cid_tag); /*!< Caller ID tag */ AST_STRING_FIELD(vmexten); /*!< Dialplan extension for MWI notify message*/ AST_STRING_FIELD(language); /*!< Default language for prompts */ AST_STRING_FIELD(mohinterpret); /*!< Music on Hold class */ diff --git a/configs/misdn.conf.sample b/configs/misdn.conf.sample index 9de874e92..bd51686e4 100644 --- a/configs/misdn.conf.sample +++ b/configs/misdn.conf.sample @@ -404,6 +404,19 @@ nodialtone=no presentation=-1 screen=-1 +; Incoming calls will have a caller ID tag set to this value +; +;incoming_cid_tag = "asterisk" + +; With this set, you can automatically append the MSN of a party +; to the cid_tag. Incoming calls have the dialed number appended +; to the tag, and outgoing calls have the caller number appended +; to the tag. An '_' is used to separate the tag from the +; MSN. +; Default is no. +; +;append_msn_to_cid_tag = no + ; Select what to do with outgoing COLP information on this port. ; ; 0 - Send out COLP information unaltered. (default) diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c index 3de69950e..357055c8c 100644 --- a/funcs/func_callerid.c +++ b/funcs/func_callerid.c @@ -44,6 +44,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name="all" /> <enum name="num" /> <enum name="name" /> + <enum name="tag" /> <enum name="ANI" /> <enum name="DNID" /> <enum name="RDNIS" /> @@ -161,6 +162,10 @@ static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, if (chan->cid.cid_name) { ast_copy_string(buf, chan->cid.cid_name, len); } + } else if (!strncasecmp("tag", data, 3)) { + if (chan->cid.cid_tag) { + ast_copy_string(buf, chan->cid.cid_tag, len); + } } else if (!strncasecmp("num", data, 3)) { /* also matches "number" */ if (chan->cid.cid_num) { @@ -254,6 +259,13 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, if (chan->cdr) { ast_cdr_setcid(chan->cdr, chan); } + } else if (!strncasecmp("tag", data, 3)) { + ast_channel_lock(chan); + if (chan->cid.cid_tag) { + ast_free(chan->cid.cid_tag); + } + chan->cid.cid_tag = ast_strdup(value); + ast_channel_unlock(chan); } else if (!strncasecmp("ani", data, 3)) { if (!strncasecmp(data + 3, "2", 1)) { chan->cid.cid_ani2 = atoi(value); diff --git a/funcs/func_connectedline.c b/funcs/func_connectedline.c index 936d49047..95bcb23af 100644 --- a/funcs/func_connectedline.c +++ b/funcs/func_connectedline.c @@ -58,6 +58,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name = "all" /> <enum name = "num" /> <enum name = "name" /> + <enum name = "tag" /> <enum name = "ton" /> <enum name = "pres" /> <enum name = "subaddr[-valid]|[-type]|[-odd]"> @@ -99,6 +100,10 @@ static int connectedline_read(struct ast_channel *chan, const char *cmd, char *d if (chan->connected.id.number) { ast_copy_string(buf, chan->connected.id.number, len); } + } else if (!strncasecmp("tag", data, 3)) { + if (chan->connected.id.tag) { + ast_copy_string(buf, chan->connected.id.tag, len); + } } else if (!strncasecmp("ton", data, 3)) { snprintf(buf, len, "%d", chan->connected.id.number_type); } else if (!strncasecmp("pres", data, 4)) { @@ -179,6 +184,10 @@ static int connectedline_write(struct ast_channel *chan, const char *cmd, char * connected.id.number = ast_strdupa(value); ast_trim_blanks(connected.id.number); set_it(chan, &connected); + } else if (!strncasecmp("tag", data, 3)) { + connected.id.tag = ast_strdupa(value); + ast_trim_blanks(connected.id.tag); + set_it(chan, &connected); } else if (!strncasecmp("ton", data, 3)) { val = ast_strdupa(value); ast_trim_blanks(val); diff --git a/funcs/func_redirecting.c b/funcs/func_redirecting.c index 87fc41abe..2f38c2f3b 100644 --- a/funcs/func_redirecting.c +++ b/funcs/func_redirecting.c @@ -68,11 +68,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name = "from-all" /> <enum name = "from-num" /> <enum name = "from-name" /> + <enum name = "from-tag" /> <enum name = "from-ton" /> <enum name = "from-pres" /> <enum name = "to-all" /> <enum name = "to-num" /> <enum name = "to-name" /> + <enum name = "to-tag" /> <enum name = "to-ton" /> <enum name = "to-pres" /> <enum name = "reason" /> @@ -144,6 +146,10 @@ static enum ID_FIELD_STATUS redirecting_id_read(char *buf, size_t len, char *dat if (id->number) { ast_copy_string(buf, id->number, len); } + } else if (!strncasecmp("tag", data, 3)) { + if (id->tag) { + ast_copy_string(buf, id->tag, len); + } } else if (!strncasecmp("ton", data, 3)) { snprintf(buf, len, "%d", id->number_type); } else if (!strncasecmp("pres", data, 4)) { @@ -257,6 +263,9 @@ static enum ID_FIELD_STATUS redirecting_id_write(struct ast_party_id *id, char * } else if (!strncasecmp("num", data, 3)) { id->number = ast_strdup(value); ast_trim_blanks(id->number); + } else if (!strncasecmp("tag", data, 3)) { + id->tag = ast_strdup(value); + ast_trim_blanks(id->tag); } else if (!strncasecmp("ton", data, 3)) { val = ast_strdupa(value); ast_trim_blanks(val); @@ -347,7 +356,6 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da switch (redirecting_id_write(&redirecting.from, data + 5, value)) { case ID_FIELD_VALID: set_it(chan, &redirecting); - ast_party_redirecting_free(&redirecting); break; case ID_FIELD_INVALID: @@ -357,11 +365,11 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); break; } + ast_party_redirecting_free(&redirecting); } else if (!strncasecmp("to-", data, 3)) { switch (redirecting_id_write(&redirecting.to, data + 3, value)) { case ID_FIELD_VALID: set_it(chan, &redirecting); - ast_party_redirecting_free(&redirecting); break; case ID_FIELD_INVALID: @@ -371,6 +379,7 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); break; } + ast_party_redirecting_free(&redirecting); } else if (!strncasecmp("pres", data, 4)) { int pres; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index b2cb8e5eb..5aa5f1ff3 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -288,6 +288,17 @@ struct ast_callerid { * (Field will eventually move to struct ast_channel.dialed.transit_network_select) */ int cid_tns; + + /*! + * \brief Callerid "Tag" + * A user-settable field used to help associate some extrinsic information + * about the channel or user of the channel to the caller ID. This information + * is not transmitted over the wire and so is only useful within an Asterisk + * environment. + * (Field will eventually move to struct ast_channel.caller.id.tag) + */ + char *cid_tag; + /*! * \brief Caller id subaddress. * (Field will eventually move to struct ast_channel.caller.id.subaddress) @@ -314,6 +325,9 @@ struct ast_party_id { /*! \brief Subscriber name (Malloced) */ char *name; + /*! \brief User-set "tag" */ + char *tag; + /*! \brief Subscriber subaddress. */ struct ast_party_subaddress subaddress; @@ -2779,6 +2793,36 @@ int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *ch int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct ast_channel *chan, const char *structure_name); +/*! + * \since 1.8 + * \brief Run a redirecting interception macro and update a channel's redirecting information + * + * \details + * Whenever we want to update a channel's redirecting 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 + * \param macro_chan The channel to run the macro on. Also the channel from which we + * 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_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 macro does not exist, or there was an error while attempting to + * 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' + */ +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); + #include "asterisk/ccss.h" /*! diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index 0d8d557d2..4198fad79 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -326,6 +326,24 @@ enum ast_control_frame_type { AST_CONTROL_T38_PARAMETERS = 24, /*! T38 state change request/notification with parameters */ AST_CONTROL_CC = 25, /*!< Indication that Call completion service is possible */ AST_CONTROL_SRCCHANGE = 26, /*!< Media source has changed and requires a new RTP SSRC */ + AST_CONTROL_READ_ACTION = 27, /*!< Tell ast_read to take a specific action */ +}; + +enum ast_frame_read_action { + AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO, +}; + +struct ast_control_read_action_payload { + /* An indicator to ast_read of what action to + * take with the frame; + */ + enum ast_frame_read_action action; + /* The size of the frame's payload + */ + size_t payload_size; + /* A payload for the frame. + */ + unsigned char payload[0]; }; enum ast_control_t38 { diff --git a/main/channel.c b/main/channel.c index c91d60219..5850c89de 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1528,6 +1528,8 @@ static void free_cid(struct ast_callerid *cid) ast_free(cid->cid_name); if (cid->cid_ani) ast_free(cid->cid_ani); + if (cid->cid_tag) + ast_free(cid->cid_tag); cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = NULL; ast_party_subaddress_free(&cid->subaddress); ast_party_subaddress_free(&cid->dialed_subaddress); @@ -1611,6 +1613,7 @@ static void ast_party_id_init(struct ast_party_id *init) { init->number = NULL; init->name = NULL; + init->tag = NULL; init->number_type = 0; /* Unknown */ init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; ast_party_subaddress_init(&init->subaddress); @@ -1642,6 +1645,11 @@ static void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_ } dest->name = ast_strdup(src->name); + if (dest->tag) { + ast_free(dest->tag); + } + dest->tag = ast_strdup(src->tag); + dest->number_type = src->number_type; dest->number_presentation = src->number_presentation; ast_party_subaddress_copy(&dest->subaddress, &src->subaddress); @@ -1668,6 +1676,7 @@ static void ast_party_id_set_init(struct ast_party_id *init, const struct ast_pa { init->number = NULL; init->name = NULL; + init->tag = NULL; init->number_type = guide->number_type; init->number_presentation = guide->number_presentation; ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress); @@ -1703,6 +1712,13 @@ static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_i dest->number = ast_strdup(src->number); } + if (src->tag && src->tag != dest->tag) { + if (dest->tag) { + ast_free(dest->tag); + } + dest->tag = ast_strdup(src->tag); + } + dest->number_type = src->number_type; dest->number_presentation = src->number_presentation; ast_party_subaddress_set(&dest->subaddress, &src->subaddress); @@ -1727,6 +1743,11 @@ static void ast_party_id_free(struct ast_party_id *doomed) ast_free(doomed->name); doomed->name = NULL; } + + if (doomed->tag) { + ast_free(doomed->tag); + doomed->tag = NULL; + } ast_party_subaddress_free(&doomed->subaddress); } @@ -1758,6 +1779,11 @@ void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid } dest->cid_name = ast_strdup(src->cid_name); + if (dest->cid_tag) { + ast_free(dest->cid_tag); + } + dest->cid_tag = ast_strdup(src->cid_tag); + dest->cid_ton = src->cid_ton; dest->cid_pres = src->cid_pres; @@ -1843,6 +1869,7 @@ void ast_party_connected_line_collect_caller(struct ast_party_connected_line *co connected->id.name = cid->cid_name; connected->id.number_type = cid->cid_ton; connected->id.number_presentation = cid->cid_pres; + connected->id.tag = cid->cid_tag; connected->id.subaddress = cid->subaddress; connected->ani = cid->cid_ani; @@ -3354,6 +3381,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) if (f) { struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq); + struct ast_control_read_action_payload *read_action_payload; + struct ast_party_connected_line connected; /* if the channel driver returned more than one frame, stuff the excess into the readq for the next ast_read call @@ -3381,6 +3410,23 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) /* removed a call to ast_cdr_answer(chan->cdr) from here. */ ast_cel_report_event(chan, AST_CEL_ANSWER, NULL, NULL, NULL); } + } else if (f->subclass.integer == AST_CONTROL_READ_ACTION) { + ast_party_connected_line_init(&connected); + read_action_payload = f->data.ptr; + switch (read_action_payload->action) { + case AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO: + if (ast_connected_line_parse_data(read_action_payload->payload, + read_action_payload->payload_size, &connected)) { + break; + } + if (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); + } + break; + } + ast_frfree(f); + f = &ast_null_frame; } break; case AST_FRAME_DTMF_END: @@ -3606,6 +3652,25 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) * and synchronous generation of outgoing frames is necessary */ ast_read_generator_actions(chan, f); } + break; + case AST_CONTROL_READ_ACTION: + ast_log(LOG_NOTICE, "Read a read action frame\n"); + read_action_payload = f->data.ptr; + switch (read_action_payload->action) { + case AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO: + if (ast_connected_line_parse_data(read_action_payload->payload, + read_action_payload->payload_size, &connected)) { + break; + } + if (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); + } + break; + } + ast_frfree(f); + f = &ast_null_frame; + break; default: /* Just pass it on! */ break; @@ -3679,6 +3744,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con case AST_CONTROL_T38_PARAMETERS: case _XXX_AST_CONTROL_T38: case AST_CONTROL_CC: + case AST_CONTROL_READ_ACTION: break; case AST_CONTROL_CONGESTION: @@ -3823,6 +3889,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_REDIRECTING: case AST_CONTROL_CC: + case AST_CONTROL_READ_ACTION: /* Nothing left to do for these. */ res = 0; break; @@ -5794,7 +5861,9 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct switch (f->subclass.integer) { case AST_CONTROL_REDIRECTING: - ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); + if (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)) { @@ -6781,6 +6850,11 @@ void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, } dest->id.name = ast_strdup(src->cid_name); + if (dest->id.tag) { + ast_free(dest->id.tag); + } + dest->id.tag = ast_strdup(src->cid_tag); + dest->id.number_type = src->cid_ton; dest->id.number_presentation = src->cid_pres; @@ -6823,6 +6897,11 @@ void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct a } dest->cid_name = ast_strdup(src->id.name); + if (dest->cid_tag) { + ast_free(dest->cid_tag); + } + dest->cid_tag = ast_strdup(src->id.tag); + dest->cid_ton = src->id.number_type; dest->cid_pres = src->id.number_presentation; @@ -6876,7 +6955,8 @@ enum { AST_CONNECTED_LINE_SUBADDRESS, AST_CONNECTED_LINE_SUBADDRESS_TYPE, AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, - AST_CONNECTED_LINE_SUBADDRESS_VALID + AST_CONNECTED_LINE_SUBADDRESS_VALID, + AST_CONNECTED_LINE_TAG, }; int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected) @@ -6915,6 +6995,18 @@ int ast_connected_line_build_data(unsigned char *data, size_t datalen, const str pos += length; } + if (connected->id.tag) { + length = strlen(connected->id.tag); + if (datalen < pos + (sizeof(data[0]) * 2) + length) { + ast_log(LOG_WARNING, "No space left for connected line tag\n"); + return -1; + } + data[pos++] = AST_CONNECTED_LINE_TAG; + data[pos++] = length; + memcpy(data + pos, connected->id.tag, length); + pos += length; + } + if (datalen < pos + (sizeof(data[0]) * 2) + 1) { ast_log(LOG_WARNING, "No space left for connected line type of number\n"); return -1; @@ -7025,6 +7117,16 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str connected->id.name[ie_len] = 0; } break; + case AST_CONNECTED_LINE_TAG: + if (connected->id.tag) { + ast_free(connected->id.tag); + } + connected->id.tag = ast_malloc(ie_len + 1); + if (connected->id.tag) { + memcpy(connected->id.tag, data + pos, ie_len); + connected->id.tag[ie_len] = 0; + } + break; case AST_CONNECTED_LINE_NUMBER_TYPE: if (ie_len != 1) { ast_log(LOG_WARNING, "Invalid connected line type of number (%u)\n", (unsigned) ie_len); @@ -7156,7 +7258,9 @@ enum { AST_REDIRECTING_TO_SUBADDRESS, AST_REDIRECTING_TO_SUBADDRESS_TYPE, AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, - AST_REDIRECTING_TO_SUBADDRESS_VALID + AST_REDIRECTING_TO_SUBADDRESS_VALID, + AST_REDIRECTING_FROM_TAG, + AST_REDIRECTING_TO_TAG, }; int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting) @@ -7195,6 +7299,18 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct pos += length; } + if (redirecting->from.tag) { + length = strlen(redirecting->from.tag); + if (datalen < pos + (sizeof(data[0]) * 2) + length) { + ast_log(LOG_WARNING, "No space left for redirecting from name\n"); + return -1; + } + data[pos++] = AST_REDIRECTING_FROM_TAG; + data[pos++] = length; + memcpy(data + pos, redirecting->from.tag, length); + pos += length; + } + if (datalen < pos + (sizeof(data[0]) * 2) + 1) { ast_log(LOG_WARNING, "No space left for redirecting from type of number\n"); return -1; @@ -7274,6 +7390,18 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct pos += length; } + if (redirecting->to.tag) { + length = strlen(redirecting->to.tag); + if (datalen < pos + (sizeof(data[0]) * 2) + length) { + ast_log(LOG_WARNING, "No space left for redirecting to name\n"); + return -1; + } + data[pos++] = AST_REDIRECTING_TO_TAG; + data[pos++] = length; + memcpy(data + pos, redirecting->to.tag, length); + pos += length; + } + if (datalen < pos + (sizeof(data[0]) * 2) + 1) { ast_log(LOG_WARNING, "No space left for redirecting to type of number\n"); return -1; @@ -7393,6 +7521,16 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct redirecting->from.name[ie_len] = 0; } break; + case AST_REDIRECTING_FROM_TAG: + if (redirecting->from.tag) { + ast_free(redirecting->from.tag); + } + redirecting->from.tag = ast_malloc(ie_len + 1); + if (redirecting->from.tag) { + memcpy(redirecting->from.tag, data + pos, ie_len); + redirecting->from.tag[ie_len] = 0; + } + break; case AST_REDIRECTING_FROM_NUMBER_TYPE: if (ie_len != 1) { ast_log(LOG_WARNING, "Invalid redirecting from type of number (%u)\n", (unsigned) ie_len); @@ -7462,6 +7600,16 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct redirecting->to.name[ie_len] = 0; } break; + case AST_REDIRECTING_TO_TAG: + if (redirecting->to.tag) { + ast_free(redirecting->to.tag); + } + redirecting->to.tag = ast_malloc(ie_len + 1); + if (redirecting->to.tag) { + memcpy(redirecting->to.tag, data + pos, ie_len); + redirecting->to.tag[ie_len] = 0; + } + break; case AST_REDIRECTING_TO_NUMBER_TYPE: if (ie_len != 1) { ast_log(LOG_WARNING, "Invalid redirecting to type of number (%u)\n", (unsigned) ie_len); @@ -7562,39 +7710,72 @@ 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) +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) { 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; + ast_channel_lock(macro_chan); + macro = pbx_builtin_getvar_helper(macro_chan, is_caller + ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"); + macro = ast_strdupa(S_OR(macro, "")); + macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller + ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARSG" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"); + macro_args = ast_strdupa(S_OR(macro_args, "")); + ast_channel_unlock(macro_chan); + + if (ast_strlen_zero(macro)) { + return -1; + } + + if (is_frame) { + const struct ast_frame *frame = connected_info; + ast_connected_line_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->connected); } else { - pointer.connected = connected_info; + const struct ast_party_connected_line *connected = connected_info; + ast_party_connected_line_copy(¯o_chan->connected, 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; +} + +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) +{ + const char *macro; + const char *macro_args; + int retval; + 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"), "")); + macro = pbx_builtin_getvar_helper(macro_chan, is_caller + ? "REDIRECTING_CALLER_SEND_MACRO" : "REDIRECTING_CALLEE_SEND_MACRO"); + macro = ast_strdupa(S_OR(macro, "")); + macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller + ? "REDIRECTING_CALLER_SEND_MACRO_ARGS" : "REDIRECTING_CALLEE_SEND_MACRO_ARGS"); + macro_args = ast_strdupa(S_OR(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); + if (is_frame) { + const struct ast_frame *frame = redirecting_info; + + ast_redirecting_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->redirecting); } else { - ast_party_connected_line_copy(¯o_chan->connected, pointer.connected); + const struct ast_party_redirecting *redirecting = redirecting_info; + + ast_party_redirecting_copy(¯o_chan->redirecting, redirecting); } - if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) { - ast_channel_update_connected_line(macro_chan, ¯o_chan->connected); + retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); + if (!retval) { + ast_channel_update_redirecting(macro_chan, ¯o_chan->redirecting); } return retval; diff --git a/main/dial.c b/main/dial.c index 7435d926c..bfd0c44a4 100644 --- a/main/dial.c +++ b/main/dial.c @@ -426,7 +426,9 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel break; case AST_CONTROL_REDIRECTING: ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name); - ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen); + if (ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) { + ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen); + } break; case AST_CONTROL_PROCEEDING: ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name); diff --git a/main/features.c b/main/features.c index 0a26ad1c0..72a626e45 100644 --- a/main/features.c +++ b/main/features.c @@ -2728,6 +2728,10 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, 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.integer == AST_CONTROL_REDIRECTING) { + if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) { + ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen); + } } else if (f->subclass.integer != -1 && f->subclass.integer != AST_CONTROL_PROGRESS) { ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer); } @@ -3196,7 +3200,14 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) { break; } - /* The implied "else" falls through purposely */ + 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; + } + ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); + break; case AST_CONTROL_HOLD: case AST_CONTROL_UNHOLD: ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 88f534614..0027b04ee 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -887,6 +887,16 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a } ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_frfree(fr); + } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) { + if (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)) { + ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); + } + ast_frfree(fr); } else { *fo = fr; *rc = who; @@ -1113,6 +1123,16 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct } ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_frfree(fr); + } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) { + if (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)) { + ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); + } + ast_frfree(fr); } else { *fo = fr; *rc = who; |