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 <a...@speakup.nl>
Committer: Alex Hermann <a...@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;
 }
 
 


_______________________________________________
sr-dev mailing list
sr-dev@lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to