[sr-dev] git:alexh/master: core/dset: Create contacts with path vector as Route header

Alex Hermann alex at speakup.nl
Mon Aug 8 11:11:05 CEST 2011


Module: sip-router
Branch: alexh/master
Commit: 0ef0618e2273dfd717014d4caa484f7f20f0a2c1
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0ef0618e2273dfd717014d4caa484f7f20f0a2c1

Author: Alex Hermann <alex at speakup.nl>
Committer: Alex Hermann <alex at speakup.nl>
Date:   Tue Jul 26 10:23:36 2011 +0200

core/dset: Create contacts with path vector as Route header

---

 config.h |    2 +-
 dset.c   |  197 ++++++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 134 insertions(+), 65 deletions(-)

diff --git a/config.h b/config.h
index 57c40b2..70791a1 100644
--- a/config.h
+++ b/config.h
@@ -170,7 +170,7 @@
 
 #define MAX_PRINT_TEXT 		256	/*!< max length of the text of fifo 'print' command */
 
-#define MAX_REDIRECTION_LEN	512	/*!< maximum length of Contact header field in redirection replies */
+#define MAX_REDIRECTION_LEN	1024	/*!< maximum length of Contact header field in redirection replies */
 
 /*! \brief used by FIFO statistics in module to terminate line;
    extra whitespaces are used to overwrite remainders of
diff --git a/dset.c b/dset.c
index f8bb337..2a42d43 100644
--- a/dset.c
+++ b/dset.c
@@ -54,6 +54,8 @@
 #define Q_PARAM ">;q="
 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
 
+#define PATH_PARAM "?Route="
+#define PATH_PARAM_LEN (sizeof(PATH_PARAM) - 1)
 
 /* 
  * Where we store URIs of additional transaction branches
@@ -355,97 +357,164 @@ int append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
 }
 
 
-/*
- * Create a Contact header field from the dset
- * array
+/*! \brief
+ * Escape all printable characters that are not valid in
+ * a param part of request uri: = | ; | , |   | " | ? | &
  */
-char* print_dset(struct sip_msg* msg, int* len) 
+static int escape_param(str *sin, str *sout)
 {
-	int cnt, i;
-	unsigned int qlen;
-	qvalue_t q;
-	str uri;
-	char* p, *qbuf;
-	static char dset[MAX_REDIRECTION_LEN];
+    char *at, *p;
+    unsigned char x;
+
+    if (sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL ||
+        sin->len<0 || sout->len < 3*sin->len+1)
+        return -1;
+
+    at = sout->s;
+    p  = sin->s;
+    while (p < sin->s+sin->len) {
+        if (*p < 32 || *p > 126) {
+            LM_ERR("invalid escaped character <%u>\n", (unsigned int)*p);
+            return -1;
+        }
+        switch (*p) {
+        case ' ':
+        case '?':
+        case '&':
+        case '=':
+        case ',':
+        case ';':
+        case '"':
+        case '+':
+            *at++ = '%';
+            x = (*p) >> 4;
+            if (x < 10)
+            {
+                *at++ = x + '0';
+            } else {
+                *at++ = x - 10 + 'a';
+            }
+            x = (*p) & 0x0f;
+            if (x < 10) {
+                *at = x + '0';
+            } else {
+                *at = x - 10 + 'a';
+            }
+            break;
+        default:
+            *at = *p;
+        }
+        at++;
+        p++;
+    }
+    *at = 0;
+    sout->len = at - sout->s;
+    LM_DBG("escaped string is <%s>\n", sout->s);
+
+    return 0;
+}
 
-	if (msg->new_uri.s) {
-		cnt = 1;
-		*len = msg->new_uri.len;
-		if (ruri_q != Q_UNSPECIFIED) {
-			*len += 1 + Q_PARAM_LEN + len_q(ruri_q);
-		}
-	} else {
-		cnt = 0;
-		*len = 0;
+
+/*! \brief
+ * Combines the given elements into a Contact header field
+ * p = target buffer
+ * uri, q, path = contact elements
+ * end = end of target buffer
+ * Returns pointer to final position in target buffer or 0 on failure
+ */
+char* print_contact_str(char *p, str uri, qvalue_t q, str path, char *end)
+{
+	str buf;
+
+	if (q != Q_UNSPECIFIED) {
+		if (p + 1 > end) return 0;
+		*p++ = '<';
 	}
 
-	init_branch_iterator();
-	while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0, 0))) {
-		cnt++;
-		*len += uri.len;
-		if (q != Q_UNSPECIFIED) {
-			*len += 1 + Q_PARAM_LEN + len_q(q);
-		}
+	/* uri */
+	if (p + uri.len > end) return 0;
+	memcpy(p, uri.s, uri.len);
+	p += uri.len;
+
+	/* path vector in Route header (uri parameter)*/
+	if (path.len > 0) {
+		if (p + PATH_PARAM_LEN + path.len*3 > end) return 0;
+		memcpy(p, PATH_PARAM, PATH_PARAM_LEN);
+		p += PATH_PARAM_LEN;
+		/* strip <> from path and escape */
+		path.s += 1;
+		path.len -= 2;
+		buf.s = p;
+		buf.len = end - p;
+		if (escape_param(&path, &buf) < 0) return 0;
+		p += buf.len;
 	}
 
-	if (cnt == 0) return 0;	
+	/* q value (header parameter) */
+	if (q != Q_UNSPECIFIED) {
+		buf.s = q2str(q, (unsigned int*)&buf.len);
+		if (p + Q_PARAM_LEN + buf.len > end) return 0;
+		memcpy(p, Q_PARAM, Q_PARAM_LEN);
+		p += Q_PARAM_LEN;
+		memcpy(p, buf.s, buf.len);
+		p += buf.len;
+	}
 
-	*len += CONTACT_LEN + CRLF_LEN + (cnt - 1) * CONTACT_DELIM_LEN;
+	return p;
+}
 
-	if (*len + 1 > MAX_REDIRECTION_LEN) {
-		LOG(L_ERR, "ERROR: redirection buffer length exceed\n");
-		return 0;
-	}
 
+/*
+ * Create a Contact header field from the dset array
+ */
+char* print_dset(struct sip_msg* msg, int* len) 
+{
+	int i;
+	qvalue_t q;
+	str uri, path;
+	char *p;
+	static char dset[MAX_REDIRECTION_LEN];
+	char *end = dset + MAX_REDIRECTION_LEN;
+
+	if (CONTACT_LEN + CRLF_LEN > MAX_REDIRECTION_LEN) goto memfail;
 	memcpy(dset, CONTACT, CONTACT_LEN);
 	p = dset + CONTACT_LEN;
 	if (msg->new_uri.s) {
-		if (ruri_q != Q_UNSPECIFIED) {
-			*p++ = '<';
-		}
-
-		memcpy(p, msg->new_uri.s, msg->new_uri.len);
-		p += msg->new_uri.len;
-
-		if (ruri_q != Q_UNSPECIFIED) {
-			memcpy(p, Q_PARAM, Q_PARAM_LEN);
-			p += Q_PARAM_LEN;
-
-			qbuf = q2str(ruri_q, &qlen);
-			memcpy(p, qbuf, qlen);
-			p += qlen;
-		}
+		p = print_contact_str(p, msg->new_uri, ruri_q,  msg->path_vec, end);
+		if (!p)
+			goto memfail;
 		i = 1;
 	} else {
 		i = 0;
 	}
 
 	init_branch_iterator();
-	while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0, 0))) {
+	while ((uri.s = next_branch(&uri.len, &q, 0, &path, 0, 0))) {
 		if (i) {
+			if (p + CONTACT_DELIM_LEN > end) goto memfail;
 			memcpy(p, CONTACT_DELIM, CONTACT_DELIM_LEN);
 			p += CONTACT_DELIM_LEN;
 		}
-
-		if (q != Q_UNSPECIFIED) {
-			*p++ = '<';
-		}
-
-		memcpy(p, uri.s, uri.len);
-		p += uri.len;
-		if (q != Q_UNSPECIFIED) {
-			memcpy(p, Q_PARAM, Q_PARAM_LEN);
-			p += Q_PARAM_LEN;
-
-			qbuf = q2str(q, &qlen);
-			memcpy(p, qbuf, qlen);
-			p += qlen;
-		}
+		p = print_contact_str(p, uri, q, path, end);
+		if (!p)
+			goto memfail;
 		i++;
 	}
 
-	memcpy(p, CRLF " ", CRLF_LEN + 1);
+	/* No contacts */
+	if (!i) {
+		goto none;
+	}
+
+	memcpy(p, CRLF, CRLF_LEN);
+	*len = p + CRLF_LEN - dset;
 	return dset;
+
+memfail:
+	LM_ERR("redirection buffer length exceeded\n");
+none:
+	*len = 0;
+	return 0;
 }
 
 




More information about the sr-dev mailing list