Parking: Eliminate local channel name hack to get peer channel.
[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/bridge.h"
36 #include "asterisk/bridge_internal.h"
37 #include "asterisk/bridge_channel.h"
38 #include "asterisk/bridge_features.h"
39 #include "asterisk/features.h"
40 #include "asterisk/say.h"
41 #include "asterisk/datastore.h"
42 #include "asterisk/stasis.h"
43 #include "asterisk/core_local.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_basic.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 *context, const char *exten)
191 {
192         char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
193         struct ast_channel *parkee;
194         struct ast_channel *parkee_side_2;
195         int cause;
196
197         /* Fill the variable with the extension and context we want to call */
198         snprintf(destination, sizeof(destination), "%s@%s", exten, context);
199
200         /* Now we request that chan_local prepare to call the destination */
201         parkee = ast_request("Local", ast_channel_nativeformats(parker), parker, destination,
202                 &cause);
203         if (!parkee) {
204                 return NULL;
205         }
206
207         /* Before we actually dial out let's inherit appropriate information. */
208         ast_channel_lock_both(parker, parkee);
209         ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker));
210         ast_channel_inherit_variables(parker, parkee);
211         ast_channel_datastore_inherit(parker, parkee);
212         ast_channel_unlock(parker);
213
214         parkee_side_2 = ast_local_get_peer(parkee);
215         ast_assert(parkee_side_2 != NULL);
216         ast_channel_unlock(parkee);
217
218         /* We need to have the parker subscribe to the new local channel before hand. */
219         create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2));
220
221         pbx_builtin_setvar_helper(parkee_side_2, "BLINDTRANSFER", ast_channel_name(parker));
222
223         ast_channel_unref(parkee_side_2);
224
225         /* Since the above worked fine now we actually call it and return the channel */
226         if (ast_call(parkee, destination, 0)) {
227                 ast_hangup(parkee);
228                 return NULL;
229         }
230
231         return parkee;
232 }
233
234 /*! \internal \brief Determine if an extension is a parking extension */
235 static int parking_is_exten_park(const char *context, const char *exten)
236 {
237         struct ast_exten *exten_obj;
238         struct pbx_find_info info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
239         const char *app_at_exten;
240
241         ast_debug(4, "Checking if %s@%s is a parking exten\n", exten, context);
242         exten_obj = pbx_find_extension(NULL, NULL, &info, context, exten, 1, NULL, NULL, E_MATCH);
243         if (!exten_obj) {
244                 return 0;
245         }
246
247         app_at_exten = ast_get_extension_app(exten_obj);
248         if (!app_at_exten || strcasecmp(PARK_APPLICATION, app_at_exten)) {
249                 return 0;
250         }
251
252         return 1;
253 }
254
255 /*!
256  * \internal
257  * \since 12.0.0
258  * \brief Perform a blind transfer to a parking lot
259  *
260  * In general, most parking features should work to call this function. This will safely
261  * park either a channel in the bridge with \ref bridge_channel or will park the entire
262  * bridge if more than one channel is in the bridge. It will create the correct data to
263  * pass to the \ref AstBridging Bridging API to safely park the channel.
264  *
265  * \param bridge_channel The bridge_channel representing the channel performing the park
266  * \param context The context to blind transfer to
267  * \param exten The extension to blind transfer to
268  *
269  * \retval 0 on success
270  * \retval non-zero on error
271  */
272 static int parking_blind_transfer_park(struct ast_bridge_channel *bridge_channel,
273                 const char *context, const char *exten)
274 {
275         RAII_VAR(struct ast_bridge_channel *, other, NULL, ao2_cleanup);
276         int peer_count;
277
278         if (ast_strlen_zero(context) || ast_strlen_zero(exten)) {
279                 return -1;
280         }
281
282         if (!bridge_channel->in_bridge) {
283                 return -1;
284         }
285
286         if (!parking_is_exten_park(context, exten)) {
287                 return -1;
288         }
289
290         ast_bridge_channel_lock_bridge(bridge_channel);
291         peer_count = bridge_channel->bridge->num_channels;
292         if (peer_count == 2) {
293                 other = ast_bridge_channel_peer(bridge_channel);
294                 ao2_ref(other, +1);
295         }
296         ast_bridge_unlock(bridge_channel->bridge);
297
298         if (peer_count < 2) {
299                 /* There is nothing to do if there is no one to park. */
300                 return -1;
301         }
302
303         /* With a multiparty bridge, we need to do a regular blind transfer. We link the
304          * existing bridge to the parking lot with a Local channel rather than
305          * transferring others. */
306         if (peer_count > 2) {
307                 struct ast_channel *transfer_chan = NULL;
308
309                 transfer_chan = park_local_transfer(bridge_channel->chan, context, exten);
310                 if (!transfer_chan) {
311                         return -1;
312                 }
313
314                 if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL, 1)) {
315                         ast_hangup(transfer_chan);
316                         return -1;
317                 }
318                 return 0;
319         }
320
321         /* Subscribe to park messages with the other channel entering */
322         if (create_parked_subscription(bridge_channel->chan, ast_channel_uniqueid(other->chan))) {
323                 return -1;
324         }
325
326         /* Write the park frame with the intended recipient and other data out to the bridge. */
327         ast_bridge_channel_write_park(bridge_channel,
328                 ast_channel_uniqueid(other->chan),
329                 ast_channel_uniqueid(bridge_channel->chan),
330                 NULL);
331
332         return 0;
333 }
334
335
336 /*!
337  * \internal
338  * \since 12.0.0
339  * \brief Perform a direct park on a channel in a bridge
340  *
341  * \note This will be called from within the \ref AstBridging Bridging API
342  *
343  * \param bridge_channel The bridge_channel representing the channel to be parked
344  * \param uuid_parkee The UUID of the channel being parked
345  * \param uuid_parker The UUID of the channel performing the park
346  * \param app_data Application parseable data to pass to the parking application
347  */
348 static int parking_park_bridge_channel(struct ast_bridge_channel *bridge_channel, const char *uuid_parkee, const char *uuid_parker, const char *app_data)
349 {
350         RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
351         RAII_VAR(struct ast_bridge *, original_bridge, NULL, ao2_cleanup);
352         RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
353
354         if (strcmp(ast_channel_uniqueid(bridge_channel->chan), uuid_parkee)) {
355                 /* We aren't the parkee, so ignore this action. */
356                 return -1;
357         }
358
359         parker = ast_channel_get_by_name(uuid_parker);
360
361         if (!parker) {
362                 ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
363                 publish_parked_call_failure(bridge_channel->chan);
364                 return -1;
365         }
366
367         if (!(parking_bridge = park_application_setup(bridge_channel->chan, parker, app_data, NULL))) {
368                 publish_parked_call_failure(bridge_channel->chan);
369                 return -1;
370         }
371
372         pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", ast_channel_name(parker));
373
374         /* bridge_channel must be locked so we can get a reference to the bridge it is currently on */
375         ao2_lock(bridge_channel);
376
377         original_bridge = bridge_channel->bridge;
378         if (!original_bridge) {
379                 ao2_unlock(bridge_channel);
380                 publish_parked_call_failure(bridge_channel->chan);
381                 return -1;
382         }
383
384         ao2_ref(original_bridge, +1); /* Cleaned by RAII_VAR */
385
386         ao2_unlock(bridge_channel);
387
388         if (ast_bridge_move(parking_bridge, original_bridge, bridge_channel->chan, NULL, 1)) {
389                 ast_log(LOG_ERROR, "Failed to move %s into the parking bridge.\n",
390                         ast_channel_name(bridge_channel->chan));
391                 return -1;
392         }
393
394         return 0;
395 }
396
397 /*!
398  * \internal
399  * \since 12.0.0
400  * \brief Park a call
401  *
402  * \param parker The bridge_channel parking the call
403  * \param exten Optional. The extension where the call was parked.
404  * \param length Optional. If \c exten is specified, the length of the buffer.
405  *
406  * \note This will determine the context and extension to park the channel based on
407  * the configuration of the \ref ast_channel associated with \ref parker. It will then
408  * park either the channel or the entire bridge.
409  *
410  * \retval 0 on success
411  * \retval -1 on error
412  */
413 static int parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
414 {
415         RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
416         const char *lot_name = NULL;
417
418         ast_channel_lock(parker->chan);
419         lot_name = find_channel_parking_lot_name(parker->chan);
420         if (!ast_strlen_zero(lot_name)) {
421                 lot_name = ast_strdupa(lot_name);
422         }
423         ast_channel_unlock(parker->chan);
424
425         if (ast_strlen_zero(lot_name)) {
426                 return -1;
427         }
428
429         lot = parking_lot_find_by_name(lot_name);
430         if (!lot) {
431                 ast_log(AST_LOG_WARNING, "Cannot Park %s: lot %s unknown\n",
432                         ast_channel_name(parker->chan), lot_name);
433                 return -1;
434         }
435
436         if (exten) {
437                 ast_copy_string(exten, lot->cfg->parkext, length);
438         }
439         return parking_blind_transfer_park(parker, lot->cfg->parking_con, lot->cfg->parkext);
440 }
441
442 static int feature_park_call(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
443 {
444         return parking_park_call(bridge_channel, NULL, 0);
445 }
446
447 /*! \internal
448  * \brief Interval hook. Pulls a parked call from the parking bridge after the timeout is passed and sets the resolution to timeout.
449  *
450  * \param bridge_channel bridge channel this interval hook is being executed on
451  * \param hook_pvt A pointer to the parked_user struct associated with the channel is stuffed in here
452  */
453 static int parking_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
454 {
455         struct parked_user *user = hook_pvt;
456         struct ast_channel *chan = user->chan;
457         struct ast_context *park_dial_context;
458         const char *dial_string;
459         char *dial_string_flat;
460         char parking_space[AST_MAX_EXTENSION];
461
462         char returnexten[AST_MAX_EXTENSION];
463         char *duplicate_returnexten;
464         struct ast_exten *existing_exten;
465         struct pbx_find_info pbx_finder = { .stacklen = 0 }; /* The rest is reset in pbx_find_extension */
466
467
468         /* We are still in the bridge, so it's possible for other stuff to mess with the parked call before we leave the bridge
469            to deal with this, lock the parked user, check and set resolution. */
470         ao2_lock(user);
471         if (user->resolution != PARK_UNSET) {
472                 /* Abandon timeout since something else has resolved the parked user before we got to it. */
473                 ao2_unlock(user);
474                 return -1;
475         }
476
477         user->resolution = PARK_TIMEOUT;
478         ao2_unlock(user);
479
480         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
481
482         /* Set parking timeout channel variables */
483         snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
484         pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
485         pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parking_space); /* Deprecated version of PARKING_SPACE */
486         pbx_builtin_setvar_helper(chan, "PARKEDLOT", user->lot->name);
487
488         dial_string = user->parker_dial_string;
489         dial_string_flat = ast_strdupa(dial_string);
490         flatten_dial_string(dial_string_flat);
491
492         pbx_builtin_setvar_helper(chan, "PARKER", dial_string);
493         pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
494
495         /* Dialplan generation for park-dial extensions */
496
497         if (ast_wrlock_contexts()) {
498                 ast_log(LOG_ERROR, "Failed to lock the contexts list. Can't add the park-dial extension.\n");
499                 return -1;
500         }
501
502         if (!(park_dial_context = ast_context_find_or_create(NULL, NULL, PARK_DIAL_CONTEXT, BASE_REGISTRAR))) {
503                 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", PARK_DIAL_CONTEXT);
504                 if (ast_unlock_contexts()) {
505                         ast_assert(0);
506                 }
507                 goto abandon_extension_creation;
508         }
509
510         if (ast_wrlock_context(park_dial_context)) {
511                 ast_log(LOG_ERROR, "failed to obtain write lock on context '%s'\n", PARK_DIAL_CONTEXT);
512                 if (ast_unlock_contexts()) {
513                         ast_assert(0);
514                 }
515                 goto abandon_extension_creation;
516         }
517
518         if (ast_unlock_contexts()) {
519                 ast_assert(0);
520         }
521
522         snprintf(returnexten, sizeof(returnexten), "%s,%u", dial_string,
523                 user->lot->cfg->comebackdialtime);
524
525         duplicate_returnexten = ast_strdup(returnexten);
526
527         if (!duplicate_returnexten) {
528                 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
529                         dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
530         }
531
532         /* If an extension already exists here because we registered it for another parked call timing out, then we may overwrite it. */
533         if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, dial_string_flat, 1, NULL, NULL, E_MATCH)) &&
534             (strcmp(ast_get_extension_registrar(existing_exten), BASE_REGISTRAR))) {
535                 ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
536                         dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
537         } else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
538                         "Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR)) {
539                         ast_free(duplicate_returnexten);
540                 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
541                         dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
542         }
543
544         if (ast_unlock_context(park_dial_context)) {
545                 ast_assert(0);
546         }
547
548 abandon_extension_creation:
549
550         /* async_goto the proper PBX destination - this should happen when we come out of the bridge */
551         if (!ast_strlen_zero(user->comeback)) {
552                 ast_async_parseable_goto(chan, user->comeback);
553         } else {
554                 comeback_goto(user, user->lot);
555         }
556
557         return -1;
558 }
559
560 void say_parking_space(struct ast_bridge_channel *bridge_channel, const char *payload)
561 {
562         int numeric_value;
563         int hangup_after;
564
565         if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
566                 /* If say_parking_space is called with a non-numeric string, we have a problem. */
567                 ast_assert(0);
568                 ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
569                 return;
570         }
571
572         ast_say_digits(bridge_channel->chan, numeric_value, "", ast_channel_language(bridge_channel->chan));
573
574         if (hangup_after) {
575                 ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
576         }
577 }
578
579 void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user)
580 {
581         unsigned int time_limit;
582
583         time_limit = user->time_limit * 1000;
584
585         if (!time_limit) {
586                 /* There is no duration limit that we need to apply. */
587                 return;
588         }
589
590         /* If the time limit has already been passed, set a really low time limit so we can kick them out immediately. */
591         time_limit = ast_remaining_ms(user->start, time_limit);
592         if (time_limit <= 0) {
593                 time_limit = 1;
594         }
595
596         /* The interval hook is going to need a reference to the parked_user */
597         ao2_ref(user, +1);
598
599         if (ast_bridge_interval_hook(features, time_limit,
600                 parking_duration_callback, user, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
601                 ast_log(LOG_ERROR, "Failed to apply duration limits to the parking call.\n");
602                 ao2_ref(user, -1);
603         }
604 }
605
606 struct ast_parking_bridge_feature_fn_table parking_provider = {
607         .module_version = PARKING_MODULE_VERSION,
608         .module_name = __FILE__,
609         .parking_is_exten_park = parking_is_exten_park,
610         .parking_blind_transfer_park = parking_blind_transfer_park,
611         .parking_park_bridge_channel = parking_park_bridge_channel,
612         .parking_park_call = parking_park_call,
613 };
614
615 void unload_parking_bridge_features(void)
616 {
617         ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_PARKCALL);
618         ast_parking_unregister_bridge_features(parking_provider.module_name);
619 }
620
621 int load_parking_bridge_features(void)
622 {
623         if (ast_parking_register_bridge_features(&parking_provider)) {
624                 return -1;
625         }
626
627         ast_bridge_features_register(AST_BRIDGE_BUILTIN_PARKCALL, feature_park_call, NULL);
628         return 0;
629 }