Пример #1
0
void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
{
	struct ao2_iterator *channels;
	struct ao2_iterator *endpoints;
	struct ao2_iterator *bridges;
	struct app_forwards *forward;
	enum forward_type forward_type;

	ast_cli(a->fd, "Name: %s\n"
		"  Debug: %s\n"
		"  Subscription Model: %s\n",
		app->name,
		app->debug ? "Yes" : "No",
		app->subscription_model == STASIS_APP_SUBSCRIBE_ALL ?
			"Global Resource Subscription" :
			"Application/Explicit Resource Subscription");
	ast_cli(a->fd, "  Subscriptions: %d\n", ao2_container_count(app->forwards));

	ast_cli(a->fd, "    Channels:\n");
	forward_type = FORWARD_CHANNEL;
	channels = ao2_callback(app->forwards, OBJ_MULTIPLE,
		forwards_filter_by_type, &forward_type);
	if (channels) {
		while ((forward = ao2_iterator_next(channels))) {
			ast_cli(a->fd, "      %s (%d)\n", forward->id, forward->interested);
			ao2_ref(forward, -1);
		}
		ao2_iterator_destroy(channels);
	}

	ast_cli(a->fd, "    Bridges:\n");
	forward_type = FORWARD_BRIDGE;
	bridges = ao2_callback(app->forwards, OBJ_MULTIPLE,
		forwards_filter_by_type, &forward_type);
	if (bridges) {
		while ((forward = ao2_iterator_next(bridges))) {
			ast_cli(a->fd, "      %s (%d)\n", forward->id, forward->interested);
			ao2_ref(forward, -1);
		}
		ao2_iterator_destroy(bridges);
	}

	ast_cli(a->fd, "    Endpoints:\n");
	forward_type = FORWARD_ENDPOINT;
	endpoints = ao2_callback(app->forwards, OBJ_MULTIPLE,
		forwards_filter_by_type, &forward_type);
	if (endpoints) {
		while ((forward = ao2_iterator_next(endpoints))) {
			ast_cli(a->fd, "      %s (%d)\n", forward->id, forward->interested);
			ao2_ref(forward, -1);
		}
		ao2_iterator_destroy(endpoints);
	}
}
Пример #2
0
static int get_write_timeout(void)
{
	int write_timeout = -1;
	struct ao2_container *transport_states;

	transport_states = ast_sip_get_transport_states();

	if (transport_states) {
		struct ao2_iterator it_transport_states = ao2_iterator_init(transport_states, 0);
		struct ast_sip_transport_state *transport_state;

		for (; (transport_state = ao2_iterator_next(&it_transport_states)); ao2_cleanup(transport_state)) {
			struct ast_sip_transport *transport;
			if (transport_state->type != AST_TRANSPORT_WS && transport_state->type != AST_TRANSPORT_WSS) {
				continue;
			}
			transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id);
			ast_debug(5, "Found %s transport with write timeout: %d\n",
				transport->type == AST_TRANSPORT_WS ? "WS" : "WSS",
				transport->write_timeout);
			write_timeout = MAX(write_timeout, transport->write_timeout);
		}
		ao2_iterator_destroy(&it_transport_states);
		ao2_cleanup(transport_states);
	}

	if (write_timeout < 0) {
		write_timeout = AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT;
	}

	ast_debug(1, "Write timeout for WS/WSS transports: %d\n", write_timeout);
	return write_timeout;
}
Пример #3
0
/*!
 * \internal
 * \brief Do completion on the endpoint.
 */
static char *cli_complete_endpoint(const char *word, int state)
{
	char *result = NULL;
	int wordlen = strlen(word);
	int which = 0;

	struct ast_sip_endpoint *endpoint;
	RAII_VAR(struct ao2_container *, endpoints,
		 ast_sip_get_endpoints(), ao2_cleanup);

	struct ao2_iterator i = ao2_iterator_init(endpoints, 0);
	while ((endpoint = ao2_iterator_next(&i))) {
		const char *name = ast_sorcery_object_get_id(endpoint);
		if (!strncasecmp(word, name, wordlen) && ++which > state) {
			result = ast_strdup(name);
		}

		ao2_cleanup(endpoint);
		if (result) {
			break;
		}
	}
	ao2_iterator_destroy(&i);
	return result;
}
Пример #4
0
static char *complete_mailbox(const char *word, int state)
{
	struct ao2_iterator iter;
	int wordlen = strlen(word);
	int which = 0;
	char *ret = NULL;
	char *regex;
	const struct ast_mwi_mailbox_object *mailbox;
	RAII_VAR(struct ao2_container *, mailboxes, NULL, ao2_cleanup);

	regex = ast_alloca(2 + wordlen);
	sprintf(regex, "^%s", word);/* Safe */

	mailboxes = ast_mwi_mailbox_get_by_regex(regex);
	if (!mailboxes) {
		return NULL;
	}

	iter = ao2_iterator_init(mailboxes, 0);
	for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
		if (++which > state) {
			ret = ast_strdup(ast_sorcery_object_get_id(mailbox));
			ast_mwi_mailbox_unref(mailbox);
			break;
		}
	}
	ao2_iterator_destroy(&iter);

	return ret;
}
/*! \brief Helper function which returns a UDP transport bound to the given address and port */
static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port)
{
	struct ao2_container *transports = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "transport",
		AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
	struct ast_sip_transport *transport;
	struct ao2_iterator iter;
	pjsip_transport *sip_transport = NULL;

	if (!transports) {
		return NULL;
	}

	for (iter = ao2_iterator_init(transports, 0); (transport = ao2_iterator_next(&iter)); ao2_ref(transport, -1)) {
		if ((transport->type != AST_TRANSPORT_UDP) ||
			(pj_strcmp(&transport->state->transport->local_name.host, address)) ||
			(transport->state->transport->local_name.port != port)) {
			continue;
		}

		sip_transport = transport->state->transport;
		ao2_ref(transport, -1);
		break;
	}
	ao2_iterator_destroy(&iter);

	ao2_ref(transports, -1);

	return sip_transport;
}
Пример #6
0
struct ao2_container *ast_multi_channel_blob_get_channels(struct ast_multi_channel_blob *obj, const char *role)
{
	RAII_VAR(struct ao2_container *, ret_container,
		ao2_container_alloc(NUM_MULTI_CHANNEL_BLOB_BUCKETS, channel_snapshot_hash_cb, channel_snapshot_cmp_cb),
		ao2_cleanup);
	struct ao2_iterator *it_role_snapshots;
	struct channel_role_snapshot *role_snapshot;
	char *arg;

	if (!obj || ast_strlen_zero(role) || !ret_container) {
		return NULL;
	}
	arg = ast_strdupa(role);

	it_role_snapshots = ao2_callback(obj->channel_snapshots, OBJ_MULTIPLE | OBJ_KEY, channel_role_multi_cmp_cb, arg);
	if (!it_role_snapshots) {
		return NULL;
	}

	while ((role_snapshot = ao2_iterator_next(it_role_snapshots))) {
		ao2_link(ret_container, role_snapshot->snapshot);
		ao2_ref(role_snapshot, -1);
	}
	ao2_iterator_destroy(it_role_snapshots);

	ao2_ref(ret_container, +1);
	return ret_container;
}
Пример #7
0
int control_prestart_dispatch_all(struct stasis_app_control *control,
	struct ast_channel *chan)
{
	struct ao2_container *command_queue;
	int count = 0;
	struct ao2_iterator iter;
	struct stasis_app_command *command;

	ast_channel_lock(chan);
	command_queue = command_prestart_get_container(chan);
	ast_channel_unlock(chan);
	if (!command_queue) {
		return 0;
	}

	iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);

	while ((command = ao2_iterator_next(&iter))) {
		command_invoke(command, control, chan);
		ao2_cleanup(command);
		++count;
	}

	ao2_iterator_destroy(&iter);
	ao2_cleanup(command_queue);
	return count;
}
Пример #8
0
/*! \brief Function called when a contact is added */
static void mwi_contact_added(const void *object)
{
	const struct ast_sip_contact *contact = object;
	struct ao2_iterator *mwi_subs;
	struct mwi_subscription *mwi_sub;
	const char *endpoint_id = ast_sorcery_object_get_id(contact->endpoint);

	if (ast_strlen_zero(contact->endpoint->subscription.mwi.mailboxes)) {
		return;
	}

	ao2_lock(unsolicited_mwi);

	mwi_subs = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE | OBJ_NOLOCK | OBJ_UNLINK);
	if (mwi_subs) {
		for (; (mwi_sub = ao2_iterator_next(mwi_subs)); ao2_cleanup(mwi_sub)) {
			unsubscribe(mwi_sub, NULL, 0);
		}
		ao2_iterator_destroy(mwi_subs);
	}

	create_mwi_subscriptions_for_endpoint(contact->endpoint, NULL, 0);

	ao2_unlock(unsolicited_mwi);

	mwi_contact_updated(object);
}
Пример #9
0
void stasis_app_set_global_debug(int debug)
{
	global_debug = debug;
	if (!global_debug) {
		struct ao2_container *app_names = stasis_app_get_all();
		struct ao2_iterator it_app_names;
		char *app_name;
		struct stasis_app *app;

		if (!app_names || !ao2_container_count(app_names)) {
			ao2_cleanup(app_names);
			return;
		}

		it_app_names = ao2_iterator_init(app_names, 0);
		while ((app_name = ao2_iterator_next(&it_app_names))) {
			if ((app = stasis_app_get_by_name(app_name))) {
				stasis_app_set_debug(app, 0);
			}

			ao2_cleanup(app_name);
			ao2_cleanup(app);
		}
		ao2_iterator_cleanup(&it_app_names);
		ao2_cleanup(app_names);
	}
}
Пример #10
0
/*!
 * \internal
 * \brief Shutdown the local proxy channel.
 * \since 12.0.0
 *
 * \return Nothing
 */
static void local_shutdown(void)
{
	struct local_pvt *p;
	struct ao2_iterator it;

	/* First, take us out of the channel loop */
	ast_cli_unregister_multiple(cli_local, ARRAY_LEN(cli_local));
	ast_manager_unregister("LocalOptimizeAway");
	ast_channel_unregister(&local_tech);

	it = ao2_iterator_init(locals, 0);
	while ((p = ao2_iterator_next(&it))) {
		if (p->base.owner) {
			ast_softhangup(p->base.owner, AST_SOFTHANGUP_APPUNLOAD);
		}
		ao2_ref(p, -1);
	}
	ao2_iterator_destroy(&it);
	ao2_ref(locals, -1);
	locals = NULL;

	ao2_cleanup(local_tech.capabilities);
	local_tech.capabilities = NULL;

	STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
	STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
	STASIS_MESSAGE_TYPE_CLEANUP(ast_local_bridge_type);
}
struct ast_json *stasis_app_mailboxes_to_json()
{
	struct ast_json *array = ast_json_array_create();
	struct ao2_container *mailboxes;
	struct ao2_iterator iter;
	const struct ast_mwi_mailbox_object *mailbox;

	if (!array) {
		return NULL;
	}

	mailboxes = ast_mwi_mailbox_get_all();
	if (!mailboxes) {
		ast_json_unref(array);
		return NULL;
	}

	iter = ao2_iterator_init(mailboxes, 0);
	for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
		struct ast_json *appending = mailbox_to_json(mailbox);
		if (!appending || ast_json_array_append(array, appending)) {
			/* Failed to append individual mailbox to the array. Abort. */
			ast_json_unref(array);
			array = NULL;
			break;
		}
	}
	ao2_iterator_destroy(&iter);

	return array;
}
Пример #12
0
/*!
 * \brief Explicitly shutdown a session.
 *
 * \details An explicit shutdown is necessary, since the \ref stasis_app has a reference
 *          to this session. We also need to be sure to null out the \c ws_session field,
 *          since the websocket is about to go away.
 *
 * \internal
 *
 * \param session  Event session object (\ref event_session).
 */
static void event_session_shutdown(struct event_session *session)
{
	struct ao2_iterator i;
	char *app;
	int j;
	SCOPED_AO2LOCK(lock, session);

	/* Clean up the websocket_apps container */
	if (session->websocket_apps) {
		i = ao2_iterator_init(session->websocket_apps, 0);
		while ((app = ao2_iterator_next(&i))) {
			stasis_app_unregister(app);
			ao2_cleanup(app);
		}
		ao2_iterator_destroy(&i);
		ao2_cleanup(session->websocket_apps);
		session->websocket_apps = NULL;
	}

	/* Clean up the message_queue container */
	for (j = 0; j < AST_VECTOR_SIZE(&session->message_queue); j++) {
		struct ast_json *msg = AST_VECTOR_GET(&session->message_queue, j);
		ast_json_unref(msg);
	}
	AST_VECTOR_FREE(&session->message_queue);

	/* Remove the handle to the underlying websocket session */
	session->ws_session = NULL;
}
Пример #13
0
/*!
 * \brief Determines if an endpoint is receiving unsolicited MWI for a particular mailbox.
 *
 * \param endpoint The endpoint to check
 * \param mailbox The candidate mailbox
 * \retval 0 The endpoint does not receive unsolicited MWI for this mailbox
 * \retval 1 The endpoint receives unsolicited MWI for this mailbox
 */
static int endpoint_receives_unsolicited_mwi_for_mailbox(struct ast_sip_endpoint *endpoint,
		const char *mailbox)
{
	struct ao2_container *unsolicited = ao2_global_obj_ref(unsolicited_mwi);
	struct ao2_iterator *mwi_subs;
	struct mwi_subscription *mwi_sub;
	const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
	int ret = 0;

	if (!unsolicited) {
		return 0;
	}

	mwi_subs = ao2_find(unsolicited, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
	ao2_cleanup(unsolicited);

	if (!mwi_subs) {
		return 0;
	}

	for (; (mwi_sub = ao2_iterator_next(mwi_subs)) && !ret; ao2_cleanup(mwi_sub)) {
		struct mwi_stasis_subscription *mwi_stasis;

		mwi_stasis = ao2_find(mwi_sub->stasis_subs, mailbox, OBJ_SEARCH_KEY);
		if (mwi_stasis) {
			ret = 1;
			ao2_cleanup(mwi_stasis);
		}
	}

	ao2_iterator_destroy(mwi_subs);
	return ret;
}
Пример #14
0
/*! \brief Function which adds ICE attributes to a media stream */
static void add_ice_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
{
	struct ast_rtp_engine_ice *ice;
	struct ao2_container *candidates;
	const char *username, *password;
	pj_str_t stmp;
	pjmedia_sdp_attr *attr;
	struct ao2_iterator it_candidates;
	struct ast_rtp_engine_ice_candidate *candidate;

	if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp)) ||
		!(candidates = ice->get_local_candidates(session_media->rtp))) {
		return;
	}

	if ((username = ice->get_ufrag(session_media->rtp))) {
		attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", pj_cstr(&stmp, username));
		media->attr[media->attr_count++] = attr;
	}

	if ((password = ice->get_password(session_media->rtp))) {
		attr = pjmedia_sdp_attr_create(pool, "ice-pwd", pj_cstr(&stmp, password));
		media->attr[media->attr_count++] = attr;
	}

	it_candidates = ao2_iterator_init(candidates, 0);
	for (; (candidate = ao2_iterator_next(&it_candidates)); ao2_ref(candidate, -1)) {
		struct ast_str *attr_candidate = ast_str_create(128);

		ast_str_set(&attr_candidate, -1, "%s %u %s %d %s ", candidate->foundation, candidate->id, candidate->transport,
					candidate->priority, ast_sockaddr_stringify_addr_remote(&candidate->address));
		ast_str_append(&attr_candidate, -1, "%s typ ", ast_sockaddr_stringify_port(&candidate->address));

		switch (candidate->type) {
			case AST_RTP_ICE_CANDIDATE_TYPE_HOST:
				ast_str_append(&attr_candidate, -1, "host");
				break;
			case AST_RTP_ICE_CANDIDATE_TYPE_SRFLX:
				ast_str_append(&attr_candidate, -1, "srflx");
				break;
			case AST_RTP_ICE_CANDIDATE_TYPE_RELAYED:
				ast_str_append(&attr_candidate, -1, "relay");
				break;
		}

		if (!ast_sockaddr_isnull(&candidate->relay_address)) {
			ast_str_append(&attr_candidate, -1, " raddr %s rport", ast_sockaddr_stringify_addr_remote(&candidate->relay_address));
			ast_str_append(&attr_candidate, -1, " %s", ast_sockaddr_stringify_port(&candidate->relay_address));
		}

		attr = pjmedia_sdp_attr_create(pool, "candidate", pj_cstr(&stmp, ast_str_buffer(attr_candidate)));
		media->attr[media->attr_count++] = attr;

		ast_free(attr_candidate);
	}

	ao2_iterator_destroy(&it_candidates);
	ao2_ref(candidates, -1);
}
Пример #15
0
int parking_lot_get_space(struct parking_lot *lot, int target_override)
{
	int original_target;
	int current_target;
	struct ao2_iterator i;
	struct parked_user *user;
	int wrap;

	if (lot->cfg->parkfindnext) {
		/* Use next_space if the lot already has next_space set; otherwise use lot start. */
		original_target = lot->next_space ? lot->next_space : lot->cfg->parking_start;
	} else {
		original_target = lot->cfg->parking_start;
	}

	if (target_override >= lot->cfg->parking_start && target_override <= lot->cfg->parking_stop) {
		original_target = target_override;
	}

	current_target = original_target;

	wrap = lot->cfg->parking_start;

	i = ao2_iterator_init(lot->parked_users, 0);
	while ((user = ao2_iterator_next(&i))) {
		/* Increment the wrap on each pass until we find an empty space */
		if (wrap == user->parking_space) {
			wrap += 1;
		}

		if (user->parking_space < current_target) {
			/* It's lower than the anticipated target, so we haven't reached the target yet. */
			ao2_ref(user, -1);
			continue;
		}

		if (user->parking_space > current_target) {
			/* The current target is usable because all items below have been read and the next target is higher than the one we want. */
			ao2_ref(user, -1);
			break;
		}

		/* We found one already parked here. */
		current_target += 1;
		ao2_ref(user, -1);
	}
	ao2_iterator_destroy(&i);

	if (current_target <= lot->cfg->parking_stop) {
		return current_target;
	}

	if (wrap <= lot->cfg->parking_stop) {
		return wrap;
	}

	return -1;
}
Пример #16
0
struct ast_channel *ast_pickup_find_by_group(struct ast_channel *chan)
{
	struct ao2_container *candidates;/*!< Candidate channels found to pickup. */
	struct ast_channel *target;/*!< Potential pickup target */

	candidates = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
	if (!candidates) {
		return NULL;
	}

	/* Find all candidate targets by group. */
	ast_channel_callback(find_channel_by_group, chan, candidates, 0);

	/* Find the oldest pickup target candidate */
	target = NULL;
	for (;;) {
		struct ast_channel *candidate;/*!< Potential new older target */
		struct ao2_iterator iter;

		iter = ao2_iterator_init(candidates, 0);
		while ((candidate = ao2_iterator_next(&iter))) {
			if (!target) {
				/* First target. */
				target = candidate;
				continue;
			}
			if (ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) {
				/* We have a new target. */
				ast_channel_unref(target);
				target = candidate;
				continue;
			}
			ast_channel_unref(candidate);
		}
		ao2_iterator_destroy(&iter);
		if (!target) {
			/* No candidates found. */
			break;
		}

		/* The found channel must be locked and ref'd. */
		ast_channel_lock(target);

		/* Recheck pickup ability */
		if (ast_can_pickup(target)) {
			/* This is the channel to pickup. */
			break;
		}

		/* Someone else picked it up or the call went away. */
		ast_channel_unlock(target);
		ao2_unlink(candidates, target);
		target = ast_channel_unref(target);
	}
	ao2_ref(candidates, -1);

	return target;
}
Пример #17
0
static int manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name)
{
	RAII_VAR(struct parking_lot *, curlot, NULL, ao2_cleanup);
	struct parked_user *curuser;
	struct ao2_iterator iter_users;
	int total = 0;

	curlot = parking_lot_find_by_name(lot_name);

	if (!curlot) {
		astman_send_error(s, m, "Requested parking lot could not be found.");
		return RESULT_SUCCESS;
	}

	astman_send_ack(s, m, "Parked calls will follow");

	iter_users = ao2_iterator_init(curlot->parked_users, 0);
	while ((curuser = ao2_iterator_next(&iter_users))) {
		RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
		RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);

		payload = parked_call_payload_from_parked_user(curuser, PARKED_CALL);
		if (!payload) {
			astman_send_error(s, m, "Failed to retrieve parking data about a parked user.");
			return RESULT_FAILURE;
		}

		parked_call_string = manager_build_parked_call_string(payload);
		if (!parked_call_string) {
			astman_send_error(s, m, "Failed to retrieve parkingd ata about a parked user.");
			return RESULT_FAILURE;
		}

		total++;

		astman_append(s, "Event: ParkedCall\r\n"
			"%s" /* The parked call string */
			"%s" /* The action ID */
			"\r\n",
			ast_str_buffer(parked_call_string),
			id_text);

		ao2_ref(curuser, -1);
	}

	ao2_iterator_destroy(&iter_users);

	astman_append(s,
		"Event: ParkedCallsComplete\r\n"
		"Total: %d\r\n"
		"%s"
		"\r\n",
		total, id_text);

	return RESULT_SUCCESS;
}
Пример #18
0
void ast_ari_channels_list(struct ast_variable *headers,
                           struct ast_ari_channels_list_args *args,
                           struct ast_ari_response *response)
{
    RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
    RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
    RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
    struct ao2_iterator i;
    void *obj;
    struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();

    cache = ast_channel_cache();
    if (!cache) {
        ast_ari_response_error(
            response, 500, "Internal Server Error",
            "Message bus not initialized");
        return;
    }
    ao2_ref(cache, +1);

    snapshots = stasis_cache_dump(cache, ast_channel_snapshot_type());
    if (!snapshots) {
        ast_ari_response_alloc_failed(response);
        return;
    }

    json = ast_json_array_create();
    if (!json) {
        ast_ari_response_alloc_failed(response);
        return;
    }

    for (i = ao2_iterator_init(snapshots, 0);
            (obj = ao2_iterator_next(&i)); ao2_cleanup(obj)) {
        RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
        struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
        int r;

        if (sanitize && sanitize->channel_snapshot
                && sanitize->channel_snapshot(snapshot)) {
            continue;
        }

        r = ast_json_array_append(
                json, ast_channel_snapshot_to_json(snapshot, NULL));
        if (r != 0) {
            ast_ari_response_alloc_failed(response);
            ao2_cleanup(obj);
            ao2_iterator_destroy(&i);
            return;
        }
    }
    ao2_iterator_destroy(&i);

    ast_ari_response_ok(response, ast_json_ref(json));
}
Пример #19
0
static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
									   int exact, size_t *var_len, WriteMethod **write_method)
{
	static unsigned long long_ret;
	static char ret_buf[256];
	struct ast_tone_zone *tz = NULL;
	int i;
	struct ao2_iterator iter;

	if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) {
		return NULL;
	}

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

	iter = ast_tone_zone_iterator_init();

	while ((tz = ao2_iterator_next(&iter)) && i) {
		tz = ast_tone_zone_unref(tz);
		i--;
	}
	ao2_iterator_destroy(&iter);

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

	switch (vp->magic) {
	case ASTINDINDEX:
		ast_tone_zone_unref(tz);
		long_ret = name[*length - 1];
		return (u_char *)&long_ret;
	case ASTINDCOUNTRY:
		ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
		ast_tone_zone_unref(tz);
		*var_len = strlen(ret_buf);
		return (u_char *) ret_buf;
	case ASTINDALIAS:
		/* No longer exists */
		ast_tone_zone_unref(tz);
		return NULL;
	case ASTINDDESCRIPTION:
		ast_tone_zone_lock(tz);
		ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
		ast_tone_zone_unlock(tz);
		ast_tone_zone_unref(tz);
		*var_len = strlen(ret_buf);
		return (u_char *) ret_buf;
	default:
		ast_tone_zone_unref(tz);
		break;
	}
	return NULL;
}
Пример #20
0
/*!
 * \internal
 * \brief Delete all mailboxes in container.
 * \since 12.1.0
 *
 * \param mailboxes Mailbox objects to delete from sorcery.
 *
 * \return Nothing
 */
static void mwi_mailbox_delete_all(struct ao2_container *mailboxes)
{
	struct ast_mwi_mailbox_object *mailbox;
	struct ao2_iterator iter;

	iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK);
	for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
		mwi_mailbox_delete(mailbox);
	}
	ao2_iterator_destroy(&iter);
}
Пример #21
0
void control_flush_queue(struct stasis_app_control *control)
{
	struct ao2_iterator iter;
	struct stasis_app_command *command;

	iter = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
	while ((command = ao2_iterator_next(&iter))) {
		command_complete(command, -1);
		ao2_ref(command, -1);
	}
	ao2_iterator_destroy(&iter);
}
Пример #22
0
/*! \brief Adds devicestate to local channels */
static int local_devicestate(const char *data)
{
	int is_inuse = 0;
	int res = AST_DEVICE_INVALID;
	char *exten = ast_strdupa(data);
	char *context;
	char *opts;
	struct local_pvt *lp;
	struct ao2_iterator it;

	/* Strip options if they exist */
	opts = strchr(exten, '/');
	if (opts) {
		*opts = '\0';
	}

	context = strchr(exten, '@');
	if (!context) {
		ast_log(LOG_WARNING,
			"Someone used Local/%s somewhere without a @context. This is bad.\n", data);
		return AST_DEVICE_INVALID;
	}
	*context++ = '\0';

	it = ao2_iterator_init(locals, 0);
	for (; (lp = ao2_iterator_next(&it)); ao2_ref(lp, -1)) {
		ao2_lock(lp);
		if (!strcmp(exten, lp->exten)
			&& !strcmp(context, lp->context)) {
			res = AST_DEVICE_NOT_INUSE;
			if (lp->base.owner
				&& ast_test_flag(&lp->base, AST_UNREAL_CARETAKER_THREAD)) {
				is_inuse = 1;
			}
		}
		ao2_unlock(lp);
		if (is_inuse) {
			res = AST_DEVICE_INUSE;
			ao2_ref(lp, -1);
			break;
		}
	}
	ao2_iterator_destroy(&it);

	if (res == AST_DEVICE_INVALID) {
		ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
		if (ast_exists_extension(NULL, context, exten, 1, NULL)) {
			res = AST_DEVICE_NOT_INUSE;
		}
	}

	return res;
}
Пример #23
0
struct ast_json *app_to_json(const struct stasis_app *app)
{
	struct ast_json *json;
	struct ast_json *channels;
	struct ast_json *bridges;
	struct ast_json *endpoints;
	struct ao2_iterator i;
	struct app_forwards *forwards;

	json = ast_json_pack("{s: s, s: [], s: [], s: []}",
		"name", app->name,
		"channel_ids", "bridge_ids", "endpoint_ids");
	if (!json) {
		return NULL;
	}
	channels = ast_json_object_get(json, "channel_ids");
	bridges = ast_json_object_get(json, "bridge_ids");
	endpoints = ast_json_object_get(json, "endpoint_ids");

	i = ao2_iterator_init(app->forwards, 0);
	while ((forwards = ao2_iterator_next(&i))) {
		struct ast_json *array = NULL;
		int append_res;

		switch (forwards->forward_type) {
		case FORWARD_CHANNEL:
			array = channels;
			break;
		case FORWARD_BRIDGE:
			array = bridges;
			break;
		case FORWARD_ENDPOINT:
			array = endpoints;
			break;
		}

		/* If forward_type value is unexpected this will safely return an error. */
		append_res = ast_json_array_append(array, ast_json_string_create(forwards->id));
		ao2_ref(forwards, -1);

		if (append_res != 0) {
			ast_log(LOG_ERROR, "Error building response\n");
			ao2_iterator_destroy(&i);
			ast_json_unref(json);

			return NULL;
		}
	}
	ao2_iterator_destroy(&i);

	return json;
}
Пример #24
0
/*!
 * \internal
 * \brief List all mailboxes in the given container.
 * \since 12.1.0
 *
 * \param cli_fd File descriptor for CLI output.
 * \param mailboxes What to list.
 *
 * \return Nothing
 */
static void mwi_cli_list_mailboxes(int cli_fd, struct ao2_container *mailboxes)
{
	struct ao2_iterator iter;
	const struct ast_mwi_mailbox_object *mailbox;

	ast_cli(cli_fd, FORMAT_MAILBOX_HDR, "New", "Old", "Mailbox");

	iter = ao2_iterator_init(mailboxes, 0);
	for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
		mwi_cli_print_mailbox(cli_fd, mailbox);
	}
	ao2_iterator_destroy(&iter);
}
Пример #25
0
/*!
 * \internal
 * \brief Do completion on the notify CLI command.
 */
static char *cli_complete_notify(const char *line, const char *word,
				 int pos, int state, int using_uri)
{
	char *c = NULL;

	if (pos == 3) {
		int which = 0;
		int wordlen = strlen(word);

		RAII_VAR(struct notify_cfg *, cfg,
			 ao2_global_obj_ref(globals), ao2_cleanup);
		struct notify_option *option;

		/* do completion for notify type */
		struct ao2_iterator i = ao2_iterator_init(cfg->notify_options, 0);
		while ((option = ao2_iterator_next(&i))) {
			if (!strncasecmp(word, option->name, wordlen) && ++which > state) {
				c = ast_strdup(option->name);
			}

			ao2_cleanup(option);
			if (c) {
				break;
			}
		}
		ao2_iterator_destroy(&i);
		return c;
	}

	if (pos == 4) {
		int wordlen = strlen(word);

		if (ast_strlen_zero(word)) {
		    if (state == 0) {
		        c = ast_strdup("endpoint");
		    } else if (state == 1) {
		        c = ast_strdup("uri");
		    }
		} else if (state == 0) {
		    if (!strncasecmp(word, "endpoint", wordlen)) {
		        c = ast_strdup("endpoint");
		    } else if (!strncasecmp(word, "uri", wordlen)) {
		        c = ast_strdup("uri");
		    }
		}

		return c;
	}

	return pos > 4 && !using_uri ? cli_complete_endpoint(word, state) : NULL;
}
Пример #26
0
struct ast_json *app_to_json(const struct stasis_app *app)
{
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	struct ast_json *channels;
	struct ast_json *bridges;
	struct ast_json *endpoints;
	struct ao2_iterator i;
	void *obj;

	json = ast_json_pack("{s: s, s: [], s: [], s: []}",
		"name", app->name,
		"channel_ids", "bridge_ids", "endpoint_ids");
	channels = ast_json_object_get(json, "channel_ids");
	bridges = ast_json_object_get(json, "bridge_ids");
	endpoints = ast_json_object_get(json, "endpoint_ids");

	i = ao2_iterator_init(app->forwards, 0);
	while ((obj = ao2_iterator_next(&i))) {
		RAII_VAR(struct app_forwards *, forwards, obj, ao2_cleanup);
		RAII_VAR(struct ast_json *, id, NULL, ast_json_unref);
		int append_res = -1;

		id = ast_json_string_create(forwards->id);

		switch (forwards->forward_type) {
		case FORWARD_CHANNEL:
			append_res = ast_json_array_append(channels,
				ast_json_ref(id));
			break;
		case FORWARD_BRIDGE:
			append_res = ast_json_array_append(bridges,
				ast_json_ref(id));
			break;
		case FORWARD_ENDPOINT:
			append_res = ast_json_array_append(endpoints,
				ast_json_ref(id));
			break;
		}

		if (append_res != 0) {
			ast_log(LOG_ERROR, "Error building response\n");
			ao2_iterator_destroy(&i);
			return NULL;
		}
	}
	ao2_iterator_destroy(&i);

	return ast_json_ref(json);
}
Пример #27
0
void ast_ari_bridges_list(struct ast_variable *headers,
	struct ast_ari_bridges_list_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
	RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	struct ao2_iterator i;
	void *obj;

	cache = ast_bridge_cache();
	if (!cache) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Message bus not initialized");
		return;
	}
	ao2_ref(cache, +1);

	snapshots = stasis_cache_dump(cache, ast_bridge_snapshot_type());
	if (!snapshots) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	json = ast_json_array_create();
	if (!json) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	i = ao2_iterator_init(snapshots, 0);
	while ((obj = ao2_iterator_next(&i))) {
		RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
		struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
		struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());

		if (!json_bridge || ast_json_array_append(json, json_bridge)) {
			ao2_iterator_destroy(&i);
			ast_ari_response_alloc_failed(response);
			return;
		}
	}
	ao2_iterator_destroy(&i);

	ast_ari_response_ok(response, ast_json_ref(json));
}
Пример #28
0
int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
		ao2_callback_fn on_contact, void *arg)
{
	struct ao2_container *contacts;
	struct ao2_iterator i;
	int res = 0;
	void *object = NULL;

	if (!on_contact ||
	    !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
		return 0;
	}

	i = ao2_iterator_init(contacts, 0);
	while ((object = ao2_iterator_next(&i))) {
		RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup);
		RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup);
		const char *aor_id = ast_sorcery_object_get_id(aor);

		wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper),
			contact_wrapper_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
		if (!wrapper) {
			res = -1;
			break;
		}
		wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2);
		if (!wrapper->contact_id) {
			res = -1;
			break;
		}
		sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri);
		wrapper->aor_id = ast_strdup(aor_id);
		if (!wrapper->aor_id) {
			res = -1;
			break;
		}
		wrapper->contact = contact;
		ao2_bump(wrapper->contact);

		if ((res = on_contact(wrapper, arg, 0))) {
			break;
		}
	}
	ao2_iterator_destroy(&i);
	ao2_ref(contacts, -1);
	return res;
}
Пример #29
0
/*!
 * \brief Explicitly shutdown a session.
 *
 * An explicit shutdown is necessary, since stasis-app has a reference to this
 * session. We also need to be sure to null out the \c ws_session field, since
 * the websocket is about to go away.
 *
 * \param session Session info struct.
 */
static void session_shutdown(struct event_session *session)
{
        struct ao2_iterator i;
	char *app;
	SCOPED_AO2LOCK(lock, session);

	i = ao2_iterator_init(session->websocket_apps, 0);
	while ((app = ao2_iterator_next(&i))) {
		stasis_app_unregister(app);
		ao2_cleanup(app);
	}
	ao2_iterator_destroy(&i);
	ao2_cleanup(session->websocket_apps);

	session->websocket_apps = NULL;
	session->ws_session = NULL;
}
Пример #30
0
/*!
 * \brief wrapper for ao2_iterator_next
 *
 * Grabs the next item in the container and replaces the ref acquired
 * from ao2_iterator_next() with a call to test_ref().
 */
static struct test_struct *test_iterator_next(struct ao2_iterator *iter)
{
    struct test_struct *test = ao2_iterator_next(iter);

    if (!test) {
        return NULL;
    }

    /* Remove ref from ao2_iterator_next() and replace it with
     * a test_ref() call. The order here is safe since we can guarantee
     * the container still has a ref to the test structure.
     */
    ao2_ref(test, -1);
    test_ref(test);

    return test;
}