[asterisk-commits] mmichelson: branch group/issue8824 r143333 - /team/group/issue8824/channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 16 19:42:45 CDT 2008


Author: mmichelson
Date: Tue Sep 16 19:42:45 2008
New Revision: 143333

URL: http://svn.digium.com/view/asterisk?view=rev&rev=143333
Log:
First batch of changes with regards to chan_sip.c for 
implementing redirecting information with the "Diversion" header.

* SIP now handles an indication of AST_CONTROL_REDIRECTING by
  sending a "181 Call is being Forwarded" response with a 
  Diversion: header if redirecting information is changed prior
  to the initial INVITE we received getting a final response.

* When we receive a 3XX response on an INVITE, we update the
  redirecting-to information for the owner channel based on the
  Contact: header present in the 3XX response.

Still left to do in chan_sip:

* Update the redirecting information if we read a Diversion:
  header on an incoming INVITE

* Update the redirecting-from information when we receive a
  3XX response. This information may come from a Diversion header
  or we can use the original RURI of the request which was responded
  to if no Diversion header is present. Also, queue an 
  AST_CONTROL_REDIRECTING frame when we receive a 3XX response.
  
* Update the add_diversion_header function to also include a
  reason based on the value of the owner channel's redirecting.reason
  value.


Modified:
    team/group/issue8824/channels/chan_sip.c

Modified: team/group/issue8824/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/chan_sip.c?view=diff&rev=143333&r1=143332&r2=143333
==============================================================================
--- team/group/issue8824/channels/chan_sip.c (original)
+++ team/group/issue8824/channels/chan_sip.c Tue Sep 16 19:42:45 2008
@@ -2123,6 +2123,7 @@
 static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline);
 static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
 static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
 
 /*-- TCP connection handling ---*/
 static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *ser);
@@ -5481,6 +5482,9 @@
 		break;
 	case AST_CONTROL_CONNECTED_LINE:
 		update_connectedline(p, data, datalen);
+		break;
+	case AST_CONTROL_REDIRECTING:
+		update_redirecting(p, data, datalen);
 		break;
 	case -1:
 		res = -1;
@@ -9052,6 +9056,45 @@
 		add_header(req, "User-Agent", global_useragent);
 }
 
+/*! \brief Add "Diversion" header to outgoing message
+ *
+ * We need to add a Diversion header if the owner channel of
+ * this dialog has redirecting information associated with it.
+ * XXX Add locking if necessary later.
+ *
+ * \param req The request/response to which we will add the header
+ * \param pvt The sip_pvt which represents the call-leg
+ */
+static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
+{
+	const char *diverting_number;
+	const char *diverting_name;
+	char header_text[256];
+
+	if (!pvt->owner) {
+		return;
+	}
+
+	/* XXX Eventually change this to use pvt->owner->redirecting.from.number */
+	diverting_number = pvt->owner->cid.cid_rdnis;
+	diverting_name = pvt->owner->redirecting.from.name;
+
+	if (ast_strlen_zero(diverting_number)) {
+		return;
+	}
+
+	/* We at least have a number to place in the Diversion header, which is enough */
+	if (ast_strlen_zero(diverting_name)) {
+		snprintf(header_text, sizeof(header_text), "sip:%s@%s", diverting_number, pvt->fromdomain);
+	} else {
+		snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>", diverting_name, diverting_number, pvt->fromdomain);
+	}
+
+	/* XXX Need to add a "reason" to the header text as well. */
+
+	add_header(req, "Diversion", header_text);
+}
+
 /*! \brief Build REFER/INVITE/OPTIONS message and transmit it 
 	\param init 0 = Prepare request within dialog, 1= prepare request, new branch, 2= prepare new request and new dialog. do_proxy_auth calls this with init!=2
  \param p sip_pvt structure
@@ -9163,6 +9206,9 @@
 	}
 	if ((sipmethod == SIP_INVITE || sipmethod == SIP_UPDATE) && ast_test_flag(&p->flags[0], SIP_SENDRPID))
 		add_rpid(&req, p);
+	if (sipmethod == SIP_INVITE) {
+		add_diversion_header(&req, p);
+	}
 	if (sdp) {
 		if (p->udptl && (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)) {
 			ast_udptl_offered_from_local(p->udptl, 1);
@@ -9515,6 +9561,21 @@
 "  *Variable: <name>=<value>  At least one variable pair must be specified.\n"
 "  ActionID: <id>             Action ID for this transaction. Will be returned.\n";
 
+/*! \brief Send a provisional response indicating that a call was redirected
+ */
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen)
+{
+	struct sip_request resp;
+
+	if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+		return;
+	}
+
+	respprep(&resp, p, "181 Call is being forwarded", &p->initreq);
+	add_diversion_header(&resp, p);
+	send_response(p, &resp, XMIT_UNRELIABLE, 0);
+}
+
 /*! \brief Notify peer that the connected line has changed */
 static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen)
 {
@@ -11225,9 +11286,14 @@
 		pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
 
 	if (sip_debug_test_pvt(p))
-		ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : "");
+		ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason : "");
 
 	ast_string_field_set(p, rdnis, rexten);
+
+	/*XXX Add logic here for updating the redirecting information for the owner channel.
+	 * The diversion header which we just parsed will have the from name and number. The "To"
+	 * will be taken care of either in the Contact: header or in the RURI 
+	 */
 
 	return 0;
 }
@@ -15129,21 +15195,35 @@
 /*! \brief Parse 302 Moved temporalily response */
 static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
 {
-	char tmp[SIPBUFSIZE];
-	char *s, *e, *t, *trans;
+	char contact[SIPBUFSIZE];
+	char *contact_name = NULL;
+	char *contact_number = NULL;
+#if 0
+	char *redirecting_name = NULL;
+	char *redirecting_number = NULL;
+#endif
+	char *separator, *trans;
 	char *domain;
 	enum sip_transport transport = SIP_TRANSPORT_UDP;
 
-	ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
-	if ((t = strchr(tmp, ',')))
-		*t = '\0';
-
-	s = get_in_brackets(tmp);
-	if ((trans = strcasestr(s, ";transport="))) do {
+	ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
+	if ((separator = strchr(contact, ',')))
+		*separator = '\0';
+
+	/* ooh, a name */
+	if (*contact == '"') {
+		contact_name = contact + 1;
+		if ((separator = strchr(contact_name, '"'))) {
+			*separator++ = '\0';
+		}
+	}
+
+	contact_number = get_in_brackets(contact);
+	if ((trans = strcasestr(contact_number, ";transport="))) {
 		trans += 11;
 
-		if ((e = strchr(trans, ';')))
-			*e = '\0';
+		if ((separator = strchr(trans, ';')))
+			*separator = '\0';
 
 		if (!strncasecmp(trans, "tcp", 3))
 			transport = SIP_TRANSPORT_TCP;
@@ -15151,11 +15231,11 @@
 			transport = SIP_TRANSPORT_TLS;
 		else {
 			if (strncasecmp(trans, "udp", 3))
-				ast_debug(1, "received contact with an invalid transport, '%s'\n", s);
+				ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number);
 			transport = SIP_TRANSPORT_UDP;
 		}
-	} while(0);
-	s = remove_uri_parameters(s);
+	}
+	contact_number = remove_uri_parameters(contact_number);
 
 	if (p->socket.ser) {
 		ao2_ref(p->socket.ser, -1);
@@ -15166,42 +15246,66 @@
 	p->socket.type = transport;
 
 	if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
-		if (!strncasecmp(s, "sip:", 4))
-			s += 4;
-		else if (!strncasecmp(s, "sips:", 5))
-			s += 5;
-		e = strchr(s, '/');
-		if (e)
-			*e = '\0';
-		ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s);
+		if (!strncasecmp(contact_number, "sip:", 4))
+			contact_number += 4;
+		else if (!strncasecmp(contact_number, "sips:", 5))
+			contact_number += 5;
+		separator = strchr(contact_number, '/');
+		if (separator)
+			*separator = '\0';
+		ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), contact_number);
 		if (p->owner)
-			ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s);
+			ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), contact_number);
 	} else {
-		e = strchr(tmp, '@');
-		if (e) {
-			*e++ = '\0';
-			domain = e;
+		separator = strchr(contact, '@');
+		if (separator) {
+			*separator++ = '\0';
+			domain = separator;
 		} else {
 			/* No username part */
-			domain = tmp;
-		}
-		e = strchr(tmp, '/');	/* WHEN do we hae a forward slash in the URI? */
-		if (e)
-			*e = '\0';
-
-		if (!strncasecmp(s, "sip:", 4))
-			s += 4;
-		else if (!strncasecmp(s, "sips:", 5))
-			s += 5;
-		e = strchr(s, ';');	/* And username ; parameters? */
-		if (e)
-			*e = '\0';	
-		ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
+			domain = contact;
+		}
+		separator = strchr(contact, '/');	/* WHEN do we hae a forward slash in the URI? */
+		if (separator)
+			*separator = '\0';
+
+		if (!strncasecmp(contact_number, "sip:", 4))
+			contact_number += 4;
+		else if (!strncasecmp(contact_number, "sips:", 5))
+			contact_number += 5;
+		separator = strchr(contact_number, ';');	/* And username ; parameters? */
+		if (separator)
+			*separator = '\0';	
+		ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
 		if (p->owner) {
 			pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
-			ast_string_field_set(p->owner, call_forward, s);
-		}
-	}
+			ast_string_field_set(p->owner, call_forward, contact_number);
+		}
+	}
+
+	/* We've gotten the number for the contact, now get the name */
+
+	if (*contact == '\"') {
+		contact_name = contact + 1;
+		if ((separator = strchr(contact_name, '\"'))) {
+			*separator = '\0';
+		}
+	}
+
+	if (p->owner) {
+		if (p->owner->redirecting.to.number) {
+			ast_free(p->owner->redirecting.to.number);
+		}
+		p->owner->redirecting.to.number = ast_strdup(contact_number);
+		if (p->owner->redirecting.to.name) {
+			ast_free(p->owner->redirecting.to.name);
+		}
+		p->owner->redirecting.to.name = ast_strdup(contact_name);
+	}
+
+	/*XXX Add logic for obtaining redirecting-from information. This may be
+	 * in a diversion header or by getting the request's original RURI
+	 */
 }
 
 /*! \brief Check pending actions on SIP call */




More information about the asterisk-commits mailing list