avpops_impl.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 1,844 行 · 第 1/3 页

C
1,844
字号
/* * $Id: avpops_impl.c,v 1.28 2006/07/10 10:17:39 miconda Exp $ * * Copyright (C) 2004 Voice Sistem SRL * * This file is part of Open SIP Express Router. * * AVPOPS OpenSER-module 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. * * AVPOPS OpenSER-module 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. * * For any questions about this software and its license, please contact * Voice Sistem at following e-mail address: *         office@voice-sistem.ro * * * History: * --------- *  2004-10-04  first version (ramona) *  2005-01-30  "fm" (fast match) operator added (ramona) *  2005-01-30  avp_copy (copy/move operation) added (ramona) */#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <regex.h>#include <fnmatch.h>#include "../../ut.h"#include "../../dprint.h"#include "../../usr_avp.h"#include "../../action.h"#include "../../ip_addr.h"#include "../../config.h"#include "../../dset.h"#include "../../data_lump.h"#include "../../data_lump_rpl.h"#include "../../items.h"#include "../../parser/parse_from.h"#include "../../parser/parse_uri.h"#include "../../mem/mem.h"#include "avpops_impl.h"#include "avpops_db.h"#define avpops_str2int_str(a, b) \	do { \		if(a.s==0) \			b.n = a.len; \		else \			b.s = a; \	} while(0)static db_key_t  store_keys[6];static db_val_t  store_vals[6];static str      empty={"",0};#define AVP_PRINTBUF_SIZE 1024static char printbuf[AVP_PRINTBUF_SIZE];void init_store_avps( char **db_columns){	/* unique user id */	store_keys[0] = db_columns[0]; /*uuid*/	store_vals[0].type = DB_STR;	store_vals[0].nul  = 0;	/* attribute */	store_keys[1] = db_columns[1]; /*attribute*/	store_vals[1].type = DB_STR;	store_vals[1].nul  = 0;	/* value */	store_keys[2] = db_columns[2]; /*value*/	store_vals[2].type = DB_STR;	store_vals[2].nul  = 0;	/* type */	store_keys[3] = db_columns[3]; /*type*/	store_vals[3].type = DB_INT;	store_vals[3].nul  = 0;	/* user name */	store_keys[4] = db_columns[4]; /*username*/	store_vals[4].type = DB_STR;	store_vals[4].nul  = 0;	/* domain */	store_keys[5] = db_columns[5]; /*domain*/	store_vals[5].type = DB_STR;	store_vals[5].nul  = 0;}/* value 0 - attr value * value 1 - attr name * value 2 - attr type */static int dbrow2avp(struct db_row *row, struct db_param *dbp, int_str attr,														int just_val_flags){	unsigned int uint;	int  db_flags;	str  atmp;	str  vtmp;	int_str avp_attr;	int_str avp_val;	int flags;	flags = dbp->a.opd;	if (just_val_flags==-1)	{		/* check for null fields into the row */		if (row->values[0].nul || row->values[1].nul || row->values[2].nul )		{			LOG( L_ERR, "ERROR:avpops:dbrow2avp: dbrow contains NULL fields\n");			return -1;		}		/* check the value types */		if ( (row->values[0].type!=DB_STRING && row->values[0].type!=DB_STR)			||  (row->values[1].type!=DB_STRING && row->values[1].type!=DB_STR)			|| row->values[2].type!=DB_INT )		{			LOG(L_ERR,"ERROR:avpops:dbrow2avp: wrong field types in dbrow\n");			return -1;		}		/* check the content of flag field */		uint = (unsigned int)row->values[2].val.int_val;		db_flags = ((uint&AVPOPS_DB_NAME_INT)?0:AVP_NAME_STR) |			((uint&AVPOPS_DB_VAL_INT)?0:AVP_VAL_STR);			DBG("db_flags=%d, flags=%d\n",db_flags,flags);		/* does the avp type match ? */		if(!((flags&(AVPOPS_VAL_INT|AVPOPS_VAL_STR))==0 ||				((flags&AVPOPS_VAL_INT)&&((db_flags&AVP_NAME_STR)==0)) ||				((flags&AVPOPS_VAL_STR)&&(db_flags&AVP_NAME_STR))))			return -2;	} else {		/* check the validity of value column */		if (row->values[0].nul || (row->values[0].type!=DB_STRING &&		row->values[0].type!=DB_STR && row->values[0].type!=DB_INT) )		{			LOG(L_ERR,"ERROR:avpops:dbrow2avp: empty or wrong type for"				" 'value' using scheme\n");			return -1;		}		db_flags = just_val_flags;	}	/* is the avp name already known? */	if ( (flags&AVPOPS_VAL_NONE)==0 )	{		/* use the name  */		avp_attr = attr;	} else {		/* take the name from db response */		if (row->values[1].type==DB_STRING)		{			atmp.s = (char*)row->values[1].val.string_val;			atmp.len = strlen(atmp.s);		} else {			atmp = row->values[1].val.str_val;		}		if (db_flags&AVP_NAME_STR)		{			/* name is string */			avp_attr.s = atmp;		} else {			/* name is ID */			if (str2int( &atmp, &uint)==-1)			{				LOG(L_ERR,"ERROR:avpops:dbrow2avp: name is not ID as "					"flags say <%s>\n", atmp.s);				return -1;			}			avp_attr.n = (int)uint;		}	}	/* now get the value as correct type */	if (row->values[0].type==DB_STRING)	{		vtmp.s = (char*)row->values[0].val.string_val;		vtmp.len = strlen(vtmp.s);	} else if (row->values[0].type==DB_STR){		vtmp = row->values[0].val.str_val;	} else {		vtmp.s = 0;		vtmp.len = 0;	}	if (db_flags&AVP_VAL_STR) {		/* value must be saved as string */		if (row->values[0].type==DB_INT) {			vtmp.s = int2str( (unsigned long)row->values[0].val.int_val,				&vtmp.len);		}		avp_val.s = vtmp;	} else {		/* value must be saved as integer */		if (row->values[0].type!=DB_INT) {			if (vtmp.len==0 || vtmp.s==0 || str2int(&vtmp, &uint)==-1) {				LOG(L_ERR,"ERROR:avpops:dbrow2avp: value is not int "					"as flags say <%s>\n", vtmp.s);				return -1;			}			avp_val.n = (int)uint;		} else {			avp_val.n = row->values[0].val.int_val;		}	}	/* added the avp */	db_flags |= AVP_IS_IN_DB;	/* set script flags */	db_flags |= (dbp->a.sval.flags>>16)&0xff00;	return add_avp( (unsigned short)db_flags, avp_attr, avp_val);}inline static str* get_source_uri(struct sip_msg* msg,int source){	/* which uri will be used? */	if (source&AVPOPS_USE_FROM)	{ /* from */		if (parse_from_header( msg )<0 )		{			LOG(L_ERR,"ERROR:avpops:get_source_uri: failed "				"to parse from\n");			goto error;		}		return &(get_from(msg)->uri);	} else if (source&AVPOPS_USE_TO)	{  /* to */		if (parse_headers( msg, HDR_TO_F, 0)<0)		{			LOG(L_ERR,"ERROR:avpops:get_source_uri: failed "				"to parse to\n");			goto error;		}		return &(get_to(msg)->uri);	} else if (source&AVPOPS_USE_RURI) {  /* RURI */		if(msg->new_uri.s!=NULL && msg->new_uri.len>0)			return &(msg->new_uri);		return &(msg->first_line.u.request.uri);	} else {		LOG(L_CRIT,"BUG:avpops:get_source_uri: unknow source <%d>\n",			source);		goto error;	}error:	return 0;}static inline void int_str2db_val( int_str is_val, str *val, int is_s){	if (is_s)	{		/* val is string */		*val = is_val.s;	} else {		/* val is integer */		val->s =			int2str((unsigned long)is_val.n, &val->len);	}}static int avpops_get_aname(struct sip_msg* msg, struct fis_param *ap,		int_str *avp_name, unsigned short *name_type){	if(ap==NULL || avp_name==NULL || name_type==NULL)	{		LOG(L_ERR, "avpops:avpops_get_aname: bad parameters\n");		return -1;	}	return xl_get_avp_name(msg, &ap->sval, avp_name, name_type);}#define AVPOPS_ATTR_LEN	64static char avpops_attr_buf[AVPOPS_ATTR_LEN];int ops_dbload_avps (struct sip_msg* msg, struct fis_param *sp,									struct db_param *dbp, int use_domain){	struct sip_uri   uri;	db_res_t         *res;	str              uuid;	int  i, n, sh_flg;	str *s0, *s1, *s2;	int_str avp_name;	xl_value_t xvalue;	s0 = s1 = s2 = NULL;	if (!((sp->opd&AVPOPS_VAL_PVAR)||(sp->opd&AVPOPS_VAL_STR))) {		LOG(L_CRIT,"BUG:avpops:load_avps: invalid flag combination (%d/%d)\n",			sp->opd, sp->ops);		goto error;	}	/* get uuid from avp */	if (sp->opd&AVPOPS_VAL_PVAR)	{		if(xl_get_spec_value(msg, &(sp->sval), &xvalue, 0)!=0)		{			LOG(L_CRIT,				"BUG:avpops:load_avps: error getting PVAR value (%d/%d)\n",				sp->opd, sp->ops);			goto error;		}		if(xvalue.flags&(XL_VAL_NULL|XL_VAL_EMPTY))		{			LOG(L_ERR,				"ERROR:avpops:load_avps: no value for first param\n");			goto error;		}		uuid = xvalue.rs;	} else {		uuid.s   = sp->sval.p.val.s;		uuid.len = sp->sval.p.val.len;	}		if(sp->opd&AVPOPS_FLAG_UUID0)	{		s0 = &uuid;	} else {		/* parse uri */		if (parse_uri(uuid.s, uuid.len, &uri)<0)		{			LOG(L_ERR,"ERROR:avpops:load_avps: failed to parse uri\n");			goto error;		}		/* check uri */		if(!uri.user.s|| !uri.user.len|| !uri.host.len|| !uri.host.s)		{			LOG(L_ERR,"ERROR:avpops:load_avps: incomplet uri <%.*s>\n",				uuid.len, uuid.s);			goto error;		}		if((sp->opd&AVPOPS_FLAG_URI0)||(sp->opd&AVPOPS_FLAG_USER0))			s1 = &uri.user;		if((sp->opd&AVPOPS_FLAG_URI0)||(sp->opd&AVPOPS_FLAG_DOMAIN0))			s2 = &uri.host;	}	/* is dynamic avp name ? */	if(dbp->a.sval.flags&XL_DPARAM)	{		if(xl_get_spec_name(msg, &(dbp->a.sval), &xvalue, 0)!=0)		{			LOG(L_CRIT,				"BUG:avpops:load_avps: error getting value for P2\n");			goto error;		}		if(xvalue.flags&(XL_VAL_NULL|XL_VAL_EMPTY))		{			LOG(L_INFO, 					"INFO:avpops:load_avps: no value for p2\n");			goto error;		}		if(xvalue.flags&XL_VAL_STR)		{			if(xvalue.rs.len>=AVPOPS_ATTR_LEN)			{				LOG(L_ERR, 					"ERROR:avpops:load_avps: name too long [%d/%.*s...]\n",					xvalue.rs.len, 16, xvalue.rs.s);				goto error;			}			dbp->sa.s = avpops_attr_buf;			memcpy(dbp->sa.s, xvalue.rs.s, xvalue.rs.len);			dbp->sa.len = xvalue.rs.len;			dbp->sa.s[dbp->sa.len] = '\0';		} else {			LOG(L_INFO, 					"INFO:avpops:load_avps: no string value for p2\n");			goto error;		}	}	/* do DB query */	res = db_load_avp( s0, s1,			((use_domain)||(sp->opd&AVPOPS_FLAG_DOMAIN0))?s2:0,			dbp->sa.s, dbp->table, dbp->scheme);	/* res query ?  */	if (res==0)	{		LOG(L_ERR,"ERROR:avpops:load_avps: db_load failed\n");		goto error;	}	sh_flg = (dbp->scheme)?dbp->scheme->db_flags:-1;	/* process the results */	for( n=0,i=0 ; i<res->n ; i++)	{		/* validate row */		memset(&avp_name, 0, sizeof(int_str));		if(dbp->a.sval.flags&XL_DPARAM)		{			if(xvalue.flags&XL_TYPE_INT)			{				avp_name.n = xvalue.ri;			} else {				avpops_str2int_str(xvalue.rs, avp_name);			}		} else {			avpops_str2int_str(dbp->a.sval.p.val, avp_name);		}		//if ( dbrow2avp( &res->rows[i], dbp->a.opd, avp_name, sh_flg) < 0 )		if ( dbrow2avp( &res->rows[i], dbp, avp_name, sh_flg) < 0 )			continue;		n++;	}	db_close_query( res );	DBG("DEBUG:avpops:load_avps: loaded avps = %d\n",n);	return n?1:-1;error:	return -1;}int ops_dbdelete_avps (struct sip_msg* msg, struct fis_param *sp,									struct db_param *dbp, int use_domain){	struct sip_uri  uri;	int             res;	str             uuid;	xl_value_t xvalue;	str *s0, *s1, *s2;	s0 = s1 = s2 = NULL;	if (!((sp->opd&AVPOPS_VAL_PVAR)||(sp->opd&AVPOPS_VAL_STR))) {		LOG(L_CRIT,			"BUG:avpops:dbdelete_avps: invalid flag combination (%d/%d)\n",			sp->opd, sp->ops);		goto error;	}	/* get uuid from avp */	if (sp->opd&AVPOPS_VAL_PVAR)	{		if(xl_get_spec_value(msg, &(sp->sval), &xvalue, 0)!=0)		{			LOG(L_CRIT,				"BUG:avpops:dbdelete_avps: error getting PVAR value (%d/%d)\n",				sp->opd, sp->ops);			goto error;		}		if(xvalue.flags&(XL_VAL_NULL|XL_VAL_EMPTY))		{			LOG(L_ERR,				"ERROR:avpops:dbdelete_avps: no value for first param\n");			goto error;		}		uuid = xvalue.rs;	} else {		uuid.s   = sp->sval.p.val.s;		uuid.len = sp->sval.p.val.len;	}		if(sp->opd&AVPOPS_FLAG_UUID0)	{		s0 = &uuid;	} else {		/* parse uri */		if (parse_uri(uuid.s, uuid.len, &uri)<0)		{			LOG(L_ERR,"ERROR:avpops:dbdelete_avps: failed to parse uri\n");			goto error;		}		/* check uri */		if(!uri.user.s|| !uri.user.len|| !uri.host.len|| !uri.host.s)		{			LOG(L_ERR,"ERROR:avpops:dbdelete_avps: incomplet uri <%.*s>\n",				uuid.len, uuid.s);			goto error;		}		if((sp->opd&AVPOPS_FLAG_URI0)||(sp->opd&AVPOPS_FLAG_USER0))			s1 = &uri.user;		if((sp->opd&AVPOPS_FLAG_URI0)||(sp->opd&AVPOPS_FLAG_DOMAIN0))			s2 = &uri.host;	}	/* is dynamic avp name ? */	if(dbp->a.sval.flags&XL_DPARAM)	{		if(xl_get_spec_name(msg, &(dbp->a.sval), &xvalue, 0)!=0)		{			LOG(L_CRIT,				"BUG:avpops:dbdelete_avps: error getting value for P2\n");			goto error;		}		if(xvalue.flags&(XL_VAL_NULL|XL_VAL_EMPTY))		{			LOG(L_INFO, 					"INFO:avpops:dbdelete_avps: no value for p2\n");			goto error;		}		if(xvalue.flags&XL_VAL_STR)		{			if(xvalue.rs.len>=AVPOPS_ATTR_LEN)			{				LOG(L_ERR, 					"ERROR:avpops:dbdelete_avps: name too long [%d/%.*s...]\n",					xvalue.rs.len, 16, xvalue.rs.s);				goto error;			}			dbp->sa.s = avpops_attr_buf;			memcpy(dbp->sa.s, xvalue.rs.s, xvalue.rs.len);			dbp->sa.len = xvalue.rs.len;			dbp->sa.s[dbp->sa.len] = '\0';		} else {			LOG(L_INFO, 					"INFO:avpops:dbdelete_avps: no string value for p2\n");			goto error;		}	}	/* do DB delete */	res = db_delete_avp(s0, s1,			(use_domain||(sp->opd&AVPOPS_FLAG_DOMAIN0))?s2:0,			dbp->sa.s, dbp->table);	/* res ?  */	if (res<0)	{		LOG(L_ERR,"ERROR:avpops:dbdelete_avps: db_delete failed\n");		goto error;	}	return 1;error:	return -1;}int ops_dbstore_avps (struct sip_msg* msg, struct fis_param *sp,									struct db_param *dbp, int use_domain){	struct sip_uri   uri;	struct usr_avp   **avp_list;	struct usr_avp   *avp;	unsigned short   name_type;	int_str          avp_name;	int_str          i_s;	str              uuid;	int              keys_nr;	int              n;	xl_value_t xvalue;	str *s0, *s1, *s2;	str *sn;	s0 = s1 = s2 = NULL;	name_type = 0;	if (!((sp->opd&AVPOPS_VAL_PVAR)||(sp->opd&AVPOPS_VAL_STR))) {		LOG(L_CRIT,			"BUG:avpops:dbstore_avps: invalid flag combination (%d/%d)\n",			sp->opd, sp->ops);		goto error;	}	keys_nr = 6; /* uuid, avp name, avp val, avp type, user, domain */		/* get uuid from avp */	if (sp->opd&AVPOPS_VAL_PVAR)	{		if(xl_get_spec_value(msg, &(sp->sval), &xvalue, 0)!=0)		{			LOG(L_CRIT,				"BUG:avpops:dbstore_avps: error getting PVAR value (%d/%d)\n",				sp->opd, sp->ops);			goto error;		}		if(xvalue.flags&(XL_VAL_NULL|XL_VAL_EMPTY))		{			LOG(L_ERR,				"ERROR:avpops:dbstore_avps: no value for first param\n");			goto error;		}		uuid = xvalue.rs;	} else {		uuid.s   = sp->sval.p.val.s;		uuid.len = sp->sval.p.val.len;	}		if(sp->opd&AVPOPS_FLAG_UUID0)	{		s0 = &uuid;	} else {		/* parse uri */		if (parse_uri(uuid.s, uuid.len, &uri)<0)		{			LOG(L_ERR,"ERROR:avpops:dbstore_avps: failed to parse uri\n");			goto error;		}		/* check uri */		if(!uri.user.s|| !uri.user.len|| !uri.host.len|| !uri.host.s)		{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?