Пример #1
0
static int w_dlg_terminate(struct sip_msg *msg, char *side, char *r) {
    struct dlg_cell *dlg;
    str reason = {0, 0};

    int n = (int) (long) side;

    //check if a reason was given
    if (r) {
        if (get_str_fparam(&reason, msg, (fparam_t *) r) < 0) {
            LM_ERR("failed to recover reason parameter\n");
            return -1;
        }
    }

    dlg = dlg_get_msg_dialog(msg);
    //dlg_get_ctx_dialog();
    if (!dlg) {
        LM_DBG("Unable to find dialog for terminate\n");
        return -1;
    }

    if (!dlg_terminate(dlg, msg, &reason, n, NULL)) {
        LM_DBG("Failed to terminate dialog\n");
        return -1;
    }

    return 1;
}
Пример #2
0
/*!
 * \brief Unset a dialog profile
 * \param msg SIP message
 * \param value value
 * \param profile dialog profile table
 * \return 1 on success, -1 on failure
 */
int unset_dlg_profile(sip_msg_t *msg, str *value,
		dlg_profile_table_t *profile)
{
	dlg_cell_t *dlg;
	dlg_profile_link_t *linker;
	dlg_profile_link_t *linker_prev;
	dlg_entry_t *d_entry;

	if (is_route_type(REQUEST_ROUTE)) {
		LM_ERR("dialog delete profile cannot be used in request route\n");
		return -1;
	}

	/* get current dialog */
	dlg = dlg_get_msg_dialog(msg);

	if (dlg==NULL) {
		LM_WARN("dialog is NULL for delete profile\n");
		return -1;
	}

	/* check the dialog linkers */
	d_entry = &d_table->entries[dlg->h_entry];
	dlg_lock( d_table, d_entry);
	linker = dlg->profile_links;
	linker_prev = NULL;
	for( ; linker ; linker_prev=linker,linker=linker->next) {
		if (linker->profile==profile) {
			if (profile->has_value==0) {
				goto found;
			} else if (value && value->len==linker->hash_linker.value.len &&
			memcmp(value->s,linker->hash_linker.value.s,value->len)==0){
				goto found;
			}
			/* allow further search - maybe the dialog is inserted twice in
			 * the same profile, but with different values -bogdan
			 */
		}
	}
	atomic_or_int((volatile int*)&dlg->dflags, DLG_FLAG_CHANGED_PROF);
	dlg_unlock( d_table, d_entry);
	dlg_release(dlg);
	return -1;

found:
	/* table still locked */
	/* remove the linker element from dialog */
	if (linker_prev==NULL) {
		dlg->profile_links = linker->next;
	} else {
		linker_prev->next = linker->next;
	}
	linker->next = NULL;
	dlg_unlock( d_table, d_entry);
	/* remove linker from profile table and free it */
	destroy_linkers(linker);
	dlg_release(dlg);
	return 1;
}
Пример #3
0
int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{

	dlg_cell_t *dlg;
	str * value;
	str spv;

	if (param==NULL || param->pvn.type!=PV_NAME_INTSTR
			|| param->pvn.u.isname.type!=AVP_NAME_STR
			|| param->pvn.u.isname.name.s.s==NULL) {
		LM_CRIT("BUG - bad parameters\n");
		return -1;
	}

	/* Retrieve the dialog for current message */
	dlg=dlg_get_msg_dialog( msg);

	if (dlg) {
		/* Lock the dialog */
		dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
	} else {
		/* Verify the local list */
		get_local_varlist_pointer(msg, 0);
	}

	/* dcm: todo - the value should be cloned for safe usage */
	value = get_dlg_variable_unsafe(dlg, &param->pvn.u.isname.name.s);

	spv.s = NULL;
	if(value) {
		spv.len = pv_get_buffer_size();
		if(spv.len<value->len+1) {
			LM_ERR("pv buffer too small (%d) - needed %d\n", spv.len, value->len);
		} else {
			spv.s = pv_get_buffer();
			strncpy(spv.s, value->s, value->len);
			spv.len = value->len;
			spv.s[spv.len] = '\0';
		}
	}

	print_lists(dlg);

	/* unlock dialog */
	if (dlg) {
		dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
		dlg_release(dlg);
	}

	if (spv.s)
		return pv_get_strval(msg, param, res, &spv);


	return pv_get_null(msg, param, res);
}
Пример #4
0
/*
 * Determine if message is in a dialog currently being tracked
 */
int	is_known_dlg(struct sip_msg *msg) {
	dlg_cell_t *dlg;

	dlg = dlg_get_msg_dialog(msg);
	
	if(dlg == NULL)
		return -1;

	dlg_release(dlg);

	return 1;
}
Пример #5
0
/*!
 * \brief Check if a dialog belongs to a profile
 * \param msg SIP message
 * \param profile dialog profile table
 * \param value value
 * \return 1 on success, -1 on failure
 */
int is_dlg_in_profile(struct sip_msg *msg, struct dlg_profile_table *profile,
		str *value) {
	struct dlg_cell *dlg;
	struct dlg_profile_link *linker;
	struct dlg_entry *d_entry;
        int ret;

	LM_DBG("Getting current dialog");
	/* get current dialog */
	dlg = dlg_get_msg_dialog(msg);

	if (dlg == NULL) {
		LM_DBG("Error: Current dlg is null");

		return -1;
	}
	LM_DBG("Current dlg found");

        ret = -1;
	/* check the dialog linkers */
	d_entry = &d_table->entries[dlg->h_entry];
	dlg_lock( d_table, d_entry);
	for (linker = dlg->profile_links; linker; linker = linker->next) {
		LM_DBG("Running through linkers");
		if (linker->profile == profile) {
			LM_DBG("Profile matches");
			if (profile->has_value == 0) {
				LM_DBG("Profile has value is zero returning true");
				dlg_unlock( d_table, d_entry);
				ret = 1;
                                goto done;
			} else if (value && value->len == linker->hash_linker.value.len
					&& memcmp(value->s, linker->hash_linker.value.s, value->len)
							== 0) {
				LM_DBG("Profile has value equal to passed value returning true");
				dlg_unlock( d_table, d_entry);
				ret = 1;
                                goto done;
			}
			/* allow further search - maybe the dialog is inserted twice in
			 * the same profile, but with different values -bogdan
			 */
		}
	}
	dlg_unlock( d_table, d_entry);
        
done:
        dlg_release(dlg);
        return ret;
}
Пример #6
0
/*!
 * \brief Check if a dialog belongs to a profile
 * \param msg SIP message
 * \param profile dialog profile table
 * \param value value
 * \return 1 on success, -1 on failure
 */
int is_dlg_in_profile(struct sip_msg *msg, struct dlg_profile_table *profile,
		str *value)
{
	struct dlg_cell *dlg;
	struct dlg_profile_link *linker;
	struct dlg_entry *d_entry;
	int ret;

	/* get current dialog */
	dlg = dlg_get_msg_dialog(msg);

	if (dlg==NULL)
		return -1;

	ret = -1;
	/* check the dialog linkers */
	d_entry = &d_table->entries[dlg->h_entry];
	dlg_lock( d_table, d_entry);
	for( linker=dlg->profile_links ; linker ; linker=linker->next) {
		if (linker->profile==profile) {
			if (profile->has_value==0) {
				dlg_unlock( d_table, d_entry);
				ret = 1;
				goto done;
			} else if (value && value->len==linker->hash_linker.value.len &&
			memcmp(value->s,linker->hash_linker.value.s,value->len)==0){
				dlg_unlock( d_table, d_entry);
				ret = 1;
				goto done;
			}
			/* allow further search - maybe the dialog is inserted twice in
			 * the same profile, but with different values -bogdan
			 */
		}
	}
	dlg_unlock( d_table, d_entry);

done:
	dlg_release(dlg);
	return ret;
}
Пример #7
0
static int w_dlg_set_timeout(struct sip_msg *msg, char *pto, char *phe, char *phi)
{
	int to = 0;
	unsigned int he = 0;
	unsigned int hi = 0;
	dlg_cell_t *dlg = NULL;

	if(fixup_get_ivalue(msg, (gparam_p)pto, &to)!=0)
	{
		LM_ERR("no timeout value\n");
		return -1;
	}
	if(phe!=NULL)
	{
		if(fixup_get_ivalue(msg, (gparam_p)phe, (int*)&he)!=0)
		{
			LM_ERR("no hash entry value value\n");
			return -1;
		}
		if(fixup_get_ivalue(msg, (gparam_p)phi, (int*)&hi)!=0)
		{
			LM_ERR("no hash id value value\n");
			return -1;
		}
		dlg = dlg_lookup(he, hi);
	} else {
		dlg = dlg_get_msg_dialog(msg);
	}

	if(dlg==NULL)
	{
		LM_DBG("no dialog found\n");
		return -1;
	}

	if(update_dlg_timeout(dlg, to) != 0) 
		return -1;

	return 1;
}
Пример #8
0
int pv_set_dlg_variable(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val)
{
	dlg_cell_t *dlg = NULL;
	int ret = -1;

	if (param==NULL || param->pvn.type!=PV_NAME_INTSTR
			|| param->pvn.u.isname.type!=AVP_NAME_STR
			|| param->pvn.u.isname.name.s.s==NULL ) {
		LM_CRIT("BUG - bad parameters\n");
		goto error;
	}

	/* Retrieve the dialog for current message */
	dlg=dlg_get_msg_dialog( msg);
	
	if (dlg) {
		/* Lock the dialog */
		dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
	} else {
		/* Verify the local list */
		get_local_varlist_pointer(msg, 0);
	}

	if (val==NULL || val->flags&(PV_VAL_NONE|PV_VAL_NULL|PV_VAL_EMPTY)) {
		/* if NULL, remove the value */
		ret = set_dlg_variable_unsafe(dlg, &param->pvn.u.isname.name.s, NULL);
		if(ret!= 0) {
			/* unlock dialog */
			if (dlg) {
				dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
				dlg_release(dlg);
			}
			return ret;
		}
	} else {
		/* if value, must be string */
		if ( !(val->flags&PV_VAL_STR)) {
			LM_ERR("non-string values are not supported\n");
			/* unlock dialog */
			if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
			goto error;
		}

		ret = set_dlg_variable_unsafe(dlg, &param->pvn.u.isname.name.s, &val->rs);
		if(ret!= 0) {
			/* unlock dialog */
			if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
			goto error;
		}
	}
	/* unlock dialog */
	if (dlg) {
		dlg->dflags |= DLG_FLAG_CHANGED_VARS;
		dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
		if ( dlg_db_mode==DB_MODE_REALTIME )
			update_dialog_dbinfo(dlg);

	}
	print_lists(dlg);

	dlg_release(dlg);
	return 0;
error:
	dlg_release(dlg);
	return -1;
}
Пример #9
0
/*!
 * \brief Set a dialog profile
 * \param msg SIP message
 * \param value value
 * \param profile dialog profile table
 * \return 0 on success, -1 on failure
 */
int set_dlg_profile(struct sip_msg *msg, str *value, struct dlg_profile_table *profile)
{
	dlg_cell_t *dlg = NULL;
	dlg_profile_link_t *linker;

	/* get current dialog */
	dlg = dlg_get_msg_dialog(msg);

	if (dlg==NULL && !is_route_type(REQUEST_ROUTE)) {
		LM_CRIT("BUG - dialog not found in a non REQUEST route (%d)\n",
			REQUEST_ROUTE);
		return -1;
	}

	/* build new linker */
	linker = (struct dlg_profile_link*)shm_malloc(
		sizeof(struct dlg_profile_link) + (profile->has_value?value->len:0) );
	if (linker==NULL) {
		LM_ERR("no more shm memory\n");
		goto error;
	}
	memset(linker, 0, sizeof(struct dlg_profile_link));

	/* set backpointers to profile and linker (itself) */
	linker->profile = profile;
	linker->hash_linker.linker = linker;

	/* set the value */
	if (profile->has_value) {
		linker->hash_linker.value.s = (char*)(linker+1);
		memcpy( linker->hash_linker.value.s, value->s, value->len);
		linker->hash_linker.value.len = value->len;
	}
	sruid_next_safe(&_dlg_profile_sruid);
	strcpy(linker->hash_linker.puid, _dlg_profile_sruid.uid.s);
	linker->hash_linker.puid_len = _dlg_profile_sruid.uid.len;

	if (dlg!=NULL) {
		/* add linker directly to the dialog and profile */
		link_dlg_profile( linker, dlg);
	} else {
		/* if existing linkers are not from current request, just discard them */
		if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) {
			current_dlg_msg_id = msg->id;
			current_dlg_msg_pid = msg->pid;
			destroy_linkers(current_pending_linkers);
			current_pending_linkers = NULL;
		}
		/* no dialog yet -> set linker as pending */
		if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) {
			current_dlg_msg_id = msg->id;
			current_dlg_msg_pid = msg->pid;
			destroy_linkers(current_pending_linkers);
		}

		linker->next = current_pending_linkers;
		current_pending_linkers = linker;
	}

	dlg_release(dlg);
	return 0;
error:
	dlg_release(dlg);
	return -1;
}
Пример #10
0
int pv_get_dlg(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	dlg_cell_t *dlg = NULL;
	int res_type = 0;
	str sv = { 0 };
	unsigned int ui = 0;

	if(param==NULL)
		return -1;

	if(_dlg_ctx.iuid.h_id==0)
	{
		/* Retrieve the dialog for current message */
		dlg=dlg_get_msg_dialog(msg);
	} else {
		/* Retrieve the dialog for current context */
		dlg=dlg_get_by_iuid(&_dlg_ctx.iuid);
	}
	if(dlg == NULL)
		return pv_get_null(msg, param, res);

	switch(param->pvn.u.isname.name.n)
	{
		case 1:
			res_type = 1;
			ui = (unsigned int)dlg->h_id;
			break;
		case 2:
			res_type = 1;
			ui = (unsigned int)dlg->state;
			break;
		case 3:
			if(dlg->route_set[DLG_CALLEE_LEG].s==NULL
					|| dlg->route_set[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->route_set[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->route_set[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 4:
			res_type = 1;
			ui = (unsigned int)dlg->dflags;
			break;
		case 5:
			res_type = 1;
			ui = (unsigned int)dlg->sflags;
			break;
		case 6:
			if(dlg->callid.s==NULL
					|| dlg->callid.len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->callid.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->callid.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 7:
			if(dlg->to_uri.s==NULL
					|| dlg->to_uri.len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->to_uri.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->to_uri.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 8:
			if(dlg->tag[DLG_CALLEE_LEG].s==NULL
					|| dlg->tag[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->tag[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->tag[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 9:
			res_type = 1;
			ui = (unsigned int)dlg->toroute;
			break;
		case 10:
			if(dlg->cseq[DLG_CALLEE_LEG].s==NULL
					|| dlg->cseq[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->cseq[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->cseq[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 11:
			if(dlg->route_set[DLG_CALLER_LEG].s==NULL
					|| dlg->route_set[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->route_set[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->route_set[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 12:
			if(dlg->from_uri.s==NULL
					|| dlg->from_uri.len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->from_uri.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->from_uri.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 13:
			if(dlg->tag[DLG_CALLER_LEG].s==NULL
					|| dlg->tag[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->tag[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->tag[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 14:
			res_type = 1;
			ui = (unsigned int)dlg->lifetime;
			break;
		case 15:
			res_type = 1;
			ui = (unsigned int)dlg->start_ts;
			break;
		case 16:
			if(dlg->cseq[DLG_CALLER_LEG].s==NULL
					|| dlg->cseq[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->cseq[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->cseq[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 17:
			if(dlg->contact[DLG_CALLEE_LEG].s==NULL
					|| dlg->contact[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->contact[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->contact[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 18:
			if(dlg->bind_addr[DLG_CALLEE_LEG]==NULL)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 19:
			if(dlg->contact[DLG_CALLER_LEG].s==NULL
					|| dlg->contact[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->contact[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->contact[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 20:
			if(dlg->bind_addr[DLG_CALLER_LEG]==NULL)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 21:
			res_type = 1;
			ui = (unsigned int)dlg->h_entry;
			break;
		default:
			res_type = 1;
			ui = (unsigned int)dlg->ref;
	}

done:
	dlg_release(dlg);

	switch(res_type) {
		case 1:
			return pv_get_uintval(msg, param, res, ui);
		case 2:
			return pv_get_strval(msg, param, res, &sv);
		default:
			return pv_get_null(msg, param, res);
	}
}