⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avpops_parse.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/* * $Id: avpops_parse.c,v 1.8.2.1 2005/01/12 13:41:47 ramona Exp $ * * Copyright (C) 2004 Voice Sistem SRL * * This file is part of SIP Express Router. * * AVPOPS SER-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 SER-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) *  2004-11-11  DB scheme added (ramona) *  2004-11-17  aligned to new AVP core global aliases (ramona) */#include <stdlib.h>#include <ctype.h>#include "../../ut.h"#include "../../dprint.h"#include "../../usr_avp.h"#include "../../mem/mem.h"#include "avpops_parse.h"#define SCHEME_UUID_COL          "uuid_col"#define SCHEME_UUID_COL_LEN      (sizeof(SCHEME_UUID_COL)-1)#define SCHEME_USERNAME_COL      "username_col"#define SCHEME_USERNAME_COL_LEN  (sizeof(SCHEME_USERNAME_COL)-1)#define SCHEME_DOMAIN_COL        "domain_col"#define SCHEME_DOMAIN_COL_LEN    (sizeof(SCHEME_DOMAIN_COL)-1)#define SCHEME_VALUE_COL         "value_col"#define SCHEME_VALUE_COL_LEN     (sizeof(SCHEME_VALUE_COL)-1)#define SCHEME_TABLE             "table"#define SCHEME_TABLE_LEN         (sizeof(SCHEME_TABLE)-1)#define SCHEME_VAL_TYPE          "value_type"#define SCHEME_VAL_TYPE_LEN      (sizeof(SCHEME_VAL_TYPE)-1)#define SCHEME_INT_TYPE          "integer"#define SCHEME_INT_TYPE_LEN      (sizeof(SCHEME_INT_TYPE)-1)#define SCHEME_STR_TYPE          "string"#define SCHEME_STR_TYPE_LEN      (sizeof(SCHEME_STR_TYPE)-1)char *parse_avp_attr(char *s, struct fis_param *attr, char end){	unsigned int uint;	str tmp;	/*DBG("s=%p s=%c(%d)\n",s,*s,*s);*/	/* search for type identifier */	if ( s[0] && s[1]==':' )	{		switch (s[0])		{			case 'i':			case 'I':				attr->flags |= AVPOPS_VAL_INT;				break;			case 's':			case 'S':				attr->flags |= AVPOPS_VAL_STR;				break;			default:				LOG(L_ERR,"ERROR:avpops:parse_avp_attr: invalid type '%c'\n",					s[0]);				goto error;		}		s += 2;	}	/* search for the avp name */	tmp.s = s;	while ( *s && *s!=end && !isspace((int)*s)) s++;	tmp.len = s - tmp.s;	if (tmp.len==0)	{		attr->flags |= AVPOPS_VAL_NONE;	} else {		if ( attr->flags&AVPOPS_VAL_INT)		{			/* convert to ID (int) */			if ( str2int( &tmp, &uint)==-1 )			{				LOG(L_ERR,"ERROR:avpops:parse_avp_attr: attribute is not "					"int as type says <%s>\n", tmp.s);				goto error;			}			attr->val.n = (int)uint;		} else {			/* duplicate name as str NULL terminated */			attr->val.s = (str*)pkg_malloc( sizeof(str) + tmp.len + 1 );			if (attr->val.s==0)			{				LOG(L_ERR,"ERROR:avpops:parse_avp_attr: no more pkg mem\n");				goto error;			}			attr->val.s->s = ((char*)attr->val.s) + sizeof(str);			attr->val.s->len = tmp.len;			memcpy( attr->val.s->s, tmp.s, tmp.len);			attr->val.s->s[attr->val.s->len] = 0;		}	}	return s;error:	return 0;}int parse_avp_db(char *s, struct db_param *dbp, int allow_scheme){	unsigned long ul;	str   tmp;	char  c;	char  have_scheme;	int   type;	/* parse the attribute name - check first if it's not an alias */	if ( *s=='$')	{		tmp.s = ++s;		/* is an avp alias -> see where it ends */		if ( (s=strchr(tmp.s, '/'))!=0 )		{			c = *s;			tmp.len = s - tmp.s;		} else {			c = 0;			tmp.len = strlen(tmp.s);		}		if (tmp.len==0)		{			LOG(L_ERR,"ERROR:avpops:parse_avp_db: empty alias in <%s>\n", s);			goto error;		}		/* search the alias */		if ( lookup_avp_galias( &tmp, &type, &dbp->a.val)!=0 )		{			LOG(L_ERR,"ERROR:avpops:parse_avp_db: unknow alias"				"\"%s\"\n", tmp.s);			goto error;		}		dbp->a.flags = (type&AVP_NAME_STR)?AVPOPS_VAL_STR:AVPOPS_VAL_INT;	} else {		if ( (s=parse_avp_attr( s, &(dbp->a), '/'))==0 )			goto error;		if (*s!=0 && *s!='/')		{			LOG(L_ERR,"ERROR:avpops:parse_avp_db: parse error arround "				"<%s>\n",s);			goto error;		}	}	dbp->a.flags |= AVPOPS_VAL_AVP;	/* optimize asn keep the attribute name as str also to	 * speed up db querie builds */	if (!(dbp->a.flags&AVPOPS_VAL_NONE))	{		if (dbp->a.flags&AVPOPS_VAL_STR)		{			dbp->sa = *dbp->a.val.s;		} else {			ul = (unsigned long)dbp->a.val.n;			tmp.s = int2str( ul, &(tmp.len) );			dbp->sa.s = (char*)pkg_malloc( tmp.len + 1 );			if (dbp->sa.s==0)			{				LOG(L_ERR,"ERROR:avpops:parse_avp_db: no more pkg mem\n");				goto error;			}			memcpy( dbp->sa.s, tmp.s, tmp.len);			dbp->sa.len = tmp.len;			dbp->sa.s[dbp->sa.len] = 0;		}	}	/* is there a table name ? */	if (s && *s)	{		s++;		if (*s=='$')		{			if (allow_scheme==0)			{				LOG(L_ERR,"ERROR:avpops:parse_avp_db: function doesn't "					"support DB schemes\n");				goto error;			}			if (dbp->a.flags&AVPOPS_VAL_NONE)			{				LOG(L_ERR,"ERROR:avpops:parse_avp_db: inconsistent usage of "					"DB scheme without complet specification of AVP name\n");				goto error;			}			have_scheme = 1;			s++;		} else {			have_scheme = 0;		}		tmp.s = s;		tmp.len = 0;		while ( *s ) s++;		tmp.len = s - tmp.s;		if (tmp.len==0)		{			LOG(L_ERR,"ERROR:avpops:parse_av_dbp: empty scheme/table name\n");			goto error;		}		if (have_scheme)		{			dbp->scheme = avp_get_db_scheme( tmp.s );			if (dbp->scheme==0) 			{				LOG(L_ERR,"ERROR:avpops:parse_avp_db: scheme <%s> not found\n",					tmp.s);				goto error;;			}			/* update scheme flags with AVP name type*/			dbp->scheme->db_flags|=dbp->a.flags&AVPOPS_VAL_STR?AVP_NAME_STR:0;		} else {			/* duplicate table as str NULL terminated */			dbp->table = (char*)pkg_malloc( tmp.len + 1 );			if (dbp->table==0)			{				LOG(L_ERR,"ERROR:avpops:parse_avp_db: no more pkg mem\n");				goto error;			}			memcpy( dbp->table, tmp.s, tmp.len);			dbp->table[tmp.len] = 0;		}	}	return 0;error:	return -1;}struct fis_param* parse_intstr_value(char *p, int len){	struct fis_param *vp;	unsigned int uint;	str val_str;	int flags;	if (p==0 || len==0)			goto error;	if (*(p+1)==':')	{		if (*p=='i' || *p=='I')			flags = AVPOPS_VAL_INT;		else if (*p=='s' || *p=='S')			flags = AVPOPS_VAL_STR;		else		{			LOG(L_ERR,"ERROR:avpops:parse_intstr_value: unknown value type "				"<%c>\n",*p);			goto error;		}		p += 2;		len -= 2;		if (*p==0 || len<=0 )		{			LOG(L_ERR,"ERROR:avpops:parse_intstr_value: parse error arround "				"<%.*s>\n",len,p);			goto error;		}	} else {		flags = AVPOPS_VAL_STR;	}	/* get the value */	vp = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));	if (vp==0)	{		LOG(L_ERR,"ERROR:avpops:parse_intstr_value: no more pkg mem\n");		goto error;;	}	memset( vp, 0, sizeof(struct fis_param));	vp->flags = flags;	val_str.s = p;	val_str.len = len;	if (flags&AVPOPS_VAL_INT) {		/* convert the value to integer */		if ( str2int( &val_str, &uint)==-1 )		{			LOG(L_ERR,"ERROR:avpops:parse_intstr_value: value is not int "				"as type says <%.*s>\n", val_str.len, val_str.s);			goto error;		}		vp->val.n = (int)uint;	} else {		/* duplicate the value as string */		vp->val.s = (str*)pkg_malloc( sizeof(str) + val_str.len +1 );		if (vp->val.s==0)		{			LOG(L_ERR,"ERROR:avpops:parse_intstr_value: no more pkg mem\n");			goto error;		}		vp->val.s->s = ((char*)vp->val.s) + sizeof(str);		vp->val.s->len = val_str.len;		memcpy( vp->val.s->s, val_str.s, val_str.len);		vp->val.s->s[vp->val.s->len] = 0;	}	return vp;error:	return 0;}struct fis_param* parse_check_value(char *s){	struct fis_param *vp;	int  flags;	char *p;	char *t;	int len;	int type;	str alias;	flags = 0;	vp = 0;	if ( (p=strchr(s,'/'))==0 || p-s!=2 )		goto parse_error;	/* get the operation */	if (strncasecmp(s,"eq",2)==0)	{		flags |= AVPOPS_OP_EQ;	} else if (strncasecmp(s,"lt",2)==0) {		flags |= AVPOPS_OP_LT;	} else if (strncasecmp(s,"gt",2)==0) {		flags |= AVPOPS_OP_GT;	} else if (strncasecmp(s,"re",2)==0) {		flags |= AVPOPS_OP_RE;	} else {		LOG(L_ERR,"ERROR:avpops:parse_check_value: unknown operation "			"<%.*s>\n",2,s);		goto error;	}	/* get the value */	if (*(++p)==0)		goto parse_error;	if ( (t=strchr(p,'/'))==0)		len = strlen(p);	else		len = t-p;	if (*p=='$')	{		if (*(++p)==0 || (--len)==0)			goto parse_error;		/* struct for value */		vp = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));		if (vp==0) {			LOG(L_ERR,"ERROR:avpops:parse_check_value: no more pkg mem\n");			goto error;		}		memset( vp, 0, sizeof(struct fis_param));		/* variable -> which one? */		if ( (strncasecmp(p,"ruri"  ,len)==0 && (flags|=AVPOPS_USE_RURI))		  || (strncasecmp(p,"from"  ,len)==0 && (flags|=AVPOPS_USE_FROM))		  || (strncasecmp(p,"to"    ,len)==0 && (flags|=AVPOPS_USE_TO))		  || (strncasecmp(p,"src_ip",len)==0 && (flags|=AVPOPS_USE_SRC_IP)))		{			flags |= AVPOPS_VAL_NONE;		} else {			alias.s = p;			alias.len = len;			if ( lookup_avp_galias( &alias, &type, &vp->val)!=0 )			{				LOG(L_ERR,"ERROR:avpops:parse_check_value: unknown "					"variable/alias <%.*s>\n",len,p);				goto error;			}			flags |= AVPOPS_VAL_AVP |				((type&AVP_NAME_STR)?AVPOPS_VAL_STR:AVPOPS_VAL_INT);			DBG("flag==%d\n",flags);		}		p += len;	} else {		/* value is explicitly given */		if ( (vp=parse_intstr_value(p,len))==0) {			LOG(L_ERR,"ERROR:avpops:parse_check_value: unable to "				"parse value\n");			goto error;		}		/* go over */		p += len;	}	/* any flags */	if (*p!=0 )	{		if (*p!='/' || *(++p)==0)			goto parse_error;		while (*p)		{			switch (*p)			{				case 'g':				case 'G':					flags|=AVPOPS_FLAG_ALL;					break;				case 'i':				case 'I':					flags|=AVPOPS_FLAG_CI;					break;				default:					LOG(L_ERR,"ERROR:avpops:parse_check_value: unknown flag "						"<%c>\n",*p);					goto error;			}			p++;		}	}	vp->flags |= flags;	return vp;parse_error:	LOG(L_ERR,"ERROR:avpops:parse_check_value: parse error in <%s> pos %ld\n",		s,(long)(p-s));error:	if (vp) pkg_free(vp);	return 0;}#define  duplicate_str(_p, _str, _error) \	do { \		_p = (char*)pkg_malloc(_str.len+1); \		if (_p==0) \		{ \			LOG(L_ERR,"ERROR:avpops:parse_avp_sb_scheme: " \				"no more pkg memory\n");\			goto _error; \		} \		memcpy( _p, _str.s, _str.len); \		_p[_str.len] = 0; \	}while(0)int parse_avp_db_scheme( char *s, struct db_scheme *scheme){	str foo;	str bar;	char *p;	if (s==0 || *s==0)		goto error;	p = s;	/*parse the name */	while (*p && isspace((int)*p)) p++;	foo.s = p;	while (*p && *p!=':' && !isspace((int)*p)) p++;	if (foo.s==p || *p==0)		/* missing name or empty scheme */		goto parse_error;	foo.len = p - foo.s;	/* dulicate it */	duplicate_str( scheme->name, foo, error);	/* parse the ':' separator */	while (*p && isspace((int)*p)) p++;	if (*p!=':')		goto parse_error;	p++;	while (*p && isspace((int)*p)) p++;	if (*p==0)		goto parse_error;	/* set as default value type string */	scheme->db_flags = AVP_VAL_STR;	/* parse the attributes */	while (*p)	{		/* get the attribute name */		foo.s = p;		while (*p && *p!='=' && !isspace((int)*p)) p++;		if (p==foo.s || *p==0)			/* missing attribute name */			goto parse_error;		foo.len = p - foo.s;		/* parse the '=' separator */		while (*p && isspace((int)*p)) p++;		if (*p!='=')			goto parse_error;		p++;		while (*p && isspace((int)*p)) p++;		if (*p==0)			goto parse_error;		/* parse the attribute value */		bar.s = p;		while (*p && *p!=';' && !isspace((int)*p)) p++;		if (p==bar.s)			/* missing attribute value */			goto parse_error;		bar.len = p - bar.s;		/* parse the ';' separator, if any */		while (*p && isspace((int)*p)) p++;		if (*p!=0 && *p!=';')			goto parse_error;		if (*p==';') p++;		while (*p && isspace((int)*p)) p++;		/* identify the attribute */		if ( foo.len==SCHEME_UUID_COL_LEN && 		!strncasecmp( foo.s, SCHEME_UUID_COL, foo.len) )		{			duplicate_str( scheme->uuid_col, bar, error);		} else		if ( foo.len==SCHEME_USERNAME_COL_LEN && 		!strncasecmp( foo.s, SCHEME_USERNAME_COL, foo.len) )		{			duplicate_str( scheme->username_col, bar, error);		} else		if ( foo.len==SCHEME_DOMAIN_COL_LEN && 		!strncasecmp( foo.s, SCHEME_DOMAIN_COL, foo.len) )		{			duplicate_str( scheme->domain_col, bar, error);		} else		if ( foo.len==SCHEME_VALUE_COL_LEN && 		!strncasecmp( foo.s, SCHEME_VALUE_COL, foo.len) )		{			duplicate_str( scheme->value_col, bar, error);		} else		if ( foo.len==SCHEME_TABLE_LEN && 		!strncasecmp( foo.s, SCHEME_TABLE, foo.len) )		{			duplicate_str( scheme->table, bar, error);		} else		if ( foo.len==SCHEME_VAL_TYPE_LEN && 		!strncasecmp( foo.s, SCHEME_VAL_TYPE, foo.len) )		{			if ( bar.len==SCHEME_INT_TYPE_LEN &&			!strncasecmp( bar.s, SCHEME_INT_TYPE, bar.len) )				scheme->db_flags &= (~AVP_VAL_STR);			else if ( bar.len==SCHEME_STR_TYPE_LEN &&			!strncasecmp( bar.s, SCHEME_STR_TYPE, bar.len) )				scheme->db_flags = AVP_VAL_STR;			else			{				LOG(L_ERR,"ERROR:avpops:parse_avp_sb_scheme: unknown "					"value type <%.*s>\n",bar.len,bar.s);				goto error;			}		} else {			LOG(L_ERR,"ERROR:avpops:parse_avp_sb_scheme: unknown "				"attribute <%.*s>\n",foo.len,foo.s);			goto error;		}	} /* end while */	return 0;parse_error:	LOG(L_ERR,"ERROR:avpops:parse_avp_sb_scheme: parse error in <%s> "		"around %ld\n", s, (long)(p-s));error:	return -1;}

⌨️ 快捷键说明

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