Example #1
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;
}
Example #2
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);
}
Example #3
0
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));
}
Example #4
0
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;
}
Example #5
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;
}
Example #6
0
/*!
 * \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;
}
Example #8
0
/*!
 * \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;
}
Example #9
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);
}
Example #10
0
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;
}