Module: sip-router Branch: master Commit: dd1ca987775be186761f8c83ea7ee9584bbebc96 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=dd1ca987...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Mon Jul 21 17:24:28 2014 +0200
uac: added commands to enable/disable records in remote registration table
- introduced a mutex per slot in memory hash table to avoid races on updating the fields of registration records
---
modules/uac/uac_reg.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 173 insertions(+), 3 deletions(-)
diff --git a/modules/uac/uac_reg.c b/modules/uac/uac_reg.c index 595f49a..da3fdd0 100644 --- a/modules/uac/uac_reg.c +++ b/modules/uac/uac_reg.c @@ -30,6 +30,7 @@ #include "../../ut.h" #include "../../trim.h" #include "../../hashes.h" +#include "../../locking.h" #include "../../parser/parse_uri.h" #include "../../parser/parse_from.h" #include "../../parser/parse_to.h" @@ -81,6 +82,7 @@ typedef struct _reg_entry unsigned int usize; reg_item_t *byuser; reg_item_t *byuuid; + gen_lock_t lock; } reg_entry_t;
typedef struct _reg_ht @@ -164,6 +166,8 @@ int uac_reg_init_db(void) */ int uac_reg_init_ht(unsigned int sz) { + int i; + _reg_htable = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t)); if(_reg_htable==NULL) { @@ -182,6 +186,22 @@ int uac_reg_init_ht(unsigned int sz) return -1; } memset(_reg_htable->entries, 0, _reg_htable->htsize*sizeof(reg_entry_t)); + for(i=0; i<_reg_htable->htsize; i++) + { + if(lock_init(&_reg_htable->entries[i].lock)==0) + { + LM_ERR("cannot initalize lock[%d] n", i); + i--; + while(i>=0) + { + lock_destroy(&_reg_htable->entries[i].lock); + i--; + } + shm_free(_reg_htable->entries); + shm_free(_reg_htable); + return -1; + } + }
return 0; } @@ -202,6 +222,7 @@ int uac_reg_free_ht(void) } for(i=0; i<_reg_htable->htsize; i++) { + lock_get(&_reg_htable->entries[i].lock); /* free entries */ it = _reg_htable->entries[i].byuuid; while(it) @@ -218,6 +239,7 @@ int uac_reg_free_ht(void) shm_free(it0->r); shm_free(it0); } + lock_destroy(&_reg_htable->entries[i].lock); } shm_free(_reg_htable->entries); shm_free(_reg_htable); @@ -225,6 +247,48 @@ int uac_reg_free_ht(void) return 0; }
+/** + * + */ +int uac_reg_reset_ht(void) +{ + int i; + reg_item_t *it = NULL; + reg_item_t *it0 = NULL; + + if(_reg_htable==NULL) + { + LM_DBG("no hash table\n"); + return -1; + } + for(i=0; i<_reg_htable->htsize; i++) + { + lock_get(&_reg_htable->entries[i].lock); + /* free entries */ + it = _reg_htable->entries[i].byuuid; + while(it) + { + it0 = it; + it = it->next; + shm_free(it0); + } + _reg_htable->entries[i].byuuid = NULL; + _reg_htable->entries[i].isize=0; + it = _reg_htable->entries[i].byuser; + while(it) + { + it0 = it; + it = it->next; + shm_free(it0->r); + shm_free(it0); + } + _reg_htable->entries[i].byuser = NULL; + _reg_htable->entries[i].usize = 0; + lock_release(&_reg_htable->entries[i].lock); + } + return 0; +} + #define reg_compute_hash(_s) get_hash1_raw((_s)->s,(_s)->len) #define reg_get_entry(_h,_size) ((_h)&((_size)-1))
@@ -251,9 +315,11 @@ int reg_ht_add_byuuid(reg_uac_t *reg) memset(ri, 0, sizeof(reg_item_t)); slot = reg_get_entry(reg->h_uuid, _reg_htable->htsize); ri->r = reg; + lock_get(&_reg_htable->entries[slot].lock); ri->next = _reg_htable->entries[slot].byuuid; _reg_htable->entries[slot].byuuid = ri; _reg_htable->entries[slot].isize++; + lock_release(&_reg_htable->entries[slot].lock); return 0; }
@@ -280,9 +346,11 @@ int reg_ht_add_byuser(reg_uac_t *reg) memset(ri, 0, sizeof(reg_item_t)); slot = reg_get_entry(reg->h_user, _reg_htable->htsize); ri->r = reg; + lock_get(&_reg_htable->entries[slot].lock); ri->next = _reg_htable->entries[slot].byuser; _reg_htable->entries[slot].byuser = ri; _reg_htable->entries[slot].usize++; + lock_release(&_reg_htable->entries[slot].lock); return 0; }
@@ -770,7 +838,7 @@ void uac_reg_timer(unsigned int ticks) tn = time(NULL); for(i=0; i<_reg_htable->htsize; i++) { - /* free entries */ + /* walk through entries */ it = _reg_htable->entries[i].byuuid; while(it) { @@ -1094,7 +1162,8 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx)
for(i=0; i<_reg_htable->htsize; i++) { - /* free entries */ + lock_get(&_reg_htable->entries[i].lock); + /* walk through entries */ reg = _reg_htable->entries[i].byuuid; while(reg) { @@ -1121,11 +1190,13 @@ static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx) "timer_expires", (int)reg->r->timer_expires )<0) { + lock_release(&_reg_htable->entries[i].lock); rpc->fault(ctx, 500, "Internal error adding item"); return; } reg = reg->next; } + lock_release(&_reg_htable->entries[i].lock); } }
@@ -1167,7 +1238,8 @@ static void rpc_uac_reg_info(rpc_t* rpc, void* ctx)
for(i=0; i<_reg_htable->htsize; i++) { - /* free entries */ + /* walk through entries */ + lock_get(&_reg_htable->entries[i].lock); reg = _reg_htable->entries[i].byuuid; while(reg) { @@ -1180,6 +1252,7 @@ static void rpc_uac_reg_info(rpc_t* rpc, void* ctx) } else if(attr.len==13 && strncmp(attr.s, "auth_username", 13)==0) { rval = ®->r->auth_username; } else { + lock_release(&_reg_htable->entries[i].lock); LM_ERR("usupoorted filter attribute %.*s\n", attr.len, attr.s); rpc->fault(ctx, 500, "Unsupported Filter Attribtue"); return; @@ -1209,6 +1282,7 @@ static void rpc_uac_reg_info(rpc_t* rpc, void* ctx) "timer_expires", (int)reg->r->timer_expires )<0) { + lock_release(&_reg_htable->entries[i].lock); rpc->fault(ctx, 500, "Internal error adding item"); return; } @@ -1216,12 +1290,108 @@ static void rpc_uac_reg_info(rpc_t* rpc, void* ctx) } reg = reg->next; } + lock_release(&_reg_htable->entries[i].lock); + } +} + + +static void rpc_uac_reg_update_flag(rpc_t* rpc, void* ctx, int mode, int fval) +{ + int i; + reg_item_t *reg = NULL; + void* th; + str none = {"none", 4}; + time_t tn; + str attr = {0}; + str val = {0}; + str *rval; + + if(_reg_htable==NULL) + { + rpc->fault(ctx, 500, "Not enabled"); + return; + } + + if(rpc->scan(ctx, "S.S", &attr, &group, &val)<2) + { + rpc->fault(ctx, 500, "Invalid Parameters"); + return; + } + if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL) + { + LM_ERR("bad parameter values\n"); + rpc->fault(ctx, 500, "Invalid Parameter Values"); + return; + } + + tn = time(NULL); + + for(i=0; i<_reg_htable->htsize; i++) + { + lock_get(&_reg_htable->entries[i].lock); + /* walk through entries */ + reg = _reg_htable->entries[i].byuuid; + while(reg) + { + if(attr.len==10 && strncmp(attr.s, "l_username", 10)==0) { + rval = ®->r->l_username; + } else if(attr.len==10 && strncmp(attr.s, "r_username", 10)==0) { + rval = ®->r->r_username; + } else if(attr.len==6 && strncmp(attr.s, "l_uuid", 6)==0) { + rval = ®->r->l_uuid; + } else if(attr.len==13 && strncmp(attr.s, "auth_username", 13)==0) { + rval = ®->r->auth_username; + } else { + lock_release(&_reg_htable->entries[i].lock); + LM_ERR("usupoorted filter attribute %.*s\n", attr.len, attr.s); + rpc->fault(ctx, 500, "Unsupported Filter Attribtue"); + return; + } + + if(rval->len==val.len && strncmp(val.s, rval->s, val.len)==0) { + /* found */ + if(mode==1) { + reg->r->flags |= fval; + } else { + reg->r->flags &= ~fval; + } + reg->r->timer_expires = time(NULL) + 1; + lock_release(&_reg_htable->entries[i].lock); + return; + } + reg = reg->next; + } + lock_release(&_reg_htable->entries[i].lock); } }
+static const char* rpc_uac_reg_enable_doc[2] = { + "Enable registration for a particular record.", + 0 +}; + +static void rpc_uac_reg_enable(rpc_t* rpc, void* ctx) +{ + rpc_uac_reg_update_flag(rpc, ctx, 1, UAC_REG_DISABLED); +} + +static const char* rpc_uac_reg_disable_doc[2] = { + "Disable registration for a particular record.", + 0 +}; + +static void rpc_uac_reg_disable(rpc_t* rpc, void* ctx) +{ + rpc_uac_reg_update_flag(rpc, ctx, 0, UAC_REG_DISABLED); +} + + + rpc_export_t uac_reg_rpc[] = { {"uac.reg_dump", rpc_uac_reg_dump, rpc_uac_reg_dump_doc, 0}, {"uac.reg_info", rpc_uac_reg_info, rpc_uac_reg_info_doc, 0}, + {"uac.reg_enable", rpc_uac_reg_enable, rpc_uac_reg_enable_doc, 0}, + {"uac.reg_disable", rpc_uac_reg_disable, rpc_uac_reg_disable_doc, 0}, {0, 0, 0, 0} };