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); }
/*! * \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 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); }
/*! * \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; }
/*! * \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); }
/*! * \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); }