/*! * \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; }
/*! \brief Add an object (snapshot) to the blob */ void ast_multi_object_blob_add(struct ast_multi_object_blob *multi, enum stasis_user_multi_object_snapshot_type type, void *object) { if (!multi || !object) { return; } AST_VECTOR_APPEND(&multi->snapshots[type],object); }
static void process_section(bfd *bfdobj, asection *section, void *obj) { struct bfd_data *data = obj; const char *file, *func; unsigned int line; bfd_vma offset; bfd_vma vma; bfd_size_type size; bfd_boolean line_found = 0; char *fn; int inlined = 0; offset = data->pc - (data->dynamic ? (bfd_vma)(uintptr_t) data->dli.dli_fbase : 0); if (!(bfd_get_section_flags(bfdobj, section) & SEC_ALLOC)) { return; } vma = bfd_get_section_vma(bfdobj, section); size = bfd_get_section_size(section); if (offset < vma || offset >= vma + size) { /* Not in this section */ return; } line_found = bfd_find_nearest_line(bfdobj, section, data->syms, offset - vma, &file, &func, &line); if (!line_found) { return; } /* * If we find a line, we will want to continue calling bfd_find_inliner_info * to capture any inlined functions that don't have their own stack frames. */ do { data->found++; /* file can possibly be null even with a success result from bfd_find_nearest_line */ file = file ? file : ""; fn = strrchr(file, '/'); #define FMT_INLINED "[%s] %s %s:%u %s()" #define FMT_NOT_INLINED "[%p] %s %s:%u %s()" snprintf(data->msg, MSG_BUFF_LEN, inlined ? FMT_INLINED : FMT_NOT_INLINED, inlined ? "inlined" : (char *)(uintptr_t) data->pc, data->libname, fn ? fn + 1 : file, line, S_OR(func, "???")); if (AST_VECTOR_APPEND(data->return_strings, strdup(data->msg))) { return; } inlined++; /* Let's see if there are any inlined functions */ } while (bfd_find_inliner_info(bfdobj, &file, &func, &line)); }
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; }
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 Callback handler for Stasis application messages. * * \internal * * \param data Void pointer to the event session (\ref event_session). * \param app_name Name of the Stasis application that dispatched the message. * \param message The dispatched message. */ static void stasis_app_message_handler( void *data, const char *app_name, struct ast_json *message) { struct event_session *session = data; const char *msg_type, *msg_application; ast_assert(session != NULL); ao2_lock(session); msg_type = S_OR(ast_json_string_get(ast_json_object_get(message, "type")), ""); msg_application = S_OR( ast_json_string_get(ast_json_object_get(message, "application")), ""); /* If we've been replaced, remove the application from our local websocket_apps container */ if (strcmp(msg_type, "ApplicationReplaced") == 0 && strcmp(msg_application, app_name) == 0) { ao2_find(session->websocket_apps, msg_application, OBJ_UNLINK | OBJ_NODATA); } /* Now, we need to determine our state to see how we will handle the message */ if (ast_json_object_set(message, "application", ast_json_string_create(app_name))) { /* We failed to add an application element to our json message */ ast_log(LOG_WARNING, "Failed to dispatch '%s' message from Stasis app '%s'; could not update message\n", msg_type, msg_application); } else if (!session->ws_session) { /* If the websocket is NULL, the message goes to the queue */ AST_VECTOR_APPEND(&session->message_queue, message); ast_log(LOG_WARNING, "Queued '%s' message for Stasis app '%s'; websocket is not ready\n", msg_type, msg_application); } else { /* We are ready to publish the message */ ast_ari_websocket_session_write(session->ws_session, message); } ao2_unlock(session); }
static int route_table_add(struct route_table *table, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data) { struct stasis_message_route route; int res; ast_assert(callback != NULL); ast_assert(route_table_find(table, message_type) == NULL); route.message_type = ao2_bump(message_type); route.callback = callback; route.data = data; res = AST_VECTOR_APPEND(table, route); if (res) { ROUTE_TABLE_ELEM_CLEANUP(route); } return res; }
/*! * \brief Add a subscriber to a topic. * \param topic Topic * \param sub Subscriber * \return 0 on success * \return Non-zero on error */ static int topic_add_subscription(struct stasis_topic *topic, struct stasis_subscription *sub) { size_t idx; SCOPED_AO2LOCK(lock, topic); /* The reference from the topic to the subscription is shared with * the owner of the subscription, which will explicitly unsubscribe * to release it. * * If we bumped the refcount here, the owner would have to unsubscribe * and cleanup, which is a bit awkward. */ AST_VECTOR_APPEND(&topic->subscribers, sub); for (idx = 0; idx < AST_VECTOR_SIZE(&topic->upstream_topics); ++idx) { topic_add_subscription( AST_VECTOR_GET(&topic->upstream_topics, idx), sub); } return 0; }
struct stasis_forward *stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic) { int res; size_t idx; RAII_VAR(struct stasis_forward *, forward, NULL, ao2_cleanup); if (!from_topic || !to_topic) { return NULL; } forward = ao2_alloc_options(sizeof(*forward), forward_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!forward) { return NULL; } /* Forwards to ourselves are implicit. */ if (to_topic == from_topic) { return ao2_bump(forward); } forward->from_topic = ao2_bump(from_topic); forward->to_topic = ao2_bump(to_topic); topic_lock_both(to_topic, from_topic); res = AST_VECTOR_APPEND(&to_topic->upstream_topics, from_topic); if (res != 0) { ao2_unlock(from_topic); ao2_unlock(to_topic); return NULL; } for (idx = 0; idx < AST_VECTOR_SIZE(&to_topic->subscribers); ++idx) { topic_add_subscription(from_topic, AST_VECTOR_GET(&to_topic->subscribers, idx)); } ao2_unlock(from_topic); ao2_unlock(to_topic); return ao2_bump(forward); }
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; }