代码拉取完成,页面将自动刷新
/*
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* History:
* ---------
* 2004-07-21 created (bogdan)
* 2004-10-09 interface more flexible - more function available (bogdan)
* 2004-11-07 AVP string values are kept 0 terminated (bogdan)
* 2004-11-14 global aliases support added (bogdan)
*/
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "sr_module.h"
#include "dprint.h"
#include "str.h"
#include "ut.h"
#include "mem/shm_mem.h"
#include "mem/mem.h"
#include "usr_avp.h"
#include "locking.h"
#include "map.h"
static gen_lock_t *extra_lock;
static struct usr_avp *global_avps = 0;
static struct usr_avp **crt_avps = &global_avps;
static struct usr_avp **crt_bavps;
static map_t avp_map = 0;
static map_t avp_map_shm = 0;
static int last_avp_index = 0;
/* it is also used to indicate that the extra AVPs that are stored in the
* shared memory have been initialized */
static int *last_avp_index_shm = 0;
#define p2int(_p) (int)(unsigned long)(_p)
#define int2p(_i) (void *)(unsigned long)(_i)
int init_global_avps(void)
{
/* initialize map for static avps */
avp_map = map_create(0);
if (!avp_map) {
LM_ERR("cannot create avp_map\n");
return -1;
}
return 0;
}
int init_extra_avps(void)
{
extra_lock = lock_alloc();
if (!extra_lock) {
LM_ERR("cannot allocate lock\n");
return -1;
}
if (!lock_init(extra_lock)) {
LM_ERR("cannot init lock\n");
return -1;
}
last_avp_index_shm = shm_malloc(sizeof(int));
if (!last_avp_index_shm) {
LM_ERR("not enough shm mem\n");
return -1;
}
*last_avp_index_shm = last_avp_index;
/* initialize map for dynamic avps */
avp_map_shm = map_create(AVLMAP_SHARED);
if (!avp_map_shm) {
LM_ERR("cannot create shared avp_map\n");
return -1;
}
return 0;
}
struct usr_avp* new_avp(unsigned short flags, int id, int_str val)
{
struct usr_avp *avp;
str *s;
int len;
assert( crt_avps!=0 );
if (id < 0) {
LM_ERR("invalid AVP name!\n");
goto error;
}
/* compute the required mem size */
len = sizeof(struct usr_avp);
if (flags & AVP_VAL_STR)
len += sizeof(str)-sizeof(void*) + (val.s.len+1);
avp = (struct usr_avp*)shm_malloc( len );
if (avp==0) {
LM_ERR("no more shm mem\n");
goto error;
}
avp->flags = flags;
avp->id = id ;
if (flags & AVP_VAL_STR) {
/* avp type ID, str value */
s = (str *)&avp->data;
s->len = val.s.len;
s->s = (char*)s + sizeof(str);
memcpy( s->s, val.s.s , s->len);
s->s[s->len] = 0;
} else if (flags & AVP_VAL_NULL) {
avp->data = NULL;
} else {
avp->data = (void *)(long)val.n;
}
return avp;
error:
return NULL;
}
int add_avp(unsigned short flags, int name, int_str val)
{
struct usr_avp* avp;
avp = new_avp(flags, name, val);
if(avp == NULL) {
LM_ERR("Failed to create new avp structure\n");
return -1;
}
avp->next = *crt_avps;
*crt_avps = avp;
return 0;
}
int add_avp_last(unsigned short flags, int name, int_str val)
{
struct usr_avp* avp;
struct usr_avp* last_avp;
avp = new_avp(flags, name, val);
if(avp == NULL) {
LM_ERR("Failed to create new avp structure\n");
return -1;
}
/* get end of the list */
for( last_avp=*crt_avps ; last_avp && last_avp->next ; last_avp=last_avp->next);
if (last_avp==NULL) {
avp->next = *crt_avps;
*crt_avps = last_avp = avp;
} else {
last_avp->next = avp;
avp->next = NULL;
last_avp = avp;
}
return 0;
}
struct usr_avp *search_index_avp(unsigned short flags,
int name, int_str *val, unsigned int index)
{
struct usr_avp *avp = NULL;
while ( (avp=search_first_avp( flags, name, val, avp))!=0 ) {
if( index == 0 ){
return avp;
}
index--;
}
return 0;
}
int replace_avp(unsigned short flags, int name, int_str val, int index)
{
struct usr_avp* avp, *avp_prev;
struct usr_avp* avp_new, *avp_del;
if(index < 0) {
/* convert negative index to 0+ */
int pidx = count_avps(flags, name) + index;
if (pidx < 0) {
LM_DBG("AVP with the specified index (%d) not found\n", index);
return -1;
}
index = pidx;
}
avp_del = search_index_avp(flags, name, 0, index);
if(avp_del == NULL) {
LM_DBG("AVP to replace not found\n");
return -1;
}
avp_new = new_avp(flags, name, val);
if(avp_new == NULL) {
LM_ERR("Failed to create new avp structure\n");
return -1;
}
for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
if (avp==avp_del) {
if (avp_prev)
avp_prev->next=avp_new;
else
*crt_avps = avp_new;
avp_new->next = avp_del->next;
shm_free(avp_del);
return 0;
}
}
return 0;
}
/* get name functions */
static inline str* __get_avp_name(int id, map_t m)
{
map_iterator_t it;
int **idp;
if (map_first(m, &it) < 0) {
LM_ERR("map doesn't exist\n");
return NULL;
}
for (;;) {
if (!iterator_is_valid(&it))
return NULL;
idp = (int**)iterator_val(&it);
if (!idp) {
LM_ERR("[BUG] while getting avp name\n");
return NULL;
}
if (p2int(*idp) == id)
return iterator_key(&it);
if (iterator_next(&it) < 0)
return NULL;
}
}
inline str* get_avp_name_id(int id)
{
str *name;
if (id < 0)
return NULL;
name = __get_avp_name(id, avp_map);
/* search extra galiases */
if (name)
return name;
lock_get(extra_lock);
name = __get_avp_name(id, avp_map_shm);
lock_release(extra_lock);
return name;
}
inline str* get_avp_name(struct usr_avp *avp)
{
return get_avp_name_id(avp->id);
}
/* get value functions */
inline void get_avp_val(struct usr_avp *avp, int_str *val)
{
if (avp==0 || val==0)
return;
if (avp->flags & AVP_VAL_STR) {
/* avp type ID, str value */
val->s = *(str *)(&avp->data);
} else {
/* avp type ID, int value */
val->n = (long)(avp->data);
}
}
struct usr_avp** get_avp_list(void)
{
assert( crt_avps!=0 );
return crt_avps;
}
/* search functions */
inline static struct usr_avp *internal_search_ID_avp( struct usr_avp *avp,
int id, unsigned short flags)
{
for( ; avp ; avp=avp->next ) {
if ( id==avp->id && (flags==0 || (flags&avp->flags))) {
return avp;
}
}
return 0;
}
/**
* search first avp beginning with 'start->next'
* if start==NULL, beging from head of avp list
*/
struct usr_avp *search_first_avp( unsigned short flags,
int id, int_str *val, struct usr_avp *start)
{
struct usr_avp *head;
struct usr_avp *avp;
if (id < 0) {
LM_ERR("invalid avp id %d\n", id);
return 0;
}
if(start==0)
{
assert( crt_avps!=0 );
if (*crt_avps==0)
return 0;
head = *crt_avps;
} else {
if(start->next==0)
return 0;
head = start->next;
}
/* search for the AVP by ID (&name) */
avp = internal_search_ID_avp(head, id, flags&AVP_SCRIPT_MASK);
/* get the value - if required */
if (avp && val)
get_avp_val(avp, val);
return avp;
}
struct usr_avp *search_next_avp( struct usr_avp *avp, int_str *val )
{
if (avp==0 || avp->next==0)
return 0;
avp = internal_search_ID_avp( avp->next, avp->id,
avp->flags&AVP_SCRIPT_MASK );
if (avp && val)
get_avp_val(avp, val);
return avp;
}
/********* free functions ********/
void destroy_avp( struct usr_avp *avp_del)
{
struct usr_avp *avp;
struct usr_avp *avp_prev;
for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
if (avp==avp_del) {
if (avp_prev)
avp_prev->next=avp->next;
else
*crt_avps = avp->next;
shm_free(avp);
return;
}
}
}
int destroy_avps( unsigned short flags, int name, int all)
{
struct usr_avp *avp;
int n;
n = 0;
while ( (avp=search_first_avp( flags, name, 0, 0))!=0 ) {
destroy_avp( avp );
n++;
if ( !all )
break;
}
return n;
}
void destroy_index_avp( unsigned short flags, int name, int index)
{
struct usr_avp *avp = NULL;
if(index < 0) {
/* convert negative index to 0+ */
int pidx = count_avps(flags, name) + index;
if (pidx < 0) {
LM_DBG("AVP with the specified index (%d) not found\n", index);
return;
}
index = pidx;
}
avp = search_index_avp(flags, name, 0, index);
if(avp== NULL) {
LM_DBG("AVP with the specified index not found\n");
return;
}
destroy_avp( avp );
}
int count_avps(unsigned short flags, int name)
{
struct usr_avp *avp = NULL;
int n = 0;
while ((avp=search_first_avp(flags, name, 0, avp)))
n++;
return n;
}
void destroy_avp_list_bulk( struct usr_avp **list )
{
struct usr_avp *avp, *foo;
avp = *list;
while( avp ) {
foo = avp;
avp = avp->next;
shm_free_bulk( foo );
}
*list = 0;
}
void destroy_avp_list_unsafe( struct usr_avp **list )
{
struct usr_avp *avp, *foo;
avp = *list;
while( avp ) {
foo = avp;
avp = avp->next;
shm_free_unsafe( foo );
}
*list = 0;
}
inline void destroy_avp_list( struct usr_avp **list )
{
struct usr_avp *avp, *foo;
LM_DBG("destroying list %p\n", *list);
avp = *list;
while( avp ) {
foo = avp;
avp = avp->next;
shm_free( foo );
}
*list = 0;
}
void reset_avps(void)
{
assert( crt_avps!=0 );
if ( crt_avps!=&global_avps) {
crt_avps = &global_avps;
}
destroy_avp_list( crt_avps );
}
struct usr_avp** set_avp_list( struct usr_avp **list )
{
struct usr_avp **foo;
assert( crt_avps!=0 );
foo = crt_avps;
crt_avps = list;
return foo;
}
static inline int __search_avp_map(const str *alias, map_t m)
{
int **id = (int **)map_find(m, *alias);
LM_DBG("looking for [%.*s] avp %s - found %d\n", alias->len, alias->s,
m == avp_map_shm ? "in shm": "", id ? p2int(*id) : -1);
return id ? p2int(*id) : -1;
}
static int lookup_avp_alias_str(const str *alias, int extra)
{
int id;
if (!alias || !alias->len || !alias->s)
return -2;
id = __search_avp_map(alias, avp_map);
if (id < 0 && extra) {
/* search extra alias */
lock_get(extra_lock);
id = __search_avp_map(alias, avp_map_shm);
lock_release(extra_lock);
}
return id;
}
static inline int new_avp_alias(const str *alias)
{
int id = last_avp_index + 1;
if (map_put(avp_map, *alias, int2p(id))) {
LM_WARN("[BUG] Value should have already be found [%.*s]\n",
alias->len, alias->s);
return -1;
}
/* successfully added avp */
last_avp_index++;
LM_DBG("added alias %.*s with id %d\n",alias->len,alias->s,id);
return id;
}
static inline int new_avp_extra_alias(const str *alias)
{
int id;
if (!last_avp_index_shm) {
LM_ERR("extra AVPs are not initialized yet\n");
return -1;
}
/* check if last avp is valid */
lock_get(extra_lock);
id = (*last_avp_index_shm) + 1;
if (map_put(avp_map_shm, *alias, int2p(id))) {
lock_release(extra_lock);
LM_WARN("[BUG] Value should have already be found [%.*s]\n",
alias->len, alias->s);
return -1;
}
(*last_avp_index_shm)++;
lock_release(extra_lock);
LM_DBG("added extra alias %.*s with id %d\n",alias->len,alias->s,id);
return id;
}
int parse_avp_spec(const str *name, int *avp_name)
{
int id, extra;
if (name==0 || name->s==0 || name->len==0)
return -1;
extra = last_avp_index_shm ? 1 : 0;
if (name->len > 2 && name->s[1] == AVP_NAME_DELIM &&
(name->s[0] == 'i' || name->s[0] == 's'))
LM_WARN("Deprecated AVP name format \"%.*s\" - use \"%.*s\" instead\n",
name->len, name->s, name->len - 2, name->s + 2);
id = lookup_avp_alias_str(name, extra);
if (id < 0) {
id = extra ? new_avp_extra_alias(name) : new_avp_alias(name);
if (id < 0) {
LM_ERR("cannot add new avp\n");
return -1;
}
}
if (avp_name)
*avp_name = id;
return 0;
}
int get_avp_id(str *name)
{
int id;
if (parse_avp_spec(name, &id)) {
LM_ERR("unable to get id\n");
return -1;
}
return id;
}
struct usr_avp *clone_avp_list(struct usr_avp *old)
{
struct usr_avp *a;
int_str val;
if (!old) return NULL;
/* create a copy of the old AVP */
get_avp_val( old, &val );
a = new_avp( old->flags, old->id, val);
if (a==NULL) {
LM_ERR("cloning failed, trunking the list\n");
return NULL;
}
a->next = clone_avp_list(old->next);
return a;
}
struct usr_avp** set_bavp_list(struct usr_avp **list)
{
struct usr_avp **foo;
foo = crt_bavps;
crt_bavps = list;
return foo;
}
struct usr_avp** get_bavp_list(void)
{
return crt_bavps;
}
struct usr_avp** reset_bavp_list(void)
{
return set_bavp_list(NULL);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。