示例#1
0
static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{
	struct frame_trace_data *framedata;
	struct ast_datastore *datastore = NULL;
	struct ast_framehook_interface interface = {
		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
		.event_cb = hook_event_cb,
		.destroy_cb = hook_destroy_cb,
	};
	int i = 0;

	if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
		return 0;
	}

	interface.data = framedata;

	if (!strcasecmp(data, "black")) {
		framedata->list_type = 1;
	}
	for (i = 0; i < ARRAY_LEN(frametype2str); i++) {
		if (strcasestr(value, frametype2str[i].str)) {
			framedata->values[i] = 1;
		}
	}

	ast_channel_lock(chan);
	i = ast_framehook_attach(chan, &interface);
	if (i >= 0) {
		int *id;
		if ((datastore = ast_channel_datastore_find(chan, &frame_trace_datastore, NULL))) {
			id = datastore->data;
			ast_framehook_detach(chan, *id);
			ast_channel_datastore_remove(chan, datastore);
		}

		if (!(datastore = ast_datastore_alloc(&frame_trace_datastore, NULL))) {
			ast_framehook_detach(chan, i);
			ast_channel_unlock(chan);
			return 0;
		}

		if (!(id = ast_calloc(1, sizeof(int)))) {
			ast_datastore_free(datastore);
			ast_framehook_detach(chan, i);
			ast_channel_unlock(chan);
			return 0;
		}

		*id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
		datastore->data = id;
		ast_channel_datastore_add(chan, datastore);
	}
	ast_channel_unlock(chan);

	return 0;
}
示例#2
0
static void t38_masq(void *data, int framehook_id,
        struct ast_channel *old_chan, struct ast_channel *new_chan)
{
	if (ast_channel_tech(old_chan) == ast_channel_tech(new_chan)) {
		return;
	}

	/* This framehook is only applicable to PJSIP channels */
	ast_framehook_detach(new_chan, framehook_id);
}
/*! \brief Function called to attach T.38 framehook to channel when appropriate */
static void t38_attach_framehook(struct ast_sip_session *session)
{
	int framehook_id;
	struct ast_datastore *datastore = NULL;
	static struct ast_framehook_interface hook = {
		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
		.event_cb = t38_framehook,
		.consume_cb = t38_consume,
		.chan_fixup_cb = t38_masq,
		.chan_breakdown_cb = t38_masq,
	};

	/* If the channel's already gone, bail */
	if (!session->channel) {
		return;
	}

	/* Only attach the framehook if t38 is enabled for the endpoint */
	if (!session->endpoint->media.t38.enabled) {
		return;
	}

	/* Skip attaching the framehook if the T.38 datastore already exists for the channel */
	ast_channel_lock(session->channel);
	if ((datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore, NULL))) {
		ast_channel_unlock(session->channel);
		return;
	}
	ast_channel_unlock(session->channel);

	framehook_id = ast_framehook_attach(session->channel, &hook);
	if (framehook_id < 0) {
		ast_log(LOG_WARNING, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
			ast_channel_name(session->channel));
		return;
	}

	ast_channel_lock(session->channel);
	datastore = ast_datastore_alloc(&t38_framehook_datastore, NULL);
	if (!datastore) {
		ast_log(LOG_ERROR, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
			ast_channel_name(session->channel));
		ast_framehook_detach(session->channel, framehook_id);
		ast_channel_unlock(session->channel);
		return;
	}

	ast_channel_datastore_add(session->channel, datastore);
	ast_channel_unlock(session->channel);
}
示例#4
0
/*! \brief Helper function which adds frame hook to bridge channel */
static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
{
	struct native_rtp_bridge_data *data = ao2_alloc(sizeof(*data), NULL);
	static struct ast_framehook_interface hook = {
		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
		.event_cb = native_rtp_framehook,
		.destroy_cb = __ao2_cleanup,
		.consume_cb = native_rtp_framehook_consume,
		.disable_inheritance = 1,
	};

	if (!data) {
		return -1;
	}

	ast_channel_lock(bridge_channel->chan);
	hook.data = ao2_bump(data);
	data->id = ast_framehook_attach(bridge_channel->chan, &hook);
	ast_channel_unlock(bridge_channel->chan);
	if (data->id < 0) {
		/* We need to drop both the reference we hold, and the one the framehook would hold */
		ao2_ref(data, -2);
		return -1;
	}

	bridge_channel->tech_pvt = data;

	return 0;
}

/*! \brief Helper function which removes frame hook from bridge channel */
static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
{
	RAII_VAR(struct native_rtp_bridge_data *, data, bridge_channel->tech_pvt, ao2_cleanup);

	if (!data) {
		return;
	}

	ast_channel_lock(bridge_channel->chan);
	ast_framehook_detach(bridge_channel->chan, data->id);
	data->detached = 1;
	ast_channel_unlock(bridge_channel->chan);
	bridge_channel->tech_pvt = NULL;
}
示例#5
0
void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_conf, int prefer_existing)
{
	struct jb_framedata *framedata;
	struct ast_datastore *datastore = NULL;
	struct ast_framehook_interface interface = {
		.version = AST_FRAMEHOOK_INTERFACE_VERSION,
		.event_cb = hook_event_cb,
		.destroy_cb = hook_destroy_cb,
	};
	int i = 0;

	/* If disabled, strip any existing jitterbuffer and don't replace it. */
	if (!strcasecmp(jb_conf->impl, "disabled")) {
		int *id;
		ast_channel_lock(chan);
		if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
			id = datastore->data;
			ast_framehook_detach(chan, *id);
			ast_channel_datastore_remove(chan, datastore);
			ast_datastore_free(datastore);
		}
		ast_channel_unlock(chan);
		return;
	}

	if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
		return;
	}

	if (jb_framedata_init(framedata, jb_conf)) {
		jb_framedata_destroy(framedata);
		return;
	}

	interface.data = framedata;

	ast_channel_lock(chan);
	i = ast_framehook_attach(chan, &interface);
	if (i >= 0) {
		int *id;
		if ((datastore = ast_channel_datastore_find(chan, &jb_datastore, NULL))) {
			/* There is already a jitterbuffer on the channel. */
			if (prefer_existing) {
				/* We prefer the existing jitterbuffer, so remove the new one and keep the old one. */
				ast_framehook_detach(chan, i);
				ast_channel_unlock(chan);
				return;
			}
			/* We prefer the new jitterbuffer, so strip the old one. */
			id = datastore->data;
			ast_framehook_detach(chan, *id);
			ast_channel_datastore_remove(chan, datastore);
			ast_datastore_free(datastore);
		}

		if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) {
			ast_framehook_detach(chan, i);
			ast_channel_unlock(chan);
			return;
		}

		if (!(id = ast_calloc(1, sizeof(int)))) {
			ast_datastore_free(datastore);
			ast_framehook_detach(chan, i);
			ast_channel_unlock(chan);
			return;
		}

		*id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
		datastore->data = id;
		ast_channel_datastore_add(chan, datastore);

		ast_channel_set_fd(chan, AST_JITTERBUFFER_FD, framedata->timer_fd);
	} else {
		jb_framedata_destroy(framedata);
		framedata = NULL;
	}
	ast_channel_unlock(chan);
}