static void sig_pri_redirecting_update(struct sig_pri_chan *pvt, struct ast_channel *ast)
{
struct pri_party_redirecting pri_redirecting;
-
-/*! \todo XXX Original called data can be put in a channel data store that is inherited. */
+ const struct ast_party_redirecting *ast_redirecting;
memset(&pri_redirecting, 0, sizeof(pri_redirecting));
- sig_pri_party_id_from_ast(&pri_redirecting.from, &ast_channel_redirecting(ast)->from);
- sig_pri_party_id_from_ast(&pri_redirecting.to, &ast_channel_redirecting(ast)->to);
- pri_redirecting.count = ast_channel_redirecting(ast)->count;
- pri_redirecting.reason = ast_to_pri_reason(ast_channel_redirecting(ast)->reason);
+ 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);
+ 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);
pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
}
{
ast_party_redirecting_set_init(ast_redirecting, ast_guide);
+ sig_pri_party_id_convert(&ast_redirecting->orig, &pri_redirecting->orig_called, pri);
sig_pri_party_id_convert(&ast_redirecting->from, &pri_redirecting->from, pri);
sig_pri_party_id_convert(&ast_redirecting->to, &pri_redirecting->to, pri);
ast_redirecting->count = pri_redirecting->count;
ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
+ ast_redirecting->orig_reason = pri_to_ast_reason(pri_redirecting->orig_reason);
}
/*!
if (owner) {
sig_pri_redirecting_convert(&ast_redirecting, &subcmd->u.redirecting,
ast_channel_redirecting(owner), pri);
+ ast_redirecting.orig.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
-
-/*! \todo XXX Original called data can be put in a channel data store that is inherited. */
-
ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
if (event_id != PRI_EVENT_RING) {
/* This redirection was not from a SETUP message. */
}
sig_pri_redirecting_convert(&ast_redirecting, &pri_deflection,
ast_channel_redirecting(owner), pri);
+ ast_redirecting.orig.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
* they are active at the same time. The plain pres option will simply
* live on as a historical relic.
*
- * Do not document the REDIRECTING(from-pres) or REDIRECTING(to-pres) datatypes.
- * The name and number now have their own presentation value. The from-pres
- * and to-pres options will simply live on as a historical relic with as best
- * as can be managed backward compatible meaning.
+ * Do not document the REDIRECTING(orig-pres), REDIRECTING(from-pres),
+ * or REDIRECTING(to-pres) datatypes.
+ * The name and number now have their own presentation value. The orig-pres,
+ * from-pres, and to-pres options will simply live on as a historical relic
+ * with as best as can be managed backward compatible meaning.
*
- * Do not document the REDIRECTING(from-ton) or REDIRECTING(to-ton) datatypes.
- * They are aliases for from-num-plan and to-num-plan respectively.
+ * Do not document the REDIRECTING(orig-ton), REDIRECTING(from-ton),
+ * or REDIRECTING(to-ton) datatypes.
+ * They are aliases for orig-num-plan, from-num-plan, and to-num-plan
+ * respectively.
*/
/*** DOCUMENTATION
<function name="CALLERID" language="en_US">
<parameter name="datatype" required="true">
<para>The allowable datatypes are:</para>
<enumlist>
+ <enum name = "orig-all" />
+ <enum name = "orig-name" />
+ <enum name = "orig-name-valid" />
+ <enum name = "orig-name-charset" />
+ <enum name = "orig-name-pres" />
+ <enum name = "orig-num" />
+ <enum name = "orig-num-valid" />
+ <enum name = "orig-num-plan" />
+ <enum name = "orig-num-pres" />
+ <enum name = "orig-subaddr" />
+ <enum name = "orig-subaddr-valid" />
+ <enum name = "orig-subaddr-type" />
+ <enum name = "orig-subaddr-odd" />
+ <enum name = "orig-tag" />
+ <enum name = "orig-reason" />
<enum name = "from-all" />
<enum name = "from-name" />
<enum name = "from-name-valid" />
<description>
<para>Gets or sets Redirecting data on the channel.</para>
<para>The allowable values for the <replaceable>reason</replaceable>
- field are the following:</para>
+ and <replaceable>orig-reason</replaceable> fields are the following:</para>
<enumlist>
<enum name = "unknown"><para>Unknown</para></enum>
<enum name = "cfb"><para>Call Forwarding Busy</para></enum>
{
struct ast_party_members member;
char *read_what;
+ const struct ast_party_redirecting *ast_redirecting;
enum ID_FIELD_STATUS status;
/* Ensure that the buffer is empty */
ast_channel_lock(chan);
- if (!strcasecmp("from", member.argv[0])) {
+ ast_redirecting = ast_channel_redirecting(chan);
+ if (!strcasecmp("orig", member.argv[0])) {
+ if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
+ ast_copy_string(buf,
+ ast_redirecting_reason_name(ast_redirecting->orig_reason), len);
+ } else {
+ status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
+ &ast_redirecting->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[0])) {
status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
- &ast_channel_redirecting(chan)->from);
+ &ast_redirecting->from);
switch (status) {
case ID_FIELD_VALID:
case ID_FIELD_INVALID:
}
} else if (!strcasecmp("to", member.argv[0])) {
status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
- &ast_channel_redirecting(chan)->to);
+ &ast_redirecting->to);
switch (status) {
case ID_FIELD_VALID:
case ID_FIELD_INVALID:
*/
ast_copy_string(buf,
ast_named_caller_presentation(
- ast_party_id_presentation(&ast_channel_redirecting(chan)->from)), len);
+ ast_party_id_presentation(&ast_redirecting->from)), len);
} else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
- ast_copy_string(buf, ast_redirecting_reason_name(ast_channel_redirecting(chan)->reason), len);
+ 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_channel_redirecting(chan)->count);
+ snprintf(buf, len, "%d", ast_redirecting->count);
} else {
ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
}
value = ast_skip_blanks(value);
- if (!strcasecmp("from", member.argv[0])) {
+ if (!strcasecmp("orig", member.argv[0])) {
+ if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
+ int reason;
+
+ val = ast_strdupa(value);
+ ast_trim_blanks(val);
+
+ if (('0' <= val[0]) && (val[0] <= '9')) {
+ reason = atoi(val);
+ } else {
+ reason = ast_redirecting_reason_parse(val);
+ }
+
+ if (reason < 0) {
+ ast_log(LOG_ERROR,
+ "Unknown redirecting orig reason '%s', value unchanged\n", val);
+ } else {
+ redirecting.orig_reason = reason;
+ set_it(chan, &redirecting, NULL);
+ }
+ } else {
+ status = party_id_write(&redirecting.orig, member.argc - 1, member.argv + 1,
+ 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[0])) {
status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
value);
switch (status) {
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);
init->count = 0;
init->reason = AST_REDIRECTING_REASON_UNKNOWN;
+ init->orig_reason = AST_REDIRECTING_REASON_UNKNOWN;
}
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
return;
}
+ ast_party_id_copy(&dest->orig, &src->orig);
ast_party_id_copy(&dest->from, &src->from);
ast_party_id_copy(&dest->to, &src->to);
dest->count = src->count;
dest->reason = src->reason;
+ dest->orig_reason = src->orig_reason;
}
void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide)
{
+ 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);
init->count = guide->count;
init->reason = guide->reason;
+ init->orig_reason = guide->orig_reason;
}
void ast_party_redirecting_set(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src, const struct ast_set_party_redirecting *update)
{
+ 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);
- dest->reason = src->reason;
dest->count = src->count;
+ dest->reason = src->reason;
+ dest->orig_reason = src->orig_reason;
}
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);
}
struct ast_party_subaddress_ies subaddress;
/*! \brief User party id tag ie. */
int tag;
- /*! \brief Combined name and number presentation ie. */
+ /*!
+ * \brief Combined name and number presentation ie.
+ * \note Not sent if value is zero.
+ */
int combined_presentation;
};
}
/* *************** Party id combined presentation *************** */
- if (!update || update->number) {
+ if (ies->combined_presentation && (!update || update->number)) {
int presentation;
if (!update || update->name) {
AST_CONNECTED_LINE_SUBADDRESS_VALID,
AST_CONNECTED_LINE_TAG,
AST_CONNECTED_LINE_VERSION,
+ /*
+ * No more party id combined number and name presentation values
+ * need to be created.
+ */
AST_CONNECTED_LINE_NAME_VALID,
AST_CONNECTED_LINE_NAME_CHAR_SET,
AST_CONNECTED_LINE_NAME_PRESENTATION,
AST_REDIRECTING_FROM_NUMBER,
AST_REDIRECTING_FROM_NAME,
AST_REDIRECTING_FROM_NUMBER_PLAN,
- AST_REDIRECTING_FROM_ID_PRESENTATION,
+ AST_REDIRECTING_FROM_ID_PRESENTATION,/* Combined number and name presentation. */
AST_REDIRECTING_TO_NUMBER,
AST_REDIRECTING_TO_NAME,
AST_REDIRECTING_TO_NUMBER_PLAN,
- AST_REDIRECTING_TO_ID_PRESENTATION,
+ AST_REDIRECTING_TO_ID_PRESENTATION,/* Combined number and name presentation. */
AST_REDIRECTING_REASON,
AST_REDIRECTING_COUNT,
AST_REDIRECTING_FROM_SUBADDRESS,
AST_REDIRECTING_FROM_TAG,
AST_REDIRECTING_TO_TAG,
AST_REDIRECTING_VERSION,
+ /*
+ * No more party id combined number and name presentation values
+ * need to be created.
+ */
AST_REDIRECTING_FROM_NAME_VALID,
AST_REDIRECTING_FROM_NAME_CHAR_SET,
AST_REDIRECTING_FROM_NAME_PRESENTATION,
AST_REDIRECTING_TO_NAME_PRESENTATION,
AST_REDIRECTING_TO_NUMBER_VALID,
AST_REDIRECTING_TO_NUMBER_PRESENTATION,
+ AST_REDIRECTING_ORIG_NUMBER,
+ AST_REDIRECTING_ORIG_NUMBER_VALID,
+ AST_REDIRECTING_ORIG_NUMBER_PLAN,
+ AST_REDIRECTING_ORIG_NUMBER_PRESENTATION,
+ AST_REDIRECTING_ORIG_NAME,
+ AST_REDIRECTING_ORIG_NAME_VALID,
+ AST_REDIRECTING_ORIG_NAME_CHAR_SET,
+ AST_REDIRECTING_ORIG_NAME_PRESENTATION,
+ AST_REDIRECTING_ORIG_SUBADDRESS,
+ AST_REDIRECTING_ORIG_SUBADDRESS_TYPE,
+ AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN,
+ AST_REDIRECTING_ORIG_SUBADDRESS_VALID,
+ AST_REDIRECTING_ORIG_TAG,
+ AST_REDIRECTING_ORIG_REASON,
};
int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
size_t pos = 0;
int res;
+ static const struct ast_party_id_ies orig_ies = {
+ .name.str = AST_REDIRECTING_ORIG_NAME,
+ .name.char_set = AST_REDIRECTING_ORIG_NAME_CHAR_SET,
+ .name.presentation = AST_REDIRECTING_ORIG_NAME_PRESENTATION,
+ .name.valid = AST_REDIRECTING_ORIG_NAME_VALID,
+
+ .number.str = AST_REDIRECTING_ORIG_NUMBER,
+ .number.plan = AST_REDIRECTING_ORIG_NUMBER_PLAN,
+ .number.presentation = AST_REDIRECTING_ORIG_NUMBER_PRESENTATION,
+ .number.valid = AST_REDIRECTING_ORIG_NUMBER_VALID,
+
+ .subaddress.str = AST_REDIRECTING_ORIG_SUBADDRESS,
+ .subaddress.type = AST_REDIRECTING_ORIG_SUBADDRESS_TYPE,
+ .subaddress.odd_even_indicator = AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN,
+ .subaddress.valid = AST_REDIRECTING_ORIG_SUBADDRESS_VALID,
+
+ .tag = AST_REDIRECTING_ORIG_TAG,
+ .combined_presentation = 0,/* Not sent. */
+ };
static const struct ast_party_id_ies from_ies = {
.name.str = AST_REDIRECTING_FROM_NAME,
.name.char_set = AST_REDIRECTING_FROM_NAME_CHAR_SET,
data[pos++] = 1;
data[pos++] = 2;/* Version 1 did not have a version ie */
+ res = party_id_build_data(data + pos, datalen - pos, &redirecting->orig,
+ "redirecting-orig", &orig_ies, update ? &update->orig : NULL);
+ if (res < 0) {
+ return -1;
+ }
+ pos += res;
+
res = party_id_build_data(data + pos, datalen - pos, &redirecting->from,
"redirecting-from", &from_ies, update ? &update->from : NULL);
if (res < 0) {
memcpy(data + pos, &value, sizeof(value));
pos += sizeof(value);
+ /* Redirecting original reason */
+ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
+ ast_log(LOG_WARNING, "No space left for redirecting original reason\n");
+ return -1;
+ }
+ data[pos++] = AST_REDIRECTING_ORIG_REASON;
+ data[pos++] = sizeof(value);
+ value = htonl(redirecting->orig_reason);
+ memcpy(data + pos, &value, sizeof(value));
+ pos += sizeof(value);
+
/* Redirecting count */
if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
ast_log(LOG_WARNING, "No space left for redirecting count\n");
}
frame_version = data[pos];
break;
+/* Redirecting-orig party id name */
+ case AST_REDIRECTING_ORIG_NAME:
+ ast_free(redirecting->orig.name.str);
+ redirecting->orig.name.str = ast_malloc(ie_len + 1);
+ if (redirecting->orig.name.str) {
+ memcpy(redirecting->orig.name.str, data + pos, ie_len);
+ redirecting->orig.name.str[ie_len] = 0;
+ }
+ break;
+ case AST_REDIRECTING_ORIG_NAME_CHAR_SET:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig name char set (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.name.char_set = data[pos];
+ break;
+ case AST_REDIRECTING_ORIG_NAME_PRESENTATION:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig name presentation (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.name.presentation = data[pos];
+ break;
+ case AST_REDIRECTING_ORIG_NAME_VALID:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig name valid (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.name.valid = data[pos];
+ break;
+/* Redirecting-orig party id number */
+ case AST_REDIRECTING_ORIG_NUMBER:
+ ast_free(redirecting->orig.number.str);
+ redirecting->orig.number.str = ast_malloc(ie_len + 1);
+ if (redirecting->orig.number.str) {
+ memcpy(redirecting->orig.number.str, data + pos, ie_len);
+ redirecting->orig.number.str[ie_len] = 0;
+ }
+ break;
+ case AST_REDIRECTING_ORIG_NUMBER_PLAN:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig numbering plan (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.number.plan = data[pos];
+ break;
+ case AST_REDIRECTING_ORIG_NUMBER_PRESENTATION:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig number presentation (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.number.presentation = data[pos];
+ break;
+ case AST_REDIRECTING_ORIG_NUMBER_VALID:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig number valid (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.number.valid = data[pos];
+ break;
+/* Redirecting-orig party id subaddress */
+ case AST_REDIRECTING_ORIG_SUBADDRESS:
+ ast_free(redirecting->orig.subaddress.str);
+ redirecting->orig.subaddress.str = ast_malloc(ie_len + 1);
+ if (redirecting->orig.subaddress.str) {
+ memcpy(redirecting->orig.subaddress.str, data + pos, ie_len);
+ redirecting->orig.subaddress.str[ie_len] = 0;
+ }
+ break;
+ case AST_REDIRECTING_ORIG_SUBADDRESS_TYPE:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig type of subaddress (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.subaddress.type = data[pos];
+ break;
+ case AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING,
+ "Invalid redirecting-orig subaddress odd-even indicator (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.subaddress.odd_even_indicator = data[pos];
+ break;
+ case AST_REDIRECTING_ORIG_SUBADDRESS_VALID:
+ if (ie_len != 1) {
+ ast_log(LOG_WARNING, "Invalid redirecting-orig subaddress valid (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ redirecting->orig.subaddress.valid = data[pos];
+ break;
+/* Redirecting-orig party id tag */
+ case AST_REDIRECTING_ORIG_TAG:
+ ast_free(redirecting->orig.tag);
+ redirecting->orig.tag = ast_malloc(ie_len + 1);
+ if (redirecting->orig.tag) {
+ memcpy(redirecting->orig.tag, data + pos, ie_len);
+ redirecting->orig.tag[ie_len] = 0;
+ }
+ break;
/* Redirecting-from party id name */
case AST_REDIRECTING_FROM_NAME:
ast_free(redirecting->from.name.str);
memcpy(&value, data + pos, sizeof(value));
redirecting->reason = ntohl(value);
break;
+/* Redirecting orig-reason */
+ case AST_REDIRECTING_ORIG_REASON:
+ if (ie_len != sizeof(value)) {
+ ast_log(LOG_WARNING, "Invalid redirecting original reason (%u)\n",
+ (unsigned) ie_len);
+ break;
+ }
+ memcpy(&value, data + pos, sizeof(value));
+ redirecting->orig_reason = ntohl(value);
+ break;
/* Redirecting count */
case AST_REDIRECTING_COUNT:
if (ie_len != sizeof(value)) {
/*
* The other end is an earlier version that we need to adjust
* for compatibility.
+ *
+ * The earlier version did not have the orig party id or
+ * orig_reason value.
*/
redirecting->from.name.valid = 1;
redirecting->from.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1;