parser: const-correctness for some module utility functions
[sip-router] / dset.c
diff --git a/dset.c b/dset.c
index 9409557..4ba5ccf 100644 (file)
--- a/dset.c
+++ b/dset.c
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/** destination set / branches support.
+ * @file dset.c
+ * @ingroup core
+ * Module: @ref core
+ */
+
 #include <string.h>
 #include "dprint.h"
 #include "config.h"
 #define Q_PARAM ">;q="
 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
 
-struct branch
-{
-       char uri[MAX_URI_SIZE];
-       unsigned int len;
-
-            /* Real destination of the request */
-       char dst_uri[MAX_URI_SIZE];
-       unsigned int dst_uri_len;
-
-       /* Path set */
-       char path[MAX_PATH_SIZE];
-       unsigned int path_len;
-
-       int q; /* Preference of the contact among
-               * contact within the array */
-       struct socket_info* force_send_socket;
-
-       /* Branch flags */
-       flag_t flags;
-};
-
 
 /* 
  * Where we store URIs of additional transaction branches
@@ -82,6 +67,9 @@ unsigned int nr_branches = 0;
 /* branch iterator */
 static int branch_iterator = 0;
 
+/* used to mark ruris "consumed" when branching (1 new, 0 consumed) */
+int ruri_is_new = 0;
+
 /* The q parameter of the Request-URI */
 static qvalue_t ruri_q = Q_UNSPECIFIED;
 
@@ -89,6 +77,54 @@ static qvalue_t ruri_q = Q_UNSPECIFIED;
 static flag_t ruri_bflags;
 
 
+/*! \brief
+ * Return pointer to branch[idx] structure
+ * @param idx - branch index
+ *
+ * @return  pointer to branch or NULL if invalid branch
+ */
+branch_t *get_sip_branch(int idx)
+{
+       if(nr_branches==0)
+               return NULL;
+       if(idx<0)
+       {
+               if(nr_branches + idx >= 0)
+                       return &branches[nr_branches+idx];
+               return NULL;
+       }
+       if(idx < nr_branches)
+               return &branches[idx];
+       return 0;
+}
+
+/*! \brief
+ * Drop branch[idx]
+ * @param idx - branch index
+ *
+ * @return  0 on success, -1 on error
+ */
+int drop_sip_branch(int idx)
+{
+       if(nr_branches==0 || idx>=nr_branches)
+               return 0;
+       if(idx<0 && nr_branches+idx<0)
+               return 0;
+       /* last branch */
+       if(idx==nr_branches-1)
+       {
+               nr_branches--;
+               return 0;
+       }
+       if(idx<0)
+               idx = nr_branches+idx;
+       /* shift back one position */
+       for(; idx<nr_branches-1; idx++)
+               memcpy(&branches[idx], &branches[idx+1], sizeof(branch_t));
+       nr_branches--;
+       return 0;
+}
+
 static inline flag_t* get_bflags_ptr(unsigned int branch)
 {
        if (branch == 0) return &ruri_bflags;
@@ -155,41 +191,20 @@ void init_branch_iterator(void)
        branch_iterator = 0;
 }
 
-
-/*
- * Return the next branch from the dset
- * array, 0 is returned if there are no
- * more branches
+/**
+ * return the value of current branch iterator
  */
-char* next_branch(int* len, qvalue_t* q, char** dst_uri, int* dst_len, struct socket_info** force_socket)
+int get_branch_iterator(void)
 {
-       unsigned int i;
+       return branch_iterator;
+}
 
-       i = branch_iterator;
-       if (i < nr_branches) {
-               branch_iterator++;
-               *len = branches[i].len;
-               *q = branches[i].q;
-               if (dst_uri && dst_len) {
-                       *dst_uri = branches[i].dst_uri;
-                       *dst_len = branches[i].dst_uri_len;
-               }
-               if (force_socket) {
-                       *force_socket = branches[i].force_send_socket;
-               }
-               return branches[i].uri;
-       } else {
-               *len = 0;
-               *q = Q_UNSPECIFIED;
-               if (dst_uri && dst_len) {
-                       *dst_uri = 0;
-                       *dst_len = 0;
-               }
-               if (force_socket) {
-                       *force_socket = 0;
-               }
-               return 0;
-       }
+/**
+ * set the value of current branch interator
+ */
+void set_branch_iterator(int n)
+{
+       branch_iterator = n;
 }
 
 
@@ -199,7 +214,8 @@ char* next_branch(int* len, qvalue_t* q, char** dst_uri, int* dst_len, struct so
  * more branches
  */
 char* get_branch(unsigned int i, int* len, qvalue_t* q, str* dst_uri,
-                                str* path, unsigned int *flags, struct socket_info** force_socket)
+                                str* path, unsigned int *flags,
+                                struct socket_info** force_socket)
 {
        if (i < nr_branches) {
                *len = branches[i].len;
@@ -224,6 +240,10 @@ char* get_branch(unsigned int i, int* len, qvalue_t* q, str* dst_uri,
                        dst_uri->s = 0;
                        dst_uri->len = 0;
                }
+               if (path) {
+                       path->s = 0;
+                       path->len = 0;
+               }
                if (force_socket)
                        *force_socket = 0;
                if (flags)
@@ -233,6 +253,23 @@ char* get_branch(unsigned int i, int* len, qvalue_t* q, str* dst_uri,
 }
 
 
+
+/** Return the next branch from the dset array.
+ * 0 is returned if there are no more branches
+ */
+char* next_branch(int* len, qvalue_t* q, str* dst_uri, str* path,
+                                       unsigned int* flags, struct socket_info** force_socket)
+{
+       char* ret;
+       
+       ret=get_branch(branch_iterator, len, q, dst_uri, path, flags,
+                                       force_socket);
+       if (likely(ret))
+               branch_iterator++;
+       return ret;
+}
+
+
 /*
  * Empty the dset array
  */
@@ -240,87 +277,32 @@ void clear_branches(void)
 {
        nr_branches = 0;
        ruri_q = Q_UNSPECIFIED;
+       ruri_bflags = 0;
+       ruri_mark_consumed();
 }
 
 
-/* 
- * Add a new branch to current transaction 
- */
-int append_branch(struct sip_msg* msg, char* uri, int uri_len, char* dst_uri, int dst_uri_len, 
-                 qvalue_t q, struct socket_info* force_socket)
-{
-            /* if we have already set up the maximum number
-             * of branches, don't try new ones 
-             */
-       if (nr_branches == MAX_BRANCHES - 1) {
-               LOG(L_ERR, "ERROR: append_branch: max nr of branches exceeded\n");
-               ser_error = E_TOO_MANY_BRANCHES;
-               return -1;
-       }
-
-       if (uri_len > MAX_URI_SIZE - 1) {
-               LOG(L_ERR, "ERROR: append_branch: too long uri: %.*s\n",
-                   uri_len, uri);
-               return -1;
-       }
-       
-       if (dst_uri_len > MAX_URI_SIZE - 1) {
-               LOG(L_ERR, "ERROR: append_branch: too long dst_uri: %.*s\n",
-                   dst_uri_len, ZSW(dst_uri));
-               return -1;
-       }
 
-            /* if not parameterized, take current uri */
-       if (uri == 0) {
-               if (msg->new_uri.s) { 
-                       uri = msg->new_uri.s;
-                       uri_len = msg->new_uri.len;
-               } else {
-                       uri = msg->first_line.u.request.uri.s;
-                       uri_len = msg->first_line.u.request.uri.len;
-               }
-       }
-       
-       memcpy(branches[nr_branches].uri, uri, uri_len);
-            /* be safe -- add zero termination */
-       branches[nr_branches].uri[uri_len] = 0;
-       branches[nr_branches].len = uri_len;
-       branches[nr_branches].q = q;
-       
-       if (dst_uri && dst_uri_len) {
-               memcpy(branches[nr_branches].dst_uri, dst_uri, dst_uri_len);
-               branches[nr_branches].dst_uri[dst_uri_len] = 0;
-               branches[nr_branches].dst_uri_len = dst_uri_len;
-       } else {
-               branches[nr_branches].dst_uri[0] = '\0';
-               branches[nr_branches].dst_uri_len = 0;
-       }
-
-       branches[nr_branches].force_send_socket = force_socket;
-       
-       nr_branches++;
-       return 1;
-}
-
-
-/* ! \brief
- * Add a new branch to current transaction using str parameters
- * Kamailio compatibility version
+/**  Add a new branch to the current transaction.
+ * @param msg - sip message, used for getting the uri if not specified (0).
+ * @param uri - uri, can be 0 (in which case the uri is taken from msg)
+ * @param dst_uri - destination uri, can be 0.
+ * @param path - path vector (passed in a string), can be 0.
+ * @param q  - q value.
+ * @param flags - per branch flags.
+ * @param force_socket - socket that should be used when sending.
+ *
+ * @return  <0 (-1) on failure, 1 on success (script convention).
  */
-int km_append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
+int append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
                qvalue_t q, unsigned int flags, struct socket_info* force_socket)
 {
        str luri;
 
-#ifdef USE_LOCAL_ROUTE
-       if (dset_state==0)
-               return -1;
-#endif
-
        /* if we have already set up the maximum number
         * of branches, don't try new ones 
         */
-       if (nr_branches == MAX_BRANCHES - 1) {
+       if (unlikely(nr_branches == MAX_BRANCHES - 1)) {
                LOG(L_ERR, "max nr of branches exceeded\n");
                ser_error = E_TOO_MANY_BRANCHES;
                return -1;
@@ -336,16 +318,15 @@ int km_append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
                luri = *uri;
        }
 
-       if (luri.len > MAX_URI_SIZE - 1) {
+       if (unlikely(luri.len > MAX_URI_SIZE - 1)) {
                LOG(L_ERR, "too long uri: %.*s\n", luri.len, luri.s);
                return -1;
        }
 
        /* copy the dst_uri */
        if (dst_uri && dst_uri->len && dst_uri->s) {
-               if (dst_uri->len > MAX_URI_SIZE - 1) {
-                       LOG(L_ERR, "too long dst_uri: %.*s\n",
-                               dst_uri->len, dst_uri->s);
+               if (unlikely(dst_uri->len > MAX_URI_SIZE - 1)) {
+                       LOG(L_ERR, "too long dst_uri: %.*s\n", dst_uri->len, dst_uri->s);
                        return -1;
                }
                memcpy(branches[nr_branches].dst_uri, dst_uri->s, dst_uri->len);
@@ -357,8 +338,8 @@ int km_append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
        }
 
        /* copy the path string */
-       if (path && path->len && path->s) {
-               if (path->len > MAX_PATH_SIZE - 1) {
+       if (unlikely(path && path->len && path->s)) {
+               if (unlikely(path->len > MAX_PATH_SIZE - 1)) {
                        LOG(L_ERR, "too long path: %.*s\n", path->len, path->s);
                        return -1;
                }
@@ -395,6 +376,7 @@ char* print_dset(struct sip_msg* msg, int* len)
        qvalue_t q;
        str uri;
        char* p, *qbuf;
+       int crt_branch;
        static char dset[MAX_REDIRECTION_LEN];
 
        if (msg->new_uri.s) {
@@ -408,8 +390,11 @@ char* print_dset(struct sip_msg* msg, int* len)
                *len = 0;
        }
 
+       /* backup current branch index to restore it later */
+       crt_branch = get_branch_iterator();
+
        init_branch_iterator();
-       while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0))) {
+       while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0, 0))) {
                cnt++;
                *len += uri.len;
                if (q != Q_UNSPECIFIED) {
@@ -423,7 +408,7 @@ char* print_dset(struct sip_msg* msg, int* len)
 
        if (*len + 1 > MAX_REDIRECTION_LEN) {
                LOG(L_ERR, "ERROR: redirection buffer length exceed\n");
-               return 0;
+               goto error;
        }
 
        memcpy(dset, CONTACT, CONTACT_LEN);
@@ -450,7 +435,7 @@ char* print_dset(struct sip_msg* msg, int* len)
        }
 
        init_branch_iterator();
-       while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0))) {
+       while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0, 0))) {
                if (i) {
                        memcpy(p, CONTACT_DELIM, CONTACT_DELIM_LEN);
                        p += CONTACT_DELIM_LEN;
@@ -474,7 +459,12 @@ char* print_dset(struct sip_msg* msg, int* len)
        }
 
        memcpy(p, CRLF " ", CRLF_LEN + 1);
+       set_branch_iterator(crt_branch);
        return dset;
+
+error:
+       set_branch_iterator(crt_branch);
+       return 0;
 }
 
 
@@ -497,24 +487,6 @@ qvalue_t get_ruri_q(void)
 
 
 
-/*
- * Get actual Request-URI
- */
-int get_request_uri(struct sip_msg* _m, str* _u)
-{
-            /* Use new_uri if present */
-       if (_m->new_uri.s) {
-               _u->s = _m->new_uri.s;
-               _u->len = _m->new_uri.len;
-       } else {
-               _u->s = _m->first_line.u.request.uri.s;
-               _u->len = _m->first_line.u.request.uri.len;
-       }
-
-       return 0;
-}
-
-
 /*
  * Rewrite Request-URI
  */
@@ -538,9 +510,9 @@ int rewrite_uri(struct sip_msg* _m, str* _s)
 
         _m->new_uri.s = buf;
         _m->new_uri.len = _s->len;
+        /* mark ruri as new and available for forking */
+        ruri_mark_new();
 
-        DBG("rewrite_uri: Rewriting Request-URI with '%.*s'\n", _s->len, 
-                                                                                                                                                  buf);
         return 1;
 }