static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
{
	struct ast_channel *target = obj;/*!< Potential pickup target */
	struct ast_channel *chan = data;/*!< Channel wanting to pickup call */

	ast_channel_lock(target);
	if (chan != target && (ast_channel_pickupgroup(chan) & ast_channel_callgroup(target))
		&& ast_can_pickup(target)) {
		/* Return with the channel still locked on purpose */
		return CMP_MATCH | CMP_STOP;
	}
	ast_channel_unlock(target);

	return 0;
}
/* Attempt to pick up specified by partial channel name */ 
static int pickup_by_part(struct ast_channel *chan, const char *part)
{
	struct ast_channel *target;/*!< Potential pickup target */
	int res = -1;

	/* The found channel is already locked. */
	target = ast_channel_callback(find_by_part, NULL, (char *) part, 0);
	if (target) {
		res = ast_do_pickup(chan, target);
		ast_channel_unlock(target);
		target = ast_channel_unref(target);
	}

	return res;
}
Example #3
0
/*!
 * \brief after bridge callback for the dial bridge
 *
 * The only purpose of this callback is to ensure that the control structure's
 * bridge pointer is NULLed
 */
static void dial_bridge_after_cb(struct ast_channel *chan, void *data)
{
	struct stasis_app_control *control = data;
	struct ast_bridge_channel *bridge_channel;

	ast_channel_lock(chan);
	bridge_channel = ast_channel_get_bridge_channel(chan);
	ast_channel_unlock(chan);

	ast_debug(3, "Channel: <%s>  Reason: %d\n", ast_channel_name(control->channel), ast_channel_hangupcause(chan));

	stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel, __ao2_cleanup);

	control->bridge = NULL;
}
Example #4
0
static int speex_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
	struct ast_datastore *datastore = NULL;
	struct speex_info *si = NULL;
	struct speex_direction_info *sdi = NULL;

	if (!chan) {
		ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd);
		return -1;
	}

	ast_channel_lock(chan);
	if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
		ast_channel_unlock(chan);
		return -1;
	}
	ast_channel_unlock(chan);

	si = datastore->data;

	if (!strcasecmp(data, "tx"))
		sdi = si->tx;
	else if (!strcasecmp(data, "rx"))
		sdi = si->rx;
	else {
		ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data);
		return -1;
	}

	if (!strcasecmp(cmd, "agc"))
		snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0);
	else
		snprintf(buf, len, "%d", sdi ? sdi->denoise : 0);

	return 0;
}
/*! \brief The callback from the audiohook subsystem. We basically get a frame to have fun with */
static int mute_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
{
	struct ast_datastore *datastore = NULL;
	struct mute_information *mute = NULL;


	/* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
	if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
		return 0;
	}

	ast_channel_lock(chan);
	/* Grab datastore which contains our mute information */
	if (!(datastore = ast_channel_datastore_find(chan, &mute_datastore, NULL))) {
		ast_channel_unlock(chan);
		ast_debug(2, "Can't find any datastore to use. Bad. \n");
		return 0;
	}

	mute = datastore->data;


	/* If this is audio then allow them to increase/decrease the gains */
	if (frame->frametype == AST_FRAME_VOICE) {
		ast_debug(2, "Audio frame - direction %s  mute READ %s WRITE %s\n", direction == AST_AUDIOHOOK_DIRECTION_READ ? "read" : "write", mute->mute_read ? "on" : "off", mute->mute_write ? "on" : "off");

		/* Based on direction of frame grab the gain, and confirm it is applicable */
		if ((direction == AST_AUDIOHOOK_DIRECTION_READ && mute->mute_read) || (direction == AST_AUDIOHOOK_DIRECTION_WRITE && mute->mute_write)) {
			/* Ok, we just want to reset all audio in this frame. Keep NOTHING, thanks. */
			ast_frame_clear(frame);
		}
	}
	ast_channel_unlock(chan);

	return 0;
}
Example #6
0
static struct chanspy_ds *next_channel(struct ast_channel *chan,
	const struct ast_channel *last, const char *spec,
	const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
{
	struct ast_channel *this;
	char channel_name[AST_CHANNEL_NAME];
	static size_t PSEUDO_CHAN_LEN = 0;

	if (!PSEUDO_CHAN_LEN) {
		PSEUDO_CHAN_LEN = *dahdi_chan_name_len + strlen("/pseudo");
	}

redo:
	if (spec)
		this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
	else if (exten)
		this = ast_walk_channel_by_exten_locked(last, exten, context);
	else
		this = ast_channel_walk_locked(last);

	if (!this)
		return NULL;

	snprintf(channel_name, AST_CHANNEL_NAME, "%s/pseudo", dahdi_chan_name);
	if (!strncmp(this->name, channel_name, PSEUDO_CHAN_LEN)) {
		last = this;
		ast_channel_unlock(this);
		goto redo;
	} else if (this == chan) {
		last = this;
		ast_channel_unlock(this);
		goto redo;
	}

	return setup_chanspy_ds(this, chanspy_ds);
}
Example #7
0
static int bridgeadd_exec(struct ast_channel *chan, const char *data)
{
	struct ast_channel *c_ref;
	struct ast_bridge_features chan_features;
	struct ast_bridge *bridge;
	char *c_name;

	/* Answer the channel if needed */
	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_answer(chan);
	}

	if (!(c_ref = ast_channel_get_by_name_prefix(data, strlen(data)))) {
		ast_log(LOG_WARNING, "Channel %s not found\n", data);
		return -1;
	}

	c_name = ast_strdupa(ast_channel_name(c_ref));

	ast_channel_lock(c_ref);
	bridge = ast_channel_get_bridge(c_ref);
	ast_channel_unlock(c_ref);

	ast_channel_unref(c_ref);

	if (!bridge) {
		ast_log(LOG_WARNING, "Channel %s is not in a bridge\n", c_name);
		return -1;
	}

	ast_verb(3, "%s is joining %s in bridge %s\n", ast_channel_name(chan),
		c_name, bridge->uniqueid);

	if (ast_bridge_features_init(&chan_features)
		|| ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, 0)) {

		ast_log(LOG_WARNING, "%s failed to join %s in bridge %s\n", ast_channel_name(chan),
			 c_name, bridge->uniqueid);

		ast_bridge_features_cleanup(&chan_features);
		ao2_cleanup(bridge);
		return -1;
	}

	ast_bridge_features_cleanup(&chan_features);
	ao2_cleanup(bridge);
	return 0;
}
Example #8
0
static int find_by_mark(void *obj, void *arg, void *data, int flags)
{
	struct ast_channel *target = obj;/*!< Potential pickup target */
	const char *mark = data;
	const char *tmp;

	ast_channel_lock(target);
	tmp = pbx_builtin_getvar_helper(target, PICKUPMARK);
	if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) {
		/* Return with the channel still locked on purpose */
		return CMP_MATCH | CMP_STOP;
	}
	ast_channel_unlock(target);

	return 0;
}
Example #9
0
static int pickup_by_group(struct ast_channel *chan)
{
	struct ast_channel *target;/*!< Potential pickup target */
	int res = -1;

	/* The found channel is already locked. */
	target = ast_pickup_find_by_group(chan);
	if (target) {
		ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
		res = ast_do_pickup(chan, target);
		ast_channel_unlock(target);
		target = ast_channel_unref(target);
	}

	return res;
}
Example #10
0
/* Find channel for pick up specified by partial channel name */ 
static int find_by_part(void *obj, void *arg, void *data, int flags)
{
	struct ast_channel *target = obj;/*!< Potential pickup target */
	const char *part = data;
	int len = strlen(part);

	ast_channel_lock(target);
	if (len <= strlen(ast_channel_name(target)) && !strncmp(ast_channel_name(target), part, len)
		&& ast_can_pickup(target)) {
		/* Return with the channel still locked on purpose */
		return CMP_MATCH | CMP_STOP;
	}
	ast_channel_unlock(target);

	return 0;
}
Example #11
0
/*! \brief possibly uninitialize the video console.
 * Called at the end of a call, should reset the 'owner' field,
 * then possibly terminate the video thread if the gui has
 * not been started manually.
 * In practice, signal the thread and give it a bit of time to
 * complete, giving up if it gets stuck. Because uninit
 * is called from hangup with the channel locked, and the thread
 * uses the chan lock, we need to unlock here. This is unsafe,
 * and we should really use refcounts for the channels.
 */
void console_video_uninit(struct video_desc *env)
{
	int i, t = 100;	/* initial wait is shorter, than make it longer */
	if (env->stayopen == 0) {	/* in a call */
		env->shutdown = 1;
		for (i=0; env->shutdown && i < 10; i++) {
			if (env->owner)
				ast_channel_unlock(env->owner);
			usleep(t);
			t = 1000000;
			if (env->owner)
				ast_channel_lock(env->owner);
		}
	}
	env->owner = NULL;	/* this is unconditional */
}
Example #12
0
static char *handle_redirect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
	const char *name, *dest;
	struct ast_channel *chan;
	int res;

	switch (cmd) {
	case CLI_INIT:
		e->command = "channel redirect";
		e->usage = ""
		"Usage: channel redirect <channel> <[[context,]exten,]priority>\n"
		"    Redirect an active channel to a specified extension.\n";
		/*! \todo It would be nice to be able to redirect 2 channels at the same
		 *  time like you can with AMI redirect.  However, it is not possible to acquire
		 *  two channels without the potential for a deadlock with how ast_channel structs
		 *  are managed today.  Once ast_channel is a refcounted object, this command
		 *  will be able to support that. */
		return NULL;
	case CLI_GENERATE:
		return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
	}

	if (a->argc != e->args + 2) {
		return CLI_SHOWUSAGE;
	}

	name = a->argv[2];
	dest = a->argv[3];

	chan = ast_get_channel_by_name_locked(name);
	if (!chan) {
		ast_cli(a->fd, "Channel '%s' not found\n", name);
		return CLI_FAILURE;
	}

	res = ast_async_parseable_goto(chan, dest);

	ast_channel_unlock(chan);

	if (!res) {
		ast_cli(a->fd, "Channel '%s' successfully redirected to %s\n", name, dest);
	} else {
		ast_cli(a->fd, "Channel '%s' failed to be redirected to %s\n", name, dest);
	}

	return res ? CLI_FAILURE : CLI_SUCCESS;
}
static void limits_interval_playback(struct ast_bridge_channel *bridge_channel, struct ast_bridge_features_limits *limits, const char *file)
{
	if (!strcasecmp(file, "timeleft")) {
		unsigned int remaining = ast_tvdiff_ms(limits->quitting_time, ast_tvnow()) / 1000;
		unsigned int min;
		unsigned int sec;

		if (remaining <= 0) {
			return;
		}

		if ((remaining / 60) > 1) {
			min = remaining / 60;
			sec = remaining % 60;
		} else {
			min = 0;
			sec = remaining;
		}

		ast_stream_and_wait(bridge_channel->chan, "vm-youhave", AST_DIGIT_NONE);
		if (min) {
			ast_say_number(bridge_channel->chan, min, AST_DIGIT_NONE,
				ast_channel_language(bridge_channel->chan), NULL);
			ast_stream_and_wait(bridge_channel->chan, "queue-minutes", AST_DIGIT_NONE);
		}
		if (sec) {
			ast_say_number(bridge_channel->chan, sec, AST_DIGIT_NONE,
				ast_channel_language(bridge_channel->chan), NULL);
			ast_stream_and_wait(bridge_channel->chan, "queue-seconds", AST_DIGIT_NONE);
		}
	} else {
		ast_stream_and_wait(bridge_channel->chan, file, AST_DIGIT_NONE);
	}

	/*
	 * It may be necessary to resume music on hold after we finish
	 * playing the announcment.
	 */
	if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_MOH)) {
		const char *latest_musicclass;

		ast_channel_lock(bridge_channel->chan);
		latest_musicclass = ast_strdupa(ast_channel_latest_musicclass(bridge_channel->chan));
		ast_channel_unlock(bridge_channel->chan);
		ast_moh_start(bridge_channel->chan, latest_musicclass, NULL);
	}
}
Example #14
0
/*! \brief Attempt to pick up named channel, does not use context */
static int pickup_by_channel(struct ast_channel *chan, char *pickup)
{
	int res = -1;
	struct ast_channel *target;/*!< Potential pickup target */

	target = my_ast_get_channel_by_name_locked(pickup);
	if (target) {
		/* Just check that we are not picking up the SAME as target. (i.e. ourself) */
		if (chan != target) {
			res = ast_do_pickup(chan, target);
		}
		ast_channel_unlock(target);
		target = ast_channel_unref(target);
	}

	return res;
}
Example #15
0
static void manager_park_bridged(struct mansession *s, const struct message *m,
		struct ast_channel *chan, struct ast_channel *parker_chan,
		const char *parkinglot, int timeout_override)
{
	struct ast_bridge_channel *bridge_channel;
	char *app_data;

	if (timeout_override != -1) {
		if (ast_asprintf(&app_data, "%s,t(%d)", parkinglot, timeout_override) == -1) {
			astman_send_error(s, m, "Park action failed\n");
			return;
		}
	} else {
		if (ast_asprintf(&app_data, "%s", parkinglot) == -1) {
			astman_send_error(s, m, "Park action failed\n");
			return;
		}
	}

	ast_channel_lock(parker_chan);
	bridge_channel = ast_channel_get_bridge_channel(parker_chan);
	ast_channel_unlock(parker_chan);

	if (!bridge_channel) {
		ast_free(app_data);
		astman_send_error(s, m, "Park action failed\n");
		return;
	}

	/* Subscribe to park messages for the channel being parked */
	if (create_parked_subscription(parker_chan, ast_channel_uniqueid(chan), 1)) {
		ast_free(app_data);
		astman_send_error(s, m, "Park action failed\n");
		ao2_cleanup(bridge_channel);
		return;
	}

	ast_bridge_channel_write_park(bridge_channel, ast_channel_uniqueid(chan),
			ast_channel_uniqueid(parker_chan), app_data);

	ast_free(app_data);

	astman_send_ack(s, m, "Park successful\n");
	ao2_cleanup(bridge_channel);
}
Example #16
0
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
{
	int res = 0;

	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));

	ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
	res = ast_audiohook_attach(autochan->chan, audiohook);

	if (!res) {
		ast_channel_lock(autochan->chan);
		if (ast_channel_is_bridged(autochan->chan)) {
			ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE);
		}
		ast_channel_unlock(autochan->chan);
	}
	return res;
}
Example #17
0
int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
{
	struct ast_hangup_handler_list *handlers;
	struct ast_hangup_handler *h_handler;

	ast_channel_lock(chan);
	handlers = ast_channel_hangup_handlers(chan);
	h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
	if (h_handler) {
		publish_hangup_handler_message("pop", chan, h_handler->args);
	}
	ast_channel_unlock(chan);
	if (h_handler) {
		ast_free(h_handler);
		return 1;
	}
	return 0;
}
/*!
 * \internal
 * \brief Session supplement callback for outgoing INVITE requests
 *
 * 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;
	}

	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);

	add_id_headers(session, tdata, &connected_id);
	ast_party_id_free(&connected_id);
}
static int manager_bridge_kick(struct mansession *s, const struct message *m)
{
	const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");
	const char *channel_name = astman_get_header(m, "Channel");
	RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel *, channel, NULL, ao2_cleanup);

	if (ast_strlen_zero(channel_name)) {
		astman_send_error(s, m, "Channel must be provided");
		return 0;
	}

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

	if (ast_strlen_zero(bridge_uniqueid)) {
		/* get the bridge from the channel */
		ast_channel_lock(channel);
		bridge = ast_channel_get_bridge(channel);
		ast_channel_unlock(channel);
		if (!bridge) {
			astman_send_error(s, m, "Channel is not in a bridge");
			return 0;
		}
	} else {
		bridge = ast_bridge_find_by_id(bridge_uniqueid);
		if (!bridge) {
			astman_send_error(s, m, "Bridge not found");
			return 0;
		}
	}

	if (ast_bridge_kick(bridge, channel)) {
		astman_send_error(s, m, "Channel kick from bridge failed");
		return 0;
	}

	astman_send_ack(s, m, "Channel has been kicked");
	return 0;
}
Example #20
0
/*!
 * \internal
 * \brief Destroy the speech datastore on the given channel.
 *
 * \param chan Channel to destroy speech datastore.
 *
 * \retval 0 on success.
 * \retval -1 not found.
 */
static int speech_datastore_destroy(struct ast_channel *chan)
{
	struct ast_datastore *datastore;
	int res;

	ast_channel_lock(chan);
	datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
	if (datastore) {
		ast_channel_datastore_remove(chan, datastore);
	}
	ast_channel_unlock(chan);
	if (datastore) {
		ast_datastore_free(datastore);
		res = 0;
	} else {
		res = -1;
	}
	return res;
}
Example #21
0
/*! \note Returns the channel in the chanspy_ds locked as well as the chanspy_ds locked */
static struct chanspy_ds *setup_chanspy_ds(struct ast_channel *chan, struct chanspy_ds *chanspy_ds)
{
	struct ast_datastore *datastore = NULL;

	ast_mutex_lock(&chanspy_ds->lock);

	if (!(datastore = ast_channel_datastore_alloc(&chanspy_ds_info, chanspy_ds->unique_id))) {
		ast_mutex_unlock(&chanspy_ds->lock);
		chanspy_ds = chanspy_ds_free(chanspy_ds);
		ast_channel_unlock(chan);
		return NULL;
	}
	
	chanspy_ds->chan = chan;
	datastore->data = chanspy_ds;
	ast_channel_datastore_add(chan, datastore);

	return chanspy_ds;
}
/*!
 * \internal
 * \brief Session supplement for outgoing INVITE response
 *
 * This will add P-Asserted-Identity and Remote-Party-ID headers if necessary
 *
 * \param session The session on which the INVITE response is to be sent
 * \param tdata The outbound INVITE response
 */
static void caller_id_outgoing_response(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);

	add_id_headers(session, tdata, &connected_id);
	ast_party_id_free(&connected_id);
}
Example #23
0
/*! \brief Helper function used to find the speech structure attached to a channel */
static struct ast_speech *find_speech(struct ast_channel *chan)
{
	struct ast_speech *speech = NULL;
	struct ast_datastore *datastore = NULL;

	if (!chan) {
		return NULL;
	}

	ast_channel_lock(chan);
	datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
	ast_channel_unlock(chan);
	if (datastore == NULL) {
		return NULL;
	}
	speech = datastore->data;

	return speech;
}
Example #24
0
static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length,
	int exact, size_t *var_len, WriteMethod **write_method)
{
	static unsigned long long_ret;
	struct ast_channel *chan = NULL;

	long_ret = 0;
	if (header_generic(vp, name, length, exact, var_len, write_method))
		return NULL;

	while ((chan = ast_channel_walk_locked(chan))) {
		if (ast_bridged_channel(chan))
			long_ret++;
		ast_channel_unlock(chan);
	}

	*var_len = sizeof(long_ret);

	return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;
}
Example #25
0
/*! \brief Helper function to not deadlock when queueing the hangup frame */
static void bridge_queue_hangup(struct bridge_pvt *p, struct ast_channel *us)
{
	struct ast_channel *other = (p->input == us ? p->output : p->input);

	while (other && ast_channel_trylock(other)) {
		ast_mutex_unlock(&p->lock);
		do {
			CHANNEL_DEADLOCK_AVOIDANCE(us);
		} while (ast_mutex_trylock(&p->lock));
		other = (p->input == us ? p->output : p->input);
	}

	/* We basically queue the frame up on the other channel if present */
	if (other) {
		ast_queue_hangup(other);
		ast_channel_unlock(other);
	}

	return;
}
static int find_by_uniqueid(void *obj, void *arg, void *data, int flags)
{
	struct ast_channel *target = obj;/*!< Potential pickup target */
	struct pickup_by_name_args *args = data;

	if (args->chan == target) {
		/* The channel attempting to pickup a call cannot pickup itself. */
		return 0;
	}

	ast_channel_lock(target);
	if (!strcasecmp(ast_channel_uniqueid(target), args->name)
		&& ast_can_pickup(target)) {
		/* Return with the channel still locked on purpose */
		return CMP_MATCH | CMP_STOP;
	}
	ast_channel_unlock(target);

	return 0;
}
Example #27
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;
}
Example #28
0
static struct ast_parked_call_payload *parked_call_payload_from_parked_user(struct parked_user *pu, enum ast_parked_call_event_type event_type)
{
	RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
	long int timeout;
	long int duration;
	struct timeval now = ast_tvnow();
	const char *lot_name = pu->lot->name;

	ast_channel_lock(pu->chan);
	parkee_snapshot = ast_channel_snapshot_create(pu->chan);
	ast_channel_unlock(pu->chan);
	if (!parkee_snapshot) {
		return NULL;
	}

	timeout = pu->start.tv_sec + (long) pu->time_limit - now.tv_sec;
	duration = now.tv_sec - pu->start.tv_sec;

	return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker_dial_string, pu->retriever, lot_name, pu->parking_space, timeout, duration);

}
/*!
 * \brief queue a frame onto either the p->owner or p->chan
 *
 * \note the ast_unreal_pvt MUST have it's ref count bumped before entering this function and
 * decremented after this function is called.  This is a side effect of the deadlock
 * avoidance that is necessary to lock 2 channels and a tech_pvt.  Without a ref counted
 * ast_unreal_pvt, it is impossible to guarantee it will not be destroyed by another thread
 * during deadlock avoidance.
 */
static int unreal_queue_frame(struct ast_unreal_pvt *p, int isoutbound, struct ast_frame *f,
	struct ast_channel *us, int us_locked)
{
	struct ast_channel *other;

	/* Recalculate outbound channel */
	other = isoutbound ? p->owner : p->chan;
	if (!other) {
		return 0;
	}

	/* do not queue media frames if a generator is on both unreal channels */
	if (us
		&& (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)
		&& ast_channel_generator(us)
		&& ast_channel_generator(other)) {
		return 0;
	}

	/* grab a ref on the channel before unlocking the pvt,
	 * other can not go away from us now regardless of locking */
	ast_channel_ref(other);
	if (us && us_locked) {
		ast_channel_unlock(us);
	}
	ao2_unlock(p);

	if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_RINGING) {
		ast_setstate(other, AST_STATE_RINGING);
	}
	ast_queue_frame(other, f);

	other = ast_channel_unref(other);
	if (us && us_locked) {
		ast_channel_lock(us);
	}
	ao2_lock(p);

	return 0;
}
/*!
 * \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);
}