summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-08-10 19:54:55 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-08-10 19:54:55 +0000
commitfb6238899ba9ecaf615982597142fd049e1cf865 (patch)
treef2fc1c780063c45fd5eba21a3669fe9b0f66db22
parent5ff199d99a64c32385eb340a48980400c45234cb (diff)
Add private representation of caller, connected and redirecting party ids.
This patch adds the feature "Private representation of caller, connected and redirecting party ids", as previously discussed with us (DATUS) and Digium. 1. Feature motivation Until now it is quite difficult to modify a party number or name which can only be seen by exactly one particular instantiated technology channel subscriber. One example where a modified party number or name on one channel is spread over several channels are supplementary services like call transfer or pickup. To implement these features Asterisk internally copies caller and connected ids from one channel to another. Another example are extension subscriptions. The monitoring entities (watchers) are notified of state changes and - if desired - of party numbers or names which represent the involving call parties. One major feature where a private representation of party names is essentially needed, i.e. where a party name shall be exclusively signaled to only one particular user, is a private user-specific name resolution for party numbers. A lookup in a private destination-dependent telephone book shall provide party names which cannot be seen by any other user at any time. 2. Feature Description This feature comes along with the implementation of additional private party id elements for caller id, connected id and redirecting ids inside Asterisk channels. The private party id elements can be read or set by the user using Asterisk dialplan functions. When a technology channel is initiating a call, receives an internal connected-line update event, or receives an internal redirecting update event, it merges the corresponding public id with the private id to create an effective party id. The effective party id is then used for protocol signaling. The channel technologies which initially support the private id representation with this patch are SIP (chan_sip), mISDN (chan_misdn) and PRI (chan_dahdi). Once a private name or number on a channel is set and (implicitly) made valid, it is generally used for any further protocol signaling until it is rewritten or invalidated. To simplify the invalidation of private ids all internally generated connected/redirecting update events and also all connected/redirecting update events which are generated by technology channels -- receiving regarding protocol information - automatically trigger the invalidation of private ids. If not using the private party id representation feature at all, i.e. if using only the 'regular' caller-id, connected and redirecting related functions, the current characteristic of Asterisk is not affected by the new extended functionality. 3. User interface Description To grant access to the private name and number representation from the Asterisk dialplan, the CALLERID, CONNECTEDLINE and REDIRECTING dialplan functions are extended by the following data types. The formats of these data types are equal to the corresponding regular 'non-private' already existing data types: CALLERID: priv-all priv-name priv-name-valid priv-name-charset priv-name-pres priv-num priv-num-valid priv-num-plan priv-num-pres priv-subaddr priv-subaddr-valid priv-subaddr-type priv-subaddr-odd priv-tag CONNECTEDLINE: priv-name priv-name-valid priv-name-pres priv-name-charset priv-num priv-num-valid priv-num-pres priv-num-plan priv-subaddr priv-subaddr-valid priv-subaddr-type priv-subaddr-odd priv-tag REDIRECTING: priv-orig-name priv-orig-name-valid priv-orig-name-pres priv-orig-name-charset priv-orig-num priv-orig-num-valid priv-orig-num-pres priv-orig-num-plan priv-orig-subaddr priv-orig-subaddr-valid priv-orig-subaddr-type priv-orig-subaddr-odd priv-orig-tag priv-from-name priv-from-name-valid priv-from-name-pres priv-from-name-charset priv-from-num priv-from-num-valid priv-from-num-pres priv-from-num-plan priv-from-subaddr priv-from-subaddr-valid priv-from-subaddr-type priv-from-subaddr-odd priv-from-tag priv-to-name priv-to-name-valid priv-to-name-pres priv-to-name-charset priv-to-num priv-to-num-valid priv-to-num-pres priv-to-num-plan priv-to-subaddr priv-to-subaddr-valid priv-to-subaddr-type priv-to-subaddr-odd priv-to-tag Reported by: Thomas Arimont Review: https://reviewboard.asterisk.org/r/2030/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@371120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_misdn.c145
-rw-r--r--channels/chan_sip.c88
-rw-r--r--channels/sig_pri.c39
-rw-r--r--funcs/func_callerid.c208
-rw-r--r--include/asterisk/channel.h99
-rw-r--r--main/channel.c706
-rw-r--r--main/channel_internal_api.c16
-rw-r--r--main/cli.c7
-rw-r--r--main/features.c3
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)) {