stasis: Add internal filtering of messages.
[asterisk/asterisk.git] / res / parking / parking_applications.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 Call Parking Applications
22  *
23  * \author Jonathan Rose <jrose@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 #include "res_parking.h"
29 #include "asterisk/config.h"
30 #include "asterisk/config_options.h"
31 #include "asterisk/utils.h"
32 #include "asterisk/astobj2.h"
33 #include "asterisk/features.h"
34 #include "asterisk/module.h"
35 #include "asterisk/app.h"
36 #include "asterisk/say.h"
37 #include "asterisk/bridge_basic.h"
38 #include "asterisk/format_cache.h"
39
40 /*** DOCUMENTATION
41         <application name="Park" language="en_US">
42                 <synopsis>
43                         Park yourself.
44                 </synopsis>
45                 <syntax>
46                         <parameter name="parking_lot_name">
47                                 <para>Specify in which parking lot to park a call.</para>
48                                 <para>The parking lot used is selected in the following order:</para>
49                                 <para>1) parking_lot_name option to this application</para>
50                                 <para>2) <variable>PARKINGLOT</variable> variable</para>
51                                 <para>3) <literal>CHANNEL(parkinglot)</literal> function
52                                 (Possibly preset by the channel driver.)</para>
53                                 <para>4) Default parking lot.</para>
54                         </parameter>
55                         <parameter name="options">
56                                 <para>A list of options for this parked call.</para>
57                                 <optionlist>
58                                         <option name="r">
59                                                 <para>Send ringing instead of MOH to the parked call.</para>
60                                         </option>
61                                         <option name="R">
62                                                 <para>Randomize the selection of a parking space.</para>
63                                         </option>
64                                         <option name="s">
65                                                 <para>Silence announcement of the parking space number.</para>
66                                         </option>
67                                         <option name="c" argsep=",">
68                                                 <argument name="context" required="false" />
69                                                 <argument name="extension" required="false" />
70                                                 <argument name="priority" required="true" />
71                                                 <para>If the parking times out, go to this place in the dialplan
72                                                         instead of where the parking lot defines the call should go.
73                                                 </para>
74                                         </option>
75                                         <option name="t">
76                                                 <argument name="duration" required="true" />
77                                                 <para>Use a timeout of <literal>duration</literal> seconds instead
78                                                         of the timeout specified by the parking lot.</para>
79                                         </option>
80                                 </optionlist>
81                         </parameter>
82                 </syntax>
83                 <description>
84                         <para>Used to park yourself (typically in combination with an attended
85                         transfer to know the parking space).</para>
86                         <para>If you set the <variable>PARKINGEXTEN</variable> variable to a
87                                 parking space extension in the parking lot, Park() will attempt to park the
88                                 call on that extension. If the extension is already in use then execution
89                                 will continue at the next priority.
90                         </para>
91                         <para>If the <literal>parkeddynamic</literal> option is enabled in
92                                 <filename>res_parking.conf</filename> the following variables can be
93                                 used to dynamically create new parking lots. When using dynamic parking
94                                 lots, be aware of the conditions as explained in the notes section
95                                 below.
96                         </para>
97                         <para>The <variable>PARKINGDYNAMIC</variable> variable specifies the
98                                 parking lot to use as a template to create a dynamic parking lot. It
99                                 is an error to specify a non-existent parking lot for the template.
100                                 If not set then the default parking lot is used as the template.
101                         </para>
102                         <para>The <variable>PARKINGDYNCONTEXT</variable> variable specifies the
103                                 dialplan context to use for the newly created dynamic parking lot. If
104                                 not set then the context from the parking lot template is used. The
105                                 context is created if it does not already exist and the new parking lot
106                                 needs to create extensions.
107                         </para>
108                         <para>The <variable>PARKINGDYNEXTEN</variable> variable specifies the
109                                 <literal>parkext</literal> to use for the newly created dynamic
110                                 parking lot. If not set then the <literal>parkext</literal> is used from
111                                 the parking lot template. If the template does not specify a
112                                 <literal>parkext</literal> then no extensions are created for the newly
113                                 created parking lot. The dynamic parking lot cannot be created if it
114                                 needs to create extensions that overlap existing parking lot extensions.
115                                 The only exception to this is for the <literal>parkext</literal>
116                                 extension and only if neither of the overlaping parking lot's
117                                 <literal>parkext</literal> is exclusive.
118                         </para>
119                         <para>The <variable>PARKINGDYNPOS</variable> variable specifies the
120                                 parking positions to use for the newly created dynamic parking lot. If
121                                 not set then the <literal>parkpos</literal> from the parking lot template
122                                 is used.
123                         </para>
124                         <note>
125                                 <para>This application must be used as the first extension priority
126                                         to be recognized as a parking access extension for blind transfers.
127                                         Blind transfers and the DTMF one-touch parking feature need this
128                                         distinction to operate properly. The parking access extension in
129                                         this case is treated like a dialplan hint.
130                                 </para>
131                         </note>
132                 </description>
133                 <see-also>
134                         <ref type="application">ParkedCall</ref>
135                 </see-also>
136         </application>
137
138         <application name="ParkedCall" language="en_US">
139                 <synopsis>
140                         Retrieve a parked call.
141                 </synopsis>
142                 <syntax>
143                         <parameter name="parking_lot_name">
144                                 <para>Specify from which parking lot to retrieve a parked call.</para>
145                                 <para>The parking lot used is selected in the following order:</para>
146                                 <para>1) parking_lot_name option</para>
147                                 <para>2) <variable>PARKINGLOT</variable> variable</para>
148                                 <para>3) <literal>CHANNEL(parkinglot)</literal> function
149                                 (Possibly preset by the channel driver.)</para>
150                                 <para>4) Default parking lot.</para>
151                         </parameter>
152                         <parameter name="parking_space">
153                                 <para>Parking space to retrieve a parked call from.
154                                 If not provided then the first available parked call in the
155                                 parking lot will be retrieved.</para>
156                         </parameter>
157                 </syntax>
158                 <description>
159                         <para>Used to retrieve a parked call from a parking lot.</para>
160                         <note>
161                                 <para>If a parking lot's parkext option is set, then Parking lots
162                                 will automatically create and manage dialplan extensions in
163                                 the parking lot context. If that is the case then you will not
164                                 need to manage parking extensions yourself, just include the
165                                 parking context of the parking lot.</para>
166                         </note>
167                 </description>
168                 <see-also>
169                         <ref type="application">Park</ref>
170                 </see-also>
171         </application>
172
173         <application name="ParkAndAnnounce" language="en_US">
174                 <synopsis>
175                         Park and Announce.
176                 </synopsis>
177                 <syntax>
178                         <parameter name="parking_lot_name">
179                                 <para>Specify in which parking lot to park a call.</para>
180                                 <para>The parking lot used is selected in the following order:</para>
181                                 <para>1) parking_lot_name option to this application</para>
182                                 <para>2) <variable>PARKINGLOT</variable> variable</para>
183                                 <para>3) <literal>CHANNEL(parkinglot)</literal> function
184                                 (Possibly preset by the channel driver.)</para>
185                                 <para>4) Default parking lot.</para>
186                         </parameter>
187                         <parameter name="options">
188                                 <para>A list of options for this parked call.</para>
189                                 <optionlist>
190                                         <option name="r">
191                                                 <para>Send ringing instead of MOH to the parked call.</para>
192                                         </option>
193                                         <option name="R">
194                                                 <para>Randomize the selection of a parking space.</para>
195                                         </option>
196                                         <option name="c" argsep=",">
197                                                 <argument name="context" required="false" />
198                                                 <argument name="extension" required="false" />
199                                                 <argument name="priority" required="true" />
200                                                 <para>If the parking times out, go to this place in the dialplan
201                                                         instead of where the parking lot defines the call should go.
202                                                 </para>
203                                         </option>
204                                         <option name="t">
205                                                 <argument name="duration" required="true" />
206                                                 <para>Use a timeout of <literal>duration</literal> seconds instead
207                                                         of the timeout specified by the parking lot.</para>
208                                         </option>
209                                 </optionlist>
210                         </parameter>
211                         <parameter name="announce_template" required="true" argsep=":">
212                                 <argument name="announce" required="true">
213                                         <para>Colon-separated list of files to announce. The word
214                                         <literal>PARKED</literal> will be replaced by a say_digits of the extension in which
215                                         the call is parked.</para>
216                                 </argument>
217                                 <argument name="announce1" multiple="true" />
218                         </parameter>
219                         <parameter name="dial" required="true">
220                                 <para>The app_dial style resource to call to make the
221                                 announcement. Console/dsp calls the console.</para>
222                         </parameter>
223                 </syntax>
224                 <description>
225                         <para>Park a call into the parkinglot and announce the call to another channel.</para>
226                         <para>The variable <variable>PARKEDAT</variable> will contain the parking extension
227                         into which the call was placed.  Use with the Local channel to allow the dialplan to make
228                         use of this information.</para>
229                 </description>
230                 <see-also>
231                         <ref type="application">Park</ref>
232                         <ref type="application">ParkedCall</ref>
233                 </see-also>
234         </application>
235  ***/
236
237 #define PARK_AND_ANNOUNCE_APPLICATION "ParkAndAnnounce"
238
239 /* Park a call */
240
241 enum park_args {
242         OPT_ARG_COMEBACK,
243         OPT_ARG_TIMEOUT,
244         OPT_ARG_ARRAY_SIZE /* Always the last element of the enum */
245 };
246
247 enum park_flags {
248         MUXFLAG_RINGING = (1 << 0),
249         MUXFLAG_RANDOMIZE = (1 << 1),
250         MUXFLAG_NOANNOUNCE = (1 << 2),
251         MUXFLAG_COMEBACK_OVERRIDE = (1 << 3),
252         MUXFLAG_TIMEOUT_OVERRIDE = (1 << 4),
253 };
254
255 AST_APP_OPTIONS(park_opts, {
256         AST_APP_OPTION('r', MUXFLAG_RINGING),
257         AST_APP_OPTION('R', MUXFLAG_RANDOMIZE),
258         AST_APP_OPTION('s', MUXFLAG_NOANNOUNCE),
259         AST_APP_OPTION_ARG('c', MUXFLAG_COMEBACK_OVERRIDE, OPT_ARG_COMEBACK),
260         AST_APP_OPTION_ARG('t', MUXFLAG_TIMEOUT_OVERRIDE, OPT_ARG_TIMEOUT),
261 });
262
263 static int apply_option_timeout (int *var, char *timeout_arg)
264 {
265         if (ast_strlen_zero(timeout_arg)) {
266                 ast_log(LOG_ERROR, "No duration value provided for the timeout ('t') option.\n");
267                 return -1;
268         }
269
270         if (sscanf(timeout_arg, "%d", var) != 1 || *var < 0) {
271                 ast_log(LOG_ERROR, "Duration value provided for timeout ('t') option must be 0 or greater.\n");
272                 return -1;
273         }
274
275         return 0;
276 }
277
278 static int park_app_parse_data(const char *data, int *disable_announce, int *use_ringing, int *randomize, int *time_limit, char **comeback_override, char **lot_name)
279 {
280         char *parse;
281         struct ast_flags flags = { 0 };
282
283         AST_DECLARE_APP_ARGS(args,
284                 AST_APP_ARG(lot_name);
285                 AST_APP_ARG(options);
286                 AST_APP_ARG(other);     /* Any remaining unused arguments */
287         );
288
289         parse = ast_strdupa(data);
290         AST_STANDARD_APP_ARGS(args, parse);
291
292         if (args.options) {
293                 char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
294                 ast_app_parse_options(park_opts, &flags, opts, args.options);
295                 if (ast_test_flag(&flags, MUXFLAG_TIMEOUT_OVERRIDE)) {
296                         if (apply_option_timeout(time_limit, opts[OPT_ARG_TIMEOUT])) {
297                                 return -1;
298                         }
299                 }
300
301                 if (ast_test_flag(&flags, MUXFLAG_COMEBACK_OVERRIDE)) {
302                         *comeback_override = ast_strdup(opts[OPT_ARG_COMEBACK]);
303                 }
304
305                 if (ast_test_flag(&flags, MUXFLAG_NOANNOUNCE)) {
306                         if (disable_announce) {
307                                 *disable_announce = 1;
308                         }
309                 }
310
311                 if (ast_test_flag(&flags, MUXFLAG_RINGING)) {
312                         *use_ringing = 1;
313                 }
314
315                 if (ast_test_flag(&flags, MUXFLAG_RANDOMIZE)) {
316                         *randomize = 1;
317                 }
318         }
319
320         if (!ast_strlen_zero(args.lot_name)) {
321                 *lot_name = ast_strdup(args.lot_name);
322         }
323
324         return 0;
325 }
326
327 void park_common_datastore_free(struct park_common_datastore *datastore)
328 {
329         if (!datastore) {
330                 return;
331         }
332
333         ast_free(datastore->parker_uuid);
334         ast_free(datastore->parker_dial_string);
335         ast_free(datastore->comeback_override);
336         ast_free(datastore);
337 }
338
339 static void park_common_datastore_destroy(void *data)
340 {
341         struct park_common_datastore *datastore = data;
342         park_common_datastore_free(datastore);
343 }
344
345 static const struct ast_datastore_info park_common_info = {
346         .type = "park entry data",
347         .destroy = park_common_datastore_destroy,
348 };
349
350 static void wipe_park_common_datastore(struct ast_channel *chan)
351 {
352         struct ast_datastore *datastore;
353
354         ast_channel_lock(chan);
355         datastore = ast_channel_datastore_find(chan, &park_common_info, NULL);
356         if (datastore) {
357                 ast_channel_datastore_remove(chan, datastore);
358                 ast_datastore_free(datastore);
359         }
360         ast_channel_unlock(chan);
361 }
362
363 static int setup_park_common_datastore(struct ast_channel *parkee, const char *parker_uuid, const char *comeback_override, int randomize, int time_limit, int silence_announce)
364 {
365         struct ast_datastore *datastore = NULL;
366         struct park_common_datastore *park_datastore;
367         const char *attended_transfer;
368         const char *blind_transfer;
369         char *parker_dial_string = NULL;
370
371         wipe_park_common_datastore(parkee);
372
373         if (!(datastore = ast_datastore_alloc(&park_common_info, NULL))) {
374                 return -1;
375         }
376
377         if (!(park_datastore = ast_calloc(1, sizeof(*park_datastore)))) {
378                 ast_datastore_free(datastore);
379                 return -1;
380         }
381         datastore->data = park_datastore;
382
383         park_datastore->parker_uuid = ast_strdup(parker_uuid);
384         if (!park_datastore->parker_uuid) {
385                 ast_datastore_free(datastore);
386                 return -1;
387         }
388
389         ast_channel_lock(parkee);
390         attended_transfer = pbx_builtin_getvar_helper(parkee, "ATTENDEDTRANSFER");
391         blind_transfer = pbx_builtin_getvar_helper(parkee, "BLINDTRANSFER");
392         if (!ast_strlen_zero(attended_transfer)) {
393                 parker_dial_string = ast_strdupa(attended_transfer);
394         } else if (!ast_strlen_zero(blind_transfer)) {
395                 parker_dial_string = ast_strdupa(blind_transfer);
396                 /* Ensure that attended_transfer is NULL and not an empty string. */
397                 attended_transfer = NULL;
398         }
399         ast_channel_unlock(parkee);
400
401         if (!ast_strlen_zero(parker_dial_string)) {
402                 ast_channel_name_to_dial_string(parker_dial_string);
403                 ast_verb(4, "Setting Parker dial string to %s from %s value\n",
404                         parker_dial_string,
405                         attended_transfer ? "ATTENDEDTRANSFER" : "BLINDTRANSFER");
406                 park_datastore->parker_dial_string = ast_strdup(parker_dial_string);
407                 if (!park_datastore->parker_dial_string) {
408                         ast_datastore_free(datastore);
409                         return -1;
410                 }
411         }
412
413         park_datastore->randomize = randomize;
414         park_datastore->time_limit = time_limit;
415         park_datastore->silence_announce = silence_announce;
416
417         if (comeback_override) {
418                 park_datastore->comeback_override = ast_strdup(comeback_override);
419                 if (!park_datastore->comeback_override) {
420                         ast_datastore_free(datastore);
421                         return -1;
422                 }
423         }
424
425
426         ast_channel_lock(parkee);
427         ast_channel_datastore_add(parkee, datastore);
428         ast_channel_unlock(parkee);
429
430         return 0;
431 }
432
433 struct park_common_datastore *get_park_common_datastore_copy(struct ast_channel *parkee)
434 {
435         struct ast_datastore *datastore;
436         struct park_common_datastore *data;
437         struct park_common_datastore *data_copy;
438
439         SCOPED_CHANNELLOCK(lock, parkee);
440
441         if (!(datastore = ast_channel_datastore_find(parkee, &park_common_info, NULL))) {
442                 return NULL;
443         }
444
445         data = datastore->data;
446
447         /* This data should always be populated if this datastore was appended to the channel */
448         ast_assert(data != NULL);
449
450         data_copy = ast_calloc(1, sizeof(*data_copy));
451         if (!data_copy) {
452                 return NULL;
453         }
454
455         data_copy->parker_uuid = ast_strdup(data->parker_uuid);
456         if (!data_copy->parker_uuid) {
457                 park_common_datastore_free(data_copy);
458                 return NULL;
459         }
460
461         data_copy->randomize = data->randomize;
462         data_copy->time_limit = data->time_limit;
463         data_copy->silence_announce = data->silence_announce;
464
465         if (data->comeback_override) {
466                 data_copy->comeback_override = ast_strdup(data->comeback_override);
467                 if (!data_copy->comeback_override) {
468                         park_common_datastore_free(data_copy);
469                         return NULL;
470                 }
471         }
472
473         if (data->parker_dial_string) {
474                 data_copy->parker_dial_string = ast_strdup(data->parker_dial_string);
475                 if (!data_copy->parker_dial_string) {
476                         park_common_datastore_free(data_copy);
477                         return NULL;
478                 }
479         }
480
481         return data_copy;
482 }
483
484 struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker,
485                 const char *lot_name, const char *comeback_override,
486                 int use_ringing, int randomize, int time_limit, int silence_announcements)
487 {
488         struct ast_bridge *parking_bridge;
489         RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
490
491         if (!parker) {
492                 parker = parkee;
493         }
494
495         /* If the name of the parking lot isn't specified in the arguments, find it based on the channel. */
496         if (ast_strlen_zero(lot_name)) {
497                 ast_channel_lock(parker);
498                 lot_name = ast_strdupa(find_channel_parking_lot_name(parker));
499                 ast_channel_unlock(parker);
500         }
501
502         lot = parking_lot_find_by_name(lot_name);
503         if (!lot) {
504                 lot = parking_create_dynamic_lot(lot_name, parker);
505         }
506         if (!lot) {
507                 ast_log(LOG_ERROR, "Could not find parking lot: '%s'\n", lot_name);
508                 return NULL;
509         }
510
511         ao2_lock(lot);
512         parking_bridge = parking_lot_get_bridge(lot);
513         ao2_unlock(lot);
514
515         if (!parking_bridge) {
516                 return NULL;
517         }
518
519         /* Apply relevant bridge roles and such to the parking channel */
520         parking_channel_set_roles(parkee, lot, use_ringing);
521         setup_park_common_datastore(parkee, ast_channel_uniqueid(parker), comeback_override, randomize, time_limit,
522                 silence_announcements);
523         return parking_bridge;
524 }
525
526 struct ast_bridge *park_application_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *app_data,
527                 int *silence_announcements)
528 {
529         int use_ringing = 0;
530         int randomize = 0;
531         int time_limit = -1;
532
533         RAII_VAR(char *, comeback_override, NULL, ast_free);
534         RAII_VAR(char *, lot_name_app_arg, NULL, ast_free);
535
536         if (app_data) {
537                 park_app_parse_data(app_data, silence_announcements, &use_ringing, &randomize, &time_limit, &comeback_override, &lot_name_app_arg);
538         }
539
540         return park_common_setup(parkee, parker, lot_name_app_arg, comeback_override, use_ringing,
541                 randomize, time_limit, silence_announcements ? *silence_announcements : 0);
542
543 }
544
545 static int park_app_exec(struct ast_channel *chan, const char *data)
546 {
547         RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
548
549         struct ast_bridge_features chan_features;
550         int res;
551         int silence_announcements = 0;
552         int blind_transfer;
553
554         /* Answer the channel if needed */
555         if (ast_channel_state(chan) != AST_STATE_UP) {
556                 ast_answer(chan);
557         }
558
559         ast_channel_lock(chan);
560         blind_transfer = !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"));
561         ast_channel_unlock(chan);
562
563         /* Handle the common parking setup stuff */
564         if (!(parking_bridge = park_application_setup(chan, NULL, data, &silence_announcements))) {
565                 if (!silence_announcements && !blind_transfer) {
566                         ast_stream_and_wait(chan, "pbx-parkingfailed", "");
567                 }
568                 publish_parked_call_failure(chan);
569                 return 0;
570         }
571
572         /* Initialize bridge features for the channel. */
573         res = ast_bridge_features_init(&chan_features);
574         if (res) {
575                 ast_bridge_features_cleanup(&chan_features);
576                 publish_parked_call_failure(chan);
577                 return -1;
578         }
579
580         /* Now for the fun part... park it! */
581         ast_bridge_join(parking_bridge, chan, NULL, &chan_features, NULL, 0);
582
583         /*
584          * If the bridge was broken for a hangup that isn't real, then
585          * don't run the h extension, because the channel isn't really
586          * hung up.  This should only happen with AST_SOFTHANGUP_ASYNCGOTO.
587          */
588         res = -1;
589
590         ast_channel_lock(chan);
591         if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
592                 res = 0;
593         }
594         ast_channel_unlock(chan);
595
596         ast_bridge_features_cleanup(&chan_features);
597
598         return res;
599 }
600
601 /* Retrieve a parked call */
602
603 static int parked_call_app_exec(struct ast_channel *chan, const char *data)
604 {
605         RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
606         RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup); /* Parked user being retrieved */
607         struct ast_bridge *retrieval_bridge;
608         int res;
609         int target_space = -1;
610         struct ast_bridge_features chan_features;
611         char *parse;
612         const char *lot_name;
613
614         AST_DECLARE_APP_ARGS(args,
615                 AST_APP_ARG(lot_name);
616                 AST_APP_ARG(parking_space);
617                 AST_APP_ARG(other);     /* Any remaining unused arguments */
618         );
619
620         parse = ast_strdupa(data);
621         AST_STANDARD_APP_ARGS(args, parse);
622
623         /* Answer the channel if needed */
624         if (ast_channel_state(chan) != AST_STATE_UP) {
625                 ast_answer(chan);
626         }
627
628         lot_name = args.lot_name;
629
630         /* If the name of the parking lot isn't in the arguments, find it based on the channel. */
631         if (ast_strlen_zero(lot_name)) {
632                 ast_channel_lock(chan);
633                 lot_name = ast_strdupa(find_channel_parking_lot_name(chan));
634                 ast_channel_unlock(chan);
635         }
636
637         lot = parking_lot_find_by_name(lot_name);
638         if (!lot) {
639                 ast_log(LOG_ERROR, "Could not find the requested parking lot\n");
640                 ast_stream_and_wait(chan, "pbx-invalidpark", "");
641                 return -1;
642         }
643
644         if (!ast_strlen_zero(args.parking_space)) {
645                 if (sscanf(args.parking_space, "%d", &target_space) != 1 || target_space < 0) {
646                         ast_stream_and_wait(chan, "pbx-invalidpark", "");
647                         ast_log(LOG_ERROR, "value '%s' for parking_space argument is invalid. Must be an integer greater than 0.\n", args.parking_space);
648                         return -1;
649                 }
650         }
651
652         /* Attempt to get the parked user from the parking lot */
653         pu = parking_lot_retrieve_parked_user(lot, target_space);
654         if (!pu) {
655                 ast_stream_and_wait(chan, "pbx-invalidpark", "");
656                 return -1;
657         }
658
659         /* The parked call needs to know who is retrieving it before we move it out of the parking bridge */
660         ast_assert(pu->retriever == NULL);
661         pu->retriever = ast_channel_snapshot_create(chan);
662
663         /* Create bridge */
664         retrieval_bridge = ast_bridge_basic_new();
665         if (!retrieval_bridge) {
666                 return -1;
667         }
668
669         /* Move the parkee into the new bridge */
670         if (ast_bridge_move(retrieval_bridge, lot->parking_bridge, pu->chan, NULL, 0)) {
671                 ast_bridge_destroy(retrieval_bridge, 0);
672                 return -1;
673         }
674
675         /* Initialize our bridge features */
676         res = ast_bridge_features_init(&chan_features);
677         if (res) {
678                 ast_bridge_destroy(retrieval_bridge, 0);
679                 ast_bridge_features_cleanup(&chan_features);
680                 return -1;
681         }
682
683         /* Set the features */
684         parked_call_retrieve_enable_features(chan, lot, AST_FEATURE_FLAG_BYCALLER);
685
686         /* If the parkedplay option is set for the caller to hear, play that tone now. */
687         if (lot->cfg->parkedplay & AST_FEATURE_FLAG_BYCALLER) {
688                 ast_stream_and_wait(chan, lot->cfg->courtesytone, NULL);
689         }
690
691         /* Now we should try to join the new bridge ourselves... */
692         ast_bridge_join(retrieval_bridge, chan, NULL, &chan_features, NULL,
693                 AST_BRIDGE_JOIN_PASS_REFERENCE);
694
695         ast_bridge_features_cleanup(&chan_features);
696
697         /* Return -1 so that call does not continue in the dialplan. This is to make
698          * behavior consistent with Asterisk versions prior to 12.
699          */
700         return -1;
701 }
702
703 struct park_announce_subscription_data {
704         char *parkee_uuid;
705         char *dial_string;
706         char *announce_string;
707 };
708
709 static void park_announce_subscription_data_destroy(void *data)
710 {
711         struct park_announce_subscription_data *pa_data = data;
712         ast_free(pa_data->parkee_uuid);
713         ast_free(pa_data->dial_string);
714         ast_free(pa_data->announce_string);
715         ast_free(pa_data);
716 }
717
718 static struct park_announce_subscription_data *park_announce_subscription_data_create(const char *parkee_uuid,
719                 const char *dial_string,
720                 const char *announce_string)
721 {
722         struct park_announce_subscription_data *pa_data;
723
724         if (!(pa_data = ast_calloc(1, sizeof(*pa_data)))) {
725                 return NULL;
726         }
727
728         if (!(pa_data->parkee_uuid = ast_strdup(parkee_uuid))
729                 || !(pa_data->dial_string = ast_strdup(dial_string))
730                 || !(pa_data->announce_string = ast_strdup(announce_string))) {
731                 park_announce_subscription_data_destroy(pa_data);
732                 return NULL;
733         }
734
735         return pa_data;
736 }
737
738 /*! \internal
739  * \brief Gathers inheritable channel variables from a channel by name.
740  *
741  * \param oh outgoing helper struct we are bestowing inheritable variables to
742  * \param channel_id name or uniqueID of the channel to inherit variables from
743  *
744  * \return Nothing
745  */
746 static void inherit_channel_vars_from_id(struct outgoing_helper *oh, const char *channel_id)
747 {
748         struct ast_channel *chan = ast_channel_get_by_name(channel_id);
749         struct ast_var_t *current;
750         struct ast_variable *newvar;
751         const char *varname;
752         int vartype;
753
754
755         if (!chan) {
756                 /* Already gone */
757                 return;
758         }
759
760         ast_channel_lock(chan);
761
762         AST_LIST_TRAVERSE(ast_channel_varshead((struct ast_channel *) chan), current, entries) {
763                 varname = ast_var_full_name(current);
764                 if (!varname) {
765                         continue;
766                 }
767
768                 vartype = 0;
769                 if (varname[0] == '_') {
770                         vartype = 1;
771                         if (varname[1] == '_') {
772                                 vartype = 2;
773                         }
774                 }
775
776                 switch (vartype) {
777                 case 1:
778                         newvar = ast_variable_new(&varname[1], ast_var_value(current), "");
779                         break;
780                 case 2:
781                         newvar = ast_variable_new(varname, ast_var_value(current), "");
782                         break;
783                 default:
784                         continue;
785                 }
786                 if (newvar) {
787                         ast_debug(1, "Inheriting variable %s from %s.\n",
788                                 newvar->name, ast_channel_name(chan));
789                         if (oh->vars) {
790                                 newvar->next = oh->vars;
791                                 oh->vars = newvar;
792                         }
793                 }
794         }
795
796         ast_channel_unlock(chan);
797         ast_channel_cleanup(chan);
798 }
799
800 static void announce_to_dial(char *dial_string, char *announce_string, int parkingspace, struct ast_channel_snapshot *parkee_snapshot)
801 {
802         struct ast_channel *dchan;
803         struct outgoing_helper oh = { 0, };
804         int outstate;
805         struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
806         char buf[13];
807         char *dial_tech;
808         char *cur_announce;
809
810         dial_tech = strsep(&dial_string, "/");
811         ast_verb(3, "Dial Tech,String: (%s,%s)\n", dial_tech, dial_string);
812
813         if (!cap_slin) {
814                 ast_log(LOG_WARNING, "PARK: Failed to announce park.\n");
815                 goto announce_cleanup;
816         }
817         ast_format_cap_append(cap_slin, ast_format_slin, 0);
818
819         snprintf(buf, sizeof(buf), "%d", parkingspace);
820         oh.vars = ast_variable_new("_PARKEDAT", buf, "");
821
822         inherit_channel_vars_from_id(&oh, parkee_snapshot->uniqueid);
823
824         dchan = __ast_request_and_dial(dial_tech, cap_slin, NULL, NULL, dial_string, 30000,
825                 &outstate,
826                 parkee_snapshot->caller_number,
827                 parkee_snapshot->caller_name,
828                 &oh);
829
830         ast_variables_destroy(oh.vars);
831         if (!dchan) {
832                 ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
833                 goto announce_cleanup;
834         }
835
836         ast_verb(4, "Announce Template: %s\n", announce_string);
837
838         for (cur_announce = strsep(&announce_string, ":"); cur_announce; cur_announce = strsep(&announce_string, ":")) {
839                 ast_verb(4, "Announce:%s\n", cur_announce);
840                 if (!strcmp(cur_announce, "PARKED")) {
841                         ast_say_digits(dchan, parkingspace, "", ast_channel_language(dchan));
842                 } else {
843                         int dres = ast_streamfile(dchan, cur_announce, ast_channel_language(dchan));
844                         if (!dres) {
845                                 dres = ast_waitstream(dchan, "");
846                         } else {
847                                 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", cur_announce, ast_channel_name(dchan));
848                         }
849                 }
850         }
851
852         ast_stopstream(dchan);
853         ast_hangup(dchan);
854
855 announce_cleanup:
856         ao2_cleanup(cap_slin);
857 }
858
859 static void park_announce_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
860 {
861         struct park_announce_subscription_data *pa_data = data;
862         char *dial_string = pa_data->dial_string;
863
864         struct ast_parked_call_payload *payload = stasis_message_data(message);
865
866         if (stasis_subscription_final_message(sub, message)) {
867                 park_announce_subscription_data_destroy(data);
868                 return;
869         }
870
871         if (ast_parked_call_type() != stasis_message_type(message)) {
872                 return;
873         }
874
875         if (payload->event_type != PARKED_CALL) {
876                 /* We are only concerned with calls parked */
877                 return;
878         }
879
880         if (strcmp(payload->parkee->uniqueid, pa_data->parkee_uuid)) {
881                 /* We are only concerned with the parkee we are subscribed for. */
882                 return;
883         }
884
885         if (!ast_strlen_zero(dial_string)) {
886                 announce_to_dial(dial_string, pa_data->announce_string, payload->parkingspace, payload->parkee);
887         }
888
889         *dial_string = '\0'; /* If we observe this dial string on a second pass, we don't want to do anything with it. */
890 }
891
892 static int park_and_announce_app_exec(struct ast_channel *chan, const char *data)
893 {
894         struct ast_bridge_features chan_features;
895         char *parse;
896         int res;
897         int silence_announcements = 1;
898
899         struct stasis_subscription *parking_subscription;
900         struct park_announce_subscription_data *pa_data;
901
902         RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
903
904         AST_DECLARE_APP_ARGS(args,
905                 AST_APP_ARG(lot_name);
906                 AST_APP_ARG(options);
907                 AST_APP_ARG(announce_template);
908                 AST_APP_ARG(dial);
909                 AST_APP_ARG(others);/* Any remaining unused arguments */
910         );
911
912         if (ast_strlen_zero(data)) {
913                 ast_log(LOG_ERROR, "ParkAndAnnounce has required arguments. No arguments were provided.\n");
914                 return -1;
915         }
916
917         parse = ast_strdupa(data);
918         AST_STANDARD_APP_ARGS(args, parse);
919
920         if (ast_strlen_zero(args.announce_template)) {
921                 /* improperly configured arguments for the application */
922                 ast_log(LOG_ERROR, "ParkAndAnnounce requires the announce_template argument.\n");
923                 return -1;
924         }
925
926         if (ast_strlen_zero(args.dial)) {
927                 /* improperly configured arguments */
928                 ast_log(LOG_ERROR, "ParkAndAnnounce requires the dial argument.\n");
929                 return -1;
930         }
931
932         if (!strchr(args.dial, '/')) {
933                 ast_log(LOG_ERROR, "ParkAndAnnounce dial string '%s' is improperly formed.\n", args.dial);
934                 return -1;
935         }
936
937         /* Handle the common parking setup stuff */
938         if (!(parking_bridge = park_application_setup(chan, NULL, data, &silence_announcements))) {
939                 return 0;
940         }
941
942         /* Initialize bridge features for the channel. */
943         res = ast_bridge_features_init(&chan_features);
944         if (res) {
945                 ast_bridge_features_cleanup(&chan_features);
946                 return -1;
947         }
948
949         /* subscribe to the parking message so that we can announce once it is parked */
950         pa_data = park_announce_subscription_data_create(ast_channel_uniqueid(chan), args.dial, args.announce_template);
951         if (!pa_data) {
952                 return -1;
953         }
954
955         if (!(parking_subscription = stasis_subscribe_pool(ast_parking_topic(), park_announce_update_cb, pa_data))) {
956                 /* Failed to create subscription */
957                 park_announce_subscription_data_destroy(pa_data);
958                 return -1;
959         }
960
961         stasis_subscription_accept_message_type(parking_subscription, ast_parked_call_type());
962         stasis_subscription_accept_message_type(parking_subscription, stasis_subscription_change_type());
963         stasis_subscription_set_filter(parking_subscription, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
964
965         /* Now for the fun part... park it! */
966         ast_bridge_join(parking_bridge, chan, NULL, &chan_features, NULL, 0);
967
968         /* Toss the subscription since we aren't bridged at this point. */
969         stasis_unsubscribe(parking_subscription);
970
971         /*
972          * If the bridge was broken for a hangup that isn't real, then
973          * don't run the h extension, because the channel isn't really
974          * hung up.  This should only happen with AST_SOFTHANGUP_ASYNCGOTO.
975          */
976         res = -1;
977
978         ast_channel_lock(chan);
979         if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
980                 res = 0;
981         }
982         ast_channel_unlock(chan);
983
984         ast_bridge_features_cleanup(&chan_features);
985
986         return res;
987 }
988
989 int load_parking_applications(void)
990 {
991         if (ast_register_application_xml(PARK_APPLICATION, park_app_exec)) {
992                 return -1;
993         }
994
995         if (ast_register_application_xml(PARKED_CALL_APPLICATION, parked_call_app_exec)) {
996                 return -1;
997         }
998
999         if (ast_register_application_xml(PARK_AND_ANNOUNCE_APPLICATION, park_and_announce_app_exec)) {
1000                 return -1;
1001         }
1002
1003         return 0;
1004 }
1005
1006 void unload_parking_applications(void)
1007 {
1008         ast_unregister_application(PARK_APPLICATION);
1009         ast_unregister_application(PARKED_CALL_APPLICATION);
1010         ast_unregister_application(PARK_AND_ANNOUNCE_APPLICATION);
1011 }