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

Author: Daniel-Constantin Mierla <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
Date:   Fri Aug 22 00:16:01 2014 +0200

dialog: internal refactoring to allow adding remote profile

- this is a profile item without a local dialog
- allow opperations to add or remove such profiles

---

 modules/dialog/dlg_profile.c |  193 +++++++++++++++++++++++++++++++++---------
 modules/dialog/dlg_profile.h |    1 +
 2 files changed, 153 insertions(+), 41 deletions(-)

diff --git a/modules/dialog/dlg_profile.c b/modules/dialog/dlg_profile.c
index 0efa1cd..aba19c4 100644
--- a/modules/dialog/dlg_profile.c
+++ b/modules/dialog/dlg_profile.c
@@ -297,6 +297,73 @@ void destroy_linkers(struct dlg_profile_link *linker)
 
 
 /*!
+ * \brief Calculate the hash profile from a dialog
+ * \see core_hash
+ * \param value hash source
+ * \param dlg dialog cell
+ * \param profile dialog profile table (for hash size)
+ * \return value hash if the value has a value, hash over dialog otherwise
+ */
+inline static unsigned int calc_hash_profile(str *value1, str *value2,
+               dlg_profile_table_t *profile)
+{
+       if (profile->has_value) {
+               /* do hash over the value1 */
+               return core_hash( value1, NULL, profile->size);
+       } else {
+               /* do hash over the value2 */
+               if(value2)
+                       return core_hash( value2, NULL, profile->size);
+               return 0;
+       }
+}
+
+
+/*!
+ * \brief Remove profile
+ * \param profile pointer to profile
+ * \param value profile value
+ * \param puid profile unique id
+ */
+int remove_profile(dlg_profile_table_t *profile, str *value, str *puid)
+{
+       unsigned int hash;
+       struct dlg_profile_entry *p_entry;
+       struct dlg_profile_hash *lh;
+       struct dlg_profile_hash *kh;
+
+       hash = calc_hash_profile(value, puid, profile);
+       lock_get(&profile->lock );
+       p_entry = &profile->entries[hash];
+       lh = p_entry->first;
+       while(lh) {
+               kh = lh->next;
+               if(lh->dlg==NULL && lh->puid_len==puid->len
+                               && lh->value.len==value->len
+                               && strncmp(lh->puid, puid->s, puid->len)==0
+                               && strncmp(lh->value.s, value->s, 
value->len)==0) {
+                       /* last element on the list? */
+                       if (lh==lh->next) {
+                               p_entry->first = NULL;
+                       } else {
+                               if (p_entry->first==lh)
+                                       p_entry->first = lh->next;
+                               lh->next->prev = lh->prev;
+                               lh->prev->next = lh->next;
+                       }
+                       lh->next = lh->prev = NULL;
+                       if(lh->linker) shm_free(lh->linker);
+                       p_entry->content--;
+                       return 1;
+               }
+               lh = kh;
+       }
+       lock_release(&profile->lock );
+       return 0;
+}
+
+
+/*!
  * \brief Cleanup a profile
  * \param msg SIP message
  * \param flags unused
@@ -328,30 +395,37 @@ int profile_cleanup( struct sip_msg *msg, unsigned int 
flags, void *param )
 }
 
 
-
 /*!
- * \brief Calculate the hash profile from a dialog
- * \see core_hash
- * \param value hash source
- * \param dlg dialog cell
- * \param profile dialog profile table (for hash size)
- * \return value hash if the value has a value, hash over dialog otherwise
+ * \brief Link a dialog profile
+ * \param linker dialog linker
+ * \param vkey key for profile hash table
  */
-inline static unsigned int calc_hash_profile(str *value1, str *value2,
-               dlg_profile_table_t *profile)
+static void link_profile(struct dlg_profile_link *linker, str *vkey)
 {
-       if (profile->has_value) {
-               /* do hash over the value1 */
-               return core_hash( value1, NULL, profile->size);
+       unsigned int hash;
+       struct dlg_profile_entry *p_entry;
+       struct dlg_entry *d_entry;
+
+       /* calculate the hash position */
+       hash = calc_hash_profile(&linker->hash_linker.value, vkey, 
linker->profile);
+       linker->hash_linker.hash = hash;
+
+       /* insert into profile hash table */
+       p_entry = &linker->profile->entries[hash];
+       lock_get( &linker->profile->lock );
+       if (p_entry->first) {
+               linker->hash_linker.prev = p_entry->first->prev;
+               linker->hash_linker.next = p_entry->first;
+               p_entry->first->prev->next = &linker->hash_linker;
+               p_entry->first->prev = &linker->hash_linker;
        } else {
-               /* do hash over the value2 */
-               if(value2)
-                       return core_hash( value2, NULL, profile->size);
-               return 0;
+               p_entry->first = linker->hash_linker.next 
+                       = linker->hash_linker.prev = &linker->hash_linker;
        }
+       p_entry->content ++;
+       lock_release( &linker->profile->lock );
 }
 
-
 /*!
  * \brief Link a dialog profile
  * \param linker dialog linker
@@ -379,24 +453,7 @@ static void link_dlg_profile(struct dlg_profile_link 
*linker, struct dlg_cell *d
                linker->hash_linker.dlg = dlg;
        }
 
-       /* calculate the hash position */
-       hash = calc_hash_profile(&linker->hash_linker.value, &dlg->callid, 
linker->profile);
-       linker->hash_linker.hash = hash;
-
-       /* insert into profile hash table */
-       p_entry = &linker->profile->entries[hash];
-       lock_get( &linker->profile->lock );
-       if (p_entry->first) {
-               linker->hash_linker.prev = p_entry->first->prev;
-               linker->hash_linker.next = p_entry->first;
-               p_entry->first->prev->next = &linker->hash_linker;
-               p_entry->first->prev = &linker->hash_linker;
-       } else {
-               p_entry->first = linker->hash_linker.next 
-                       = linker->hash_linker.prev = &linker->hash_linker;
-       }
-       p_entry->content ++;
-       lock_release( &linker->profile->lock );
+       link_profile(linker, &dlg->callid);
 }
 
 
@@ -461,8 +518,9 @@ int set_dlg_profile(struct sip_msg *msg, str *value, struct 
dlg_profile_table *p
        }
        memset(linker, 0, sizeof(struct dlg_profile_link));
 
-       /* set backpointer to profile */
+       /* set backpointers to profile and linker (itself) */
        linker->profile = profile;
+       linker->hash_linker.linker = linker;
 
        /* set the value */
        if (profile->has_value) {
@@ -514,9 +572,7 @@ int dlg_add_profile(dlg_cell_t *dlg, str *value, struct 
dlg_profile_table *profi
                str *puid, time_t expires, int flags)
 {
        dlg_profile_link_t *linker;
-
-       if (dlg==NULL)
-               return -1;
+       str vkey;
 
        /* build new linker */
        linker = (struct dlg_profile_link*)shm_malloc(
@@ -527,8 +583,9 @@ int dlg_add_profile(dlg_cell_t *dlg, str *value, struct 
dlg_profile_table *profi
        }
        memset(linker, 0, sizeof(struct dlg_profile_link));
 
-       /* set backpointer to profile */
+       /* set backpointers to profile and linker (itself) */
        linker->profile = profile;
+       linker->hash_linker.linker = linker;
 
        /* set the value */
        if (profile->has_value) {
@@ -539,6 +596,7 @@ int dlg_add_profile(dlg_cell_t *dlg, str *value, struct 
dlg_profile_table *profi
        }
        if(puid && puid->s && puid->len>0 && puid->len<SRUID_SIZE) {
                strcpy(linker->hash_linker.puid, puid->s);
+               linker->hash_linker.puid_len = puid->len;
        } else {
                sruid_next_safe(&_dlg_profile_sruid);
                strcpy(linker->hash_linker.puid, _dlg_profile_sruid.uid.s);
@@ -548,7 +606,13 @@ int dlg_add_profile(dlg_cell_t *dlg, str *value, struct 
dlg_profile_table *profi
        linker->hash_linker.flags = flags;
 
        /* add linker directly to the dialog and profile */
-       link_dlg_profile( linker, dlg);
+       if(dlg!=NULL) {
+               link_dlg_profile(linker, dlg);
+       } else {
+               vkey.s = linker->hash_linker.puid;
+               vkey.len = linker->hash_linker.puid_len;
+               link_profile(linker, &vkey);
+       }
        return 0;
 error:
        return -1;
@@ -1187,3 +1251,50 @@ int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t 
*jdoc)
        }
        return 0;
 }
+
+/**
+ *
+ */
+int dlg_cmd_remote_profile(str *cmd, str *pname, str *value, str *puid,
+               time_t expires, int flags)
+{
+       dlg_profile_table_t *dprofile;
+       int ret;
+
+       if(cmd==NULL || cmd->s==NULL || cmd->len<=0
+                       || pname==NULL || pname->s==NULL || pname->len<=0
+                       || puid==NULL || puid->s==NULL || puid->len<=0) {
+               LM_ERR("invalid parameters\n");
+               return -1;
+       }
+       dprofile = search_dlg_profile(pname);
+       if(dprofile==NULL) {
+               LM_ERR("profile [%.*s] not found\n", pname->len, pname->s);
+               return -1;
+       }
+       if(dprofile->has_value) {
+               if(value==NULL || value->s==NULL || value->len<=0) {
+                       LM_ERR("profile [%.*s] requires a value\n", pname->len, 
pname->s);
+                       return -1;
+               }
+       }
+
+       if(cmd->len==3 && strncmp(cmd->s, "add", 3)==0) {
+               if(value && value->s && value->len>0) {
+                       ret = dlg_add_profile(NULL, value, dprofile, puid, 
expires, flags);
+               } else {
+                       ret = dlg_add_profile(NULL, NULL, dprofile, puid, 
expires, flags);
+               }
+               if(ret<0) {
+                       LM_ERR("failed to add to profile [%.*s]\n", pname->len, 
pname->s);
+                       return -1;
+               }
+       } else if(cmd->len==2 && strncmp(cmd->s, "rm", 2)==0) {
+               ret = remove_profile(dprofile, value, puid);
+               return ret;
+       } else {
+               LM_ERR("unknown command [%.*s]\n", cmd->len, cmd->s);
+               return -1;
+       }
+       return 0;
+}
diff --git a/modules/dialog/dlg_profile.h b/modules/dialog/dlg_profile.h
index 00ef276..0773fe1 100644
--- a/modules/dialog/dlg_profile.h
+++ b/modules/dialog/dlg_profile.h
@@ -55,6 +55,7 @@ typedef struct dlg_profile_hash {
        int puid_len;
        time_t expires;
        int flags;
+       struct dlg_profile_link *linker;
        struct dlg_profile_hash *next;
        struct dlg_profile_hash *prev;
        unsigned int hash; /*!< position in the hash table */


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to