예제 #1
0
static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
	struct local_pvt *p = ast_channel_tech_pvt(newchan);

	if (!p) {
		return -1;
	}

	ao2_lock(p);

	if ((p->owner != oldchan) && (p->chan != oldchan)) {
		ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
		ao2_unlock(p);
		return -1;
	}
	if (p->owner == oldchan) {
		p->owner = newchan;
	} else {
		p->chan = newchan;
	}

	/* Do not let a masquerade cause a Local channel to be bridged to itself! */
	if (!ast_check_hangup(newchan) && ((p->owner && ast_channel_internal_bridged_channel(p->owner) == p->chan) || (p->chan && ast_channel_internal_bridged_channel(p->chan) == p->owner))) {
		ast_log(LOG_WARNING, "You can not bridge a Local channel to itself!\n");
		ao2_unlock(p);
		ast_queue_hangup(newchan);
		return -1;
	}

	ao2_unlock(p);
	return 0;
}
예제 #2
0
static int manager_optimize_away(struct mansession *s, const struct message *m)
{
	const char *channel;
	struct local_pvt *p;
	struct local_pvt *found;
	struct ast_channel *chan;

	channel = astman_get_header(m, "Channel");
	if (ast_strlen_zero(channel)) {
		astman_send_error(s, m, "'Channel' not specified.");
		return 0;
	}

	chan = ast_channel_get_by_name(channel);
	if (!chan) {
		astman_send_error(s, m, "Channel does not exist.");
		return 0;
	}

	p = ast_channel_tech_pvt(chan);
	ast_channel_unref(chan);

	found = p ? ao2_find(locals, p, 0) : NULL;
	if (found) {
		ao2_lock(found);
		ast_clear_flag(&found->base, AST_UNREAL_NO_OPTIMIZATION);
		ao2_unlock(found);
		ao2_ref(found, -1);
		astman_send_ack(s, m, "Queued channel to be optimized away");
	} else {
		astman_send_error(s, m, "Unable to find channel");
	}

	return 0;
}
예제 #3
0
static int local_write(struct ast_channel *ast, struct ast_frame *f)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int res = -1;
	int isoutbound;

	if (!p) {
		return -1;
	}

	/* Just queue for delivery to the other side */
	ao2_ref(p, 1); /* ref for local_queue_frame */
	ao2_lock(p);
	isoutbound = IS_OUTBOUND(ast, p);

	if (isoutbound
		&& (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
		check_bridge(ast, p);
	}

	if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) {
		res = local_queue_frame(p, isoutbound, f, ast, 1);
	} else {
		ast_debug(1, "Not posting to '%s' queue since already masqueraded out\n",
			ast_channel_name(ast));
		res = 0;
	}
	ao2_unlock(p);
	ao2_ref(p, -1);

	return res;
}
예제 #4
0
int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
{
	struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
	int res = -1;

	if (!p) {
		return -1;
	}

	/* Just queue for delivery to the other side */
	ao2_ref(p, 1);
	ao2_lock(p);
	switch (f->frametype) {
	case AST_FRAME_VOICE:
	case AST_FRAME_VIDEO:
		if (got_optimized_out(ast, p)) {
			break;
		}
		/* fall through */
	default:
		res = unreal_queue_frame(p, AST_UNREAL_IS_OUTBOUND(ast, p), f, ast, 1);
		break;
	}
	ao2_unlock(p);
	ao2_ref(p, -1);

	return res;
}
예제 #5
0
int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
{
	struct local_pvt *p;
	struct local_pvt *found;
	int res = -1;

	/* Sanity checks. */
	if (!ast || !masq) {
		return -1;
	}

	ast_channel_lock(ast);
	p = ast_channel_tech_pvt(ast);
	ast_channel_unlock(ast);

	found = p ? ao2_find(locals, p, 0) : NULL;
	if (found) {
		ao2_lock(found);
		if (found->type == LOCAL_CALL_ACTION_DIALPLAN
			&& found->base.owner
			&& found->base.chan
			&& !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
			ast_channel_ref(masq);
			found->type = LOCAL_CALL_ACTION_MASQUERADE;
			found->action.masq = masq;
			res = 0;
		}
		ao2_unlock(found);
		ao2_ref(found, -1);
	}

	return res;
}
예제 #6
0
int ast_unreal_answer(struct ast_channel *ast)
{
	struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
	int isoutbound;
	int res = -1;

	if (!p) {
		return -1;
	}

	ao2_ref(p, 1);
	ao2_lock(p);
	isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
	if (isoutbound) {
		/* Pass along answer since somebody answered us */
		struct ast_frame answer = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };

		res = unreal_queue_frame(p, isoutbound, &answer, ast, 1);
	} else {
		ast_log(LOG_WARNING, "Huh?  %s is being asked to answer?\n",
			ast_channel_name(ast));
	}
	ao2_unlock(p);
	ao2_ref(p, -1);
	return res;
}
예제 #7
0
/*! \brief Hangup a call through the local proxy channel */
static int local_hangup(struct ast_channel *ast)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int res;

	if (!p) {
		return -1;
	}

	/* give the pvt a ref to fulfill calling requirements. */
	ao2_ref(p, +1);
	res = ast_unreal_hangup(&p->base, ast);
	if (!res) {
		int unlink;

		ao2_lock(p);
		unlink = !p->base.owner && !p->base.chan;
		ao2_unlock(p);
		if (unlink) {
			ao2_unlink(locals, p);
		}
	}
	ao2_ref(p, -1);

	return res;
}
예제 #8
0
struct ast_channel *ast_local_get_peer(struct ast_channel *ast)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	struct local_pvt *found;
	struct ast_channel *peer;

	if (!p) {
		return NULL;
	}

	found = p ? ao2_find(locals, p, 0) : NULL;
	if (!found) {
		/* ast is either not a local channel or it has alredy been hungup */
		return NULL;
	}
	ao2_lock(found);
	if (ast == p->base.owner) {
		peer = p->base.chan;
	} else if (ast == p->base.chan) {
		peer = p->base.owner;
	} else {
		peer = NULL;
	}
	if (peer) {
		ast_channel_ref(peer);
	}
	ao2_unlock(found);
	ao2_ref(found, -1);
	return peer;
}
예제 #9
0
/*! \brief Return the bridged channel of a Local channel */
static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
{
	struct local_pvt *p = ast_channel_tech_pvt(bridge);
	struct ast_channel *bridged = bridge;

	if (!p) {
		ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning <none>\n",
			ast_channel_name(chan), ast_channel_name(bridge));
		return NULL;
	}

	ao2_lock(p);

	if (ast_test_flag(p, LOCAL_BRIDGE)) {
		/* Find the opposite channel */
		bridged = (bridge == p->owner ? p->chan : p->owner);

		/* Now see if the opposite channel is bridged to anything */
		if (!bridged) {
			bridged = bridge;
		} else if (ast_channel_internal_bridged_channel(bridged)) {
			bridged = ast_channel_internal_bridged_channel(bridged);
		}
	}

	ao2_unlock(p);

	return bridged;
}
예제 #10
0
/* Called with ast locked */
static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen)
{
	int res = 0;
	struct local_pvt *p = NULL;
	struct ast_channel *otherchan = NULL;
	ast_chan_write_info_t *write_info;

	if (option != AST_OPTION_CHANNEL_WRITE) {
		return -1;
	}

	write_info = data;

	if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
		ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
		return -1;
	}

	if (!strcmp(write_info->function, "CHANNEL")
		&& !strncasecmp(write_info->data, "hangup_handler_", 15)) {
		/* Block CHANNEL(hangup_handler_xxx) writes to the other local channel. */
		return 0;
	}

	/* get the tech pvt */
	if (!(p = ast_channel_tech_pvt(ast))) {
		return -1;
	}
	ao2_ref(p, 1);
	ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */

	/* get the channel we are supposed to write to */
	ao2_lock(p);
	otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
	if (!otherchan || otherchan == write_info->chan) {
		res = -1;
		otherchan = NULL;
		ao2_unlock(p);
		goto setoption_cleanup;
	}
	ast_channel_ref(otherchan);

	/* clear the pvt lock before grabbing the channel */
	ao2_unlock(p);

	ast_channel_lock(otherchan);
	res = write_info->write_fn(otherchan, write_info->function, write_info->data, write_info->value);
	ast_channel_unlock(otherchan);

setoption_cleanup:
	if (p) {
		ao2_ref(p, -1);
	}
	if (otherchan) {
		ast_channel_unref(otherchan);
	}
	ast_channel_lock(ast); /* Lock back before we leave */
	return res;
}
예제 #11
0
/*! \brief Function called when we should actually call the destination */
static int multicast_rtp_call(struct ast_channel *ast, const char *dest, int timeout)
{
	struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast);

	ast_queue_control(ast, AST_CONTROL_ANSWER);

	return ast_rtp_instance_activate(instance);
}
예제 #12
0
/*!
 * \brief handler for incoming calls. Either autoanswer, or start ringing
 */
static int oss_call(struct ast_channel *c, const char *dest, int timeout)
{
	struct chan_oss_pvt *o = ast_channel_tech_pvt(c);
	struct ast_frame f = { AST_FRAME_CONTROL, };
	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(name);
		AST_APP_ARG(flags);
	);
예제 #13
0
/*!
 * \brief Implements function 'read' callback.
 *
 * Valid actions are 'read' and 'remove'.
 */
static int func_read_header(struct ast_channel *chan, const char *function, char *data,
							char *buf, size_t len)
{
	struct ast_sip_channel_pvt *channel = chan ? ast_channel_tech_pvt(chan) : NULL;
	struct header_data header_data;
	int number;
	AST_DECLARE_APP_ARGS(args,
						 AST_APP_ARG(action);
						 AST_APP_ARG(header_name); AST_APP_ARG(header_number););
예제 #14
0
/*!
 * \internal \brief Handle reading RTP information
 */
static int channel_read_rtp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
{
	struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
	struct chan_pjsip_pvt *pvt;
	struct ast_sip_session_media *media = NULL;
	struct ast_sockaddr addr;

	if (!channel) {
		ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
		return -1;
	}

	pvt = channel->pvt;
	if (!pvt) {
		ast_log(AST_LOG_WARNING, "Channel %s has no chan_pjsip pvt!\n", ast_channel_name(chan));
		return -1;
	}

	if (ast_strlen_zero(type)) {
		ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
		return -1;
	}

	if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
		media = pvt->media[SIP_MEDIA_AUDIO];
	} else if (!strcmp(field, "video")) {
		media = pvt->media[SIP_MEDIA_VIDEO];
	} else {
		ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
		return -1;
	}

	if (!media || !media->rtp) {
		ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
			ast_channel_name(chan), S_OR(field, "audio"));
		return -1;
	}

	if (!strcmp(type, "src")) {
		ast_rtp_instance_get_local_address(media->rtp, &addr);
		ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
	} else if (!strcmp(type, "dest")) {
		ast_rtp_instance_get_remote_address(media->rtp, &addr);
		ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
	} else if (!strcmp(type, "direct")) {
		ast_copy_string(buf, ast_sockaddr_stringify(&media->direct_media_addr), buflen);
	} else if (!strcmp(type, "secure")) {
		snprintf(buf, buflen, "%d", media->srtp ? 1 : 0);
	} else if (!strcmp(type, "hold")) {
		snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
	} else {
		ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
		return -1;
	}

	return 0;
}
예제 #15
0
/*! \brief Function called when we should hang the channel up */
static int multicast_rtp_hangup(struct ast_channel *ast)
{
	struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast);

	ast_rtp_instance_destroy(instance);

	ast_channel_tech_pvt_set(ast, NULL);

	return 0;
}
예제 #16
0
int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
{
	struct sip_pvt *p = ast_channel_tech_pvt(chan);
	char *parse = ast_strdupa(preparse);
	int res = 0;
	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(param);
		AST_APP_ARG(type);
		AST_APP_ARG(field);
	);
예제 #17
0
static int respoke_metadata_function_read(struct ast_channel *chan,
	const char *cmd, char *data, struct ast_str **buf, ssize_t len)
{
	char *parsed_data = ast_strdupa(data);
	const char *key;
	const struct respoke_session *session = chan ? ast_channel_tech_pvt(chan) : NULL;
	struct ast_json *value_json;
	int res = -1;

	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(key);
	);
예제 #18
0
/*! \brief Frame hook callback for T.38 related stuff */
static struct ast_frame *t38_framehook(struct ast_channel *chan, struct ast_frame *f,
	enum ast_framehook_event event, void *data)
{
	struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);

	if (event == AST_FRAMEHOOK_EVENT_READ) {
		f = t38_framehook_read(channel->session, f);
	} else if (event == AST_FRAMEHOOK_EVENT_WRITE) {
		f = t38_framehook_write(channel->session, f);
	}

	return f;
}
예제 #19
0
static int snoop_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
	struct stasis_app_snoop *snoop = ast_channel_tech_pvt(oldchan);

	if (snoop->chan != oldchan) {
		return -1;
	}

	ast_channel_unref(snoop->chan);
	ast_channel_ref(newchan);
	snoop->chan = newchan;

	return 0;
}
예제 #20
0
static int media_hangup(struct ast_channel *ast)
{
	struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
	int res;

	if (!p) {
		return -1;
	}

	/* Give the pvt a ref to fulfill calling requirements. */
	ao2_ref(p, +1);
	res = ast_unreal_hangup(p, ast);
	ao2_ref(p, -1);

	return res;
}
예제 #21
0
/* Called with ast locked */
static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
{
	struct local_pvt *p;
	struct ast_channel *bridged = NULL;
	struct ast_channel *tmp = NULL;
	int res = 0;

	if (option != AST_OPTION_T38_STATE) {
		/* AST_OPTION_T38_STATE is the only supported option at this time */
		return -1;
	}

	/* for some reason the channel is not locked in channel.c when this function is called */
	if (!(p = ast_channel_tech_pvt(ast))) {
		return -1;
	}

	ao2_lock(p);
	if (!(tmp = IS_OUTBOUND(ast, p) ? p->owner : p->chan)) {
		ao2_unlock(p);
		return -1;
	}
	ast_channel_ref(tmp);
	ao2_unlock(p);
	ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */

	ast_channel_lock(tmp);
	if (!(bridged = ast_bridged_channel(tmp))) {
		res = -1;
		ast_channel_unlock(tmp);
		goto query_cleanup;
	}
	ast_channel_ref(bridged);
	ast_channel_unlock(tmp);

query_cleanup:
	if (bridged) {
		res = ast_channel_queryoption(bridged, option, data, datalen, 0);
		bridged = ast_channel_unref(bridged);
	}
	if (tmp) {
		tmp = ast_channel_unref(tmp);
	}
	ast_channel_lock(ast); /* Lock back before we leave */

	return res;
}
예제 #22
0
int sccpconf_announce_channel_push(struct ast_channel *ast, struct ast_bridge *bridge)
{
	struct ast_bridge_features *features;
	struct ast_channel *chan;
	struct announce_pvt *p = NULL;

	{
		ast_channel_lock(ast);
		p = ast_channel_tech_pvt(ast);
		if (!p) {
			ast_channel_unlock(ast);
			return -1;
		}
		ao2_ref(p, +1);
		chan = p->base.chan;
		if (!chan) {
			ast_channel_unlock(ast);
			ao2_cleanup(p);
			return -1;
		}
		ast_channel_ref(chan);
		ast_channel_unlock(ast);
	}

	features = ast_bridge_features_new();
	if (!features) {
		ast_channel_unref(chan);
		ao2_cleanup(p);
		return -1;
	}
	ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);

	// Impart the output channel into the bridge
	if (ast_bridge_impart(bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) {
		ast_bridge_features_destroy(features);
		ast_channel_unref(chan);
		ao2_cleanup(p);
		return -1;
	}
	ao2_lock(p);
	ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
	ao2_unlock(p);
	ao2_cleanup(p);
	return 0;
}
예제 #23
0
/*! \brief Callback function for writing to a Snoop whisper audiohook */
static int snoop_write(struct ast_channel *chan, struct ast_frame *frame)
{
	struct stasis_app_snoop *snoop = ast_channel_tech_pvt(chan);

	if (!snoop->whisper_active) {
		return 0;
	}

	ast_audiohook_lock(&snoop->whisper);
	if (snoop->whisper_direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
		ast_audiohook_write_frame(&snoop->whisper, AST_AUDIOHOOK_DIRECTION_READ, frame);
		ast_audiohook_write_frame(&snoop->whisper, AST_AUDIOHOOK_DIRECTION_WRITE, frame);
	} else {
		ast_audiohook_write_frame(&snoop->whisper, snoop->whisper_direction, frame);
	}
	ast_audiohook_unlock(&snoop->whisper);

	return 0;
}
예제 #24
0
int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
	struct ast_unreal_pvt *p = ast_channel_tech_pvt(newchan);
	struct ast_bridge *bridge_owner;
	struct ast_bridge *bridge_chan;

	if (!p) {
		return -1;
	}

	ao2_lock(p);

	if ((p->owner != oldchan) && (p->chan != oldchan)) {
		ast_log(LOG_WARNING, "Old channel %p wasn't %p or %p\n", oldchan, p->owner, p->chan);
		ao2_unlock(p);
		return -1;
	}
	if (p->owner == oldchan) {
		p->owner = newchan;
	} else {
		p->chan = newchan;
	}

	if (ast_check_hangup(newchan) || !p->owner || !p->chan) {
		ao2_unlock(p);
		return 0;
	}

	/* Do not let a masquerade cause an unreal channel to be bridged to itself! */
	bridge_owner = ast_channel_internal_bridge(p->owner);
	bridge_chan = ast_channel_internal_bridge(p->chan);
	if (bridge_owner && bridge_owner == bridge_chan) {
		ast_log(LOG_WARNING, "You can not bridge an unreal channel (%s) to itself!\n",
			ast_channel_name(newchan));
		ao2_unlock(p);
		ast_queue_hangup(newchan);
		return -1;
	}

	ao2_unlock(p);
	return 0;
}
예제 #25
0
int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
{
	struct local_pvt *p;
	struct local_pvt *found;
	int res = -1;

	/* Sanity checks. */
	if (!ast || !bridge) {
		ast_bridge_features_destroy(features);
		return -1;
	}

	ast_channel_lock(ast);
	p = ast_channel_tech_pvt(ast);
	ast_channel_unlock(ast);

	found = p ? ao2_find(locals, p, 0) : NULL;
	if (found) {
		ao2_lock(found);
		if (found->type == LOCAL_CALL_ACTION_DIALPLAN
			&& found->base.owner
			&& found->base.chan
			&& !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
			ao2_ref(bridge, +1);
			if (swap) {
				ast_channel_ref(swap);
			}
			found->type = LOCAL_CALL_ACTION_BRIDGE;
			found->action.bridge.join = bridge;
			found->action.bridge.swap = swap;
			found->action.bridge.features = features;
			res = 0;
		} else {
			ast_bridge_features_destroy(features);
		}
		ao2_unlock(found);
		ao2_ref(found, -1);
	}

	return res;
}
예제 #26
0
static int local_digit_begin(struct ast_channel *ast, char digit)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int res = -1;
	struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
	int isoutbound;

	if (!p) {
		return -1;
	}

	ao2_ref(p, 1); /* ref for local_queue_frame */
	ao2_lock(p);
	isoutbound = IS_OUTBOUND(ast, p);
	f.subclass.integer = digit;
	res = local_queue_frame(p, isoutbound, &f, ast, 0);
	ao2_unlock(p);
	ao2_ref(p, -1);

	return res;
}
예제 #27
0
/*! \brief Callback function for reading from a Snoop channel */
static struct ast_frame *snoop_read(struct ast_channel *chan)
{
	struct stasis_app_snoop *snoop = ast_channel_tech_pvt(chan);
	struct ast_frame *frame = NULL;

	/* If we fail to ack the timer OR if any active audiohooks are done hangup */
	if ((ast_timer_ack(snoop->timer, 1) < 0) ||
		(snoop->spy_active && snoop->spy.status != AST_AUDIOHOOK_STATUS_RUNNING) ||
		(snoop->whisper_active && snoop->whisper.status != AST_AUDIOHOOK_STATUS_RUNNING)) {
		return NULL;
	}

	/* Only get audio from the spy audiohook if it is active */
	if (snoop->spy_active) {
		ast_audiohook_lock(&snoop->spy);
		frame = ast_audiohook_read_frame(&snoop->spy, snoop->spy_samples, snoop->spy_direction, snoop->spy_format);
		ast_audiohook_unlock(&snoop->spy);
	}

	return frame ? frame : &ast_null_frame;
}
예제 #28
0
static int local_sendtext(struct ast_channel *ast, const char *text)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int res = -1;
	struct ast_frame f = { AST_FRAME_TEXT, };
	int isoutbound;

	if (!p) {
		return -1;
	}

	ao2_lock(p);
	ao2_ref(p, 1); /* ref for local_queue_frame */
	isoutbound = IS_OUTBOUND(ast, p);
	f.data.ptr = (char *) text;
	f.datalen = strlen(text) + 1;
	res = local_queue_frame(p, isoutbound, &f, ast, 0);
	ao2_unlock(p);
	ao2_ref(p, -1);
	return res;
}
예제 #29
0
static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int res = -1;
	struct ast_frame f = { AST_FRAME_HTML, };
	int isoutbound;

	if (!p) {
		return -1;
	}

	ao2_lock(p);
	ao2_ref(p, 1); /* ref for local_queue_frame */
	isoutbound = IS_OUTBOUND(ast, p);
	f.subclass.integer = subclass;
	f.data.ptr = (char *)data;
	f.datalen = datalen;
	res = local_queue_frame(p, isoutbound, &f, ast, 0);
	ao2_unlock(p);
	ao2_ref(p, -1);

	return res;
}
예제 #30
0
/* Called with ast locked */
int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
{
	struct ast_unreal_pvt *p;
	struct ast_channel *peer;
	struct ast_channel *other;
	int res = 0;

	if (option != AST_OPTION_T38_STATE) {
		/* AST_OPTION_T38_STATE is the only supported option at this time */
		return -1;
	}

	/* for some reason the channel is not locked in channel.c when this function is called */
	if (!(p = ast_channel_tech_pvt(ast))) {
		return -1;
	}

	ao2_lock(p);
	other = AST_UNREAL_IS_OUTBOUND(ast, p) ? p->owner : p->chan;
	if (!other) {
		ao2_unlock(p);
		return -1;
	}
	ast_channel_ref(other);
	ao2_unlock(p);
	ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */

	peer = ast_channel_bridge_peer(other);
	if (peer) {
		res = ast_channel_queryoption(peer, option, data, datalen, 0);
		ast_channel_unref(peer);
	}
	ast_channel_unref(other);
	ast_channel_lock(ast); /* Lock back before we leave */

	return res;
}