int ds_next_dst(struct sip_msg *msg, int mode) { struct socket_info *sock; struct usr_avp *avp; struct usr_avp *tmp_avp; struct usr_avp *attr_avp; int_str avp_value; int_str sock_avp_value; if(!(ds_flags&DS_FAILOVER_ON) || dst_avp_name < 0) { LM_WARN("failover support disabled\n"); return -1; } tmp_avp = search_first_avp(dst_avp_type, dst_avp_name, NULL, 0); if(tmp_avp==NULL) return -1; /* used avp deleted -- strange */ /* get AVP with next destination URI */ avp = search_next_avp(tmp_avp, &avp_value); destroy_avp(tmp_avp); /* remove old attribute AVP (from prev destination) */ if (attrs_avp_name >= 0) { attr_avp = search_first_avp(attrs_avp_type, attrs_avp_name, NULL, 0); if (attr_avp) destroy_avp(attr_avp); } if(avp==NULL || !(avp->flags&AVP_VAL_STR)) return -1; /* no more avps or value is int */ /* get AVP with next destination socket */ tmp_avp = search_first_avp(sock_avp_type, sock_avp_name, &sock_avp_value, 0); if (tmp_avp) { /* this shuold not happen, it is a bogus state */ sock = NULL; } else { if (sscanf( sock_avp_value.s.s, "%p", (void**)&sock ) != 1) sock = NULL; } if(ds_update_dst(msg, &avp_value.s, sock, mode)!=0) { LM_ERR("cannot set dst addr\n"); return -1; } LM_DBG("using [%.*s]\n", avp_value.s.len, avp_value.s.s); return 1; }
int ops_delete_avp(struct sip_msg* msg, struct fis_param *ap) { struct usr_avp **avp_list; struct usr_avp *avp; struct usr_avp *avp_next; unsigned short name_type; int n; n = 0; if ( (ap->flags&AVPOPS_VAL_NONE)==0) { /* avp name is known ->search by name */ name_type = (((ap->flags&AVPOPS_VAL_INT))?0:AVP_NAME_STR); while ( (avp=search_first_avp( name_type, ap->val, 0))!=0 ) { destroy_avp( avp ); n++; if ( !(ap->flags&AVPOPS_FLAG_ALL) ) break; } } else { /* avp name is not given - we have just flags */ /* -> go through all list */ avp_list = get_avp_list(); avp = *avp_list; for ( ; avp ; avp=avp_next ) { avp_next = avp->next; /* check if type match */ if ( !( (ap->flags&(AVPOPS_VAL_INT|AVPOPS_VAL_STR))==0 || ((ap->flags&AVPOPS_VAL_INT)&&((avp->flags&AVP_NAME_STR))==0) || ((ap->flags&AVPOPS_VAL_STR)&&(avp->flags&AVP_NAME_STR)) ) ) continue; /* remove avp */ destroy_avp( avp ); n++; if ( !(ap->flags&AVPOPS_FLAG_ALL) ) break; } } DBG("DEBUG:avpops:remove_avps: %d avps were removed\n",n); return n?1:-1; }
void destroy_index_avp( unsigned short flags, int name, int index) { struct usr_avp *avp = NULL; avp = search_index_avp(flags, name, 0, index); if(avp== NULL) { LM_DBG("AVP with the specified index not found\n"); return; } destroy_avp( avp ); }
int ops_delete_avp(struct sip_msg* msg, struct fis_param *ap) { struct usr_avp **avp_list; struct usr_avp *avp; struct usr_avp *avp_next; unsigned short name_type; int avp_name; int n; n = 0; if ((ap->opd&AVPOPS_VAL_NONE)==0) { /* avp name is known ->search by name */ /* get avp name */ if(avpops_get_aname(msg, ap, &avp_name, &name_type)!=0) { LM_ERR("failed to get dst AVP name\n"); return -1; } n = destroy_avps( name_type, avp_name, ap->ops&AVPOPS_FLAG_ALL ); } else { /* avp name is not given - we have just flags */ /* -> go through all list */ avp_list = get_avp_list(); avp = *avp_list; for ( ; avp ; avp=avp_next ) { avp_next = avp->next; /* check if type match */ if ( !( (ap->opd&(AVPOPS_VAL_INT|AVPOPS_VAL_STR))==0 || ((ap->opd&AVPOPS_VAL_INT)&&((avp->flags&AVP_NAME_STR))==0) || ((ap->opd&AVPOPS_VAL_STR)&&(avp->flags&AVP_NAME_STR)) ) ) continue; if((ap->u.sval.pvp.pvn.u.isname.type&AVP_SCRIPT_MASK)!=0 && ((ap->u.sval.pvp.pvn.u.isname.type&AVP_SCRIPT_MASK) &avp->flags)==0) continue; /* remove avp */ destroy_avp( avp ); n++; if ( !(ap->ops&AVPOPS_FLAG_ALL) ) break; } } LM_DBG("%d avps were removed\n",n); return n?1:-1; }
int destroy_avps( unsigned short flags, int name, int all) { struct usr_avp *avp; int n; n = 0; while ( (avp=search_first_avp( flags, name, 0, 0))!=0 ) { destroy_avp( avp ); n++; if ( !all ) break; } return n; }
static int del_attr(struct sip_msg* msg, char* p1, char* p2) { fparam_t* fp; avp_t* avp; struct search_state st; fp = (fparam_t*)p1; avp = search_avp(fp->v.avp, 0, &st); while (avp) { destroy_avp(avp); avp = search_next_avp(&st, 0); } return 1; }
/* fixes an attribute containing xl formatted string to pure string runtime */ static int xlfix_attr(struct sip_msg* msg, char* p1, char* p2) { avp_t* avp; avp_ident_t* avpid; avp_value_t val; xl_elog_t* format=NULL; int ret=-1; avpid = &((fparam_t*)p1)->v.avp; /* search the AVP */ avp = search_avp(*avpid, &val, 0); if (!avp) { DBG("xlfix_attr: AVP does not exist\n"); goto error; } if ((avp->flags & AVP_VAL_STR) == 0) { DBG("xlfix_attr: Not a string AVP\n"); goto error; } /* parse the xl syntax -- AVP values are always zero-terminated */ if (xl_parse(val.s.s, &format)<0) { LOG(L_ERR, "ERROR: xlfix_attr: wrong format[%s]\n", val.s.s); goto error; } if (xl_printstr(msg, format, &val.s.s, &val.s.len) > 0) { /* we must delete and re-add the AVP again */ destroy_avp(avp); if (add_avp(avpid->flags | AVP_VAL_STR, avpid->name, val)) { ERR("xlfix_attr:Error adding new AVP\n"); goto error; } /* everything went OK */ ret = 1; } error: /* free the parsed xl expression */ if (format) xl_free(format); return ret; }
void get_watchers_from_avp(str_lst_t **watchers, unsigned int *watcher_size, unsigned int *watchers_no) { str_lst_t *new_watcher; struct usr_avp *avp; int_str val; unsigned int size; struct sip_uri parsed_uri; char *p; *watchers = NULL; *watcher_size = 0; *watchers_no = 0; for(;;) { avp = search_first_avp(watchers_avp_type, watchers_avp_name, &val, 0); if (avp == NULL) break; if(avp->flags&AVP_VAL_STR) if (parse_uri(val.s.s, val.s.len, &parsed_uri)<0) LM_WARN("discarding non URI watcher [%.*s]\n", val.s.len, val.s.s); else { LM_DBG("got watcher [%.*s]\n", val.s.len, val.s.s); size = sizeof(str_lst_t) + val.s.len; new_watcher = (str_lst_t *)pkg_malloc(size); if (new_watcher == NULL) { LM_ERR("OOM\n"); return; } memset(new_watcher, 0, size); p = (char*)(new_watcher + 1); new_watcher->watcher.len = val.s.len; new_watcher->watcher.s = p; memcpy(p, val.s.s, val.s.len); add_watcher(watchers, new_watcher); *watcher_size += size; *watchers_no += 1; } else LM_WARN("Ignoring non STR AVP\n"); destroy_avp(avp); } print_watchers(*watchers); return; }
static int subst_attr(struct sip_msg* msg, char* p1, char* p2) { avp_t* avp; avp_value_t val; str *res = NULL; int count; avp_ident_t* name = &((fparam_t*)p1)->v.avp; if ((avp = search_avp(*name, &val, NULL))) { if (avp->flags & AVP_VAL_STR) { res = subst_str(val.s.s, msg, ((fparam_t*)p2)->v.subst, &count); if (res == NULL) { ERR("avp_subst: error while running subst\n"); goto error; } DBG("avp_subst: %d, result %.*s\n", count, res->len, ZSW(res->s)); val.s = *res; if (add_avp_before(avp, name->flags | AVP_VAL_STR, name->name, val)) { ERR("avp_subst: error while adding new AVP\n"); goto error; } destroy_avp(avp); return 1; } else { ERR("avp_subst: AVP has numeric value\n"); goto error; } } else { ERR("avp_subst: AVP[%.*s] index %d, flags %x not found\n", name->name.s.len, name->name.s.s, name->index, name->flags); goto error; } error: if (res) pkg_free(res); return -1; }
static int func_time_end(struct sip_msg *msg, char *key) { char unix_time[20]; char *endptr; long int start_time; int result; struct search_state st; get_milliseconds(unix_time); LM_DBG("Statsd: statsd_stop at %s\n",unix_time); avp_t* prev_avp; int_str avp_value, avp_name; avp_name.s.s = key; avp_name.s.len = strlen(avp_name.s.s); prev_avp = search_first_avp( AVP_NAME_STR|AVP_VAL_STR, avp_name, &avp_value, &st); if(avp_value.s.len == 0){ LM_ERR("Statsd: statsd_stop not valid key(%s)\n",key); return 1; } start_time = strtol(avp_value.s.s, &endptr,10); if(strlen(endptr) >0){ LM_DBG( "Statsd:statsd_stop not valid key(%s) it's not a number value=%s\n", key, avp_value.s.s); return 0; } result = atol(unix_time) - start_time; LM_DBG( "Statsd: statsd_stop Start_time=%ld unix_time=%ld (%i)\n", start_time, atol(unix_time), result); destroy_avp(prev_avp); return statsd_timing(key, result); }
static int l_siplua_AVP_destroy(lua_State *L) { struct usr_avp *first_avp; int name; str s; int_str val; int flags = 0; luaL_checkany(L, 1); s.s = (char *) lua_tostring(L, 1); s.len = strlen(s.s); name = get_avp_id(&s); first_avp = search_first_avp(flags, name, &val, NULL); if (first_avp != NULL) { destroy_avp(first_avp); lua_pushboolean(L, 1); } else lua_pushnil(L); return 1; }
static void remove_avps(avp_t *avp) { struct search_state ss; avp_name_t name; avp_t *a; str *s; if (avp->flags & AVP_NAME_STR) { s = get_avp_name(avp); if (s) name.s = *s; else { name.s.s = NULL; name.s.len = 0; } } else name.n = avp->id; a = search_first_avp(avp->flags, name, 0, &ss); while(a) { destroy_avp(a); a = search_next_avp(&ss, 0); } }
int ops_copy_avp( struct sip_msg* msg, struct fis_param* src, struct fis_param* dst) { struct usr_avp *avp; struct usr_avp *prev_avp; int_str avp_val; int_str avp_val2; unsigned short name_type1; unsigned short name_type2; int avp_name1; int avp_name2; int n; n = 0; prev_avp = 0; /* get avp src name */ if(avpops_get_aname(msg, src, &avp_name1, &name_type1)!=0) { LM_ERR("failed to get src AVP name\n"); goto error; } /* get avp dst name */ if(avpops_get_aname(msg, dst, &avp_name2, &name_type2)!=0) { LM_ERR("failed to get dst AVP name\n"); goto error; } avp = search_first_avp( name_type1, avp_name1, &avp_val, 0); while ( avp ) { /* build a new avp with new name, but old value */ /* do we need cast conversion ?!?! */ if((avp->flags&AVP_VAL_STR) && (dst->ops&AVPOPS_FLAG_CASTN)) { if(str2int(&avp_val.s, (unsigned int*)&avp_val2.n)!=0) { LM_ERR("cannot convert str to int\n"); goto error; } if ( add_avp( name_type2, avp_name2, avp_val2)==-1 ) { LM_ERR("failed to create new avp!\n"); goto error; } } else if(!(avp->flags&AVP_VAL_STR)&&(dst->ops&AVPOPS_FLAG_CASTS)) { avp_val2.s.s = int2str(avp_val.n, &avp_val2.s.len); if ( add_avp( name_type2|AVP_VAL_STR, avp_name2, avp_val2)==-1 ) { LM_ERR("failed to create new avp.\n"); goto error; } } else { if ( add_avp( name_type2|(avp->flags&AVP_VAL_STR), avp_name2, avp_val)==-1 ) { LM_ERR("failed to create new avp\n"); goto error; } } n++; /* copy all avps? */ if ( !(dst->ops&AVPOPS_FLAG_ALL) ) { /* delete the old one? */ if (dst->ops&AVPOPS_FLAG_DELETE) destroy_avp( avp ); break; } else { prev_avp = avp; avp = search_first_avp( name_type1, avp_name1, &avp_val, prev_avp); /* delete the old one? */ if (dst->ops&AVPOPS_FLAG_DELETE) destroy_avp( prev_avp ); } } return n?1:-1; error: return -1; }
int do_lb_reset(struct sip_msg *req, struct lb_data *data) { struct usr_avp *id_avp; struct usr_avp *res_avp, *del_res_avp; int_str id_val; int_str res_val; struct dlg_cell *dlg; struct lb_dst *it_d, *last_dst; struct lb_resource *it_r; if ( (dlg=lb_dlg_binds.get_dlg())==NULL ) { LM_ERR("no dialog found for this call, LB not started\n"); return -1; } /* remove any saved AVPs */ destroy_avps(0, group_avp_name, 0); destroy_avps(0, flags_avp_name, 0); destroy_avps(0, mask_avp_name, 0); /* get previous iteration destination, if any */ last_dst = NULL; id_avp = search_first_avp(0, id_avp_name, &id_val, NULL); if( id_avp && (is_avp_str_val(id_avp) == 0) ) { for( it_d=data->dsts ; it_d ; it_d=it_d->next ) { if( it_d->id == id_val.n ) { last_dst = it_d; LM_DBG("reset LB - found previous dst %d [%.*s]\n", last_dst->id, last_dst->profile_id.len, last_dst->profile_id.s); break; } } } destroy_avps(0, id_avp_name, 0); /* any valid previous iteration ? */ if(last_dst == NULL) { /* simply delete all possible resources */ destroy_avps(0, res_avp_name, 1); } else { /* search and clean up previous iteration resources, if any */ res_avp = search_first_avp(0, res_avp_name, &res_val, NULL); while (res_avp) { if ( (it_r=get_resource_by_name( data, &res_val.s))!=NULL ) { if( lb_dlg_binds.unset_profile(dlg, &last_dst->profile_id, it_r->profile) != 1 ) LM_ERR("reset LB - failed to remove from profile [%.*s]->" "[%.*s]\n", res_val.s.len, res_val.s.s, last_dst->profile_id.len, last_dst->profile_id.s ); } else { LM_WARN("reset LB - ignore unknown previous resource " "[%.*s]\n", res_val.s.len, res_val.s.s); } del_res_avp = res_avp; res_avp = search_next_avp(del_res_avp, &res_val); destroy_avp(del_res_avp); } } return 0; }
int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, unsigned int flags, struct lb_data *data, int reuse) { /* resources for previous iteration */ static struct lb_resource **res_prev = NULL; static unsigned int res_prev_size = 0; /* resources for new iteration */ static struct lb_resource **res_new = NULL; static unsigned int res_new_size = 0; /* probed destinations bitmap */ static unsigned int *dst_bitmap = NULL; static unsigned int bitmap_size = 0; /* selected destinations buffer */ static struct lb_dst **dsts = NULL; static unsigned int dsts_size = 0; /* control vars */ struct lb_resource **res_cur; int res_prev_n, res_new_n, res_cur_n; struct lb_dst **dsts_cur; struct lb_dst *last_dst, *dst; unsigned int dsts_size_cur, dsts_size_max; unsigned int *dst_bitmap_cur; unsigned int bitmap_size_cur; struct dlg_cell *dlg; /* AVP related vars */ struct usr_avp *group_avp; struct usr_avp *flags_avp; struct usr_avp *mask_avp; struct usr_avp *id_avp; struct usr_avp *res_avp; int_str group_val; int_str flags_val; int_str mask_val; int_str id_val; int_str res_val; /* iterators, e.t.c. */ struct lb_dst *it_d; struct lb_resource *it_r; int load, it_l; int i, j, cond; /* init control vars state */ res_cur = NULL; res_cur_n = res_prev_n = res_new_n = 0; last_dst = dst = NULL; dst_bitmap_cur = NULL; /* search and fill new resources references if we should not reuse previous iteration data */ if( !reuse ) { res_new_n = rl->n; /* adjust size of statically allocated buffer */ if( res_new_n > res_new_size ) { res_new = (struct lb_resource **)pkg_realloc (res_new, (res_new_n * sizeof(struct lb_resource *))); if( res_new == NULL ) { res_new_size = 0; LM_ERR("no more pkg mem - resources ptr buffer realloc " "failure\n"); return -1; } res_new_size = res_new_n; } /* fill resource references */ for( it_r=data->resources,i=0 ; it_r ; it_r=it_r->next ) { if( search_resource_str(rl, &it_r->name) ) { res_new[i++] = it_r; LM_DBG("initial call of LB - found requested %d/%d " "resource [%.*s]\n", i, res_new_n, it_r->name.len, it_r->name.s); } } if( i != res_new_n ) { LM_ERR("initial call of LB - unknown resource found in " "input string\n"); return -1; } /* set 'res_new' as current iteration buffer */ res_cur = res_new; res_cur_n = res_new_n; } /* always search for previous iteration data, no matter if we will reuse it or not */ group_avp = search_first_avp(0, group_avp_name, &group_val, NULL); flags_avp = search_first_avp(0, flags_avp_name, &flags_val, NULL); mask_avp = search_first_avp(0, mask_avp_name, &mask_val, NULL); id_avp = search_first_avp(0, id_avp_name, &id_val, NULL); /* sanity checks for fetched AVPs */ if( group_avp && !(is_avp_str_val(group_avp) == 0) ) { destroy_avp(group_avp); group_avp = NULL; } if( flags_avp && !(is_avp_str_val(flags_avp) == 0) ) { destroy_avp(flags_avp); flags_avp = NULL; } if( mask_avp && !(is_avp_str_val(mask_avp) != 0) ) { destroy_avp(mask_avp); mask_avp = NULL; } if( id_avp && !(is_avp_str_val(id_avp) == 0) ) { destroy_avp(id_avp); id_avp = NULL; } /* get previous iteration destination, if any */ if( id_avp ) { for( it_d=data->dsts ; it_d ; it_d=it_d->next ) { if( it_d->id == id_val.n ) { last_dst = it_d; LM_DBG("%s call of LB - found previous dst %d [%.*s]\n", (reuse ? "sequential" : "initial"), last_dst->id, last_dst->profile_id.len, last_dst->profile_id.s); break; } } } /* search and fill previous iteration resources references only if... */ if( /* we should reuse previous resources list */ reuse || /* we have 'last_dst', i.e. previous iteration was successfull and * we need to clean it up */ (last_dst != NULL) ) { do { cond = 0; /* use it here as a 'start loop again' flag */ res_prev_n = 0; res_avp = search_first_avp(0, res_avp_name, &res_val, NULL); for( ; res_avp ; res_avp=search_next_avp(res_avp, &res_val) ) { /* ignore AVPs with invalid type */ if( !(is_avp_str_val(res_avp) != 0) ) continue; if ( (it_r=get_resource_by_name( data, &res_val.s))==NULL ) { LM_WARN("%s call of LB - ignore unknown previous " "resource [%.*s]\n", (reuse?"sequential":"initial"), res_val.s.len, res_val.s.s); continue; } /* fill buffer only if buffer size not exeeded */ if( res_prev_n < res_prev_size ) { res_prev[res_prev_n] = it_r; LM_DBG("%s call of LB - found previous resource [%.*s]\n", (reuse ? "sequential" : "initial"), it_r->name.len, it_r->name.s); } res_prev_n++; } /* adjust size of statically allocated buffer */ if( res_prev_n > res_prev_size ) { /* small hack: if we need to adjust 'res_prev' buffer adjust * it according to 'res_new' size to minimize * future pkg_realloc()'s */ if( !reuse && (res_prev_n < res_new_n) ) res_prev_n = res_new_n; res_prev = (struct lb_resource **)pkg_realloc (res_prev, (res_prev_n * sizeof(struct lb_resource *))); if( res_prev == NULL ) { res_prev_size = 0; LM_ERR("no more pkg mem - previous resources ptr " "buffer realloc failure\n"); return -1; } res_prev_size = res_prev_n; cond = 1; } } while( cond ); } /* reuse previous iteration resources, group and flags */ if( reuse ) { /* set 'res_prev' as current iteration buffer */ res_cur = res_prev; res_cur_n = res_prev_n; if( res_cur_n == 0 ) { LM_ERR("sequential call of LB - cannot find previous resources\n"); return -1; } if( group_avp ) group = group_val.n; else { LM_ERR("sequential call of LB - cannot find previous group\n"); return -1; } if( flags_avp ) flags = flags_val.n; else flags = LB_FLAGS_DEFAULT; LM_DBG("sequential call of LB - found previous group %d and " "flags 0x%x\n", group, flags); } /* sanity check - double check that we have a resource list to work with */ if( (res_cur == NULL) || (res_cur_n == 0) ) { LM_ERR("%s call of LB - no resources list to work with\n", (reuse ? "sequential" : "initial")); return -1; } /* [re-]initialize/reuse destinations mask */ /* sanity check - always calculate current iteration * res_cur[]->bitmap_size */ bitmap_size_cur=(unsigned int)(-1); for( i=0 ; i<res_cur_n ; i++ ) { if( bitmap_size_cur > res_cur[i]->bitmap_size ) bitmap_size_cur = res_cur[i]->bitmap_size; } /* always try to reuse 'mask' buffer from AVP, even if we need * to reinitialize it to avoid un-neded AVP ops */ if(mask_avp && (mask_val.s.len==(bitmap_size_cur*sizeof(unsigned int)))) { dst_bitmap_cur = (unsigned int *)mask_val.s.s; } /* ...or use our static buffer */ if( dst_bitmap_cur == NULL ) { /* adjust size of statically allocated buffer */ if( bitmap_size_cur > bitmap_size ) { dst_bitmap = (unsigned int *)pkg_realloc (dst_bitmap, (bitmap_size_cur * sizeof(unsigned int))); if( dst_bitmap == NULL ) { bitmap_size = 0; LM_ERR("no more pkg mem - dst bitmap buffer realloc failed\n"); return -1; } bitmap_size = bitmap_size_cur; } dst_bitmap_cur = dst_bitmap; } /* reinitalize buffer if... */ if( (dst_bitmap_cur == dst_bitmap) || /* it is our static buffer */ !reuse /* should not reuse previous iteration data */ ) { if( reuse ) { LM_WARN("sequential call of LB - cannot %s previous mask, routing " "will be re-started", (mask_avp ? "reuse" : "find")); } memset(dst_bitmap_cur, 0xff, (bitmap_size_cur * sizeof(unsigned int))); for( i=0 ; i<res_cur_n ; i++ ) { for( j=0 ; j<bitmap_size_cur ; j++ ) dst_bitmap_cur[j] &= res_cur[i]->dst_bitmap[j]; } } /* init selected destinations buff */ dsts_cur = NULL; dsts_size_max = (flags & LB_FLAGS_RANDOM) ? data->dst_no : 1; if( dsts_size_max > 1 ) { if( dsts_size_max > dsts_size ) { dsts = (struct lb_dst **)pkg_realloc (dsts, (dsts_size_max * sizeof(struct lb_dst *))); if( dsts == NULL ) { dsts_size_max = dsts_size = 0; LM_WARN("no more pkg mem - dsts buffer realloc failed\n"); } else dsts_size = dsts_size_max; } dsts_cur = dsts; } if( dsts_cur == NULL ) { /* fallback to no-buffer / 'select first' scenario */ dsts_cur = &dst; dsts_size_max = 1; } /* be sure the dialog is created */ if ( (dlg=lb_dlg_binds.get_dlg())==NULL ) { if( lb_dlg_binds.create_dlg(req, 0) != 1 ) { LM_ERR("%s call of LB - failed to create dialog\n", (reuse ? "sequential" : "initial")); return -1; } /* get the dialog reference */ dlg = lb_dlg_binds.get_dlg(); } /* we're initialized from here and no errors could abort us */ /* remove the dialog from previous profiles, if any */ if ( (last_dst != NULL) && (res_prev_n > 0) ) { for( i=0 ; i<res_prev_n ; i++ ) { if( lb_dlg_binds.unset_profile(dlg, &last_dst->profile_id, res_prev[i]->profile) != 1 ) LM_ERR("%s call of LB - failed to remove from profile [%.*s]" "->[%.*s]\n", (reuse ? "sequential" : "initial"), res_prev[i]->profile->name.len, res_prev[i]->profile->name.s, last_dst->profile_id.len, last_dst->profile_id.s ); } } /* lock resources */ for( i=0 ; i<res_cur_n ; i++ ) lock_get(res_cur[i]->lock); /* do the load-balancing */ /* select destinations */ cond = 0; /* use it here as a 'first iteration' flag */ load = it_l = 0; dsts_size_cur = 0; for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) { if( it_d->group == group ) { if( (dst_bitmap_cur[i] & (1 << j)) && ((it_d->flags & LB_DST_STAT_DSBL_FLAG) == 0) ) { /* valid destination (group & resources & status) */ if( get_dst_load(res_cur, res_cur_n, it_d, flags, &it_l) ) { /* only valid load here */ if( (it_l > 0) || (flags & LB_FLAGS_NEGATIVE) ) { /* only allowed load here */ if( !cond/*first pass*/ || (it_l > load)/*new max*/ ) { cond = 1; /* restart buffer */ dsts_size_cur = 0; } else if( it_l < load ) { /* lower availability -> new iteration */ continue; } /* add destination to to selected destinations buffer, * if we have a room for it */ if( dsts_size_cur < dsts_size_max ) { load = it_l; dsts_cur[dsts_size_cur++] = it_d; LM_DBG("%s call of LB - destination %d <%.*s> " "selected for LB set with free=%d\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s, it_l ); } } } else { LM_WARN("%s call of LB - skipping destination %d <%.*s> - " "unable to calculate free resources\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s ); } } else { LM_DBG("%s call of LB - skipping destination %d <%.*s> " "(filtered=%d , disabled=%d)\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s, ((dst_bitmap_cur[i] & (1 << j)) ? 0 : 1), ((it_d->flags & LB_DST_STAT_DSBL_FLAG) ? 1 : 0) ); } } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } /* choose one destination among selected */ if( dsts_size_cur > 0 ) { if( (dsts_size_cur > 1) && (flags & LB_FLAGS_RANDOM) ) { dst = dsts_cur[rand() % dsts_size_cur]; } else { dst = dsts_cur[0]; } } if( dst != NULL ) { LM_DBG("%s call of LB - winning destination %d <%.*s> selected " "for LB set with free=%d\n", (reuse ? "sequential" : "initial"), dst->id, dst->uri.len, dst->uri.s, load ); /* add to the profiles */ for( i=0 ; i<res_cur_n ; i++ ) { if( lb_dlg_binds.set_profile(dlg, &dst->profile_id, res_cur[i]->profile, 0) != 0 ) LM_ERR("%s call of LB - failed to add to profile [%.*s]->" "[%.*s]\n", (reuse ? "sequential" : "initial"), res_cur[i]->profile->name.len, res_cur[i]->profile->name.s, dst->profile_id.len, dst->profile_id.s); } /* set dst as used (not selected) */ for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) { if( it_d == dst ) { dst_bitmap_cur[i] &= ~(1 << j); break; } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } } else { LM_DBG("%s call of LB - no destination found\n", (reuse ? "sequential" : "initial")); } /* unlock resources */ for( i=0 ; i<res_cur_n ; i++ ) lock_release(res_cur[i]->lock); /* we're done with load-balancing, now save state */ /* save state - group */ if( group_avp == NULL ) { group_val.n = group; if( add_avp(0, group_avp_name, group_val) != 0 ) { LM_ERR("failed to add GROUP AVP\n"); } } else if( group_val.n != group ) { group_avp->data = (void *)(long)group; } /* save state - flags, save only if they are set */ if( flags_avp == NULL ) { if( flags != LB_FLAGS_DEFAULT ) { flags_val.n = flags; if( add_avp(0, flags_avp_name, flags_val) != 0 ) { LM_ERR("failed to add FLAGS AVP\n"); } } } else if( flags_val.n != flags ) { flags_avp->data = (void *)(long)flags; } /* save state - dst_bitmap mask */ if( (mask_avp!=NULL) && (dst_bitmap_cur!=(unsigned int *)mask_val.s.s) ) { destroy_avp(mask_avp); mask_avp = NULL; } if( mask_avp == NULL ) { mask_val.s.s = (char *)dst_bitmap_cur; mask_val.s.len = bitmap_size_cur * sizeof(unsigned int); if( add_avp(AVP_VAL_STR, mask_avp_name, mask_val) != 0 ) { LM_ERR("failed to add MASK AVP\n"); } } /* save state - dst, save only if we have one */ if( id_avp == NULL ) { if( dst != NULL ) { id_val.n = dst->id; if( add_avp(0, id_avp_name, id_val) != 0 ) { LM_ERR("failed to add ID AVP\n"); } } } else { if( dst != NULL ) { id_avp->data = (void *)(long)dst->id; } else { destroy_avp(id_avp); id_avp = NULL; } } /* save state - res */ /* iterate AVPs once and delete old resources */ destroy_avps(0, res_avp_name, 1 /*all*/); /* add new resources */ for( i=0 ; i<res_cur_n ; i++ ) { res_val.s = res_cur[i]->name; if( add_avp(AVP_VAL_STR, res_avp_name, res_val) != 0 ) LM_ERR("failed to add RES AVP\n"); } /* outcome: set dst uri */ if( (dst != NULL) && (set_dst_uri(req, &dst->uri) != 0) ) { LM_ERR("failed to set duri\n"); return -2; } return dst ? 0 : -2; }
/*! \brief * Adds to request a destination set that includes all highest priority * class contacts in "serial_avp" AVP. If called from a route block, * rewrites the request uri with first contact and adds the remaining * contacts as branches. If called from failure route block, adds all * contacts as brances. Removes added contacts from "serial_avp" AVP. */ int next_branches( struct sip_msg *msg) { struct usr_avp *avp, *prev; int_str val; struct socket_info *sock_info; qvalue_t q; str uri, dst_uri, path; char *p; unsigned int flags; int rval; if (route_type != REQUEST_ROUTE && route_type != FAILURE_ROUTE ) { /* unsupported route type */ LM_ERR("called from unsupported route type %d\n", route_type); goto error; } /* Find first avp */ avp = search_first_avp(0, serial_avp, &val, 0); if (!avp) { LM_DBG("no AVPs -- we are done!\n"); goto error; } if (!val.s.s) { LM_ERR("invalid avp value\n"); goto error; } /* *sock_info, flags, q, uri, 0, dst_uri, 0, path, 0,... */ p = val.s.s; sock_info = (struct socket_info*) *((long*) p); p += sizeof(long); flags = (unsigned int) *((long*) p); p += sizeof(long); q = (unsigned int) *((long*) p); p += sizeof(long); uri.s = p; uri.len = strlen(p); p += uri.len + 1; dst_uri.s = p; dst_uri.len = strlen(p); p += dst_uri.len + 1; path.s = p; path.len = strlen(p); /* Set Request-URI */ if ( set_ruri(msg, &uri) == -1 || set_dst_uri(msg, &dst_uri) == -1 || set_path_vector(msg, &path) == -1 ) goto error1; msg->force_send_socket = sock_info; set_ruri_q( q ); setb0flags( flags ); LM_DBG("Msg information <%.*s,%.*s,%.*s,%d,%u> (avp flag=%u)\n", uri.len, uri.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags, avp->flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); goto done; } prev = avp; avp = search_next_avp(prev, &val); destroy_avp(prev); /* Append branches until out of branches or Q_FLAG is set */ while (avp != NULL) { if (!val.s.s) { LM_ERR("invalid avp value\n"); continue; } p = val.s.s; sock_info = (struct socket_info*) *((long*) p); p += sizeof(long); flags = (unsigned int) *((long*) p); p += sizeof(long); q = (unsigned int) *((long*) p); p += sizeof(long); uri.s = p; uri.len = strlen(p); p += strlen(p) + 1; dst_uri.s = p; dst_uri.len = strlen(p); p += strlen(p) + 1; path.s = p; path.len = strlen(p); LM_DBG("Branch information <%.*s,%.*s,%.*s,%d,%u> (avp flag=%u)\n", uri.len, uri.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags, avp->flags); rval = append_branch(msg, &uri, &dst_uri, &path, q, flags, sock_info); if (rval == -1) { LM_ERR("append_branch failed\n"); goto error1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); goto done; } prev = avp; avp = search_next_avp(prev, &val); destroy_avp(prev); } return 2; done: return (search_next_avp(avp, NULL)==NULL)?2:1; error1: destroy_avp(avp); error: return -1; }
/* * Adds to request a new destination set that includes all highest * priority class contacts in contacts_avp. Request URI is rewritten with * first contact and the remaining contacts (if any) are added as branches. * Removes used contacts from contacts_avp. Returns 1, if contacts_avp * was not empty and a destination set was successfully added. Returns -2, * if contacts_avp was empty and thus there was nothing to do. * Returns -1 in case of an error. */ int t_next_contacts(struct sip_msg* msg, char* key, char* value) { struct usr_avp *avp, *prev; int_str val; str uri, dst, path; struct socket_info *sock; unsigned int flags; struct search_state st; /* Check if contacts_avp has been defined */ if (contacts_avp.n == 0) { LM_ERR("feature has been disabled - " "to enable define contacts_avp module parameter"); return -1; } /* Load Request-URI and branches */ /* Find first contacts_avp value */ avp = search_first_avp(contacts_avp_type, contacts_avp, &val, &st); if (!avp) { LM_DBG("no AVPs - we are done!\n"); return -2; } LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } /* Rewrite Request-URI */ rewrite_uri(msg, &uri); if (dst.s && dst.len) set_dst_uri(msg, &dst); else reset_dst_uri(msg); if (path.s && path.len) set_path_vector(msg, &path); else reset_path_vector(msg); set_force_socket(msg, sock); setbflagsval(0, flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } /* Append branches until out of branches or Q_FLAG is set */ prev = avp; while ((avp = search_next_avp(&st, &val))) { destroy_avp(prev); LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) { LM_ERR("appending branch failed\n"); destroy_avp(avp); return -1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } prev = avp; } destroy_avp(prev); return 1; }
int ops_subst(struct sip_msg* msg, struct fis_param** src, struct subst_expr* se) { struct usr_avp *avp; struct usr_avp *prev_avp; int_str avp_val; unsigned short name_type1; unsigned short name_type2; int avp_name1; int avp_name2; int n; int nmatches; str* result; n = 0; prev_avp = 0; /* avp name is known ->search by name */ /* get src avp name */ if(avpops_get_aname(msg, src[0], &avp_name1, &name_type1)!=0) { LM_ERR("failed to get src AVP name\n"); return -1; } avp = search_first_avp(name_type1, avp_name1, &avp_val, 0); if(avp==NULL) return -1; if(src[1]!=0) { /* get dst avp name */ if(avpops_get_aname(msg, src[1], &avp_name2, &name_type2)!=0) { LM_ERR("failed to get dst AVP name\n"); return -1; } } else { name_type2 = name_type1; avp_name2 = avp_name1; } /* TODO: delete? if(name_type2&AVP_NAME_STR) { if(avp_name2.s.len>=STR_BUF_SIZE) { LM_ERR("dst name too long\n"); goto error; } strncpy(str_buf, avp_name2.s.s, avp_name2.s.len); str_buf[avp_name2.s.len] = '\0'; avp_name2.s.s = str_buf; } */ while(avp) { if(!is_avp_str_val(avp)) { prev_avp = avp; avp = search_first_avp(name_type1, avp_name1, &avp_val, prev_avp); continue; } result=subst_str(avp_val.s.s, msg, se, &nmatches); if(result!=NULL) { /* build a new avp with new name */ avp_val.s = *result; if(add_avp(name_type2|AVP_VAL_STR, avp_name2, avp_val)==-1 ) { LM_ERR("failed to create new avp\n"); if(result->s!=0) pkg_free(result->s); pkg_free(result); goto error; } if(result->s!=0) pkg_free(result->s); pkg_free(result); n++; /* copy all avps? */ if (!(src[0]->ops&AVPOPS_FLAG_ALL) ) { /* delete the old one? */ if (src[0]->ops&AVPOPS_FLAG_DELETE || src[1]==0) destroy_avp(avp); break; } else { prev_avp = avp; avp = search_first_avp(name_type1,avp_name1,&avp_val,prev_avp); /* delete the old one? */ if (src[0]->ops&AVPOPS_FLAG_DELETE || src[1]==0) destroy_avp( prev_avp ); } } else { prev_avp = avp; avp = search_first_avp(name_type1, avp_name1, &avp_val, prev_avp); } } LM_DBG("subst to %d avps\n", n); return n?1:-1; error: return -1; }
int ops_op_avp( struct sip_msg* msg, struct fis_param** av, struct fis_param* val) { unsigned short name_type1; unsigned short name_type2; unsigned short name_type3; struct fis_param* src; struct usr_avp *avp1; struct usr_avp *avp2; struct usr_avp *prev_avp; int avp_name1; int avp_name2; int avp_name3; int_str avp_val; int_str op_val; int result; pv_value_t xvalue; src = av[0]; /* look if the required avp(s) is/are present */ /* search for the avp */ if(avpops_get_aname(msg, src, &avp_name1, &name_type1)!=0) { LM_ERR("failed to get src AVP name\n"); goto error; } avp1 = search_first_avp(name_type1, avp_name1, &avp_val, 0); if (avp1==0) { LM_DBG(" no src avp found\n"); goto error; } while(avp1!=0) { if(!(avp1->flags&AVP_VAL_STR)) break; avp1 = search_first_avp(name_type1, avp_name1, &avp_val, avp1); } if (avp1==0 && !(val->ops&AVPOPS_OP_BNOT)) { LM_DBG("no proper avp found\n"); goto error; } name_type3 = name_type1; avp_name3 = avp_name1; if(av[1]!=0) { if(avpops_get_aname(msg, av[1], &avp_name3, &name_type3)!=0) { LM_ERR("failed to get dst AVP name\n"); goto error; } } /* TODO: delete? if(name_type3&AVP_NAME_STR) { if(avp_name3.s.len>=STR_BUF_SIZE) { LM_ERR("failed to get dst name too long\n"); goto error; } strncpy(str_buf, avp_name3.s.s, avp_name3.s.len); str_buf[avp_name3.s.len] = '\0'; avp_name3.s.s = str_buf; } */ prev_avp = 0; result = 0; cycle1: if (val->opd&AVPOPS_VAL_PVAR) { /* the 2nd operator is variable -> get value */ if(val->u.sval.type==PVT_AVP) { /* search for the avp */ if(avpops_get_aname(msg, val, &avp_name2, &name_type2)!=0) { LM_ERR("failed to get dst AVP name\n"); goto error; } avp2 = search_first_avp( name_type2, avp_name2, &op_val, 0); while(avp2!=0) { if(!(avp2->flags&AVP_VAL_STR)) break; avp2 = search_first_avp( name_type2, avp_name2, &op_val, avp2); } if (avp2==0) { LM_DBG("no dst avp found\n"); goto error; } } else { avp2 = 0; if(pv_get_spec_value(msg, &(val->u.sval), &xvalue)!=0) { LM_ERR("cannot get dst value\n"); goto error; } if(xvalue.flags&PV_TYPE_INT) { op_val.n = xvalue.ri; } else { LM_ERR("dst value is str\n"); goto error; } } } else { if(val->type == AVPOPS_VAL_INT) op_val.n = val->u.n; else op_val.s = val->u.s; avp2 = 0; } cycle2: /* do operation */ LM_DBG(" use <%d> and <%d>\n", avp_val.n, op_val.n); if (val->ops&AVPOPS_OP_ADD) { result = avp_val.n+op_val.n; } else if (val->ops&AVPOPS_OP_SUB) { result = avp_val.n-op_val.n; } else if (val->ops&AVPOPS_OP_MUL) { result = avp_val.n*op_val.n; } else if (val->ops&AVPOPS_OP_DIV) { if(op_val.n!=0) result = (int)(avp_val.n/op_val.n); else { LM_ERR("division by 0\n"); result = 0; } } else if (val->ops&AVPOPS_OP_MOD) { if(op_val.n!=0) result = avp_val.n%op_val.n; else { LM_ERR("modulo by 0\n"); result = 0; } } else if (val->ops&AVPOPS_OP_BAND) { result = avp_val.n&op_val.n; } else if (val->ops&AVPOPS_OP_BOR) { result = avp_val.n|op_val.n; } else if (val->ops&AVPOPS_OP_BXOR) { result = avp_val.n^op_val.n; } else if (val->ops&AVPOPS_OP_BNOT) { result = ~op_val.n; } else { LM_CRIT("unknown operation (flg=%d)\n",val->ops); goto error; } /* add the new avp */ avp_val.n = result; if(add_avp(name_type3, avp_name3, avp_val)==-1 ) { LM_ERR("failed to create new avp\n"); goto error; } /* cycle for the second value (only if avp can have multiple vals) */ while((avp2!=NULL) &&(avp2=search_first_avp( name_type2, avp_name2, &op_val, avp2))!=0) { if(!(avp2->flags&AVP_VAL_STR)) goto cycle2; } prev_avp = avp1; /* cycle for the first value -> next avp */ while((avp1!=NULL) &&(avp1=search_first_avp(name_type1, avp_name1, &avp_val, avp1))!=0) { if (!(avp1->flags&AVP_VAL_STR)) { if(val->ops&AVPOPS_FLAG_DELETE && prev_avp!=0) { destroy_avp(prev_avp); prev_avp = 0; } goto cycle1; } } LM_DBG("done\n"); if(val->ops&AVPOPS_FLAG_DELETE && prev_avp!=0) { destroy_avp(prev_avp); prev_avp = 0; } return 1; error: return -1; }