[Asterisk-cvs] asterisk/channels chan_sip.c,1.672,1.673
markster at lists.digium.com
markster at lists.digium.com
Mon Mar 14 23:55:19 CST 2005
Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv15860/channels
Modified Files:
chan_sip.c
Log Message:
Merge tony's refactoring code with small mods (bug #3710)
Index: chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.672
retrieving revision 1.673
diff -u -d -r1.672 -r1.673
--- chan_sip.c 9 Mar 2005 04:56:51 -0000 1.672
+++ chan_sip.c 15 Mar 2005 05:50:58 -0000 1.673
@@ -5358,135 +5358,171 @@
return 0;
}
+/*--- get_sip_pvt_byid_locked: Lock interface lock and find matching pvt lock ---*/
+static struct sip_pvt *get_sip_pvt_byid_locked(char *callid)
+{
+ struct sip_pvt *sip_pvt_ptr = NULL;
+
+ /* Search interfaces and find the match */
+ ast_mutex_lock(&iflock);
+ sip_pvt_ptr = iflist;
+ while(sip_pvt_ptr) {
+ if (!strcmp(sip_pvt_ptr->callid, callid)) {
+ /* Go ahead and lock it (and its owner) before returning */
+ ast_mutex_lock(&sip_pvt_ptr->lock);
+ if (sip_pvt_ptr->owner) {
+ while(ast_mutex_trylock(&sip_pvt_ptr->owner->lock)) {
+ ast_mutex_unlock(&sip_pvt_ptr->lock);
+ usleep(1);
+ ast_mutex_lock(&sip_pvt_ptr->lock);
+ if (!sip_pvt_ptr->owner)
+ break;
+ }
+ }
+ break;
+ }
+ sip_pvt_ptr = sip_pvt_ptr->next;
+ }
+ ast_mutex_unlock(&iflock);
+ return sip_pvt_ptr;
+}
+
+/*--- sip_unescape_uri: Turn %XX into and ascii char ---*/
+static int sip_unescape_uri(char *uri)
+{
+ char *ptr = uri;
+ int replaced = 0;
+
+ while ((ptr = strchr(ptr, '%'))) {
+ /* un-escape urlencoded text */
+ if (strlen(ptr) < 3)
+ break;
+ *ptr = hex2int(ptr[1]) * 16 + hex2int(ptr[2]);
+ memmove(ptr+1, ptr+3, strlen(ptr+3) + 1);
+ ptr++;
+ replaced++;
+ }
+
+ return replaced;
+}
+
+
+
/*--- get_refer_info: Call transfer support (new standard) ---*/
-static int get_refer_info(struct sip_pvt *p, struct sip_request *oreq)
+static int get_refer_info(struct sip_pvt *sip_pvt, struct sip_request *outgoing_req)
{
- char tmp[256] = "", *c, *a;
- char tmp2[256] = "", *c2, *a2;
- char tmp3[256];
- char tmp4[256];
- char tmp5[256] = ""; /* CallID to replace */
- struct sip_request *req;
- struct sip_pvt *p2;
+
+ char *p_refer_to = NULL, *p_referred_by = NULL, *h_refer_to = NULL, *h_referred_by = NULL, *h_contact = NULL;
+ char *replace_callid = "", *refer_to = NULL, *referred_by = NULL, *ptr = NULL;
+ struct sip_request *req = NULL;
+ struct sip_pvt *sip_pvt_ptr = NULL;
struct ast_channel *chan = NULL, *peer = NULL;
- req = oreq;
- if (!req)
- req = &p->initreq;
- strncpy(tmp, get_header(req, "Refer-To"), sizeof(tmp) - 1);
- strncpy(tmp2, get_header(req, "Referred-By"), sizeof(tmp2) - 1);
- strncpy(tmp3, get_header(req, "Contact"), sizeof(tmp3) - 1);
- strncpy(tmp4, get_header(req, "Remote-Party-ID"), sizeof(tmp4) - 1);
+ req = outgoing_req;
+
+ if (!req) {
+ req = &sip_pvt->initreq;
+ }
- c = ditch_braces(tmp);
- c2 = ditch_braces(tmp2);
+ if(!( (p_refer_to = get_header(req, "Refer-To")) && (h_refer_to = ast_strdupa(p_refer_to)) )) {
+ ast_log(LOG_WARNING, "No Refer-To Header That's illegal\n");
+ return -1;
+ }
+
+ refer_to = ditch_braces(h_refer_to);
+
+ if(!( (p_referred_by = get_header(req, "Referred-By")) && (h_referred_by = ast_strdupa(p_referred_by)) )) {
+ ast_log(LOG_WARNING, "No Refer-To Header That's illegal\n");
+ return -1;
+ }
+
+ referred_by = ditch_braces(h_referred_by);
+ h_contact = get_header(req, "Contact");
-
- if (strncmp(c, "sip:", 4) && strncmp(c2, "sip:", 4)) {
- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c2);
+ if (strncmp(refer_to, "sip:", 4) && strncmp(referred_by, "sip:", 4)) {
+ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", refer_to);
+ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", referred_by);
return -1;
}
- c += 4;
- c2 += 4;
- if ((a = strchr(c, '?'))) {
+ refer_to += 4;
+ referred_by += 4;
+
+
+ if ((ptr = strchr(refer_to, '?'))) {
/* Search for arguemnts */
- *a = '\0';
- a++;
- if (!strncasecmp(a, "REPLACES=", strlen("REPLACES="))) {
- strncpy(tmp5, a + strlen("REPLACES="), sizeof(tmp5) - 1);
- a = tmp5;
- while ((a = strchr(a, '%'))) {
- /* Yuck! Pingtel converts the '@' to a %40, icky icky! Convert
- back to an '@' */
- if (strlen(a) < 3)
- break;
- *a = hex2int(a[1]) * 16 + hex2int(a[2]);
- memmove(a + 1, a+3, strlen(a + 3) + 1);
- a++;
- }
- if ((a = strchr(tmp5, '%')))
- *a = '\0';
- if ((a = strchr(tmp5, ';')))
- *a = '\0';
+ *ptr = '\0';
+ ptr++;
+ if (!strncasecmp(ptr, "REPLACES=", 9)) {
+ replace_callid = ast_strdupa(ptr + 9);
+ /* someday soon to support invite/replaces properly!
+ replaces_header = ast_strdupa(replace_callid);
+ -anthm
+ */
+ sip_unescape_uri(replace_callid);
+ if ((ptr = strchr(replace_callid, '%')))
+ *ptr = '\0';
+ if ((ptr = strchr(replace_callid, ';')))
+ *ptr = '\0';
/* Skip leading whitespace */
- while(tmp5[0] && (tmp5[0] < 33))
- memmove(tmp5, tmp5+1, strlen(tmp5));
-
+ while(replace_callid[0] && (replace_callid[0] < 33))
+ memmove(replace_callid, replace_callid+1, strlen(replace_callid));
}
}
- if ((a = strchr(c, '@')))
- *a = '\0';
- if ((a = strchr(c, ';')))
- *a = '\0';
-
-
- if ((a2 = strchr(c2, '@')))
- *a2 = '\0';
-
- if ((a2 = strchr(c2, ';')))
- *a2 = '\0';
+ if ((ptr = strchr(refer_to, '@')))
+ *ptr = '\0';
+ if ((ptr = strchr(refer_to, ';')))
+ *ptr = '\0';
+ if ((ptr = strchr(referred_by, '@')))
+ *ptr = '\0';
+ if ((ptr = strchr(referred_by, ';')))
+ *ptr = '\0';
- if (sip_debug_test_pvt(p)) {
- ast_verbose("Looking for %s in %s\n", c, p->context);
- ast_verbose("Looking for %s in %s\n", c2, p->context);
+ if (sip_debug_test_pvt(sip_pvt)) {
+ ast_verbose("Looking for %s in %s\n", refer_to, sip_pvt->context);
+ ast_verbose("Looking for %s in %s\n", referred_by, sip_pvt->context);
}
- if (!ast_strlen_zero(tmp5)) {
+ if (!ast_strlen_zero(replace_callid)) {
/* This is a supervised transfer */
- ast_log(LOG_DEBUG,"Assigning Replace-Call-ID Info %s to REPLACE_CALL_ID\n",tmp5);
+ ast_log(LOG_DEBUG,"Assigning Replace-Call-ID Info %s to REPLACE_CALL_ID\n",replace_callid);
- strncpy(p->refer_to, "", sizeof(p->refer_to) - 1);
- strncpy(p->referred_by, "", sizeof(p->referred_by) - 1);
- strncpy(p->refer_contact, "", sizeof(p->refer_contact) - 1);
- p->refer_call = NULL;
- ast_mutex_lock(&iflock);
- /* Search interfaces and find the match */
- p2 = iflist;
- while(p2) {
- if (!strcmp(p2->callid, tmp5)) {
- /* Go ahead and lock it (and its owner) before returning */
- ast_mutex_lock(&p2->lock);
- if (p2->owner) {
- while(ast_mutex_trylock(&p2->owner->lock)) {
- ast_mutex_unlock(&p2->lock);
- usleep(1);
- ast_mutex_lock(&p2->lock);
- if (!p2->owner)
- break;
- }
- }
- p->refer_call = p2;
- break;
- }
- p2 = p2->next;
- }
- ast_mutex_unlock(&iflock);
- if (p->refer_call) {
- if (p->refer_call == p) {
- ast_log(LOG_NOTICE, "Supervised transfer attempted to transfer into same call id (%s == %s)!\n", tmp5, p->callid);
- p->refer_call = NULL;
+ strncpy(sip_pvt->refer_to, "", sizeof(sip_pvt->refer_to) - 1);
+ strncpy(sip_pvt->referred_by, "", sizeof(sip_pvt->referred_by) - 1);
+ strncpy(sip_pvt->refer_contact, "", sizeof(sip_pvt->refer_contact) - 1);
+ sip_pvt->refer_call = NULL;
+ if ((sip_pvt_ptr = get_sip_pvt_byid_locked(replace_callid))) {
+ sip_pvt->refer_call = sip_pvt_ptr;
+ if (sip_pvt->refer_call == sip_pvt) {
+ ast_log(LOG_NOTICE, "Supervised transfer attempted to transfer into same call id (%s == %s)!\n", replace_callid, sip_pvt->callid);
+ sip_pvt->refer_call = NULL;
} else
return 0;
- } else
- ast_log(LOG_NOTICE, "Supervised transfer requested, but unable to find callid '%s'\n", tmp5);
- } else if (ast_exists_extension(NULL, p->context, c, 1, NULL) || !strcmp(c, ast_parking_ext())) {
+ } else {
+ ast_log(LOG_NOTICE, "Supervised transfer requested, but unable to find callid '%s'. Both legs must reside on Asterisk box to transfer at this time.\n", replace_callid);
+ /* XXX The refer_to could contain a call on an entirely different machine, requiring an
+ INVITE with a replaces header -anthm XXX */
+
+
+ }
+ } else if (ast_exists_extension(NULL, sip_pvt->context, refer_to, 1, NULL) || !strcmp(refer_to, ast_parking_ext())) {
/* This is an unsupervised transfer */
- ast_log(LOG_DEBUG,"Assigning Extension %s to REFER-TO\n", c);
- ast_log(LOG_DEBUG,"Assigning Extension %s to REFERRED-BY\n", c2);
- ast_log(LOG_DEBUG,"Assigning Contact Info %s to REFER_CONTACT\n", tmp3);
- strncpy(p->refer_to, c, sizeof(p->refer_to) - 1);
- strncpy(p->referred_by, c2, sizeof(p->referred_by) - 1);
- strncpy(p->refer_contact, tmp3, sizeof(p->refer_contact) - 1);
- p->refer_call = NULL;
- if((chan = p->owner) && (peer = ast_bridged_channel(p->owner))) {
+ ast_log(LOG_DEBUG,"Assigning Extension %s to REFER-TO\n", refer_to);
+ ast_log(LOG_DEBUG,"Assigning Extension %s to REFERRED-BY\n", referred_by);
+ ast_log(LOG_DEBUG,"Assigning Contact Info %s to REFER_CONTACT\n", h_contact);
+ strncpy(sip_pvt->refer_to, refer_to, sizeof(sip_pvt->refer_to) - 1);
+ strncpy(sip_pvt->referred_by, referred_by, sizeof(sip_pvt->referred_by) - 1);
+ if (h_contact) {
+ strncpy(sip_pvt->refer_contact, h_contact, sizeof(sip_pvt->refer_contact) - 1);
+ }
+ sip_pvt->refer_call = NULL;
+ if((chan = sip_pvt->owner) && (peer = ast_bridged_channel(sip_pvt->owner))) {
pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
}
return 0;
- } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) {
+ } else if (ast_canmatch_extension(NULL, sip_pvt->context, refer_to, 1, NULL)) {
return 1;
}
More information about the svn-commits
mailing list