123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2013, Digium, Inc.
- *
- * Jonathan Rose <jrose@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
- /*! \file
- *
- * \brief Parking Core
- *
- * \author Jonathan Rose <jrose@digium.com>
- */
- #include "asterisk.h"
- ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
- #include "asterisk/_private.h"
- #include "asterisk/astobj2.h"
- #include "asterisk/pbx.h"
- #include "asterisk/bridge.h"
- #include "asterisk/parking.h"
- #include "asterisk/channel.h"
- #include "asterisk/_private.h"
- #include "asterisk/module.h"
- /*! \brief Message type for parked calls */
- STASIS_MESSAGE_TYPE_DEFN(ast_parked_call_type);
- /*! \brief Topic for parking lots */
- static struct stasis_topic *parking_topic;
- /*! \brief The container for the parking provider */
- static AO2_GLOBAL_OBJ_STATIC(parking_provider);
- static void parking_stasis_cleanup(void)
- {
- STASIS_MESSAGE_TYPE_CLEANUP(ast_parked_call_type);
- ao2_cleanup(parking_topic);
- parking_topic = NULL;
- }
- int ast_parking_stasis_init(void)
- {
- if (STASIS_MESSAGE_TYPE_INIT(ast_parked_call_type)) {
- return -1;
- }
- parking_topic = stasis_topic_create("ast_parking");
- if (!parking_topic) {
- return -1;
- }
- ast_register_cleanup(parking_stasis_cleanup);
- return 0;
- }
- struct stasis_topic *ast_parking_topic(void)
- {
- return parking_topic;
- }
- /*! \brief Destructor for parked_call_payload objects */
- static void parked_call_payload_destructor(void *obj)
- {
- struct ast_parked_call_payload *park_obj = obj;
- ao2_cleanup(park_obj->parkee);
- ao2_cleanup(park_obj->retriever);
- ast_string_field_free_memory(park_obj);
- }
- struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_call_event_type event_type,
- struct ast_channel_snapshot *parkee_snapshot, const char *parker_dial_string,
- struct ast_channel_snapshot *retriever_snapshot, const char *parkinglot,
- unsigned int parkingspace, unsigned long int timeout,
- unsigned long int duration)
- {
- RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
- payload = ao2_alloc(sizeof(*payload), parked_call_payload_destructor);
- if (!payload) {
- return NULL;
- }
- if (ast_string_field_init(payload, 32)) {
- return NULL;
- }
- payload->event_type = event_type;
- ao2_ref(parkee_snapshot, +1);
- payload->parkee = parkee_snapshot;
- if (retriever_snapshot) {
- ao2_ref(retriever_snapshot, +1);
- payload->retriever = retriever_snapshot;
- }
- if (parkinglot) {
- ast_string_field_set(payload, parkinglot, parkinglot);
- }
- if (parker_dial_string) {
- ast_string_field_set(payload, parker_dial_string, parker_dial_string);
- }
- payload->parkingspace = parkingspace;
- payload->timeout = timeout;
- payload->duration = duration;
- /* Bump the ref count by one since RAII_VAR is going to eat one when we leave. */
- ao2_ref(payload, +1);
- return payload;
- }
- int ast_parking_park_bridge_channel(struct ast_bridge_channel *parkee, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- if (!table || !table->parking_park_bridge_channel) {
- return -1;
- }
- if (table->module_info) {
- SCOPED_MODULE_USE(table->module_info->self);
- return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
- }
- return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
- }
- int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker,
- const char *context, const char *exten, transfer_channel_cb parked_channel_cb,
- struct transfer_channel_data *parked_channel_data)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- if (!table || !table->parking_blind_transfer_park) {
- return -1;
- }
- if (table->module_info) {
- SCOPED_MODULE_USE(table->module_info->self);
- return table->parking_blind_transfer_park(parker, context, exten, parked_channel_cb, parked_channel_data);
- }
- return table->parking_blind_transfer_park(parker, context, exten, parked_channel_cb, parked_channel_data);
- }
- int ast_parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- if (!table || !table->parking_park_call) {
- return -1;
- }
- if (table->module_info) {
- SCOPED_MODULE_USE(table->module_info->self);
- return table->parking_park_call(parker, exten, length);
- }
- return table->parking_park_call(parker, exten, length);
- }
- int ast_parking_is_exten_park(const char *context, const char *exten)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- if (!table || !table->parking_is_exten_park) {
- return -1;
- }
- if (table->module_info) {
- SCOPED_MODULE_USE(table->module_info->self);
- return table->parking_is_exten_park(context, exten);
- }
- return table->parking_is_exten_park(context, exten);
- }
- int ast_parking_register_bridge_features(struct ast_parking_bridge_feature_fn_table *fn_table)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, wrapper,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- if (fn_table->module_version != PARKING_MODULE_VERSION) {
- ast_log(AST_LOG_WARNING, "Parking module provided incorrect parking module "
- "version: %u (expected: %d)\n", fn_table->module_version, PARKING_MODULE_VERSION);
- return -1;
- }
- if (wrapper) {
- ast_log(AST_LOG_WARNING, "Parking provider already registered by %s!\n",
- wrapper->module_name);
- return -1;
- }
- wrapper = ao2_alloc(sizeof(*wrapper), NULL);
- if (!wrapper) {
- return -1;
- }
- *wrapper = *fn_table;
- ao2_global_obj_replace_unref(parking_provider, wrapper);
- return 0;
- }
- int ast_parking_unregister_bridge_features(const char *module_name)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, wrapper,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- if (!wrapper) {
- return -1;
- }
- if (strcmp(wrapper->module_name, module_name)) {
- ast_log(AST_LOG_WARNING, "%s has not registered the parking provider\n", module_name);
- return -1;
- }
- ao2_global_obj_release(parking_provider);
- return 0;
- }
- int ast_parking_provider_registered(void)
- {
- RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
- ao2_global_obj_ref(parking_provider), ao2_cleanup);
- return !!table;
- }
|