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