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;
848 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
849 char *x, *goto_on_transfer;
852 if (ast_strlen_zero(val))
855 goto_on_transfer = ast_strdupa(val);
857 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", chan->linkedid, 0, "%s", chan->name)))
860 for (x = goto_on_transfer; x && *x; x++) {
864 /* Make formats okay */
865 xferchan->readformat = chan->readformat;
866 xferchan->writeformat = chan->writeformat;
867 ast_channel_masquerade(xferchan, chan);
868 ast_parseable_goto(xferchan, goto_on_transfer);
869 xferchan->_state = AST_STATE_UP;
870 ast_clear_flag(xferchan, AST_FLAGS_ALL);
871 ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
872 if ((f = ast_read(xferchan))) {
875 ast_pbx_start(xferchan);
877 ast_hangup(xferchan);
881 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
882 const char *caller_name, struct ast_channel *requestor,
883 struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, void *data,
884 int timeout, int *outstate, const char *language);
887 * \brief bridge the call
888 * \param data thread bridge.
890 * Set Last Data for respective channels, reset cdr for channels
891 * bridge call, check if we're going back to dialplan
892 * if not hangup both legs of the call
894 static void *bridge_call_thread(void *data)
896 struct ast_bridge_thread_obj *tobj = data;
899 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
900 tobj->chan->data = tobj->peer->name;
901 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
902 tobj->peer->data = tobj->chan->name;
904 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
906 if (tobj->return_to_pbx) {
907 if (!ast_check_hangup(tobj->peer)) {
908 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
909 res = ast_pbx_start(tobj->peer);
910 if (res != AST_PBX_SUCCESS)
911 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
913 ast_hangup(tobj->peer);
914 if (!ast_check_hangup(tobj->chan)) {
915 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
916 res = ast_pbx_start(tobj->chan);
917 if (res != AST_PBX_SUCCESS)
918 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
920 ast_hangup(tobj->chan);
922 ast_hangup(tobj->chan);
923 ast_hangup(tobj->peer);
932 * \brief create thread for the parked call
935 * Create thread and attributes, call bridge_call_thread
937 static void bridge_call_thread_launch(void *data)
941 struct sched_param sched;
943 pthread_attr_init(&attr);
944 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
945 ast_pthread_create(&thread, &attr, bridge_call_thread, data);
946 pthread_attr_destroy(&attr);
947 memset(&sched, 0, sizeof(sched));
948 pthread_setschedparam(thread, SCHED_RR, &sched);
952 * \brief Announce call parking by ADSI
954 * \param parkingexten .
955 * Create message to show for ADSI, display message.
956 * \retval 0 on success.
957 * \retval -1 on failure.
959 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
962 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
964 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
966 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
968 res = ast_adsi_load_session(chan, NULL, 0, 1);
971 return ast_adsi_print(chan, message, justify, 1);
975 * \brief Find parking lot name from channel
976 * \note Channel needs to be locked while the returned string is in use.
978 static const char *findparkinglotname(struct ast_channel *chan)
982 /* The channel variable overrides everything */
983 name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
984 if (!name && !ast_strlen_zero(chan->parkinglot)) {
985 /* Use the channel's parking lot. */
986 name = chan->parkinglot;
991 /*! \brief Notify metermaids that we've changed an extension */
992 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
994 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
995 exten, context, ast_devstate2str(state));
997 ast_devstate_changed(state, "park:%s@%s", exten, context);
1000 /*! \brief metermaids callback from devicestate.c */
1001 static enum ast_device_state metermaidstate(const char *data)
1006 context = ast_strdupa(data);
1008 exten = strsep(&context, "@");
1010 return AST_DEVICE_INVALID;
1012 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
1014 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
1015 return AST_DEVICE_NOT_INUSE;
1017 return AST_DEVICE_INUSE;
1020 /*! Options to pass to park_call_full */
1021 enum ast_park_call_options {
1022 /*! Provide ringing to the parked caller instead of music on hold */
1023 AST_PARK_OPT_RINGING = (1 << 0),
1024 /*! Randomly choose a parking spot for the caller instead of choosing
1025 * the first one that is available. */
1026 AST_PARK_OPT_RANDOMIZE = (1 << 1),
1027 /*! Do not announce the parking number */
1028 AST_PARK_OPT_SILENCE = (1 << 2),
1031 /*! Optional additional parking options when parking a call. */
1032 struct ast_park_call_args {
1033 /*! How long to wait in the parking lot before the call gets sent back
1034 * to the specified return extension (or a best guess at where it came
1035 * from if not explicitly specified). */
1037 /*! An output parameter to store the parking space where the parked caller
1040 const char *orig_chan_name;
1041 const char *return_con;
1042 const char *return_ext;
1045 /*! Parked user that has already obtained a parking space */
1046 struct parkeduser *pu;
1047 /*! \brief Parkinglot to be parked in */
1048 struct ast_parkinglot *parkinglot;
1053 * \brief Create a dynamic parking lot.
1055 * \param name Dynamic parking lot name to create.
1056 * \param chan Channel to get dynamic parking lot parameters.
1058 * \retval parkinglot on success.
1059 * \retval NULL on error.
1061 static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
1063 const char *dyn_context;
1064 const char *dyn_exten;
1065 const char *dyn_range;
1066 const char *template_name;
1067 struct ast_parkinglot *template_parkinglot = NULL;
1068 struct ast_parkinglot *parkinglot;
1072 ast_channel_lock(chan);
1073 template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
1074 dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
1075 dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
1076 dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
1077 ast_channel_unlock(chan);
1079 if (!ast_strlen_zero(template_name)) {
1080 template_parkinglot = find_parkinglot(template_name);
1081 if (!template_parkinglot) {
1082 ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
1084 } else if (template_parkinglot->cfg.is_invalid) {
1085 ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
1087 parkinglot_unref(template_parkinglot);
1088 template_parkinglot = NULL;
1091 if (!template_parkinglot) {
1092 template_parkinglot = parkinglot_addref(default_parkinglot);
1093 ast_debug(1, "Using default parking lot for template\n");
1096 parkinglot = copy_parkinglot(name, template_parkinglot);
1098 ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
1100 /* Configure the dynamic parking lot. */
1101 if (!ast_strlen_zero(dyn_context)) {
1102 ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
1103 sizeof(parkinglot->cfg.parking_con));
1105 if (!ast_strlen_zero(dyn_exten)) {
1106 ast_copy_string(parkinglot->cfg.parkext, dyn_exten,
1107 sizeof(parkinglot->cfg.parkext));
1109 if (!ast_strlen_zero(dyn_range)) {
1110 if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
1111 ast_log(LOG_WARNING,
1112 "Format for parking positions is a-b, where a and b are numbers\n");
1113 } else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
1114 ast_log(LOG_WARNING,
1115 "Format for parking positions is a-b, where a <= b\n");
1117 parkinglot->cfg.parking_start = dyn_start;
1118 parkinglot->cfg.parking_stop = dyn_end;
1123 * Sanity check for dynamic parking lot configuration.
1125 * XXX It may be desirable to instead check if the dynamic
1126 * parking lot overlaps any existing lots like what is done for
1129 if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
1130 if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)
1131 && parkinglot->cfg.parkext_exclusive) {
1132 ast_log(LOG_WARNING,
1133 "Parking lot '%s' conflicts with template parking lot '%s'!\n"
1134 "Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
1135 parkinglot->name, template_parkinglot->name);
1137 if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
1138 && parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
1139 || (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
1140 && parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
1141 || (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
1142 && template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
1143 ast_log(LOG_WARNING,
1144 "Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
1145 "Change PARKINGDYNPOS.\n",
1146 parkinglot->name, template_parkinglot->name);
1150 parkinglot_activate(parkinglot);
1151 ao2_link(parkinglots, parkinglot);
1153 parkinglot_unref(template_parkinglot);
1160 * \brief Reserve a parking space in a parking lot for a call being parked.
1162 * \param park_me Channel being parked.
1163 * \param parker Channel parking the call.
1164 * \param args Optional additional parking options when parking a call.
1166 * \return Parked call descriptor or NULL if failed.
1167 * \note The parking lot list is locked if successful.
1169 static struct parkeduser *park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
1171 struct parkeduser *pu;
1173 int parking_space = -1;
1174 const char *parkinglotname;
1175 const char *parkingexten;
1176 struct parkeduser *cur;
1177 struct ast_parkinglot *parkinglot = NULL;
1179 if (args->parkinglot) {
1180 parkinglot = parkinglot_addref(args->parkinglot);
1181 parkinglotname = parkinglot->name;
1184 parkinglotname = findparkinglotname(parker);
1185 } else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
1186 parkinglotname = findparkinglotname(park_me);
1188 if (!ast_strlen_zero(parkinglotname)) {
1189 parkinglot = find_parkinglot(parkinglotname);
1191 /* Parking lot is not specified, so use the default parking lot. */
1192 ast_debug(4, "This could be an indication channel driver needs updating, using default lot.\n");
1193 parkinglot = parkinglot_addref(default_parkinglot);
1197 /* Dynamically create parkinglot */
1198 if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
1199 parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
1203 ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", park_me->name);
1207 ast_debug(1, "Parking lot: %s\n", parkinglot->name);
1208 if (parkinglot->disabled || parkinglot->cfg.is_invalid) {
1209 ast_log(LOG_WARNING, "Parking lot %s is not in a useable state.\n",
1211 parkinglot_unref(parkinglot);
1215 /* Allocate memory for parking data */
1216 if (!(pu = ast_calloc(1, sizeof(*pu)))) {
1217 parkinglot_unref(parkinglot);
1221 /* Lock parking list */
1222 AST_LIST_LOCK(&parkinglot->parkings);
1224 /* Check for channel variable PARKINGEXTEN */
1225 parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
1226 if (!ast_strlen_zero(parkingexten)) {
1228 * \note The API forces us to specify a numeric parking slot, even
1229 * though the architecture would tend to support non-numeric extensions
1230 * (as are possible with SIP, for example). Hence, we enforce that
1231 * limitation here. If extout was not numeric, we could permit
1232 * arbitrary non-numeric extensions.
1234 if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space <= 0) {
1235 ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n",
1237 AST_LIST_UNLOCK(&parkinglot->parkings);
1238 parkinglot_unref(parkinglot);
1243 if (parking_space < parkinglot->cfg.parking_start
1244 || parkinglot->cfg.parking_stop < parking_space) {
1246 * Cannot allow park because parking lots are not setup for
1247 * spaces outside of the lot. (Things like dialplan hints don't
1248 * exist for outside lot space.)
1250 ast_log(LOG_WARNING, "PARKINGEXTEN=%d is not in %s (%d-%d).\n",
1251 parking_space, parkinglot->name, parkinglot->cfg.parking_start,
1252 parkinglot->cfg.parking_stop);
1253 AST_LIST_UNLOCK(&parkinglot->parkings);
1254 parkinglot_unref(parkinglot);
1259 /* Check if requested parking space is in use. */
1260 AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1261 if (cur->parkingnum == parking_space) {
1262 ast_log(LOG_WARNING, "PARKINGEXTEN=%d is already in use in %s\n",
1263 parking_space, parkinglot->name);
1264 AST_LIST_UNLOCK(&parkinglot->parkings);
1265 parkinglot_unref(parkinglot);
1271 /* PARKINGEXTEN is empty, so find a usable extension in the lot to park the call */
1272 int start; /* The first slot we look in the parkinglot. It can be randomized. */
1273 int start_checked = 0; /* flag raised once the first slot is checked */
1275 /* If using randomize mode, set start to random position on parking range */
1276 if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
1277 start = ast_random() % (parkinglot->cfg.parking_stop - parkinglot->cfg.parking_start + 1);
1278 start += parkinglot->cfg.parking_start;
1279 } else if (parkinglot->cfg.parkfindnext
1280 && parkinglot->cfg.parking_start <= parkinglot->next_parking_space
1281 && parkinglot->next_parking_space <= parkinglot->cfg.parking_stop) {
1282 /* Start looking with the next parking space in the lot. */
1283 start = parkinglot->next_parking_space;
1285 /* Otherwise, just set it to the start position. */
1286 start = parkinglot->cfg.parking_start;
1289 /* free parking extension linear search: O(n^2) */
1290 for (i = start; ; i++) {
1291 /* If we are past the end, wrap around to the first parking slot*/
1292 if (i == parkinglot->cfg.parking_stop + 1) {
1293 i = parkinglot->cfg.parking_start;
1297 /* At this point, if start_checked, we've exhausted all the possible slots. */
1298 if (start_checked) {
1305 /* Search the list of parked calls already in use for i. If we find it, it's in use. */
1306 AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
1307 if (cur->parkingnum == i) {
1312 /* We found a parking space. */
1317 if (parking_space == -1) {
1318 /* We did not find a parking space. Lot is full. */
1319 ast_log(LOG_WARNING, "No more parking spaces in %s\n", parkinglot->name);
1320 AST_LIST_UNLOCK(&parkinglot->parkings);
1321 parkinglot_unref(parkinglot);
1327 /* Prepare for next parking space search. */
1328 parkinglot->next_parking_space = parking_space + 1;
1330 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
1331 pu->notquiteyet = 1;
1332 pu->parkingnum = parking_space;
1333 pu->parkinglot = parkinglot;
1334 AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
1340 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
1342 struct parkeduser *pu = args->pu;
1343 const char *event_from;
1344 char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
1347 args->pu = pu = park_space_reserve(chan, peer, args);
1353 chan->appl = "Parked Call";
1358 /* Put the parked channel on hold if we have two different channels */
1360 if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
1361 pu->hold_method = AST_CONTROL_RINGING;
1362 ast_indicate(pu->chan, AST_CONTROL_RINGING);
1364 pu->hold_method = AST_CONTROL_HOLD;
1365 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
1366 S_OR(pu->parkinglot->cfg.mohclass, NULL),
1367 !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1371 pu->start = ast_tvnow();
1372 pu->parkingtime = (args->timeout > 0) ? args->timeout : pu->parkinglot->cfg.parkingtime;
1374 *(args->extout) = pu->parkingnum;
1378 * This is so ugly that it hurts, but implementing
1379 * get_base_channel() on local channels could have ugly side
1380 * effects. We could have
1381 * transferer<->local,1<->local,2<->parking and we need the
1382 * callback name to be that of transferer. Since local,1/2 have
1383 * the same name we can be tricky and just grab the bridged
1384 * channel from the other side of the local.
1386 if (!strcasecmp(peer->tech->type, "Local")) {
1387 struct ast_channel *tmpchan, *base_peer;
1388 char other_side[AST_CHANNEL_NAME];
1391 ast_copy_string(other_side, S_OR(args->orig_chan_name, peer->name), sizeof(other_side));
1392 if ((c = strrchr(other_side, ';'))) {
1395 if ((tmpchan = ast_channel_get_by_name(other_side))) {
1396 ast_channel_lock(tmpchan);
1397 if ((base_peer = ast_bridged_channel(tmpchan))) {
1398 ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
1400 ast_channel_unlock(tmpchan);
1401 tmpchan = ast_channel_unref(tmpchan);
1404 ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
1409 * Remember what had been dialed, so that if the parking
1410 * expires, we try to come back to the same place
1412 pu->options_specified = (!ast_strlen_zero(args->return_con) || !ast_strlen_zero(args->return_ext) || args->return_pri);
1415 * If extension has options specified, they override all other
1416 * possibilities such as the returntoorigin flag and transferred
1417 * context. Information on extension options is lost here, so
1420 ast_copy_string(pu->context,
1421 S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)),
1422 sizeof(pu->context));
1423 ast_copy_string(pu->exten,
1424 S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)),
1426 pu->priority = args->return_pri ? args->return_pri :
1427 (chan->macropriority ? chan->macropriority : chan->priority);
1430 * If parking a channel directly, don't quite yet get parking
1431 * running on it. All parking lot entries are put into the
1432 * parking lot with notquiteyet on.
1435 pu->notquiteyet = 0;
1438 /* Wake up the (presumably select()ing) thread */
1439 pthread_kill(parking_thread, SIGURG);
1440 ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
1441 pu->chan->name, pu->parkingnum, pu->parkinglot->name,
1442 pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
1444 ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
1447 event_from = peer->name;
1449 event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
1452 ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
1455 "Parkinglot: %s\r\n"
1458 "CallerIDNum: %s\r\n"
1459 "CallerIDName: %s\r\n"
1460 "ConnectedLineNum: %s\r\n"
1461 "ConnectedLineName: %s\r\n"
1463 pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
1464 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
1465 S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
1466 S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
1467 S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
1468 S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
1472 if (peer && adsipark && ast_adsi_available(peer)) {
1473 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
1474 ast_adsi_unload_session(peer);
1477 snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
1478 pu->parkinglot->name);
1479 if (ast_add_extension(pu->parkinglot->cfg.parking_con, 1, pu->parkingexten, 1,
1480 NULL, NULL, parkedcall, ast_strdup(app_data), ast_free_ptr, registrar)) {
1481 ast_log(LOG_ERROR, "Could not create parked call exten: %s@%s\n",
1482 pu->parkingexten, pu->parkinglot->cfg.parking_con);
1484 notify_metermaids(pu->parkingexten, pu->parkinglot->cfg.parking_con, AST_DEVICE_INUSE);
1487 AST_LIST_UNLOCK(&pu->parkinglot->parkings);
1489 /* Only say number if it's a number and the channel hasn't been masqueraded away */
1490 if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE)
1491 && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
1493 * If a channel is masqueraded into peer while playing back the
1494 * parking space number do not continue playing it back. This
1495 * is the case if an attended transfer occurs.
1497 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1498 /* Tell the peer channel the number of the parking space */
1499 ast_say_digits(peer, pu->parkingnum, "", peer->language);
1500 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
1502 if (peer == chan) { /* pu->notquiteyet = 1 */
1503 /* Wake up parking thread if we're really done */
1504 pu->hold_method = AST_CONTROL_HOLD;
1505 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
1506 S_OR(pu->parkinglot->cfg.mohclass, NULL),
1507 !ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
1508 pu->notquiteyet = 0;
1509 pthread_kill(parking_thread, SIGURG);
1514 /*! \brief Park a call */
1515 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, const char *parkexten, int *extout)
1517 struct ast_park_call_args args = {
1522 return park_call_full(chan, peer, &args);
1526 * \param rchan the real channel to be parked
1527 * \param peer the channel to have the parking read to.
1528 * \param timeout is a timeout in milliseconds
1529 * \param extout is a parameter to an int that will hold the parked location, or NULL if you want.
1530 * \param play_announcement TRUE if to play which parking space call parked in to peer.
1531 * \param args Optional additional parking options when parking a call.
1533 * \retval 0 on success.
1534 * \retval -1 on failure.
1536 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)
1538 struct ast_channel *chan;
1539 struct ast_park_call_args park_args = {0,};
1543 args->timeout = timeout;
1544 args->extout = extout;
1547 /* Make a new, channel that we'll use to masquerade in the real one */
1548 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten,
1549 rchan->context, rchan->linkedid, rchan->amaflags, "Parked/%s", rchan->name);
1551 ast_log(LOG_WARNING, "Unable to create parked channel\n");
1552 if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1553 if (peer == rchan) {
1554 /* Only have one channel to worry about. */
1555 ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1557 /* Have two different channels to worry about. */
1558 play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1564 args->pu = park_space_reserve(rchan, peer, args);
1566 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
1568 if (!ast_test_flag(args, AST_PARK_OPT_SILENCE)) {
1569 if (peer == rchan) {
1570 /* Only have one channel to worry about. */
1571 ast_stream_and_wait(peer, "pbx-parkingfailed", "");
1573 /* Have two different channels to worry about. */
1574 play_message_on_chan(peer, rchan, "failure message", "pbx-parkingfailed");
1580 /* Make formats okay */
1581 chan->readformat = rchan->readformat;
1582 chan->writeformat = rchan->writeformat;
1583 ast_channel_masquerade(chan, rchan);
1585 /* Setup the extensions and such */
1586 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
1588 /* Setup the macro extension and such */
1589 ast_copy_string(chan->macrocontext,rchan->macrocontext,sizeof(chan->macrocontext));
1590 ast_copy_string(chan->macroexten,rchan->macroexten,sizeof(chan->macroexten));
1591 chan->macropriority = rchan->macropriority;
1593 /* Manually do the masquerade to make sure it is complete. */
1594 ast_do_masquerade(chan);
1596 if (peer == rchan) {
1600 if (peer && (!play_announcement && args == &park_args)) {
1601 args->orig_chan_name = ast_strdupa(peer->name);
1604 /* parking space reserved, return code check unnecessary */
1605 park_call_full(chan, peer, args);
1610 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
1612 return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
1616 * \brief Park call via masqueraded channel and announce parking spot on peer channel.
1618 * \param rchan the real channel to be parked
1619 * \param peer the channel to have the parking read to.
1620 * \param args Optional additional parking options when parking a call.
1622 * \retval 0 on success.
1623 * \retval -1 on failure.
1625 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args)
1627 return masq_park_call(rchan, peer, 0, NULL, 1, args);
1630 static int finishup(struct ast_channel *chan)
1632 ast_indicate(chan, AST_CONTROL_UNHOLD);
1634 return ast_autoservice_stop(chan);
1639 * \brief Builtin transfer park call helper.
1641 * \param park_me Channel to be parked.
1642 * \param parker Channel parking the call.
1643 * \param park_exten Parking lot dialplan access ramp extension.
1645 * \note Assumes park_me is on hold and in autoservice.
1647 * \retval -1 on successful park.
1648 * \retval -1 on park_me hangup.
1649 * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
1651 static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
1654 const char *app_data;
1655 const char *pl_name;
1656 struct ast_park_call_args args = { 0, };
1657 struct park_app_args app_args;
1660 app_data = ast_get_extension_app_data(park_exten);
1664 parse = ast_strdupa(app_data);
1665 AST_STANDARD_APP_ARGS(app_args, parse);
1667 /* Find the parking lot */
1668 if (!ast_strlen_zero(app_args.pl_name)) {
1669 pl_name = app_args.pl_name;
1671 pl_name = findparkinglotname(parker);
1673 if (ast_strlen_zero(pl_name)) {
1674 /* Parking lot is not specified, so use the default parking lot. */
1675 args.parkinglot = parkinglot_addref(default_parkinglot);
1677 args.parkinglot = find_parkinglot(pl_name);
1678 if (!args.parkinglot && parkeddynamic) {
1679 args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
1683 if (args.parkinglot) {
1685 res = finishup(park_me);
1687 /* park_me hungup on us. */
1688 parkinglot_unref(args.parkinglot);
1691 res = masq_park_call_announce(park_me, parker, &args);
1692 parkinglot_unref(args.parkinglot);
1694 /* Parking failed because parking lot does not exist. */
1695 if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
1696 ast_stream_and_wait(parker, "pbx-parkingfailed", "");
1702 return res ? AST_FEATURE_RETURN_SUCCESS : -1;
1706 * \brief set caller and callee according to the direction
1707 * \param caller, callee, peer, chan, sense
1709 * Detect who triggered feature and set callee/caller variables accordingly
1711 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
1712 struct ast_channel *peer, struct ast_channel *chan, int sense)
1714 if (sense == FEATURE_SENSE_PEER) {
1724 * \brief support routing for one touch call parking
1725 * \param chan channel parking call
1726 * \param peer channel to be parked
1727 * \param config unsed
1728 * \param code unused
1729 * \param sense feature options
1730 * \param data unused
1732 * \retval -1 on successful park.
1733 * \retval -1 on chan hangup.
1734 * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
1736 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1738 struct ast_channel *parker;
1739 struct ast_channel *parkee;
1742 * We used to set chan's exten and priority to "s" and 1 here,
1743 * but this generates (in some cases) an invalid extension, and
1744 * if "s" exists, could errantly cause execution of extensions
1745 * you don't expect. It makes more sense to let nature take its
1746 * course when chan finishes, and let the pbx do its thing and
1747 * hang up when the park is over.
1750 /* Answer if call is not up */
1751 if (chan->_state != AST_STATE_UP) {
1753 * XXX Why are we doing this? Both of the channels should be up
1754 * since you cannot do DTMF features unless you are bridged.
1756 if (ast_answer(chan)) {
1760 /* Sleep to allow VoIP streams to settle down */
1761 if (ast_safe_sleep(chan, 1000)) {
1766 /* one direction used to call park_call.... */
1767 set_peers(&parker, &parkee, peer, chan, sense);
1768 return masq_park_call_announce(parkee, parker, NULL)
1769 ? AST_FEATURE_RETURN_SUCCESS : -1;
1774 * \brief Play file to specified channel.
1776 * \param play_to Channel to play audiofile to.
1777 * \param other Channel to put in autoservice while playing file.
1778 * \param msg Descriptive name of message type being played.
1779 * \param audiofile Audio file to play.
1781 * \retval 0 on success.
1782 * \retval -1 on error. (Couldn't play file, a channel hung up,...)
1784 static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel *other, const char *msg, const char *audiofile)
1786 /* Put other channel in autoservice. */
1787 if (ast_autoservice_start(other)) {
1790 ast_autoservice_ignore(other, AST_FRAME_DTMF_BEGIN);
1791 ast_autoservice_ignore(other, AST_FRAME_DTMF_END);
1792 if (ast_stream_and_wait(play_to, audiofile, "")) {
1793 ast_log(LOG_WARNING, "Failed to play %s '%s'!\n", msg, audiofile);
1794 ast_autoservice_stop(other);
1797 if (ast_autoservice_stop(other)) {
1805 * \brief Play file to specified channels.
1807 * \param left Channel on left to play file.
1808 * \param right Channel on right to play file.
1809 * \param which Play file on indicated channels: which < 0 play left, which == 0 play both, which > 0 play right
1810 * \param msg Descriptive name of message type being played.
1811 * \param audiofile Audio file to play to channels.
1813 * \note Plays file to the indicated channels in turn so please
1814 * don't use this for very long messages.
1816 * \retval 0 on success.
1817 * \retval -1 on error. (Couldn't play file, channel hung up,...)
1819 static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
1821 /* First play the file to the left channel if requested. */
1822 if (which <= 0 && play_message_on_chan(left, right, msg, audiofile)) {
1826 /* Then play the file to the right channel if requested. */
1827 if (which >= 0 && play_message_on_chan(right, left, msg, audiofile)) {
1835 * \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
1836 * other channel during the message, so please don't use this for very long messages
1838 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
1840 return play_message_to_chans(caller_chan, callee_chan, 0, "automon message",
1845 * \brief Monitor a channel by DTMF
1846 * \param chan channel requesting monitor
1847 * \param peer channel to be monitored
1850 * \param sense feature options
1853 * Check monitor app enabled, setup channels, both caller/callee chans not null
1854 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
1855 * \retval AST_FEATURE_RETURN_SUCCESS on success.
1856 * \retval -1 on error.
1858 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1860 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1863 struct ast_channel *caller_chan, *callee_chan;
1864 const char *automon_message_start = NULL;
1865 const char *automon_message_stop = NULL;
1868 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1872 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
1874 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
1878 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1879 if (caller_chan) { /* Find extra messages */
1880 automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
1881 automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
1884 if (!ast_strlen_zero(courtesytone)) { /* Play courtesy tone if configured */
1885 if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
1890 if (callee_chan->monitor) {
1891 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
1892 if (!ast_strlen_zero(automon_message_stop)) {
1893 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
1895 callee_chan->monitor->stop(callee_chan, 1);
1896 return AST_FEATURE_RETURN_SUCCESS;
1899 if (caller_chan && callee_chan) {
1900 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
1901 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
1902 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
1905 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
1908 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
1910 if (!touch_monitor_prefix)
1911 touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
1913 if (touch_monitor) {
1914 len = strlen(touch_monitor) + 50;
1916 touch_filename = alloca(len);
1917 snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
1918 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1920 caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
1921 caller_chan->caller.id.number.str, caller_chan->name));
1922 callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
1923 callee_chan->caller.id.number.str, callee_chan->name));
1924 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1926 touch_filename = alloca(len);
1927 snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
1928 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
1931 for(x = 0; x < strlen(args); x++) {
1936 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
1938 pbx_exec(callee_chan, monitor_app, args);
1939 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1940 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
1942 if (!ast_strlen_zero(automon_message_start)) { /* Play start message for both channels */
1943 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
1946 return AST_FEATURE_RETURN_SUCCESS;
1949 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
1953 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
1955 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1958 struct ast_channel *caller_chan, *callee_chan;
1959 const char *mixmonitor_spy_type = "MixMonitor";
1962 if (!mixmonitor_ok) {
1963 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1967 if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
1969 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1973 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1975 if (!ast_strlen_zero(courtesytone)) {
1976 if (ast_autoservice_start(callee_chan))
1978 ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
1979 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
1980 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1981 ast_autoservice_stop(callee_chan);
1984 if (ast_autoservice_stop(callee_chan))
1988 ast_channel_lock(callee_chan);
1989 count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1990 ast_channel_unlock(callee_chan);
1992 /* This means a mixmonitor is attached to the channel, running or not is unknown. */
1995 ast_verb(3, "User hit '%s' to stop recording call.\n", code);
1997 /* Make sure they are running */
1998 ast_channel_lock(callee_chan);
1999 count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
2000 ast_channel_unlock(callee_chan);
2002 if (!stopmixmonitor_ok) {
2003 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2006 if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
2007 stopmixmonitor_ok = 0;
2008 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
2011 pbx_exec(callee_chan, stopmixmonitor_app, "");
2012 return AST_FEATURE_RETURN_SUCCESS;
2016 ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
2019 if (caller_chan && callee_chan) {
2020 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
2021 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
2024 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
2027 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
2029 if (touch_monitor) {
2030 len = strlen(touch_monitor) + 50;
2032 touch_filename = alloca(len);
2033 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
2034 snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
2036 caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
2037 caller_chan->caller.id.number.str, caller_chan->name));
2038 callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
2039 callee_chan->caller.id.number.str, callee_chan->name));
2040 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
2042 touch_filename = alloca(len);
2043 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
2044 snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
2047 for( x = 0; x < strlen(args); x++) {
2052 ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
2054 pbx_exec(callee_chan, mixmonitor_app, args);
2055 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2056 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
2057 return AST_FEATURE_RETURN_SUCCESS;
2061 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
2066 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2068 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
2069 return AST_FEATURE_RETURN_HANGUP;
2073 * \brief Find the context for the transfer
2077 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
2078 * \return a context string
2080 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
2082 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
2083 if (ast_strlen_zero(s)) {
2084 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
2086 if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
2087 s = transferer->macrocontext;
2089 if (ast_strlen_zero(s)) {
2090 s = transferer->context;
2096 * \brief Blind transfer user to another extension
2097 * \param chan channel to be transfered
2098 * \param peer channel initiated blind transfer
2102 * \param sense feature options
2104 * Place chan on hold, check if transferred to parkinglot extension,
2105 * otherwise check extension exists and transfer caller.
2106 * \retval AST_FEATURE_RETURN_SUCCESS.
2107 * \retval -1 on failure.
2109 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2111 struct ast_channel *transferer;
2112 struct ast_channel *transferee;
2113 struct ast_exten *park_exten;
2114 const char *transferer_real_context;
2115 char xferto[256] = "";
2118 set_peers(&transferer, &transferee, peer, chan, sense);
2119 transferer_real_context = real_ctx(transferer, transferee);
2121 /* Start autoservice on transferee while we talk to the transferer */
2122 ast_autoservice_start(transferee);
2123 ast_indicate(transferee, AST_CONTROL_HOLD);
2126 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2128 finishup(transferee);
2129 return -1; /* error ? */
2131 if (res > 0) { /* If they've typed a digit already, handle it */
2132 xferto[0] = (char) res;
2135 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2136 if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2137 finishup(transferee);
2142 ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2143 xferto, transferer_real_context);
2145 /* Does anyone care about this case? */
2146 ast_log(LOG_WARNING, "No digits dialed.\n");
2148 ast_stream_and_wait(transferer, "pbx-invalid", "");
2149 finishup(transferee);
2150 return AST_FEATURE_RETURN_SUCCESS;
2153 park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2155 /* We are transfering the transferee to a parking lot. */
2156 return xfer_park_call_helper(transferee, transferer, park_exten);
2159 /* Do blind transfer. */
2160 ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
2161 pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
2162 pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
2163 res = finishup(transferee);
2164 if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
2165 transferer->cdr = ast_cdr_alloc();
2166 if (transferer->cdr) {
2167 ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
2168 ast_cdr_start(transferer->cdr);
2171 if (transferer->cdr) {
2172 struct ast_cdr *swap = transferer->cdr;
2175 "transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
2176 transferer->name, transferee->name, transferer->cdr->lastapp,
2177 transferer->cdr->lastdata, transferer->cdr->channel,
2178 transferer->cdr->dstchannel);
2179 ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
2180 transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel,
2181 transferee->cdr->dstchannel);
2182 ast_debug(1, "transferer_real_context=%s; xferto=%s\n",
2183 transferer_real_context, xferto);
2184 /* swap cdrs-- it will save us some time & work */
2185 transferer->cdr = transferee->cdr;
2186 transferee->cdr = swap;
2188 if (!transferee->pbx) {
2189 /* Doh! Use our handy async_goto functions */
2190 ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n",
2191 transferee->name, xferto, transferer_real_context);
2192 if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
2193 ast_log(LOG_WARNING, "Async goto failed :-(\n");
2196 /* Set the channel's new extension, since it exists, using transferer context */
2197 ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
2199 "ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n",
2201 if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
2202 ast_channel_update_connected_line(transferer, &transferer->connected, NULL);
2204 set_c_e_p(transferee, transferer_real_context, xferto, 0);
2206 check_goto_on_transfer(transferer);
2211 * \brief make channels compatible
2214 * \retval 0 on success.
2215 * \retval -1 on failure.
2217 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
2219 if (ast_channel_make_compatible(c, newchan) < 0) {
2220 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
2221 c->name, newchan->name);
2222 ast_hangup(newchan);
2230 * \brief Builtin attended transfer failed cleanup.
2233 * \param transferee Party A in the transfer.
2234 * \param transferer Party B in the transfer.
2235 * \param connected_line Saved connected line info about party A.
2237 * \note The connected_line data is freed.
2241 static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
2243 finishup(transferee);
2246 * Restore party B connected line info about party A.
2248 * Party B was the caller to party C and is the last known mode
2251 if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
2252 ast_channel_update_connected_line(transferer, connected_line, NULL);
2254 ast_party_connected_line_free(connected_line);
2258 * \brief Attended transfer
2259 * \param chan transfered user
2260 * \param peer person transfering call
2263 * \param sense feature options
2266 * Get extension to transfer to, if you cannot generate channel (or find extension)
2267 * return to host channel. After called channel answered wait for hangup of transferer,
2268 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
2270 * \return -1 on failure
2272 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
2274 struct ast_channel *transferer;/* Party B */
2275 struct ast_channel *transferee;/* Party A */
2276 struct ast_exten *park_exten;
2277 const char *transferer_real_context;
2278 char xferto[256] = "";
2281 struct ast_channel *newchan;
2282 struct ast_channel *xferchan;
2283 struct ast_bridge_thread_obj *tobj;
2284 struct ast_bridge_config bconfig;
2286 struct ast_party_connected_line connected_line;
2287 struct ast_datastore *features_datastore;
2288 struct ast_dial_features *dialfeatures = NULL;
2289 char *transferer_tech;
2290 char *transferer_name;
2291 char *transferer_name_orig;
2294 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
2295 set_peers(&transferer, &transferee, peer, chan, sense);
2296 transferer_real_context = real_ctx(transferer, transferee);
2298 /* Start autoservice on transferee while we talk to the transferer */
2299 ast_autoservice_start(transferee);
2300 ast_indicate(transferee, AST_CONTROL_HOLD);
2303 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
2305 finishup(transferee);
2308 if (res > 0) { /* If they've typed a digit already, handle it */
2309 xferto[0] = (char) res;
2312 /* this is specific of atxfer */
2313 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
2314 if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
2315 finishup(transferee);
2321 ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
2322 xferto, transferer_real_context);
2324 /* Does anyone care about this case? */
2325 ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
2327 ast_stream_and_wait(transferer, "pbx-invalid", "");
2328 finishup(transferee);
2329 return AST_FEATURE_RETURN_SUCCESS;
2332 park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
2334 /* We are transfering the transferee to a parking lot. */
2335 return xfer_park_call_helper(transferee, transferer, park_exten);
2338 /* Append context to dialed transfer number. */
2339 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
2341 /* If we are performing an attended transfer and we have two channels involved then
2342 copy sound file information to play upon attended transfer completion */
2344 const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2345 const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
2347 if (!ast_strlen_zero(chan1_attended_sound)) {
2348 pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
2350 if (!ast_strlen_zero(chan2_attended_sound)) {
2351 pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
2355 /* Extract redial transferer information from the channel name. */
2356 transferer_name_orig = ast_strdupa(transferer->name);
2357 transferer_name = ast_strdupa(transferer_name_orig);
2358 transferer_tech = strsep(&transferer_name, "/");
2359 dash = strrchr(transferer_name, '-');
2361 /* Trim off channel name sequence/serial number. */
2365 /* Stop autoservice so we can monitor all parties involved in the transfer. */
2366 if (ast_autoservice_stop(transferee) < 0) {
2367 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2371 /* Save connected line info for party B about party A in case transfer fails. */
2372 ast_party_connected_line_init(&connected_line);
2373 ast_channel_lock(transferer);
2374 ast_party_connected_line_copy(&connected_line, &transferer->connected);
2375 ast_channel_unlock(transferer);
2376 connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2379 newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
2380 transferee, "Local", transferer->nativeformats, xferto,
2381 atxfernoanswertimeout, &outstate, transferer->language);
2382 ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
2384 if (!ast_check_hangup(transferer)) {
2385 int hangup_dont = 0;
2387 /* Transferer (party B) is up */
2388 ast_debug(1, "Actually doing an attended transfer.\n");
2390 /* Start autoservice on transferee while the transferer deals with party C. */
2391 ast_autoservice_start(transferee);
2393 ast_indicate(transferer, -1);
2395 /* any reason besides user requested cancel and busy triggers the failed sound */
2397 case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
2398 case AST_CONTROL_BUSY:
2399 case AST_CONTROL_CONGESTION:
2400 if (ast_stream_and_wait(transferer, xfersound, "")) {
2401 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2405 if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2406 ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2410 atxfer_fail_cleanup(transferee, transferer, &connected_line);
2411 return AST_FEATURE_RETURN_SUCCESS;
2414 if (check_compat(transferer, newchan)) {
2415 if (ast_stream_and_wait(transferer, xferfailsound, "")) {
2416 ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
2418 atxfer_fail_cleanup(transferee, transferer, &connected_line);
2419 return AST_FEATURE_RETURN_SUCCESS;
2421 memset(&bconfig,0,sizeof(struct ast_bridge_config));
2422 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
2423 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
2425 /* ast_bridge_call clears AST_FLAG_BRIDGE_HANGUP_DONT, but we don't
2426 want that to happen here because we're also in another bridge already
2428 if (ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)) {
2431 /* Let party B and party C talk as long as they want. */
2432 ast_bridge_call(transferer, newchan, &bconfig);
2434 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
2437 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
2438 ast_hangup(newchan);
2439 if (ast_stream_and_wait(transferer, xfersound, "")) {
2440 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2442 atxfer_fail_cleanup(transferee, transferer, &connected_line);
2443 return AST_FEATURE_RETURN_SUCCESS;
2446 /* Transferer (party B) is confirmed hung up at this point. */
2447 if (check_compat(transferee, newchan)) {
2448 finishup(transferee);
2449 ast_party_connected_line_free(&connected_line);
2453 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2454 if ((ast_autoservice_stop(transferee) < 0)
2455 || (ast_waitfordigit(transferee, 100) < 0)
2456 || (ast_waitfordigit(newchan, 100) < 0)
2457 || ast_check_hangup(transferee)
2458 || ast_check_hangup(newchan)) {
2459 ast_hangup(newchan);
2460 ast_party_connected_line_free(&connected_line);
2463 } else if (!ast_check_hangup(transferee)) {
2464 /* Transferer (party B) has hung up at this point. Doing blonde transfer. */
2465 ast_debug(1, "Actually doing a blonde transfer.\n");
2467 if (!newchan && !atxferdropcall) {
2468 /* Party C is not available, try to call party B back. */
2469 unsigned int tries = 0;
2471 if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
2472 ast_log(LOG_WARNING,
2473 "Transferer channel name: '%s' cannot be used for callback.\n",
2474 transferer_name_orig);
2475 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2476 ast_party_connected_line_free(&connected_line);
2482 /* Try to get party B back. */
2483 ast_debug(1, "We're trying to callback %s/%s\n",
2484 transferer_tech, transferer_name);
2485 newchan = feature_request_and_dial(transferer, transferer_name_orig,
2486 transferee, transferee, transferer_tech,
2487 transferee->nativeformats, transferer_name,
2488 atxfernoanswertimeout, &outstate, transferer->language);
2489 ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
2490 !!newchan, outstate);
2491 if (newchan || ast_check_hangup(transferee)) {
2496 if (atxfercallbackretries <= tries) {
2497 /* No more callback tries remaining. */
2501 if (atxferloopdelay) {
2502 /* Transfer failed, sleeping */
2503 ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
2505 ast_safe_sleep(transferee, atxferloopdelay);
2506 if (ast_check_hangup(transferee)) {
2507 ast_party_connected_line_free(&connected_line);
2512 /* Retry dialing party C. */
2513 ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
2514 newchan = feature_request_and_dial(transferer, transferer_name_orig,
2515 transferer, transferee, "Local",
2516 transferee->nativeformats, xferto,
2517 atxfernoanswertimeout, &outstate, transferer->language);
2518 ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
2519 !!newchan, outstate);
2520 if (newchan || ast_check_hangup(transferee)) {
2525 ast_indicate(transferee, AST_CONTROL_UNHOLD);
2527 /* No party C or could not callback party B. */
2528 ast_party_connected_line_free(&connected_line);
2532 /* newchan is up, we should prepare transferee and bridge them */
2533 if (ast_check_hangup(newchan)) {
2534 ast_hangup(newchan);
2535 ast_party_connected_line_free(&connected_line);
2538 if (check_compat(transferee, newchan)) {
2539 ast_party_connected_line_free(&connected_line);
2544 * Both the transferer and transferee have hungup. If newchan
2545 * is up, hang it up as it has no one to talk to.
2547 ast_debug(1, "Everyone is hungup.\n");
2549 ast_hangup(newchan);
2551 ast_party_connected_line_free(&connected_line);
2555 /* Initiate the channel transfer of party A to party C (or recalled party B). */
2556 ast_cel_report_event(transferee, AST_CEL_ATTENDEDTRANSFER, NULL, NULL, newchan);
2558 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", transferee->linkedid, 0, "Transfered/%s", transferee->name);
2560 ast_hangup(newchan);
2561 ast_party_connected_line_free(&connected_line);
2565 /* Give party A a momentary ringback tone during transfer. */
2566 xferchan->visible_indication = AST_CONTROL_RINGING;
2568 /* Make formats okay */
2569 xferchan->readformat = transferee->readformat;
2570 xferchan->writeformat = transferee->writeformat;
2572 ast_channel_masquerade(xferchan, transferee);
2573 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
2574 xferchan->_state = AST_STATE_UP;
2575 ast_clear_flag(xferchan, AST_FLAGS_ALL);
2577 /* Do the masquerade manually to make sure that is is completed. */
2578 ast_do_masquerade(xferchan);
2580 newchan->_state = AST_STATE_UP;
2581 ast_clear_flag(newchan, AST_FLAGS_ALL);
2582 tobj = ast_calloc(1, sizeof(*tobj));
2584 ast_hangup(xferchan);
2585 ast_hangup(newchan);
2586 ast_party_connected_line_free(&connected_line);
2590 ast_channel_lock(newchan);
2591 if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
2592 dialfeatures = features_datastore->data;
2594 ast_channel_unlock(newchan);
2597 /* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
2598 I don't currently understand, the abilities of newchan seem to be stored on the caller side */
2599 ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2600 dialfeatures = NULL;
2603 ast_channel_lock(xferchan);
2604 if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
2605 dialfeatures = features_datastore->data;
2607 ast_channel_unlock(xferchan);
2610 ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
2613 tobj->chan = newchan;
2614 tobj->peer = xferchan;
2615 tobj->bconfig = *config;
2617 if (tobj->bconfig.end_bridge_callback_data_fixup) {
2618 tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
2622 * xferchan is transferee, and newchan is the transfer target
2623 * So...in a transfer, who is the caller and who is the callee?
2625 * When the call is originally made, it is clear who is caller and callee.
2626 * When a transfer occurs, it is my humble opinion that the transferee becomes
2627 * the caller, and the transfer target is the callee.
2629 * The problem is that these macros were set with the intention of the original
2630 * caller and callee taking those roles. A transfer can totally mess things up,
2631 * to be technical. What sucks even more is that you can't effectively change
2632 * the macros in the dialplan during the call from the transferer to the transfer
2633 * target because the transferee is stuck with whatever role he originally had.
2635 * I think the answer here is just to make sure that it is well documented that
2636 * during a transfer, the transferee is the "caller" and the transfer target
2639 * This means that if party B calls party A, and party B transfers party A to
2640 * party C, then A has switched roles for the call. Now party A will have the
2641 * caller macro called on his channel instead of the callee macro.
2643 * Luckily, the method by which the party B to party C bridge is
2644 * launched above ensures that the transferee is the "chan" on
2645 * the bridge and the transfer target is the "peer," so my idea
2646 * for the roles post-transfer does not require extensive code
2650 /* Transfer party C connected line to party A */
2651 ast_channel_lock(transferer);
2653 * Due to a limitation regarding when callerID is set on a Local channel,
2654 * we use the transferer's connected line information here.
2656 ast_party_connected_line_copy(&connected_line, &transferer->connected);
2657 ast_channel_unlock(transferer);
2658 connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2659 if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
2660 ast_channel_update_connected_line(xferchan, &connected_line, NULL);
2663 /* Transfer party A connected line to party C */
2664 ast_channel_lock(xferchan);
2665 ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
2666 ast_channel_unlock(xferchan);
2667 connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
2668 if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
2669 ast_channel_update_connected_line(newchan, &connected_line, NULL);
2672 if (ast_stream_and_wait(newchan, xfersound, ""))
2673 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
2674 bridge_call_thread_launch(tobj);
2676 ast_party_connected_line_free(&connected_line);
2677 return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
2680 /* add atxfer and automon as undefined so you can only use em if you configure them */
2681 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
2683 AST_RWLOCK_DEFINE_STATIC(features_lock);
2685 static struct ast_call_feature builtin_features[] = {
2686 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2687 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2688 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2689 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2690 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2691 { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
2695 static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
2697 /*! \brief register new feature into feature_list*/
2698 void ast_register_feature(struct ast_call_feature *feature)
2701 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
2705 AST_RWLIST_WRLOCK(&feature_list);
2706 AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
2707 AST_RWLIST_UNLOCK(&feature_list);
2709 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
2713 * \brief Add new feature group
2714 * \param fgname feature group name.
2716 * Add new feature group to the feature group list insert at head of list.
2717 * \note This function MUST be called while feature_groups is locked.
2719 static struct feature_group *register_group(const char *fgname)
2721 struct feature_group *fg;
2724 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
2728 if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
2732 ast_string_field_set(fg, gname, fgname);
2734 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
2736 ast_verb(2, "Registered group '%s'\n", fg->gname);
2742 * \brief Add feature to group
2743 * \param fg feature group
2745 * \param feature feature to add.
2747 * Check fg and feature specified, add feature to list
2748 * \note This function MUST be called while feature_groups is locked.
2750 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
2752 struct feature_group_exten *fge;
2755 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
2760 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
2764 if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
2768 ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
2770 fge->feature = feature;
2772 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
2774 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
2775 feature->sname, fg->gname, fge->exten);
2778 void ast_unregister_feature(struct ast_call_feature *feature)
2784 AST_RWLIST_WRLOCK(&feature_list);
2785 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
2786 AST_RWLIST_UNLOCK(&feature_list);
2791 /*! \brief Remove all features in the list */
2792 static void ast_unregister_features(void)
2794 struct ast_call_feature *feature;
2796 AST_RWLIST_WRLOCK(&feature_list);
2797 while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
2800 AST_RWLIST_UNLOCK(&feature_list);
2803 /*! \brief find a call feature by name */
2804 static struct ast_call_feature *find_dynamic_feature(const char *name)
2806 struct ast_call_feature *tmp;
2808 AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
2809 if (!strcasecmp(tmp->sname, name)) {
2817 /*! \brief Remove all feature groups in the list */
2818 static void ast_unregister_groups(void)
2820 struct feature_group *fg;
2821 struct feature_group_exten *fge;
2823 AST_RWLIST_WRLOCK(&feature_groups);
2824 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
2825 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
2826 ast_string_field_free_memory(fge);
2830 ast_string_field_free_memory(fg);
2833 AST_RWLIST_UNLOCK(&feature_groups);
2837 * \brief Find a group by name
2838 * \param name feature name
2839 * \retval feature group on success.
2840 * \retval NULL on failure.
2842 static struct feature_group *find_group(const char *name)
2844 struct feature_group *fg = NULL;
2846 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
2847 if (!strcasecmp(fg->gname, name))
2854 void ast_rdlock_call_features(void)
2856 ast_rwlock_rdlock(&features_lock);
2859 void ast_unlock_call_features(void)
2861 ast_rwlock_unlock(&features_lock);
2864 struct ast_call_feature *ast_find_call_feature(const char *name)
2867 for (x = 0; x < FEATURES_COUNT; x++) {
2868 if (!strcasecmp(name, builtin_features[x].sname))
2869 return &builtin_features[x];
2875 * \brief exec an app by feature
2876 * \param chan,peer,config,code,sense,data
2878 * Find a feature, determine which channel activated
2879 * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
2881 * \retval -2 when an application cannot be found.
2883 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)
2885 struct ast_app *app;
2886 struct ast_call_feature *feature = data;
2887 struct ast_channel *work, *idle;
2890 if (!feature) { /* shouldn't ever happen! */
2891 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
2895 if (sense == FEATURE_SENSE_CHAN) {
2896 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
2897 return AST_FEATURE_RETURN_KEEPTRYING;
2898 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2906 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
2907 return AST_FEATURE_RETURN_KEEPTRYING;
2908 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
2917 if (!(app = pbx_findapp(feature->app))) {
2918 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
2922 ast_autoservice_start(idle);
2923 ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
2926 pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", idle->name);
2927 pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", work->name);
2928 pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
2929 pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
2932 if (!ast_strlen_zero(feature->moh_class))
2933 ast_moh_start(idle, feature->moh_class, NULL);
2935 res = pbx_exec(work, app, feature->app_args);
2937 if (!ast_strlen_zero(feature->moh_class))
2940 ast_autoservice_stop(idle);
2943 return AST_FEATURE_RETURN_SUCCESSBREAK;
2945 return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
2948 static void unmap_features(void)
2952 ast_rwlock_wrlock(&features_lock);
2953 for (x = 0; x < FEATURES_COUNT; x++)
2954 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
2955 ast_rwlock_unlock(&features_lock);
2958 static int remap_feature(const char *name, const char *value)
2962 ast_rwlock_wrlock(&features_lock);
2963 for (x = 0; x < FEATURES_COUNT; x++) {
2964 if (strcasecmp(builtin_features[x].sname, name))
2967 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
2971 ast_rwlock_unlock(&features_lock);
2977 * \brief Helper function for feature_interpret and ast_feature_detect
2978 * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
2980 * Lock features list, browse for code, unlock list
2981 * If a feature is found and the operation variable is set, that feature's
2982 * operation is executed. The first feature found is copied to the feature parameter.
2983 * \retval res on success.
2984 * \retval -1 on failure.
2986 static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
2987 struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
2988 struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
2991 struct feature_group *fg = NULL;
2992 struct feature_group_exten *fge;
2993 struct ast_call_feature *tmpfeature;
2995 int res = AST_FEATURE_RETURN_PASSDIGITS;
2996 int feature_detected = 0;
2998 if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
2999 return -1; /* can not run feature operation */
3002 ast_rwlock_rdlock(&features_lock);
3003 for (x = 0; x < FEATURES_COUNT; x++) {
3004 if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
3005 !ast_strlen_zero(builtin_features[x].exten)) {
3006 /* Feature is up for consideration */
3007 if (!strcmp(builtin_features[x].exten, code)) {
3008 ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
3009 if (operation == FEATURE_INTERPRET_CHECK) {
3010 res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3011 } else if (operation == FEATURE_INTERPRET_DO) {
3012 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
3015 memcpy(feature, &builtin_features[x], sizeof(feature));
3017 feature_detected = 1;
3019 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
3020 if (res == AST_FEATURE_RETURN_PASSDIGITS) {
3021 res = AST_FEATURE_RETURN_STOREDIGITS;
3026 ast_rwlock_unlock(&features_lock);
3028 if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
3032 tmp = dynamic_features_buf;
3034 while ((tok = strsep(&tmp, "#"))) {
3035 AST_RWLIST_RDLOCK(&feature_groups);
3037 fg = find_group(tok);
3040 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
3041 if (!strcmp(fge->exten, code)) {
3043 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
3045 memcpy(feature, fge->feature, sizeof(feature));
3046 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3047 AST_RWLIST_UNLOCK(&feature_groups);
3050 res = AST_FEATURE_RETURN_PASSDIGITS;
3051 } else if (!strncmp(fge->exten, code, strlen(code))) {
3052 res = AST_FEATURE_RETURN_STOREDIGITS;
3060 AST_RWLIST_UNLOCK(&feature_groups);
3062 AST_RWLIST_RDLOCK(&feature_list);
3064 if (!(tmpfeature = find_dynamic_feature(tok))) {
3065 AST_RWLIST_UNLOCK(&feature_list);
3069 /* Feature is up for consideration */
3070 if (!strcmp(tmpfeature->exten, code)) {
3071 ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
3072 if (operation == FEATURE_INTERPRET_CHECK) {
3073 res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
3074 } else if (operation == FEATURE_INTERPRET_DO) {
3075 res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
3078 memcpy(feature, tmpfeature, sizeof(feature));
3080 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
3081 AST_RWLIST_UNLOCK(&feature_list);
3084 res = AST_FEATURE_RETURN_PASSDIGITS;
3085 } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
3086 res = AST_FEATURE_RETURN_STOREDIGITS;
3088 AST_RWLIST_UNLOCK(&feature_list);