static struct stasis_message_router *stasis_message_router_create_internal( struct stasis_topic *topic, int use_thread_pool) { int res; RAII_VAR(struct stasis_message_router *, router, NULL, ao2_cleanup); router = ao2_t_alloc(sizeof(*router), router_dtor, stasis_topic_name(topic)); if (!router) { return NULL; } res = 0; res |= AST_VECTOR_INIT(&router->routes, 0); res |= AST_VECTOR_INIT(&router->cache_routes, 0); if (res) { return NULL; } if (use_thread_pool) { router->subscription = stasis_subscribe_pool(topic, router_dispatch, router); } else { router->subscription = stasis_subscribe(topic, router_dispatch, router); } if (!router->subscription) { return NULL; } ao2_ref(router, +1); return router; }
static int test_init_cb(struct ast_test_info *info, struct ast_test *test) { received_user_events = 0; handler_received_message = 0; message_received = 0; AST_VECTOR_INIT(&expected_user_event_fields, DEFAULT_EXPECTED_EVENTS); AST_VECTOR_INIT(&bad_headers, DEFAULT_EXPECTED_EVENTS); return 0; }
/*! * \brief Internal initialization function * \internal * \param mgr * \param pool_head * \param needed * \param file * \param lineno * \param func * * \retval 0 Success * \retval -1 Failure */ int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, int needed, const char *file, int lineno, const char *func) { const char **p = (const char **) pool_head + 1; size_t initial_vector_size = ((size_t) (((char *)mgr) - ((char *)p))) / sizeof(*p); if (needed <= 0) { return __ast_string_field_free_memory(mgr, pool_head, needed, file, lineno, func); } mgr->last_alloc = NULL; #if defined(__AST_DEBUG_MALLOC) mgr->owner_file = file; mgr->owner_func = func; mgr->owner_line = lineno; #endif if (AST_VECTOR_INIT(&mgr->string_fields, initial_vector_size)) { return -1; } while ((struct ast_string_field_mgr *) p != mgr) { AST_VECTOR_APPEND(&mgr->string_fields, p); *p++ = __ast_string_field_empty; } *pool_head = NULL; mgr->embedded_pool = NULL; if (add_string_pool(mgr, pool_head, needed, file, lineno, func)) { AST_VECTOR_FREE(&mgr->string_fields); return -1; } return 0; }
struct stasis_topic *stasis_topic_create(const char *name) { struct stasis_topic *topic; int res = 0; topic = ao2_t_alloc(sizeof(*topic), topic_dtor, name); if (!topic) { return NULL; } topic->name = ast_strdup(name); res |= AST_VECTOR_INIT(&topic->subscribers, INITIAL_SUBSCRIBERS_MAX); res |= AST_VECTOR_INIT(&topic->upstream_topics, 0); if (!topic->name || res) { ao2_cleanup(topic); return NULL; } return topic; }
static int create_artificial_endpoint(void) { artificial_endpoint = ast_sorcery_alloc(ast_sip_get_sorcery(), "endpoint", NULL); if (!artificial_endpoint) { return -1; } AST_VECTOR_INIT(&artificial_endpoint->inbound_auths, 1); /* Pushing a bogus value into the vector will ensure that * the proper size of the vector is returned. This value is * not actually used anywhere */ AST_VECTOR_APPEND(&artificial_endpoint->inbound_auths, ast_strdup("artificial-auth")); return 0; }
/*! * \internal * \brief Remove excess existing contacts that expire the soonest. * \since 13.18.0 * * \param contacts Container of unmodified contacts that could remove. * \param to_remove Maximum number of contacts to remove. * * \return Nothing */ static void remove_excess_contacts(struct ao2_container *contacts, struct ao2_container *response_contacts, unsigned int to_remove) { struct excess_contact_vector contact_vec; /* * Create a sorted vector to hold the to_remove soonest to * expire contacts. The vector has an extra space to * temporarily hold the longest to expire contact that we * won't remove. */ if (AST_VECTOR_INIT(&contact_vec, to_remove + 1)) { return; } ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, vec_contact_add, &contact_vec); /* * The vector should always be populated with the number * of contacts we need to remove. Just in case, we will * remove all contacts in the vector even if the contacts * container had fewer contacts than there should be. */ ast_assert(AST_VECTOR_SIZE(&contact_vec) == to_remove); to_remove = AST_VECTOR_SIZE(&contact_vec); /* Remove the excess contacts that expire the soonest */ while (to_remove--) { struct ast_sip_contact *contact; contact = AST_VECTOR_GET(&contact_vec, to_remove); ast_sip_location_delete_contact(contact); ast_verb(3, "Removed contact '%s' from AOR '%s' due to remove_existing\n", contact->uri, contact->aor); ast_test_suite_event_notify("AOR_CONTACT_REMOVED", "Contact: %s\r\n" "AOR: %s\r\n" "UserAgent: %s", contact->uri, contact->aor, contact->user_agent); ao2_unlink(response_contacts, contact); } AST_VECTOR_FREE(&contact_vec); }
void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset, size_t field_mgr_pool_offset, size_t pool_size, const char *file, int lineno, const char *func) { struct ast_string_field_mgr *mgr; struct ast_string_field_pool *pool; struct ast_string_field_pool **pool_head; size_t pool_size_needed = sizeof(*pool) + pool_size; size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed); void *allocation; const char **p; size_t initial_vector_size; ast_assert(num_structs == 1); if (!(allocation = calloc_wrapper(num_structs, size_to_alloc, file, lineno, func))) { return NULL; } mgr = allocation + field_mgr_offset; pool = allocation + struct_size; pool_head = allocation + field_mgr_pool_offset; p = (const char **) pool_head + 1; initial_vector_size = ((size_t) (((char *)mgr) - ((char *)p))) / sizeof(*p); if (AST_VECTOR_INIT(&mgr->string_fields, initial_vector_size)) { ast_free(allocation); return NULL; } while ((struct ast_string_field_mgr *) p != mgr) { AST_VECTOR_APPEND(&mgr->string_fields, p); *p++ = __ast_string_field_empty; } mgr->embedded_pool = pool; *pool_head = pool; pool->size = size_to_alloc - struct_size - sizeof(*pool); #if defined(__AST_DEBUG_MALLOC) mgr->owner_file = file; mgr->owner_func = func; mgr->owner_line = lineno; #endif return allocation; }
/*! \brief Create a stasis user event multi object blob */ struct ast_multi_object_blob *ast_multi_object_blob_create(struct ast_json *blob) { int type; RAII_VAR(struct ast_multi_object_blob *, multi, ao2_alloc(sizeof(*multi), multi_object_blob_dtor), ao2_cleanup); ast_assert(blob != NULL); if (!multi) { return NULL; } for (type = 0; type < STASIS_UMOS_MAX; ++type) { if (AST_VECTOR_INIT(&multi->snapshots[type], 0)) { return NULL; } } multi->blob = ast_json_ref(blob); ao2_ref(multi, +1); return multi; }
struct ast_vector_string *__ast_bt_get_symbols(void **addresses, size_t num_frames) { struct ast_vector_string *return_strings; int stackfr; bfd *bfdobj; long allocsize; char msg[MSG_BUFF_LEN]; static pthread_mutex_t bfd_mutex = PTHREAD_MUTEX_INITIALIZER; return_strings = malloc(sizeof(struct ast_vector_string)); if (!return_strings) { return NULL; } if (AST_VECTOR_INIT(return_strings, num_frames)) { free(return_strings); return NULL; } for (stackfr = 0; stackfr < num_frames; stackfr++) { int symbolcount; struct bfd_data data = { .return_strings = return_strings, .msg = msg, .pc = (bfd_vma)(uintptr_t) addresses[stackfr], .found = 0, .dynamic = 0, }; msg[0] = '\0'; if (!dladdr((void *)(uintptr_t) data.pc, &data.dli)) { continue; } data.libname = strrchr(data.dli.dli_fname, '/'); if (!data.libname) { data.libname = data.dli.dli_fname; } else { data.libname++; } pthread_mutex_lock(&bfd_mutex); /* Using do while(0) here makes it easier to escape and clean up */ do { bfdobj = bfd_openr(data.dli.dli_fname, NULL); if (!bfdobj) { break; } /* bfd_check_format does more than check. It HAS to be called */ if (!bfd_check_format(bfdobj, bfd_object)) { break; } data.has_syms = !!(bfd_get_file_flags(bfdobj) & HAS_SYMS); data.dynamic = !!(bfd_get_file_flags(bfdobj) & DYNAMIC); if (!data.has_syms) { break; } allocsize = data.dynamic ? bfd_get_dynamic_symtab_upper_bound(bfdobj) : bfd_get_symtab_upper_bound(bfdobj); if (allocsize < 0) { break; } data.syms = malloc(allocsize); if (!data.syms) { break; } symbolcount = data.dynamic ? bfd_canonicalize_dynamic_symtab(bfdobj, data.syms) : bfd_canonicalize_symtab(bfdobj, data.syms); if (symbolcount < 0) { break; } bfd_map_over_sections(bfdobj, process_section, &data); } while(0); if (bfdobj) { bfd_close(bfdobj); free(data.syms); data.syms = NULL; } pthread_mutex_unlock(&bfd_mutex); /* Default output, if we cannot find the information within BFD */ if (!data.found) { snprintf(msg, sizeof(msg), "%s %s()", data.libname, S_OR(data.dli.dli_sname, "<unknown>")); AST_VECTOR_APPEND(return_strings, strdup(msg)); } } return return_strings; } #else struct ast_vector_string *__ast_bt_get_symbols(void **addresses, size_t num_frames) { char **strings; struct ast_vector_string *return_strings; int i; return_strings = malloc(sizeof(struct ast_vector_string)); if (!return_strings) { return NULL; } if (AST_VECTOR_INIT(return_strings, num_frames)) { free(return_strings); return NULL; } strings = backtrace_symbols(addresses, num_frames); if (strings) { for (i = 0; i < num_frames; i++) { AST_VECTOR_APPEND(return_strings, strdup(strings[i])); } free(strings); } return return_strings; }
/*! * \brief Creates an \ref event_session object and registers its apps with Stasis. * * \internal * * \param ser HTTP TCP/TLS Server Session (\ref ast_tcptls_session_instance). * \param args The Stasis [app] parameters as parsed from the HTTP request * (\ref ast_ari_events_event_websocket_args). * \param session_id The id for the websocket session that will be created for this * event session. * * \retval 0 on success * \retval -1 on failure */ static int event_session_alloc(struct ast_tcptls_session_instance *ser, struct ast_ari_events_event_websocket_args *args, const char *session_id) { RAII_VAR(struct event_session *, session, NULL, ao2_cleanup); size_t size, i; /* The request must have at least one [app] parameter */ if (args->app_count == 0) { return event_session_allocation_error_handler( session, ERROR_TYPE_MISSING_APP_PARAM, ser); } size = sizeof(*session) + strlen(session_id) + 1; /* Instantiate the event session */ session = ao2_alloc(size, event_session_dtor); if (!session) { return event_session_allocation_error_handler(session, ERROR_TYPE_OOM, ser); } strncpy(session->session_id, session_id, size - sizeof(*session)); /* Instantiate the hash table for Stasis apps */ session->websocket_apps = ast_str_container_alloc(APPS_NUM_BUCKETS); if (!session->websocket_apps) { return event_session_allocation_error_handler(session, ERROR_TYPE_OOM, ser); } /* Instantiate the message queue */ if (AST_VECTOR_INIT(&session->message_queue, MESSAGES_INIT_SIZE)) { return event_session_allocation_error_handler(session, ERROR_TYPE_OOM, ser); } /* Register the apps with Stasis */ for (i = 0; i < args->app_count; ++i) { const char *app = args->app[i]; if (ast_strlen_zero(app)) { return event_session_allocation_error_handler( session, ERROR_TYPE_INVALID_APP_PARAM, ser); } if (ast_str_container_add(session->websocket_apps, app)) { return event_session_allocation_error_handler(session, ERROR_TYPE_OOM, ser); } if (stasis_app_register(app, stasis_app_message_handler, session)) { ast_log(LOG_WARNING, "Stasis registration failed for application: '%s'\n", app); return event_session_allocation_error_handler( session, ERROR_TYPE_STASIS_REGISTRATION, ser); } } /* Add the event session to the local registry */ if (!ao2_link(event_session_registry, session)) { return event_session_allocation_error_handler(session, ERROR_TYPE_OOM, ser); } return 0; }