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