示例#1
0
int ops_is_avp_set(struct sip_msg* msg, struct fis_param *ap)
{
	struct usr_avp *avp;
	unsigned short    name_type;
	int avp_name;
	int_str avp_value;
	int index;
	int findex;

	/* get avp name */
	if(avpops_get_aname(msg, ap, &avp_name, &name_type)!=0)
	{
		LM_ERR("failed to get AVP name\n");
		return -1;
	}

	/* get avp index */
	if(pv_get_spec_index(msg, &ap->u.sval.pvp, &index, &findex)!=0)
	{
		LM_ERR("failed to get AVP index\n");
		return -1;
	}

	avp=search_first_avp(name_type, avp_name, &avp_value, 0);
	if(avp==0)
		return -1;

	do {
		/* last index [-1] or all [*] go here as well */
		if(index<=0)
		{
			if(ap->ops&AVPOPS_FLAG_ALL)
				return 1;
			if((ap->ops&AVPOPS_FLAG_CASTS && !(avp->flags&AVP_VAL_STR))
					||(ap->ops&AVPOPS_FLAG_CASTN && avp->flags&AVP_VAL_STR))
				return -1;
			if(ap->ops&AVPOPS_FLAG_EMPTY)
			{
				if(avp->flags&AVP_VAL_STR)
				{
					if(avp_value.s.s==0 || avp_value.s.len==0)
						return 1;
					else
						return -1;
				} else {
					if(avp_value.n==0)
						return 1;
					else
						return -1;
				}
			}
			return 1;
		}
		index--;
	} while ((avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0);

	return -1;
}
示例#2
0
int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	pv_xavp_name_t *xname=NULL;
	sr_xavp_t *avp=NULL;
	int idxf = 0;
	int idx = 0;
	int count;
	char *p, *p_ini;
	int p_size;

	if(param==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}
	xname = (pv_xavp_name_t*)param->pvn.u.dname;

	if(xname->index.type==PVT_EXTRA)
	{
		/* get the index */
		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
	}
	/* fix the index */
	if(idx<0)
	{
		count = xavp_count(&xname->name, NULL);
		idx = count + idx;
	}
	avp = xavp_get_by_index(&xname->name, idx, NULL);
	if(avp==NULL)
		return pv_get_null(msg, param, res);
	if(xname->next==NULL)
		return pv_xavp_get_value(msg, param, res, avp);
	if(avp->val.type != SR_XTYPE_XAVP)
		return pv_get_null(msg, param, res);

	idx = 0;
	idxf = 0;
	if(xname->next->index.type==PVT_EXTRA)
	{
		/* get the index */
		if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
	}
	/* fix the index */
	if(idx<0)
	{
		count = xavp_count(&xname->next->name, &avp->val.v.xavp);
		idx = count + idx;
	}
	avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp);
	if(avp==NULL)
		return pv_get_null(msg, param, res);
	/* get all values of second key */
	if(idxf==PV_IDX_ALL)
	{
		p_ini = pv_get_buffer();
		p = p_ini;
		p_size = pv_get_buffer_size();
		do {
			if(p!=p_ini)
			{
				if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size)
				{
					LM_ERR("local buffer length exceeded\n");
					return pv_get_null(msg, param, res);
				}
				memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
				p += PV_FIELD_DELIM_LEN;
			}
			if(pv_xavp_get_value(msg, param, res, avp)<0)
			{
				LM_ERR("can get value\n");
				return pv_get_null(msg, param, res);
			}
			if(p-p_ini+res->rs.len+1>p_size)
			{
				LM_ERR("local buffer length exceeded!\n");
				return pv_get_null(msg, param, res);
			}
			memcpy(p, res->rs.s, res->rs.len);
			p += res->rs.len;
		} while ((avp=xavp_get_next(avp))!=0);
		res->rs.s = p_ini;
		res->rs.len = p - p_ini;
		return 0;
	}
	return pv_xavp_get_value(msg, param, res, avp);
}
示例#3
0
/**
 * $xavp(name1[idx1]=>name2[idx2])
 */
int pv_set_xavp(struct sip_msg* msg, pv_param_t *param,
		int op, pv_value_t *val)
{
	pv_xavp_name_t *xname=NULL;
	sr_xavp_t *avp=NULL;
	sr_xavp_t *list=NULL;
	sr_xval_t xval;
	int idxf = 0;
	int idx = 0;
	int idxf1 = 0;
	int idx1 = 0;
	int count;

	if(param==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}
	xname = (pv_xavp_name_t*)param->pvn.u.dname;

	if(xname->index.type==PVT_EXTRA)
	{
		/* get the index */
		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
	}

	if((val==NULL) || (val->flags&PV_VAL_NULL))
	{
		if(xname->next==NULL)
		{
			if(xname->index.type==PVT_EXTRA) {
				if(idxf==PV_IDX_ALL) {
					xavp_rm_by_name(&xname->name, 1, NULL);
					return 0;
				}
			}
			if(idx==0) {
				xavp_rm_by_name(&xname->name, 0, NULL);
				return 0;
			}
			/* fix the index */
			if(idx<0)
			{
				count = xavp_count(&xname->name, NULL);
				idx = count + idx + 1;
			}
			xavp_rm_by_index(&xname->name, idx, NULL);
			return 0;
		}
		
		if(xname->next->index.type==PVT_EXTRA)
		{
			/* get the index */
			if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
			{
				LM_ERR("invalid index!\n");
				return -1;
			}
		}

		if(idxf==PV_IDX_ALL) {
			/* iterate */
			avp = xavp_get(&xname->name, NULL);
			while(avp) {
				if(avp->val.type==SR_XTYPE_XAVP) {
					if(xname->next->index.type==PVT_EXTRA) {
						if(idxf1==PV_IDX_ALL) {
							xavp_rm_by_name(&xname->next->name, 1,
									&avp->val.v.xavp);
						} else {
							/* fix the index */
							idx = idx1;
							if(idx<0)
							{
								count = xavp_count(&xname->next->name,
										&avp->val.v.xavp);
								idx = count + idx1 + 1;
							}
							xavp_rm_by_index(&xname->next->name, idx,
									&avp->val.v.xavp);
						}
					} else {
						xavp_rm_by_name(&xname->next->name, 0,
								&avp->val.v.xavp);
					}
				}
				avp = xavp_get_next(avp);
			}
			return 0;
		}

		if(idx==0) {
			avp = xavp_get(&xname->name, NULL);
		} else {
			/* fix the index */
			if(idx<0)
			{
				count = xavp_count(&xname->name, NULL);
				idx = count + idx + 1;
			}
			avp = xavp_get_by_index(&xname->name, idx, NULL);
		}
		if(avp) {
			if(avp->val.type==SR_XTYPE_XAVP) {
				if(xname->next->index.type==PVT_EXTRA) {
					if(idxf1==PV_IDX_ALL) {
						xavp_rm_by_name(&xname->next->name, 1,
								&avp->val.v.xavp);
					} else {
						/* fix the index */
						idx = idx1;
						if(idx<0)
						{
							count = xavp_count(&xname->next->name,
									&avp->val.v.xavp);
							idx = count + idx1 + 1;
						}
						xavp_rm_by_index(&xname->next->name, idx,
								&avp->val.v.xavp);
					}
				} else {
					xavp_rm_by_name(&xname->next->name, 0,
							&avp->val.v.xavp);
				}
			}
		}
		return 0;
	} /* NULL assignment */

	/* build xavp value */
	memset(&xval, 0, sizeof(sr_xval_t));

	if(val->flags&PV_TYPE_INT)
	{
		xval.type = SR_XTYPE_INT;
		xval.v.i = val->ri;
	} else {
		xval.type = SR_XTYPE_STR;
		xval.v.s = val->rs;
	}

	/* where to add */
	if(xname->next==NULL)
	{
		/* xavp with single value */
		if(xname->index.type==PVT_EXTRA) {
			if(idxf==PV_IDX_ALL) {
				/* ignore: should iterate and set same value to all xavps
				 * with same name?!?! */
				return -1;
			}
			/* fix the index */
			if(idx<0)
			{
				count = xavp_count(&xname->name, NULL);
				idx = count + idx + 1;
			}
			/* set the value */
			if(xavp_set_value(&xname->name, idx, &xval, NULL)==NULL)
				return -1;
			return 0;
		}
		/* add new value */
		if(xavp_add_value(&xname->name, &xval, NULL)==NULL)
			return -1;
		return 0;
	}
		
	/* xavp with xavp list value */
	if(xname->next->index.type==PVT_EXTRA)
	{
		/* get the index */
		if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
		{
			LM_ERR("invalid index!\n");
			return -1;
		}
	}

	if(xname->index.type==PVT_EXTRA)
	{
		/* set the value */
		if(idxf==PV_IDX_ALL) {
			/* ignore: should iterate and set same value to all xavps
			 * with same name?!?! */
			return 0;
		}

		if(idx==0) {
			avp = xavp_get(&xname->name, NULL);
		} else {
			/* fix the index */
			if(idx<0)
			{
				count = xavp_count(&xname->name, NULL);
				idx = count + idx + 1;
			}
			avp = xavp_get_by_index(&xname->name, idx, NULL);
		}
		if(avp==NULL)
			return 0;

		if(avp->val.type!=SR_XTYPE_XAVP)
			return -1;
			
		if(xname->next->index.type==PVT_EXTRA) {
			if(idxf1==PV_IDX_ALL) {
				/* ignore: should iterate and set same value to all xavps
				 * with same name?!?! */
				return 0;
			}
			/* fix the index */
			idx = idx1;
			if(idx<0)
			{
				count = xavp_count(&xname->next->name,
						&avp->val.v.xavp);
				idx = count + idx1 + 1;
			}
			/* set value */
			xavp_set_value(&xname->next->name, idx, &xval, &avp->val.v.xavp);
			return 0;
		}
		/* add new value in sublist */
		if(xavp_add_value(&xname->next->name, &xval, &avp->val.v.xavp)==NULL)
			return -1;
		return 0;
	}
	/* add new xavp with xavp list */
	if(xavp_add_value(&xname->next->name, &xval, &list)==NULL)
		return -1;
	
	/* build xavp value */
	memset(&xval, 0, sizeof(sr_xval_t));
	xval.type = SR_XTYPE_XAVP;
	xval.v.xavp = list;
	xavp_add_value(&xname->name, &xval, NULL);

	return 0;
}
示例#4
0
文件: regpv.c 项目: krys1976/kamailio
int pv_get_ulc(struct sip_msg *msg,  pv_param_t *param,
		pv_value_t *res)
{
	regpv_name_t *rp;
	regpv_profile_t *rpp;
	ucontact_t *c;
	int idx;
	int i;

	if(param==NULL)
	{
		LM_ERR("invalid params\n");
		return -1;
	}
	rp = (regpv_name_t*)param->pvn.u.dname;
	if(rp==NULL || rp->rp==NULL)
	{
		LM_DBG("no profile in params\n");
		return pv_get_null(msg, param, res);
	}
	rpp = rp->rp;

	if(rpp->flags==0 || rpp->contacts==NULL)
	{
		LM_DBG("profile not set or no contacts there\n");
		return pv_get_null(msg, param, res);
	}
	/* get index */
	if(pv_get_spec_index(msg, param, &idx, &i)!=0)
	{
		LM_ERR("invalid index\n");
		return -1;
	}

	/* work only with positive indexes by now */
	if(idx<0)
		idx = 0;

	/* get contact */
	i = 0;
	c = rpp->contacts;
	while(rpp)
	{
		if(i == idx)
			break;
		i++;
		c = c->next;
	}
	if(c==NULL)
		return pv_get_null(msg, param, res);

	switch(rp->attr)
	{
		case 0: /* aor */
			return  pv_get_strval(msg, param, res, &rpp->aor);
		break;
		case 1: /* domain */
			return  pv_get_strval(msg, param, res, &rpp->domain);
		break;
		case 2: /* aorhash */
			return pv_get_uintval(msg, param, res, rpp->aorhash);
		break;
		case 3: /* addr */
			return  pv_get_strval(msg, param, res, &c->c);
		break;
		case 4: /* path */
			return  pv_get_strval(msg, param, res, &c->path);
		break;
		case 5: /* received */
			return  pv_get_strval(msg, param, res, &c->received);
		break;
		case 6: /* expires */
			return pv_get_uintval(msg, param, res,
					(unsigned int)c->expires);
		break;
		case 7: /* callid */
			return  pv_get_strval(msg, param, res, &c->callid);
		break;
		case 8: /* q */
			return pv_get_sintval(msg, param, res, (int)c->q);
		break;
		case 9: /* cseq */
			return pv_get_sintval(msg, param, res, c->cseq);
		break;
		case 10: /* flags */
			return pv_get_uintval(msg, param, res, c->flags);
		break;
		case 11: /* cflags */
			return pv_get_uintval(msg, param, res, c->cflags);
		break;
		case 12: /* user agent */
			return  pv_get_strval(msg, param, res, &c->user_agent);
		break;
		case 14: /* socket */
			if(c->sock==NULL)
				return pv_get_null(msg, param, res);
			return pv_get_strval(msg, param, res, &c->sock->sock_str);
		break;
		case 15: /* modified */
			return pv_get_uintval(msg, param, res,
					(unsigned int)c->last_modified);
		break;
		case 16: /* methods */
			return pv_get_uintval(msg, param, res, c->methods);
		break;
		case 17: /* count */
			return pv_get_sintval(msg, param, res, rpp->nrc);
		break;
	}

	return pv_get_null(msg, param, res);
}
示例#5
0
int pv_get_branchx_helper(sip_msg_t *msg, pv_param_t *param,
		pv_value_t *res, int btype)
{
	int idx = 0;
	int idxf = 0;
	branch_t *br;

	if(btype==1) {
		br = &_pv_sbranch;
	} else {
		/* get the index */
		if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return pv_get_null(msg, param, res);
		}
		br = get_sip_branch(idx);
		if(br==NULL) {
			return pv_get_null(msg, param, res);
		}
	}

	/* branch(count) doesn't need a valid branch, everything else does */
	if(br->len == 0 && ( param->pvn.u.isname.name.n != 5/* count*/ ))
	{
		LM_ERR("error accessing branch [%d]\n", idx);
		return pv_get_null(msg, param, res);
	}

	switch(param->pvn.u.isname.name.n)
	{
		case 1: /* dst uri */
			if(br->dst_uri_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->dst_uri, br->dst_uri_len);
		case 2: /* path */
			if(br->path_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->path, br->path_len);
		case 3: /* Q */
			if(br->q == Q_UNSPECIFIED)
				return pv_get_null(msg, param, res);
			return pv_get_sintval(msg, param, res, br->q);
		case 4: /* send socket */
			if(br->force_send_socket!=0)
				return pv_get_strval(msg, param, res, &br->force_send_socket->sock_str);
			return pv_get_null(msg, param, res);
		case 5: /* count */
			return pv_get_uintval(msg, param, res, nr_branches);
		case 6: /* flags */
			return pv_get_uintval(msg, param, res, br->flags);
		case 7: /* ruid */
			if(br->ruid_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->ruid, br->ruid_len);
		case 8: /* location_ua */
			if(br->location_ua_len==0)
				return pv_get_null(msg, param, res);
			return pv_get_strlval(msg, param, res, br->location_ua, br->location_ua_len);
		default:
			/* 0 - uri */
			return pv_get_strlval(msg, param, res, br->uri, br->len);
	}

	return 0;
}
示例#6
0
int pv_set_branchx_helper(sip_msg_t *msg, pv_param_t *param,
		int op, pv_value_t *val, int btype)
{
	int idx = 0;
	int idxf = 0;
	branch_t *br;
	struct socket_info *si;
	int port, proto;
	str host;
	char backup;

	if(msg==NULL || param==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}

	if(btype==1) {
		br = &_pv_sbranch;
	} else {
		/* get the index */
		if(pv_get_spec_index(msg, param, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
		if(idx<0)
		{
			if((int)nr_branches + idx >= 0) {
				idx += nr_branches;
			} else {
				LM_ERR("index too low: %d (%u)\n", idx, nr_branches);
				return -1;
			}
		}
		LM_DBG("managing branch index %d (%u)\n", idx, nr_branches);
		br = get_sip_branch(idx);
	}

	if(br==NULL)
	{
		LM_DBG("no branch to operate on\n");
		return -1;
	}

	switch(param->pvn.u.isname.name.n)
	{
		case 1: /* dst uri */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->dst_uri[0] = '\0';
				br->dst_uri_len = 0;
				break;
			}
			if(!(val->flags&PV_VAL_STR))
			{
				LM_ERR("str value required to set branch dst uri\n");
				return -1;
			}
			if(val->rs.len<=0)
			{
				br->dst_uri[0] = '\0';
				br->dst_uri_len = 0;
				break;
			}

			if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
			{
				LM_ERR("too long dst uri: %.*s\n",
								val->rs.len, val->rs.s);
				return -1;
			}
			memcpy(br->dst_uri, val->rs.s, val->rs.len);
			br->dst_uri[val->rs.len] = 0;
			br->dst_uri_len = val->rs.len;
		break;
		case 2: /* path */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->path[0] = '\0';
				br->path_len = 0;
				break;
			}
			if(!(val->flags&PV_VAL_STR))
			{
				LM_ERR("str value required to set branch path\n");
				return -1;
			}
			if(val->rs.len<=0)
			{
				br->path[0] = '\0';
				br->path_len = 0;
				break;
			}

			if (unlikely(val->rs.len > MAX_PATH_SIZE - 1))
			{
				LM_ERR("path too long: %.*s\n",
							val->rs.len, val->rs.s);
				return -1;
			}
			memcpy(br->path, val->rs.s, val->rs.len);
			br->path[val->rs.len] = 0;
			br->path_len = val->rs.len;
		break;
		case 3: /* Q */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->q = Q_UNSPECIFIED;
				break;
			}
			if(!(val->flags&PV_VAL_INT))
			{
				LM_ERR("int value required to set branch q\n");
				return -1;
			}
			br->q = val->ri;
		break;
		case 4: /* send socket */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->force_send_socket = NULL;
				break;
			}
			if(!(val->flags&PV_VAL_STR))
			{
				LM_ERR("str value required to set branch send sock\n");
				return -1;
			}
			if(val->rs.len<=0)
			{
				br->force_send_socket = NULL;
				break;
			}
			backup = val->rs.s[val->rs.len];
			val->rs.s[val->rs.len] = '\0';
			if (parse_phostport(val->rs.s, &host.s, &host.len, &port,
						&proto) < 0)
			{
				LM_ERR("invalid socket specification\n");
				val->rs.s[val->rs.len] = backup;
				return -1;
			}
			val->rs.s[val->rs.len] = backup;
			si = grep_sock_info(&host, (unsigned short)port,
					(unsigned short)proto);
			if (si!=NULL)
			{
				br->force_send_socket = si;
			} else {
				LM_WARN("no socket found to match [%.*s]\n",
					val->rs.len, val->rs.s);
				br->force_send_socket = NULL;
			}
		break;
		case 5: /* count */
			/* do nothing - cannot set the branch counter */
		break;
		case 6: /* flags */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				br->flags = 0;
				break;
			}
			if(!(val->flags&PV_VAL_INT))
			{
				LM_ERR("int value required to set branch flags\n");
				return -1;
			}
			br->flags = val->ri;
		break;
		case 7: /* ruid */
			/* do nothing - cannot set the ruid */
		break;
		case 8: /* location_ua */
			/* do nothing - cannot set the location_ua */
		break;
		default:
			/* 0 - uri */
			if(val==NULL || (val->flags&PV_VAL_NULL))
			{
				if(btype==1) {
					memset(br, 0, sizeof(branch_t));
				} else {
					drop_sip_branch(idx);
				}
			} else {
				if(!(val->flags&PV_VAL_STR))
				{
					LM_ERR("str value required to set branch uri\n");
					return -1;
				}
				if(val->rs.len<=0)
				{
					if(btype==1) {
						memset(br, 0, sizeof(branch_t));
					} else {
						drop_sip_branch(idx);
					}
				} else {
					if (unlikely(val->rs.len > MAX_URI_SIZE - 1))
					{
						LM_ERR("too long r-uri: %.*s\n",
								val->rs.len, val->rs.s);
						return -1;
					}
					memcpy(br->uri, val->rs.s, val->rs.len);
					br->uri[val->rs.len] = 0;
					br->len = val->rs.len;
				}
			}
	}

	return 0;
}
示例#7
0
文件: tm.c 项目: Deni90/opensips
int pv_set_tm_branch_avp(struct sip_msg *msg, pv_param_t *param, int op,
		pv_value_t *val)
{
	int avp_name;
	int_str avp_val;
	int flags, res=0;
	unsigned short name_type;
	int idx, idxf;
	struct usr_avp **old_list=NULL;
	struct usr_avp **avp_list=NULL;

	if (!msg || !val)
		goto error;

	avp_list = get_bavp_list();
	if (!avp_list) {
		pv_get_null(msg, param, val);
		goto success;
	}

	if (!param) {
		LM_ERR("bad parameters\n");
		goto error;
	}

	if (pv_get_avp_name(msg, param, &avp_name, &name_type)) {
		LM_ALERT("BUG in getting bavp name\n");
		goto error;
	}

	/* get the index */
	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
		LM_ERR("invalid index\n");
		goto error;
	}

	/* setting the avp head */
	old_list = set_avp_list(avp_list);
	if (!old_list) {
		LM_CRIT("no bavp head list found\n");
		goto error;
	}

	if(val == NULL) {
		if(op == COLONEQ_T || idxf == PV_IDX_ALL)
			destroy_avps(name_type, avp_name, 1);
		else {
			if(idx < 0) {
				LM_ERR("index with negative value\n");
				goto error;
			}
			destroy_index_avp(name_type, avp_name, idx);
		}
		/* restoring head */
		goto success;
	}

	if(op == COLONEQ_T || idxf == PV_IDX_ALL)
		destroy_avps(name_type, avp_name, 1);

	flags = name_type;
	if(val->flags&PV_TYPE_INT) {
		avp_val.n = val->ri;
	} else {
		avp_val.s = val->rs;
		flags |= AVP_VAL_STR;
	}

	if(idxf == PV_IDX_INT || idxf == PV_IDX_PVAR) {
		if(replace_avp(flags, avp_name, avp_val, idx)< 0) {
			LM_ERR("failed to replace bavp\n");
			goto error;
		}
	} else {
		if (add_avp(flags, avp_name, avp_val)<0) {
			LM_ERR("error - cannot add bavp\n");
			goto error;
		}
	}
	goto success;

error:
	res = -1;
success:
	if (old_list)
		set_avp_list(old_list);
	return res;
}
示例#8
0
文件: tm.c 项目: Deni90/opensips
int pv_get_tm_branch_avp(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *val)
{
	int avp_name;
	int_str avp_value;
	unsigned short name_type;
	int idx, idxf, res=0;
	struct usr_avp **old_list=NULL;
	struct usr_avp **avp_list=NULL;
	struct usr_avp *avp;
	int_str avp_value0;
	struct usr_avp *avp0;
	int n=0;
	char *p;

	if (!msg || !val)
		goto error;

	avp_list = get_bavp_list();
	if (!avp_list) {
		pv_get_null(msg, param, val);
		goto success;
	}

	if (!param) {
		LM_ERR("bad parameters\n");
		goto error;
	}

	if (pv_get_avp_name(msg, param, &avp_name, &name_type)) {
		LM_ALERT("BUG in getting bavp name\n");
		goto error;
	}

	/* get the index */
	if(pv_get_spec_index(msg, param, &idx, &idxf)!=0) {
		LM_ERR("invalid index\n");
		goto error;
	}

	/* setting the avp head */
	old_list = set_avp_list(avp_list);
	if (!old_list) {
		LM_CRIT("no bavp head list found\n");
		goto error;
	}

	if ((avp=search_first_avp(name_type, avp_name, &avp_value, 0))==0) {
		pv_get_null(msg, param, val);
		goto success;
	}
	val->flags = PV_VAL_STR;
	if ( (idxf==0 || idxf==PV_IDX_INT) && idx==0) {
		if(avp->flags & AVP_VAL_STR) {
			val->rs = avp_value.s;
		} else {
			val->rs.s = sint2str(avp_value.n, &val->rs.len);
			val->ri = avp_value.n;
			val->flags |= PV_VAL_INT|PV_TYPE_INT;
		}
		goto success;
	}
	if(idxf==PV_IDX_ALL) {
		p = pv_local_buf;
		do {
			if(avp->flags & AVP_VAL_STR) {
				val->rs = avp_value.s;
			} else {
				val->rs.s = sint2str(avp_value.n, &val->rs.len);
			}

			if(p-pv_local_buf+val->rs.len+1>PV_LOCAL_BUF_SIZE) {
				LM_ERR("local buffer length exceeded!\n");
				pv_get_null(msg, param, val);
				goto success;
			}
			memcpy(p, val->rs.s, val->rs.len);
			p += val->rs.len;
			if(p-pv_local_buf+PV_FIELD_DELIM_LEN+1>PV_LOCAL_BUF_SIZE) {
				LM_ERR("local buffer length exceeded\n");
				pv_get_null(msg, param, val);
				goto success;
			}
			memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
			p += PV_FIELD_DELIM_LEN;
		} while ((avp=search_first_avp(name_type, avp_name,
						&avp_value, avp))!=0);
		*p = 0;
		val->rs.s = pv_local_buf;
		val->rs.len = p - pv_local_buf;
		goto success;
	}

	/* we have a numeric index */
	if(idx<0) {
		n = 1;
		avp0 = avp;
		while ((avp0=search_first_avp(name_type, avp_name,
						&avp_value0, avp0))!=0) n++;
		idx = -idx;
		if(idx>n) {
			LM_DBG("index out of range\n");
			pv_get_null(msg, param, val);
			goto success;
		}
		idx = n - idx;
		if(idx==0) {
			if(avp->flags & AVP_VAL_STR) {
				val->rs = avp_value.s;
			} else {
				val->rs.s = sint2str(avp_value.n, &val->rs.len);
				val->ri = avp_value.n;
				val->flags |= PV_VAL_INT|PV_TYPE_INT;
			}
			goto success;
		}
	}
	n=0;
	while(n<idx &&
			(avp=search_first_avp(name_type, avp_name, &avp_value, avp))!=0)
		n++;

	if(avp!=0) {
		if(avp->flags & AVP_VAL_STR) {
			val->rs = avp_value.s;
		} else {
			val->rs.s = sint2str(avp_value.n, &val->rs.len);
			val->ri = avp_value.n;
			val->flags |= PV_VAL_INT|PV_TYPE_INT;
		}
	}

	goto success;

error:
	res = -1;
success:
	if (old_list)
		set_avp_list(old_list);
	return res;
}