Exemplo n.º 1
0
static void topic_dtor(void *obj)
{
	struct stasis_topic *topic = obj;

	/* Subscribers hold a reference to topics, so they should all be
	 * unsubscribed before we get here. */
	ast_assert(AST_VECTOR_SIZE(&topic->subscribers) == 0);

	ast_free(topic->name);
	topic->name = NULL;

	AST_VECTOR_FREE(&topic->subscribers);
	AST_VECTOR_FREE(&topic->upstream_topics);
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/*!
 * \brief Explicitly shutdown a session.
 *
 * \details An explicit shutdown is necessary, since the \ref stasis_app has a reference
 *          to this session. We also need to be sure to null out the \c ws_session field,
 *          since the websocket is about to go away.
 *
 * \internal
 *
 * \param session  Event session object (\ref event_session).
 */
static void event_session_shutdown(struct event_session *session)
{
	struct ao2_iterator i;
	char *app;
	int j;
	SCOPED_AO2LOCK(lock, session);

	/* Clean up the websocket_apps container */
	if (session->websocket_apps) {
		i = ao2_iterator_init(session->websocket_apps, 0);
		while ((app = ao2_iterator_next(&i))) {
			stasis_app_unregister(app);
			ao2_cleanup(app);
		}
		ao2_iterator_destroy(&i);
		ao2_cleanup(session->websocket_apps);
		session->websocket_apps = NULL;
	}

	/* Clean up the message_queue container */
	for (j = 0; j < AST_VECTOR_SIZE(&session->message_queue); j++) {
		struct ast_json *msg = AST_VECTOR_GET(&session->message_queue, j);
		ast_json_unref(msg);
	}
	AST_VECTOR_FREE(&session->message_queue);

	/* Remove the handle to the underlying websocket session */
	session->ws_session = NULL;
}
static void route_table_dtor(struct route_table *table)
{
	size_t idx;
	struct stasis_message_route *route;

	for (idx = 0; idx < AST_VECTOR_SIZE(table); ++idx) {
		route = AST_VECTOR_GET_ADDR(table, idx);
		ROUTE_TABLE_ELEM_CLEANUP(*route);
	}
	AST_VECTOR_FREE(table);
}
Exemplo n.º 5
0
/*!
 * \brief Internal cleanup function
 * \internal
 * \param mgr
 * \param pool_head
 * \param cleanup_type
 * 	     0: Reset all string fields and free all pools except the last or embedded pool.
 * 	        Keep the internal management structures so the structure can be reused.
 * 	    -1: Reset all string fields and free all pools except the embedded pool.
 * 	        Free the internal management structures.
 * \param file
 * \param lineno
 * \param func
 *
 * \retval 0 Success
 * \retval -1 Failure
 */
int __ast_string_field_free_memory(struct ast_string_field_mgr *mgr,
	struct ast_string_field_pool **pool_head, enum ast_stringfield_cleanup_type cleanup_type,
	const char *file, int lineno, const char *func)
{
	struct ast_string_field_pool *cur = NULL;
	struct ast_string_field_pool *preserve = NULL;

	/* reset all the fields regardless of cleanup type */
	AST_VECTOR_CALLBACK_VOID(&mgr->string_fields, reset_field);

	switch (cleanup_type) {
	case AST_STRINGFIELD_DESTROY:
		AST_VECTOR_FREE(&mgr->string_fields);

		if (mgr->embedded_pool) { /* ALWAYS preserve the embedded pool if there is one */
			preserve = mgr->embedded_pool;
			preserve->used = preserve->active = 0;
		}

		break;
	case AST_STRINGFIELD_RESET:
		/* Preserve the embedded pool if there is one, otherwise the last pool */
		if (mgr->embedded_pool) {
			preserve = mgr->embedded_pool;
		} else {
			if (*pool_head == NULL) {
				ast_log(LOG_WARNING, "trying to reset empty pool\n");
				return -1;
			}
			preserve = *pool_head;
		}
		preserve->used = preserve->active = 0;
		break;
	default:
		return -1;
	}

	cur = *pool_head;
	while (cur) {
		struct ast_string_field_pool *prev = cur->prev;

		if (cur != preserve) {
			ast_free(cur);
		}
		cur = prev;
	}

	*pool_head = preserve;
	if (preserve) {
		preserve->prev = NULL;
	}

	return 0;
}
Exemplo n.º 6
0
/*!
 * \internal
 * \brief Destructor for \ref ast_multi_object_blob objects
 */
static void multi_object_blob_dtor(void *obj)
{
	struct ast_multi_object_blob *multi = obj;
	int type;
	int i;

	for (type = 0; type < STASIS_UMOS_MAX; ++type) {
		for (i = 0; i < AST_VECTOR_SIZE(&multi->snapshots[type]); ++i) {
			ao2_cleanup(AST_VECTOR_GET(&multi->snapshots[type], i));
		}
		AST_VECTOR_FREE(&multi->snapshots[type]);
	}
	ast_json_unref(multi->blob);
}
Exemplo n.º 7
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);
}