<p>Kevin Harwell <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/8803">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Richard Mudgett: Looks good to me, but someone else must approve
Kevin Harwell: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_mobile: support handling of caller-id names ("cnam").<br><br>Add support to handle caller-ID names ("cnam") in addition to caller-ID<br>numbers. The prior code ignored the caller-ID name altogether, and<br>used the local name for the cell phone (e.g. "my-iphone") in its place.<br><br>Note: as of this writing, at least some Android phones don't pass cnam to<br>us. This can be seen by issuing "core set debug 2" in the CLI and watching<br>the "CLIP" record when a call comes in. If cnam isn't in the CLIP record,<br>there's nothing we can do to provide one. We'll provide a null cnam field,<br>so later Asterisk processes know to try other sources (e.g. cidname database,<br>OpenCNAM, etc.).<br><br>Reported by: Brian Martin<br>Tested by: Brian Martin<br>ASTERISK-27726<br><br>Change-Id: I89490d85fa406c36261879c50ae5e65595538ba5<br>---<br>M addons/chan_mobile.c<br>1 file changed, 106 insertions(+), 40 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c<br>index 7d92f8d..427977d 100644<br>--- a/addons/chan_mobile.c<br>+++ b/addons/chan_mobile.c<br>@@ -56,6 +56,7 @@<br> <br> #include "asterisk/compat.h"<br> #include "asterisk/lock.h"<br>+#include "asterisk/callerid.h"<br> #include "asterisk/channel.h"<br> #include "asterisk/config.h"<br> #include "asterisk/logger.h"<br>@@ -161,6 +162,12 @@<br> AST_LIST_ENTRY(mbl_pvt) entry;<br> };<br> <br>+/*! Structure used by hfp_parse_clip to return two items */<br>+struct cidinfo {<br>+ char *cnum;<br>+ char *cnam;<br>+};<br>+<br> static AST_RWLIST_HEAD_STATIC(devices, mbl_pvt);<br> <br> static int handle_response_ok(struct mbl_pvt *pvt, char *buf);<br>@@ -206,7 +213,7 @@<br> " Dest - destination\n"<br> " Message - text of the message\n";<br> <br>-static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num,<br>+static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo,<br> const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor);<br> static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap,<br> const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);<br>@@ -362,7 +369,8 @@<br> <br> <br> static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value);<br>-static char *hfp_parse_clip(struct hfp_pvt *hfp, char *buf);<br>+static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf);<br>+static int parse_next_token(char string[], const int start, const char delim);<br> static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf);<br> static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text);<br> static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf);<br>@@ -835,7 +843,7 @@<br> <br> */<br> <br>-static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num,<br>+static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo,<br> const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)<br> {<br> struct ast_channel *chn;<br>@@ -851,9 +859,11 @@<br> ast_smoother_reset(pvt->smoother, DEVICE_FRAME_SIZE);<br> ast_dsp_digitreset(pvt->dsp);<br> <br>- chn = ast_channel_alloc(1, state, cid_num, pvt->id, 0, 0, pvt->context,<br>- assignedids, requestor, 0,<br>- "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);<br>+ chn = ast_channel_alloc(1, state,<br>+ cidinfo ? cidinfo->cnum : NULL,<br>+ cidinfo ? cidinfo->cnam : NULL,<br>+ 0, 0, pvt->context, assignedids, requestor, 0,<br>+ "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);<br> if (!chn) {<br> goto e_return;<br> }<br>@@ -2201,45 +2211,103 @@<br> * \param hfp an hfp_pvt struct<br> * \param buf the buffer to parse (null terminated)<br> * \note buf will be modified when the CID string is parsed<br>- * \return NULL on error (parse error) or a pointer to the caller id<br>- * information in buf<br>+ * \return a cidinfo structure pointing to the cnam and cnum<br>+ * data in buf. On parse errors, either or both pointers<br>+ * will point to null strings<br> */<br>-static char *hfp_parse_clip(struct hfp_pvt *hfp, char *buf)<br>+static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf)<br> {<br>- int i, state;<br>- char *clip = NULL;<br>- size_t s;<br>+ int i;<br>+ int tokens[6];<br>+ char *cnamtmp;<br>+ char delim = ' '; /* First token terminates with space */<br>+ int invalid = 0; /* Number of invalid chars in cnam */<br>+ struct cidinfo cidinfo = { NULL, NULL };<br> <br> /* parse clip info in the following format:<br> * +CLIP: "123456789",128,...<br> */<br>- state = 0;<br>- s = strlen(buf);<br>- for (i = 0; i < s && state != 3; i++) {<br>- switch (state) {<br>- case 0: /* search for start of the number (") */<br>- if (buf[i] == '"') {<br>- state++;<br>- }<br>- break;<br>- case 1: /* mark the number */<br>- clip = &buf[i];<br>- state++;<br>- /* fall through */<br>- case 2: /* search for the end of the number (") */<br>- if (buf[i] == '"') {<br>- buf[i] = '\0';<br>- state++;<br>- }<br>- break;<br>+ ast_debug(3, "[%s] hfp_parse_clip is processing \"%s\"\n", hfp->owner->id, buf);<br>+ tokens[0] = 0; /* First token starts in position 0 */<br>+ for (i = 1; i < ARRAY_LEN(tokens); i++) {<br>+ tokens[i] = parse_next_token(buf, tokens[i - 1], delim);<br>+ delim = ','; /* Subsequent tokens terminate with comma */<br>+ }<br>+ ast_debug(3, "[%s] hfp_parse_clip found tokens: 0=%s, 1=%s, 2=%s, 3=%s, 4=%s, 5=%s\n",<br>+ hfp->owner->id, &buf[tokens[0]], &buf[tokens[1]], &buf[tokens[2]],<br>+ &buf[tokens[3]], &buf[tokens[4]], &buf[tokens[5]]);<br>+<br>+ /* Clean up cnum, and make sure it is legitimate since it is untrusted. */<br>+ cidinfo.cnum = ast_strip_quoted(&buf[tokens[1]], "\"", "\"");<br>+ if (!ast_isphonenumber(cidinfo.cnum)) {<br>+ ast_debug(1, "[%s] hfp_parse_clip invalid cidinfo.cnum data \"%s\" - deleting\n",<br>+ hfp->owner->id, cidinfo.cnum);<br>+ cidinfo.cnum = "";<br>+ }<br>+<br>+ /*<br>+ * Some docs say tokens 2 and 3 including the commas are optional.<br>+ * If absent, that would move CNAM back to token 3.<br>+ */<br>+ cidinfo.cnam = &buf[tokens[5]]; /* Assume it's in token 5 */<br>+ if (buf[tokens[5]] == '\0' && buf[tokens[4]] == '\0') {<br>+ /* Tokens 4 and 5 are empty. See if token 3 looks like CNAM (starts with ") */<br>+ i = tokens[3];<br>+ while (buf[i] == ' ') { /* Find the first non-blank */<br>+ i++;<br>+ }<br>+ if (buf[i] == '"') {<br>+ /* Starts with quote. Use this for CNAM. */<br>+ cidinfo.cnam = &buf[i];<br> }<br> }<br> <br>- if (state != 3) {<br>- return NULL;<br>+ /* Clean up CNAM. */<br>+ cidinfo.cnam = ast_strip_quoted(cidinfo.cnam, "\"", "\"");<br>+ for (cnamtmp = cidinfo.cnam; *cnamtmp != '\0'; cnamtmp++) {<br>+ if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789-,abcdefghijklmnopqrstuvwxyz_", *cnamtmp)) {<br>+ *cnamtmp = '_'; /* Invalid. Replace with underscore. */<br>+ invalid++;<br>+ }<br> }<br>+ if (invalid) {<br>+ ast_debug(2, "[%s] hfp_parse_clip replaced %d invalid byte(s) in cnam data\n",<br>+ hfp->owner->id, invalid);<br>+ }<br>+ ast_debug(2, "[%s] hfp_parse_clip returns cnum=%s and cnam=%s\n",<br>+ hfp->owner->id, cidinfo.cnum, cidinfo.cnam);<br> <br>- return clip;<br>+ return cidinfo;<br>+}<br>+<br>+/*!<br>+ * \brief Terminate current token and return an index to start of the next token.<br>+ * \param string the null-terminated string being parsed (will be altered!)<br>+ * \param start where the current token starts<br>+ * \param delim the token termination delimiter. \0 is also considered a terminator.<br>+ * \return index of the next token. May be the same as this token if the string is<br>+ * exhausted.<br>+ */<br>+static int parse_next_token(char string[], const int start, const char delim)<br>+{<br>+ int index;<br>+ int quoting = 0;<br>+<br>+ for (index = start; string[index] != 0; index++) {<br>+ if ((string[index] == delim) && !quoting ) {<br>+ /* Found the delimiter, outside of quotes. This is the end of the token. */<br>+ string[index] = '\0'; /* Terminate this token. */<br>+ index++; /* Point the index to the start of the next token. */<br>+ break; /* We're done. */<br>+ } else if (string[index] == '"' && !quoting) {<br>+ /* Found a beginning quote mark. Remember it. */<br>+ quoting = 1;<br>+ } else if (string[index] == '"' ) {<br>+ /* Found the end quote mark. */<br>+ quoting = 0;<br>+ }<br>+ }<br>+ return index;<br> }<br> <br> /*!<br>@@ -3576,19 +3644,17 @@<br> */<br> static int handle_response_clip(struct mbl_pvt *pvt, char *buf)<br> {<br>- char *clip;<br> struct msg_queue_entry *msg;<br> struct ast_channel *chan;<br>+ struct cidinfo cidinfo;<br> <br> if ((msg = msg_queue_head(pvt)) && msg->expected == AT_CLIP) {<br> msg_queue_free_and_pop(pvt);<br> <br> pvt->needcallerid = 0;<br>- if (!(clip = hfp_parse_clip(pvt->hfp, buf))) {<br>- ast_debug(1, "[%s] error parsing CLIP: %s\n", pvt->id, buf);<br>- }<br>+ cidinfo = hfp_parse_clip(pvt->hfp, buf);<br> <br>- if (!(chan = mbl_new(AST_STATE_RING, pvt, clip, NULL, NULL))) {<br>+ if (!(chan = mbl_new(AST_STATE_RING, pvt, &cidinfo, NULL, NULL))) {<br> ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);<br> hfp_send_chup(pvt->hfp);<br> msg_queue_push(pvt, AT_OK, AT_CHUP);<br>@@ -3857,7 +3923,7 @@<br> break;<br> }<br> <br>- ast_debug(1, "[%s] %s\n", pvt->id, buf);<br>+ ast_debug(1, "[%s] read %s\n", pvt->id, buf);<br> <br> switch (at_msg) {<br> case AT_BRSF:<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8803">change 8803</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/8803"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I89490d85fa406c36261879c50ae5e65595538ba5 </div>
<div style="display:none"> Gerrit-Change-Number: 8803 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: B. Martin <asterisk-forum@silverflash.net> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>