2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * Jonathan Rose <jrose@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
23 * \author Jonathan Rose <jrose@digium.com>
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include "asterisk/_private.h"
31 #include "asterisk/astobj2.h"
32 #include "asterisk/pbx.h"
33 #include "asterisk/bridge.h"
34 #include "asterisk/parking.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/_private.h"
37 #include "asterisk/module.h"
39 /*! \brief Message type for parked calls */
40 STASIS_MESSAGE_TYPE_DEFN(ast_parked_call_type);
42 /*! \brief Topic for parking lots */
43 static struct stasis_topic *parking_topic;
45 /*! \brief The container for the parking provider */
46 static AO2_GLOBAL_OBJ_STATIC(parking_provider);
48 static void parking_stasis_cleanup(void)
50 STASIS_MESSAGE_TYPE_CLEANUP(ast_parked_call_type);
51 ao2_cleanup(parking_topic);
55 int ast_parking_stasis_init(void)
57 if (STASIS_MESSAGE_TYPE_INIT(ast_parked_call_type)) {
61 parking_topic = stasis_topic_create("ast_parking");
65 ast_register_cleanup(parking_stasis_cleanup);
69 struct stasis_topic *ast_parking_topic(void)
74 /*! \brief Destructor for parked_call_payload objects */
75 static void parked_call_payload_destructor(void *obj)
77 struct ast_parked_call_payload *park_obj = obj;
79 ao2_cleanup(park_obj->parkee);
80 ao2_cleanup(park_obj->retriever);
81 ast_string_field_free_memory(park_obj);
84 struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_call_event_type event_type,
85 struct ast_channel_snapshot *parkee_snapshot, const char *parker_dial_string,
86 struct ast_channel_snapshot *retriever_snapshot, const char *parkinglot,
87 unsigned int parkingspace, unsigned long int timeout,
88 unsigned long int duration)
90 RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
92 payload = ao2_alloc(sizeof(*payload), parked_call_payload_destructor);
97 if (ast_string_field_init(payload, 32)) {
101 payload->event_type = event_type;
103 ao2_ref(parkee_snapshot, +1);
104 payload->parkee = parkee_snapshot;
106 if (retriever_snapshot) {
107 ao2_ref(retriever_snapshot, +1);
108 payload->retriever = retriever_snapshot;
112 ast_string_field_set(payload, parkinglot, parkinglot);
115 if (parker_dial_string) {
116 ast_string_field_set(payload, parker_dial_string, parker_dial_string);
119 payload->parkingspace = parkingspace;
120 payload->timeout = timeout;
121 payload->duration = duration;
123 /* Bump the ref count by one since RAII_VAR is going to eat one when we leave. */
124 ao2_ref(payload, +1);
128 int ast_parking_park_bridge_channel(struct ast_bridge_channel *parkee, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
130 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
131 ao2_global_obj_ref(parking_provider), ao2_cleanup);
133 if (!table || !table->parking_park_bridge_channel) {
137 if (table->module_info) {
138 SCOPED_MODULE_USE(table->module_info->self);
139 return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
142 return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
145 int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten)
147 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
148 ao2_global_obj_ref(parking_provider), ao2_cleanup);
150 if (!table || !table->parking_blind_transfer_park) {
154 if (table->module_info) {
155 SCOPED_MODULE_USE(table->module_info->self);
156 return table->parking_blind_transfer_park(parker, context, exten);
159 return table->parking_blind_transfer_park(parker, context, exten);
162 int ast_parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
164 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
165 ao2_global_obj_ref(parking_provider), ao2_cleanup);
167 if (!table || !table->parking_park_call) {
171 if (table->module_info) {
172 SCOPED_MODULE_USE(table->module_info->self);
173 return table->parking_park_call(parker, exten, length);
176 return table->parking_park_call(parker, exten, length);
179 int ast_parking_is_exten_park(const char *context, const char *exten)
181 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
182 ao2_global_obj_ref(parking_provider), ao2_cleanup);
184 if (!table || !table->parking_is_exten_park) {
188 if (table->module_info) {
189 SCOPED_MODULE_USE(table->module_info->self);
190 return table->parking_is_exten_park(context, exten);
193 return table->parking_is_exten_park(context, exten);
196 int ast_parking_register_bridge_features(struct ast_parking_bridge_feature_fn_table *fn_table)
198 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, wrapper,
199 ao2_global_obj_ref(parking_provider), ao2_cleanup);
201 if (fn_table->module_version != PARKING_MODULE_VERSION) {
202 ast_log(AST_LOG_WARNING, "Parking module provided incorrect parking module "
203 "version: %d (expected: %d)\n", fn_table->module_version, PARKING_MODULE_VERSION);
208 ast_log(AST_LOG_WARNING, "Parking provider already registered by %s!\n",
209 wrapper->module_name);
213 wrapper = ao2_alloc(sizeof(*wrapper), NULL);
217 *wrapper = *fn_table;
219 ao2_global_obj_replace_unref(parking_provider, wrapper);
223 int ast_parking_unregister_bridge_features(const char *module_name)
225 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, wrapper,
226 ao2_global_obj_ref(parking_provider), ao2_cleanup);
232 if (strcmp(wrapper->module_name, module_name)) {
233 ast_log(AST_LOG_WARNING, "%s has not registered the parking provider\n", module_name);
237 ao2_global_obj_release(parking_provider);
241 int ast_parking_provider_registered(void)
243 RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
244 ao2_global_obj_ref(parking_provider), ao2_cleanup);