Пример #1
0
static inline int insert_siptrace_avp(struct usr_avp *avp,
		int_str *first_val,db_key_t *keys,db_val_t *vals)
{
	int_str        avp_value;

	if (avp == 0)
		return 0;

	if (!is_avp_str_val(avp)) {
		avp_value.s.s=int2str(first_val->n,&avp_value.s.len);
		LM_DBG("int val [%.*s]\n",avp_value.s.len,avp_value.s.s);
	} else {
		avp_value = *first_val;
		LM_DBG("str val [%.*s]\n",avp_value.s.len,avp_value.s.s);
	}
	db_vals[13].val.str_val.s = avp_value.s.s;
	db_vals[13].val.str_val.len = avp_value.s.len;

	LM_DBG("storing info 14...\n");
	CON_PS_REFERENCE(db_con) = &siptrace_ps;
	if (con_set_inslist(&db_funcs,db_con,&ins_list,keys,NR_KEYS) < 0 )
		CON_RESET_INSLIST(db_con);
	if(db_funcs.insert(db_con, keys, vals, NR_KEYS) < 0) {
		LM_ERR("error storing trace\n");
		return -1;
	}

	avp = search_next_avp( avp, &avp_value);
	while(avp!=NULL)
	{
		if (!is_avp_str_val(avp))
			avp_value.s.s=int2str(avp_value.n,&avp_value.s.len);
		db_vals[13].val.str_val.s = avp_value.s.s;
		db_vals[13].val.str_val.len = avp_value.s.len;

		LM_DBG("### - storing info 14 \n");
		CON_PS_REFERENCE(db_con) = &siptrace_ps;
		if (con_set_inslist(&db_funcs,db_con,&ins_list,keys,NR_KEYS) < 0 )
			CON_RESET_INSLIST(db_con);
		if(db_funcs.insert(db_con, keys, vals, NR_KEYS) < 0)
		{
			LM_ERR("error storing trace\n");
			return -1;
		}
		avp = search_next_avp( avp, &avp_value);
	}

	return 0;
}
Пример #2
0
int do_lb_is_started(struct sip_msg *req)
{
	struct usr_avp *group_avp;
	struct usr_avp *mask_avp;
	struct usr_avp *res_avp;

	return (
		((group_avp=search_first_avp(0, group_avp_name, NULL, NULL))!=NULL) &&
			(is_avp_str_val(group_avp) == 0) &&
		((mask_avp =search_first_avp(0, mask_avp_name,  NULL, NULL))!=NULL) &&
			(is_avp_str_val(mask_avp)  != 0) &&
		((res_avp  =search_first_avp(0, res_avp_name,   NULL, NULL))!=NULL) &&
			(is_avp_str_val(res_avp)   != 0)
	) ? 1 : -1;
}
Пример #3
0
int do_lb_disable_dst(struct sip_msg *req, struct lb_data *data, unsigned int verbose)
{
	struct usr_avp *id_avp;
	int_str id_val;

	struct lb_dst *dst;
	int old_flags;

	id_avp = search_first_avp( 0, id_avp_name, &id_val, NULL);
	if( id_avp && (is_avp_str_val(id_avp) == 0) ) {
		for( dst=data->dsts ; dst ; dst=dst->next ) {
			if( dst->id == id_val.n ) {
				old_flags = dst->flags;
				dst->flags |= LB_DST_STAT_DSBL_FLAG;

				if( dst->flags != old_flags ) {
					lb_raise_event(dst);
					if( verbose )
						LM_INFO("manually disable destination %d <%.*s> "
							"from script\n",dst->id, dst->uri.len, dst->uri.s);
				}
				return 0;
			}
		}
	} else
		LM_DBG("no AVP ID -> nothing to disable\n");

	return -1;
}
Пример #4
0
/*! \brief the is_registered() function
 * Return true if the AOR in the Request-URI is registered,
 * it is similar to lookup but registered neither rewrites
 * the Request-URI nor appends branches
 */
int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
{
	str uri, aor;
	urecord_t* r;
	ucontact_t* ptr;
	int res;
	int_str match_callid=(int_str)0;

	if(_uri!=NULL)
	{
		uri = *_uri;
	} else {
		if (_m->new_uri.s) uri = _m->new_uri;
		else uri = _m->first_line.u.request.uri;
	}
	
	if (extract_aor(&uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -1;
	}
	
	ul.lock_udomain(_d, &aor);
	res = ul.get_urecord(_d, &aor, &r);

	if (res < 0) {
		ul.unlock_udomain(_d, &aor);
		LM_ERR("failed to query usrloc\n");
		return -1;
	}

	if (res == 0) {
		
		if (reg_callid_avp_name.n) {
			struct usr_avp *avp =
				search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0);
			if (!(avp && is_avp_str_val(avp)))
				match_callid.n = 0;
				match_callid.s.s = NULL;
		} else {
			match_callid.n = 0;
			match_callid.s.s = NULL;
		}

		for (ptr = r->contacts; ptr; ptr = ptr->next) {
			if(!VALID_CONTACT(ptr, act_time)) continue;
			if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */
				memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len))
				continue;
			ul.release_urecord(r);
			ul.unlock_udomain(_d, &aor);
			LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
			return 1;
		}
	}

	ul.unlock_udomain(_d, &aor);
	LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
	return -1;
}
Пример #5
0
int nio_msg_received(void *data)
{
    sip_msg_t msg;
    str *obuf;
    char *nbuf = NULL;
    int_str avp_value;
    struct usr_avp *avp;
    struct run_act_ctx ra_ctx;

    obuf = (str*)data;

    if (obuf->len < nio_min_msg_len) {
        return -1;
    }

    memset(&msg, 0, sizeof(sip_msg_t));
    msg.buf = obuf->s;
    msg.len = obuf->len;

    nio_is_incoming = 1;
    init_run_actions_ctx(&ra_ctx);
    run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg);

    if(nio_msg_avp_name.n!=0) {
        avp = NULL;
        avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name,
            &avp_value, 0);
        if(avp!=NULL && is_avp_str_val(avp)) {
            msg.buf = avp_value.s.s;
            msg.len = avp_value.s.len;
            nbuf = nio_msg_update(&msg, (unsigned int*)&obuf->len);
            if(obuf->len>=BUF_SIZE) {
                LM_ERR("new buffer overflow (%d)\n", obuf->len);
                pkg_free(nbuf);
                return -1;
            }
            memcpy(obuf->s, nbuf, obuf->len);
            obuf->s[obuf->len] = '\0';
        } else {
            LM_WARN("no value set for AVP %.*s, using unmodified message\n",
                nio_msg_avp_param.len, nio_msg_avp_param.s);
        }
    }

    if(nbuf!=NULL)
        pkg_free(nbuf);
    free_sip_msg(&msg);
    return 0;
}
Пример #6
0
static inline str* siptrace_get_table(void)
{
	static int_str         avp_value;
	struct usr_avp *avp;

	if(trace_table_avp < 0)
		return &siptrace_table;

	avp=search_first_avp(trace_table_avp_type, trace_table_avp,
			&avp_value, 0);

	if(avp==NULL || !is_avp_str_val(avp) || avp_value.s.len<=0)
		return &siptrace_table;

	return &avp_value.s;
}
Пример #7
0
int nio_msg_sent(void *data)
{
    sip_msg_t msg;
    str *obuf;
    int_str avp_value;
    struct usr_avp *avp;
    struct run_act_ctx ra_ctx;

    obuf = (str*)data;

    if (obuf->len < nio_min_msg_len) {
        return -1;
    }

    memset(&msg, 0, sizeof(sip_msg_t));
    msg.buf = obuf->s;
    msg.len = obuf->len;

    nio_is_incoming = 0;
    init_run_actions_ctx(&ra_ctx);
    run_actions(&ra_ctx, event_rt.rlist[nio_route_no], &msg);

    if(nio_msg_avp_name.n!=0) {
        avp = NULL;
        avp=search_first_avp(nio_msg_avp_type, nio_msg_avp_name,
                &avp_value, 0);
        if(avp!=NULL && is_avp_str_val(avp)) {
            msg.buf = avp_value.s.s;
            msg.len = avp_value.s.len;
            obuf->s = nio_msg_update(&msg, (unsigned int*)&obuf->len);
        } else {
            LM_WARN("no value set for AVP %.*s, using unmodified message\n",
                nio_msg_avp_param.len, nio_msg_avp_param.s);
        }
    }

    free_sip_msg(&msg);
    return 0;
}
Пример #8
0
static int l_siplua_AVP_get(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)
    {
      if (is_avp_str_val(first_avp))
	  lua_pushlstring(L, val.s.s, val.s.len);
      else
	lua_pushinteger(L, val.n);
    }
  else
    lua_pushnil(L);
  return 1;
}
Пример #9
0
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;
}
Пример #10
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;
}
Пример #11
0
static int trace_dialog(struct sip_msg *msg)
{
	unsigned char n;
	struct dlg_cell* dlg;
	struct usr_avp *avp;
	static int_str avp_value;
	str *name;

	if (!msg) {
		LM_ERR("no msg specified\n");
		return -1;
	}

	if (trace_is_off()) {
		LM_DBG("Trace if off...\n");
		return -1;
	}

	/* any need to do tracing here ? check the triggers */
	avp = traced_user_avp<0 ? NULL : search_first_avp(traced_user_avp_type,
			traced_user_avp, &avp_value, 0);
	if (avp==NULL && (msg->flags&trace_flag)==0) {
		LM_DBG("Nothing to trace here\n");
		return -1;
	}

	if (dlgb.create_dlg(msg,0)<1) {
		LM_ERR("failed to create dialog\n");
		return -1;
	}

	dlg = dlgb.get_dlg();
	if (dlg==NULL) {
		LM_CRIT("BUG: no dialog found after create dialog\n");
		return -1;
	}

	if(dlgb.register_dlgcb(dlg, DLGCB_REQ_WITHIN|DLGCB_TERMINATED,
	trace_transaction,0,0)!=0) {
		LM_ERR("failed to register dialog callback\n");
		return -1;
	}

	/* store in dialog the user avps for tracing ; we will restore
	 them for each transactin from the dialog */
	if(traced_user_avp>=0) {
		n = 0;
		while(avp!=NULL) {
			/* generate a name */
			name = generate_val_name(n);
			if (!is_avp_str_val(avp))
				avp_value.s.s=int2str(avp_value.n,
						&avp_value.s.len);
			/* add the avp value as dialog var */
			dlgb.store_dlg_value( dlg, name, &avp_value.s);
			/* next avp */
			avp = search_next_avp( avp, &avp_value);
			n++;
		}
	}

	/* set the flag to trace the rest of the transaction */
	if (msg->flags&trace_flag) {
		avp_value.s.s = "1";
		avp_value.s.len = 1;
		dlgb.store_dlg_value( dlg, &st_flag_val, &avp_value.s);
	}

	/* trace current request */
	sip_trace(msg);

	/* we also want to catch the incoming cancel */
	if ( tmb.register_tmcb( msg, NULL,TMCB_TRANS_CANCELLED,
				siptrace_dlg_cancel, NULL, NULL)<0 ) {
		LM_ERR("failed to register trans cancelled TMCB\n");
	}

	return 1;
}
Пример #12
0
/*! \brief
 * Extract Address of Record
 */
int extract_aor(str* _uri, str* _a) {
    static char aor_buf[MAX_AOR_LEN];
    str tmp;
    struct sip_uri puri;
    int user_len;
    int_str avp_val;
    struct usr_avp *avp;
    str *uri;
    str realm_prefix;

    memset(aor_buf, 0, MAX_AOR_LEN);
    if (aor_avp_name.n != 0) {
        avp = search_first_avp(aor_avp_type, aor_avp_name, &avp_val, 0);
        if (avp && is_avp_str_val(avp)) {
            uri = &avp_val.s;
        } else {
            uri = _uri;
        }
    } else {
        uri = _uri;
    }

    if (parse_uri(uri->s, uri->len, &puri) < 0) {
        rerrno = R_AOR_PARSE;
        LM_ERR("failed to parse Address of Record\n");
        return -1;
    }

    if ((puri.user.len + puri.host.len + 1 + 4) > MAX_AOR_LEN
            || puri.user.len > USERNAME_MAX_SIZE
            || puri.host.len > DOMAIN_MAX_SIZE) {
        rerrno = R_AOR_LEN;
        LM_ERR("Address Of Record too long\n");
        return -2;
    }

    _a->s = aor_buf;
    _a->len = puri.user.len + 4;
    strncpy(_a->s, "sip:", 4);

    str tmps;
    tmps.s = _a->s + 4;
    tmps.len = puri.user.len;

    if (un_escape(&puri.user, &tmps) < 0) {
        rerrno = R_UNESCAPE;
        LM_ERR("failed to unescape username\n");
        return -3;
    }

    user_len = tmps.len + 4;//_a->len;

    if (user_len>4)
        aor_buf[_a->len++] = '@';
    /* strip prefix (if defined) */
    realm_prefix.s = cfg_get(registrar, registrar_cfg, realm_pref);
    realm_prefix.len = strlen(realm_prefix.s);
    if (realm_prefix.len && realm_prefix.len < puri.host.len
            && (memcmp(realm_prefix.s, puri.host.s, realm_prefix.len) == 0)) {
        memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len,
               puri.host.len - realm_prefix.len);
        _a->len += puri.host.len - realm_prefix.len;
    } else {
        memcpy(aor_buf + _a->len, puri.host.s, puri.host.len);
        _a->len += puri.host.len;
    }

    if (cfg_get(registrar, registrar_cfg, case_sensitive) && user_len) {
        tmp.s = _a->s + user_len + 1;
        tmp.len = _a->s + _a->len - tmp.s;
        strlower(&tmp);
    } else {
        strlower(_a);
    }

    return 0;
}
Пример #13
0
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;
}