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