📄 avpops_impl.c
字号:
/* * $Id: avpops_impl.c,v 1.5 2004/11/15 10:19:39 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) */#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <regex.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 "../../parser/parse_from.h"#include "../../parser/parse_uri.h"#include "../../mem/mem.h"#include "avpops_impl.h"#include "avpops_db.h"static db_key_t store_keys[6];static db_val_t store_vals[6];static str empty={"",0};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, int flags, 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; 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) ) { 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 { vtmp = row->values[0].val.str_val; } if (db_flags&AVP_VAL_STR) { /* value is string */ avp_val.s = &vtmp; } else { /* name is ID */ if (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; } /* added the avp */ db_flags |= AVP_IS_IN_DB; 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, 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 int parse_source_uri(struct sip_msg* msg,int source,struct sip_uri *uri){ str *uri_s; /* get uri */ if ( (uri_s=get_source_uri(msg,source))==0 ) { LOG(L_ERR,"ERROR:avpops:parse_source_uri: cannot get uri\n"); goto error; } /* parse uri */ if (parse_uri(uri_s->s, uri_s->len , uri)<0) { LOG(L_ERR,"ERROR:avpops:parse_source_uri: 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:parse_source_uri: incomplet uri <%.*s>\n", uri_s->len,uri_s->s); goto error; } return 0;error: return -1;}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 get_avp_as_str(struct fis_param *ap ,str *val){ struct usr_avp *avp; unsigned short name_type; int_str avp_val; name_type = ((ap->flags&AVPOPS_VAL_INT)?0:AVP_NAME_STR); avp = search_first_avp( name_type, ap->val, &avp_val); if (avp==0) { DBG("DEBUG:avpops:get_val_as_str: no avp found\n"); return -1; } int_str2db_val( avp_val, val, avp->flags&AVP_VAL_STR); return 0;}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; if (sp->flags&AVPOPS_VAL_NONE) { /* get and parse uri */ if (parse_source_uri( msg, sp->flags, &uri)<0 ) { LOG(L_ERR,"ERROR:avpops:load_avps: failed to get uri\n"); goto error; } /* do DB query */ res = db_load_avp( 0, (sp->flags&AVPOPS_FLAG_DOMAIN)?&empty:&uri.user, (use_domain||(sp->flags&AVPOPS_FLAG_DOMAIN))?&uri.host:0, dbp->sa.s, dbp->table , dbp->scheme); } else if (sp->flags&AVPOPS_VAL_AVP) { /* get uuid from avp */ if (get_avp_as_str( sp, &uuid)<0) { LOG(L_ERR,"ERROR:avpops:load_avps: failed to get uuid\n"); goto error; } /* do DB query */ res = db_load_avp( &uuid, 0, 0, dbp->sa.s, dbp->table, dbp->scheme); } else if (sp->flags&AVPOPS_VAL_STR) { /* use the STR val as uuid */ /* do DB query */ res = db_load_avp( sp->val.s, 0, 0, dbp->sa.s, dbp->table, dbp->scheme); } else { LOG(L_CRIT,"BUG:avpops:load_avps: invalid flag combination (%d)\n", sp->flags); goto error; } /* 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 */ if ( dbrow2avp( &res->rows[i], dbp->a.flags, dbp->a.val, 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_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 i_s; str uuid; int keys_off; int keys_nr; int n; if (sp->flags&AVPOPS_VAL_NONE) { /* get and parse uri */ if (parse_source_uri( msg, sp->flags, &uri)<0 ) { LOG(L_ERR,"ERROR:avpops:store_avps: failed to get uri\n"); goto error; } /* set values for keys */ keys_off = 1; store_vals[4].val.str_val = (sp->flags&AVPOPS_FLAG_DOMAIN)?empty:uri.user; if (use_domain || sp->flags&AVPOPS_FLAG_DOMAIN) { store_vals[5].val.str_val = uri.host; keys_nr = 5; } else { keys_nr = 4; } } else if (sp->flags&AVPOPS_VAL_AVP) { /* get uuid from avp */ if (get_avp_as_str(sp, &uuid)<0) { LOG(L_ERR,"ERROR:avpops:store_avps: failed to get uuid\n"); goto error; } /* set values for keys */ keys_off = 0; keys_nr = 4; store_vals[0].val.str_val = uuid; } else if (sp->flags&AVPOPS_VAL_STR) { /* use the STR value as uuid */ /* set values for keys */ keys_off = 0; keys_nr = 4; store_vals[0].val.str_val = *sp->val.s; } else { LOG(L_CRIT,"BUG:avpops:store_avps: invalid flag combination (%d)\n", sp->flags); goto error; } /* set uuid/(username and domain) fields */ n =0 ; if ((dbp->a.flags&AVPOPS_VAL_NONE)==0) { /* avp name is known ->set it and its type */ name_type = (((dbp->a.flags&AVPOPS_VAL_INT))?0:AVP_NAME_STR); store_vals[1].val.str_val = dbp->sa; /*attr name*/ avp = search_first_avp( name_type, dbp->a.val, &i_s); for( ; avp; avp=search_next_avp(avp,&i_s)) { /* don't insert avps which were loaded */ if (avp->flags&AVP_IS_IN_DB) continue; /* set type */ store_vals[3].val.int_val = (avp->flags&AVP_NAME_STR?0:AVPOPS_DB_NAME_INT)| (avp->flags&AVP_VAL_STR?0:AVPOPS_DB_VAL_INT); /* set value */ int_str2db_val( i_s, &store_vals[2].val.str_val, avp->flags&AVP_VAL_STR); /* save avp */ if (db_store_avp( store_keys+keys_off, store_vals+keys_off, keys_nr, dbp->table)==0 ) { avp->flags |= AVP_IS_IN_DB; n++; } } } else { /* avp name is unknown -> go through all list */ avp_list = get_avp_list(); avp = *avp_list; for ( ; avp ; avp=avp->next ) { /* don't insert avps which were loaded */ if (avp->flags&AVP_IS_IN_DB) continue; /* check if type match */ if ( !( (dbp->a.flags&(AVPOPS_VAL_INT|AVPOPS_VAL_STR))==0 || ((dbp->a.flags&AVPOPS_VAL_INT)&&((avp->flags&AVP_NAME_STR))==0) ||((dbp->a.flags&AVPOPS_VAL_STR)&&(avp->flags&AVP_NAME_STR)))) continue; /* set attribute name and type */ if ( (i_s.s=get_avp_name(avp))==0 ) i_s.n = avp->id; int_str2db_val( i_s, &store_vals[1].val.str_val, avp->flags&AVP_NAME_STR); store_vals[3].val.int_val = (avp->flags&AVP_NAME_STR?0:AVPOPS_DB_NAME_INT)| (avp->flags&AVP_VAL_STR?0:AVPOPS_DB_VAL_INT); /* set avp value */ get_avp_val( avp, &i_s); int_str2db_val( i_s, &store_vals[2].val.str_val, avp->flags&AVP_VAL_STR); /* save avp */ if (db_store_avp( store_keys+keys_off, store_vals+keys_off, keys_nr, dbp->table)==0) { avp->flags |= AVP_IS_IN_DB; n++; } } } DBG("DEBUG:avpops:store_avps: %d avps were stored\n",n); return n==0?-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; if (sp->flags&AVPOPS_VAL_NONE) { /* get and parse uri */ if (parse_source_uri( msg, sp->flags, &uri)<0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -