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 + -
显示快捷键?