Пример #1
0
struct ast_json *ast_json_party_id(struct ast_party_id *party)
{
	RAII_VAR(struct ast_json *, json_party_id, NULL, ast_json_unref);
	int pres;

	/* Combined party presentation */
	pres = ast_party_id_presentation(party);
	json_party_id = ast_json_pack("{s: i, s: s}",
		"presentation", pres,
		"presentation_txt", ast_describe_caller_presentation(pres));
	if (!json_party_id) {
		return NULL;
	}

	/* Party number */
	if (party->number.valid && ast_json_object_set(json_party_id, "number", json_party_number(&party->number))) {
		return NULL;
	}

	/* Party name */
	if (party->name.valid && ast_json_object_set(json_party_id, "name", json_party_name(&party->name))) {
		return NULL;
	}

	/* Party subaddress */
	if (party->subaddress.valid && ast_json_object_set(json_party_id, "subaddress", json_party_subaddress(&party->subaddress))) {
		return NULL;
	}

	return ast_json_ref(json_party_id);
}
/*!
 * \internal
 * \brief Add any appropriate identification headers to an outbound SIP message
 *
 * This will determine if an outbound message should have identification headers and
 * will add the appropriately configured headers
 *
 * \param session The session on which we will be sending the message
 * \param tdata The outbound message
 * \param The identity information to place on the message
 */
static void add_id_headers(const struct ast_sip_session *session, pjsip_tx_data *tdata, const struct ast_party_id *id)
{
	if (!id->number.valid
		|| (!session->endpoint->id.trust_outbound
			&& (ast_party_id_presentation(id) & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
		return;
	}
	if (session->endpoint->id.send_pai) {
		add_pai_header(tdata, id);
	}
	if (session->endpoint->id.send_rpid) {
		add_rpid_header(tdata, id);
	}
}
/*!
 * \internal
 * \brief Add privacy and screen parameters to a Remote-Party-ID header.
 *
 * If privacy is requested, then the privacy and screen parameters need to
 * reflect this. Similarly, if no privacy or screening is to be communicated,
 * we need to make sure that any previously set values are updated.
 *
 * \param tdata The message where the Remote-Party-ID header is
 * \param hdr The header on which the parameters are being added
 * \param id The identification information used to determine privacy
 */
static void add_privacy_params(pjsip_tx_data *tdata, pjsip_fromto_hdr *hdr, const struct ast_party_id *id)
{
	static const pj_str_t privacy_str = { "privacy", 7 };
	static const pj_str_t screen_str = { "screen", 6 };
	static const pj_str_t privacy_full_str = { "full", 4 };
	static const pj_str_t privacy_off_str = { "off", 3 };
	static const pj_str_t screen_yes_str = { "yes", 3 };
	static const pj_str_t screen_no_str = { "no", 2 };
	pjsip_param *old_privacy;
	pjsip_param *old_screen;
	pjsip_param *privacy;
	pjsip_param *screen;
	int presentation;

	old_privacy = pjsip_param_find(&hdr->other_param, &privacy_str);
	old_screen = pjsip_param_find(&hdr->other_param, &screen_str);

	if (!old_privacy) {
		privacy = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
		privacy->name = privacy_str;
		pj_list_insert_before(&hdr->other_param, privacy);
	} else {
		privacy = old_privacy;
	}

	if (!old_screen) {
		screen = PJ_POOL_ALLOC_T(tdata->pool, pjsip_param);
		screen->name = screen_str;
		pj_list_insert_before(&hdr->other_param, screen);
	} else {
		screen = old_screen;
	}

	presentation = ast_party_id_presentation(id);
	if ((presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
		privacy->value = privacy_off_str;
	} else {
		privacy->value = privacy_full_str;
	}
	if ((presentation & AST_PRES_NUMBER_TYPE) == AST_PRES_USER_NUMBER_PASSED_SCREEN) {
		screen->value = screen_yes_str;
	} else {
		screen->value = screen_no_str;
	}
}
/*!
 * \internal
 * \brief Add a Privacy header to an outbound message
 *
 * When sending a P-Asserted-Identity header, if privacy is requested, then we
 * will need to indicate such by adding a Privacy header. Similarly, if no
 * privacy is requested, and a Privacy header already exists on the message,
 * then the old Privacy header should be removed.
 *
 * \param tdata The outbound message to add the Privacy header to
 * \param id The id information used to determine privacy
 */
static void add_privacy_header(pjsip_tx_data *tdata, const struct ast_party_id *id)
{
	static const pj_str_t pj_privacy_name = { "Privacy", 7 };
	static const pj_str_t pj_privacy_value = { "id", 2 };
	pjsip_hdr *old_privacy;

	old_privacy = pjsip_msg_find_hdr_by_name(tdata->msg, &pj_privacy_name, NULL);

	if ((ast_party_id_presentation(id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
		if (old_privacy) {
			pj_list_erase(old_privacy);
		}
	} else if (!old_privacy) {
		pjsip_generic_string_hdr *privacy_hdr = pjsip_generic_string_hdr_create(
				tdata->pool, &pj_privacy_name, &pj_privacy_value);
		pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)privacy_hdr);
	}
}
/*!
 * \internal
 * \brief Session supplement callback for outgoing INVITE requests
 *
 * For an initial INVITE request, we may change the From header to appropriately
 * reflect the identity information. On all INVITEs (initial and reinvite) we may
 * add other identity headers such as P-Asserted-Identity and Remote-Party-ID based
 * on configuration and privacy settings
 *
 * \param session The session on which the INVITE will be sent
 * \param tdata The outbound INVITE request
 */
static void caller_id_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
{
	struct ast_party_id effective_id;
	struct ast_party_id connected_id;

	if (!session->channel) {
		return;
	}

	/* Must do a deep copy unless we hold the channel lock the entire time. */
	ast_party_id_init(&connected_id);
	ast_channel_lock(session->channel);
	effective_id = ast_channel_connected_effective_id(session->channel);
	ast_party_id_copy(&connected_id, &effective_id);
	ast_channel_unlock(session->channel);

	if (session->inv_session->state < PJSIP_INV_STATE_CONFIRMED) {
		/* Only change the From header on the initial outbound INVITE. Switching it
		 * mid-call might confuse some UAs.
		 */
		pjsip_fromto_hdr *from;
		pjsip_dialog *dlg;

		from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, tdata->msg->hdr.next);
		dlg = session->inv_session->dlg;

		if (ast_strlen_zero(session->endpoint->fromuser)
			&& (session->endpoint->id.trust_outbound
				|| (ast_party_id_presentation(&connected_id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED)) {
			modify_id_header(tdata->pool, from, &connected_id);
			modify_id_header(dlg->pool, dlg->local.info, &connected_id);
		}

		ast_sip_add_usereqphone(session->endpoint, tdata->pool, from->uri);
		ast_sip_add_usereqphone(session->endpoint, dlg->pool, dlg->local.info->uri);
	}
	add_id_headers(session, tdata, &connected_id);
	ast_party_id_free(&connected_id);
}
Пример #6
0
static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length,
									int exact, size_t *var_len, WriteMethod **write_method)
{
	static unsigned long long_ret;
	static u_char bits_ret[2];
	static char string_ret[256];
	struct ast_channel *chan, *bridge;
	struct timeval tval;
	u_char *ret = NULL;
	int i, bit;
	struct ast_str *out = ast_str_alloca(2048);
	struct ast_channel_iterator *iter;

	if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
		return NULL;

	i = name[*length - 1] - 1;

	if (!(iter = ast_channel_iterator_all_new())) {
		return NULL;
	}

	while ((chan = ast_channel_iterator_next(iter)) && i) {
		ast_channel_unref(chan);
		i--;
	}

	iter = ast_channel_iterator_destroy(iter);

	if (chan == NULL) {
		return NULL;
	}

	*var_len = sizeof(long_ret);

	ast_channel_lock(chan);

	switch (vp->magic) {
	case ASTCHANINDEX:
		long_ret = name[*length - 1];
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANNAME:
		if (!ast_strlen_zero(ast_channel_name(chan))) {
			ast_copy_string(string_ret, ast_channel_name(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANLANGUAGE:
		if (!ast_strlen_zero(ast_channel_language(chan))) {
			ast_copy_string(string_ret, ast_channel_language(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANTYPE:
		ast_copy_string(string_ret, ast_channel_tech(chan)->type, sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMUSICCLASS:
		if (!ast_strlen_zero(ast_channel_musicclass(chan))) {
			ast_copy_string(string_ret, ast_channel_musicclass(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANBRIDGE:
		if ((bridge = ast_bridged_channel(chan)) != NULL) {
			ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANMASQ:
		if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) {
			ast_copy_string(string_ret, ast_channel_name(ast_channel_masq(chan)), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANMASQR:
		if (ast_channel_masqr(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masqr(chan)))) {
			ast_copy_string(string_ret, ast_channel_name(ast_channel_masqr(chan)), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANWHENHANGUP:
		if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
			gettimeofday(&tval, NULL);
			long_ret = difftime(ast_channel_whentohangup(chan)->tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
			ret= (u_char *)&long_ret;
		}
		break;
	case ASTCHANAPP:
		if (ast_channel_appl(chan)) {
			ast_copy_string(string_ret, ast_channel_appl(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANDATA:
		if (ast_channel_data(chan)) {
			ast_copy_string(string_ret, ast_channel_data(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCONTEXT:
		ast_copy_string(string_ret, ast_channel_context(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMACROCONTEXT:
		ast_copy_string(string_ret, ast_channel_macrocontext(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMACROEXTEN:
		ast_copy_string(string_ret, ast_channel_macroexten(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMACROPRI:
		long_ret = ast_channel_macropriority(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANEXTEN:
		ast_copy_string(string_ret, ast_channel_exten(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANPRI:
		long_ret = ast_channel_priority(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANACCOUNTCODE:
		if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
			ast_copy_string(string_ret, ast_channel_accountcode(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANFORWARDTO:
		if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
			ast_copy_string(string_ret, ast_channel_call_forward(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANUNIQUEID:
		ast_copy_string(string_ret, ast_channel_uniqueid(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANCALLGROUP:
		long_ret = ast_channel_callgroup(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANPICKUPGROUP:
		long_ret = ast_channel_pickupgroup(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANSTATE:
		long_ret = ast_channel_state(chan) & 0xffff;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANMUTED:
		long_ret = ast_channel_state(chan) & AST_STATE_MUTE ? 1 : 2;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANRINGS:
		long_ret = ast_channel_rings(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDDNID:
		if (ast_channel_dialed(chan)->number.str) {
			ast_copy_string(string_ret, ast_channel_dialed(chan)->number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDNUM:
		if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
			ast_copy_string(string_ret, ast_channel_caller(chan)->id.number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDNAME:
		if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
			ast_copy_string(string_ret, ast_channel_caller(chan)->id.name.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDANI:
		if (ast_channel_caller(chan)->ani.number.valid && ast_channel_caller(chan)->ani.number.str) {
			ast_copy_string(string_ret, ast_channel_caller(chan)->ani.number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDRDNIS:
		if (ast_channel_redirecting(chan)->from.number.valid && ast_channel_redirecting(chan)->from.number.str) {
			ast_copy_string(string_ret, ast_channel_redirecting(chan)->from.number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDPRES:
		long_ret = ast_party_id_presentation(&ast_channel_caller(chan)->id);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDANI2:
		long_ret = ast_channel_caller(chan)->ani2;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDTON:
		long_ret = ast_channel_caller(chan)->id.number.plan;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDTNS:
		long_ret = ast_channel_dialed(chan)->transit_network_select;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANAMAFLAGS:
		long_ret = ast_channel_amaflags(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANADSI:
		long_ret = ast_channel_adsicpe(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANTONEZONE:
		if (ast_channel_zone(chan)) {
			ast_copy_string(string_ret, ast_channel_zone(chan)->country, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANHANGUPCAUSE:
		long_ret = ast_channel_hangupcause(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANVARIABLES:
		if (pbx_builtin_serialize_variables(chan, &out)) {
			*var_len = ast_str_strlen(out);
			ret = (u_char *)ast_str_buffer(out);
		}
		break;
	case ASTCHANFLAGS:
		bits_ret[0] = 0;
		for (bit = 0; bit < 8; bit++)
			bits_ret[0] |= ((ast_channel_flags(chan)->flags & (1 << bit)) >> bit) << (7 - bit);
		bits_ret[1] = 0;
		for (bit = 0; bit < 8; bit++)
			bits_ret[1] |= (((ast_channel_flags(chan)->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
		*var_len = 2;
		ret = bits_ret;
		break;
	case ASTCHANTRANSFERCAP:
		long_ret = ast_channel_transfercapability(chan);
		ret = (u_char *)&long_ret;
	default:
		break;
	}

	ast_channel_unlock(chan);
	chan = ast_channel_unref(chan);

	return ret;
}
Пример #7
0
struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
{
	struct ast_channel_snapshot *snapshot;
	struct ast_bridge *bridge;
	char nativeformats[256];
	struct ast_str *write_transpath = ast_str_alloca(256);
	struct ast_str *read_transpath = ast_str_alloca(256);
	struct ast_party_id effective_connected_id;
	struct ast_callid *callid;

	/* no snapshots for dummy channels */
	if (!ast_channel_tech(chan)) {
		return NULL;
	}

	snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor);
	if (!snapshot || ast_string_field_init(snapshot, 1024)) {
		ao2_cleanup(snapshot);
		return NULL;
	}

	ast_string_field_set(snapshot, name, ast_channel_name(chan));
	ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type);
	ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));
	ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));
	ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));
	ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));
	ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));
	ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));
	if (ast_channel_appl(chan)) {
		ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
	}
	if (ast_channel_data(chan)) {
		ast_string_field_set(snapshot, data, ast_channel_data(chan));
	}
	ast_string_field_set(snapshot, context, ast_channel_context(chan));
	ast_string_field_set(snapshot, exten, ast_channel_exten(chan));

	ast_string_field_set(snapshot, caller_name,
		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
	ast_string_field_set(snapshot, caller_number,
		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
	ast_string_field_set(snapshot, caller_dnid, S_OR(ast_channel_dialed(chan)->number.str, ""));
	ast_string_field_set(snapshot, caller_subaddr,
		S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));
	ast_string_field_set(snapshot, dialed_subaddr,
		S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
	ast_string_field_set(snapshot, caller_ani,
		S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));
	ast_string_field_set(snapshot, caller_rdnis,
		S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));
	ast_string_field_set(snapshot, caller_dnid,
		S_OR(ast_channel_dialed(chan)->number.str, ""));

	ast_string_field_set(snapshot, connected_name,
		S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
	ast_string_field_set(snapshot, connected_number,
		S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
	ast_string_field_set(snapshot, language, ast_channel_language(chan));

	if ((bridge = ast_channel_get_bridge(chan))) {
		ast_string_field_set(snapshot, bridgeid, bridge->uniqueid);
		ao2_cleanup(bridge);
	}

	ast_string_field_set(snapshot, nativeformats, ast_getformatname_multiple(nativeformats, sizeof(nativeformats),
		ast_channel_nativeformats(chan)));
	ast_string_field_set(snapshot, readformat, ast_getformatname(ast_channel_readformat(chan)));
	ast_string_field_set(snapshot, writeformat, ast_getformatname(ast_channel_writeformat(chan)));
	ast_string_field_set(snapshot, writetrans, ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath));
	ast_string_field_set(snapshot, readtrans, ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath));

	effective_connected_id = ast_channel_connected_effective_id(chan);
	ast_string_field_set(snapshot, effective_name,
		S_COR(effective_connected_id.name.valid, effective_connected_id.name.str, ""));
	ast_string_field_set(snapshot, effective_number,
		S_COR(effective_connected_id.number.valid, effective_connected_id.number.str, ""));

	if ((callid = ast_channel_callid(chan))) {
		ast_callid_strnprint(snapshot->callid, sizeof(snapshot->callid), callid);
		ast_callid_unref(callid);
	}

	snapshot->creationtime = ast_channel_creationtime(chan);
	snapshot->hanguptime = *(ast_channel_whentohangup(chan));
	snapshot->state = ast_channel_state(chan);
	snapshot->priority = ast_channel_priority(chan);
	snapshot->amaflags = ast_channel_amaflags(chan);
	snapshot->hangupcause = ast_channel_hangupcause(chan);
	ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);
	snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
	snapshot->callgroup = ast_channel_callgroup(chan);
	snapshot->pickupgroup = ast_channel_pickupgroup(chan);
	ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan));

	snapshot->manager_vars = ast_channel_get_manager_vars(chan);
	snapshot->channel_vars = ast_channel_get_vars(chan);
	snapshot->tech_properties = ast_channel_tech(chan)->properties;

	return snapshot;
}