Perform the initial renaming of the Bridging API
[asterisk/asterisk.git] / res / parking / parking_bridge_features.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Jonathan Rose <jrose@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*! \file
20  *
21  * \brief Parking Bridge DTMF and Interval features
22  *
23  * \author Jonathan Rose <jrose@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "res_parking.h"
31 #include "asterisk/utils.h"
32 #include "asterisk/astobj2.h"
33 #include "asterisk/logger.h"
34 #include "asterisk/pbx.h"
35 #include "asterisk/bridging.h"
36 #include "asterisk/bridging_internal.h"
37 #include "asterisk/bridging_channel_internal.h"
38 #include "asterisk/bridging_channel.h"
39 #include "asterisk/bridging_features.h"
40 #include "asterisk/features.h"
41 #include "asterisk/say.h"
42 #include "asterisk/datastore.h"
43 #include "asterisk/stasis.h"
44
45 struct parked_subscription_datastore {
46         struct stasis_subscription *parked_subscription;
47 };
48
49 struct parked_subscription_data {
50         char *parkee_uuid;
51         char parker_uuid[0];
52 };
53
54 static void parked_subscription_datastore_destroy(void *data)
55 {
56         struct parked_subscription_datastore *subscription_datastore = data;
57
58         stasis_unsubscribe(subscription_datastore->parked_subscription);
59         subscription_datastore->parked_subscription = NULL;
60
61         ast_free(subscription_datastore);
62 }
63
64 static const struct ast_datastore_info parked_subscription_info = {
65         .type = "park subscription",
66         .destroy = parked_subscription_datastore_destroy,
67 };
68
69 static void wipe_subscription_datastore(struct ast_channel *chan)
70 {
71         struct ast_datastore *datastore;
72
73         ast_channel_lock(chan);
74
75         datastore = ast_channel_datastore_find(chan, &parked_subscription_info, NULL);
76         if (datastore) {
77                 ast_channel_datastore_remove(chan, datastore);
78                 ast_datastore_free(datastore);
79         }
80         ast_channel_unlock(chan);
81 }
82
83 static void parker_parked_call_message_response(struct ast_parked_call_payload *message, struct parked_subscription_data *data,
84         struct stasis_subscription *sub)
85 {
86         const char *parkee_to_act_on = data->parkee_uuid;
87         char saynum_buf[16];
88         struct ast_channel_snapshot *parkee_snapshot = message->parkee;
89         RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
90         RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
91
92         if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) {
93                 return;
94         }
95
96         if (message->event_type != PARKED_CALL && message->event_type != PARKED_CALL_FAILED) {
97                 /* We only care about these two event types */
98                 return;
99         }
100
101         parker = ast_channel_get_by_name(data->parker_uuid);
102         if (!parker) {
103                 return;
104         }
105
106         ast_channel_lock(parker);
107         bridge_channel = ast_channel_get_bridge_channel(parker);
108         ast_channel_unlock(parker);
109         if (!bridge_channel) {
110                 return;
111         }
112
113         if (message->event_type == PARKED_CALL) {
114                 /* queue the saynum on the bridge channel and hangup */
115                 snprintf(saynum_buf, sizeof(saynum_buf), "%u %u", 1, message->parkingspace);
116                 ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
117                 wipe_subscription_datastore(bridge_channel->chan);
118         }
119
120         if (message->event_type == PARKED_CALL_FAILED) {
121                 ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL);
122                 wipe_subscription_datastore(bridge_channel->chan);
123         }
124 }
125
126 static void parker_update_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
127 {
128         if (stasis_subscription_final_message(sub, message)) {
129                 ast_free(data);
130                 return;
131         }
132
133         if (stasis_message_type(message) == ast_parked_call_type()) {
134                 struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
135                 parker_parked_call_message_response(parked_call_message, data, sub);
136         }
137 }
138
139 static int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid)
140 {
141         struct ast_datastore *datastore;
142         struct parked_subscription_datastore *parked_datastore;
143         struct parked_subscription_data *subscription_data;
144
145         char *parker_uuid = ast_strdupa(ast_channel_uniqueid(chan));
146         size_t parker_uuid_size = strlen(parker_uuid) + 1;
147
148         /* If there is already a subscription, get rid of it. */
149         wipe_subscription_datastore(chan);
150
151         if (!(datastore = ast_datastore_alloc(&parked_subscription_info, NULL))) {
152                 return -1;
153         }
154
155         if (!(parked_datastore = ast_calloc(1, sizeof(*parked_datastore)))) {
156                 ast_datastore_free(datastore);
157                 return -1;
158         }
159
160         if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data) + parker_uuid_size +
161                         strlen(parkee_uuid) + 1))) {
162                 ast_datastore_free(datastore);
163                 ast_free(parked_datastore);
164                 return -1;
165         }
166
167         subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
168         strcpy(subscription_data->parkee_uuid, parkee_uuid);
169         strcpy(subscription_data->parker_uuid, parker_uuid);
170
171         if (!(parked_datastore->parked_subscription = stasis_subscribe(ast_parking_topic(), parker_update_cb, subscription_data))) {
172                 return -1;
173         }
174
175         datastore->data = parked_datastore;
176
177         ast_channel_lock(chan);
178         ast_channel_datastore_add(chan, datastore);
179         ast_channel_unlock(chan);
180
181         return 0;
182 }
183
184 /*!
185  * \internal
186  * \brief Helper function that creates an outgoing channel and returns it immediately. This function is nearly
187  *        identical to the dial_transfer function in bridge_builtin_features.c, however it doesn't swap the
188  *        local channel and the channel that instigated the park.
189  */
190 static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *exten, const char *context)
191 {
192         RAII_VAR(struct ast_channel *, parkee_side_2, NULL, ao2_cleanup);
193         char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
194         struct ast_channel *parkee;
195         int cause;
196
197         /* Used for side_2 hack */
198         char *parkee_name;
199         char *semi_pos;
200
201         /* Fill the variable with the extension and context we want to call */
202         snprintf(destination, sizeof(destination), "%s@%s", exten, context);
203
204         /* Now we request that chan_local prepare to call the destination */
205         parkee = ast_request("Local", ast_channel_nativeformats(parker), parker, destination,
206                 &cause);
207         if (!parkee) {
208                 return NULL;
209         }
210
211         /* Before we actually dial out let's inherit appropriate information. */
212         ast_channel_lock_both(parker, parkee);
213         ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker));
214         ast_channel_inherit_variables(parker, parkee);
215         ast_channel_datastore_inherit(parker, parkee);
216         ast_channel_unlock(parkee);
217         ast_channel_unlock(parker);
218
219         /* BUGBUG Use Richard's unreal channel stuff here instead of this hack */
220         parkee_name = ast_strdupa(ast_channel_name(parkee));
221
222         semi_pos = strrchr(parkee_name, ';');
223         if (!semi_pos) {
224                 /* There should always be a semicolon present in the string if is used since it's a local channel. */
225                 ast_assert(0);
226                 return NULL;
227         }
228
229         parkee_name[(semi_pos - parkee_name) + 1] = '2';
230         parkee_side_2 = ast_channel_get_by_name(parkee_name);
231
232         /* We need to have the parker subscribe to the new local channel before hand. */
233         create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2));
234
235         pbx_builtin_setvar_helper(parkee_side_2, "BLINDTRANSFER", ast_channel_name(parker));
236
237         /* Since the above worked fine now we actually call it and return the channel */
238         if (ast_call(parkee, destination, 0)) {
239                 ast_hangup(parkee);
240                 return NULL;
241         }
242
243         return parkee;
244 }
245
246 static int park_feature_helper(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_exten *park_exten)
247 {
248         RAII_VAR(struct ast_channel *, other, NULL, ao2_cleanup);
249         RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
250         RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
251         RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
252         RAII_VAR(struct ao2_container *, bridge_peers, NULL, ao2_cleanup);
253         struct ao2_iterator iter;
254
255         bridge_peers = ast_bridge_peers(bridge);
256
257         if (ao2_container_count(bridge_peers) < 2) {
258                 /* There is nothing to do if there is no one to park. */
259                 return 0;
260         }
261
262         if (ao2_container_count(bridge_peers) > 2) {
263                 /* With a multiparty bridge, we need to do a regular blind transfer. We link the existing bridge to the parking lot with a
264                  * local channel rather than transferring others. */
265                 struct ast_channel *transfer_chan = NULL;
266
267                 if (!park_exten) {
268                         /* This simply doesn't work. The user attempted to one-touch park the parking lot and we can't originate a local channel
269                          * without knowing an extension to transfer it to.
270                          * XXX However, when parking lots are changed to be able to register extensions then this will be doable. */
271                         ast_log(LOG_ERROR, "Can not one-touch park a multiparty bridge.\n");
272                         return 0;
273                 }
274
275                 transfer_chan = park_local_transfer(bridge_channel->chan,
276                         ast_get_extension_name(park_exten), ast_get_context_name(ast_get_extension_context(park_exten)));
277
278                 if (!transfer_chan) {
279                         return 0;
280                 }
281
282                 if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL, 1)) {
283                         ast_hangup(transfer_chan);
284                 }
285
286                 return 0;
287         }
288
289         /* Since neither of the above cases were used, we are doing a simple park with a two party bridge. */
290
291         for (iter = ao2_iterator_init(bridge_peers, 0); (other = ao2_iterator_next(&iter)); ao2_ref(other, -1)) {
292                 /* We need the channel that isn't the bridge_channel's channel. */
293                 if (strcmp(ast_channel_uniqueid(other), ast_channel_uniqueid(bridge_channel->chan))) {
294                         break;
295                 }
296         }
297         ao2_iterator_destroy(&iter);
298
299         if (!other) {
300                 ast_assert(0);
301                 return -1;
302         }
303
304         /* Subscribe to park messages with the other channel entering */
305         if (create_parked_subscription(bridge_channel->chan, ast_channel_uniqueid(other))) {
306                 return -1;
307         }
308
309         /* Write the park frame with the intended recipient and other data out to the bridge. */
310         ast_bridge_channel_write_park(bridge_channel, ast_channel_uniqueid(other), ast_channel_uniqueid(bridge_channel->chan), ast_get_extension_app_data(park_exten));
311
312         return 0;
313 }
314
315 static void park_bridge_channel(struct ast_bridge_channel *bridge_channel, const char *uuid_parkee, const char *uuid_parker, const char *app_data)
316 {
317         RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
318         RAII_VAR(struct ast_bridge *, original_bridge, NULL, ao2_cleanup);
319         RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
320
321         if (strcmp(ast_channel_uniqueid(bridge_channel->chan), uuid_parkee)) {
322                 /* We aren't the parkee, so ignore this action. */
323                 return;
324         }
325
326         parker = ast_channel_get_by_name(uuid_parker);
327
328         if (!parker) {
329                 ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
330                 publish_parked_call_failure(bridge_channel->chan);
331                 return;
332         }
333
334         if (!(parking_bridge = park_application_setup(bridge_channel->chan, parker, app_data, NULL))) {
335                 publish_parked_call_failure(bridge_channel->chan);
336                 return;
337         }
338
339         pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", ast_channel_name(parker));
340
341         /* bridge_channel must be locked so we can get a reference to the bridge it is currently on */
342         ao2_lock(bridge_channel);
343
344         original_bridge = bridge_channel->bridge;
345         if (!original_bridge) {
346                 ao2_unlock(bridge_channel);
347                 publish_parked_call_failure(bridge_channel->chan);
348                 return;
349         }
350
351         ao2_ref(original_bridge, +1); /* Cleaned by RAII_VAR */
352
353         ao2_unlock(bridge_channel);
354
355         if (ast_bridge_move(parking_bridge, original_bridge, bridge_channel->chan, NULL, 1)) {
356                 ast_log(LOG_ERROR, "Failed to move %s into the parking bridge.\n",
357                         ast_channel_name(bridge_channel->chan));
358         }
359 }
360
361 static int feature_park(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
362 {
363         park_feature_helper(bridge, bridge_channel, NULL);
364         return 0;
365 }
366
367 static void parking_duration_cb_destroyer(void *hook_pvt)
368 {
369         struct parked_user *user = hook_pvt;
370         ao2_ref(user, -1);
371 }
372
373 /*! \internal
374  * \brief Interval hook. Pulls a parked call from the parking bridge after the timeout is passed and sets the resolution to timeout.
375  *
376  * \param bridge Which bridge the channel was parked in
377  * \param bridge_channel bridge channel this interval hook is being executed on
378  * \param hook_pvt A pointer to the parked_user struct associated with the channel is stuffed in here
379  */
380 static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
381 {
382         struct parked_user *user = hook_pvt;
383         struct ast_channel *chan = user->chan;
384         struct ast_context *park_dial_context;
385         const char *dial_string;
386         char *dial_string_flat;
387         char parking_space[AST_MAX_EXTENSION];
388
389         char returnexten[AST_MAX_EXTENSION];
390         char *duplicate_returnexten;
391         struct ast_exten *existing_exten;
392         struct pbx_find_info pbx_finder = { .stacklen = 0 }; /* The rest is reset in pbx_find_extension */
393
394
395         /* We are still in the bridge, so it's possible for other stuff to mess with the parked call before we leave the bridge
396            to deal with this, lock the parked user, check and set resolution. */
397         ao2_lock(user);
398         if (user->resolution != PARK_UNSET) {
399                 /* Abandon timeout since something else has resolved the parked user before we got to it. */
400                 ao2_unlock(user);
401                 return -1;
402         }
403
404         user->resolution = PARK_TIMEOUT;
405         ao2_unlock(user);
406
407         ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
408
409         /* Set parking timeout channel variables */
410         snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
411         pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
412         pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parking_space); /* Deprecated version of PARKING_SPACE */
413         pbx_builtin_setvar_helper(chan, "PARKEDLOT", user->lot->name);
414
415         dial_string = user->parker_dial_string;
416         dial_string_flat = ast_strdupa(dial_string);
417         flatten_dial_string(dial_string_flat);
418
419         pbx_builtin_setvar_helper(chan, "PARKER", dial_string);
420         pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
421
422         /* Dialplan generation for park-dial extensions */
423
424         if (ast_wrlock_contexts()) {
425                 ast_log(LOG_ERROR, "Failed to lock the contexts list. Can't add the park-dial extension.\n");
426                 return -1;
427         }
428
429         if (!(park_dial_context = ast_context_find_or_create(NULL, NULL, PARK_DIAL_CONTEXT, BASE_REGISTRAR))) {
430                 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", PARK_DIAL_CONTEXT);
431                 if (ast_unlock_contexts()) {
432                         ast_assert(0);
433                 }
434                 goto abandon_extension_creation;
435         }
436
437         if (ast_wrlock_context(park_dial_context)) {
438                 ast_log(LOG_ERROR, "failed to obtain write lock on context '%s'\n", PARK_DIAL_CONTEXT);
439                 if (ast_unlock_contexts()) {
440                         ast_assert(0);
441                 }
442                 goto abandon_extension_creation;
443         }
444
445         if (ast_unlock_contexts()) {
446                 ast_assert(0);
447         }
448
449         snprintf(returnexten, sizeof(returnexten), "%s,%u", dial_string,
450                 user->lot->cfg->comebackdialtime);
451
452         duplicate_returnexten = ast_strdup(returnexten);
453
454         if (!duplicate_returnexten) {
455                 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
456                         dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
457         }
458
459         /* If an extension already exists here because we registered it for another parked call timing out, then we may overwrite it. */
460         if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, dial_string_flat, 1, NULL, NULL, E_MATCH)) &&
461             (strcmp(ast_get_extension_registrar(existing_exten), BASE_REGISTRAR))) {
462                 ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
463                         dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
464         } else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
465                         "Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR)) {
466                         ast_free(duplicate_returnexten);
467                 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
468                         dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
469         }
470
471         if (ast_unlock_context(park_dial_context)) {
472                 ast_assert(0);
473         }
474
475 abandon_extension_creation:
476
477         /* async_goto the proper PBX destination - this should happen when we come out of the bridge */
478         if (!ast_strlen_zero(user->comeback)) {
479                 ast_async_parseable_goto(chan, user->comeback);
480         } else {
481                 comeback_goto(user, user->lot);
482         }
483
484         return -1;
485 }
486
487 void say_parking_space(struct ast_bridge_channel *bridge_channel, const char *payload)
488 {
489         int numeric_value;
490         int hangup_after;
491
492         if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
493                 /* If say_parking_space is called with a non-numeric string, we have a problem. */
494                 ast_assert(0);
495                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
496                 return;
497         }
498
499         ast_say_digits(bridge_channel->chan, numeric_value, "", ast_channel_language(bridge_channel->chan));
500
501         if (hangup_after) {
502                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
503         }
504 }
505
506 void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user)
507 {
508         unsigned int time_limit;
509
510         time_limit = user->time_limit * 1000;
511
512         if (!time_limit) {
513                 /* There is no duration limit that we need to apply. */
514                 return;
515         }
516
517         /* If the time limit has already been passed, set a really low time limit so we can kick them out immediately. */
518         time_limit = ast_remaining_ms(user->start, time_limit);
519         if (time_limit <= 0) {
520                 time_limit = 1;
521         }
522
523         /* The interval hook is going to need a reference to the parked_user */
524         ao2_ref(user, +1);
525
526         if (ast_bridge_interval_hook(features, time_limit,
527                 parking_duration_callback, user, parking_duration_cb_destroyer, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
528                 ast_log(LOG_ERROR, "Failed to apply duration limits to the parking call.\n");
529                 ao2_ref(user, -1);
530         }
531 }
532
533 void unload_parking_bridge_features(void)
534 {
535         ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_PARKCALL);
536         ast_uninstall_park_blind_xfer_func();
537         ast_uninstall_bridge_channel_park_func();
538 }
539
540 int load_parking_bridge_features(void)
541 {
542         ast_bridge_features_register(AST_BRIDGE_BUILTIN_PARKCALL, feature_park, NULL);
543         ast_install_park_blind_xfer_func(park_feature_helper);
544         ast_install_bridge_channel_park_func(park_bridge_channel);
545         return 0;
546 }