[asterisk-commits] kharwell: branch kharwell/pimp_sip_diversion r386161 - /team/kharwell/pimp_si...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Apr 19 17:41:26 CDT 2013


Author: kharwell
Date: Fri Apr 19 17:41:22 2013
New Revision: 386161

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386161
Log:
compiles, not tested.  incoming/outgoing code in place.

Modified:
    team/kharwell/pimp_sip_diversion/res/res_sip_diversion.c

Modified: team/kharwell/pimp_sip_diversion/res/res_sip_diversion.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_diversion/res/res_sip_diversion.c?view=diff&rev=386161&r1=386160&r2=386161
==============================================================================
--- team/kharwell/pimp_sip_diversion/res/res_sip_diversion.c (original)
+++ team/kharwell/pimp_sip_diversion/res/res_sip_diversion.c Fri Apr 19 17:41:22 2013
@@ -36,6 +36,8 @@
 #include "asterisk/strings.h"
 
 #define DIV_HDR_MAX_SIZE 256
+
+static const pj_str_t diversion_name = { "Diversion", 8 };
 
 /*! \brief Diversion header reasons
  *
@@ -79,25 +81,39 @@
 	return "unknown";
 }
 
+static enum AST_REDIRECTING_REASON reason_str_to_code(const char *text)
+{
+	enum AST_REDIRECTING_REASON code = AST_REDIRECTING_REASON_UNKNOWN;
+	int i;
+
+	for (i = 0; i < ARRAY_LEN(reason_table); ++i) {
+		if (!strcasecmp(text, reason_table[i].text)) {
+			code = reason_table[i].code;
+			break;
+		}
+	}
+
+	return code;
+}
+
 static pjsip_fromto_hdr *get_diversion_header(pjsip_rx_data *rdata)
 {
-	static const pj_str_t diversion = { "Diversion", 8 };
-	static const pj_str_t diversion = { "From", 4 };
+	static const pj_str_t from_name = { "From", 4 };
 
 	pjsip_generic_string_hdr *hdr;
 	pjsip_fromto_hdr *parsed;
 	pj_str_t value;
 	int size;
 
-	if (!(hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &diversion, NULL))) {
+	if (!(hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &diversion_name, NULL))) {
 		return NULL;
 	}
 
 	pj_strdup_with_null(rdata->tp_info.pool, &value, &hdr->hvalue);
 
 	/* parse as a fromto header */
-	parsed = pjsip_parse_hdr(rdata->tp_info.pool, &from, value.ptr,
-				 pj_strlen(&header_content), &size);
+	parsed = pjsip_parse_hdr(rdata->tp_info.pool, &from_name, value.ptr,
+				 pj_strlen(&value), &size);
 
 	return parsed ? parsed : NULL;
 }
@@ -109,59 +125,81 @@
 	ast_copy_pj_str(*dst, src, pj_strlen(src));
 }
 
-static void set_redirecting_id(pjsip_name_addr *hdr, struct ast_party_id *data,
+static void set_redirecting_id(pjsip_name_addr *uri, struct ast_party_id *data,
 			       struct ast_set_party_id *update)
 {
-	pjsip_sip_uri *uri = pjsip_uri_get_uri(hdr->uri);
-
-	if (pj_strlen(uri->user)) {
+	pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri->uri);
+
+	if (pj_strlen(&sip_uri->user)) {
 		update->number = 1;
 		data->number.valid = 1;
-		set_redirecting_value(&data->number.str, uri->user);
-	}
-
-	if (pj_strlen(hdr->display)) {
+		set_redirecting_value(&data->number.str, &sip_uri->user);
+	}
+
+	if (pj_strlen(&uri->display)) {
 		update->name = 1;
 		data->name.valid = 1;
-		set_redirecting_value(&data->name.str, hdr->display);
-	}
-}
-
-static int set_redirecting(pjsip_name_addr *div_hdr, pjsip_name_addr *to_hdr,
-			   struct ast_party_redirecting *data,
-			   struct ast_set_party_redirecting *update)
-{
-	set_redirecting_id(div_hdr, &data->from, &update.from);
-	set_redirecting_id(to_hdr, &data->to, &update.to);
-}
-
-static int set_redirecting(struct ast_sip_session *session,
-			   pjsip_name_addr *div_hdr,
-			   pjsip_name_addr *to_hdr)
+		set_redirecting_value(&data->name.str, &uri->display);
+	}
+
+	/* if (!ast_strlen_zero(p->cid_tag)) { */
+	/* 	ast_free(redirecting->from.tag); */
+	/* 	redirecting->from.tag = ast_strdup(p->cid_tag); */
+	/* 	ast_free(redirecting->to.tag); */
+	/* 	redirecting->to.tag = ast_strdup(p->cid_tag); */
+	/* } */
+}
+
+static void set_redirecting_reason(pjsip_name_addr *uri,
+				   struct ast_party_redirecting_reason *data)
+{
+	static const pj_str_t reason_name = { "reason", 6 };
+
+	pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri->uri);
+	pjsip_param *reason = pjsip_param_find(&sip_uri->other_param, &reason_name);
+
+	if (!reason) {
+		return;
+	}
+
+	set_redirecting_value(&data->str, &reason->value);
+	data->code = reason_str_to_code(data->str);
+}
+
+static void set_redirecting(struct ast_sip_session *session,
+			    pjsip_name_addr *div_uri,
+			    pjsip_name_addr *to_uri)
 {
 	struct ast_party_redirecting data;
 	struct ast_set_party_redirecting update;
 
+	if (!session->channel) {
+		return;
+	}
+
 	ast_party_redirecting_init(&data);
 	memset(&update, 0, sizeof(update));
 
-	set_redirecting(div_hdr, to_hdr, &data, &update);
+	set_redirecting_id(div_uri, &data.from, &update.from);
+	set_redirecting_id(to_uri, &data.to, &update.to);
+	set_redirecting_reason(div_uri, &data.reason);
 
 	ast_set_party_id_all(&update.priv_orig);
 	ast_set_party_id_all(&update.priv_from);
 	ast_set_party_id_all(&update.priv_to);
 
-	ast_channel_queue_redirecting_update(session->channel, &data, update);
+	ast_channel_set_redirecting(session->channel, &data, &update); /* ast_channel_queue_redirecting_update */
 	ast_party_redirecting_free(&data);
 }
 
 static int diversion_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata)
 {
 	/* check if diversion header is present, if so update channel's redirecting info */
-	pjsip_fromto_hdr *hdr = get_diversion_header(rdata);
+	pjsip_fromto_hdr *div_hdr = get_diversion_header(rdata);
 	
-	if (!hdr) {
-		return -1;
+	if (div_hdr) {
+		set_redirecting(session, (pjsip_name_addr*)div_hdr->uri,
+				(pjsip_name_addr*)rdata->msg_info.msg->line.req.uri);
 	}
 
 	return 0;
@@ -171,42 +209,86 @@
 {
 	/* check if diversion header is present, if so update channel's redirecting info */
 	/* if 3xx and not present then update channel redirect info */
-	if (!session->channel) {
+	struct pjsip_status_line status = rdata->msg_info.msg->line.status;
+	pjsip_fromto_hdr *div_hdr;
+
+	if (status.code != 302 || (!(div_hdr = get_diversion_header(rdata)))) {
 		return;
 	}
+
+	set_redirecting(session, (pjsip_name_addr*)div_hdr->uri,
+			(pjsip_name_addr*)PJSIP_MSG_TO_HDR(rdata->msg_info.msg)->uri);
+}
+
+static pjsip_fromto_hdr *create_hdr(pjsip_tx_data *tdata, const pj_str_t *hdr_name)
+{
+	pjsip_fromto_hdr *hdr;
+
+	/* if request base off 'msg line' otherwise use 'from' (e.g. response) */
+	pjsip_uri *base = tdata->msg->type == PJSIP_REQUEST_MSG ?
+		tdata->msg->line.req.uri : PJSIP_MSG_FROM_HDR(tdata->msg)->uri;
+
+	hdr = pjsip_from_hdr_create(tdata->pool);
+	hdr->type = PJSIP_H_OTHER;
+	pj_strdup(tdata->pool, &hdr->name, hdr_name);
+	hdr->sname.slen = 0;
+	hdr->uri = pjsip_uri_clone(tdata->pool, base);
+
+	return hdr;
+}
+
+#define param_add(pool,list,pname,pvalue) \
+	do { \
+	    pjsip_param *param; \
+	    param = PJ_POOL_ALLOC_T(pool, pjsip_param); \
+	    param->name = pj_str(pname); \
+	    param->value = pj_str(pvalue); \
+	    pj_list_insert_before(&list, param); \
+	} while (0)
+
+static pjsip_fromto_hdr *update_hdr(pjsip_tx_data *tdata, pjsip_fromto_hdr *hdr,
+				    struct ast_party_redirecting *data)
+{
+	pjsip_name_addr *name_addr = (pjsip_name_addr*)hdr;
+	pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri);
+
+	struct ast_party_id *id = tdata->msg->type == PJSIP_REQUEST_MSG ?
+		&data->to : &data->from;
+
+	if (!id->number.valid || ast_strlen_zero(id->number.str)) {
+		return hdr;
+	}
+
+	pj_strdup2(tdata->pool, &name_addr->display, id->name.str);
+	pj_strdup2(tdata->pool, &uri->user, id->number.str);
+
+	param_add(tdata->pool, uri->other_param, "reason",
+		  (char*)reason_code_to_str(&data->reason));
+
+	return hdr;
 }
 
 /*!
  * \internal
  * \brief Adds diversion header information to an outbound SIP message
  *
- * \param session The session on which we will be sending the message
  * \param tdata The outbound message
- */
-static void add_diversion_header(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
-{
-	struct ast_str *buf = ast_str_alloca(DIV_HDR_MAX_SIZE);
-	const char *reason, *contact, *domain;
-	struct ast_party_id from = ast_channel_redirecting_effective_from(session->channel);
-
-	if (!from.number.valid || ast_strlen_zero(from.number.str)) {
-		return;
-	}
-
-	if (from.name.valid && !ast_strlen_zero(from.name.str)) {
-		ast_str_set(&buf, ast_str_size(buf), "\"%s\"", from.name.str);
-	}
-
-	contact = ast_sip_location_retrieve_contact_from_aor_list(session->endpoint->aors)->uri;
-	if ((domain = strchr(contact, '@'))) {
-		++domain;
-	}
-
-	reason = reason_code_to_str(&ast_channel_redirecting(session->channel)->reason);
-	ast_str_append(&buf, ast_str_size(buf) - ast_str_strlen(buf), "<sip:%s@%s>;reason=%s",
-		       from.number.str, domain ? domain : contact, reason);
-
-	ast_sip_add_header(tdata, "Diversion", ast_str_buffer(buf));
+ * \param data The redirecting data used to fill parts of the diversion header
+ */
+static void add_diversion_header(pjsip_tx_data *tdata, struct ast_party_redirecting *data)
+{
+	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)update_hdr(tdata,
+				  create_hdr(tdata, &diversion_name), data));
+}
+
+static void get_redirecting_add_diversion(struct ast_sip_session *session, pjsip_tx_data *tdata)
+{
+	struct ast_party_redirecting *data;
+
+	if (session->channel && 
+	    (data = ast_channel_redirecting(session->channel))->count) {
+		add_diversion_header(tdata, data);
+	}
 }
 
 /*!
@@ -219,12 +301,7 @@
  */
 static void diversion_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
 {
-	struct ast_party_redirecting *data;
-
-	if (session->channel && 
-	    (data = ast_channel_redirecting(session->channel))->count) {
-		add_diversion_header(session, tdata, data);
-	}
+	get_redirecting_add_diversion(session, tdata);
 }
 
 /*!
@@ -237,13 +314,10 @@
 static void diversion_outgoing_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
 {
 	struct pjsip_status_line status = tdata->msg->line.status;
-	struct ast_party_redirecting *data;
 
 	/* add to 302 and 181 */
-	if (((status.code >= 300) && (status.code < 400) ||
-	     (status.code == 181)) && session->channel &&
-	    (data = ast_channel_redirecting(session->channel))->count)) {
-		add_diversion_header(session, tdata, data);
+	if (((status.code >= 300) && (status.code < 400)) || (status.code == 181)) {
+		get_redirecting_add_diversion(session, tdata);
 	}
 }
 




More information about the asterisk-commits mailing list