Beispiel #1
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;
}
Beispiel #2
0
/*!
 * \internal
 * \brief A contact has been deleted remove status tracking.
 */
static void contact_deleted(const void *obj)
{
	struct ast_sip_contact *contact = (struct ast_sip_contact *) obj;
	struct ast_sip_contact_status *status;

	unschedule_qualify(contact);

	status = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(contact));
	if (!status) {
		return;
	}

	if (ast_sorcery_delete(ast_sip_get_sorcery(), status)) {
		ast_log(LOG_ERROR, "Unable to delete ast_sip_contact_status for contact %s\n",
			contact->uri);
	}
	ao2_ref(status, -1);
}
static enum ast_timer_event pthread_timer_get_event(int handle)
{
	struct pthread_timer *timer;
	enum ast_timer_event res = AST_TIMING_EVENT_EXPIRED;

	if (!(timer = find_timer(handle, 0))) {
		return res;
	}

	ao2_lock(timer);
	if (timer->continuous && timer->pending_ticks == 1) {
		res = AST_TIMING_EVENT_CONTINUOUS;
	}
	ao2_unlock(timer);

	ao2_ref(timer, -1);

	return res;
}
static int pthread_timer_ack(int handle, unsigned int quantity)
{
	struct pthread_timer *timer;
	int res;

	ast_assert(quantity > 0);

	if (!(timer = find_timer(handle, 0))) {
		return -1;
	}

	ao2_lock(timer);
	res = read_pipe(timer, quantity);
	ao2_unlock(timer);

	ao2_ref(timer, -1);

	return res;
}
Beispiel #5
0
/*! \brief Custom handler for permanent URIs */
static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
	struct ast_sip_aor *aor = obj;
	const char *aor_id = ast_sorcery_object_get_id(aor);
	char *contacts;
	char *contact_uri;

	if (ast_strlen_zero(var->value)) {
		return 0;
	}

	contacts = ast_strdupa(var->value);
	while ((contact_uri = strsep(&contacts, ","))) {
		struct ast_sip_contact *contact;
		char contact_id[strlen(aor_id) + strlen(contact_uri) + 2 + 1];

		if (ast_sip_push_task_synchronous(NULL, permanent_contact_validate, contact_uri)) {
			ast_log(LOG_ERROR, "Permanent URI on aor '%s' with contact '%s' failed to parse\n",
				ast_sorcery_object_get_id(aor), contact_uri);
			return -1;
		}

		if (!aor->permanent_contacts) {
			aor->permanent_contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
				AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL);
			if (!aor->permanent_contacts) {
				return -1;
			}
		}

		snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, contact_uri);
		contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id);
		if (!contact) {
			return -1;
		}

		ast_string_field_set(contact, uri, contact_uri);
		ao2_link(aor->permanent_contacts, contact);
		ao2_ref(contact, -1);
	}

	return 0;
}
Beispiel #6
0
static struct app_forwards *forwards_create(struct stasis_app *app,
	const char *id)
{
	RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);

	if (!app || ast_strlen_zero(id)) {
		return NULL;
	}

	forwards = ao2_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor);
	if (!forwards) {
		return NULL;
	}

	strcpy(forwards->id, id);

	ao2_ref(forwards, +1);
	return forwards;
}
/*! \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;
}
static int bucket_http_wizard_is_stale(const struct ast_sorcery *sorcery, void *data, void *object)
{
	struct ast_bucket_file *bucket_file = object;
	struct ast_bucket_metadata *metadata;
	struct curl_slist *header_list = NULL;
	long http_code;
	CURL *curl;
	struct curl_bucket_file_data cb_data = {
		.bucket_file = bucket_file
	};
	char etag_buf[256];

	if (!bucket_file_expired(bucket_file) && !bucket_file_always_revalidate(bucket_file)) {
		return 0;
	}

	/* See if we have an ETag for this item. If not, it's stale. */
	metadata = ast_bucket_file_metadata_get(bucket_file, "etag");
	if (!metadata) {
		return 1;
	}

	curl = get_curl_instance(&cb_data);

	/* Set the ETag header on our outgoing request */
	snprintf(etag_buf, sizeof(etag_buf), "If-None-Match: %s", metadata->value);
	header_list = curl_slist_append(header_list, etag_buf);
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
	curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
	ao2_ref(metadata, -1);

	http_code = execute_curl_instance(curl);

	curl_slist_free_all(header_list);

	if (http_code == 304) {
		bucket_file_set_expiration(bucket_file);
		return 0;
	}

	return 1;
}
Beispiel #9
0
static int get_message_count(void *obj, void *arg, int flags)
{
	struct stasis_message *msg;
	struct mwi_stasis_subscription *mwi_stasis = obj;
	struct ast_sip_message_accumulator *counter = arg;
	struct ast_mwi_state *mwi_state;

	msg = stasis_cache_get(ast_mwi_state_cache(), ast_mwi_state_type(), mwi_stasis->mailbox);
	if (!msg) {
		return 0;
	}

	mwi_state = stasis_message_data(msg);
	counter->old_msgs += mwi_state->old_msgs;
	counter->new_msgs += mwi_state->new_msgs;

	ao2_ref(msg, -1);

	return 0;
}
Beispiel #10
0
struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_topic)
{
	struct stasis_topic_pool *pool;

	pool = ao2_alloc_options(sizeof(*pool), topic_pool_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
	if (!pool) {
		return NULL;
	}

	pool->pool_container = ao2_container_alloc(TOPIC_POOL_BUCKETS,
		topic_pool_entry_hash, topic_pool_entry_cmp);
	if (!pool->pool_container) {
		ao2_cleanup(pool);
		return NULL;
	}
	ao2_ref(pooled_topic, +1);
	pool->pool_topic = pooled_topic;

	return pool;
}
static struct ast_datastore *dialog_info_xml_state_find_or_create(struct ao2_container *datastores)
{
	struct ast_datastore *datastore = ast_datastores_find(datastores, "dialog-info+xml");

	if (datastore) {
		return datastore;
	}

	datastore = ast_datastores_alloc_datastore(&dialog_info_xml_datastore, "dialog-info+xml");
	if (!datastore) {
		return NULL;
	}
	datastore->data = ast_calloc(1, sizeof(struct dialog_info_xml_state));
	if (!datastore->data || ast_datastores_add(datastores, datastore)) {
		ao2_ref(datastore, -1);
		return NULL;
	}

	return datastore;
}
Beispiel #12
0
static void mwi_to_ami(struct ast_sip_subscription *sub,
		       struct ast_str **buf)
{
	struct mwi_subscription *mwi_sub;
	struct ast_datastore *mwi_datastore;

	mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
	if (!mwi_datastore) {
		return;
	}

	mwi_sub = mwi_datastore->data;

	ast_str_append(buf, 0, "SubscriptionType: mwi\r\n");
	ast_str_append(buf, 0, "Mailboxes: ");
	mwi_subscription_mailboxes_str(mwi_sub->stasis_subs, buf);
	ast_str_append(buf, 0, "\r\n");

	ao2_ref(mwi_datastore, -1);
}
Beispiel #13
0
static int pthread_timer_disable_continuous(int handle)
{
	struct pthread_timer *timer;

	if (!(timer = find_timer(handle, 0))) {
		errno = EINVAL;
		return -1;
	}

	ao2_lock(timer);
	if (timer->continuous) {
		timer->continuous = 0;
		read_pipe(timer, 1);
	}
	ao2_unlock(timer);

	ao2_ref(timer, -1);

	return 0;
}
static char *complete_parking_lot(const char *word, int seeking)
{
	char *ret = NULL;
	struct parking_lot *lot;
	struct ao2_container *global_lots = get_parking_lot_container();
	struct parking_lot_complete search = {
		.seeking = seeking,
		};

	lot = ao2_callback_data(global_lots, ast_strlen_zero(word) ? 0 : OBJ_PARTIAL_KEY,
		complete_parking_lot_search, (char *) word, &search);

	if (!lot) {
		return NULL;
	}

	ret = ast_strdup(lot->name);
	ao2_ref(lot, -1);
	return ret;
}
Beispiel #15
0
/*! \internal
 * \brief get joint format attributes using an interface
 */
static int format_joint_helper(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result)
{
	int res = 0;
	struct interface_ao2_wrapper *wrapper;

	if (!(wrapper = find_interface(format1))) {
		/* if no interface is present, we assume formats are joint by id alone */
		return res;
	}

	ast_rwlock_rdlock(&wrapper->wraplock);
	if (wrapper->interface && wrapper->interface->format_attr_get_joint) {
		res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr);
	}
	ast_rwlock_unlock(&wrapper->wraplock);

	ao2_ref(wrapper, -1);

	return res;
}
Beispiel #16
0
/*! \brief Allocator for AOR */
static void *aor_alloc(const char *name)
{
	void *lock;
	struct ast_sip_aor *aor;

	lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", name);
	if (!lock) {
		return NULL;
	}

	aor = ast_sorcery_lockable_alloc(sizeof(struct ast_sip_aor), aor_destroy, lock);
	ao2_ref(lock, -1);

	if (!aor) {
		return NULL;
	}
	ast_string_field_init(aor, 128);

	return aor;
}
Beispiel #17
0
/*!
 * \internal
 * \brief Construct a notify URI data object for AMI.
 */
static struct notify_uri_data* notify_ami_uri_data_create(
	const char *uri, void *info)
{
	struct notify_uri_data *data = ao2_alloc(sizeof(*data),
							notify_ami_uri_data_destroy);
	if (!data) {
		return NULL;
	}

	data->uri = ast_strdup(uri);
	if (!data->uri) {
		ao2_ref(data, -1);
		return NULL;
	}

	data->info = info;
	data->build_notify = build_ami_notify;

	return data;
}
static struct ast_datastore *dialog_info_xml_state_find_or_create(struct ast_sip_subscription *sub)
{
	struct ast_datastore *datastore = ast_sip_subscription_get_datastore(sub, "dialog-info+xml");

	if (datastore) {
		return datastore;
	}

	datastore = ast_sip_subscription_alloc_datastore(&dialog_info_xml_datastore, "dialog-info+xml");
	if (!datastore) {
		return NULL;
	}
	datastore->data = ast_calloc(1, sizeof(struct dialog_info_xml_state));
	if (!datastore->data || ast_sip_subscription_add_datastore(sub, datastore)) {
		ao2_ref(datastore, -1);
		return NULL;
	}

	return datastore;
}
Beispiel #19
0
static int lookup_element(unsigned int *seedp)
{
	char keybuf[100];
	struct ht_element *el, lookup;
	int x;
	
	/* pick a random element from 0 to highwater-1 */
	x = my_rand(0,glob_highwater-1,seedp);
	sprintf(keybuf, "key%08d", x);
	lookup.key = keybuf;
	el = ao2_find(glob_hashtab, &lookup, OBJ_POINTER);
	els_lookedup++;
	if (el) {
		els_found++;
		ao2_ref(el, -1); /* toss out this ref, no longer needed */
		return 1;
	} else {
		return 0;
	}
}
int ast_local_init(void)
{

	if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_begin_type)) {
		return -1;
	}

	if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_end_type)) {
		return -1;
	}

	if (STASIS_MESSAGE_TYPE_INIT(ast_local_bridge_type)) {
		return -1;
	}

	if (!(local_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
		return -1;
	}
	ast_format_cap_append_by_type(local_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);

	locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
	if (!locals) {
		ao2_cleanup(local_tech.capabilities);
		local_tech.capabilities = NULL;
		return -1;
	}

	/* Make sure we can register our channel type */
	if (ast_channel_register(&local_tech)) {
		ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
		ao2_ref(locals, -1);
		ao2_cleanup(local_tech.capabilities);
		local_tech.capabilities = NULL;
		return -1;
	}
	ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
	ast_manager_register_xml_core("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away);

	ast_register_cleanup(local_shutdown);
	return 0;
}
Beispiel #21
0
struct ast_channel_snapshot *ast_channel_snapshot_get_latest_by_name(const char *name)
{
	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
	struct ast_channel_snapshot *snapshot;

	ast_assert(!ast_strlen_zero(name));

	message = stasis_cache_get(ast_channel_cache_by_name(),
			ast_channel_snapshot_type(),
			name);
	if (!message) {
		return NULL;
	}

	snapshot = stasis_message_data(message);
	if (!snapshot) {
		return NULL;
	}
	ao2_ref(snapshot, +1);
	return snapshot;
}
Beispiel #22
0
struct stasis_cache *stasis_cache_create(snapshot_get_id id_fn)
{
        RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);

        cache = ao2_alloc_options(sizeof(*cache), cache_dtor,
		AO2_ALLOC_OPT_LOCK_NOLOCK);
        if (!cache) {
                return NULL;
        }

        cache->entries = ao2_container_alloc(NUM_CACHE_BUCKETS, cache_entry_hash,
                cache_entry_cmp);
        if (!cache->entries) {
                return NULL;
        }

        cache->id_fn = id_fn;

        ao2_ref(cache, +1);
        return cache;
}
Beispiel #23
0
/*! \brief Destroy function which unreserves/unreferences/removes a multiplexed thread structure */
static int multiplexed_bridge_destroy(struct ast_bridge *bridge)
{
	struct multiplexed_thread *multiplexed_thread = bridge->bridge_pvt;

	ao2_lock(multiplexed_threads);

	multiplexed_thread->count -= 2;

	if (!multiplexed_thread->count) {
		ast_debug(1, "Unlinking multiplexed thread '%p' since nobody is using it anymore\n", multiplexed_thread);
		ao2_unlink(multiplexed_threads, multiplexed_thread);
	}

	multiplexed_nudge(multiplexed_thread);

	ao2_unlock(multiplexed_threads);

	ao2_ref(multiplexed_thread, -1);

	return 0;
}
Beispiel #24
0
/*!
 * \internal
 * \brief Post initial MWI count events.
 * \since 12.1.0
 *
 * \return Nothing
 */
static void mwi_initial_events(void)
{
	struct ao2_container *mailboxes;
	const struct ast_mwi_mailbox_object *mailbox;
	struct ao2_iterator iter;

	/* Get all mailbox counts. */
	mailboxes = ast_mwi_mailbox_get_all();
	if (!mailboxes) {
		return;
	}

	/* Post all mailbox counts. */
	iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK);
	for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) {
		mwi_post_event(mailbox);
	}
	ao2_iterator_destroy(&iter);

	ao2_ref(mailboxes, -1);
}
Beispiel #25
0
struct stasis_message *stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
{
	RAII_VAR(struct cache_entry *, search_entry, NULL, ao2_cleanup);
	RAII_VAR(struct cache_entry *, cached_entry, NULL, ao2_cleanup);

	ast_assert(cache->entries != NULL);

	search_entry = cache_entry_create(type, id, NULL);
	if (search_entry == NULL) {
		return NULL;
	}

	cached_entry = ao2_find(cache->entries, search_entry, OBJ_POINTER);
	if (cached_entry == NULL) {
		return NULL;
	}

	ast_assert(cached_entry->snapshot != NULL);
	ao2_ref(cached_entry->snapshot, +1);
	return cached_entry->snapshot;
}
Beispiel #26
0
/*! /brief Grow the hash data as specified */
static void *hash_test_grow(void *d)
{
    struct hash_test *data = d;
    int i;

    for (i = 0; i < data->max_grow; ++i) {
        char *ht;
        if (is_timed_out(data)) {
            printf("Growth timed out at %d\n", i);
            return "Growth timed out";
        }
        ht = ht_new(i);
        if (ht == NULL) {
            return "Allocation failed";
        }
        ao2_link(data->to_be_thrashed, ht);
        ao2_ref(ht, -1);
        ast_atomic_fetchadd_int(&data->grow_count, 1);
    }
    return NULL;
}
Beispiel #27
0
/*! \brief Called when a channel should be hung up */
static int bridge_hangup(struct ast_channel *ast)
{
	struct bridge_pvt *p = ast->tech_pvt;

	if (!p) {
		return 0;
	}

	ao2_lock(p);
	if (p->input == ast) {
		p->input = NULL;
	} else if (p->output == ast) {
		p->output = NULL;
	}
	ao2_unlock(p);

	ast->tech_pvt = NULL;
	ao2_ref(p, -1);

	return 0;
}
Beispiel #28
0
/*! \brief Part of PBX interface */
static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
	struct local_pvt *p;
	struct ast_channel *chan;
	ast_callid callid;

	/* Allocate a new private structure and then Asterisk channels */
	p = local_alloc(data, cap);
	if (!p) {
		return NULL;
	}
	callid = ast_read_threadstorage_callid();
	chan = ast_unreal_new_channels(&p->base, &local_tech, AST_STATE_DOWN, AST_STATE_RING,
		p->exten, p->context, assignedids, requestor, callid);
	if (chan) {
		ao2_link(locals, p);
	}
	ao2_ref(p, -1); /* kill the ref from the alloc */

	return chan;
}
Beispiel #29
0
static void aor_deleted_observer(const void *object)
{
	const struct ast_sip_aor *aor = object;
	const char *aor_id = ast_sorcery_object_get_id(object);
	/* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
	char regex[strlen(aor_id) + 4];
	struct ao2_container *contacts;

	if (aor->permanent_contacts) {
		ao2_callback(aor->permanent_contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, destroy_contact, NULL);
	}

	snprintf(regex, sizeof(regex), "^%s;@", aor_id);
	if (!(contacts = ast_sorcery_retrieve_by_regex(ast_sip_get_sorcery(), "contact", regex))) {
		return;
	}
	/* Destroy any contacts that may still exist that were made for this AoR */
	ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, destroy_contact, NULL);

	ao2_ref(contacts, -1);
}
Beispiel #30
0
static struct stasis_app_command *exec_command(
	struct stasis_app_control *control, stasis_app_command_cb command_fn,
	void *data)
{
	RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);

	command_fn = command_fn ? : noop_cb;

	command = command_create(command_fn, data);
	if (!command) {
		return NULL;
	}

	ao2_lock(control->command_queue);
	ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
	ast_cond_signal(&control->wait_cond);
	ao2_unlock(control->command_queue);

	ao2_ref(command, +1);
	return command;
}