Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <ctype.h>
00047 #include "../../dprint.h"
00048 #include "../../ut.h"
00049 #include "../../usr_avp.h"
00050 #include "../../mem/mem.h"
00051 #include "acc_api.h"
00052 #include "acc_extra.h"
00053
00054 #define EQUAL '='
00055 #define SEPARATOR ';'
00056
00057
00058 #if MAX_ACC_EXTRA<MAX_ACC_LEG
00059 #define MAX_ACC_INT_BUF MAX_ACC_LEG
00060 #else
00061 #define MAX_ACC_INT_BUF MAX_ACC_EXTRA
00062 #endif
00063
00064 static char int_buf[INT2STR_MAX_LEN*MAX_ACC_INT_BUF];
00065
00066 static char *static_detector = 0;
00067
00068 void init_acc_extra(void)
00069 {
00070 int i;
00071
00072 static_detector = int2str( (unsigned long)3, &i) + i;
00073 }
00074
00075
00076 struct acc_extra *parse_acc_leg(char *extra_str)
00077 {
00078 struct acc_extra *legs;
00079 struct acc_extra *it;
00080 int n;
00081
00082 legs = parse_acc_extra(extra_str);
00083 if (legs==0) {
00084 LM_ERR("failed to parse extra leg\n");
00085 return 0;
00086 }
00087
00088
00089 for( it=legs,n=0 ; it ; it=it->next ) {
00090 if (it->spec.type!=PVT_AVP) {
00091 LM_ERR("only AVP are accepted as leg info\n");
00092 destroy_extras(legs);
00093 return 0;
00094 }
00095 n++;
00096 if (n>MAX_ACC_LEG) {
00097 LM_ERR("too many leg info; MAX=%d\n", MAX_ACC_LEG);
00098 destroy_extras(legs);
00099 return 0;
00100 }
00101 }
00102
00103 return legs;
00104 }
00105
00106
00107 struct acc_extra *parse_acc_extra(char *extra_str)
00108 {
00109 struct acc_extra *head;
00110 struct acc_extra *tail;
00111 struct acc_extra *extra;
00112 char *foo;
00113 char *s;
00114 int n;
00115 str stmp;
00116
00117 n = 0;
00118 head = 0;
00119 extra = 0;
00120 tail = 0;
00121 s = extra_str;
00122
00123 if (s==0) {
00124 LM_ERR("null string received\n");
00125 goto error;
00126 }
00127
00128 while (*s) {
00129
00130 while (*s && isspace((int)*s)) s++;
00131 if (*s==0)
00132 goto parse_error;
00133 if (n==MAX_ACC_EXTRA) {
00134 LM_ERR("too many extras -> please increase the internal buffer\n");
00135 goto error;
00136 }
00137 extra = (struct acc_extra*)pkg_malloc(sizeof(struct acc_extra));
00138 if (extra==0) {
00139 LM_ERR("no more pkg mem 1\n");
00140 goto error;
00141 }
00142 memset( extra, 0, sizeof(struct acc_extra));
00143
00144
00145 if (tail==0) {
00146 head = extra;
00147 } else {
00148 tail->next = extra;
00149 }
00150 tail = extra;
00151 n++;
00152
00153
00154 foo = s;
00155 while (*s && !isspace((int)*s) && EQUAL!=*s) s++;
00156 if (*s==0)
00157 goto parse_error;
00158 if (*s==EQUAL) {
00159 extra->name.len = (s++) - foo;
00160 } else {
00161 extra->name.len = (s++) - foo;
00162
00163 while (*s && isspace((int)*s)) s++;
00164 if (*s!=EQUAL)
00165 goto parse_error;
00166 s++;
00167 }
00168 extra->name.s = foo;
00169
00170
00171 while (*s && isspace((int)*s)) s++;
00172
00173
00174 stmp.s = s; stmp.len = strlen(s);
00175 if ( (foo=pv_parse_spec(&stmp, &extra->spec))==0 )
00176 goto parse_error;
00177 s = foo;
00178
00179
00180 while (*s && isspace((int)*s)) s++;
00181 if (*s && (*(s++)!=SEPARATOR || *s==0))
00182 goto parse_error;
00183 }
00184
00185
00186 for( extra=head ; extra ; extra=extra->next)
00187 extra->name.s[extra->name.len] = 0;
00188
00189 return head;
00190 parse_error:
00191 LM_ERR("parse failed in <%s> "
00192 "around position %d\n",extra_str, (int)(long)(s-extra_str));
00193 error:
00194 LM_ERR("error\n");
00195 destroy_extras(head);
00196 return 0;
00197 }
00198
00199
00200
00201 void destroy_extras( struct acc_extra *extra)
00202 {
00203 struct acc_extra *foo;
00204
00205 while (extra) {
00206 foo = extra;
00207 extra = extra->next;
00208 pkg_free(foo);
00209 }
00210 }
00211
00212
00213 #ifdef RAD_ACC
00214
00217 int extra2attrs( struct acc_extra *extra, struct attr *attrs, int offset)
00218 {
00219 int i;
00220
00221 for(i=0 ; extra ; i++, extra=extra->next) {
00222 attrs[offset+i].n = extra->name.s;
00223 }
00224 return i;
00225 }
00226 #endif
00227
00228
00232 int extra2int( struct acc_extra *extra, int *attrs )
00233 {
00234 unsigned int ui;
00235 int i;
00236
00237 for( i=0 ; extra ; i++,extra=extra->next ) {
00238 if (str2int( &extra->name, &ui)!=0) {
00239 LM_ERR("<%s> is not a number\n", extra->name.s);
00240 return -1;
00241 }
00242 attrs[i] = (int)ui;
00243 }
00244 return i;
00245 }
00246
00247
00248
00249 int extra2strar(struct acc_extra *extra, struct sip_msg *rq, str *val_arr,
00250 int *int_arr, char *type_arr)
00251 {
00252 pv_value_t value;
00253 int n;
00254 int r;
00255
00256 n = 0;
00257 r = 0;
00258
00259 while (extra) {
00260
00261 if (pv_get_spec_value( rq, &extra->spec, &value)!=0) {
00262 LM_ERR("failed to get '%.*s'\n", extra->name.len,extra->name.s);
00263 }
00264
00265
00266 if (n==MAX_ACC_EXTRA) {
00267 LM_WARN("array to short -> ommiting extras for accounting\n");
00268 goto done;
00269 }
00270
00271 if(value.flags&PV_VAL_NULL) {
00272
00273 val_arr[n].s = 0;
00274 val_arr[n].len = 0;
00275 type_arr[n] = TYPE_NULL;
00276 } else {
00277
00278 if (value.rs.s+value.rs.len==static_detector) {
00279 val_arr[n].s = int_buf + r*INT2STR_MAX_LEN;
00280 val_arr[n].len = value.rs.len;
00281 memcpy(val_arr[n].s, value.rs.s, value.rs.len);
00282 r++;
00283 } else {
00284 val_arr[n] = value.rs;
00285 }
00286 if (value.flags&PV_VAL_INT) {
00287 int_arr[n] = value.ri;
00288 type_arr[n] = TYPE_INT;
00289 } else {
00290 type_arr[n] = TYPE_STR;
00291 }
00292 }
00293 n++;
00294
00295 extra = extra->next;
00296 }
00297
00298 done:
00299 return n;
00300 }
00301
00302
00303 int legs2strar( struct acc_extra *legs, struct sip_msg *rq, str *val_arr,
00304 int *int_arr, char *type_arr, int start)
00305 {
00306 static struct usr_avp *avp[MAX_ACC_LEG];
00307 static struct search_state st[MAX_ACC_LEG];
00308 unsigned short name_type;
00309 int_str name;
00310 int_str value;
00311 int n;
00312 int found;
00313 int r;
00314
00315 found = 0;
00316 r = 0;
00317
00318 for( n=0 ; legs ; legs=legs->next,n++ ) {
00319
00320 if (start) {
00321 if ( pv_get_avp_name( rq, &(legs->spec.pvp), &name, &name_type)<0 )
00322 goto exit;
00323 avp[n] = search_first_avp( name_type, name, &value, st + n);
00324 } else {
00325 avp[n] = search_next_avp(st + n, &value);
00326 }
00327
00328
00329 if (avp[n]) {
00330 found = 1;
00331
00332 if(avp[n]->flags & AVP_VAL_STR) {
00333 val_arr[n] = value.s;
00334 type_arr[n] = TYPE_STR;
00335 } else {
00336 val_arr[n].s = int2bstr( value.n, int_buf+r*INT2STR_MAX_LEN,
00337 &val_arr[n].len);
00338 r++;
00339 int_arr[n] = value.n;
00340 type_arr[n] = TYPE_INT;
00341 }
00342 } else {
00343 val_arr[n].s = 0;
00344 val_arr[n].len = 0;
00345 type_arr[n] = TYPE_NULL;
00346 }
00347
00348 }
00349
00350 if (found || start)
00351 return n;
00352 exit:
00353 return 0;
00354 }