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