diff options
-rw-r--r-- | channels/chan_misdn.c | 145 | ||||
-rw-r--r-- | channels/chan_sip.c | 88 | ||||
-rw-r--r-- | channels/sig_pri.c | 39 | ||||
-rw-r--r-- | funcs/func_callerid.c | 208 | ||||
-rw-r--r-- | include/asterisk/channel.h | 99 | ||||
-rw-r--r-- | main/channel.c | 706 | ||||
-rw-r--r-- | main/channel_internal_api.c | 16 | ||||
-rw-r--r-- | main/cli.c | 7 | ||||
-rw-r--r-- | main/features.c | 3 |
9 files changed, 1219 insertions, 92 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index ce654ee41..da45db9c3 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -6109,6 +6109,13 @@ 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); + + /* + * Make sure that any earlier private connected id + * representation at the remote end is invalidated + */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = cid_tag; connected.source = source; ast_channel_queue_connected_line_update(ast, &connected, &update_connected); @@ -6182,20 +6189,21 @@ static void misdn_update_remote_party(struct ast_channel *ast, const struct misd static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator) { int number_type; + struct ast_party_id connected_id = ast_channel_connected_effective_id(ast); if (originator == ORG_MISDN) { /* ORIGINATOR MISDN (incoming call) */ ast_copy_string(bc->connected.name, - S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""), + S_COR(connected_id.name.valid, connected_id.name.str, ""), sizeof(bc->connected.name)); - if (ast_channel_connected(ast)->id.number.valid) { - ast_copy_string(bc->connected.number, S_OR(ast_channel_connected(ast)->id.number.str, ""), + if (connected_id.number.valid) { + ast_copy_string(bc->connected.number, S_OR(connected_id.number.str, ""), sizeof(bc->connected.number)); - bc->connected.presentation = ast_to_misdn_pres(ast_channel_connected(ast)->id.number.presentation); - bc->connected.screening = ast_to_misdn_screen(ast_channel_connected(ast)->id.number.presentation); - bc->connected.number_type = ast_to_misdn_ton(ast_channel_connected(ast)->id.number.plan); - bc->connected.number_plan = ast_to_misdn_plan(ast_channel_connected(ast)->id.number.plan); + bc->connected.presentation = ast_to_misdn_pres(connected_id.number.presentation); + bc->connected.screening = ast_to_misdn_screen(connected_id.number.presentation); + bc->connected.number_type = ast_to_misdn_ton(connected_id.number.plan); + bc->connected.number_plan = ast_to_misdn_plan(connected_id.number.plan); } else { bc->connected.number[0] = '\0'; bc->connected.presentation = 0;/* Allowed */ @@ -6215,15 +6223,15 @@ static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchan /* ORIGINATOR Asterisk (outgoing call) */ ast_copy_string(bc->caller.name, - S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""), + S_COR(connected_id.name.valid, connected_id.name.str, ""), sizeof(bc->caller.name)); - if (ast_channel_connected(ast)->id.number.valid) { - ast_copy_string(bc->caller.number, S_OR(ast_channel_connected(ast)->id.number.str, ""), + if (connected_id.number.valid) { + ast_copy_string(bc->caller.number, S_OR(connected_id.number.str, ""), sizeof(bc->caller.number)); - bc->caller.presentation = ast_to_misdn_pres(ast_channel_connected(ast)->id.number.presentation); - bc->caller.screening = ast_to_misdn_screen(ast_channel_connected(ast)->id.number.presentation); - bc->caller.number_type = ast_to_misdn_ton(ast_channel_connected(ast)->id.number.plan); - bc->caller.number_plan = ast_to_misdn_plan(ast_channel_connected(ast)->id.number.plan); + bc->caller.presentation = ast_to_misdn_pres(connected_id.number.presentation); + bc->caller.screening = ast_to_misdn_screen(connected_id.number.presentation); + bc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan); + bc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan); } else { bc->caller.number[0] = '\0'; bc->caller.presentation = 0;/* Allowed */ @@ -6336,16 +6344,19 @@ static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bc */ static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast) { + struct ast_party_id from_id = ast_channel_redirecting_effective_from(ast); + struct ast_party_id to_id = ast_channel_redirecting_effective_to(ast); + ast_copy_string(bc->redirecting.from.name, - S_COR(ast_channel_redirecting(ast)->from.name.valid, ast_channel_redirecting(ast)->from.name.str, ""), + S_COR(from_id.name.valid, from_id.name.str, ""), sizeof(bc->redirecting.from.name)); - if (ast_channel_redirecting(ast)->from.number.valid) { - ast_copy_string(bc->redirecting.from.number, S_OR(ast_channel_redirecting(ast)->from.number.str, ""), + if (from_id.number.valid) { + ast_copy_string(bc->redirecting.from.number, S_OR(from_id.number.str, ""), sizeof(bc->redirecting.from.number)); - bc->redirecting.from.presentation = ast_to_misdn_pres(ast_channel_redirecting(ast)->from.number.presentation); - bc->redirecting.from.screening = ast_to_misdn_screen(ast_channel_redirecting(ast)->from.number.presentation); - bc->redirecting.from.number_type = ast_to_misdn_ton(ast_channel_redirecting(ast)->from.number.plan); - bc->redirecting.from.number_plan = ast_to_misdn_plan(ast_channel_redirecting(ast)->from.number.plan); + bc->redirecting.from.presentation = ast_to_misdn_pres(from_id.number.presentation); + bc->redirecting.from.screening = ast_to_misdn_screen(from_id.number.presentation); + bc->redirecting.from.number_type = ast_to_misdn_ton(from_id.number.plan); + bc->redirecting.from.number_plan = ast_to_misdn_plan(from_id.number.plan); } else { bc->redirecting.from.number[0] = '\0'; bc->redirecting.from.presentation = 0;/* Allowed */ @@ -6355,15 +6366,15 @@ static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct as } ast_copy_string(bc->redirecting.to.name, - S_COR(ast_channel_redirecting(ast)->to.name.valid, ast_channel_redirecting(ast)->to.name.str, ""), + S_COR(to_id.name.valid, to_id.name.str, ""), sizeof(bc->redirecting.to.name)); - if (ast_channel_redirecting(ast)->to.number.valid) { - ast_copy_string(bc->redirecting.to.number, S_OR(ast_channel_redirecting(ast)->to.number.str, ""), + if (to_id.number.valid) { + ast_copy_string(bc->redirecting.to.number, S_OR(to_id.number.str, ""), sizeof(bc->redirecting.to.number)); - bc->redirecting.to.presentation = ast_to_misdn_pres(ast_channel_redirecting(ast)->to.number.presentation); - bc->redirecting.to.screening = ast_to_misdn_screen(ast_channel_redirecting(ast)->to.number.presentation); - bc->redirecting.to.number_type = ast_to_misdn_ton(ast_channel_redirecting(ast)->to.number.plan); - bc->redirecting.to.number_plan = ast_to_misdn_plan(ast_channel_redirecting(ast)->to.number.plan); + bc->redirecting.to.presentation = ast_to_misdn_pres(to_id.number.presentation); + bc->redirecting.to.screening = ast_to_misdn_screen(to_id.number.presentation); + bc->redirecting.to.number_type = ast_to_misdn_ton(to_id.number.plan); + bc->redirecting.to.number_plan = ast_to_misdn_plan(to_id.number.plan); } else { bc->redirecting.to.number[0] = '\0'; bc->redirecting.to.presentation = 0;/* Allowed */ @@ -6595,6 +6606,8 @@ static int misdn_call(struct ast_channel *ast, const char *dest, int timeout) } else #endif /* defined(AST_MISDN_ENHANCEMENTS) */ { + struct ast_party_id connected_id = ast_channel_connected_effective_id(ast); + /* * dest is ---v * Dial(mISDN/g:group_name[/extension[/options]]) @@ -6616,15 +6629,15 @@ static int misdn_call(struct ast_channel *ast, const char *dest, int timeout) ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number)); if (ast_strlen_zero(newbc->caller.name) - && ast_channel_connected(ast)->id.name.valid - && !ast_strlen_zero(ast_channel_connected(ast)->id.name.str)) { - ast_copy_string(newbc->caller.name, ast_channel_connected(ast)->id.name.str, sizeof(newbc->caller.name)); + && connected_id.name.valid + && !ast_strlen_zero(connected_id.name.str)) { + ast_copy_string(newbc->caller.name, connected_id.name.str, sizeof(newbc->caller.name)); chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number); } if (ast_strlen_zero(newbc->caller.number) - && ast_channel_connected(ast)->id.number.valid - && !ast_strlen_zero(ast_channel_connected(ast)->id.number.str)) { - ast_copy_string(newbc->caller.number, ast_channel_connected(ast)->id.number.str, sizeof(newbc->caller.number)); + && connected_id.number.valid + && !ast_strlen_zero(connected_id.number.str)) { + ast_copy_string(newbc->caller.number, connected_id.number.str, sizeof(newbc->caller.number)); chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number); } @@ -6638,9 +6651,9 @@ static int misdn_call(struct ast_channel *ast, const char *dest, int timeout) misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type)); if (number_type < 0) { - if (ast_channel_connected(ast)->id.number.valid) { - newbc->caller.number_type = ast_to_misdn_ton(ast_channel_connected(ast)->id.number.plan); - newbc->caller.number_plan = ast_to_misdn_plan(ast_channel_connected(ast)->id.number.plan); + if (connected_id.number.valid) { + newbc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan); + newbc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan); } else { newbc->caller.number_type = NUMTYPE_UNKNOWN; newbc->caller.number_plan = NUMPLAN_ISDN; @@ -8605,8 +8618,16 @@ static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list ast_party_connected_line_init(&target_colp); ast_party_connected_line_copy(&target_colp, ast_channel_connected(target)); + + /* Reset any earlier private connected id representation */ + ast_party_id_reset(&target_colp.priv); + ast_party_connected_line_init(&transferee_colp); ast_party_connected_line_copy(&transferee_colp, ast_channel_connected(held_ch->ast)); + + /* Reset any earlier private connected id representation*/ + ast_party_id_reset(&transferee_colp.priv); + held_ch->hold.state = MISDN_HOLD_TRANSFER; /* @@ -9283,11 +9304,25 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel bc->div_leg_3_rx_wanted = 0; if (ch && ch->ast) { + struct ast_party_redirecting redirecting; + ast_channel_redirecting(ch->ast)->to.number.presentation = bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator ? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED : AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED; - ast_channel_queue_redirecting_update(ch->ast, ast_channel_redirecting(ch->ast), NULL); + ast_party_redirecting_init(&redirecting); + ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast)); + + /* + * Reset any earlier private redirecting id representations and + * make sure that it is invalidated at the remote end. + */ + ast_party_id_reset(&redirecting.priv_orig); + ast_party_id_reset(&redirecting.priv_from); + ast_party_id_reset(&redirecting.priv_to); + + ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL); + ast_party_redirecting_free(&redirecting); } } break; @@ -10518,9 +10553,23 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) bc->div_leg_3_rx_wanted = 0; if (ch->ast) { + struct ast_party_redirecting redirecting; + ast_channel_redirecting(ch->ast)->to.number.presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED; - ast_channel_queue_redirecting_update(ch->ast, ast_channel_redirecting(ch->ast), NULL); + ast_party_redirecting_init(&redirecting); + ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast)); + + /* + * Reset any earlier private redirecting id representations and + * make sure that it is invalidated at the remote end. + */ + ast_party_id_reset(&redirecting.priv_orig); + ast_party_id_reset(&redirecting.priv_from); + ast_party_id_reset(&redirecting.priv_to); + + ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL); + ast_party_redirecting_free(&redirecting); } } #endif /* defined(AST_MISDN_ENHANCEMENTS) */ @@ -10939,6 +10988,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) bc->redirecting.to_changed = 0; break; case mISDN_NOTIFY_CODE_CALL_IS_DIVERTING: + { + struct ast_party_redirecting redirecting; + if (!bc->redirecting.to_changed) { break; } @@ -10957,8 +11009,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; } misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag); - ast_channel_queue_redirecting_update(ch->ast, ast_channel_redirecting(ch->ast), NULL); + ast_party_redirecting_init(&redirecting); + ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast)); + + /* + * Reset any earlier private redirecting id representations and + * make sure that it is invalidated at the remote end. + */ + ast_party_id_reset(&redirecting.priv_orig); + ast_party_id_reset(&redirecting.priv_from); + ast_party_id_reset(&redirecting.priv_to); + + ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL); + ast_party_redirecting_free(&redirecting); break; + } case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING: /* * It would be preferable to update the connected line information diff --git a/channels/chan_sip.c b/channels/chan_sip.c index eaaffebae..7569bba11 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -6009,6 +6009,9 @@ static int sip_call(struct ast_channel *ast, const char *dest, int timeout) connected.id.name.presentation = p->callingpres; } if (update_connected.id.number || update_connected.id.name) { + /* Invalidate any earlier private connected id representation */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = (char *) p->cid_tag; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(ast, &connected, &update_connected); @@ -11872,25 +11875,28 @@ static int add_rpid(struct sip_request *req, struct sip_pvt *p) char tmp2[256]; char *lid_num = NULL; char *lid_name = NULL; - int lid_pres; + int lid_pres = AST_PRES_NUMBER_NOT_AVAILABLE; const char *fromdomain; const char *privacy = NULL; const char *screen = NULL; const char *anonymous_string = "\"Anonymous\" <sip:anonymous@anonymous.invalid>"; + struct ast_party_id connected_id; if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) { return 0; } - if (p->owner && ast_channel_connected(p->owner)->id.number.valid - && ast_channel_connected(p->owner)->id.number.str) { - lid_num = ast_channel_connected(p->owner)->id.number.str; - } - if (p->owner && ast_channel_connected(p->owner)->id.name.valid - && ast_channel_connected(p->owner)->id.name.str) { - lid_name = ast_channel_connected(p->owner)->id.name.str; + if (p->owner) { + connected_id = ast_channel_connected_effective_id(p->owner); + + if (connected_id.number.valid) { + lid_num = connected_id.number.str; + } + if (connected_id.name.valid) { + lid_name = connected_id.name.str; + } + lid_pres = ast_party_id_presentation(&connected_id); } - lid_pres = (p->owner) ? ast_party_id_presentation(&ast_channel_connected(p->owner)->id) : AST_PRES_NUMBER_NOT_AVAILABLE; if (ast_strlen_zero(lid_num)) return 0; @@ -13079,6 +13085,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho int ourport; int cid_has_name = 1; int cid_has_num = 1; + struct ast_party_id connected_id; if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) { const char *s = p->username; /* being a string field, cannot be NULL */ @@ -13104,9 +13111,15 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho d = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip)); if (p->owner) { - if ((ast_party_id_presentation(&ast_channel_connected(p->owner)->id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) { - l = ast_channel_connected(p->owner)->id.number.valid ? ast_channel_connected(p->owner)->id.number.str : NULL; - n = ast_channel_connected(p->owner)->id.name.valid ? ast_channel_connected(p->owner)->id.name.str : NULL; + connected_id = ast_channel_connected_effective_id(p->owner); + + if ((ast_party_id_presentation(&connected_id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) { + if (connected_id.number.valid) { + l = connected_id.number.str; + } + if (connected_id.name.valid) { + n = connected_id.name.str; + } } else { /* Even if we are using RPID, we shouldn't leak information in the From if the user wants * their callerid restricted */ @@ -13260,8 +13273,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho */ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt) { - const char *diverting_number; - const char *diverting_name; + struct ast_party_id diverting_from; const char *reason; char header_text[256]; @@ -13274,23 +13286,22 @@ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt) return; } - diverting_number = ast_channel_redirecting(pvt->owner)->from.number.str; - if (!ast_channel_redirecting(pvt->owner)->from.number.valid - || ast_strlen_zero(diverting_number)) { + diverting_from = ast_channel_redirecting_effective_from(pvt->owner); + if (!diverting_from.number.valid + || ast_strlen_zero(diverting_from.number.str)) { return; } reason = sip_reason_code_to_str(ast_channel_redirecting(pvt->owner)->reason); /* We at least have a number to place in the Diversion header, which is enough */ - diverting_name = ast_channel_redirecting(pvt->owner)->from.name.str; - if (!ast_channel_redirecting(pvt->owner)->from.name.valid - || ast_strlen_zero(diverting_name)) { - snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, + if (!diverting_from.name.valid + || ast_strlen_zero(diverting_from.name.str)) { + snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_from.number.str, ast_sockaddr_stringify_host_remote(&pvt->ourip), reason); } else { snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", - diverting_name, diverting_number, + diverting_from.name.str, diverting_from.number.str, ast_sockaddr_stringify_host_remote(&pvt->ourip), reason); } @@ -14195,19 +14206,20 @@ static void update_redirecting(struct sip_pvt *p, const void *data, size_t datal /*! \brief Notify peer that the connected line has changed */ static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen) { + struct ast_party_id connected_id = ast_channel_connected_effective_id(p->owner); if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) { return; } - if (!ast_channel_connected(p->owner)->id.number.valid - || ast_strlen_zero(ast_channel_connected(p->owner)->id.number.str)) { + if (!connected_id.number.valid + || ast_strlen_zero(connected_id.number.str)) { return; } append_history(p, "ConnectedLine", "%s party is now %s <%s>", ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called", - S_COR(ast_channel_connected(p->owner)->id.name.valid, ast_channel_connected(p->owner)->id.name.str, ""), - S_COR(ast_channel_connected(p->owner)->id.number.valid, ast_channel_connected(p->owner)->id.number.str, "")); + S_COR(connected_id.name.valid, connected_id.name.str, ""), + S_COR(connected_id.number.valid, connected_id.number.str, "")); if (ast_channel_state(p->owner) == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) { struct sip_request req; @@ -21789,6 +21801,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest connected.id.name.str = (char *) p->cid_name; connected.id.name.presentation = p->callingpres; + /* Invalidate any earlier private connected id representation */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = (char *) p->cid_tag; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(p->owner, &connected, @@ -21832,6 +21847,12 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest memset(&update_redirecting, 0, sizeof(update_redirecting)); change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); + + /* Invalidate any earlier private redirecting id representations */ + ast_set_party_id_all(&update_redirecting.priv_orig); + ast_set_party_id_all(&update_redirecting.priv_from); + ast_set_party_id_all(&update_redirecting.priv_to); + ast_channel_queue_redirecting_update(p->owner, &redirecting, &update_redirecting); ast_party_redirecting_free(&redirecting); @@ -21867,6 +21888,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest connected.id.name.str = (char *) p->cid_name; connected.id.name.presentation = p->callingpres; + /* Invalidate any earlier private connected id representation */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = (char *) p->cid_tag; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(p->owner, &connected, @@ -21936,6 +21960,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest connected.id.name.presentation = p->callingpres; } if (update_connected.id.number || update_connected.id.name) { + /* Invalidate any earlier private connected id representation */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = (char *) p->cid_tag; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(p->owner, &connected, @@ -24010,6 +24037,9 @@ static int handle_request_update(struct sip_pvt *p, struct sip_request *req) connected.id.name.str = (char *) p->cid_name; connected.id.name.presentation = p->callingpres; + /* Invalidate any earlier private connected id representation */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = (char *) p->cid_tag; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; ast_channel_queue_connected_line_update(p->owner, &connected, &update_connected); @@ -24360,6 +24390,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str connected.id.name.str = (char *) p->cid_name; connected.id.name.presentation = p->callingpres; + /* Invalidate any earlier private connected id representation */ + ast_set_party_id_all(&update_connected.priv); + connected.id.tag = (char *) p->cid_tag; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; ast_channel_queue_connected_line_update(p->owner, &connected, @@ -25054,6 +25087,9 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual * ast_party_connected_line_copy(&connected_to_transferee, ast_channel_connected(current->chan1)); /* No need to lock target.chan1 here since it was locked in get_sip_pvt_byid_locked */ ast_party_connected_line_copy(&connected_to_target, ast_channel_connected(target.chan1)); + /* Reset any earlier private connected id representation */ + ast_party_id_reset(&connected_to_transferee.priv); + ast_party_id_reset(&connected_to_target.priv); connected_to_target.source = connected_to_transferee.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; res = attempt_transfer(current, &target); if (res) { diff --git a/channels/sig_pri.c b/channels/sig_pri.c index 902c5098d..2840c3b28 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -906,12 +906,15 @@ static void sig_pri_redirecting_update(struct sig_pri_chan *pvt, struct ast_chan { struct pri_party_redirecting pri_redirecting; const struct ast_party_redirecting *ast_redirecting; + struct ast_party_id redirecting_from = ast_channel_redirecting_effective_from(ast); + struct ast_party_id redirecting_to = ast_channel_redirecting_effective_to(ast); + struct ast_party_id redirecting_orig = ast_channel_redirecting_effective_orig(ast); memset(&pri_redirecting, 0, sizeof(pri_redirecting)); ast_redirecting = ast_channel_redirecting(ast); - sig_pri_party_id_from_ast(&pri_redirecting.from, &ast_redirecting->from); - sig_pri_party_id_from_ast(&pri_redirecting.to, &ast_redirecting->to); - sig_pri_party_id_from_ast(&pri_redirecting.orig_called, &ast_redirecting->orig); + sig_pri_party_id_from_ast(&pri_redirecting.from, &redirecting_from); + sig_pri_party_id_from_ast(&pri_redirecting.to, &redirecting_to); + sig_pri_party_id_from_ast(&pri_redirecting.orig_called, &redirecting_orig); pri_redirecting.count = ast_redirecting->count; pri_redirecting.orig_reason = ast_to_pri_reason(ast_redirecting->orig_reason); pri_redirecting.reason = ast_to_pri_reason(ast_redirecting->reason); @@ -4247,6 +4250,12 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev ast_channel_set_redirecting(owner, &ast_redirecting, NULL); if (event_id != PRI_EVENT_RING) { /* This redirection was not from a SETUP message. */ + + /* Invalidate any earlier private redirecting id representations */ + ast_party_id_invalidate(&ast_redirecting.priv_orig); + ast_party_id_invalidate(&ast_redirecting.priv_from); + ast_party_id_invalidate(&ast_redirecting.priv_to); + ast_channel_queue_redirecting_update(owner, &ast_redirecting, NULL); } ast_party_redirecting_free(&ast_redirecting); @@ -7726,10 +7735,11 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd ); struct ast_flags opts; char *opt_args[OPT_ARG_ARRAY_SIZE]; + struct ast_party_id connected_id = ast_channel_connected_effective_id(ast); ast_debug(1, "CALLER NAME: %s NUM: %s\n", - S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""), - S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, "")); + S_COR(connected_id.name.valid, connected_id.name.str, ""), + S_COR(connected_id.number.valid, connected_id.number.str, "")); if (!p->pri) { ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel); @@ -7785,14 +7795,14 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd l = NULL; n = NULL; if (!p->hidecallerid) { - if (ast_channel_connected(ast)->id.number.valid) { + if (connected_id.number.valid) { /* If we get to the end of this loop without breaking, there's no * calleridnum. This is done instead of testing for "unknown" or * the thousands of other ways that the calleridnum could be * invalid. */ - for (l = ast_channel_connected(ast)->id.number.str; l && *l; l++) { + for (l = connected_id.number.str; l && *l; l++) { if (strchr("0123456789", *l)) { - l = ast_channel_connected(ast)->id.number.str; + l = connected_id.number.str; break; } } @@ -7800,7 +7810,7 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd l = NULL; } if (!p->hidecalleridname) { - n = ast_channel_connected(ast)->id.name.valid ? ast_channel_connected(ast)->id.name.str : NULL; + n = connected_id.name.valid ? connected_id.name.str : NULL; } } @@ -8016,7 +8026,7 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd } } else if (prilocaldialplan == -1) { /* Use the numbering plan passed in. */ - prilocaldialplan = ast_channel_connected(ast)->id.number.plan; + prilocaldialplan = connected_id.number.plan; } if (l != NULL) { while (*l > '9' && *l != '*' && *l != '#') { @@ -8075,14 +8085,14 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, const char *rd } } pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, - p->use_callingpres ? ast_channel_connected(ast)->id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); + p->use_callingpres ? connected_id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); #if defined(HAVE_PRI_SUBADDR) - if (ast_channel_connected(ast)->id.subaddress.valid) { + if (connected_id.subaddress.valid) { struct pri_party_subaddress subaddress; memset(&subaddress, 0, sizeof(subaddress)); - sig_pri_party_subaddress_from_ast(&subaddress, &ast_channel_connected(ast)->id.subaddress); + sig_pri_party_subaddress_from_ast(&subaddress, &connected_id.subaddress); pri_sr_set_caller_subaddress(sr, &subaddress); } #endif /* defined(HAVE_PRI_SUBADDR) */ @@ -8313,6 +8323,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi int dialplan; int prefix_strip; int colp_allowed = 0; + struct ast_party_id connected_id = ast_channel_connected_effective_id(chan); pri_grab(p, p->pri); @@ -8341,7 +8352,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi } memset(&connected, 0, sizeof(connected)); - sig_pri_party_id_from_ast(&connected.id, &ast_channel_connected(chan)->id); + sig_pri_party_id_from_ast(&connected.id, &connected_id); /* Determine the connected line numbering plan to actually use. */ switch (p->pri->cpndialplan) { diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c index f15e3676f..789575399 100644 --- a/funcs/func_callerid.c +++ b/funcs/func_callerid.c @@ -103,6 +103,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name = "subaddr-type" /> <enum name = "subaddr-odd" /> <enum name = "tag" /> + <enum name = "priv-all" /> + <enum name = "priv-name" /> + <enum name = "priv-name-valid" /> + <enum name = "priv-name-charset" /> + <enum name = "priv-name-pres" /> + <enum name = "priv-num" /> + <enum name = "priv-num-valid" /> + <enum name = "priv-num-plan" /> + <enum name = "priv-num-pres" /> + <enum name = "priv-subaddr" /> + <enum name = "priv-subaddr-valid" /> + <enum name = "priv-subaddr-type" /> + <enum name = "priv-subaddr-odd" /> + <enum name = "priv-tag" /> <enum name = "ANI-all" /> <enum name = "ANI-name" /> <enum name = "ANI-name-valid" /> @@ -209,6 +223,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name = "subaddr-type" /> <enum name = "subaddr-odd" /> <enum name = "tag" /> + <enum name = "priv-all" /> + <enum name = "priv-name" /> + <enum name = "priv-name-valid" /> + <enum name = "priv-name-charset" /> + <enum name = "priv-name-pres" /> + <enum name = "priv-num" /> + <enum name = "priv-num-valid" /> + <enum name = "priv-num-plan" /> + <enum name = "priv-num-pres" /> + <enum name = "priv-subaddr" /> + <enum name = "priv-subaddr-valid" /> + <enum name = "priv-subaddr-type" /> + <enum name = "priv-subaddr-odd" /> + <enum name = "priv-tag" /> </enumlist> </parameter> <parameter name="i"> @@ -285,6 +313,48 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <enum name = "to-subaddr-type" /> <enum name = "to-subaddr-odd" /> <enum name = "to-tag" /> + <enum name = "priv-orig-all" /> + <enum name = "priv-orig-name" /> + <enum name = "priv-orig-name-valid" /> + <enum name = "priv-orig-name-charset" /> + <enum name = "priv-orig-name-pres" /> + <enum name = "priv-orig-num" /> + <enum name = "priv-orig-num-valid" /> + <enum name = "priv-orig-num-plan" /> + <enum name = "priv-orig-num-pres" /> + <enum name = "priv-orig-subaddr" /> + <enum name = "priv-orig-subaddr-valid" /> + <enum name = "priv-orig-subaddr-type" /> + <enum name = "priv-orig-subaddr-odd" /> + <enum name = "priv-orig-tag" /> + <enum name = "priv-from-all" /> + <enum name = "priv-from-name" /> + <enum name = "priv-from-name-valid" /> + <enum name = "priv-from-name-charset" /> + <enum name = "priv-from-name-pres" /> + <enum name = "priv-from-num" /> + <enum name = "priv-from-num-valid" /> + <enum name = "priv-from-num-plan" /> + <enum name = "priv-from-num-pres" /> + <enum name = "priv-from-subaddr" /> + <enum name = "priv-from-subaddr-valid" /> + <enum name = "priv-from-subaddr-type" /> + <enum name = "priv-from-subaddr-odd" /> + <enum name = "priv-from-tag" /> + <enum name = "priv-to-all" /> + <enum name = "priv-to-name" /> + <enum name = "priv-to-name-valid" /> + <enum name = "priv-to-name-charset" /> + <enum name = "priv-to-name-pres" /> + <enum name = "priv-to-num" /> + <enum name = "priv-to-num-valid" /> + <enum name = "priv-to-num-plan" /> + <enum name = "priv-to-num-pres" /> + <enum name = "priv-to-subaddr" /> + <enum name = "priv-to-subaddr-valid" /> + <enum name = "priv-to-subaddr-type" /> + <enum name = "priv-to-subaddr-odd" /> + <enum name = "priv-to-tag" /> <enum name = "reason" /> <enum name = "count" /> </enumlist> @@ -997,6 +1067,17 @@ static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data); break; } + } else if (!strcasecmp("priv", member.argv[0])) { + status = party_id_read(buf, len, member.argc - 1, member.argv + 1, + &ast_channel_caller(chan)->priv); + switch (status) { + case ID_FIELD_VALID: + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data); + break; + } } else { status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_caller(chan)->id); switch (status) { @@ -1159,6 +1240,23 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, break; } ast_party_caller_free(&caller); + } else if (!strcasecmp("priv", member.argv[0])) { + ast_party_caller_set_init(&caller, ast_channel_caller(chan)); + status = party_id_write(&caller.priv, member.argc - 1, member.argv + 1, value); + switch (status) { + case ID_FIELD_VALID: + ast_party_caller_set(ast_channel_caller(chan), &caller, NULL); + if (ast_channel_cdr(chan)) { + ast_cdr_setcid(ast_channel_cdr(chan), chan); + } + break; + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data); + break; + } + ast_party_caller_free(&caller); } else { ast_party_caller_set_init(&caller, ast_channel_caller(chan)); status = party_id_write(&caller.id, member.argc, member.argv, value); @@ -1199,6 +1297,7 @@ static int connectedline_read(struct ast_channel *chan, const char *cmd, char *d { struct ast_party_members member; char *read_what; + enum ID_FIELD_STATUS status; /* Ensure that the buffer is empty */ *buf = 0; @@ -1218,8 +1317,18 @@ static int connectedline_read(struct ast_channel *chan, const char *cmd, char *d if (member.argc == 1 && !strcasecmp("source", member.argv[0])) { ast_copy_string(buf, ast_connected_line_source_name(ast_channel_connected(chan)->source), len); + } else if (!strcasecmp("priv", member.argv[0])) { + status = party_id_read(buf, len, member.argc - 1, member.argv + 1, + &ast_channel_connected(chan)->priv); + switch (status) { + case ID_FIELD_VALID: + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data); + break; + } } else { - enum ID_FIELD_STATUS status; status = party_id_read(buf, len, member.argc, member.argv, &ast_channel_connected(chan)->id); switch (status) { case ID_FIELD_VALID: @@ -1258,6 +1367,7 @@ static int connectedline_write(struct ast_channel *chan, const char *cmd, char * struct ast_party_members member; struct ast_flags opts; char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE]; + enum ID_FIELD_STATUS status; if (!value || !chan) { return -1; @@ -1312,8 +1422,20 @@ static int connectedline_write(struct ast_channel *chan, const char *cmd, char * connected.source = source; set_it(chan, &connected, NULL); } + } else if (!strcasecmp("priv", member.argv[0])) { + status = party_id_write(&connected.priv, member.argc - 1, member.argv + 1, value); + switch (status) { + case ID_FIELD_VALID: + set_it(chan, &connected, NULL); + break; + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data); + break; + } + ast_party_connected_line_free(&connected); } else { - enum ID_FIELD_STATUS status; status = party_id_write(&connected.id, member.argc, member.argv, value); switch (status) { case ID_FIELD_VALID: @@ -1418,6 +1540,43 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat ast_copy_string(buf, ast_redirecting_reason_name(ast_redirecting->reason), len); } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) { snprintf(buf, len, "%d", ast_redirecting->count); + } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) { + if (!strcasecmp("orig", member.argv[1])) { + status = party_id_read(buf, len, member.argc - 2, member.argv + 2, + &ast_redirecting->priv_orig); + switch (status) { + case ID_FIELD_VALID: + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + break; + } + } else if (!strcasecmp("from", member.argv[1])) { + status = party_id_read(buf, len, member.argc - 2, member.argv + 2, + &ast_redirecting->priv_from); + switch (status) { + case ID_FIELD_VALID: + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + break; + } + } else if (!strcasecmp("to", member.argv[1])) { + status = party_id_read(buf, len, member.argc - 2, member.argv + 2, + &ast_redirecting->priv_to); + switch (status) { + case ID_FIELD_VALID: + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + break; + } + } else { + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + } } else { ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); } @@ -1598,6 +1757,51 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da } else { ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val); } + } else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) { + if (!strcasecmp("orig", member.argv[1])) { + status = party_id_write(&redirecting.priv_orig, member.argc - 2, member.argv + 2, + value); + switch (status) { + case ID_FIELD_VALID: + set_it(chan, &redirecting, NULL); + break; + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + break; + } + ast_party_redirecting_free(&redirecting); + } else if (!strcasecmp("from", member.argv[1])) { + status = party_id_write(&redirecting.priv_from, member.argc - 2, member.argv + 2, + value); + switch (status) { + case ID_FIELD_VALID: + set_it(chan, &redirecting, NULL); + break; + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + break; + } + ast_party_redirecting_free(&redirecting); + } else if (!strcasecmp("to", member.argv[1])) { + status = party_id_write(&redirecting.priv_to, member.argc - 2, member.argv + 2, value); + switch (status) { + case ID_FIELD_VALID: + set_it(chan, &redirecting, NULL); + break; + case ID_FIELD_INVALID: + break; + default: + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + break; + } + ast_party_redirecting_free(&redirecting); + } else { + ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); + } } else { ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data); } diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index c9d13187c..abfe18139 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -380,6 +380,9 @@ struct ast_party_caller { */ struct ast_party_id ani; + /*! \brief Private caller party ID */ + struct ast_party_id priv; + /*! \brief Automatic Number Identification 2 (Info Digits) */ int ani2; }; @@ -393,6 +396,8 @@ struct ast_set_party_caller { struct ast_set_party_id id; /*! What ANI id information to set. */ struct ast_set_party_id ani; + /*! What private caller id information to set. */ + struct ast_set_party_id priv; }; /*! @@ -413,6 +418,9 @@ struct ast_party_connected_line { */ struct ast_party_id ani; + /*! \brief Private connected party ID */ + struct ast_party_id priv; + /*! * \brief Automatic Number Identification 2 (Info Digits) * \note Not really part of connected line data but needed to @@ -437,6 +445,8 @@ struct ast_set_party_connected_line { struct ast_set_party_id id; /*! What ANI id information to set. */ struct ast_set_party_id ani; + /*! What private connected line id information to set. */ + struct ast_set_party_id priv; }; /*! @@ -458,6 +468,15 @@ struct ast_party_redirecting { /*! \brief Call is redirecting to a new party (Sent to the caller) */ struct ast_party_id to; + /*! \brief Who originally redirected the call (Sent to the party the call is redirected toward) - private representation */ + struct ast_party_id priv_orig; + + /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) - private representation */ + struct ast_party_id priv_from; + + /*! \brief Call is redirecting to a new party (Sent to the caller) - private representation */ + struct ast_party_id priv_to; + /*! \brief Number of times the call was redirected */ int count; @@ -479,6 +498,12 @@ struct ast_set_party_redirecting { struct ast_set_party_id from; /*! What redirecting-to id information to set. */ struct ast_set_party_id to; + /*! What private redirecting-orig id information to set. */ + struct ast_set_party_id priv_orig; + /*! What private redirecting-from id information to set. */ + struct ast_set_party_id priv_from; + /*! What private redirecting-to id information to set. */ + struct ast_set_party_id priv_to; }; /*! @@ -2864,6 +2889,16 @@ void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct as void ast_party_subaddress_free(struct ast_party_subaddress *doomed); /*! + * \brief Set the update marker to update all information of a corresponding party id. + * \since 11.0 + * + * \param update_id The update marker for a corresponding party id. + * + * \return Nothing + */ +void ast_set_party_id_all(struct ast_set_party_id *update_id); + +/*! * \brief Initialize the given party id structure. * \since 1.8 * @@ -2936,6 +2971,66 @@ void ast_party_id_free(struct ast_party_id *doomed); int ast_party_id_presentation(const struct ast_party_id *id); /*! + * \brief Invalidate all components of the given party id. + * \since 11.0 + * + * \param id The party id to invalidate. + * + * \return Nothing + */ +void ast_party_id_invalidate(struct ast_party_id *id); + +/*! + * \brief Destroy and initialize the given party id structure. + * \since 11.0 + * + * \param id The party id to reset. + * + * \return Nothing + */ +void ast_party_id_reset(struct ast_party_id *id); + +/*! + * \brief Merge a given party id into another given party id. + * \since 11.0 + * + * \details + * This function will generate an effective party id. + * + * Each party id component of the party id 'base' is overwritten + * by components of the party id 'overlay' if the overlay + * component is marked as valid. However the component 'tag' of + * the base party id remains untouched. + * + * \param base The party id which is merged. + * \param overlay The party id which is used to merge into. + * + * \return The merged party id as a struct, not as a pointer. + * \note The merged party id returned is a shallow copy and must not be freed. + */ +struct ast_party_id ast_party_id_merge(struct ast_party_id *base, struct ast_party_id *overlay); + +/*! + * \brief Copy a merge of a given party id into another given party id to a given destination party id. + * \since 11.0 + * + * \details + * Each party id component of the party id 'base' is overwritten by components + * of the party id 'overlay' if the 'overlay' component is marked as valid. + * However the component 'tag' of the 'base' party id remains untouched. + * The result is copied into the given party id 'dest'. + * + * \note The resulting merged party id is a real copy and has to be freed. + * + * \param dest The resulting merged party id. + * \param base The party id which is merged. + * \param overlay The party id which is used to merge into. + * + * \return Nothing + */ +void ast_party_id_merge_copy(struct ast_party_id *dest, struct ast_party_id *base, struct ast_party_id *overlay); + +/*! * \brief Initialize the given dialed structure. * \since 1.8 * @@ -3778,8 +3873,12 @@ struct ast_frame *ast_channel_dtmff(struct ast_channel *chan); struct ast_jb *ast_channel_jb(struct ast_channel *chan); struct ast_party_caller *ast_channel_caller(struct ast_channel *chan); struct ast_party_connected_line *ast_channel_connected(struct ast_channel *chan); +struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan); struct ast_party_dialed *ast_channel_dialed(struct ast_channel *chan); struct ast_party_redirecting *ast_channel_redirecting(struct ast_channel *chan); +struct ast_party_id ast_channel_redirecting_effective_orig(struct ast_channel *chan); +struct ast_party_id ast_channel_redirecting_effective_from(struct ast_channel *chan); +struct ast_party_id ast_channel_redirecting_effective_to(struct ast_channel *chan); struct timeval *ast_channel_dtmf_tv(struct ast_channel *chan); struct timeval *ast_channel_whentohangup(struct ast_channel *chan); struct varshead *ast_channel_varshead(struct ast_channel *chan); diff --git a/main/channel.c b/main/channel.c index d5f1d31c1..bccba2e14 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1891,6 +1891,13 @@ void ast_party_subaddress_free(struct ast_party_subaddress *doomed) doomed->str = NULL; } +void ast_set_party_id_all(struct ast_set_party_id *update_id) +{ + update_id->name = 1; + update_id->number = 1; + update_id->subaddress = 1; +} + void ast_party_id_init(struct ast_party_id *init) { ast_party_name_init(&init->name); @@ -2023,6 +2030,45 @@ int ast_party_id_presentation(const struct ast_party_id *id) return number_value | number_screening; } +void ast_party_id_invalidate(struct ast_party_id *id) +{ + id->name.valid = 0; + id->number.valid = 0; + id->subaddress.valid = 0; +} + +void ast_party_id_reset(struct ast_party_id *id) +{ + ast_party_id_free(id); + ast_party_id_init(id); +} + +struct ast_party_id ast_party_id_merge(struct ast_party_id *base, struct ast_party_id *overlay) +{ + struct ast_party_id merged; + + merged = *base; + if (overlay->name.valid) { + merged.name = overlay->name; + } + if (overlay->number.valid) { + merged.number = overlay->number; + } + if (overlay->subaddress.valid) { + merged.subaddress = overlay->subaddress; + } + /* Note the actual structure is returned and not a pointer to it! */ + return merged; +} + +void ast_party_id_merge_copy(struct ast_party_id *dest, struct ast_party_id *base, struct ast_party_id *overlay) +{ + struct ast_party_id merged; + + merged = ast_party_id_merge(base, overlay); + ast_party_id_copy(dest, &merged); +} + void ast_party_dialed_init(struct ast_party_dialed *init) { init->number.str = NULL; @@ -2077,6 +2123,7 @@ void ast_party_caller_init(struct ast_party_caller *init) { ast_party_id_init(&init->id); ast_party_id_init(&init->ani); + ast_party_id_init(&init->priv); init->ani2 = 0; } @@ -2089,6 +2136,7 @@ void ast_party_caller_copy(struct ast_party_caller *dest, const struct ast_party ast_party_id_copy(&dest->id, &src->id); ast_party_id_copy(&dest->ani, &src->ani); + ast_party_id_copy(&dest->priv, &src->priv); dest->ani2 = src->ani2; } @@ -2096,6 +2144,7 @@ void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_p { ast_party_id_set_init(&init->id, &guide->id); ast_party_id_set_init(&init->ani, &guide->ani); + ast_party_id_set_init(&init->priv, &guide->priv); init->ani2 = guide->ani2; } @@ -2103,6 +2152,7 @@ void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_ { ast_party_id_set(&dest->id, &src->id, update ? &update->id : NULL); ast_party_id_set(&dest->ani, &src->ani, update ? &update->ani : NULL); + ast_party_id_set(&dest->priv, &src->priv, update ? &update->priv : NULL); dest->ani2 = src->ani2; } @@ -2110,12 +2160,14 @@ void ast_party_caller_free(struct ast_party_caller *doomed) { ast_party_id_free(&doomed->id); ast_party_id_free(&doomed->ani); + ast_party_id_free(&doomed->priv); } void ast_party_connected_line_init(struct ast_party_connected_line *init) { ast_party_id_init(&init->id); ast_party_id_init(&init->ani); + ast_party_id_init(&init->priv); init->ani2 = 0; init->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; } @@ -2129,6 +2181,7 @@ void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const ast_party_id_copy(&dest->id, &src->id); ast_party_id_copy(&dest->ani, &src->ani); + ast_party_id_copy(&dest->priv, &src->priv); dest->ani2 = src->ani2; dest->source = src->source; } @@ -2137,6 +2190,7 @@ void ast_party_connected_line_set_init(struct ast_party_connected_line *init, co { ast_party_id_set_init(&init->id, &guide->id); ast_party_id_set_init(&init->ani, &guide->ani); + ast_party_id_set_init(&init->priv, &guide->priv); init->ani2 = guide->ani2; init->source = guide->source; } @@ -2145,6 +2199,7 @@ void ast_party_connected_line_set(struct ast_party_connected_line *dest, const s { ast_party_id_set(&dest->id, &src->id, update ? &update->id : NULL); ast_party_id_set(&dest->ani, &src->ani, update ? &update->ani : NULL); + ast_party_id_set(&dest->priv, &src->priv, update ? &update->priv : NULL); dest->ani2 = src->ani2; dest->source = src->source; } @@ -2153,6 +2208,7 @@ void ast_party_connected_line_collect_caller(struct ast_party_connected_line *co { connected->id = caller->id; connected->ani = caller->ani; + connected->priv = caller->priv; connected->ani2 = caller->ani2; connected->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; } @@ -2161,6 +2217,7 @@ void ast_party_connected_line_free(struct ast_party_connected_line *doomed) { ast_party_id_free(&doomed->id); ast_party_id_free(&doomed->ani); + ast_party_id_free(&doomed->priv); } void ast_party_redirecting_init(struct ast_party_redirecting *init) @@ -2168,6 +2225,9 @@ void ast_party_redirecting_init(struct ast_party_redirecting *init) ast_party_id_init(&init->orig); ast_party_id_init(&init->from); ast_party_id_init(&init->to); + ast_party_id_init(&init->priv_orig); + ast_party_id_init(&init->priv_from); + ast_party_id_init(&init->priv_to); init->count = 0; init->reason = AST_REDIRECTING_REASON_UNKNOWN; init->orig_reason = AST_REDIRECTING_REASON_UNKNOWN; @@ -2183,6 +2243,9 @@ void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_id_copy(&dest->orig, &src->orig); ast_party_id_copy(&dest->from, &src->from); ast_party_id_copy(&dest->to, &src->to); + ast_party_id_copy(&dest->priv_orig, &src->priv_orig); + ast_party_id_copy(&dest->priv_from, &src->priv_from); + ast_party_id_copy(&dest->priv_to, &src->priv_to); dest->count = src->count; dest->reason = src->reason; dest->orig_reason = src->orig_reason; @@ -2193,6 +2256,9 @@ void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const st ast_party_id_set_init(&init->orig, &guide->orig); ast_party_id_set_init(&init->from, &guide->from); ast_party_id_set_init(&init->to, &guide->to); + ast_party_id_set_init(&init->priv_orig, &guide->priv_orig); + ast_party_id_set_init(&init->priv_from, &guide->priv_from); + ast_party_id_set_init(&init->priv_to, &guide->priv_to); init->count = guide->count; init->reason = guide->reason; init->orig_reason = guide->orig_reason; @@ -2203,6 +2269,9 @@ void ast_party_redirecting_set(struct ast_party_redirecting *dest, const struct ast_party_id_set(&dest->orig, &src->orig, update ? &update->orig : NULL); ast_party_id_set(&dest->from, &src->from, update ? &update->from : NULL); ast_party_id_set(&dest->to, &src->to, update ? &update->to : NULL); + ast_party_id_set(&dest->priv_orig, &src->priv_orig, update ? &update->priv_orig : NULL); + ast_party_id_set(&dest->priv_from, &src->priv_from, update ? &update->priv_from : NULL); + ast_party_id_set(&dest->priv_to, &src->priv_to, update ? &update->priv_to : NULL); dest->count = src->count; dest->reason = src->reason; dest->orig_reason = src->orig_reason; @@ -2213,6 +2282,9 @@ void ast_party_redirecting_free(struct ast_party_redirecting *doomed) ast_party_id_free(&doomed->orig); ast_party_id_free(&doomed->from); ast_party_id_free(&doomed->to); + ast_party_id_free(&doomed->priv_orig); + ast_party_id_free(&doomed->priv_from); + ast_party_id_free(&doomed->priv_to); } /*! \brief Free a channel structure */ @@ -6624,6 +6696,11 @@ static void masquerade_colp_transfer(struct ast_channel *transferee, struct xfer * case, the frame we queue tells ast_read() to call the * connected line interception macro configured for transferee. */ + + /* Reset any earlier private connected id representation */ + ast_party_id_reset(&colp->target_id.priv); + ast_party_id_reset(&colp->transferee_id.priv); + payload_size = ast_connected_line_build_data(connected_line_data, sizeof(connected_line_data), &colp->target_id, NULL); if (payload_size != -1) { @@ -6947,14 +7024,30 @@ int ast_do_masquerade(struct ast_channel *original) ast_channel_dialed_set(original, ast_channel_dialed(clonechan)); ast_channel_dialed_set(clonechan, &exchange.dialed); + /* Reset any earlier private caller id representations */ + ast_party_id_reset(&ast_channel_caller(original)->priv); + ast_party_id_reset(&ast_channel_caller(clonechan)->priv); + exchange.caller = *ast_channel_caller(original); ast_channel_caller_set(original, ast_channel_caller(clonechan)); ast_channel_caller_set(clonechan, &exchange.caller); + /* Reset any earlier private connected id representations */ + ast_party_id_reset(&ast_channel_connected(original)->priv); + ast_party_id_reset(&ast_channel_connected(clonechan)->priv); + exchange.connected = *ast_channel_connected(original); ast_channel_connected_set(original, ast_channel_connected(clonechan)); ast_channel_connected_set(clonechan, &exchange.connected); + /* Reset any earlier private redirecting orig, from or to representations */ + ast_party_id_reset(&ast_channel_redirecting(original)->priv_orig); + ast_party_id_reset(&ast_channel_redirecting(clonechan)->priv_orig); + ast_party_id_reset(&ast_channel_redirecting(original)->priv_from); + ast_party_id_reset(&ast_channel_redirecting(clonechan)->priv_from); + ast_party_id_reset(&ast_channel_redirecting(original)->priv_to); + ast_party_id_reset(&ast_channel_redirecting(clonechan)->priv_to); + exchange.redirecting = *ast_channel_redirecting(original); ast_channel_redirecting_set(original, ast_channel_redirecting(clonechan)); ast_channel_redirecting_set(clonechan, &exchange.redirecting); @@ -9029,6 +9122,19 @@ enum { AST_CONNECTED_LINE_NAME_PRESENTATION, AST_CONNECTED_LINE_NUMBER_VALID, AST_CONNECTED_LINE_NUMBER_PRESENTATION, + AST_CONNECTED_LINE_PRIV_NUMBER, + AST_CONNECTED_LINE_PRIV_NUMBER_PLAN, + AST_CONNECTED_LINE_PRIV_NUMBER_VALID, + AST_CONNECTED_LINE_PRIV_NUMBER_PRESENTATION, + AST_CONNECTED_LINE_PRIV_NAME, + AST_CONNECTED_LINE_PRIV_NAME_VALID, + AST_CONNECTED_LINE_PRIV_NAME_CHAR_SET, + AST_CONNECTED_LINE_PRIV_NAME_PRESENTATION, + AST_CONNECTED_LINE_PRIV_SUBADDRESS, + AST_CONNECTED_LINE_PRIV_SUBADDRESS_TYPE, + AST_CONNECTED_LINE_PRIV_SUBADDRESS_ODD_EVEN, + AST_CONNECTED_LINE_PRIV_SUBADDRESS_VALID, + AST_CONNECTED_LINE_PRIV_TAG, }; int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update) @@ -9057,6 +9163,26 @@ int ast_connected_line_build_data(unsigned char *data, size_t datalen, const str .combined_presentation = AST_CONNECTED_LINE_ID_PRESENTATION, }; + static const struct ast_party_id_ies priv_ies = { + .name.str = AST_CONNECTED_LINE_PRIV_NAME, + .name.char_set = AST_CONNECTED_LINE_PRIV_NAME_CHAR_SET, + .name.presentation = AST_CONNECTED_LINE_PRIV_NAME_PRESENTATION, + .name.valid = AST_CONNECTED_LINE_PRIV_NAME_VALID, + + .number.str = AST_CONNECTED_LINE_PRIV_NUMBER, + .number.plan = AST_CONNECTED_LINE_PRIV_NUMBER_PLAN, + .number.presentation = AST_CONNECTED_LINE_PRIV_NUMBER_PRESENTATION, + .number.valid = AST_CONNECTED_LINE_PRIV_NUMBER_VALID, + + .subaddress.str = AST_CONNECTED_LINE_PRIV_SUBADDRESS, + .subaddress.type = AST_CONNECTED_LINE_PRIV_SUBADDRESS_TYPE, + .subaddress.odd_even_indicator = AST_CONNECTED_LINE_PRIV_SUBADDRESS_ODD_EVEN, + .subaddress.valid = AST_CONNECTED_LINE_PRIV_SUBADDRESS_VALID, + + .tag = AST_CONNECTED_LINE_PRIV_TAG, + .combined_presentation = 0,/* Not sent. */ + }; + /* * The size of integer values must be fixed in case the frame is * shipped to another machine. @@ -9078,6 +9204,13 @@ int ast_connected_line_build_data(unsigned char *data, size_t datalen, const str } pos += res; + res = party_id_build_data(data + pos, datalen - pos, &connected->priv, + "connected line priv", &priv_ies, update ? &update->priv : NULL); + if (res < 0) { + return -1; + } + pos += res; + /* Connected line source */ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { ast_log(LOG_WARNING, "No space left for connected line source\n"); @@ -9190,16 +9323,6 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str } connected->id.number.valid = data[pos]; break; -/* Connected line party id combined presentation */ - case AST_CONNECTED_LINE_ID_PRESENTATION: - if (ie_len != 1) { - ast_log(LOG_WARNING, "Invalid connected line combined presentation (%u)\n", - (unsigned) ie_len); - break; - } - combined_presentation = data[pos]; - got_combined_presentation = 1; - break; /* Connected line party id subaddress */ case AST_CONNECTED_LINE_SUBADDRESS: ast_free(connected->id.subaddress.str); @@ -9243,6 +9366,125 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str connected->id.tag[ie_len] = 0; } break; +/* Connected line party id combined presentation */ + case AST_CONNECTED_LINE_ID_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line combined presentation (%u)\n", + (unsigned) ie_len); + break; + } + combined_presentation = data[pos]; + got_combined_presentation = 1; + break; +/* Private connected line party id name */ + case AST_CONNECTED_LINE_PRIV_NAME: + ast_free(connected->priv.name.str); + connected->priv.name.str = ast_malloc(ie_len + 1); + if (connected->priv.name.str) { + memcpy(connected->priv.name.str, data + pos, ie_len); + connected->priv.name.str[ie_len] = 0; + } + break; + case AST_CONNECTED_LINE_PRIV_NAME_CHAR_SET: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private name char set (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.name.char_set = data[pos]; + break; + case AST_CONNECTED_LINE_PRIV_NAME_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private name presentation (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.name.presentation = data[pos]; + break; + case AST_CONNECTED_LINE_PRIV_NAME_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private name valid (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.name.valid = data[pos]; + break; +/* Private connected line party id number */ + case AST_CONNECTED_LINE_PRIV_NUMBER: + ast_free(connected->priv.number.str); + connected->priv.number.str = ast_malloc(ie_len + 1); + if (connected->priv.number.str) { + memcpy(connected->priv.number.str, data + pos, ie_len); + connected->priv.number.str[ie_len] = 0; + } + break; + case AST_CONNECTED_LINE_PRIV_NUMBER_PLAN: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private numbering plan (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.number.plan = data[pos]; + break; + case AST_CONNECTED_LINE_PRIV_NUMBER_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private number presentation (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.number.presentation = data[pos]; + break; + case AST_CONNECTED_LINE_PRIV_NUMBER_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private number valid (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.number.valid = data[pos]; + break; +/* Private connected line party id subaddress */ + case AST_CONNECTED_LINE_PRIV_SUBADDRESS: + ast_free(connected->priv.subaddress.str); + connected->priv.subaddress.str = ast_malloc(ie_len + 1); + if (connected->priv.subaddress.str) { + memcpy(connected->priv.subaddress.str, data + pos, ie_len); + connected->priv.subaddress.str[ie_len] = 0; + } + break; + case AST_CONNECTED_LINE_PRIV_SUBADDRESS_TYPE: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private type of subaddress (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.subaddress.type = data[pos]; + break; + case AST_CONNECTED_LINE_PRIV_SUBADDRESS_ODD_EVEN: + if (ie_len != 1) { + ast_log(LOG_WARNING, + "Invalid connected line private subaddress odd-even indicator (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.subaddress.odd_even_indicator = data[pos]; + break; + case AST_CONNECTED_LINE_PRIV_SUBADDRESS_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid connected line private subaddress valid (%u)\n", + (unsigned) ie_len); + break; + } + connected->priv.subaddress.valid = data[pos]; + break; +/* Private connected line party tag */ + case AST_CONNECTED_LINE_PRIV_TAG: + ast_free(connected->priv.tag); + connected->priv.tag = ast_malloc(ie_len + 1); + if (connected->priv.tag) { + memcpy(connected->priv.tag, data + pos, ie_len); + connected->priv.tag[ie_len] = 0; + } + break; /* Connected line party source */ case AST_CONNECTED_LINE_SOURCE: if (ie_len != sizeof(value)) { @@ -9383,6 +9625,45 @@ enum { AST_REDIRECTING_ORIG_SUBADDRESS_VALID, AST_REDIRECTING_ORIG_TAG, AST_REDIRECTING_ORIG_REASON, + AST_REDIRECTING_PRIV_TO_NUMBER, + AST_REDIRECTING_PRIV_TO_NUMBER_PLAN, + AST_REDIRECTING_PRIV_TO_NUMBER_VALID, + AST_REDIRECTING_PRIV_TO_NUMBER_PRESENTATION, + AST_REDIRECTING_PRIV_TO_NAME, + AST_REDIRECTING_PRIV_TO_NAME_VALID, + AST_REDIRECTING_PRIV_TO_NAME_CHAR_SET, + AST_REDIRECTING_PRIV_TO_NAME_PRESENTATION, + AST_REDIRECTING_PRIV_TO_SUBADDRESS, + AST_REDIRECTING_PRIV_TO_SUBADDRESS_TYPE, + AST_REDIRECTING_PRIV_TO_SUBADDRESS_ODD_EVEN, + AST_REDIRECTING_PRIV_TO_SUBADDRESS_VALID, + AST_REDIRECTING_PRIV_TO_TAG, + AST_REDIRECTING_PRIV_FROM_NUMBER, + AST_REDIRECTING_PRIV_FROM_NUMBER_PLAN, + AST_REDIRECTING_PRIV_FROM_NUMBER_VALID, + AST_REDIRECTING_PRIV_FROM_NUMBER_PRESENTATION, + AST_REDIRECTING_PRIV_FROM_NAME, + AST_REDIRECTING_PRIV_FROM_NAME_VALID, + AST_REDIRECTING_PRIV_FROM_NAME_CHAR_SET, + AST_REDIRECTING_PRIV_FROM_NAME_PRESENTATION, + AST_REDIRECTING_PRIV_FROM_SUBADDRESS, + AST_REDIRECTING_PRIV_FROM_SUBADDRESS_TYPE, + AST_REDIRECTING_PRIV_FROM_SUBADDRESS_ODD_EVEN, + AST_REDIRECTING_PRIV_FROM_SUBADDRESS_VALID, + AST_REDIRECTING_PRIV_FROM_TAG, + AST_REDIRECTING_PRIV_ORIG_NUMBER, + AST_REDIRECTING_PRIV_ORIG_NUMBER_VALID, + AST_REDIRECTING_PRIV_ORIG_NUMBER_PLAN, + AST_REDIRECTING_PRIV_ORIG_NUMBER_PRESENTATION, + AST_REDIRECTING_PRIV_ORIG_NAME, + AST_REDIRECTING_PRIV_ORIG_NAME_VALID, + AST_REDIRECTING_PRIV_ORIG_NAME_CHAR_SET, + AST_REDIRECTING_PRIV_ORIG_NAME_PRESENTATION, + AST_REDIRECTING_PRIV_ORIG_SUBADDRESS, + AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_TYPE, + AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_ODD_EVEN, + AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_VALID, + AST_REDIRECTING_PRIV_ORIG_TAG, }; int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update) @@ -9448,6 +9729,63 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct .tag = AST_REDIRECTING_TO_TAG, .combined_presentation = AST_REDIRECTING_TO_ID_PRESENTATION, }; + static const struct ast_party_id_ies priv_orig_ies = { + .name.str = AST_REDIRECTING_PRIV_ORIG_NAME, + .name.char_set = AST_REDIRECTING_PRIV_ORIG_NAME_CHAR_SET, + .name.presentation = AST_REDIRECTING_PRIV_ORIG_NAME_PRESENTATION, + .name.valid = AST_REDIRECTING_PRIV_ORIG_NAME_VALID, + + .number.str = AST_REDIRECTING_PRIV_ORIG_NUMBER, + .number.plan = AST_REDIRECTING_PRIV_ORIG_NUMBER_PLAN, + .number.presentation = AST_REDIRECTING_PRIV_ORIG_NUMBER_PRESENTATION, + .number.valid = AST_REDIRECTING_PRIV_ORIG_NUMBER_VALID, + + .subaddress.str = AST_REDIRECTING_PRIV_ORIG_SUBADDRESS, + .subaddress.type = AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_TYPE, + .subaddress.odd_even_indicator = AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_ODD_EVEN, + .subaddress.valid = AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_VALID, + + .tag = AST_REDIRECTING_PRIV_ORIG_TAG, + .combined_presentation = 0,/* Not sent. */ + }; + static const struct ast_party_id_ies priv_from_ies = { + .name.str = AST_REDIRECTING_PRIV_FROM_NAME, + .name.char_set = AST_REDIRECTING_PRIV_FROM_NAME_CHAR_SET, + .name.presentation = AST_REDIRECTING_PRIV_FROM_NAME_PRESENTATION, + .name.valid = AST_REDIRECTING_PRIV_FROM_NAME_VALID, + + .number.str = AST_REDIRECTING_PRIV_FROM_NUMBER, + .number.plan = AST_REDIRECTING_PRIV_FROM_NUMBER_PLAN, + .number.presentation = AST_REDIRECTING_PRIV_FROM_NUMBER_PRESENTATION, + .number.valid = AST_REDIRECTING_PRIV_FROM_NUMBER_VALID, + + .subaddress.str = AST_REDIRECTING_PRIV_FROM_SUBADDRESS, + .subaddress.type = AST_REDIRECTING_PRIV_FROM_SUBADDRESS_TYPE, + .subaddress.odd_even_indicator = AST_REDIRECTING_PRIV_FROM_SUBADDRESS_ODD_EVEN, + .subaddress.valid = AST_REDIRECTING_PRIV_FROM_SUBADDRESS_VALID, + + .tag = AST_REDIRECTING_PRIV_FROM_TAG, + .combined_presentation = 0,/* Not sent. */ + }; + static const struct ast_party_id_ies priv_to_ies = { + .name.str = AST_REDIRECTING_PRIV_TO_NAME, + .name.char_set = AST_REDIRECTING_PRIV_TO_NAME_CHAR_SET, + .name.presentation = AST_REDIRECTING_PRIV_TO_NAME_PRESENTATION, + .name.valid = AST_REDIRECTING_PRIV_TO_NAME_VALID, + + .number.str = AST_REDIRECTING_PRIV_TO_NUMBER, + .number.plan = AST_REDIRECTING_PRIV_TO_NUMBER_PLAN, + .number.presentation = AST_REDIRECTING_PRIV_TO_NUMBER_PRESENTATION, + .number.valid = AST_REDIRECTING_PRIV_TO_NUMBER_VALID, + + .subaddress.str = AST_REDIRECTING_PRIV_TO_SUBADDRESS, + .subaddress.type = AST_REDIRECTING_PRIV_TO_SUBADDRESS_TYPE, + .subaddress.odd_even_indicator = AST_REDIRECTING_PRIV_TO_SUBADDRESS_ODD_EVEN, + .subaddress.valid = AST_REDIRECTING_PRIV_TO_SUBADDRESS_VALID, + + .tag = AST_REDIRECTING_PRIV_TO_TAG, + .combined_presentation = 0,/* Not sent. */ + }; /* Redirecting frame version */ if (datalen < pos + (sizeof(data[0]) * 2) + 1) { @@ -9479,6 +9817,27 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct } pos += res; + res = party_id_build_data(data + pos, datalen - pos, &redirecting->priv_orig, + "redirecting-priv-orig", &priv_orig_ies, update ? &update->priv_orig : NULL); + if (res < 0) { + return -1; + } + pos += res; + + res = party_id_build_data(data + pos, datalen - pos, &redirecting->priv_from, + "redirecting-priv-from", &priv_from_ies, update ? &update->priv_from : NULL); + if (res < 0) { + return -1; + } + pos += res; + + res = party_id_build_data(data + pos, datalen - pos, &redirecting->priv_to, + "redirecting-priv-to", &priv_to_ies, update ? &update->priv_to : NULL); + if (res < 0) { + return -1; + } + pos += res; + /* Redirecting reason */ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { ast_log(LOG_WARNING, "No space left for redirecting reason\n"); @@ -9896,6 +10255,333 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct redirecting->to.tag[ie_len] = 0; } break; +/* Private redirecting-orig party id name */ + case AST_REDIRECTING_PRIV_ORIG_NAME: + ast_free(redirecting->priv_orig.name.str); + redirecting->priv_orig.name.str = ast_malloc(ie_len + 1); + if (redirecting->priv_orig.name.str) { + memcpy(redirecting->priv_orig.name.str, data + pos, ie_len); + redirecting->priv_orig.name.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_ORIG_NAME_CHAR_SET: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig name char set (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.name.char_set = data[pos]; + break; + case AST_REDIRECTING_PRIV_ORIG_NAME_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig name presentation (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.name.presentation = data[pos]; + break; + case AST_REDIRECTING_PRIV_ORIG_NAME_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig name valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.name.valid = data[pos]; + break; +/* Private redirecting-orig party id number */ + case AST_REDIRECTING_PRIV_ORIG_NUMBER: + ast_free(redirecting->priv_orig.number.str); + redirecting->priv_orig.number.str = ast_malloc(ie_len + 1); + if (redirecting->priv_orig.number.str) { + memcpy(redirecting->priv_orig.number.str, data + pos, ie_len); + redirecting->priv_orig.number.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_ORIG_NUMBER_PLAN: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig numbering plan (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.number.plan = data[pos]; + break; + case AST_REDIRECTING_PRIV_ORIG_NUMBER_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig number presentation (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.number.presentation = data[pos]; + break; + case AST_REDIRECTING_PRIV_ORIG_NUMBER_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig number valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.number.valid = data[pos]; + break; +/* Private redirecting-orig party id subaddress */ + case AST_REDIRECTING_PRIV_ORIG_SUBADDRESS: + ast_free(redirecting->priv_orig.subaddress.str); + redirecting->priv_orig.subaddress.str = ast_malloc(ie_len + 1); + if (redirecting->priv_orig.subaddress.str) { + memcpy(redirecting->priv_orig.subaddress.str, data + pos, ie_len); + redirecting->priv_orig.subaddress.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_TYPE: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig type of subaddress (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.subaddress.type = data[pos]; + break; + case AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_ODD_EVEN: + if (ie_len != 1) { + ast_log(LOG_WARNING, + "Invalid private redirecting-orig subaddress odd-even indicator (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.subaddress.odd_even_indicator = data[pos]; + break; + case AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-orig subaddress valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_orig.subaddress.valid = data[pos]; + break; +/* Private redirecting-orig party id tag */ + case AST_REDIRECTING_PRIV_ORIG_TAG: + ast_free(redirecting->priv_orig.tag); + redirecting->priv_orig.tag = ast_malloc(ie_len + 1); + if (redirecting->priv_orig.tag) { + memcpy(redirecting->priv_orig.tag, data + pos, ie_len); + redirecting->priv_orig.tag[ie_len] = 0; + } + break; +/* Private redirecting-from party id name */ + case AST_REDIRECTING_PRIV_FROM_NAME: + ast_free(redirecting->priv_from.name.str); + redirecting->priv_from.name.str = ast_malloc(ie_len + 1); + if (redirecting->priv_from.name.str) { + memcpy(redirecting->priv_from.name.str, data + pos, ie_len); + redirecting->priv_from.name.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_FROM_NAME_CHAR_SET: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from name char set (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.name.char_set = data[pos]; + break; + case AST_REDIRECTING_PRIV_FROM_NAME_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from name presentation (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.name.presentation = data[pos]; + break; + case AST_REDIRECTING_PRIV_FROM_NAME_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from name valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.name.valid = data[pos]; + break; +/* Private redirecting-from party id number */ + case AST_REDIRECTING_PRIV_FROM_NUMBER: + ast_free(redirecting->priv_from.number.str); + redirecting->priv_from.number.str = ast_malloc(ie_len + 1); + if (redirecting->priv_from.number.str) { + memcpy(redirecting->priv_from.number.str, data + pos, ie_len); + redirecting->priv_from.number.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_FROM_NUMBER_PLAN: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from numbering plan (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.number.plan = data[pos]; + break; + case AST_REDIRECTING_PRIV_FROM_NUMBER_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from number presentation (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.number.presentation = data[pos]; + break; + case AST_REDIRECTING_PRIV_FROM_NUMBER_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from number valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.number.valid = data[pos]; + break; +/* Private redirecting-from party id subaddress */ + case AST_REDIRECTING_PRIV_FROM_SUBADDRESS: + ast_free(redirecting->priv_from.subaddress.str); + redirecting->priv_from.subaddress.str = ast_malloc(ie_len + 1); + if (redirecting->priv_from.subaddress.str) { + memcpy(redirecting->priv_from.subaddress.str, data + pos, ie_len); + redirecting->priv_from.subaddress.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_FROM_SUBADDRESS_TYPE: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from type of subaddress (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.subaddress.type = data[pos]; + break; + case AST_REDIRECTING_PRIV_FROM_SUBADDRESS_ODD_EVEN: + if (ie_len != 1) { + ast_log(LOG_WARNING, + "Invalid private redirecting-from subaddress odd-even indicator (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.subaddress.odd_even_indicator = data[pos]; + break; + case AST_REDIRECTING_PRIV_FROM_SUBADDRESS_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-from subaddress valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_from.subaddress.valid = data[pos]; + break; +/* Private redirecting-from party id tag */ + case AST_REDIRECTING_PRIV_FROM_TAG: + ast_free(redirecting->priv_from.tag); + redirecting->priv_from.tag = ast_malloc(ie_len + 1); + if (redirecting->priv_from.tag) { + memcpy(redirecting->priv_from.tag, data + pos, ie_len); + redirecting->priv_from.tag[ie_len] = 0; + } + break; +/* Private redirecting-to party id name */ + case AST_REDIRECTING_PRIV_TO_NAME: + ast_free(redirecting->priv_to.name.str); + redirecting->priv_to.name.str = ast_malloc(ie_len + 1); + if (redirecting->priv_to.name.str) { + memcpy(redirecting->priv_to.name.str, data + pos, ie_len); + redirecting->priv_to.name.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_TO_NAME_CHAR_SET: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to name char set (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.name.char_set = data[pos]; + break; + case AST_REDIRECTING_PRIV_TO_NAME_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to name presentation (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.name.presentation = data[pos]; + break; + case AST_REDIRECTING_PRIV_TO_NAME_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to name valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.name.valid = data[pos]; + break; +/* Private redirecting-to party id number */ + case AST_REDIRECTING_PRIV_TO_NUMBER: + ast_free(redirecting->priv_to.number.str); + redirecting->priv_to.number.str = ast_malloc(ie_len + 1); + if (redirecting->priv_to.number.str) { + memcpy(redirecting->priv_to.number.str, data + pos, ie_len); + redirecting->priv_to.number.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_TO_NUMBER_PLAN: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to numbering plan (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.number.plan = data[pos]; + break; + case AST_REDIRECTING_PRIV_TO_NUMBER_PRESENTATION: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to number presentation (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.number.presentation = data[pos]; + break; + case AST_REDIRECTING_PRIV_TO_NUMBER_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to number valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.number.valid = data[pos]; + break; +/* Private redirecting-to party id subaddress */ + case AST_REDIRECTING_PRIV_TO_SUBADDRESS: + ast_free(redirecting->priv_to.subaddress.str); + redirecting->priv_to.subaddress.str = ast_malloc(ie_len + 1); + if (redirecting->priv_to.subaddress.str) { + memcpy(redirecting->priv_to.subaddress.str, data + pos, ie_len); + redirecting->priv_to.subaddress.str[ie_len] = 0; + } + break; + case AST_REDIRECTING_PRIV_TO_SUBADDRESS_TYPE: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to type of subaddress (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.subaddress.type = data[pos]; + break; + case AST_REDIRECTING_PRIV_TO_SUBADDRESS_ODD_EVEN: + if (ie_len != 1) { + ast_log(LOG_WARNING, + "Invalid private redirecting-to subaddress odd-even indicator (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.subaddress.odd_even_indicator = data[pos]; + break; + case AST_REDIRECTING_PRIV_TO_SUBADDRESS_VALID: + if (ie_len != 1) { + ast_log(LOG_WARNING, "Invalid private redirecting-to subaddress valid (%u)\n", + (unsigned) ie_len); + break; + } + redirecting->priv_to.subaddress.valid = data[pos]; + break; +/* Private redirecting-to party id tag */ + case AST_REDIRECTING_PRIV_TO_TAG: + ast_free(redirecting->priv_to.tag); + redirecting->priv_to.tag = ast_malloc(ie_len + 1); + if (redirecting->priv_to.tag) { + memcpy(redirecting->priv_to.tag, data + pos, ie_len); + redirecting->priv_to.tag[ie_len] = 0; + } + break; /* Redirecting reason */ case AST_REDIRECTING_REASON: if (ie_len != sizeof(value)) { diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 368940fa1..e3543d8ec 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -930,6 +930,10 @@ struct ast_party_connected_line *ast_channel_connected(struct ast_channel *chan) { return &chan->connected; } +struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan) +{ + return ast_party_id_merge(&chan->connected.id, &chan->connected.priv); +} struct ast_party_dialed *ast_channel_dialed(struct ast_channel *chan) { return &chan->dialed; @@ -938,6 +942,18 @@ struct ast_party_redirecting *ast_channel_redirecting(struct ast_channel *chan) { return &chan->redirecting; } +struct ast_party_id ast_channel_redirecting_effective_orig(struct ast_channel *chan) +{ + return ast_party_id_merge(&chan->redirecting.orig, &chan->redirecting.priv_orig); +} +struct ast_party_id ast_channel_redirecting_effective_from(struct ast_channel *chan) +{ + return ast_party_id_merge(&chan->redirecting.from, &chan->redirecting.priv_from); +} +struct ast_party_id ast_channel_redirecting_effective_to(struct ast_channel *chan) +{ + return ast_party_id_merge(&chan->redirecting.to, &chan->redirecting.priv_to); +} struct timeval *ast_channel_dtmf_tv(struct ast_channel *chan) { return &chan->dtmf_tv; diff --git a/main/cli.c b/main/cli.c index 7f71da924..e5118ede6 100644 --- a/main/cli.c +++ b/main/cli.c @@ -1399,6 +1399,7 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar int hour=0, min=0, sec=0; struct ast_callid *callid; char call_identifier_str[AST_CALLID_BUFFER_LENGTH] = ""; + struct ast_party_id effective_connected_id; #ifdef CHANNEL_TRACE int trace_enabled; #endif @@ -1452,6 +1453,8 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar ast_callid_unref(callid); } + effective_connected_id = ast_channel_connected_effective_id(c); + ast_str_append(&output, 0, " -- General --\n" " Name: %s\n" @@ -1462,6 +1465,8 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar " Caller ID Name: %s\n" "Connected Line ID: %s\n" "Connected Line ID Name: %s\n" + "Eff. Connected Line ID: %s\n" + "Eff. Connected Line ID Name: %s\n" " DNID Digits: %s\n" " Language: %s\n" " State: %s (%d)\n" @@ -1493,6 +1498,8 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"), S_COR(ast_channel_connected(c)->id.number.valid, ast_channel_connected(c)->id.number.str, "(N/A)"), S_COR(ast_channel_connected(c)->id.name.valid, ast_channel_connected(c)->id.name.str, "(N/A)"), + S_COR(effective_connected_id.number.valid, effective_connected_id.number.str, "(N/A)"), + S_COR(effective_connected_id.name.valid, effective_connected_id.name.str, "(N/A)"), S_OR(ast_channel_dialed(c)->number.str, "(N/A)"), ast_channel_language(c), ast_state2str(ast_channel_state(c)), ast_channel_state(c), ast_channel_rings(c), diff --git a/main/features.c b/main/features.c index 48b733922..4cfbcfb68 100644 --- a/main/features.c +++ b/main/features.c @@ -7801,6 +7801,9 @@ int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target) ast_party_connected_line_init(&connected_caller); ast_party_connected_line_copy(&connected_caller, ast_channel_connected(target)); ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */ + /* Reset any earlier private connected id representation */ + ast_party_id_reset(&connected_caller.priv); + connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0) && ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) { |