示例#1
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;
}
示例#2
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;
}
示例#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;
}
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;
}
示例#5
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;
}
/*! \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;
}
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;
}
示例#8
0
文件: app.c 项目: roramirez/asterisk
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);
	}
}
示例#9
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);
}
示例#10
0
static char *complete_show_sorcery_object(struct ao2_container *container,
	struct ast_sip_cli_formatter_entry *formatter_entry,
	const char *word, int state)
{
	char *result = NULL;
	int wordlen = strlen(word);
	int which = 0;

	struct ao2_iterator i = ao2_iterator_init(container, 0);
	void *object;

	while ((object = ao2_t_iterator_next(&i, "iterate thru endpoints table"))) {
		const char *id = formatter_entry->get_id(object);
		if (!strncasecmp(word, id, wordlen)
			&& ++which > state) {
			result = ast_strdup(id);
		}
		ao2_t_ref(object, -1, "toss iterator endpoint ptr before break");
		if (result) {
			break;
		}
	}
	ao2_iterator_destroy(&i);

	return result;
}
示例#11
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);
}
示例#12
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;
}
示例#13
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;
}
示例#14
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));
}
示例#15
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;
}
示例#16
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);
}
示例#17
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);
}
示例#18
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;
}
示例#19
0
文件: app.c 项目: roramirez/asterisk
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;
}
示例#20
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);
}
示例#21
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;
}
示例#22
0
文件: app.c 项目: lyx2014/Asterisk
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);
}
示例#23
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));
}
示例#24
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;
}
示例#25
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;
}
示例#26
0
static void mwi_subscription_mailboxes_str(struct ao2_container *stasis_subs,
					   struct ast_str **str)
{
	int num = ao2_container_count(stasis_subs);

	struct mwi_stasis_subscription *node;
	struct ao2_iterator i = ao2_iterator_init(stasis_subs, 0);

	while ((node = ao2_iterator_next(&i))) {
		if (--num) {
			ast_str_append(str, 0, "%s,", node->mailbox);
		} else {
			ast_str_append(str, 0, "%s", node->mailbox);
		}
		ao2_ref(node, -1);
	}
	ao2_iterator_destroy(&i);
}
示例#27
0
/*!
 * \internal
 * \brief Build the NOTIFY request from CLI info adding header and content
 *        when specified.
 */
static void build_cli_notify(pjsip_tx_data *tdata, void *info)
{
	struct notify_option *option = info;
	RAII_VAR(struct ast_str *, content_type, NULL, ast_free);
	RAII_VAR(struct ast_str *, content, NULL, ast_free);

	struct notify_option_item *item;
	struct ao2_iterator i = ao2_iterator_init(option->items, 0);

	while ((item = ao2_iterator_next(&i))) {
		build_notify(tdata, item->name, item->value,
			     &content_type, &content);
		ao2_cleanup(item);
	}
	ao2_iterator_destroy(&i);

	build_notify_body(tdata, content_type, content);
}
示例#28
0
int control_dispatch_all(struct stasis_app_control *control,
	struct ast_channel *chan)
{
	int count = 0;
	struct ao2_iterator iter;
	struct stasis_app_command *command;

	ast_assert(control->channel == chan);

	iter = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
	while ((command = ao2_iterator_next(&iter))) {
		command_invoke(command, control, chan);
		ao2_ref(command, -1);
		++count;
	}
	ao2_iterator_destroy(&iter);

	return count;
}
示例#29
0
static int dialgroup_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
	struct ao2_iterator i;
	struct group *grhead = ao2_find(group_container, data, 0);
	struct group_entry *entry;
	size_t bufused = 0;
	int trunc_warning = 0;
	int res = 0;

	if (!grhead) {
		if (!ast_strlen_zero(cmd)) {
			ast_log(LOG_WARNING, "No such dialgroup '%s'\n", data);
		}
		return -1;
	}

	buf[0] = '\0';

	i = ao2_iterator_init(grhead->entries, OBJ_POINTER);
	while ((entry = ao2_iterator_next(&i))) {
		int tmp = strlen(entry->name);
		/* Ensure that we copy only complete names, not partials */
		if (len - bufused > tmp + 2) {
			if (bufused != 0)
				buf[bufused++] = '&';
			ast_copy_string(buf + bufused, entry->name, len - bufused);
			bufused += tmp;
		} else if (trunc_warning++ == 0) {
			if (!ast_strlen_zero(cmd)) {
				ast_log(LOG_WARNING, "Dialgroup '%s' is too large.  Truncating list.\n", data);
			} else {
				res = 1;
				ao2_ref(entry, -1);
				break;
			}
		}
		ao2_ref(entry, -1);
	}
	ao2_iterator_destroy(&i);

	return res;
}
示例#30
0
/*! \brief Adds devicestate to local channels */
static int local_devicestate(const char *data)
{
	char *exten = ast_strdupa(data);
	char *context = NULL, *opts = NULL;
	int res;
	struct local_pvt *lp;
	struct ao2_iterator it;

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

	*context++ = '\0';

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

	ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);

	res = ast_exists_extension(NULL, context, exten, 1, NULL);
	if (!res)
		return AST_DEVICE_INVALID;

	res = AST_DEVICE_NOT_INUSE;

	it = ao2_iterator_init(locals, 0);
	while ((lp = ao2_iterator_next(&it)) && (res == AST_DEVICE_NOT_INUSE)) {
		if (!strcmp(exten, lp->exten) && !strcmp(context, lp->context) && lp->owner) {
			ao2_lock(lp);
			if (ast_test_flag(lp, LOCAL_LAUNCHED_PBX)) {
				res = AST_DEVICE_INUSE;
			}
			ao2_unlock(lp);
		}
		ao2_ref(lp, -1);
	}
	ao2_iterator_destroy(&it);

	return res;
}