[svn-commits] rmudgett: branch rmudgett/subaddr r224778 - in /team/rmudgett/subaddr: channe...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Oct 20 13:15:01 CDT 2009


Author: rmudgett
Date: Tue Oct 20 13:14:57 2009
New Revision: 224778

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=224778
Log:
Add support for calling and called subaddress.  Partial support for COLP subaddress.

The Telecom Specs in NZ suggests that SUB ADDRESS is always on, so doing
"desk to desk" between offices each with an asterisk box over the ISDN
should then be possible, without a whole load of DDI numbers required.

(issue #15604)
Reported by: alecdavis
Patches:
      asterisk_subaddr_trunk.diff11.txt uploaded by alecdavis (license 585)
      Some minor modificatons were made.
Tested by: alecdavis, rmudgett

Review: https://reviewboard.asterisk.org/r/405/

Modified:
    team/rmudgett/subaddr/channels/sig_pri.c
    team/rmudgett/subaddr/funcs/func_callerid.c
    team/rmudgett/subaddr/funcs/func_connectedline.c
    team/rmudgett/subaddr/include/asterisk/channel.h
    team/rmudgett/subaddr/main/channel.c

Modified: team/rmudgett/subaddr/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/subaddr/channels/sig_pri.c?view=diff&rev=224778&r1=224777&r2=224778
==============================================================================
--- team/rmudgett/subaddr/channels/sig_pri.c (original)
+++ team/rmudgett/subaddr/channels/sig_pri.c Tue Oct 20 13:14:57 2009
@@ -437,6 +437,168 @@
 	return pri_to_ast_presentation(number_value | number_screening);
 }
 
+#if defined(HAVE_PRI_SUBADDR)
+/*!
+ * \internal
+ * \brief Fill in the asterisk party subaddress from the given PRI party subaddress.
+ * \since 1.6.3
+ *
+ * \param ast_subaddress Asterisk party subaddress structure.
+ * \param pri_subaddress PRI party subaddress structure.
+ *
+ * \return Nothing
+ *
+ */
+static void sig_pri_set_subaddress(struct ast_party_subaddress *ast_subaddress, const struct pri_party_subaddress *pri_subaddress)
+{
+	char *cnum, *ptr;
+	int x, len;
+
+	if (ast_subaddress->str) {
+		ast_free(ast_subaddress->str);
+	}
+	if (pri_subaddress->length <= 0) {
+		ast_party_subaddress_init(ast_subaddress);
+		return;
+	}
+
+	if (!pri_subaddress->type) {
+		/* NSAP */
+		ast_subaddress->str = ast_strdup((char *) pri_subaddress->data);
+	} else {
+		/* User Specified */
+		if (!(cnum = ast_malloc(2 * pri_subaddress->length + 1))) {
+			ast_party_subaddress_init(ast_subaddress);
+			return;
+		}
+
+		ptr = cnum;
+		len = pri_subaddress->length - 1; /* -1 account for zero based indexing */
+		for (x = 0; x < len; ++x) {
+			ptr += sprintf(ptr, "%02x", pri_subaddress->data[x]);
+		}
+
+		if (pri_subaddress->odd_even_indicator) {
+			/* ODD */
+			sprintf(ptr, "%01x", (pri_subaddress->data[len]) >> 4);
+		} else {
+			/* EVEN */
+			sprintf(ptr, "%02x", pri_subaddress->data[len]);
+		}
+		ast_subaddress->str = cnum;
+	}
+	ast_subaddress->type = pri_subaddress->type;
+	ast_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
+	ast_subaddress->valid = 1;
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
+#if defined(HAVE_PRI_SUBADDR)
+static unsigned char ast_pri_pack_hex_char(char c)
+{
+	unsigned char res;
+
+	if (c < '0') {
+		res = 0;
+	} else if (c < ('9' + 1)) {
+		res = c - '0';
+	} else if (c < 'A') {
+		res = 0;
+	} else if (c < ('F' + 1)) {
+		res = c - 'A' + 10;
+	} else if (c < 'a') {
+		res = 0;
+	} else if (c < ('f' + 1)) {
+		res = c - 'a' + 10;
+	} else {
+		res = 0;
+	}
+	return res;
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
+#if defined(HAVE_PRI_SUBADDR)
+/*!
+ * \internal
+ * \brief Convert a null terminated hexadecimal string to a packed hex byte array.
+ * \details left justified, with 0 padding if odd length.
+ * \since 1.6.3
+ *
+ * \param dst pointer to packed byte array.
+ * \param src pointer to null terminated hexadecimal string.
+ * \param maxlen destination array size.
+ *
+ * \return Length of byte array
+ *
+ * \note The dst is not an ASCIIz string.
+ * \note The src is an ASCIIz hex string.
+ */
+static int ast_pri_pack_hex_string(unsigned char *dst, char *src, int maxlen)
+{
+	int res = 0;
+	int len = strlen(src);
+
+	if (len > (2 * maxlen)) {
+		len = 2 * maxlen;
+	}
+
+	res = len / 2 + len % 2;
+
+	while (len > 1) {
+		*dst = ast_pri_pack_hex_char(*src) << 4;
+		src++;
+		*dst |= ast_pri_pack_hex_char(*src);
+		dst++, src++;
+		len -= 2;
+	}
+	if (len) { /* 1 left */
+		*dst = ast_pri_pack_hex_char(*src) << 4;
+	}
+	return res;
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
+#if defined(HAVE_PRI_SUBADDR)
+/*!
+ * \internal
+ * \brief Fill in the PRI party subaddress from the given asterisk party subaddress.
+ * \since 1.6.3
+ *
+ * \param pri_subaddress PRI party subaddress structure.
+ * \param ast_subaddress Asterisk party subaddress structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes that pri_subaddress has been previously memset to zero.
+ */
+static void sig_pri_party_subaddress_from_ast(struct pri_party_subaddress *pri_subaddress, const struct ast_party_subaddress *ast_subaddress)
+{
+	if (ast_subaddress->valid && !ast_strlen_zero(ast_subaddress->str)) {
+		pri_subaddress->type = ast_subaddress->type;
+		if (!ast_subaddress->type) {
+			/* 0 = NSAP */
+			ast_copy_string((char *) pri_subaddress->data, ast_subaddress->str,
+				sizeof(pri_subaddress->data));
+			pri_subaddress->length = strlen((char *) pri_subaddress->data);
+			pri_subaddress->odd_even_indicator = 0;
+			pri_subaddress->valid = 1;
+		} else {
+			/* 2 = User Specified */
+			/*
+			 * Copy HexString to packed HexData,
+			 * if odd length then right pad trailing byte with 0
+			 */
+			int length = ast_pri_pack_hex_string(pri_subaddress->data,
+				ast_subaddress->str, sizeof(pri_subaddress->data));
+
+			pri_subaddress->length = length;
+			pri_subaddress->odd_even_indicator = (length & 1);
+			pri_subaddress->valid = 1;
+		}
+	}
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
 /*!
  * \internal
  * \brief Fill in the PRI party id from the given asterisk party id.
@@ -466,6 +628,9 @@
 		pri_id->number.plan = ast_id->number_type;
 		ast_copy_string(pri_id->number.str, ast_id->number, sizeof(pri_id->number.str));
 	}
+#if defined(HAVE_PRI_SUBADDR)
+	sig_pri_party_subaddress_from_ast(&pri_id->subaddress, &ast_id->subaddress);
+#endif	/* defined(HAVE_PRI_SUBADDR) */
 }
 
 /*!
@@ -1789,9 +1954,42 @@
 								e->ring.ctype, pri->pvts[chanpos]->exten, NULL);
 							ast_mutex_lock(&pri->lock);
 							if (c) {
+#if defined(HAVE_PRI_SUBADDR)
+								if (e->ring.calling.subaddress.valid) {
+									/* Set Calling Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.subaddress,
+										&e->ring.calling.subaddress);
+									if (!e->ring.calling.subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.calling.subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
+											(char *) e->ring.calling.subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+								if (e->ring.called_subaddress.valid) {
+									/* Set Called Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.dialed_subaddress,
+										&e->ring.called_subaddress);
+									if (!e->ring.called_subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.called_subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
+											(char *) e->ring.called_subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+#else
 								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
 									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
 								}
+#endif /* !defined(HAVE_PRI_SUBADDR) */
 								if (e->ring.ani2 >= 0) {
 									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
 									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
@@ -1851,9 +2049,42 @@
 								 * will do anything with the channel we have just
 								 * created.
 								 */
+#if defined(HAVE_PRI_SUBADDR)
+								if (e->ring.calling.subaddress.valid) {
+									/* Set Calling Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.subaddress,
+										&e->ring.calling.subaddress);
+									if (!e->ring.calling.subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.calling.subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
+											(char *) e->ring.calling.subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+								if (e->ring.called_subaddress.valid) {
+									/* Set Called Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.dialed_subaddress,
+										&e->ring.called_subaddress);
+									if (!e->ring.called_subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.called_subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
+											(char *) e->ring.called_subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+#else
 								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
 									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
 								}
+#endif /* !defined(HAVE_PRI_SUBADDR) */
 								if (e->ring.ani2 >= 0) {
 									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
 									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
@@ -2467,6 +2698,7 @@
 int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1)
 {
 	char dest[256]; /* must be same length as p->dialdest */
+	struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
 	struct pri_sr *sr;
 	char *c, *l, *n, *s = NULL;
 #ifdef SUPPORT_USERUSER
@@ -2485,7 +2717,6 @@
 		return -1;
 	}
 
-
 	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 		ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast->name);
 		return -1;
@@ -2495,6 +2726,34 @@
 
 	p->dialdest[0] = '\0';
 	p->outgoing = 1;
+
+	/* setup dialed_subaddress if found */
+	ast_party_subaddress_init(&dialed_subaddress);
+	c = strrchr(dest, ':');
+	if (c) {
+		*c = '\0';
+		c++;
+		/* prefix */
+		/* 'n' = NSAP */
+		/* 'U' = odd, 'u'= even */
+		/* Default = NSAP */
+		switch (*c) {
+		case 'U':
+			dialed_subaddress.odd_even_indicator = 1;
+			/* fall through */
+		case 'u':
+			c++;
+			dialed_subaddress.type = 2;
+			break;
+		case 'N':
+		case 'n':
+			c++;
+			/* default already covered with ast_party_subaddress_init */
+			break;
+		}
+		dialed_subaddress.str = c;
+		dialed_subaddress.valid = 1;
+	}
 
 	c = strchr(dest, '/');
 	if (c) {
@@ -2627,6 +2886,16 @@
 	}
 	pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
 
+#if defined(HAVE_PRI_SUBADDR)
+	if (dialed_subaddress.valid) {
+		struct pri_party_subaddress subaddress;
+
+		memset(&subaddress, 0, sizeof(subaddress));
+		sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
+		pri_sr_set_called_subaddress(sr, &subaddress);
+	}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
 	ldp_strip = 0;
 	prilocaldialplan = p->pri->localdialplan - 1;
 	if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
@@ -2702,6 +2971,17 @@
 	}
 	pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
 		p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
+
+#if defined(HAVE_PRI_SUBADDR)
+	if (ast->connected.id.subaddress.valid) {
+		struct pri_party_subaddress subaddress;
+
+		memset(&subaddress, 0, sizeof(subaddress));
+		sig_pri_party_subaddress_from_ast(&subaddress, &ast->connected.id.subaddress);
+		pri_sr_set_caller_subaddress(sr, &subaddress);
+	}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
 	sig_pri_redirecting_update(p, ast);
 
 #ifdef SUPPORT_USERUSER

Modified: team/rmudgett/subaddr/funcs/func_callerid.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/subaddr/funcs/func_callerid.c?view=diff&rev=224778&r1=224777&r2=224778
==============================================================================
--- team/rmudgett/subaddr/funcs/func_callerid.c (original)
+++ team/rmudgett/subaddr/funcs/func_callerid.c Tue Oct 20 13:14:57 2009
@@ -49,6 +49,12 @@
 					<enum name="RDNIS" />
 					<enum name="pres" />
 					<enum name="ton" />
+					<enum name="subaddr[-valid]|[-type]|[-odd]">
+						<para>ISDN Calling Subaddress</para>
+					</enum>
+					<enum name="dnid-subaddr[-valid]|[-type]|[-odd]">
+						<para>ISDN Called Subaddress</para>
+					</enum>
 				</enumlist>
 			</parameter>
 			<parameter name="CID">
@@ -167,8 +173,40 @@
 				ast_copy_string(buf, chan->cid.cid_ani, len);
 			}
 		} else if (!strncasecmp("dnid", data, 4)) {
-			if (chan->cid.cid_dnid) {
-				ast_copy_string(buf, chan->cid.cid_dnid, len);
+			/* Called parties info */
+
+			/* also matches dnid-subaddr-valid, dnid-subaddr-type, dnid-subaddr-odd, dnid-subaddr */
+			if (!strncasecmp(data + 4 ,"-subaddr", 8)) {
+				if (!strncasecmp(data + 12 ,"-valid", 6)) {		/* dnid-subaddr-valid */
+					snprintf(buf, len, "%d", chan->cid.dialed_subaddress.valid);
+				} else if (!strncasecmp(data + 12 ,"-type", 5)) {	/* dnid-subaddr-type */
+					snprintf(buf, len, "%d", chan->cid.dialed_subaddress.type);
+				} else if (!strncasecmp(data + 12 ,"-odd", 4)) {	/* dnid-subaddr-odd */
+					snprintf(buf, len, "%d", chan->cid.dialed_subaddress.odd_even_indicator);
+				} else {						/* dnid-subaddr */
+					if (chan->cid.dialed_subaddress.str) {
+						ast_copy_string(buf, chan->cid.dialed_subaddress.str, len);
+					}
+				}
+			} else {							/* dnid */
+				if (chan->cid.cid_dnid) {
+					ast_copy_string(buf, chan->cid.cid_dnid, len);
+				}
+			}
+		} else if (!strncasecmp("subaddr", data, 7)) {
+			/* Calling parties info */
+
+			/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
+			if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
+				snprintf(buf, len, "%d", chan->cid.subaddress.valid);
+			} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
+				snprintf(buf, len, "%d", chan->cid.subaddress.type);
+			} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
+				snprintf(buf, len, "%d", chan->cid.subaddress.odd_even_indicator);
+			} else {						/* subaddr */
+				if (chan->cid.subaddress.str) {
+					ast_copy_string(buf, chan->cid.subaddress.str, len);
+				}
 			}
 		} else if (!strncasecmp("rdnis", data, 5)) {
 			if (chan->cid.cid_rdnis) {
@@ -227,10 +265,46 @@
 		}
 	} else if (!strncasecmp("dnid", data, 4)) {
 		ast_channel_lock(chan);
-		if (chan->cid.cid_dnid) {
-			ast_free(chan->cid.cid_dnid);
-		}
-		chan->cid.cid_dnid = ast_strdup(value);
+		/* also matches dnid-subaddr-valid, dnid-subaddr-type, dnid-subaddr-odd, dnid-subaddr */
+		if (!strncasecmp(data + 4 ,"-subaddr", 8)) {
+			if (!strncasecmp(data + 12 ,"-valid", 6)) {		/* dnid-subaddr-valid */
+				chan->cid.dialed_subaddress.valid = atoi(value) ? 1 : 0;
+			} else if (!strncasecmp(data + 12 ,"-type", 5)) {	/* dnid-subaddr-type */
+				chan->cid.dialed_subaddress.type = atoi(value) ? 2 : 0;
+			} else if (!strncasecmp(data + 12 ,"-odd", 4)) {	/* dnid-subaddr-odd */
+				chan->cid.dialed_subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
+			} else {						/* dnid-subaddr */
+				if (chan->cid.dialed_subaddress.str) {
+					ast_free(chan->cid.dialed_subaddress.str);
+				}
+				chan->cid.dialed_subaddress.str = ast_strdup(value);
+			}
+		} else {							/* dnid */
+			if (chan->cid.cid_dnid) {
+				ast_free(chan->cid.cid_dnid);
+			}
+			chan->cid.cid_dnid = ast_strdup(value);
+		}
+
+		if (chan->cdr) {
+			ast_cdr_setcid(chan->cdr, chan);
+		}
+		ast_channel_unlock(chan);
+	} else if (!strncasecmp("subaddr", data, 7)) {
+		ast_channel_lock(chan);
+		/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
+		if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
+			chan->cid.subaddress.valid = atoi(value) ? 1 : 0;
+		} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
+			chan->cid.subaddress.type = atoi(value) ? 2 : 0;
+		} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
+			chan->cid.subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
+		} else {						/* subaddr */
+			if (chan->cid.subaddress.str) {
+				ast_free(chan->cid.subaddress.str);
+			}
+			chan->cid.subaddress.str = ast_strdup(value);
+		}
 		if (chan->cdr) {
 			ast_cdr_setcid(chan->cdr, chan);
 		}

Modified: team/rmudgett/subaddr/funcs/func_connectedline.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/subaddr/funcs/func_connectedline.c?view=diff&rev=224778&r1=224777&r2=224778
==============================================================================
--- team/rmudgett/subaddr/funcs/func_connectedline.c (original)
+++ team/rmudgett/subaddr/funcs/func_connectedline.c Tue Oct 20 13:14:57 2009
@@ -43,7 +43,7 @@
 
 /*
  * Do not document the CONNECTEDLINE(source) datatype.
- * It has turned out to not be needed.  The source value is really                                      .
+ * It has turned out to not be needed.  The source value is really
  * only useful as a possible tracing aid.
  */
 /*** DOCUMENTATION
@@ -60,6 +60,9 @@
 					<enum name = "name" />
 					<enum name = "ton" />
 					<enum name = "pres" />
+					<enum name = "subaddr[-valid]|[-type]|[-odd]">
+						<para>ISDN Connected line subaddress</para>
+					</enum>
 				</enumlist>
 			</parameter>
 			<parameter name="i">
@@ -102,6 +105,19 @@
 		ast_copy_string(buf, ast_named_caller_presentation(chan->connected.id.number_presentation), len);
 	} else if (!strncasecmp("source", data, 6)) {
 		ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
+	} else if (!strncasecmp("subaddr", data, 7)) {
+		/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
+		if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
+			snprintf(buf, len, "%d", chan->connected.id.subaddress.valid);
+		} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
+			snprintf(buf, len, "%d", chan->connected.id.subaddress.type);
+		} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
+			snprintf(buf, len, "%d", chan->connected.id.subaddress.odd_even_indicator);
+		} else {						/* subaddr */
+			if (chan->connected.id.subaddress.str) {
+				ast_copy_string(buf, chan->connected.id.subaddress.str, len);
+			}
+		}
 	} else {
 		ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
 	}
@@ -209,6 +225,21 @@
 			connected.source = source;
 			set_it(chan, &connected);
 		}
+	} else if (!strncasecmp("subaddr", data, 7)) { /* outbound: set calling subaddress */
+		/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
+		if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
+			chan->connected.id.subaddress.valid = atoi(value) ? 1 : 0;
+		} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
+			chan->connected.id.subaddress.type = atoi(value) ? 2 : 0;
+		} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
+			chan->connected.id.subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
+		} else {						/* subaddr */
+			if (chan->connected.id.subaddress.str) {
+				ast_free(chan->connected.id.subaddress.str);
+			}
+			chan->connected.id.subaddress.str = ast_strdup(value);
+		}
+		set_it(chan, &connected);
 	} else {
 		ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
 	}

Modified: team/rmudgett/subaddr/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/subaddr/include/asterisk/channel.h?view=diff&rev=224778&r1=224777&r2=224778
==============================================================================
--- team/rmudgett/subaddr/include/asterisk/channel.h (original)
+++ team/rmudgett/subaddr/include/asterisk/channel.h Tue Oct 20 13:14:57 2009
@@ -2669,6 +2669,16 @@
 
 /*!
  * \since 1.6.3
+ * \brief Initialize the given subaddress structure.
+ *
+ * \param init Subaddress structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_init(struct ast_party_subaddress *init);
+
+/*!
+ * \since 1.6.3
  * \brief Indicate that the redirecting id has changed
  *
  * \param chan Asterisk channel to indicate redirecting id information

Modified: team/rmudgett/subaddr/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/subaddr/main/channel.c?view=diff&rev=224778&r1=224777&r2=224778
==============================================================================
--- team/rmudgett/subaddr/main/channel.c (original)
+++ team/rmudgett/subaddr/main/channel.c Tue Oct 20 13:14:57 2009
@@ -210,6 +210,8 @@
 	return var;
 }
 
+static void ast_party_subaddress_free(struct ast_party_subaddress *doomed);
+
 /*! \brief Show channel types - CLI command */
 static char *handle_cli_core_show_channeltypes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
@@ -1503,6 +1505,8 @@
 	if (cid->cid_rdnis)
 		ast_free(cid->cid_rdnis);
 	cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = cid->cid_rdnis = NULL;
+	ast_party_subaddress_free(&cid->subaddress);
+	ast_party_subaddress_free(&cid->dialed_subaddress);
 }
 
 struct ast_channel *ast_channel_release(struct ast_channel *chan)
@@ -1510,6 +1514,121 @@
 	/* Safe, even if already unlinked. */
 	ao2_unlink(channels, chan);
 	return ast_channel_unref(chan);
+}
+
+/*!
+ * \internal
+ * \brief Initialize the given subaddress structure.
+ * \since 1.6.3
+ *
+ * \param init Subaddress structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_init(struct ast_party_subaddress *init)
+{
+	init->str = NULL;
+	init->type = 0;
+	init->odd_even_indicator = 0;
+	init->valid = 0;
+}
+
+/*!
+ * \internal
+ * \brief Copy the source party subaddress information to the destination party subaddress.
+ * \since 1.6.3
+ *
+ * \param dest Destination party subaddress
+ * \param src Source party subaddress
+ *
+ * \return Nothing
+ */
+static void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src)
+{
+	if (dest == src) {
+		/* Don't copy to self */
+		return;
+	}
+
+	if (dest->str) {
+		ast_free(dest->str);
+	}
+	dest->str = ast_strdup(src->str);
+	dest->type = src->type;
+	dest->odd_even_indicator = src->odd_even_indicator;
+	dest->valid = src->valid;
+}
+
+/*!
+ * \internal
+ * \brief Initialize the given party subadress structure using the given guide
+ * for a set update operation.
+ * \since 1.6.3
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated.  Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Party Subaddress structure to initialize.
+ * \param guide Source party subaddress to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+static void ast_party_subaddress_set_init(struct ast_party_subaddress *init, const struct ast_party_subaddress *guide)
+{
+	init->str = NULL;
+	init->type = guide->type;
+	init->odd_even_indicator = guide->odd_even_indicator;
+	init->valid = guide->valid;
+}
+
+/*!
+ * \internal
+ * \brief Set the source party subaddress information into the destination party subaddress.
+ * \since 1.6.3
+ *
+ * \param dest Destination party subaddress
+ * \param src Source party subaddress
+ *
+ * \return Nothing
+ */
+static void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src)
+{
+	if (dest == src) {
+		/* Don't set to self */
+		return;
+	}
+
+	if (src->str && src->str != dest->str) {
+		if (dest->str) {
+			ast_free(dest->str);
+		}
+		dest->str = ast_strdup(src->str);
+	}
+
+	dest->type = src->type;
+	dest->odd_even_indicator = src->odd_even_indicator;
+	dest->valid = src->valid;
+}
+
+/*!
+ * \internal
+ * \brief Destroy the party subaddress contents
+ * \since 1.6.3
+ *
+ * \param doomed The party subaddress to destroy.
+ *
+ * \return Nothing
+ */
+static void ast_party_subaddress_free(struct ast_party_subaddress *doomed)
+{
+	if (doomed->str) {
+		ast_free(doomed->str);
+		doomed->str = NULL;
+	}
 }
 
 /*!
@@ -1526,6 +1645,7 @@
 	init->name = NULL;
 	init->number_type = 0;	/* Unknown */
 	init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	ast_party_subaddress_init(&init->subaddress);
 }
 
 /*!
@@ -1556,6 +1676,7 @@
 
 	dest->number_type = src->number_type;
 	dest->number_presentation = src->number_presentation;
+	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
 }
 
 /*!
@@ -1581,6 +1702,7 @@
 	init->name = NULL;
 	init->number_type = guide->number_type;
 	init->number_presentation = guide->number_presentation;
+	ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
 }
 
 /*!
@@ -1615,6 +1737,7 @@
 
 	dest->number_type = src->number_type;
 	dest->number_presentation = src->number_presentation;
+	ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
 }
 
 /*!
@@ -1636,6 +1759,7 @@
 		ast_free(doomed->name);
 		doomed->name = NULL;
 	}
+	ast_party_subaddress_free(&doomed->subaddress);
 }
 
 void ast_party_caller_init(struct ast_party_caller *init)
@@ -1678,6 +1802,8 @@
 
 	dest->cid_ani2 = src->cid_ani2;
 
+	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
+
 #else
 
 	/* The src and dest parameter types will become struct ast_party_caller ptrs. */
@@ -1749,6 +1875,7 @@
 	connected->id.name = cid->cid_name;
 	connected->id.number_type = cid->cid_ton;
 	connected->id.number_presentation = cid->cid_pres;
+	connected->id.subaddress = cid->subaddress;
 
 	connected->ani = cid->cid_ani;
 	connected->ani2 = cid->cid_ani2;
@@ -6565,6 +6692,7 @@
 	dest->ani = ast_strdup(src->cid_ani);
 
 	dest->ani2 = src->cid_ani2;
+	ast_party_subaddress_copy(&dest->id.subaddress, &src->subaddress);
 
 #else
 
@@ -6606,6 +6734,7 @@
 	dest->cid_ani = ast_strdup(src->ani);
 
 	dest->cid_ani2 = src->ani2;
+	ast_party_subaddress_copy(&dest->subaddress, &src->id.subaddress);
 
 #else
 
@@ -6644,7 +6773,11 @@
 	AST_CONNECTED_LINE_NAME,
 	AST_CONNECTED_LINE_NUMBER_TYPE,
 	AST_CONNECTED_LINE_NUMBER_PRESENTATION,
-	AST_CONNECTED_LINE_SOURCE
+	AST_CONNECTED_LINE_SOURCE,
+	AST_CONNECTED_LINE_SUBADDRESS,
+	AST_CONNECTED_LINE_SUBADDRESS_TYPE,
+	AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN,
+	AST_CONNECTED_LINE_SUBADDRESS_VALID
 };
 
 int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected)
@@ -6710,6 +6843,46 @@
 	memcpy(data + pos, &value, sizeof(value));
 	pos += sizeof(value);
 
+	/* Connected line Subaddress */
+	if (connected->id.subaddress.str) {
+		length = strlen(connected->id.subaddress.str);
+		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+			ast_log(LOG_WARNING, "No space left for connected line subaddress\n");
+			return -1;
+		}
+		data[pos++] = AST_CONNECTED_LINE_SUBADDRESS;
+		data[pos++] = length;
+		memcpy(data + pos, connected->id.subaddress.str, length);
+		pos += length;
+	}
+	/* Connected line Subaddress Type */
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for connected line type of subaddress\n");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_TYPE;
+	data[pos++] = 1;
+	data[pos++] = connected->id.subaddress.type;
+
+	/* Connected line Subaddress Odd/Even indicator */
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING,
+			"No space left for connected line subaddress odd-even indicator\n");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN;
+	data[pos++] = 1;
+	data[pos++] = connected->id.subaddress.odd_even_indicator;
+
+	/* Connected line Subaddress Valid */
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for connected line subaddress valid\n");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_VALID;
+	data[pos++] = 1;
+	data[pos++] = connected->id.subaddress.valid;
+
 	return pos;
 }
 
@@ -6774,6 +6947,41 @@
 			}
 			memcpy(&value, data + pos, sizeof(value));
 			connected->source = ntohl(value);
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS:
+			if (connected->id.subaddress.str) {
+				ast_free(connected->id.subaddress.str);
+			}
+			connected->id.subaddress.str = ast_malloc(ie_len + 1);
+			if (connected->id.subaddress.str) {
+				memcpy(connected->id.subaddress.str, data + pos, ie_len);
+				connected->id.subaddress.str[ie_len] = 0;
+			}
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS_TYPE:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line type of subaddress (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.subaddress.type = data[pos];
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING,
+					"Invalid connected line subaddress odd-even indicator (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.subaddress.odd_even_indicator = data[pos];
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line subaddress valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.subaddress.valid = data[pos];
 			break;
 		default:
 			ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
@@ -6853,7 +7061,15 @@
 	AST_REDIRECTING_TO_NUMBER_TYPE,
 	AST_REDIRECTING_TO_NUMBER_PRESENTATION,
 	AST_REDIRECTING_REASON,
-	AST_REDIRECTING_COUNT
+	AST_REDIRECTING_COUNT,
+	AST_REDIRECTING_FROM_SUBADDRESS,
+	AST_REDIRECTING_FROM_SUBADDRESS_TYPE,
+	AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN,
+	AST_REDIRECTING_FROM_SUBADDRESS_VALID,
+	AST_REDIRECTING_TO_SUBADDRESS,
+	AST_REDIRECTING_TO_SUBADDRESS_TYPE,
+	AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN,
+	AST_REDIRECTING_TO_SUBADDRESS_VALID
 };
 
 int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting)
@@ -6908,6 +7124,44 @@
 	data[pos++] = 1;
 	data[pos++] = redirecting->from.number_presentation;
 
+	/* subaddress */
+	if (redirecting->from.subaddress.str) {
+		length = strlen(redirecting->from.subaddress.str);
+		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+			ast_log(LOG_WARNING, "No space left for redirecting-from subaddress\n");
+			return -1;
+		}
+		data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS;
+		data[pos++] = length;
+		memcpy(data + pos, redirecting->from.subaddress.str, length);
+		pos += length;
+	}
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for redirecting-from type of subaddress\n");
+		return -1;
+	}
+	data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS_TYPE;
+	data[pos++] = 1;
+	data[pos++] = redirecting->from.subaddress.type;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING,
+			"No space left for redirecting-from subaddress odd-even indicator\n");
+		return -1;
+	}
+	data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN;
+	data[pos++] = 1;
+	data[pos++] = redirecting->from.subaddress.odd_even_indicator;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for redirecting-from subaddress valid\n");
+		return -1;
+	}
+	data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS_VALID;
+	data[pos++] = 1;
+	data[pos++] = redirecting->from.subaddress.valid;
+
 	/* *************** Redirecting to party id *************** */
 	if (redirecting->to.number) {
 		length = strlen(redirecting->to.number);
@@ -6949,6 +7203,44 @@
 	data[pos++] = 1;
 	data[pos++] = redirecting->to.number_presentation;
 
+	/* subaddress */
+	if (redirecting->to.subaddress.str) {
+		length = strlen(redirecting->to.subaddress.str);
+		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+			ast_log(LOG_WARNING, "No space left for redirecting-to subaddress\n");
+			return -1;
+		}
+		data[pos++] = AST_REDIRECTING_TO_SUBADDRESS;
+		data[pos++] = length;
+		memcpy(data + pos, redirecting->to.subaddress.str, length);
+		pos += length;
+	}
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for redirecting-to type of subaddress\n");
+		return -1;
+	}
+	data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_TYPE;
+	data[pos++] = 1;
+	data[pos++] = redirecting->to.subaddress.type;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING,
+			"No space left for redirecting-to subaddress odd-even indicator\n");
+		return -1;
+	}
+	data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN;
+	data[pos++] = 1;
+	data[pos++] = redirecting->to.subaddress.odd_even_indicator;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for redirecting-to subaddress valid\n");
+		return -1;
+	}
+	data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_VALID;
+	data[pos++] = 1;
+	data[pos++] = redirecting->to.subaddress.valid;
+
 	/* Redirecting reason */
 	if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
 		ast_log(LOG_WARNING, "No space left for redirecting reason\n");
@@ -7028,6 +7320,41 @@
 			}
 			redirecting->from.number_presentation = data[pos];
 			break;
+		case AST_REDIRECTING_FROM_SUBADDRESS:
+			if (redirecting->from.subaddress.str) {
+				ast_free(redirecting->from.subaddress.str);
+			}
+			redirecting->from.subaddress.str = ast_malloc(ie_len + 1);
+			if (redirecting->from.subaddress.str) {
+				memcpy(redirecting->from.subaddress.str, data + pos, ie_len);
+				redirecting->from.subaddress.str[ie_len] = 0;
+			}
+			break;
+		case AST_REDIRECTING_FROM_SUBADDRESS_TYPE:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting from type of subaddress (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->from.subaddress.type = data[pos];
+			break;
+		case AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING,
+					"Invalid redirecting from subaddress odd-even indicator (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->from.subaddress.odd_even_indicator = data[pos];
+			break;
+		case AST_REDIRECTING_FROM_SUBADDRESS_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting from subaddress valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->from.subaddress.valid = data[pos];
+			break;
 		case AST_REDIRECTING_TO_NUMBER:
 			if (redirecting->to.number) {
 				ast_free(redirecting->to.number);
@@ -7061,6 +7388,41 @@
 				break;
 			}
 			redirecting->to.number_presentation = data[pos];
+			break;
+		case AST_REDIRECTING_TO_SUBADDRESS:
+			if (redirecting->to.subaddress.str) {
+				ast_free(redirecting->to.subaddress.str);
+			}
+			redirecting->to.subaddress.str = ast_malloc(ie_len + 1);
+			if (redirecting->to.subaddress.str) {
+				memcpy(redirecting->to.subaddress.str, data + pos, ie_len);
+				redirecting->to.subaddress.str[ie_len] = 0;
+			}
+			break;
+		case AST_REDIRECTING_TO_SUBADDRESS_TYPE:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting to type of subaddress (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->to.subaddress.type = data[pos];
+			break;
+		case AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING,
+					"Invalid redirecting to subaddress odd-even indicator (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->to.subaddress.odd_even_indicator = data[pos];
+			break;
+		case AST_REDIRECTING_TO_SUBADDRESS_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting to subaddress valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->to.subaddress.valid = data[pos];
 			break;
 		case AST_REDIRECTING_REASON:
 			if (ie_len != sizeof(value)) {




More information about the svn-commits mailing list