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