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