f73f37157ef56fdd8a8a39a92659284fa3d38db6
[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 #include "res_parking.h"
29 #include "asterisk/utils.h"
30 #include "asterisk/astobj2.h"
31 #include "asterisk/logger.h"
32 #include "asterisk/pbx.h"
33 #include "asterisk/app.h"
34 #include "asterisk/bridge.h"
35 #include "asterisk/bridge_internal.h"
36 #include "asterisk/bridge_channel.h"
37 #include "asterisk/bridge_features.h"
38 #include "asterisk/conversions.h"
39 #include "asterisk/features.h"
40 #include "asterisk/say.h"
41 #include "asterisk/datastore.h"
42 #include "asterisk/stasis.h"
43 #include "asterisk/module.h"
44 #include "asterisk/core_local.h"
45 #include "asterisk/causes.h"
46
47 /*** DOCUMENTATION
48         <function name="PARK_GET_CHANNEL" language="en_US">
49                 <synopsis>
50                         Get the channel name of an occupied parking space in a parking lot.
51                 </synopsis>
52                         <syntax>
53                                 <parameter name="parking_space" required="true">
54                                 </parameter>
55                                 <parameter name="parking_lot" required="true">
56                                 </parameter>
57                         </syntax>
58                 <description>
59                         <para>This function returns the channel of the specified parking space
60                                 if the parking lot space is occupied.</para>
61                         </description>
62         </function>
63 ***/
64
65 struct parked_subscription_datastore {
66         struct stasis_subscription *parked_subscription;
67 };
68
69 struct parked_subscription_data {
70         struct transfer_channel_data *transfer_data;
71         char *parkee_uuid;
72         int hangup_after:1;
73         char parker_uuid[0];
74 };
75
76 static void parked_subscription_datastore_destroy(void *data)
77 {
78         struct parked_subscription_datastore *subscription_datastore = data;
79
80         stasis_unsubscribe(subscription_datastore->parked_subscription);
81         subscription_datastore->parked_subscription = NULL;
82
83         ast_free(subscription_datastore);
84 }
85
86 static const struct ast_datastore_info parked_subscription_info = {
87         .type = "park subscription",
88         .destroy = parked_subscription_datastore_destroy,
89 };
90
91 static void wipe_subscription_datastore(struct ast_channel *chan)
92 {
93         struct ast_datastore *datastore;
94
95         ast_channel_lock(chan);
96
97         datastore = ast_channel_datastore_find(chan, &parked_subscription_info, NULL);
98         if (datastore) {
99                 ast_channel_datastore_remove(chan, datastore);
100                 ast_datastore_free(datastore);
101         }
102         ast_channel_unlock(chan);
103 }
104
105 static void parker_parked_call_message_response(struct ast_parked_call_payload *message, struct parked_subscription_data *data,
106         struct stasis_subscription *sub)
107 {
108         const char *parkee_to_act_on = data->parkee_uuid;
109         char saynum_buf[16];
110         struct ast_channel_snapshot *parkee_snapshot = message->parkee;
111         RAII_VAR(struct ast_channel *, parker, NULL, ast_channel_cleanup);
112         RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
113
114         if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) {
115                 return;
116         }
117
118         if (message->event_type != PARKED_CALL && message->event_type != PARKED_CALL_FAILED) {
119                 /* We only care about these two event types */
120                 return;
121         }
122
123         parker = ast_channel_get_by_name(data->parker_uuid);
124         if (!parker) {
125                 return;
126         }
127
128         ast_channel_lock(parker);
129         bridge_channel = ast_channel_get_bridge_channel(parker);
130         ast_channel_unlock(parker);
131         if (!bridge_channel) {
132                 return;
133         }
134
135         /* This subscription callback will block for the duration of the announcement if
136          * parked_subscription_data is tracking a transfer_channel_data struct. */
137         if (message->event_type == PARKED_CALL) {
138                 /* queue the saynum on the bridge channel and hangup */
139                 snprintf(saynum_buf, sizeof(saynum_buf), "%d %u", data->hangup_after, message->parkingspace);
140                 if (!data->transfer_data) {
141                         ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
142                 } else {
143                         ast_bridge_channel_queue_playfile_sync(bridge_channel, say_parking_space, saynum_buf, NULL);
144                         data->transfer_data->completed = 1;
145                 }
146                 wipe_subscription_datastore(parker);
147         } else if (message->event_type == PARKED_CALL_FAILED) {
148                 if (!data->transfer_data) {
149                         ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL);
150                 } else {
151                         ast_bridge_channel_queue_playfile_sync(bridge_channel, NULL, "pbx-parkingfailed", NULL);
152                         data->transfer_data->completed = 1;
153                 }
154                 wipe_subscription_datastore(parker);
155         }
156 }
157
158 static void parker_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
159 {
160         if (stasis_subscription_final_message(sub, message)) {
161                 struct parked_subscription_data *ps_data = data;
162                 ao2_cleanup(ps_data->transfer_data);
163                 ps_data->transfer_data = NULL;
164                 ast_free(data);
165                 return;
166         }
167
168         if (stasis_message_type(message) == ast_parked_call_type()) {
169                 struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
170                 parker_parked_call_message_response(parked_call_message, data, sub);
171         }
172 }
173
174 static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after,
175         struct transfer_channel_data *parked_channel_data)
176 {
177         struct ast_datastore *datastore;
178         struct parked_subscription_datastore *parked_datastore;
179         struct parked_subscription_data *subscription_data;
180
181         char *parker_uuid = ast_strdupa(ast_channel_uniqueid(chan));
182         size_t parker_uuid_size = strlen(parker_uuid) + 1;
183
184         /* If there is already a subscription, get rid of it. */
185         wipe_subscription_datastore(chan);
186
187         if (!(datastore = ast_datastore_alloc(&parked_subscription_info, NULL))) {
188                 return -1;
189         }
190
191         if (!(parked_datastore = ast_calloc(1, sizeof(*parked_datastore)))) {
192                 ast_datastore_free(datastore);
193                 return -1;
194         }
195
196         if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data) + parker_uuid_size +
197                         strlen(parkee_uuid) + 1))) {
198                 ast_datastore_free(datastore);
199                 ast_free(parked_datastore);
200                 return -1;
201         }
202
203         if (parked_channel_data) {
204                 subscription_data->transfer_data = parked_channel_data;
205                 ao2_ref(parked_channel_data, +1);
206         }
207
208         subscription_data->hangup_after = hangup_after;
209         subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
210         strcpy(subscription_data->parkee_uuid, parkee_uuid);
211         strcpy(subscription_data->parker_uuid, parker_uuid);
212
213         if (!(parked_datastore->parked_subscription = stasis_subscribe_pool(ast_parking_topic(), parker_update_cb, subscription_data))) {
214                 return -1;
215         }
216
217         datastore->data = parked_datastore;
218
219         ast_channel_lock(chan);
220         ast_channel_datastore_add(chan, datastore);
221         ast_channel_unlock(chan);
222
223         return 0;
224 }
225
226 int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
227 {
228         return create_parked_subscription_full(chan, parkee_uuid, hangup_after, NULL);
229 }
230
231 /*!
232  * \internal
233  * \brief Helper function that creates an outgoing channel and returns it immediately. This function is nearly
234  *        identical to the dial_transfer function in bridge_basic.c, however it doesn't swap the
235  *        local channel and the channel that instigated the park.
236  */
237 static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *context, const char *exten, struct transfer_channel_data *parked_channel_data)
238 {
239         char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
240         struct ast_channel *parkee;
241         struct ast_channel *parkee_side_2;
242         int cause;
243
244         /* Fill the variable with the extension and context we want to call */
245         snprintf(destination, sizeof(destination), "%s@%s", exten, context);
246
247         /* Now we request that chan_local prepare to call the destination */
248         parkee = ast_request("Local", ast_channel_nativeformats(parker), NULL, parker, destination,
249                 &cause);
250         if (!parkee) {
251                 return NULL;
252         }
253
254         /* Before we actually dial out let's inherit appropriate information. */
255         ast_channel_lock_both(parker, parkee);
256         ast_channel_req_accountcodes(parkee, parker, AST_CHANNEL_REQUESTOR_REPLACEMENT);
257         ast_channel_parkinglot_set(parkee, ast_channel_parkinglot(parker));
258         ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker));
259         ast_channel_inherit_variables(parker, parkee);
260         ast_bridge_set_transfer_variables(parkee, ast_channel_name(parker), 0);
261         ast_channel_datastore_inherit(parker, parkee);
262         ast_channel_unlock(parker);
263
264         parkee_side_2 = ast_local_get_peer(parkee);
265         ast_assert(parkee_side_2 != NULL);
266         ast_channel_unlock(parkee);
267
268         /* We need to have the parker subscribe to the new local channel before hand. */
269         if (create_parked_subscription_full(parker, ast_channel_uniqueid(parkee_side_2), 1, parked_channel_data)) {
270                 ast_channel_unref(parkee_side_2);
271                 ast_hangup(parkee);
272                 return NULL;
273         }
274
275         ast_channel_unref(parkee_side_2);
276
277         /* Since the above worked fine now we actually call it and return the channel */
278         if (ast_call(parkee, destination, 0)) {
279                 ast_hangup(parkee);
280                 return NULL;
281         }
282
283         return parkee;
284 }
285
286 /*!
287  * \internal
288  * \brief Determine if an extension is a parking extension
289  */
290 static int parking_is_exten_park(const char *context, const char *exten)
291 {
292         struct ast_exten *exten_obj;
293         struct pbx_find_info info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
294         const char *app_at_exten;
295
296         ast_debug(4, "Checking if %s@%s is a parking exten\n", exten, context);
297         exten_obj = pbx_find_extension(NULL, NULL, &info, context, exten, 1, NULL, NULL, E_MATCH);
298         if (!exten_obj) {
299                 return 0;
300         }
301
302         app_at_exten = ast_get_extension_app(exten_obj);
303         if (!app_at_exten || strcasecmp(PARK_APPLICATION, app_at_exten)) {
304                 return 0;
305         }
306
307         return 1;
308 }
309
310 /*!
311  * \internal
312  * \since 12.0.0
313  * \brief Perform a blind transfer to a parking lot
314  *
315  * In general, most parking features should work to call this function. This will safely
316  * park either a channel in the bridge with \ref bridge_channel or will park the entire
317  * bridge if more than one channel is in the bridge. It will create the correct data to
318  * pass to the \ref AstBridging Bridging API to safely park the channel.
319  *
320  * \param bridge_channel The bridge_channel representing the channel performing the park
321  * \param context The context to blind transfer to
322  * \param exten The extension to blind transfer to
323  * \param parked_channel_cb Optional callback executed prior to sending the parked channel into the bridge
324  * \param parked_channel_data Data for the parked_channel_cb
325  *
326  * \retval 0 on success
327  * \retval non-zero on error
328  */
329 static int parking_blind_transfer_park(struct ast_bridge_channel *bridge_channel,
330                 const char *context, const char *exten, transfer_channel_cb parked_channel_cb,
331                 struct transfer_channel_data *parked_channel_data)
332 {
333         RAII_VAR(struct ast_bridge_channel *, other, NULL, ao2_cleanup);
334         RAII_VAR(struct ast_channel *, other_chan, NULL, ast_channel_cleanup);
335
336         struct ast_exten *e;
337         struct pbx_find_info find_info = { .stacklen = 0 };
338         int peer_count;
339
340         if (ast_strlen_zero(context) || ast_strlen_zero(exten)) {
341                 return -1;
342         }
343
344         if (!bridge_channel->in_bridge) {
345                 return -1;
346         }
347
348         if (!parking_is_exten_park(context, exten)) {
349                 return -1;
350         }
351
352         ast_bridge_channel_lock_bridge(bridge_channel);
353         peer_count = bridge_channel->bridge->num_channels;
354         if (peer_count == 2) {
355                 other = ast_bridge_channel_peer(bridge_channel);
356                 ao2_ref(other, +1);
357                 other_chan = other->chan;
358                 ast_channel_ref(other_chan);
359         }
360         ast_bridge_unlock(bridge_channel->bridge);
361
362         if (peer_count < 2) {
363                 /* There is nothing to do if there is no one to park. */
364                 return -1;
365         }
366
367         /* With a multiparty bridge, we need to do a regular blind transfer. We link the
368          * existing bridge to the parking lot with a Local channel rather than
369          * transferring others. */
370         if (peer_count > 2) {
371                 struct ast_channel *transfer_chan = NULL;
372
373                 transfer_chan = park_local_transfer(bridge_channel->chan, context, exten, parked_channel_data);
374                 if (!transfer_chan) {
375                         return -1;
376                 }
377                 ast_channel_ref(transfer_chan);
378
379                 if (parked_channel_cb) {
380                         parked_channel_cb(transfer_chan, parked_channel_data, AST_BRIDGE_TRANSFER_MULTI_PARTY);
381                 }
382
383                 if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL,
384                         AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
385                         ast_hangup(transfer_chan);
386                         ast_channel_unref(transfer_chan);
387                         return -1;
388                 }
389
390                 ast_channel_unref(transfer_chan);
391
392                 return 0;
393         }
394
395         /* Subscribe to park messages with the other channel entering */
396         if (create_parked_subscription_full(bridge_channel->chan, ast_channel_uniqueid(other->chan), 1, parked_channel_data)) {
397                 return -1;
398         }
399
400         if (parked_channel_cb) {
401                 parked_channel_cb(other_chan, parked_channel_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
402         }
403
404         e = pbx_find_extension(NULL, NULL, &find_info, context, exten, 1, NULL, NULL, E_MATCH);
405
406         /* Write the park frame with the intended recipient and other data out to the bridge. */
407         ast_bridge_channel_write_park(bridge_channel,
408                 ast_channel_uniqueid(other_chan),
409                 ast_channel_uniqueid(bridge_channel->chan),
410                 e ? ast_get_extension_app_data(e) : NULL);
411
412         return 0;
413 }
414
415 /*!
416  * \internal
417  * \since 12.0.0
418  * \brief Perform a direct park on a channel in a bridge
419  *
420  * \note This will be called from within the \ref AstBridging Bridging API
421  *
422  * \param bridge_channel The bridge_channel representing the channel to be parked
423  * \param uuid_parkee The UUID of the channel being parked
424  * \param uuid_parker The UUID of the channel performing the park
425  * \param app_data Application parseable data to pass to the parking application
426  */
427 static int parking_park_bridge_channel(struct ast_bridge_channel *bridge_channel, const char *uuid_parkee, const char *uuid_parker, const char *app_data)
428 {
429         RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
430         RAII_VAR(struct ast_bridge *, original_bridge, NULL, ao2_cleanup);
431         RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
432
433         if (strcmp(ast_channel_uniqueid(bridge_channel->chan), uuid_parkee)) {
434                 /* We aren't the parkee, so ignore this action. */
435                 return -1;
436         }
437
438         parker = ast_channel_get_by_name(uuid_parker);
439
440         if (!parker) {
441                 ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
442                 publish_parked_call_failure(bridge_channel->chan);
443                 return -1;
444         }
445
446         if (!(parking_bridge = park_application_setup(bridge_channel->chan, parker, app_data, NULL))) {
447                 publish_parked_call_failure(bridge_channel->chan);
448                 return -1;
449         }
450
451         ast_bridge_set_transfer_variables(bridge_channel->chan, ast_channel_name(parker), 0);
452
453         /* bridge_channel must be locked so we can get a reference to the bridge it is currently on */
454         ao2_lock(bridge_channel);
455
456         original_bridge = bridge_channel->bridge;
457         if (!original_bridge) {
458                 ao2_unlock(bridge_channel);
459                 publish_parked_call_failure(bridge_channel->chan);
460                 return -1;
461         }
462
463         ao2_ref(original_bridge, +1); /* Cleaned by RAII_VAR */
464
465         ao2_unlock(bridge_channel);
466
467         if (ast_bridge_move(parking_bridge, original_bridge, bridge_channel->chan, NULL, 1)) {
468                 ast_log(LOG_ERROR, "Failed to move %s into the parking bridge.\n",
469                         ast_channel_name(bridge_channel->chan));
470                 return -1;
471         }
472
473         return 0;
474 }
475
476 /*!
477  * \internal
478  * \since 12.0.0
479  * \brief Park a call
480  *
481  * \param parker The bridge_channel parking the call
482  * \param exten Optional. The extension where the call was parked.
483  * \param length Optional. If \c exten is specified, the length of the buffer.
484  *
485  * \note This will determine the context and extension to park the channel based on
486  * the configuration of the \ref ast_channel associated with \ref parker. It will then
487  * park either the channel or the entire bridge.
488  *
489  * \retval 0 on success
490  * \retval -1 on error
491  */
492 static int parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
493 {
494         RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
495         const char *lot_name;
496
497         ast_channel_lock(parker->chan);
498         lot_name = ast_strdupa(find_channel_parking_lot_name(parker->chan));
499         ast_channel_unlock(parker->chan);
500
501         lot = parking_lot_find_by_name(lot_name);
502         if (!lot) {
503                 lot = parking_create_dynamic_lot(lot_name, parker->chan);
504         }
505         if (!lot) {
506                 ast_log(AST_LOG_WARNING, "Cannot Park %s: lot %s unknown\n",
507                         ast_channel_name(parker->chan), lot_name);
508                 return -1;
509         }
510
511         if (exten) {
512                 ast_copy_string(exten, lot->cfg->parkext, length);
513         }
514         return parking_blind_transfer_park(parker, lot->cfg->parking_con, lot->cfg->parkext, NULL, NULL);
515 }
516
517 static int feature_park_call(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
518 {
519         SCOPED_MODULE_USE(AST_MODULE_SELF);
520
521         parking_park_call(bridge_channel, NULL, 0);
522         return 0;
523 }
524
525 /*!
526  * \internal
527  * \brief Setup the caller features for when that channel is dialed.
528  * \since 12.0.0
529  *
530  * \param chan Parked channel leaving the parking lot.
531  * \param cfg Parking lot configuration.
532  *
533  * \return Nothing
534  */
535 static void parking_timeout_set_caller_features(struct ast_channel *chan, struct parking_lot_cfg *cfg)
536 {
537         char features[5];
538         char *pos;
539
540         /*
541          * We are setting the callee Dial flag values because in the
542          * timeout case, the caller is who is being called back.
543          */
544         pos = features;
545         if (cfg->parkedcalltransfers & AST_FEATURE_FLAG_BYCALLER) {
546                 *pos++ = 't';
547         }
548         if (cfg->parkedcallreparking & AST_FEATURE_FLAG_BYCALLER) {
549                 *pos++ = 'k';
550         }
551         if (cfg->parkedcallhangup & AST_FEATURE_FLAG_BYCALLER) {
552                 *pos++ = 'h';
553         }
554         if (cfg->parkedcallrecording & AST_FEATURE_FLAG_BYCALLER) {
555                 *pos++ = 'x';
556         }
557         *pos = '\0';
558
559         pbx_builtin_setvar_helper(chan, "BRIDGE_FEATURES", features);
560 }
561
562 /*! \internal
563  * \brief Interval hook. Pulls a parked call from the parking bridge after the timeout is passed and sets the resolution to timeout.
564  *
565  * \param bridge_channel bridge channel this interval hook is being executed on
566  * \param hook_pvt A pointer to the parked_user struct associated with the channel is stuffed in here
567  */
568 static int parking_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
569 {
570         struct parked_user *user = hook_pvt;
571         struct ast_channel *chan = user->chan;
572         struct ast_context *park_dial_context;
573         const char *dial_string;
574         char *dial_string_flat;
575         char parking_space[AST_MAX_EXTENSION];
576
577         char returnexten[AST_MAX_EXTENSION];
578         char *duplicate_returnexten;
579         struct ast_exten *existing_exten;
580         struct pbx_find_info pbx_finder = { .stacklen = 0 }; /* The rest is reset in pbx_find_extension */
581
582
583         /* We are still in the bridge, so it's possible for other stuff to mess with the parked call before we leave the bridge
584            to deal with this, lock the parked user, check and set resolution. */
585         ao2_lock(user);
586         if (user->resolution != PARK_UNSET) {
587                 /* Abandon timeout since something else has resolved the parked user before we got to it. */
588                 ao2_unlock(user);
589                 return -1;
590         }
591         user->resolution = PARK_TIMEOUT;
592         ao2_unlock(user);
593
594         ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
595                 AST_CAUSE_NORMAL_CLEARING);
596
597         dial_string = user->parker_dial_string;
598         dial_string_flat = ast_strdupa(dial_string);
599         flatten_dial_string(dial_string_flat);
600
601         /* Set parking timeout channel variables */
602         snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
603         ast_channel_lock(chan);
604         ast_channel_stage_snapshot(chan);
605         pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
606         pbx_builtin_setvar_helper(chan, "PARKEDLOT", user->lot->name);
607         pbx_builtin_setvar_helper(chan, "PARKER", dial_string);
608         pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
609         parking_timeout_set_caller_features(chan, user->lot->cfg);
610         ast_channel_stage_snapshot_done(chan);
611         ast_channel_unlock(chan);
612
613         /* Dialplan generation for park-dial extensions */
614
615         if (ast_wrlock_contexts()) {
616                 ast_log(LOG_ERROR, "Failed to lock the contexts list. Can't add the park-dial extension.\n");
617                 return -1;
618         }
619
620         if (!(park_dial_context = ast_context_find_or_create(NULL, NULL, PARK_DIAL_CONTEXT, BASE_REGISTRAR))) {
621                 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", PARK_DIAL_CONTEXT);
622                 if (ast_unlock_contexts()) {
623                         ast_assert(0);
624                 }
625                 goto abandon_extension_creation;
626         }
627
628         if (ast_wrlock_context(park_dial_context)) {
629                 ast_log(LOG_ERROR, "failed to obtain write lock on context '%s'\n", PARK_DIAL_CONTEXT);
630                 if (ast_unlock_contexts()) {
631                         ast_assert(0);
632                 }
633                 goto abandon_extension_creation;
634         }
635
636         if (ast_unlock_contexts()) {
637                 ast_assert(0);
638         }
639
640         snprintf(returnexten, sizeof(returnexten), "%s,%u", dial_string,
641                 user->lot->cfg->comebackdialtime);
642
643         duplicate_returnexten = ast_strdup(returnexten);
644         if (!duplicate_returnexten) {
645                 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
646                         dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
647         }
648
649         /* If an extension already exists here because we registered it for another parked call timing out, then we may overwrite it. */
650         if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, dial_string_flat, 1, NULL, NULL, E_MATCH)) &&
651             (strcmp(ast_get_extension_registrar(existing_exten), BASE_REGISTRAR))) {
652                 ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
653                         dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
654         } else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
655                         "Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR, NULL, 0)) {
656                         ast_free(duplicate_returnexten);
657                 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
658                         dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
659         }
660
661         if (ast_unlock_context(park_dial_context)) {
662                 ast_assert(0);
663         }
664
665 abandon_extension_creation:
666
667         /* async_goto the proper PBX destination - this should happen when we come out of the bridge */
668         if (!ast_strlen_zero(user->comeback)) {
669                 ast_async_parseable_goto(chan, user->comeback);
670         } else {
671                 comeback_goto(user, user->lot);
672         }
673
674         return -1;
675 }
676
677 void say_parking_space(struct ast_bridge_channel *bridge_channel, const char *payload)
678 {
679         unsigned int numeric_value;
680         unsigned int hangup_after;
681
682         if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
683                 /* If say_parking_space is called with a non-numeric string, we have a problem. */
684                 ast_assert(0);
685                 ast_bridge_channel_leave_bridge(bridge_channel,
686                         BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
687                 return;
688         }
689
690         ast_say_digits(bridge_channel->chan, numeric_value, "",
691                 ast_channel_language(bridge_channel->chan));
692
693         if (hangup_after) {
694                 ast_bridge_channel_leave_bridge(bridge_channel,
695                         BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
696         }
697 }
698
699 void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user)
700 {
701         unsigned int time_limit;
702
703         time_limit = user->time_limit * 1000;
704
705         if (!time_limit) {
706                 /* There is no duration limit that we need to apply. */
707                 return;
708         }
709
710         /* If the time limit has already been passed, set a really low time limit so we can kick them out immediately. */
711         time_limit = ast_remaining_ms(user->start, time_limit);
712         if (time_limit <= 0) {
713                 time_limit = 1;
714         }
715
716         /* The interval hook is going to need a reference to the parked_user */
717         ao2_ref(user, +1);
718
719         if (ast_bridge_interval_hook(features, 0, time_limit,
720                 parking_duration_callback, user, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
721                 ast_log(LOG_ERROR, "Failed to apply duration limit to the parked call.\n");
722                 ao2_ref(user, -1);
723         }
724 }
725
726 /*! \brief  Dial plan function to get the parking lot channel of an occupied parking lot */
727 static int func_get_parkingslot_channel(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
728 {
729         RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
730         RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
731         unsigned int space = 0;
732         const char *content = NULL;
733
734         AST_DECLARE_APP_ARGS(args,
735                 AST_APP_ARG(parking_space);
736                 AST_APP_ARG(parking_lot);
737                 AST_APP_ARG(other);
738         );
739
740         /* Parse the arguments. */
741         AST_STANDARD_APP_ARGS(args, data);
742
743         if (args.argc < 2) {
744                 /* Didn't receive enough arguments to do anything */
745                 ast_log(LOG_ERROR, "Usage: %s(<parking_space>,<parking_lot>)\n",
746                         function);
747                 return -1;
748         }
749
750         lot = parking_lot_find_by_name(args.parking_lot);
751         if (!lot) {
752                 ast_log(LOG_ERROR, "Could not find parking lot: '%s'\n", args.parking_lot);
753                 return -1;
754         }
755
756         if (!ast_strlen_zero(args.parking_space)) {
757                 if (ast_str_to_uint(args.parking_space, &space) != 0) {
758                         ast_log(LOG_ERROR, "value '%s' for parking_space argument is invalid. Must be an integer greater than 0.\n",
759                                 args.parking_space);
760                         return -1;
761                 }
762         }
763
764         pu = parking_lot_inspect_parked_user(lot, space);
765         if (!pu) {
766                 return -1;
767         }
768
769         content = ast_channel_name(pu->chan);
770         ast_copy_string(buf, content, len);
771
772         return 0;
773 }
774
775 static struct ast_custom_function getparkingslotchannel_function = {
776         .name = "PARK_GET_CHANNEL",
777         .read = func_get_parkingslot_channel,
778 };
779
780 struct ast_parking_bridge_feature_fn_table parking_provider = {
781         .module_version = PARKING_MODULE_VERSION,
782         .module_name = __FILE__,
783         .parking_is_exten_park = parking_is_exten_park,
784         .parking_blind_transfer_park = parking_blind_transfer_park,
785         .parking_park_bridge_channel = parking_park_bridge_channel,
786         .parking_park_call = parking_park_call,
787 };
788
789 void unload_parking_bridge_features(void)
790 {
791         ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_PARKCALL);
792         ast_parking_unregister_bridge_features(parking_provider.module_name);
793         ast_custom_function_unregister(&getparkingslotchannel_function);
794 }
795
796 int load_parking_bridge_features(void)
797 {
798         parking_provider.module = AST_MODULE_SELF;
799
800         ast_custom_function_register(&getparkingslotchannel_function);
801
802         if (ast_parking_register_bridge_features(&parking_provider)) {
803                 return -1;
804         }
805
806         if (ast_bridge_features_register(AST_BRIDGE_BUILTIN_PARKCALL, feature_park_call, NULL)) {
807                 return -1;
808         }
809
810         return 0;
811 }