/*! \brief Allocate an \ref ast_ari_conf for config parsing */ static void *conf_alloc(void) { struct ast_ari_conf *cfg; cfg = ao2_alloc_options(sizeof(*cfg), conf_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!cfg) { return NULL; } cfg->general = ao2_alloc_options(sizeof(*cfg->general), conf_general_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK); cfg->users = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, user_sort_cmp, NULL); if (!cfg->users || !cfg->general || ast_string_field_init(cfg->general, 64) || aco_set_defaults(&general_option, "general", cfg->general)) { ao2_ref(cfg, -1); return NULL; } return cfg; }
/*! \brief Allocate an \ref ast_ari_conf for config parsing */ static void *conf_alloc(void) { RAII_VAR(struct ast_ari_conf *, cfg, NULL, ao2_cleanup); cfg = ao2_alloc_options(sizeof(*cfg), conf_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!cfg) { return NULL; } cfg->general = ao2_alloc_options(sizeof(*cfg->general), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!cfg->general) { return NULL; } aco_set_defaults(&general_option, "general", cfg->general); if (ast_string_field_init(cfg->general, 64)) { return NULL; } cfg->users = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, user_sort_cmp, NULL); ao2_ref(cfg, +1); return cfg; }
struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *data, enum stasis_app_subscription_model subscription_model) { RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup); size_t size; int res = 0; size_t context_size = strlen("stasis-") + strlen(name) + 1; char context_name[context_size]; ast_assert(name != NULL); ast_assert(handler != NULL); ast_verb(1, "Creating Stasis app '%s'\n", name); size = sizeof(*app) + strlen(name) + 1; app = ao2_alloc_options(size, app_dtor, AO2_ALLOC_OPT_LOCK_MUTEX); if (!app) { return NULL; } app->subscription_model = subscription_model; app->forwards = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT, forwards_sort, NULL); if (!app->forwards) { return NULL; } app->topic = stasis_topic_create(name); if (!app->topic) { return NULL; } app->bridge_router = stasis_message_router_create(ast_bridge_topic_all()); if (!app->bridge_router) { return NULL; } res |= stasis_message_router_add(app->bridge_router, ast_bridge_merge_message_type(), bridge_merge_handler, app); res |= stasis_message_router_add(app->bridge_router, ast_blind_transfer_type(), bridge_blind_transfer_handler, app); res |= stasis_message_router_add(app->bridge_router, ast_attended_transfer_type(), bridge_attended_transfer_handler, app); res |= stasis_message_router_add(app->bridge_router, stasis_subscription_change_type(), bridge_subscription_change_handler, app); if (res != 0) { return NULL; } /* Bridge router holds a reference */ ao2_ref(app, +1); app->router = stasis_message_router_create(app->topic); if (!app->router) { return NULL; } res |= stasis_message_router_add(app->router, ast_bridge_snapshot_type(), sub_bridge_update_handler, app); res |= stasis_message_router_add(app->router, ast_channel_snapshot_type(), sub_channel_update_handler, app); res |= stasis_message_router_add_cache_update(app->router, ast_endpoint_snapshot_type(), sub_endpoint_update_handler, app); res |= stasis_message_router_add(app->router, stasis_subscription_change_type(), sub_subscription_change_handler, app); stasis_message_router_set_formatters_default(app->router, sub_default_handler, app, STASIS_SUBSCRIPTION_FORMATTER_JSON); if (res != 0) { return NULL; } /* Router holds a reference */ ao2_ref(app, +1); strncpy(app->name, name, size - sizeof(*app)); app->handler = handler; app->data = ao2_bump(data); /* Create a context, a match-all extension, and a 'h' extension for this application. Note that * this should only be done if a context does not already exist. */ strcpy(context_name, "stasis-"); strcat(context_name, name); if (!ast_context_find(context_name)) { if (!ast_context_find_or_create(NULL, NULL, context_name, "res_stasis")) { ast_log(LOG_WARNING, "Could not create context '%s' for Stasis application '%s'\n", context_name, name); } else { ast_add_extension(context_name, 0, "_.", 1, NULL, NULL, "Stasis", ast_strdup(name), ast_free_ptr, "res_stasis"); ast_add_extension(context_name, 0, "h", 1, NULL, NULL, "NoOp", NULL, NULL, "res_stasis"); } } else { ast_log(LOG_WARNING, "Not creating context '%s' for Stasis application '%s' because it already exists\n", context_name, name); } ao2_ref(app, +1); return app; }
struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *data) { RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup); size_t size; int res = 0; ast_assert(name != NULL); ast_assert(handler != NULL); ast_verb(1, "Creating Stasis app '%s'\n", name); size = sizeof(*app) + strlen(name) + 1; app = ao2_alloc_options(size, app_dtor, AO2_ALLOC_OPT_LOCK_MUTEX); if (!app) { return NULL; } app->forwards = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT, forwards_sort, NULL); if (!app->forwards) { return NULL; } app->topic = stasis_topic_create(name); if (!app->topic) { return NULL; } app->bridge_router = stasis_message_router_create(ast_bridge_topic_all()); if (!app->bridge_router) { return NULL; } res |= stasis_message_router_add(app->bridge_router, ast_bridge_merge_message_type(), bridge_merge_handler, app); res |= stasis_message_router_add(app->bridge_router, ast_blind_transfer_type(), bridge_blind_transfer_handler, app); res |= stasis_message_router_add(app->bridge_router, ast_attended_transfer_type(), bridge_attended_transfer_handler, app); res |= stasis_message_router_set_default(app->bridge_router, bridge_default_handler, app); if (res != 0) { return NULL; } /* Bridge router holds a reference */ ao2_ref(app, +1); app->router = stasis_message_router_create(app->topic); if (!app->router) { return NULL; } res |= stasis_message_router_add_cache_update(app->router, ast_bridge_snapshot_type(), sub_bridge_update_handler, app); res |= stasis_message_router_add_cache_update(app->router, ast_channel_snapshot_type(), sub_channel_update_handler, app); res |= stasis_message_router_add_cache_update(app->router, ast_endpoint_snapshot_type(), sub_endpoint_update_handler, app); res |= stasis_message_router_set_default(app->router, sub_default_handler, app); if (res != 0) { return NULL; } /* Router holds a reference */ ao2_ref(app, +1); strncpy(app->name, name, size - sizeof(*app)); app->handler = handler; ao2_ref(data, +1); app->data = data; ao2_ref(app, +1); return app; }