acc_extra.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 299 行

C
299
字号
/* * $Id: acc_extra.c,v 1.7 2006/05/22 11:16:44 miconda Exp $ * * Copyright (C) 2004 Voice Sistem SRL * * This file is part of SIP Express Router. * * openser 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. * * openser 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. * * * History: * --------- *  2004-10-28  first version (ramona) *  2005-05-30  acc_extra patch commited (ramona) *  2005-07-13  acc_extra specification moved to use pseudo-variables (bogdan) */#include <stdlib.h>#include <string.h>#include <ctype.h>#include "../../dprint.h"#include "../../ut.h"#include "../../items.h"#include "../../mem/mem.h"#include "acc_extra.h"#define EQUAL '='#define SEPARATOR ';'/* static arrays used for faster and simpler int to str conversion *//* here we copy the strings returned by int2str (which uses a static buffer) */static char int_buf[INT2STR_MAX_LEN*MAX_ACC_EXTRA];/* str's with all extra values; first MAX_ACC_EXTRA elements point into  * int_buf[] and are used for int2str vals; second MAX_ACC_EXTRA are just  * containers for the normal str vals */static str  str_buf[2*MAX_ACC_EXTRA];static char *static_detector = 0;static str na = {"n/a", 3};void init_acc_extra(){	int i;	for (i=0; i<MAX_ACC_EXTRA; i++)	{		str_buf[i].s = int_buf + i*INT2STR_MAX_LEN;		str_buf[i].len = 0;	}	for (i=MAX_ACC_EXTRA;i<2*MAX_ACC_EXTRA; i++)	{		str_buf[i].s = 0;		str_buf[i].len = 0;	}	/* ugly trick to get the address of the static buffer */	static_detector = int2str( (unsigned long)3, &i) + i;}struct acc_extra *parse_acc_extra(char *extra_str){	struct acc_extra *head;	struct acc_extra *tail;	struct acc_extra *extra;	char *foo;	char *s;	int  xl_flags;	int  n;	n = 0;	head = 0;	extra = 0;	tail = 0;	s = extra_str;	xl_flags = XL_THROW_ERROR | XL_DISABLE_COLORS;	if (s==0)	{		LOG(L_ERR,"ERROR:acc:parse_acc_extra: null string received\n");		goto error;	}	while (*s)	{		/* skip white spaces */		while (*s && isspace((int)*s))  s++;		if (*s==0)			goto parse_error;		if (n==MAX_ACC_EXTRA)		{			LOG(L_ERR,"ERROR:acc:parse_acc_extra: too many extras -> please "				"increase the internal buffer\n");			goto error;		}		extra = (struct acc_extra*)pkg_malloc(sizeof(struct acc_extra));		if (extra==0)		{			LOG(L_ERR,"ERROR:acc:parse_acc_extra: no more pkg mem 1\n");			goto error;		}		memset( extra, 0, sizeof(struct acc_extra));		/* link the new extra at the end */		if (tail==0)		{			head = extra;		} else {			tail->next = extra;		}		tail = extra;		n++;		/* get name */		foo = s;		while (*s && !isspace((int)*s) && EQUAL!=*s)  s++;		if (*s==0)			goto parse_error;		if (*s==EQUAL)		{			extra->name.len = (s++) - foo;		} else {			extra->name.len = (s++) - foo;			/* skip spaces */			while (*s && isspace((int)*s))  s++;			if (*s!=EQUAL)				goto parse_error;			s++;		}		extra->name.s = foo;		/* skip spaces */		while (*s && isspace((int)*s))  s++;		/* get value type */		if ( (foo=xl_parse_spec( s, &extra->spec, xl_flags))==0 )			goto parse_error;		s = foo;		/* skip spaces */		while (*s && isspace((int)*s))  s++;		if (*s && (*(s++)!=SEPARATOR || *s==0))			goto parse_error;	}	/* go throught all extras and make the names null terminated */	for( extra=head ; extra ; extra=extra->next)		extra->name.s[extra->name.len] = 0;	return head;parse_error:	LOG(L_ERR,"ERROR:acc:parse_acc_extra: parse failed in <%s> "		"around position %d\n",extra_str, (int)(long)(s-extra_str));error:	LOG(L_ERR,"acc:parse_acc_extra: error\n");	destroy_extras(head);	return 0;}void destroy_extras( struct acc_extra *extra){	struct acc_extra *foo;	while (extra)	{		foo = extra;		extra = extra->next;		pkg_free(foo);	}}/* extra name is moved as string part of an attribute; str.len will contain an * index to the corresponding attribute */int extra2attrs( struct acc_extra *extra, struct attr *attrs, int offset){	int i;	for(i=0 ; extra && i<MAX_ACC_EXTRA ; i++, extra=extra->next)	{		attrs[offset+i].n = extra->name.s;		extra->name.s =0;		extra->name.len = offset + i;	}	return i;}/* converts the name of the extra from str to integer  * and stores it over str.len ; str.s is freed and made zero */int extra2int( struct acc_extra *extra ){	unsigned int ui;	int i;	for( i=0 ; extra&&i<MAX_ACC_EXTRA ; i++,extra=extra->next )	{		if (str2int( &extra->name, &ui)!=0)		{			LOG(L_ERR,"ERROR:acc:extra2int: <%s> is not number\n",				extra->name.s);			return -1;		}		pkg_free( extra->name.s );		extra->name.s = 0;		extra->name.len = (int)ui;	}	return 0;}#define set_acc( _n, _name, _vals) \	do {\		attr_arr[_n] = _name; \		val_arr[_n] = _vals; \		*attr_len += attr_arr[_n].len; \		*val_len += val_arr[_n]->len; \		(_n)++; \	} while(0)int extra2strar( struct acc_extra *extra, /* extra list to account */		struct sip_msg *rq, /* accounted message */		int *attr_len,  /* total length of accounted attribute names */		int *val_len, /* total length of accounted values */		str *attr_arr,		str **val_arr){	xl_value_t value;	int    n;	int    p;	int    r;	n = 0;	p = 0;	r = MAX_ACC_EXTRA;	while (extra) 	{		/* get the value */		if (xl_get_spec_value( rq, &extra->spec, &value, 0)!=0)		{			LOG(L_ERR,"ERROR:acc:extra2strar: failed to get '%.*s'\n",				extra->name.len,extra->name.s);		}		/* check for overflow */		if (n==MAX_ACC_EXTRA) 		{			LOG(L_WARN,"WARNING:acc:extra2strar: array to short "				"-> ommiting extras for accounting\n");			goto done;		}		if(value.flags&XL_VAL_NULL)		{ /* convert <null> to <n/a> to have consistency */			str_buf[r] = na;			set_acc( n, extra->name, &str_buf[r] );			r++;		} else {			/* set the value into the acc buffer */			if (value.rs.s+value.rs.len==static_detector)			{				memcpy(str_buf[p].s, value.rs.s, value.rs.len);				str_buf[p].len = value.rs.len;				set_acc( n, extra->name, &str_buf[p] );				p++;			} else {				str_buf[r] = value.rs;				set_acc( n, extra->name, &str_buf[r] );				r++;			}		}		extra = extra->next;	}done:	return n;}

⌨️ 快捷键说明

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