2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2008, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief Routines implementing call features as call pickup, parking and transfer
23 * \author Mark Spencer <markster@digium.com>
27 <support_level>core</support_level>
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include "asterisk/_private.h"
39 #include <sys/signal.h>
40 #include <netinet/in.h>
42 #include "asterisk/lock.h"
43 #include "asterisk/file.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/causes.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/app.h"
50 #include "asterisk/say.h"
51 #include "asterisk/features.h"
52 #include "asterisk/musiconhold.h"
53 #include "asterisk/config.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/manager.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/adsi.h"
58 #include "asterisk/devicestate.h"
59 #include "asterisk/monitor.h"
60 #include "asterisk/audiohook.h"
61 #include "asterisk/global_datastores.h"
62 #include "asterisk/astobj2.h"
63 #include "asterisk/cel.h"
64 #include "asterisk/test.h"
67 * Party A - transferee
68 * Party B - transferer
69 * Party C - target of transfer
71 * DTMF attended transfer works within the channel bridge.
72 * Unfortunately, when either party A or B in the channel bridge
73 * hangs up, that channel is not completely hung up until the
74 * transfer completes. This is a real problem depending upon
75 * the channel technology involved.
77 * For chan_dahdi, the channel is crippled until the hangup is
78 * complete. Either the channel is not useable (analog) or the
79 * protocol disconnect messages are held up (PRI/BRI/SS7) and
80 * the media is not released.
82 * For chan_sip, a call limit of one is going to block that
83 * endpoint from any further calls until the hangup is complete.
85 * For party A this is a minor problem. The party A channel
86 * will only be in this condition while party B is dialing and
87 * when party B and C are conferring. The conversation between
88 * party B and C is expected to be a short one. Party B is
89 * either asking a question of party C or announcing party A.
90 * Also party A does not have much incentive to hangup at this
93 * For party B this can be a major problem during a blonde
94 * transfer. (A blonde transfer is our term for an attended
95 * transfer that is converted into a blind transfer. :)) Party
96 * B could be the operator. When party B hangs up, he assumes
97 * that he is out of the original call entirely. The party B
98 * channel will be in this condition while party C is ringing,
99 * while attempting to recall party B, and while waiting between
103 * The ATXFER_NULL_TECH conditional is a hack to fix the
104 * problem. It will replace the party B channel technology with
105 * a NULL channel driver. The consequences of this code is that
106 * the 'h' extension will not be able to access any channel
107 * technology specific information like SIP statistics for the
110 * Uncomment the ATXFER_NULL_TECH define below to replace the
111 * party B channel technology in the channel bridge to complete
112 * hanging up the channel technology.
114 //#define ATXFER_NULL_TECH 1
117 <application name="Bridge" language="en_US">
122 <parameter name="channel" required="true">
123 <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
125 <parameter name="options">
128 <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
131 <para>Allow the called party to hang up by sending the
132 <replaceable>*</replaceable> DTMF digit.</para>
135 <para>Allow the calling party to hang up by pressing the
136 <replaceable>*</replaceable> DTMF digit.</para>
139 <para>Allow the called party to enable parking of the call by sending
140 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
143 <para>Allow the calling party to enable parking of the call by sending
144 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
146 <option name="L(x[:y][:z])">
147 <para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
148 when <replaceable>y</replaceable> ms are left. Repeat the warning every
149 <replaceable>z</replaceable> ms. The following special variables can be
150 used with this option:</para>
152 <variable name="LIMIT_PLAYAUDIO_CALLER">
153 <para>Play sounds to the caller. yes|no (default yes)</para>
155 <variable name="LIMIT_PLAYAUDIO_CALLEE">
156 <para>Play sounds to the callee. yes|no</para>
158 <variable name="LIMIT_TIMEOUT_FILE">
159 <para>File to play when time is up.</para>
161 <variable name="LIMIT_CONNECT_FILE">
162 <para>File to play when call begins.</para>
164 <variable name="LIMIT_WARNING_FILE">
165 <para>File to play as warning if <replaceable>y</replaceable> is
166 defined. The default is to say the time remaining.</para>
171 <para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
174 <para>Allow the called party to transfer the calling party by sending the
175 DTMF sequence defined in <filename>features.conf</filename>.</para>
178 <para>Allow the calling party to transfer the called party by sending the
179 DTMF sequence defined in <filename>features.conf</filename>.</para>
182 <para>Allow the called party to enable recording of the call by sending
183 the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
186 <para>Allow the calling party to enable recording of the call by sending
187 the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
190 <para>Cause the called party to be hung up after the bridge, instead of being
191 restarted in the dialplan.</para>
197 <para>Allows the ability to bridge two channels via the dialplan.</para>
198 <para>This application sets the following channel variable upon completion:</para>
200 <variable name="BRIDGERESULT">
201 <para>The result of the bridge attempt as a text string.</para>
202 <value name="SUCCESS" />
203 <value name="FAILURE" />
204 <value name="LOOP" />
205 <value name="NONEXISTENT" />
206 <value name="INCOMPATIBLE" />
211 <application name="ParkedCall" language="en_US">
213 Retrieve a parked call.
216 <parameter name="exten">
217 <para>Parking space extension to retrieve a parked call.
218 If not provided then the first available parked call in the
219 parking lot will be retrieved.</para>
221 <parameter name="parking_lot_name">
222 <para>Specify from which parking lot to retrieve a parked call.</para>
223 <para>The parking lot used is selected in the following order:</para>
224 <para>1) parking_lot_name option</para>
225 <para>2) <variable>PARKINGLOT</variable> variable</para>
226 <para>3) <literal>CHANNEL(parkinglot)</literal> function
227 (Possibly preset by the channel driver.)</para>
228 <para>4) Default parking lot.</para>
232 <para>Used to retrieve a parked call from a parking lot.</para>
234 <para>Parking lots automatically create and manage dialplan extensions in
235 the parking lot context. You do not need to explicitly use this
236 application in your dialplan. Instead, all you should do is include the
237 parking lot context in your dialplan.</para>
241 <ref type="application">Park</ref>
242 <ref type="application">ParkAndAnnounce</ref>
245 <application name="Park" language="en_US">
250 <parameter name="timeout">
251 <para>A custom parking timeout for this parked call. Value in milliseconds.</para>
253 <parameter name="return_context">
254 <para>The context to return the call to after it times out.</para>
256 <parameter name="return_exten">
257 <para>The extension to return the call to after it times out.</para>
259 <parameter name="return_priority">
260 <para>The priority to return the call to after it times out.</para>
262 <parameter name="options">
263 <para>A list of options for this parked call.</para>
266 <para>Send ringing instead of MOH to the parked call.</para>
269 <para>Randomize the selection of a parking space.</para>
272 <para>Silence announcement of the parking space number.</para>
276 <parameter name="parking_lot_name">
277 <para>Specify in which parking lot to park a call.</para>
278 <para>The parking lot used is selected in the following order:</para>
279 <para>1) parking_lot_name option</para>
280 <para>2) <variable>PARKINGLOT</variable> variable</para>
281 <para>3) <literal>CHANNEL(parkinglot)</literal> function
282 (Possibly preset by the channel driver.)</para>
283 <para>4) Default parking lot.</para>
287 <para>Used to park yourself (typically in combination with a supervised
288 transfer to know the parking space).</para>
289 <para>If you set the <variable>PARKINGEXTEN</variable> variable to a
290 parking space extension in the parking lot, Park() will attempt to park the call
291 on that extension. If the extension is already is in use then execution
292 will continue at the next priority.</para>
293 <para>If the <literal>parkeddynamic</literal> option is enabled in <filename>features.conf</filename>
294 the following variables can be used to dynamically create new parking lots.</para>
295 <para>If you set the <variable>PARKINGDYNAMIC</variable> variable and this parking lot
296 exists then it will be used as a template for the newly created dynamic lot. Otherwise,
297 the default parking lot will be used.</para>
298 <para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable then the newly created dynamic
299 parking lot will use this context.</para>
300 <para>If you set the <variable>PARKINGDYNEXTEN</variable> variable then the newly created dynamic
301 parking lot will use this extension to access the parking lot.</para>
302 <para>If you set the <variable>PARKINGDYNPOS</variable> variable then the newly created dynamic parking lot
303 will use those parking postitions.</para>
305 <para>This application must be used as the first extension priority
306 to be recognized as a parking access extension. DTMF transfers
307 and some channel drivers need this distinction to operate properly.
308 The parking access extension in this case is treated like a dialplan
312 <para>Parking lots automatically create and manage dialplan extensions in
313 the parking lot context. You do not need to explicitly use this
314 application in your dialplan. Instead, all you should do is include the
315 parking lot context in your dialplan.</para>
319 <ref type="application">ParkAndAnnounce</ref>
320 <ref type="application">ParkedCall</ref>
323 <manager name="ParkedCalls" language="en_US">
328 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
331 <para>List parked calls.</para>
334 <manager name="Park" language="en_US">
339 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
340 <parameter name="Channel" required="true">
341 <para>Channel name to park.</para>
343 <parameter name="Channel2" required="true">
344 <para>Channel to return to if timeout.</para>
346 <parameter name="Timeout">
347 <para>Number of milliseconds to wait before callback.</para>
349 <parameter name="Parkinglot">
350 <para>Specify in which parking lot to park the channel.</para>
354 <para>Park a channel.</para>
357 <manager name="Bridge" language="en_US">
359 Bridge two channels already in the PBX.
362 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
363 <parameter name="Channel1" required="true">
364 <para>Channel to Bridge to Channel2.</para>
366 <parameter name="Channel2" required="true">
367 <para>Channel to Bridge to Channel1.</para>
369 <parameter name="Tone">
370 <para>Play courtesy tone to Channel 2.</para>
378 <para>Bridge together two channels already in the PBX.</para>
383 #define DEFAULT_PARK_TIME 45000 /*!< ms */
384 #define DEFAULT_PARK_EXTENSION "700"
385 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000 /*!< ms */
386 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000 /*!< ms */
387 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000 /*!< ms */
388 #define DEFAULT_ATXFER_DROP_CALL 0 /*!< Do not drop call. */
389 #define DEFAULT_ATXFER_LOOP_DELAY 10000 /*!< ms */
390 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
392 #define AST_MAX_WATCHERS 256
393 #define MAX_DIAL_FEATURE_OPTIONS 30
395 struct feature_group_exten {
396 AST_LIST_ENTRY(feature_group_exten) entry;
397 AST_DECLARE_STRING_FIELDS(
398 AST_STRING_FIELD(exten);
400 struct ast_call_feature *feature;
403 struct feature_group {
404 AST_LIST_ENTRY(feature_group) entry;
405 AST_DECLARE_STRING_FIELDS(
406 AST_STRING_FIELD(gname);
408 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
411 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
414 FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
415 FEATURE_INTERPRET_DO, /* Used by feature_interpret */
416 FEATURE_INTERPRET_CHECK, /* Used by feature_check */
417 } feature_interpret_op;
419 static char *parkedcall = "ParkedCall";
421 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
423 /*! Parking lot access ramp dialplan usage entry. */
424 struct parking_dp_ramp {
425 /*! Next node in the parking lot spaces dialplan list. */
426 AST_LIST_ENTRY(parking_dp_ramp) node;
427 /*! TRUE if the parking lot access extension is exclusive. */
428 unsigned int exclusive:1;
429 /*! Parking lot access extension */
433 /*! Parking lot dialplan access ramp map */
434 AST_LIST_HEAD_NOLOCK(parking_dp_ramp_map, parking_dp_ramp);
436 /*! Parking lot spaces dialplan usage entry. */
437 struct parking_dp_spaces {
438 /*! Next node in the parking lot spaces dialplan list. */
439 AST_LIST_ENTRY(parking_dp_spaces) node;
440 /*! First parking space */
442 /*! Last parking space */
446 /*! Parking lot dialplan context space map */
447 AST_LIST_HEAD_NOLOCK(parking_dp_space_map, parking_dp_spaces);
449 /*! Parking lot context dialplan usage entry. */
450 struct parking_dp_context {
451 /*! Next node in the parking lot contexts dialplan list. */
452 AST_LIST_ENTRY(parking_dp_context) node;
453 /*! Parking access extensions defined in this context. */
454 struct parking_dp_ramp_map access_extens;
455 /*! Parking spaces defined in this context. */
456 struct parking_dp_space_map spaces;
457 /*! Parking hints defined in this context. */
458 struct parking_dp_space_map hints;
459 /*! Parking lot context name */
463 /*! Parking lot dialplan usage map. */
464 AST_LIST_HEAD_NOLOCK(parking_dp_map, parking_dp_context);
467 * \brief Description of one parked call, added to a list while active, then removed.
468 * The list belongs to a parkinglot.
471 struct ast_channel *chan; /*!< Parked channel */
472 struct timeval start; /*!< Time the park started */
473 int parkingnum; /*!< Parking lot space used */
474 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
475 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
476 char exten[AST_MAX_EXTENSION];
478 int parkingtime; /*!< Maximum length in parking lot before return */
479 /*! Method to entertain the caller when parked: AST_CONTROL_RINGING, AST_CONTROL_HOLD, or 0(none) */
480 enum ast_control_frame_type hold_method;
481 unsigned int notquiteyet:1;
482 unsigned int options_specified:1;
484 unsigned char moh_trys;
485 /*! Parking lot this entry belongs to. Holds a parking lot reference. */
486 struct ast_parkinglot *parkinglot;
487 AST_LIST_ENTRY(parkeduser) list;
490 /*! Parking lot configuration options. */
491 struct parkinglot_cfg {
492 /*! Music class used for parking */
493 char mohclass[MAX_MUSICCLASS];
494 /*! Extension to park calls in this parking lot. */
495 char parkext[AST_MAX_EXTENSION];
496 /*! Context for which parking is made accessible */
497 char parking_con[AST_MAX_EXTENSION];
498 /*! First available extension for parking */
500 /*! Last available extension for parking */
502 /*! Default parking time in ms. */
505 * \brief Enable DTMF based transfers on bridge when picking up parked calls.
509 * AST_FEATURE_FLAG_BYCALLEE
510 * AST_FEATURE_FLAG_BYCALLER
511 * AST_FEATURE_FLAG_BYBOTH
513 int parkedcalltransfers;
515 * \brief Enable DTMF based parking on bridge when picking up parked calls.
519 * AST_FEATURE_FLAG_BYCALLEE
520 * AST_FEATURE_FLAG_BYCALLER
521 * AST_FEATURE_FLAG_BYBOTH
523 int parkedcallreparking;
525 * \brief Enable DTMF based hangup on a bridge when pickup up parked calls.
529 * AST_FEATURE_FLAG_BYCALLEE
530 * AST_FEATURE_FLAG_BYCALLER
531 * AST_FEATURE_FLAG_BYBOTH
533 int parkedcallhangup;
535 * \brief Enable DTMF based recording on a bridge when picking up parked calls.
539 * AST_FEATURE_FLAG_BYCALLEE
540 * AST_FEATURE_FLAG_BYCALLER
541 * AST_FEATURE_FLAG_BYBOTH
543 int parkedcallrecording;
545 /*! TRUE if findslot is set to next */
546 unsigned int parkfindnext:1;
547 /*! TRUE if the parking lot is exclusively accessed by parkext */
548 unsigned int parkext_exclusive:1;
549 /*! Add parking hints automatically */
550 unsigned int parkaddhints:1;
551 /*! TRUE if configuration is invalid and the parking lot should not be used. */
552 unsigned int is_invalid:1;
555 /*! \brief Structure for parking lots which are put in a container. */
556 struct ast_parkinglot {
557 /*! Name of the parking lot. */
558 char name[AST_MAX_CONTEXT];
559 /*! Parking lot user configuration. */
560 struct parkinglot_cfg cfg;
562 /*! Parking space to start next park search. */
563 int next_parking_space;
565 /*! That which bears the_mark shall be deleted if parking lot empty! (Used during reloads.) */
566 unsigned int the_mark:1;
567 /*! TRUE if the parking lot is disabled. */
568 unsigned int disabled:1;
570 /*! List of active parkings in this parkinglot */
571 AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings;
574 /*! \brief The configured parking lots container. Always at least one - the default parking lot */
575 static struct ao2_container *parkinglots;
578 * \brief Default parking lot.
579 * \note Holds a parkinglot reference.
580 * \note Will not be NULL while running.
582 static struct ast_parkinglot *default_parkinglot;
584 /*! Force a config reload to reload regardless of config file timestamp. */
585 static int force_reload_load;
587 static int parkedplay = 0; /*!< Who to play courtesytone to when someone picks up a parked call. */
588 static int parkeddynamic = 0; /*!< Enable creation of parkinglots dynamically */
589 static char courtesytone[256]; /*!< Courtesy tone used to pickup parked calls and on-touch-record */
590 static char xfersound[256]; /*!< Call transfer sound */
591 static char xferfailsound[256]; /*!< Call transfer failure sound */
592 static char pickupsound[256]; /*!< Pickup sound */
593 static char pickupfailsound[256]; /*!< Pickup failure sound */
596 * \brief Context for parking dialback to parker.
597 * \note The need for the context is a KLUDGE.
599 * \todo Might be able to eliminate the parking_con_dial context
600 * kludge by running app_dial directly in its own thread to
603 static char parking_con_dial[] = "park-dial";
605 /*! Ensure that features.conf reloads on one thread at a time. */
606 AST_MUTEX_DEFINE_STATIC(features_reload_lock);
610 static int transferdigittimeout;
611 static int featuredigittimeout;
612 static int comebacktoorigin = 1;
614 static int atxfernoanswertimeout;
615 static unsigned int atxferdropcall;
616 static unsigned int atxferloopdelay;
617 static unsigned int atxfercallbackretries;
619 static char *registrar = "features"; /*!< Registrar for operations */
621 /*! PARK_APP_NAME application arguments */
622 AST_DEFINE_APP_ARGS_TYPE(park_app_args,
623 AST_APP_ARG(timeout); /*!< Time in ms to remain in the parking lot. */
624 AST_APP_ARG(return_con); /*!< Context to return parked call if timeout. */
625 AST_APP_ARG(return_ext); /*!< Exten to return parked call if timeout. */
626 AST_APP_ARG(return_pri); /*!< Priority to return parked call if timeout. */
627 AST_APP_ARG(options); /*!< Parking option flags. */
628 AST_APP_ARG(pl_name); /*!< Parking lot name to use if present. */
629 AST_APP_ARG(dummy); /*!< Place to put any remaining args string. */
632 /* module and CLI command definitions */
633 static char *parkcall = PARK_APP_NAME;
635 static struct ast_app *monitor_app = NULL;
636 static int monitor_ok = 1;
638 static struct ast_app *mixmonitor_app = NULL;
639 static int mixmonitor_ok = 1;
641 static struct ast_app *stopmixmonitor_app = NULL;
642 static int stopmixmonitor_ok = 1;
644 static pthread_t parking_thread;
645 struct ast_dial_features {
646 struct ast_flags features_caller;
647 struct ast_flags features_callee;
651 #if defined(ATXFER_NULL_TECH)
654 * \brief Set the channel technology to the kill technology.
656 * \param chan Channel to change technology.
660 static void set_kill_chan_tech(struct ast_channel *chan)
664 ast_channel_lock(chan);
666 /* Hangup the channel's physical side */
667 if (chan->tech->hangup) {
668 chan->tech->hangup(chan);
670 if (chan->tech_pvt) {
671 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n",
673 ast_free(chan->tech_pvt);
674 chan->tech_pvt = NULL;
677 /* Install the kill technology and wake up anyone waiting on it. */
678 chan->tech = &ast_kill_tech;
679 for (idx = 0; idx < AST_MAX_FDS; ++idx) {
683 case AST_GENERATOR_FD:
684 /* Don't clear these fd's. */
687 ast_channel_set_fd(chan, idx, -1);
691 ast_queue_frame(chan, &ast_null_frame);
693 ast_channel_unlock(chan);
695 #endif /* defined(ATXFER_NULL_TECH) */
697 #if defined(ATXFER_NULL_TECH)
700 * \brief Set the channel name to something unique.
702 * \param chan Channel to change name.
706 static void set_new_chan_name(struct ast_channel *chan)
708 static int seq_num_last;
714 /* Create the new channel name string. */
715 ast_channel_lock(chan);
716 seq_num = ast_atomic_fetchadd_int(&seq_num_last, +1);
717 len = snprintf(dummy, sizeof(dummy), "%s<XFER_%x>", chan->name, seq_num) + 1;
718 chan_name = alloca(len);
719 snprintf(chan_name, len, "%s<XFER_%x>", chan->name, seq_num);
720 ast_channel_unlock(chan);
722 ast_change_name(chan, chan_name);
724 #endif /* defined(ATXFER_NULL_TECH) */
726 static void *dial_features_duplicate(void *data)
728 struct ast_dial_features *df = data, *df_copy;
730 if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
734 memcpy(df_copy, df, sizeof(*df));
739 static void dial_features_destroy(void *data)
741 struct ast_dial_features *df = data;
747 static const struct ast_datastore_info dial_features_info = {
748 .type = "dial-features",
749 .destroy = dial_features_destroy,
750 .duplicate = dial_features_duplicate,
753 /* Forward declarations */
754 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
755 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
756 static struct ast_parkinglot *find_parkinglot(const char *name);
757 static struct ast_parkinglot *create_parkinglot(const char *name);
758 static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
759 static int parkinglot_activate(struct ast_parkinglot *parkinglot);
760 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile);
764 * \brief Get the parking extension if it exists.
766 * \param exten_str Parking extension to see if exists.
767 * \param chan Channel to autoservice while looking for exten. (Could be NULL)
768 * \param context Parking context to look in for exten.
770 * \retval exten on success.
771 * \retval NULL on error or exten does not exist.
773 static struct ast_exten *get_parking_exten(const char *exten_str, struct ast_channel *chan, const char *context)
775 struct ast_exten *exten;
776 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
777 const char *app_at_exten;
779 exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL,
785 app_at_exten = ast_get_extension_app(exten);
786 if (!app_at_exten || strcasecmp(PARK_APP_NAME, app_at_exten)) {
793 int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const char *context)
795 return get_parking_exten(exten_str, chan, context) ? 1 : 0;
798 const char *ast_pickup_ext(void)
803 struct ast_bridge_thread_obj
805 struct ast_bridge_config bconfig;
806 struct ast_channel *chan;
807 struct ast_channel *peer;
808 unsigned int return_to_pbx:1;
811 static int parkinglot_hash_cb(const void *obj, const int flags)
813 const struct ast_parkinglot *parkinglot = obj;
815 return ast_str_case_hash(parkinglot->name);
818 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
820 struct ast_parkinglot *parkinglot = obj;
821 struct ast_parkinglot *parkinglot2 = arg;
823 return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
827 * \brief store context, extension and priority
828 * \param chan, context, ext, pri
830 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
832 ast_copy_string(chan->context, context, sizeof(chan->context));
833 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
834 chan->priority = pri;
838 * \brief Check goto on transfer
841 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
842 * When found make sure the types are compatible. Check if channel is valid
843 * if so start the new channel else hangup the call.
845 static void check_goto_on_transfer(struct ast_channel *chan)
847 struct ast_channel *xferchan;
849 char *goto_on_transfer;
852 ast_channel_lock(chan);
853 val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
854 if (ast_strlen_zero(val)) {
855 ast_channel_unlock(chan);
858 goto_on_transfer = ast_strdupa(val);
859 ast_channel_unlock(chan);
861 ast_debug(1, "Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, chan->name);
863 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0,
869 /* Make formats okay */
870 xferchan->readformat = chan->readformat;
871 xferchan->writeformat = chan->writeformat;
873 if (ast_channel_masquerade(xferchan, chan)) {
874 /* Failed to setup masquerade. */
875 ast_hangup(xferchan);
879 for (x = goto_on_transfer; *x; ++x) {
884 ast_parseable_goto(xferchan, goto_on_transfer);
885 xferchan->_state = AST_STATE_UP;
886 ast_clear_flag(xferchan, AST_FLAGS_ALL);
887 ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
889 if (ast_do_masquerade(xferchan) || ast_pbx_start(xferchan)) {
890 /* Failed to do masquerade or could not start PBX. */
891 ast_hangup(xferchan);
895 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
896 const char *caller_name, struct ast_channel *requestor,
897 struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data,
898 int timeout, int *outstate, const char *language);
901 * \brief bridge the call
902 * \param data thread bridge.
904 * Set Last Data for respective channels, reset cdr for channels
905 * bridge call, check if we're going back to dialplan
906 * if not hangup both legs of the call
908 static void *bridge_call_thread(void *data)
910 struct ast_bridge_thread_obj *tobj = data;
913 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
914 tobj->chan->data = tobj->peer->name;
915 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
916 tobj->peer->data = tobj->chan->name;
918 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
920 if (tobj->return_to_pbx) {
921 if (!ast_check_hangup(tobj->peer)) {
922 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
923 res = ast_pbx_start(tobj->peer);
924 if (res != AST_PBX_SUCCESS)
925 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
927 ast_hangup(tobj->peer);
928 if (!ast_check_hangup(tobj->chan)) {
929 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
930 res = ast_pbx_start(tobj->chan);
931 if (res != AST_PBX_SUCCESS)
932 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
934 ast_hangup(tobj->chan);
936 ast_hangup(tobj->chan);
937 ast_hangup(tobj->peer);
946 * \brief create thread for the parked call
949 * Create thread and attributes, call bridge_call_thread
951 static void bridge_call_thread_launch(void *data)
955 struct sched_param sched;
957 pthread_attr_init(&attr);
958 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
959 ast_pthread_create(&thread, &attr, bridge_call_thread, data);
960 pthread_attr_destroy(&attr);
961 memset(&sched, 0, sizeof(sched));
962 pthread_setschedparam(thread, SCHED_RR, &sched);
966 * \brief Announce call parking by ADSI
968 * \param parkingexten .
969 * Create message to show for ADSI, display message.
970 * \retval 0 on success.
971 * \retval -1 on failure.
973 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
976 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
978 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
980 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
982 res = ast_adsi_load_session(chan, NULL, 0, 1);
985 return ast_adsi_print(chan, message, justify, 1);
989 * \brief Find parking lot name from channel
990 * \note Channel needs to be locked while the returned string is in use.
992 static const char *findparkinglotname(struct ast_channel *chan)
996 /* The channel variable overrides everything */
997 name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
998 if (!name && !ast_strlen_zero(chan->parkinglot)) {
999 /* Use the channel's parking lot. */
1000 name = chan->parkinglot;
1005 /*! \brief Notify metermaids that we've changed an extension */
1006 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
1008 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
1009 exten, context, ast_devstate2str(state));
1011 ast_devstate_changed(state, "park:%s@%s", exten, context);
1014 /*! \brief metermaids callback from devicestate.c */
1015 static enum ast_device_state metermaidstate(const char *data)
1020 context = ast_strdupa(data);
1022 exten = strsep(&context, "@");
1024 return AST_DEVICE_INVALID;
1026 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
1028 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
1029 return AST_DEVICE_NOT_INUSE;
1031 return AST_DEVICE_INUSE;
1034 /*! Options to pass to park_call_full */
1035 enum ast_park_call_options {
1036 /*! Provide ringing to the parked caller instead of music on hold */
1037 AST_PARK_OPT_RINGING = (1 << 0),
1038 /*! Randomly choose a parking spot for the caller instead of choosing
1039 * the first one that is available. */
1040 AST_PARK_OPT_RANDOMIZE = (1 << 1),
1041 /*! Do not announce the parking number */
1042 AST_PARK_OPT_SILENCE = (1 << 2),
1045 /*! Optional additional parking options when parking a call. */
1046 struct ast_park_call_args {
1047 /*! How long to wait in the parking lot before the call gets sent back
1048 * to the specified return extension (or a best guess at where it came
1049 * from if not explicitly specified). */
1051 /*! An output parameter to store the parking space where the parked caller
1054 const char *orig_chan_name;
1055 const char *return_con;
1056 const char *return_ext;
1059 /*! Parked user that has already obtained a parking space */
1060 struct parkeduser *pu;
1061 /*! \brief Parkinglot to be parked in */
1062 struct ast_parkinglot *parkinglot;
1067 * \brief Create a dynamic parking lot.
1069 * \param name Dynamic parking lot name to create.
1070 * \param chan Channel to get dynamic parking lot parameters.
1072 * \retval parkinglot on success.
1073 * \retval NULL on error.
1075 static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
1077 const char *dyn_context;
1078 const char *dyn_exten;
1079 const char *dyn_range;
1080 const char *template_name;
1081 struct ast_parkinglot *template_parkinglot = NULL;
1082 struct ast_parkinglot *parkinglot;
1086 ast_channel_lock(chan);
1087 template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
1088 dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
1089 dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
1090 dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
1091 ast_channel_unlock(chan);
1093 if (!ast_strlen_zero(template_name)) {
1094 template_parkinglot = find_parkinglot(template_name);
1095 if (!template_parkinglot) {
1096 ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
1098 } else if (template_parkinglot->cfg.is_invalid) {
1099 ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
1101 parkinglot_unref(template_parkinglot);
1102 template_parkinglot = NULL;
1105 if (!template_parkinglot) {
1106 template_parkinglot = parkinglot_addref(default_parkinglot);
1107 ast_debug(1, "Using default parking lot for template\n");
1110 parkinglot = copy_parkinglot(name, template_parkinglot);
1112 ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
1114 /* Configure the dynamic parking lot. */
1115 if (!ast_strlen_zero(dyn_context)) {
1116 ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
1117 sizeof(parkinglot->cfg.parking_con));
1119 if (!ast_strlen_zero(dyn_exten)) {
1120 ast_copy_string(parkinglot->cfg.parkext, dyn_exten,
1121 sizeof(parkinglot->cfg.parkext));
1123 if (!ast_strlen_zero(dyn_range)) {
1124 if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
1125 ast_log(LOG_WARNING,
1126 "Format for parking positions is a-b, where a and b are numbers\n");
1127 } else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
1128 ast_log(LOG_WARNING,
1129 "Format for parking positions is a-b, where a <= b\n");
1131 parkinglot->cfg.parking_start = dyn_start;
1132 parkinglot->cfg.parking_stop = dyn_end;
1137 * Sanity check for dynamic parking lot configuration.
1139 * XXX It may be desirable to instead check if the dynamic
1140 * parking lot overlaps any existing lots like what is done for
1143 if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
1144 if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)
1145 && parkinglot->cfg.parkext_exclusive) {
1146 ast_log(LOG_WARNING,
1147 "Parking lot '%s' conflicts with template parking lot '%s'!\n"
1148 "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
1149 parkinglot->name, template_parkinglot->name);
1151 if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
1152 && parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
1153 || (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
1154 && parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
1155 || (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
1156 && template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
1157 ast_log(LOG_WARNING,
1158 "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
1159 "Change PARKINGDYNPOS.\n",
1160 parkinglot->name, template_parkinglot->name);
1164 parkinglot_activate(parkinglot);
1165 ao2_link(parkinglots, parkinglot);
1167 parkinglot_unref(template_parkinglot);
1174 * \brief Reserve a parking space in a parking lot for a call being parked.
1176 * \param park_me Channel being parked.
1177 * \param parker Channel parking the call.
1178 * \param args Optional additional parking options when parking a call.
1180 * \return Parked call descriptor or NULL if failed.
1181 * \note The parking lot list is locked if successful.
1183 static struct parkeduser *park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
1185 struct parkeduser *pu;
1187 int parking_space = -1;
1188 const char *parkinglotname;
1189 const char *parkingexten;
1190 struct parkeduser *cur;
1191 struct ast_parkinglot *parkinglot = NULL;
1193 if (args->parkinglot) {
1194 parkinglot = parkinglot_addref(args->parkinglot);
1195 parkinglotname = parkinglot->name;
1198 parkinglotname = findparkinglotname(parker);
1199 } else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
1200 parkinglotname = findparkinglotname(park_me);
1202 if (!ast_strlen_zero(parkinglotname)) {
1203 parkinglot = find_parkinglot(parkinglotname);
1205 /* Parking lot is not specified, so use the default parking lot. */
1206 ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
1207 parkinglot = parkinglot_addref(default_parkinglot);
1211 /* Dynamically create parkinglot */
1212 if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
1213 parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
1217 ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", park_me->name);
1221 ast_debug(1, "Parking lot: %s\n", parkinglot->name);
1222 if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
1223 ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
1225 parkinglot_unref(parkinglot);
1229 /* Allocate memory for parking data */
1230 if (!(pu = ast_calloc(1, sizeof(*pu)))) {
1231 parkinglot_unref(parkinglot);
1235 /* Lock parking list */
1236 AST_LIST_LOCK(&parkinglot->parkings);
1238 /* Check for channel variable PARKINGEXTEN */
1239 parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
1240 if (!ast_strlen_zero(parkingexten)) {
1242 * \note The API forces us to specify a numeric parking slot, even
1243 * though the architecture would tend to support non-numeric extensions
1244 * (as are possible with SIP, for example). Hence, we enforce that
1245 * limitation here. If extout was not numeric, we could permit
1246 * arbitrary non-numeric extensions.
1248 if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
1249 ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
1251 AST_LIST_UNLOCK(&parkinglot->parkings);
1252 parkinglot_unref(parkinglot);
1257 if (parking_space < parkinglot->cfg.parking_start
1258 || parkinglot->cfg.parking_stop < parking_space) {
1260 * Cannot allow park because parking lots are not setup for
1261 * spaces outside of the lot. (Things like dialplan hints don't
1262 * exist for outside lot space.)
1264 ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
1265 parking_space, parkinglot->name, parkinglot->cfg.parking_start,
1266 parkinglot->cfg.parking_stop);
1267 AST_LIST_UNLOCK(&parkinglot->parkings);
1268 parkinglot_unref(parkinglot);
1273 /* Check if requested parking space is in use. */
1274 AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1275 if (cur->parkingnum == parking_space) {
1276 ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
1277 parking_space, parkinglot->name);
1278 AST_LIST_UNLOCK(&parkinglot->parkings);
1279 parkinglot_unref(parkinglot);
1285 /* PARKINGEXTEN is empty, so find a usable extension in the lot to park the call */
1286 int start; /* The first slot we look in the parkinglot. It can be randomized. */
1287 int start_checked = 0; /* flag raised once the first slot is checked */
1289 /* If using randomize mode, set start to random position on parking range */
1290 if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
1291 start = ast_random() % (parkinglot->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
1292 start += parkinglot->cfg.parking_start;
1293 } else if (parkinglot->cfg.parkfindnext
1294 && parkinglot->cfg.parking_start <= parkinglot->next_parking_space
1295 && parkinglot->next_parking_space <= parkinglot->cfg.parking_stop) {
1296 /* Start looking with the next parking space in the lot. */
1297 start = parkinglot->next_parking_space;
1299 /* Otherwise, just set it to the start position. */
1300 start = parkinglot->cfg.parking_start;
1303 /* free parking extension linear search: O(n^2) */
1304 for (i = start; ; i++) {
1305 /* If we are past the end, wrap around to the first parking slot*/
1306 if (i == parkinglot->cfg.parking_stop + 1) {
1307 i = parkinglot->cfg.parking_start;
1311 /* At this point, if start_checked, we've exhausted all the possible slots. */
1312 if (start_checked) {
1319 /* Search the list of parked calls already in use for i. If we find it, it's in use. */
1320 AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1321 if (cur->parkingnum == i) {
1326 /* We found a parking space. */
1331 if (parking_space == -1) {
1332 /* We did not find a parking space. Lot is full. */
1333 ast_log(LOG_WARNING, "No more parking spaces in %s\n", parkinglot->name);
1334 AST_LIST_UNLOCK(&parkinglot->parkings);
1335 parkinglot_unref(parkinglot);
1341 /* Prepare for next parking space search. */
1342 parkinglot->next_parking_space = parking_space + 1;
1344 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1345 pu->notquiteyet = 1;
1346 pu->parkingnum = parking_space;
1347 pu->parkinglot = parkinglot;
1348 AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
1354 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
1356 struct parkeduser *pu = args->pu;
1357 const char *event_from;
1358 char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
1361 args->pu = pu = park_space_reserve(chan, peer, args);
1367 chan->appl = "Parked Call";
1372 /* Put the parked channel on hold if we have two different channels */
1374 if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1375 pu->hold_method = AST_CONTROL_RINGING;
1376 ast_indicate(pu->chan, AST_CONTROL_RINGING);
1378 pu->hold_method = AST_CONTROL_HOLD;
1379 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
1380 S_OR(pu->parkinglot->cfg.mohclass, NULL),
1381 !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1385 pu->start = ast_tvnow();
1386 pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->cfg.parkingtime;
1388 *(args->extout) = pu->parkingnum;
1392 * This is so ugly that it hurts, but implementing
1393 * get_base_channel() on local channels could have ugly side
1394 * effects. We could have
1395 * transferer<->local,1<->local,2<->parking and we need the
1396 * callback name to be that of transferer. Since local,1/2 have
1397 * the same name we can be tricky and just grab the bridged
1398 * channel from the other side of the local.
1400 if (!strcasecmp(peer->tech->type, "Local")) {
1401 struct ast_channel *tmpchan, *base_peer;
1402 char other_side[AST_CHANNEL_NAME];
1405 ast_copy_string(other_side, S_OR(args->orig_chan_name, peer->name), sizeof(other_side));
1406 if ((c = strrchr(other_side, ';'))) {
1409 if ((tmpchan = ast_channel_get_by_name(other_side))) {
1410 ast_channel_lock(tmpchan);
1411 if ((base_peer = ast_bridged_channel(tmpchan))) {
1412 ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
1414 ast_channel_unlock(tmpchan);
1415 tmpchan = ast_channel_unref(tmpchan);
1418 ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
1423 * Remember what had been dialed, so that if the parking
1424 * expires, we try to come back to the same place
1426 pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
1429 * If extension has options specified, they override all other
1430 * possibilities such as the returntoorigin flag and transferred
1431 * context. Information on extension options is lost here, so
1434 ast_copy_string(pu->context,
1435 S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)),
1436 sizeof(pu->context));
1437 ast_copy_string(pu->exten,
1438 S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)),
1440 pu->priority = args->return_pri ? args->return_pri :
1441 (chan->macropriority ? chan->macropriority : chan->priority);
1444 * If parking a channel directly, don't quite yet get parking
1445 * running on it. All parking lot entries are put into the
1446 * parking lot with notquiteyet on.
1449 pu->notquiteyet = 0;
1452 /* Wake up the (presumably select()ing) thread */
1453 pthread_kill(parking_thread, SIGURG);
1454 ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
1455 pu->chan->name, pu->parkingnum, pu->parkinglot->name,
1456 pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
1458 ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
1461 event_from = peer->name;
1463 event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
1466 ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
1469 "Parkinglot: %s\r\n"
1472 "CallerIDNum: %s\r\n"
1473 "CallerIDName: %s\r\n"
1474 "ConnectedLineNum: %s\r\n"
1475 "ConnectedLineName: %s\r\n"
1477 pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
1478 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
1479 S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
1480 S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
1481 S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
1482 S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
1486 if (peer && adsipark && ast_adsi_available(peer)) {
1487 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
1488 ast_adsi_unload_session(peer);
1491 snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
1492 pu->parkinglot->name);
1493 if (ast_add_extension(pu->parkinglot->cfg.parking_con, 1, pu->parkingexten, 1,
1494 NULL, NULL, parkedcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
1495 ast_log(LOG_ERROR, "Could not create parked call exten: %s@%s\n",
1496 pu->parkingexten, pu->parkinglot->cfg.parking_con);
1498 notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con, AST_DEVICE_INUSE);
1501 AST_LIST_UNLOCK(&pu->parkinglot->parkings);
1503 /* Only say number if it's a number and the channel hasn't been masqueraded away */
1504 if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE)
1505 && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
1507 * If a channel is masqueraded into peer while playing back the
1508 * parking space number do not continue playing it back. This
1509 * is the case if an attended transfer occurs.
1511 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1512 /* Tell the peer channel the number of the parking space */
1513 ast_say_digits(peer, pu->parkingnum, "", peer->language);
1514 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1516 if (peer == chan) { /* pu->notquiteyet = 1 */
1517 /* Wake up parking thread if we're really done */
1518 pu->hold_method = AST_CONTROL_HOLD;
1519 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
1520 S_OR(pu->parkinglot->cfg.mohclass, NULL),
1521 !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1522 pu->notquiteyet = 0;
1523 pthread_kill(parking_thread, SIGURG);
1528 /*! \brief Park a call */
1529 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, const char *parkexten, int *extout)
1531 struct ast_park_call_args args = {
1536 return park_call_full(chan, peer, &args);
1540 * \param rchan the real channel to be parked
1541 * \param peer the channel to have the parking read to.
1542 * \param timeout is a timeout in milliseconds
1543 * \param extout is a parameter to an int that will hold the parked location, or NULL if you want.
1544 * \param play_announcement TRUE if to play which parking space call parked in to peer.
1545 * \param args Optional additional parking options when parking a call.
1547 * \retval 0 on success.
1548 * \retval -1 on failure.
1550 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, struct ast_park_call_args *args)
1552 struct ast_channel *chan;
1553 struct ast_park_call_args park_args = {0,};
1557 args->timeout = timeout;
1558 args->extout = extout;
1561 /* Make a new, channel that we'll use to masquerade in the real one */
1562 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten,
1563 rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s", rchan->name);
1565 ast_log(LOG_WARNING, "Unable to create parked channel\n");
1566 if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1567 if (peer == rchan) {
1568 /* Only have one channel to worry about. */
1569 ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1571 /* Have two different channels to worry about. */
1572 play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1578 args->pu = park_space_reserve(rchan, peer, args);
1580 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
1582 if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1583 if (peer == rchan) {
1584 /* Only have one channel to worry about. */
1585 ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1587 /* Have two different channels to worry about. */
1588 play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1594 /* Make formats okay */
1595 chan->readformat = rchan->readformat;
1596 chan->writeformat = rchan->writeformat;
1597 ast_channel_masquerade(chan, rchan);
1599 /* Setup the extensions and such */
1600 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
1602 /* Setup the macro extension and such */
1603 ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
1604 ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
1605 chan->macropriority = rchan->macropriority;
1607 /* Manually do the masquerade to make sure it is complete. */
1608 ast_do_masquerade(chan);
1610 if (peer == rchan) {
1614 if (peer && (!play_announcement && args == &park_args)) {
1615 args->orig_chan_name = ast_strdupa(peer->name);
1618 /* parking space reserved, return code check unnecessary */
1619 park_call_full(chan, peer, args);
1624 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
1626 return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
1630 * \brief Park call via masqueraded channel and announce parking spot on peer channel.
1632 * \param rchan the real channel to be parked
1633 * \param peer the channel to have the parking read to.
1634 * \param args Optional additional parking options when parking a call.
1636 * \retval 0 on success.
1637 * \retval -1 on failure.
1639 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
1641 return masq_park_call(rchan, peer, 0, NULL, 1, args);
1644 static int finishup(struct ast_channel *chan)
1646 ast_indicate(chan, AST_CONTROL_UNHOLD);
1648 return ast_autoservice_stop(chan);
1653 * \brief Builtin transfer park call helper.
1655 * \param park_me Channel to be parked.
1656 * \param parker Channel parking the call.
1657 * \param park_exten Parking lot dialplan access ramp extension.
1659 * \note Assumes park_me is on hold and in autoservice.
1661 * \retval -1 on successful park.
1662 * \retval -1 on park_me hangup.
1663 * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
1665 static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
1668 const char *app_data;
1669 const char *pl_name;
1670 struct ast_park_call_args args = { 0, };
1671 struct park_app_args app_args;
1674 app_data = ast_get_extension_app_data(park_exten);
1678 parse = ast_strdupa(app_data);
1679 AST_STANDARD_APP_ARGS(app_args, parse);
1681 /* Find the parking lot */
1682 if (!ast_strlen_zero(app_args.pl_name)) {
1683 pl_name = app_args.pl_name;
1685 pl_name = findparkinglotname(parker);
1687 if (ast_strlen_zero(pl_name)) {
1688 /* Parking lot is not specified, so use the default parking lot. */
1689 args.parkinglot = parkinglot_addref(default_parkinglot);
1691 args.parkinglot = find_parkinglot(pl_name);
1692 if (!args.parkinglot && parkeddynamic) {
1693 args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
1697 if (args.parkinglot) {
1699 res = finishup(park_me);
1701 /* park_me hungup on us. */
1702 parkinglot_unref(args.parkinglot);
1705 res = masq_park_call_announce(park_me, parker, &args);
1706 parkinglot_unref(args.parkinglot);
1708 /* Parking failed because parking lot does not exist. */
1709 if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
1710 ast_stream_and_wait(parker, "pbx-parkingfailed", "");
1716 return res ? AST_FEATURE_RETURN_SUCCESS : -1;
1720 * \brief set caller and callee according to the direction
1721 * \param caller, callee, peer, chan, sense
1723 * Detect who triggered feature and set callee/caller variables accordingly
1725 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
1726 struct ast_channel *peer, struct ast_channel *chan, int sense)
1728 if (sense == FEATURE_SENSE_PEER) {
1738 * \brief support routing for one touch call parking
1739 * \param chan channel parking call
1740 * \param peer channel to be parked
1741 * \param config unsed
1742 * \param code unused
1743 * \param sense feature options
1744 * \param data unused
1746 * \retval -1 on successful park.
1747 * \retval -1 on chan hangup.
1748 * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
1750 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1752 struct ast_channel *parker;
1753 struct ast_channel *parkee;
1756 * We used to set chan's exten and priority to "s" and 1 here,
1757 * but this generates (in some cases) an invalid extension, and
1758 * if "s" exists, could errantly cause execution of extensions
1759 * you don't expect. It makes more sense to let nature take its
1760 * course when chan finishes, and let the pbx do its thing and
1761 * hang up when the park is over.
1764 /* Answer if call is not up */
1765 if (chan->_state != AST_STATE_UP) {
1767 * XXX Why are we doing this? Both of the channels should be up
1768 * since you cannot do DTMF features unless you are bridged.
1770 if (ast_answer(chan)) {
1774 /* Sleep to allow VoIP streams to settle down */
1775 if (ast_safe_sleep(chan, 1000)) {
1780 /* one direction used to call park_call.... */
1781 set_peers(&parker, &parkee, peer, chan, sense);
1782 return masq_park_call_announce(parkee, parker, NULL)
1783 ? AST_FEATURE_RETURN_SUCCESS : -1;
1788 * \brief Play file to specified channel.
1790 * \param play_to Channel to play audiofile to.
1791 * \param other Channel to put in autoservice while playing file.
1792 * \param msg Descriptive name of message type being played.
1793 * \param audiofile Audio file to play.
1795 * \retval 0 on success.
1796 * \retval -1 on error. (Couldn't play file, a channel hung up,...)
1798 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
1800 /* Put other channel in autoservice. */
1801 if (ast_autoservice_start(other)) {
1804 ast_autoservice_ignore(other, AST_FRAME_DTMF_BEGIN);
1805 ast_autoservice_ignore(other, AST_FRAME_DTMF_END);
1806 if (ast_stream_and_wait(play_to, audiofile, "")) {
1807 ast_log(LOG_WARNING, "Failed to play %s '%s'!\n", msg, audiofile);
1808 ast_autoservice_stop(other);
1811 if (ast_autoservice_stop(other)) {
1819 * \brief Play file to specified channels.
1821 * \param left Channel on left to play file.
1822 * \param right Channel on right to play file.
1823 * \param which Play file on indicated channels: which < 0 play left, which == 0 play both, which > 0 play right
1824 * \param msg Descriptive name of message type being played.
1825 * \param audiofile Audio file to play to channels.
1827 * \note Plays file to the indicated channels in turn so please
1828 * don't use this for very long messages.
1830 * \retval 0 on success.
1831 * \retval -1 on error. (Couldn't play file, channel hung up,...)
1833 static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
1835 /* First play the file to the left channel if requested. */
1836 if (which <= 0 && play_message_on_chan(left, right, msg, audiofile)) {
1840 /* Then play the file to the right channel if requested. */
1841 if (which >= 0 && play_message_on_chan(right, left, msg, audiofile)) {
1849 * \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
1850 * other channel during the message, so please don't use this for very long messages
1852 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
1854 return play_message_to_chans(caller_chan, callee_chan, 0, "automon message",
1859 * \brief Monitor a channel by DTMF
1860 * \param chan channel requesting monitor
1861 * \param peer channel to be monitored
1864 * \param sense feature options
1867 * Check monitor app enabled, setup channels, both caller/callee chans not null
1868 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
1869 * \retval AST_FEATURE_RETURN_SUCCESS on success.
1870 * \retval -1 on error.
1872 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1874 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1877 struct ast_channel *caller_chan, *callee_chan;
1878 const char *automon_message_start = NULL;
1879 const char *automon_message_stop = NULL;
1882 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1886 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
1888 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1892 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1893 if (caller_chan) { /* Find extra messages */
1894 automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
1895 automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
1898 if (!ast_strlen_zero(courtesytone)) { /* Play courtesy tone if configured */
1899 if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
1904 if (callee_chan->monitor) {
1905 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
1906 if (!ast_strlen_zero(automon_message_stop)) {
1907 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
1909 callee_chan->monitor->stop(callee_chan, 1);
1910 return AST_FEATURE_RETURN_SUCCESS;
1913 if (caller_chan && callee_chan) {
1914 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
1915 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
1916 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
1919 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
1922 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
1924 if (!touch_monitor_prefix)
1925 touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
1927 if (touch_monitor) {
1928 len = strlen(touch_monitor) + 50;
1930 touch_filename = alloca(len);
1931 snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
1932 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1934 caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
1935 caller_chan->caller.id.number.str, caller_chan->name));
1936 callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
1937 callee_chan->caller.id.number.str, callee_chan->name));
1938 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1940 touch_filename = alloca(len);
1941 snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
1942 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1945 for(x = 0; x < strlen(args); x++) {
1950 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
1952 pbx_exec(callee_chan, monitor_app, args);
1953 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1954 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1956 if (!ast_strlen_zero(automon_message_start)) { /* Play start message for both channels */
1957 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
1960 return AST_FEATURE_RETURN_SUCCESS;
1963 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
1967 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1969 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1972 struct ast_channel *caller_chan, *callee_chan;
1973 const char *mixmonitor_spy_type = "MixMonitor";
1976 if (!mixmonitor_ok) {
1977 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1981 if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
1983 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1987 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1989 if (!ast_strlen_zero(courtesytone)) {
1990 if (ast_autoservice_start(callee_chan))
1992 ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
1993 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
1994 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1995 ast_autoservice_stop(callee_chan);
1998 if (ast_autoservice_stop(callee_chan))
2002 ast_channel_lock(callee_chan);
2003 count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2004 ast_channel_unlock(callee_chan);
2006 /* This means a mixmonitor is attached to the channel, running or not is unknown. */
2009 ast_verb(3, "User hit '%s' to stop recording call.\n", code);
2011 /* Make sure they are running */
2012 ast_channel_lock(callee_chan);
2013 count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2014 ast_channel_unlock(callee_chan);
2016 if (!stopmixmonitor_ok) {
2017 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2020 if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
2021 stopmixmonitor_ok = 0;
2022 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2025 pbx_exec(callee_chan, stopmixmonitor_app, "");
2026 return AST_FEATURE_RETURN_SUCCESS;
2030 ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
2033 if (caller_chan && callee_chan) {
2034 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
2035 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
2038 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
2041 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
2043 if (touch_monitor) {
2044 len = strlen(touch_monitor) + 50;
2046 touch_filename = alloca(len);
2047 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
2048 snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
2050 caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
2051 caller_chan->caller.id.number.str, caller_chan->name));
2052 callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
2053 callee_chan->caller.id.number.str, callee_chan->name));
2054 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2056 touch_filename = alloca(len);
2057 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
2058 snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
2061 for( x = 0; x < strlen(args); x++) {
2066 ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
2068 pbx_exec(callee_chan, mixmonitor_app, args);
2069 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2070 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2071 return AST_FEATURE_RETURN_SUCCESS;
2075 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
2080 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2082 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
2083 return AST_FEATURE_RETURN_HANGUP;
2087 * \brief Find the context for the transfer
2091 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
2092 * \return a context string
2094 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
2096 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
2097 if (ast_strlen_zero(s)) {
2098 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
2100 if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
2101 s = transferer->macrocontext;
2103 if (ast_strlen_zero(s)) {
2104 s = transferer->context;
2110 * \brief Blind transfer user to another extension
2111 * \param chan channel to be transfered
2112 * \param peer channel initiated blind transfer
2116 * \param sense feature options
2118 * Place chan on hold, check if transferred to parkinglot extension,
2119 * otherwise check extension exists and transfer caller.
2120 * \retval AST_FEATURE_RETURN_SUCCESS.
2121 * \retval -1 on failure.
2123 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2125 struct ast_channel *transferer;
2126 struct ast_channel *transferee;
2127 struct ast_exten *park_exten;
2128 const char *transferer_real_context;
2129 char xferto[256] = "";
2132 ast_debug(1, "Executing Blind Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2133 set_peers(&transferer, &transferee, peer, chan, sense);
2134 transferer_real_context = real_ctx(transferer, transferee);
2136 /* Start autoservice on transferee while we talk to the transferer */
2137 ast_autoservice_start(transferee);
2138 ast_indicate(transferee, AST_CONTROL_HOLD);
2141 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2143 finishup(transferee);
2144 return -1; /* error ? */
2146 if (res > 0) { /* If they've typed a digit already, handle it */
2147 xferto[0] = (char) res;
2150 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2151 if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2152 finishup(transferee);
2157 ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2158 xferto, transferer_real_context);
2160 /* Does anyone care about this case? */
2161 ast_log(LOG_WARNING, "No digits dialed.\n");
2163 ast_stream_and_wait(transferer, "pbx-invalid", "");
2164 finishup(transferee);
2165 return AST_FEATURE_RETURN_SUCCESS;
2168 park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2170 /* We are transfering the transferee to a parking lot. */
2171 return xfer_park_call_helper(transferee, transferer, park_exten);
2174 /* Do blind transfer. */
2175 ast_verb(3, "Blind transferring %s to '%s' (context %s) priority 1\n",
2176 transferee->name, xferto, transferer_real_context);
2177 ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
2178 pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
2179 pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
2180 finishup(transferee);
2181 if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
2182 transferer->cdr = ast_cdr_alloc();
2183 if (transferer->cdr) {
2184 ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
2185 ast_cdr_start(transferer->cdr);
2188 if (transferer->cdr) {
2189 struct ast_cdr *swap = transferer->cdr;
2192 "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
2193 transferer->name, transferee->name, transferer->cdr->lastapp,
2194 transferer->cdr->lastdata, transferer->cdr->channel,
2195 transferer->cdr->dstchannel);
2196 ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
2197 transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel,
2198 transferee->cdr->dstchannel);
2199 ast_debug(1, "transferer_real_context=%s; xferto=%s\n",
2200 transferer_real_context, xferto);
2201 /* swap cdrs-- it will save us some time & work */
2202 transferer->cdr = transferee->cdr;
2203 transferee->cdr = swap;
2205 if (!transferee->pbx) {
2206 /* Doh! Use our handy async_goto functions */
2207 ast_debug(1, "About to ast_async_goto %s.\n", transferee->name);
2208 if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
2209 ast_log(LOG_WARNING, "Async goto failed :-(\n");
2212 /* The transferee is masqueraded and the original bridged channels can be hungup. */
2215 /* Set the transferee's new extension, since it exists, using transferer context */
2216 ast_debug(1, "About to explicit goto %s, it has a PBX.\n", transferee->name);
2217 ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
2218 set_c_e_p(transferee, transferer_real_context, xferto, 0);
2221 * Break the bridge. The transferee needs to resume executing
2222 * dialplan at the xferto location.
2224 res = AST_FEATURE_RETURN_SUCCESSBREAK;
2226 check_goto_on_transfer(transferer);
2231 * \brief make channels compatible
2234 * \retval 0 on success.
2235 * \retval -1 on failure.
2237 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
2239 if (ast_channel_make_compatible(c, newchan) < 0) {
2240 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
2241 c->name, newchan->name);
2242 ast_hangup(newchan);
2250 * \brief Builtin attended transfer failed cleanup.
2253 * \param transferee Party A in the transfer.
2254 * \param transferer Party B in the transfer.
2255 * \param connected_line Saved connected line info about party A.
2257 * \note The connected_line data is freed.
2261 static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
2263 finishup(transferee);
2266 * Restore party B connected line info about party A.
2268 * Party B was the caller to party C and is the last known mode
2271 if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
2272 ast_channel_update_connected_line(transferer, connected_line, NULL);
2274 ast_party_connected_line_free(connected_line);
2278 * \brief Attended transfer
2279 * \param chan transfered user
2280 * \param peer person transfering call
2283 * \param sense feature options
2286 * Get extension to transfer to, if you cannot generate channel (or find extension)
2287 * return to host channel. After called channel answered wait for hangup of transferer,
2288 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
2290 * \return -1 on failure
2292 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2294 struct ast_channel *transferer;/* Party B */
2295 struct ast_channel *transferee;/* Party A */
2296 struct ast_exten *park_exten;
2297 const char *transferer_real_context;
2298 char xferto[256] = "";
2301 struct ast_channel *newchan;
2302 struct ast_channel *xferchan;
2303 struct ast_bridge_thread_obj *tobj;
2304 struct ast_bridge_config bconfig;
2306 struct ast_party_connected_line connected_line;
2307 struct ast_datastore *features_datastore;
2308 struct ast_dial_features *dialfeatures = NULL;
2309 char *transferer_tech;
2310 char *transferer_name;
2311 char *transferer_name_orig;
2314 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2315 set_peers(&transferer, &transferee, peer, chan, sense);
2316 transferer_real_context = real_ctx(transferer, transferee);
2318 /* Start autoservice on transferee while we talk to the transferer */
2319 ast_autoservice_start(transferee);
2320 ast_indicate(transferee, AST_CONTROL_HOLD);
2323 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2325 finishup(transferee);
2328 if (res > 0) { /* If they've typed a digit already, handle it */
2329 xferto[0] = (char) res;
2332 /* this is specific of atxfer */
2333 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2334 if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2335 finishup(transferee);
2341 ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2342 xferto, transferer_real_context);
2344 /* Does anyone care about this case? */
2345 ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
2347 ast_stream_and_wait(transferer, "pbx-invalid", "");
2348 finishup(transferee);
2349 return AST_FEATURE_RETURN_SUCCESS;
2352 park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2354 /* We are transfering the transferee to a parking lot. */
2355 return xfer_park_call_helper(transferee, transferer, park_exten);
2358 /* Append context to dialed transfer number. */
2359 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
2361 /* If we are performing an attended transfer and we have two channels involved then
2362 copy sound file information to play upon attended transfer completion */
2364 const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2365 const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2367 if (!ast_strlen_zero(chan1_attended_sound)) {
2368 pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
2370 if (!ast_strlen_zero(chan2_attended_sound)) {
2371 pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
2375 /* Extract redial transferer information from the channel name. */
2376 transferer_name_orig = ast_strdupa(transferer->name);
2377 transferer_name = ast_strdupa(transferer_name_orig);
2378 transferer_tech = strsep(&transferer_name, "/");
2379 dash = strrchr(transferer_name, '-');
2381 /* Trim off channel name sequence/serial number. */
2385 /* Stop autoservice so we can monitor all parties involved in the transfer. */
2386 if (ast_autoservice_stop(transferee) < 0) {
2387 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2391 /* Save connected line info for party B about party A in case transfer fails. */
2392 ast_party_connected_line_init(&connected_line);
2393 ast_channel_lock(transferer);
2394 ast_party_connected_line_copy(&connected_line, &transferer->connected);
2395 ast_channel_unlock(transferer);
2396 connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2399 newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
2400 transferee, "Local", transferer->nativeformats, xferto,
2401 atxfernoanswertimeout, &outstate, transferer->language);
2402 ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2404 if (!ast_check_hangup(transferer)) {
2405 int hangup_dont = 0;
2407 /* Transferer (party B) is up */
2408 ast_debug(1, "Actually doing an attended transfer.\n");
2410 /* Start autoservice on transferee while the transferer deals with party C. */
2411 ast_autoservice_start(transferee);
2413 ast_indicate(transferer, -1);
2415 /* any reason besides user requested cancel and busy triggers the failed sound */
2417 case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
2418 case AST_CONTROL_BUSY:
2419 case AST_CONTROL_CONGESTION:
2420 if (ast_stream_and_wait(transferer, xfersound, "")) {
2421 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2425 if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2426 ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2430 atxfer_fail_cleanup(transferee, transferer, &connected_line);
2431 return AST_FEATURE_RETURN_SUCCESS;
2434 if (check_compat(transferer, newchan)) {
2435 if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2436 ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2438 atxfer_fail_cleanup(transferee, transferer, &connected_line);
2439 return AST_FEATURE_RETURN_SUCCESS;
2441 memset(&bconfig,0,sizeof(struct ast_bridge_config));
2442 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
2443 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
2445 /* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
2446 want that to happen here because we're also in another bridge already
2448 if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
2451 /* Let party B and party C talk as long as they want. */
2452 ast_bridge_call(transferer, newchan, &bconfig);
2454 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
2457 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
2458 ast_hangup(newchan);
2459 if (ast_stream_and_wait(transferer, xfersound, "")) {
2460 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2462 atxfer_fail_cleanup(transferee, transferer, &connected_line);
2463 return AST_FEATURE_RETURN_SUCCESS;
2466 /* Transferer (party B) is confirmed hung up at this point. */
2467 if (check_compat(transferee, newchan)) {
2468 finishup(transferee);
2469 ast_party_connected_line_free(&connected_line);
2473 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2474 if ((ast_autoservice_stop(transferee) < 0)
2475 || (ast_waitfordigit(transferee, 100) < 0)
2476 || (ast_waitfordigit(newchan, 100) < 0)
2477 || ast_check_hangup(transferee)
2478 || ast_check_hangup(newchan)) {
2479 ast_hangup(newchan);
2480 ast_party_connected_line_free(&connected_line);
2483 } else if (!ast_check_hangup(transferee)) {
2484 /* Transferer (party B) has hung up at this point. Doing blonde transfer. */
2485 ast_debug(1, "Actually doing a blonde transfer.\n");
2487 if (!newchan && !atxferdropcall) {
2488 /* Party C is not available, try to call party B back. */
2489 unsigned int tries = 0;
2491 if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
2492 ast_log(LOG_WARNING,
2493 "Transferer channel name: '%s' cannot be used for callback.\n",
2494 transferer_name_orig);
2495 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2496 ast_party_connected_line_free(&connected_line);
2502 /* Try to get party B back. */
2503 ast_debug(1, "We're trying to callback %s/%s\n",
2504 transferer_tech, transferer_name);
2505 newchan = feature_request_and_dial(transferer, transferer_name_orig,
2506 transferee, transferee, transferer_tech,
2507 transferee->nativeformats, transferer_name,
2508 atxfernoanswertimeout, &outstate, transferer->language);
2509 ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
2510 !!newchan, outstate);
2511 if (newchan || ast_check_hangup(transferee)) {
2516 if (atxfercallbackretries <= tries) {
2517 /* No more callback tries remaining. */
2521 if (atxferloopdelay) {
2522 /* Transfer failed, sleeping */
2523 ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
2525 ast_safe_sleep(transferee, atxferloopdelay);
2526 if (ast_check_hangup(transferee)) {
2527 ast_party_connected_line_free(&connected_line);
2532 /* Retry dialing party C. */
2533 ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
2534 newchan = feature_request_and_dial(transferer, transferer_name_orig,
2535 transferer, transferee, "Local",
2536 transferee->nativeformats, xferto,
2537 atxfernoanswertimeout, &outstate, transferer->language);
2538 ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
2539 !!newchan, outstate);
2540 if (newchan || ast_check_hangup(transferee)) {
2545 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2547 /* No party C or could not callback party B. */
2548 ast_party_connected_line_free(&connected_line);
2552 /* newchan is up, we should prepare transferee and bridge them */
2553 if (ast_check_hangup(newchan)) {
2554 ast_hangup(newchan);
2555 ast_party_connected_line_free(&connected_line);
2558 if (check_compat(transferee, newchan)) {
2559 ast_party_connected_line_free(&connected_line);
2564 * Both the transferer and transferee have hungup. If newchan
2565 * is up, hang it up as it has no one to talk to.
2567 ast_debug(1, "Everyone is hungup.\n");
2569 ast_hangup(newchan);
2571 ast_party_connected_line_free(&connected_line);
2575 /* Initiate the channel transfer of party A to party C (or recalled party B). */
2576 ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
2578 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
2580 ast_hangup(newchan);
2581 ast_party_connected_line_free(&connected_line);
2585 /* Give party A a momentary ringback tone during transfer. */
2586 xferchan->visible_indication = AST_CONTROL_RINGING;
2588 /* Make formats okay */
2589 xferchan->readformat = transferee->readformat;
2590 xferchan->writeformat = transferee->writeformat;
2592 ast_channel_masquerade(xferchan, transferee);
2593 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
2594 xferchan->_state = AST_STATE_UP;
2595 ast_clear_flag(xferchan, AST_FLAGS_ALL);
2597 /* Do the masquerade manually to make sure that is is completed. */
2598 ast_do_masquerade(xferchan);
2600 newchan->_state = AST_STATE_UP;
2601 ast_clear_flag(newchan, AST_FLAGS_ALL);
2602 tobj = ast_calloc(1, sizeof(*tobj));
2604 ast_hangup(xferchan);
2605 ast_hangup(newchan);
2606 ast_party_connected_line_free(&connected_line);
2610 ast_channel_lock(newchan);
2611 if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
2612 dialfeatures = features_datastore->data;
2614 ast_channel_unlock(newchan);
2617 /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
2618 I don't currently understand, the abilities of newchan seem to be stored on the caller side */
2619 ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2620 dialfeatures = NULL;
2623 ast_channel_lock(xferchan);
2624 if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
2625 dialfeatures = features_datastore->data;
2627 ast_channel_unlock(xferchan);
2630 ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2633 tobj->chan = newchan;
2634 tobj->peer = xferchan;
2635 tobj->bconfig = *config;
2637 if (tobj->bconfig.end_bridge_callback_data_fixup) {
2638 tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
2642 * xferchan is transferee, and newchan is the transfer target
2643 * So...in a transfer, who is the caller and who is the callee?
2645 * When the call is originally made, it is clear who is caller and callee.
2646 * When a transfer occurs, it is my humble opinion that the transferee becomes
2647 * the caller, and the transfer target is the callee.
2649 * The problem is that these macros were set with the intention of the original
2650 * caller and callee taking those roles. A transfer can totally mess things up,
2651 * to be technical. What sucks even more is that you can't effectively change
2652 * the macros in the dialplan during the call from the transferer to the transfer
2653 * target because the transferee is stuck with whatever role he originally had.
2655 * I think the answer here is just to make sure that it is well documented that
2656 * during a transfer, the transferee is the "caller" and the transfer target
2659 * This means that if party B calls party A, and party B transfers party A to
2660 * party C, then A has switched roles for the call. Now party A will have the
2661 * caller macro called on his channel instead of the callee macro.
2663 * Luckily, the method by which the party B to party C bridge is
2664 * launched above ensures that the transferee is the "chan" on
2665 * the bridge and the transfer target is the "peer," so my idea
2666 * for the roles post-transfer does not require extensive code
2670 /* Transfer party C connected line to party A */
2671 ast_channel_lock(transferer);
2673 * Due to a limitation regarding when callerID is set on a Local channel,
2674 * we use the transferer's connected line information here.
2676 ast_party_connected_line_copy(&connected_line, &transferer->connected);
2677 ast_channel_unlock(transferer);
2678 connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2679 if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
2680 ast_channel_update_connected_line(xferchan, &connected_line, NULL);
2683 /* Transfer party A connected line to party C */
2684 ast_channel_lock(xferchan);
2685 ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
2686 ast_channel_unlock(xferchan);
2687 connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2688 if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
2689 ast_channel_update_connected_line(newchan, &connected_line, NULL);
2692 if (ast_stream_and_wait(newchan, xfersound, ""))
2693 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2694 bridge_call_thread_launch(tobj);
2696 ast_party_connected_line_free(&connected_line);
2697 return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
2700 /* add atxfer and automon as undefined so you can only use em if you configure them */
2701 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
2703 AST_RWLOCK_DEFINE_STATIC(features_lock);
2705 static struct ast_call_feature builtin_features[] = {
2706 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2707 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2708 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2709 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2710 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2711 { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2715 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
2717 /*! \brief register new feature into feature_list*/
2718 void ast_register_feature(struct ast_call_feature *feature)
2721 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
2725 AST_RWLIST_WRLOCK(&feature_list);
2726 AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
2727 AST_RWLIST_UNLOCK(&feature_list);
2729 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
2733 * \brief Add new feature group
2734 * \param fgname feature group name.
2736 * Add new feature group to the feature group list insert at head of list.
2737 * \note This function MUST be called while feature_groups is locked.
2739 static struct feature_group *register_group(const char *fgname)
2741 struct feature_group *fg;
2744 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
2748 if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
2752 ast_string_field_set(fg, gname, fgname);
2754 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
2756 ast_verb(2, "Registered group '%s'\n", fg->gname);
2762 * \brief Add feature to group
2763 * \param fg feature group
2765 * \param feature feature to add.
2767 * Check fg and feature specified, add feature to list
2768 * \note This function MUST be called while feature_groups is locked.
2770 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
2772 struct feature_group_exten *fge;
2775 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
2780 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
2784 if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
2788 ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
2790 fge->feature = feature;
2792 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
2794 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
2795 feature->sname, fg->gname, fge->exten);
2798 void ast_unregister_feature(struct ast_call_feature *feature)
2804 AST_RWLIST_WRLOCK(&feature_list);
2805 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
2806 AST_RWLIST_UNLOCK(&feature_list);
2811 /*! \brief Remove all features in the list */
2812 static void ast_unregister_features(void)
2814 struct ast_call_feature *feature;
2816 AST_RWLIST_WRLOCK(&feature_list);
2817 while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
2820 AST_RWLIST_UNLOCK(&feature_list);
2823 /*! \brief find a call feature by name */
2824 static struct ast_call_feature *find_dynamic_feature(const char *name)
2826 struct ast_call_feature *tmp;
2828 AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
2829 if (!strcasecmp(tmp->sname, name)) {
2837 /*! \brief Remove all feature groups in the list */
2838 static void ast_unregister_groups(void)
2840 struct feature_group *fg;
2841 struct feature_group_exten *fge;
2843 AST_RWLIST_WRLOCK(&feature_groups);
2844 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
2845 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
2846 ast_string_field_free_memory(fge);
2850 ast_string_field_free_memory(fg);
2853 AST_RWLIST_UNLOCK(&feature_groups);
2857 * \brief Find a group by name
2858 * \param name feature name
2859 * \retval feature group on success.
2860 * \retval NULL on failure.
2862 static struct feature_group *find_group(const char *name)
2864 struct feature_group *fg = NULL;
2866 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
2867 if (!strcasecmp(fg->gname, name))
2874 void ast_rdlock_call_features(void)
2876 ast_rwlock_rdlock(&features_lock);
2879 void ast_unlock_call_features(void)
2881 ast_rwlock_unlock(&features_lock);
2884 struct ast_call_feature *ast_find_call_feature(const char *name)
2887 for (x = 0; x < FEATURES_COUNT; x++) {
2888 if (!strcasecmp(name, builtin_features[x].sname))
2889 return &builtin_features[x];
2895 * \brief exec an app by feature
2896 * \param chan,peer,config,code,sense,data
2898 * Find a feature, determine which channel activated
2899 * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
2901 * \retval -2 when an application cannot be found.
2903 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2905 struct ast_app *app;
2906 struct ast_call_feature *feature = data;
2907 struct ast_channel *work, *idle;
2910 if (!feature) { /* shouldn't ever happen! */
2911 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
2915 if (sense == FEATURE_SENSE_CHAN) {
2916 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
2917 return AST_FEATURE_RETURN_KEEPTRYING;
2918 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2926 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
2927 return AST_FEATURE_RETURN_KEEPTRYING;
2928 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2937 if (!(app = pbx_findapp(feature->app))) {
2938 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
2942 ast_autoservice_start(idle);
2943 ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
2946 pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
2947 pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
2948 pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
2949 pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
2952 if (!ast_strlen_zero(feature->moh_class))
2953 ast_moh_start(idle, feature->moh_class, NULL);
2955 res = pbx_exec(work, app, feature->app_args);
2957 if (!ast_strlen_zero(feature->moh_class))
2960 ast_autoservice_stop(idle);
2963 return AST_FEATURE_RETURN_SUCCESSBREAK;
2965 return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
2968 static void unmap_features(void)
2972 ast_rwlock_wrlock(&features_lock);
2973 for (x = 0; x < FEATURES_COUNT; x++)
2974 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
2975 ast_rwlock_unlock(&features_lock);
2978 static int remap_feature(const char *name, const char *value)
2982 ast_rwlock_wrlock(&features_lock);
2983 for (x = 0; x < FEATURES_COUNT; x++) {
2984 if (strcasecmp(builtin_features[x].sname, name))
2987 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
2991 ast_rwlock_unlock(&features_lock);
2997 * \brief Helper function for feature_interpret and ast_feature_detect
2998 * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
3000 * Lock features list, browse for code, unlock list
3001 * If a feature is found and the operation variable is set, that feature's
3002 * operation is executed. The first feature found is copied to the feature parameter.
3003 * \retval res on success.
3004 * \retval -1 on failure.
3006 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
3007 struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
3008 struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
3011 struct feature_group *fg = NULL;
3012 struct feature_group_exten *fge;
3013 struct ast_call_feature *tmpfeature;
3015 int res = AST_FEATURE_RETURN_PASSDIGITS;
3016 int feature_detected = 0;
3018 if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
3019 return -1; /* can not run feature operation */
3022 ast_rwlock_rdlock(&features_lock);
3023 for (x = 0; x < FEATURES_COUNT; x++) {
3024 if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
3025 !ast_strlen_zero(builtin_features[x].exten)) {
3026 /* Feature is up for consideration */
3027 if (!strcmp(builtin_features[x].exten, code)) {
3028 ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
3029 if (operation == FEATURE_INTERPRET_CHECK) {
3030 res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3031 } else if (operation == FEATURE_INTERPRET_DO) {
3032 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
3035 memcpy(feature, &builtin_features[x], sizeof(feature));
3037 feature_detected = 1;
3039 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
3040 if (res == AST_FEATURE_RETURN_PASSDIGITS) {
3041 res = AST_FEATURE_RETURN_STOREDIGITS;
3046 ast_rwlock_unlock(&features_lock);
3048 if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
3052 tmp = dynamic_features_buf;
3054 while ((tok = strsep(&tmp, "#"))) {
3055 AST_RWLIST_RDLOCK(&feature_groups);
3057 fg = find_group(tok);
3060 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
3061 if (!strcmp(fge->exten, code)) {
3063 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
3065 memcpy(feature, fge->feature, sizeof(feature));
3066 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3067 AST_RWLIST_UNLOCK(&feature_groups);
3070 res = AST_FEATURE_RETURN_PASSDIGITS;
3071 } else if (!strncmp(fge->exten, code, strlen(code))) {
3072 res = AST_FEATURE_RETURN_STOREDIGITS;
3080 AST_RWLIST_UNLOCK(&feature_groups);
3082 AST_RWLIST_RDLOCK(&feature_list);
3084 if (!(tmpfeature = find_dynamic_feature(tok))) {
3085 AST_RWLIST_UNLOCK(&feature_list);
3089 /* Feature is up for consideration */
3090 if (!strcmp(tmpfeature->exten, code)) {
3091 ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
3092 if (operation == FEATURE_INTERPRET_CHECK) {
3093 res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3094 } else if (operation == FEATURE_INTERPRET_DO) {
3095 res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);