Exemplo n.º 1
0
int pv_get_acc_current_leg(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *val)
{
	acc_ctx_t* ctx=try_fetch_ctx();

	if (ctx == NULL) {
		/* if we don't have a context then create it */
		if (init_acc_ctx(&ctx) < 0) {
			LM_ERR("failed to create accounting context!\n");
			return -1;
		}

		ACC_PUT_CTX(ctx);
	}

	if (ctx->leg_values == NULL) {
		LM_ERR("no legs defined!\n");
		return -1;
	}

	accX_lock(&ctx->lock);
	val->ri = ctx->legs_no - 1;
	val->rs.s = int2str(ctx->legs_no - 1, &val->rs.len);
	accX_unlock(&ctx->lock);

	val->flags = PV_VAL_INT | PV_VAL_STR | PV_TYPE_INT;

	return 0;
}
Exemplo n.º 2
0
/*
 * setter function for $acc_extra
 */
int pv_set_acc_extra(struct sip_msg *msg, pv_param_t *param, int op,
		pv_value_t *val)
{
	int tag_idx;

	acc_ctx_t* ctx=try_fetch_ctx();

	if (param == NULL || val == NULL) {
		LM_ERR("bad params!\n");
		return -1;
	}

	if (ctx == NULL) {
		/* if we don't have a context then create it */
		if (init_acc_ctx(&ctx) < 0) {
			LM_ERR("failed to create accounting context!\n");
			return -1;
		}

		ACC_PUT_CTX(ctx);
	}


	tag_idx = param->pvn.u.isname.name.n;
	/* sanity checks for the tag; it should be valid since
	 * we found it in the parse name function */
	if (tag_idx < 0 || tag_idx >= extra_tgs_len) {
		LM_BUG("invalid tag value! probably a memory corruption issue!\n");
		return -1;
	}


	/* go through all extras and fetch first value you find
	 * all the extras with the same tag will have the same
	 * value */
	accX_lock(&ctx->lock);
	if (set_value_shm(val, &ctx->extra_values[tag_idx]) < 0) {
		LM_ERR("failed to set extra <%.*s> value!\n",
				extra_tags[tag_idx].len, extra_tags[tag_idx].s);
		accX_unlock(&ctx->lock);
		return -1;
	}
	accX_unlock(&ctx->lock);

	return 0;
}
Exemplo n.º 3
0
/*
 * getter function for $acc_extra
 */
int pv_get_acc_extra(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *val)
{
	int tag_idx;

	acc_ctx_t* ctx=try_fetch_ctx();

	if (param == NULL || val == NULL) {
		LM_ERR("bad input params!\n");
		return -1;
	}

	if (ctx == NULL) {
		/* if we don't have a context then create it */
		if (init_acc_ctx(&ctx) < 0) {
			LM_ERR("failed to create accounting context!\n");
			return -1;
		}

		ACC_PUT_CTX(ctx);
	}

	tag_idx = param->pvn.u.isname.name.n;
	/* sanity checks for the tag; it should be valid since
	 * we found it in the parse name function */
	if (tag_idx < 0 || tag_idx >= extra_tgs_len) {
		LM_BUG("invalid tag value! probably a memory corruption issue!\n");
		return -1;
	}


	accX_lock(&ctx->lock);
	if (ctx->extra_values[tag_idx].value.s == NULL) {
		val->flags = PV_VAL_NULL;
	} else {
		val->rs = ctx->extra_values[tag_idx].value;
		val->flags = PV_VAL_STR;
	}
	accX_unlock(&ctx->lock);

	return 0;
}
Exemplo n.º 4
0
int w_new_leg(struct sip_msg* msg)
{
	acc_ctx_t* ctx = try_fetch_ctx();

	if (ctx == NULL) {
		if (init_acc_ctx(&ctx) < 0) {
			LM_ERR("failed to create accounting context!\n");
			return -1;
		}
	}

	accX_lock(&ctx->lock);
	if (push_leg(ctx) < 0) {
		LM_ERR("failed to create new leg!\n");
		accX_unlock(&ctx->lock);
		return -1;
	}
	accX_unlock(&ctx->lock);

	return 1;

}
Exemplo n.º 5
0
int w_do_acc_3(struct sip_msg* msg, char* type_p, char* flags_p, char* table_p)
{
	unsigned long long type=0, flags=0;
	unsigned long long flag_mask;

	acc_ctx_t* acc_ctx;

	acc_type_param_t* acc_param;

	str in;
	str table_name;

	int tmcb_types;
	int is_invite;

	if (type_p == NULL) {
		LM_ERR("accounting type is mandatory!\n");
		return -1;
	}

	acc_param = (acc_type_param_t *)type_p;
	if (acc_param->t == DO_ACC_PARAM_TYPE_VALUE) {
		type = acc_param->u.ival;
	} else {
		if (pv_printf_s(msg, acc_param->u.pval, &in) < 0) {
			LM_ERR("failed to fetch type value!\n");
			return -1;
		}

		if ((type=do_acc_parse(&in, do_acc_type_parser)) == DO_ACC_ERR) {
			LM_ERR("Invalid expression <%.*s> for acc type!\n", in.len, in.s);
			return -1;
		}
	}

	if (table_p != NULL) {
		if (fixup_get_svalue(msg, (gparam_p)table_p, &table_name) < 0) {
			LM_ERR("failed to fetch table name!\n");
			return -1;
		}
	}

	if (flags_p != NULL) {
		flags= *(unsigned long long*)flags_p;
	}

	flag_mask = type + type * flags;
	if (is_cdr_acc_on(flag_mask)) {
		/* setting this flag will allow us to register everything
		 * that is needed for CDR accounting only once */
		set_cdr_values_registered(flag_mask);
	}

	/* is it the first time when the function was called ? */
	acc_ctx = try_fetch_ctx();

	/* we go in here only if do_accounting function was called before;
	 * if accounting context is null or it's created but flags value is
	 * 0(meaning that context was created from somewhere else but do_accounting
	 * wasn't called)  then we need to jump over this and register
	 * all the callbacks we need */
	if (acc_ctx != NULL  && acc_ctx->flags != 0) {
		/* do_accounting already called once */
		/* first check if the accounting table changed  */
		if (is_db_acc_on(flag_mask) &&
				(table_p != NULL ||
				(acc_ctx->acc_table.s==NULL && acc_ctx->acc_table.len == 0))) {
			if (table_p == NULL) {
				table_name = db_table_acc;
			}

			if (store_acc_table( acc_ctx, &table_name) < 0) {
				LM_ERR("failed to store acc table!\n");
				return -1;
			}
		}

		if (!cdr_values_registered(acc_ctx->flags) &&
				cdr_values_registered(flag_mask)) {
			/* CDR support requested for the first time, we need to create
			 * the dialog support, if an initial INVITE */
			if (!has_totag(msg)) {
				acc_ctx->created = time(NULL);

				if (msg->REQ_METHOD == METHOD_INVITE && create_acc_dlg(msg) < 0) {
					LM_ERR("cannot use dialog accounting module\n");
					return -1;
				}
			}
		}

		/* if it's the first time the missed calls flag was used register the callback */
		if (is_mc_acc_on(flag_mask) && !failure_cb_registered(acc_ctx->flags)) {
			if (tmb.register_tmcb( msg, 0, TMCB_ON_FAILURE, tmcb_func, acc_ctx, 0)<=0) {
				LM_ERR("cannot register missed calls callback\n");
				return -1;
			}

			/* don't allow the callback to be registered agian in the future */
			set_failure_cb_registered(acc_ctx->flags);
		}

		acc_ctx->flags |= flag_mask;
		return 1;
	}

	/* initialize accounting context if not created before */
	if (acc_ctx == NULL && init_acc_ctx(&acc_ctx) < 0) {
		LM_ERR("failed to create accounting context!\n");
		return -1;
	}

	/* move acc table in context if we have database accounting */
	if (is_db_acc_on(flag_mask)) {
		if (table_p == NULL) {
			table_name = db_table_acc;
		}

		if (store_acc_table( acc_ctx, &table_name) < 0) {
			LM_ERR("failed to store acc table!\n");
			return -1;
		}
	}


	/*
	 * the first bit in each byte will just tell that we want that type of
	 * accounting
	 * next bits will tell extra options for that type of accounting
	 * so we keep the first bits in each byte and on the following positions
	 * next flags
	 */
	acc_ctx->flags = flag_mask;

	/* make sure that context won't be freed by GLOBAL_CONTEXT free function */
	acc_ctx->flags |= ACC_PROCESSING_CTX_NO_FREE;
	ACC_PUT_CTX(acc_ctx);

	if ( msg && !skip_cancel(msg) &&
	(is_acc_on(acc_ctx->flags) || is_mc_acc_on(acc_ctx->flags)) ) {
		/* do some parsing in advance */
		if (acc_preparse_req(msg)<0)
			return -1;
		is_invite = (msg->REQ_METHOD==METHOD_INVITE)?1:0;
		/* install additional handlers */
		tmcb_types =
			/* report on completed transactions */
			TMCB_RESPONSE_IN;

		if (is_invite && is_mc_acc_on(acc_ctx->flags)) {
			/* register it manually; see explanation below
			 * get incoming replies ready for processing */
			/* TMCB_RESPONSE_OUT | */
			/* report on missed calls */
			tmcb_types |= TMCB_ON_FAILURE;
			/* the flag will help on further do_accounting calls to know
			 * not to register the callback twice */
			set_failure_cb_registered(acc_ctx->flags);
		}

		/* if cdr accounting is enabled */
		if (is_cdr_acc_on(acc_ctx->flags) && !has_totag(msg)) {
			acc_ctx->created = time(NULL);

			if (is_invite && create_acc_dlg(msg) < 0) {
				LM_ERR("cannot use dialog accounting module\n");
				return -1;
			}
		}

		/* we do register_tmcb twice because we want to register the free
		 * function only once */
		if (tmb.register_tmcb( msg, 0, TMCB_RESPONSE_OUT, tmcb_func,
				acc_ctx, tm_free_acc_ctx)<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return -1;
		}

		if (tmb.register_tmcb( msg, 0, tmcb_types, tmcb_func,
				acc_ctx, 0)<=0) {
			LM_ERR("cannot register additional callbacks\n");
			return -1;
		}

		/* if required, determine request direction */
		if( detect_direction && !rrb.is_direction(msg,RR_FLOW_UPSTREAM) ) {
			LM_DBG("detected an UPSTREAM req -> flaging it\n");
			msg->msg_flags |= FL_REQ_UPSTREAM;
		}
	}

	return 1;
}
Exemplo n.º 6
0
int pv_set_acc_leg(struct sip_msg *msg, pv_param_t *param, int flag,
		pv_value_t *val)
{
	int tag_idx, leg_idx;
	acc_ctx_t* ctx = try_fetch_ctx();

	pv_value_t idx_value;

	if (ctx == NULL) {
		/* if we don't have a context then create it */
		if (init_acc_ctx(&ctx) < 0) {
			LM_ERR("failed to create accounting context!\n");
			return -1;
		}

		ACC_PUT_CTX(ctx);
	}

	if (ctx->leg_values == NULL) {
		LM_ERR("no legs defined!\n");
		return -1;
	}

	tag_idx = param->pvn.u.isname.name.n;

	if (param->pvi.type == PV_IDX_PVAR) {
		if (pv_get_spec_value(msg, param->pvi.u.dval, &idx_value) < 0) {
			LM_ERR("failed to fetch index value!\n");
			return -1;
		}

		if (idx_value.flags&PV_VAL_INT) {
			leg_idx = idx_value.ri;
		} else if (idx_value.flags&PV_VAL_STR) {
			if (str2sint(&idx_value.rs, &leg_idx) < 0) {
				goto invalid_leg;
			}
		} else {
			goto invalid_leg;
		}

	} else if(param->pvi.type == PV_IDX_INT) {
		leg_idx = param->pvi.u.ival;
	} else {
		/* if not provided consider the value of the last leg */
		leg_idx = ctx->legs_no - 1;
	}

	if (leg_idx >= (int)ctx->legs_no) {
		LM_ERR("there aren't that many legs!\n");
		return -1;
	}

	if (leg_idx < 0) {
		if ((int)ctx->legs_no + leg_idx < 0) {
			LM_ERR("invalid leg index %d!\n", leg_idx);
			return -1;
		}

		/* -1 will be the last element and so on */
		leg_idx += ctx->legs_no;
	}

	accX_lock(&ctx->lock);
	if (set_value_shm(val, &ctx->leg_values[leg_idx][tag_idx]) < 0) {
		LM_ERR("failed to set leg <%.*s> value for leg number %d!\n",
				extra_tags[tag_idx].len, leg_tags[tag_idx].s, leg_idx);
		accX_unlock(&ctx->lock);
		return -1;
	}
	accX_unlock(&ctx->lock);

	return 0;

invalid_leg:
	LM_ERR("cannot fetch leg index value!\n");
	return -1;
}