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