Пример #1
0
/*! \brief Publish single channel user event (for app_userevent compatibility) */
void ast_multi_object_blob_single_channel_publish(struct ast_channel *chan,
	struct stasis_message_type *type, struct ast_json *blob)
{
	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, channel_snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct ast_multi_object_blob *, multi, NULL, ao2_cleanup);

	if (!type) {
		return;
	}

	multi = ast_multi_object_blob_create(blob);
	if (!multi) {
		return;
	}

	channel_snapshot = ast_channel_snapshot_create(chan);
	ao2_ref(channel_snapshot, +1);
	ast_multi_object_blob_add(multi, STASIS_UMOS_CHANNEL, channel_snapshot);

	message = stasis_message_create(type, multi);
	if (message) {
		/* app_userevent still publishes to channel */
		stasis_publish(ast_channel_topic(chan), message);
	}
}
Пример #2
0
struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
	struct stasis_message_type *type, struct ast_json *blob)
{
	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);

	if (chan) {
		snapshot = ast_channel_snapshot_create(chan);
	}

	return create_channel_blob_message(snapshot, type, blob);
}
Пример #3
0
static struct ast_parked_call_payload *parked_call_payload_from_failure(struct ast_channel *chan)
{
	RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);

	parkee_snapshot = ast_channel_snapshot_create(chan);
	if (!parkee_snapshot) {
		return NULL;
	}

	return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0);
}
Пример #4
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);

}
Пример #5
0
void ast_channel_publish_snapshot(struct ast_channel *chan)
{
	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);

	if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE)) {
		return;
	}

	snapshot = ast_channel_snapshot_create(chan);
	if (!snapshot) {
		return;
	}

	message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
	if (!message) {
		return;
	}

	ast_assert(ast_channel_topic(chan) != NULL);
	stasis_publish(ast_channel_topic(chan), message);
}
Пример #6
0
void ast_publish_channel_state(struct ast_channel *chan)
{
	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);

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

	snapshot = ast_channel_snapshot_create(chan);
	if (!snapshot) {
		return;
	}

	message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
	if (!message) {
		return;
	}

	ast_assert(ast_channel_topic(chan) != NULL);
	stasis_publish(ast_channel_topic(chan), message);
}
Пример #7
0
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer,
	struct ast_channel *forwarded, const char *dialstring, const char *dialstatus,
	const char *forward)
{
	RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
	RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, peer_snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, forwarded_snapshot, NULL, ao2_cleanup);

	ast_assert(peer != NULL);
	blob = ast_json_pack("{s: s, s: s, s: s}",
			     "dialstatus", S_OR(dialstatus, ""),
			     "forward", S_OR(forward, ""),
			     "dialstring", S_OR(dialstring, ""));
	if (!blob) {
		return;
	}
	payload = ast_multi_channel_blob_create(blob);
	if (!payload) {
		return;
	}

	if (caller) {
		ast_channel_lock(caller);
		caller_snapshot = ast_channel_snapshot_create(caller);
		ast_channel_unlock(caller);
		if (!caller_snapshot) {
			return;
		}
		ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
	}

	ast_channel_lock(peer);
	peer_snapshot = ast_channel_snapshot_create(peer);
	ast_channel_unlock(peer);
	if (!peer_snapshot) {
		return;
	}
	ast_multi_channel_blob_add_channel(payload, "peer", peer_snapshot);

	if (forwarded) {
		ast_channel_lock(forwarded);
		forwarded_snapshot = ast_channel_snapshot_create(forwarded);
		ast_channel_unlock(forwarded);
		if (!forwarded_snapshot) {
			return;
		}
		ast_multi_channel_blob_add_channel(payload, "forwarded", forwarded_snapshot);
	}

	msg = stasis_message_create(ast_channel_dial_type(), payload);
	if (!msg) {
		return;
	}

	if (forwarded) {
		struct stasis_subscription *subscription = stasis_subscribe(ast_channel_topic(peer), dummy_event_cb, NULL);

		stasis_publish(ast_channel_topic(peer), msg);
		stasis_unsubscribe_and_join(subscription);
	} else {
		publish_message_for_channel_topics(msg, caller);
	}
}
Пример #8
0
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
{
	struct ast_party_connected_line connected_caller;
	struct ast_datastore *ds_pickup;
	const char *chan_name;/*!< A masquerade changes channel names. */
	const char *target_name;/*!< A masquerade changes channel names. */
	int res = -1;

	RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, target_snapshot, NULL, ao2_cleanup);

	target_name = ast_strdupa(ast_channel_name(target));
	ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan));

	/* Mark the target to block any call pickup race. */
	ds_pickup = ast_datastore_alloc(&pickup_active, NULL);
	if (!ds_pickup) {
		ast_log(LOG_WARNING,
			"Unable to create channel datastore on '%s' for call pickup\n", target_name);
		return -1;
	}
	ast_channel_datastore_add(target, ds_pickup);

	ast_party_connected_line_init(&connected_caller);
	ast_party_connected_line_copy(&connected_caller, ast_channel_connected(target));
	ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
	/* Reset any earlier private connected id representation */
	ast_party_id_reset(&connected_caller.priv);

	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
	if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0) &&
		ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
		ast_channel_update_connected_line(chan, &connected_caller, NULL);
	}
	ast_party_connected_line_free(&connected_caller);

	ast_channel_lock(chan);
	chan_name = ast_strdupa(ast_channel_name(chan));
	ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(chan));
	ast_channel_unlock(chan);
	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;

	if (ast_answer(chan)) {
		ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
		goto pickup_failed;
	}

	if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
		ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
		goto pickup_failed;
	}

	ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);

	/* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */
	ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE);

	ast_channel_lock(chan);
	chan_snapshot = ast_channel_snapshot_create(chan);
	ast_channel_unlock(chan);
	if (!chan_snapshot) {
		goto pickup_failed;
	}

	target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target));
	if (!target_snapshot) {
		goto pickup_failed;
	}

	if (ast_channel_move(target, chan)) {
		ast_log(LOG_WARNING, "Unable to complete call pickup of '%s' with '%s'\n",
			chan_name, target_name);
		goto pickup_failed;
	}

	/* target points to the channel that did the pickup at this point, so use that channel's topic instead of chan */
	send_call_pickup_stasis_message(target, chan_snapshot, target_snapshot);

	res = 0;

pickup_failed:
	ast_channel_lock(target);
	if (!ast_channel_datastore_remove(target, ds_pickup)) {
		ast_datastore_free(ds_pickup);
	}
	ast_party_connected_line_free(&connected_caller);

	return res;
}