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>
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include "asterisk/_private.h"
34 #include <sys/signal.h>
35 #include <netinet/in.h>
37 #include "asterisk/lock.h"
38 #include "asterisk/file.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/causes.h"
42 #include "asterisk/module.h"
43 #include "asterisk/translate.h"
44 #include "asterisk/app.h"
45 #include "asterisk/say.h"
46 #include "asterisk/features.h"
47 #include "asterisk/musiconhold.h"
48 #include "asterisk/config.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/manager.h"
51 #include "asterisk/utils.h"
52 #include "asterisk/adsi.h"
53 #include "asterisk/devicestate.h"
54 #include "asterisk/monitor.h"
55 #include "asterisk/audiohook.h"
56 #include "asterisk/global_datastores.h"
57 #include "asterisk/astobj2.h"
60 <application name="Bridge" language="en_US">
65 <parameter name="channel" required="true">
66 <para>The current channel is bridged to the specified <replaceable>channel</replaceable>.</para>
68 <parameter name="options">
71 <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
77 <para>Allows the ability to bridge two channels via the dialplan.</para>
78 <para>This application sets the following channel variable upon completion:</para>
80 <variable name="BRIDGERESULT">
81 <para>The result of the bridge attempt as a text string.</para>
82 <value name="SUCCESS" />
83 <value name="FAILURE" />
85 <value name="NONEXISTENT" />
86 <value name="INCOMPATIBLE" />
91 <application name="ParkedCall" language="en_US">
96 <parameter name="exten" required="true" />
99 <para>Used to connect to a parked call. This application is always
100 registered internally and does not need to be explicitly added
101 into the dialplan, although you should include the <literal>parkedcalls</literal>
102 context. If no extension is provided, then the first available
103 parked call will be acquired.</para>
106 <ref type="application">Park</ref>
107 <ref type="application">ParkAndAnnounce</ref>
110 <application name="Park" language="en_US">
115 <parameter name="timeout">
116 <para>A custom parking timeout for this parked call.</para>
118 <parameter name="return_context">
119 <para>The context to return the call to after it times out.</para>
121 <parameter name="return_exten">
122 <para>The extension to return the call to after it times out.</para>
124 <parameter name="return_priority">
125 <para>The priority to return the call to after it times out.</para>
127 <parameter name="options">
128 <para>A list of options for this parked call.</para>
131 <para>Send ringing instead of MOH to the parked call.</para>
134 <para>Randomize the selection of a parking space.</para>
137 <para>Silence announcement of the parking space number.</para>
143 <para>Used to park yourself (typically in combination with a supervised
144 transfer to know the parking space). This application is always
145 registered internally and does not need to be explicitly added
146 into the dialplan, although you should include the <literal>parkedcalls</literal>
147 context (or the context specified in <filename>features.conf</filename>).</para>
148 <para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
149 parking context, Park() will park the call on that extension, unless
150 it already exists. In that case, execution will continue at next priority.</para>
153 <ref type="application">ParkAndAnnounce</ref>
154 <ref type="application">ParkedCall</ref>
159 #define DEFAULT_PARK_TIME 45000
160 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
161 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 2000
162 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
163 #define DEFAULT_PARKINGLOT "default" /*!< Default parking lot */
164 #define DEFAULT_ATXFER_DROP_CALL 0
165 #define DEFAULT_ATXFER_LOOP_DELAY 10000
166 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
168 #define AST_MAX_WATCHERS 256
170 struct feature_group_exten {
171 AST_LIST_ENTRY(feature_group_exten) entry;
172 AST_DECLARE_STRING_FIELDS(
173 AST_STRING_FIELD(exten);
175 struct ast_call_feature *feature;
178 struct feature_group {
179 AST_LIST_ENTRY(feature_group) entry;
180 AST_DECLARE_STRING_FIELDS(
181 AST_STRING_FIELD(gname);
183 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
186 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
188 static char *parkedcall = "ParkedCall";
190 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
192 /*! \brief Description of one parked call, added to a list while active, then removed.
193 The list belongs to a parkinglot
196 struct ast_channel *chan; /*!< Parking channel */
197 struct timeval start; /*!< Time the parking started */
198 int parkingnum; /*!< Parking lot */
199 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
200 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
201 char exten[AST_MAX_EXTENSION];
203 int parkingtime; /*!< Maximum length in parking lot before return */
206 unsigned char moh_trys;
207 struct ast_parkinglot *parkinglot;
208 AST_LIST_ENTRY(parkeduser) list;
211 /*! \brief Structure for parking lots which are put in a container. */
212 struct ast_parkinglot {
213 char name[AST_MAX_CONTEXT];
214 char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
215 char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
216 int parking_start; /*!< First available extension for parking */
217 int parking_stop; /*!< Last available extension for parking */
220 int parkingtime; /*!< Default parking time */
221 char mohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
222 int parkaddhints; /*!< Add parking hints automatically */
223 int parkedcalltransfers; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
224 int parkedcallreparking; /*!< Enable DTMF based parking on bridge when picking up parked calls */
225 AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
228 /*! \brief The list of parking lots configured. Always at least one - the default parking lot */
229 static struct ao2_container *parkinglots;
231 struct ast_parkinglot *default_parkinglot;
232 char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
234 static char courtesytone[256]; /*!< Courtesy tone */
235 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
236 static char xfersound[256]; /*!< Call transfer sound */
237 static char xferfailsound[256]; /*!< Call transfer failure sound */
241 static int transferdigittimeout;
242 static int featuredigittimeout;
243 static int comebacktoorigin = 1;
245 static int atxfernoanswertimeout;
246 static unsigned int atxferdropcall;
247 static unsigned int atxferloopdelay;
248 static unsigned int atxfercallbackretries;
250 static char *registrar = "features"; /*!< Registrar for operations */
252 /* module and CLI command definitions */
253 static char *parkcall = PARK_APP_NAME;
255 static struct ast_app *monitor_app = NULL;
256 static int monitor_ok = 1;
258 static struct ast_app *mixmonitor_app = NULL;
259 static int mixmonitor_ok = 1;
261 static struct ast_app *stopmixmonitor_app = NULL;
262 static int stopmixmonitor_ok = 1;
264 static pthread_t parking_thread;
266 /* Forward declarations */
267 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
268 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
269 static void parkinglot_destroy(void *obj);
270 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
271 struct ast_parkinglot *find_parkinglot(const char *name);
274 const char *ast_parking_ext(void)
279 const char *ast_pickup_ext(void)
284 struct ast_bridge_thread_obj
286 struct ast_bridge_config bconfig;
287 struct ast_channel *chan;
288 struct ast_channel *peer;
289 unsigned int return_to_pbx:1;
292 static int parkinglot_hash_cb(const void *obj, const int flags)
294 const struct ast_parkinglot *parkinglot = obj;
295 return ast_str_hash(parkinglot->name);
298 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
300 struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
301 return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
305 * \brief store context, extension and priority
306 * \param chan, context, ext, pri
308 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
310 ast_copy_string(chan->context, context, sizeof(chan->context));
311 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
312 chan->priority = pri;
316 * \brief Check goto on transfer
319 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
320 * When found make sure the types are compatible. Check if channel is valid
321 * if so start the new channel else hangup the call.
323 static void check_goto_on_transfer(struct ast_channel *chan)
325 struct ast_channel *xferchan;
326 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
327 char *x, *goto_on_transfer;
330 if (ast_strlen_zero(val))
333 goto_on_transfer = ast_strdupa(val);
335 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
338 for (x = goto_on_transfer; x && *x; x++) {
342 /* Make formats okay */
343 xferchan->readformat = chan->readformat;
344 xferchan->writeformat = chan->writeformat;
345 ast_channel_masquerade(xferchan, chan);
346 ast_parseable_goto(xferchan, goto_on_transfer);
347 xferchan->_state = AST_STATE_UP;
348 ast_clear_flag(xferchan, AST_FLAGS_ALL);
349 xferchan->_softhangup = 0;
350 if ((f = ast_read(xferchan))) {
353 ast_pbx_start(xferchan);
355 ast_hangup(xferchan);
359 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language);
362 * \brief bridge the call
363 * \param data thread bridge.
365 * Set Last Data for respective channels, reset cdr for channels
366 * bridge call, check if we're going back to dialplan
367 * if not hangup both legs of the call
369 static void *ast_bridge_call_thread(void *data)
371 struct ast_bridge_thread_obj *tobj = data;
374 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
375 tobj->chan->data = tobj->peer->name;
376 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
377 tobj->peer->data = tobj->chan->name;
379 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
381 if (tobj->return_to_pbx) {
382 if (!ast_check_hangup(tobj->peer)) {
383 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
384 res = ast_pbx_start(tobj->peer);
385 if (res != AST_PBX_SUCCESS)
386 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
388 ast_hangup(tobj->peer);
389 if (!ast_check_hangup(tobj->chan)) {
390 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
391 res = ast_pbx_start(tobj->chan);
392 if (res != AST_PBX_SUCCESS)
393 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
395 ast_hangup(tobj->chan);
397 ast_hangup(tobj->chan);
398 ast_hangup(tobj->peer);
407 * \brief create thread for the parked call
410 * Create thread and attributes, call ast_bridge_call_thread
412 static void ast_bridge_call_thread_launch(void *data)
416 struct sched_param sched;
418 pthread_attr_init(&attr);
419 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
420 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
421 pthread_attr_destroy(&attr);
422 memset(&sched, 0, sizeof(sched));
423 pthread_setschedparam(thread, SCHED_RR, &sched);
427 * \brief Announce call parking by ADSI
429 * \param parkingexten .
430 * Create message to show for ADSI, display message.
431 * \retval 0 on success.
432 * \retval -1 on failure.
434 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
437 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
439 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
441 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
443 res = ast_adsi_load_session(chan, NULL, 0, 1);
446 return ast_adsi_print(chan, message, justify, 1);
449 /*! \brief Find parking lot name from channel */
450 static const char *findparkinglotname(struct ast_channel *chan)
452 const char *temp, *parkinglot = NULL;
454 /* Check if the channel has a parking lot */
455 if (!ast_strlen_zero(chan->parkinglot))
456 parkinglot = chan->parkinglot;
458 /* Channel variables override everything */
460 if ((temp = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
466 /*! \brief Notify metermaids that we've changed an extension */
467 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
469 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
470 exten, context, ast_devstate2str(state));
472 ast_devstate_changed(state, "park:%s@%s", exten, context);
475 /*! \brief metermaids callback from devicestate.c */
476 static enum ast_device_state metermaidstate(const char *data)
481 context = ast_strdupa(data);
483 exten = strsep(&context, "@");
485 return AST_DEVICE_INVALID;
487 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
489 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
490 return AST_DEVICE_NOT_INUSE;
492 return AST_DEVICE_INUSE;
495 /*! Options to pass to ast_park_call_full */
496 enum ast_park_call_options {
497 /*! Provide ringing to the parked caller instead of music on hold */
498 AST_PARK_OPT_RINGING = (1 << 0),
499 /*! Randomly choose a parking spot for the caller instead of choosing
500 * the first one that is available. */
501 AST_PARK_OPT_RANDOMIZE = (1 << 1),
502 /*! Do not announce the parking number */
503 AST_PARK_OPT_SILENCE = (1 << 2),
506 struct ast_park_call_args {
507 /*! How long to wait in the parking lot before the call gets sent back
508 * to the specified return extension (or a best guess at where it came
509 * from if not explicitly specified). */
511 /*! An output parameter to store the parking space where the parked caller
514 const char *orig_chan_name;
515 const char *return_con;
516 const char *return_ext;
522 static int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer,
523 struct ast_park_call_args *args)
525 struct parkeduser *pu;
526 int i, x = -1, parking_range, parkingnum_copy;
527 struct ast_context *con;
528 const char *parkinglotname = NULL;
529 const char *parkingexten;
530 struct ast_parkinglot *parkinglot = NULL;
533 parkinglotname = findparkinglotname(peer);
535 if (parkinglotname) {
537 ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
538 parkinglot = find_parkinglot(parkinglotname);
541 parkinglot = default_parkinglot;
543 parkinglot_addref(parkinglot);
545 ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
547 /* Allocate memory for parking data */
548 if (!(pu = ast_calloc(1, sizeof(*pu)))) {
549 parkinglot_unref(parkinglot);
553 /* Lock parking list */
554 AST_LIST_LOCK(&parkinglot->parkings);
555 /* Check for channel variable PARKINGEXTEN */
556 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
557 if (!ast_strlen_zero(parkingexten)) {
558 /*!\note The API forces us to specify a numeric parking slot, even
559 * though the architecture would tend to support non-numeric extensions
560 * (as are possible with SIP, for example). Hence, we enforce that
561 * limitation here. If extout was not numeric, we could permit
562 * arbitrary non-numeric extensions.
564 if (sscanf(parkingexten, "%d", &x) != 1 || x < 0) {
565 AST_LIST_UNLOCK(&parkinglot->parkings);
566 parkinglot_unref(parkinglot);
568 ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
569 return 1; /* Continue execution if possible */
571 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
573 if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
574 AST_LIST_UNLOCK(&parkinglot->parkings);
575 parkinglot_unref(parkinglot);
577 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
578 return 1; /* Continue execution if possible */
582 struct parkeduser *cur = NULL;
584 /* Select parking space within range */
585 parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
587 if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
588 start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
590 start = parkinglot->parking_start;
593 for (i = start; 1; i++) {
594 if (i == parkinglot->parking_stop + 1) {
595 i = parkinglot->parking_start - 1;
599 AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
600 if (cur->parkingnum == i) {
605 if (!cur || i == start - 1) {
611 if (i == start - 1 && cur) {
612 ast_log(LOG_WARNING, "No more parking spaces\n");
614 AST_LIST_UNLOCK(&parkinglot->parkings);
615 parkinglot_unref(parkinglot);
618 /* Set pointer for next parking */
619 if (parkinglot->parkfindnext)
620 parkinglot->parking_offset = x - parkinglot->parking_start + 1;
621 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
624 chan->appl = "Parked Call";
629 /* Put the parked channel on hold if we have two different channels */
631 if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
632 ast_indicate(pu->chan, AST_CONTROL_RINGING);
634 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
635 S_OR(parkinglot->mohclass, NULL),
636 !ast_strlen_zero(parkinglot->mohclass) ? strlen(parkinglot->mohclass) + 1 : 0);
640 pu->start = ast_tvnow();
642 pu->parkinglot = parkinglot;
643 pu->parkingtime = (args->timeout > 0) ? args->timeout : parkinglot->parkingtime;
644 parkingnum_copy = pu->parkingnum;
649 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
651 /* Remember what had been dialed, so that if the parking
652 expires, we try to come back to the same place */
653 ast_copy_string(pu->context,
654 S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)),
655 sizeof(pu->context));
656 ast_copy_string(pu->exten,
657 S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)),
659 pu->priority = pu->priority ? pu->priority :
660 (chan->macropriority ? chan->macropriority : chan->priority);
662 AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
664 /* If parking a channel directly, don't quiet yet get parking running on it */
668 /* Wake up the (presumably select()ing) thread */
669 pthread_kill(parking_thread, SIGURG);
670 ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
672 manager_event(EVENT_FLAG_CALL, "ParkedCall",
678 "CallerIDNum: %s\r\n"
679 "CallerIDName: %s\r\n"
681 pu->parkingexten, pu->chan->name, pu->parkinglot->name, peer ? peer->name : "",
682 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
683 S_OR(pu->chan->cid.cid_num, "<unknown>"),
684 S_OR(pu->chan->cid.cid_name, "<unknown>"),
688 if (peer && adsipark && ast_adsi_available(peer)) {
689 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
690 ast_adsi_unload_session(peer);
693 con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar);
694 if (!con) /* Still no context? Bad */
695 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
697 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
698 notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_INUSE);
701 AST_LIST_UNLOCK(&parkinglot->parkings);
703 /* Only say number if it's a number and the channel hasn't been masqueraded away */
704 if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE) && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) {
705 /* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
706 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
707 /* Tell the peer channel the number of the parking space */
708 ast_say_digits(peer, pu->parkingnum, "", peer->language);
709 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
711 if (peer == chan) { /* pu->notquiteyet = 1 */
712 /* Wake up parking thread if we're really done */
713 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
714 S_OR(parkinglot->mohclass, NULL),
715 !ast_strlen_zero(parkinglot->mohclass) ? strlen(parkinglot->mohclass) + 1 : 0);
717 pthread_kill(parking_thread, SIGURG);
722 /*! \brief Park a call */
723 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
725 struct ast_park_call_args args = {
730 return ast_park_call_full(chan, peer, &args);
733 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement)
735 struct ast_channel *chan;
737 char *orig_chan_name = NULL;
740 /* Make a new, fake channel that we'll use to masquerade in the real one */
741 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
742 ast_log(LOG_WARNING, "Unable to create parked channel\n");
746 /* Make formats okay */
747 chan->readformat = rchan->readformat;
748 chan->writeformat = rchan->writeformat;
749 ast_channel_masquerade(chan, rchan);
751 /* Setup the extensions and such */
752 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
754 /* Make the masq execute */
755 if ((f = ast_read(chan)))
758 if (!play_announcement) {
759 orig_chan_name = ast_strdupa(chan->name);
763 struct ast_park_call_args args = {
766 .orig_chan_name = orig_chan_name,
769 park_status = ast_park_call_full(chan, peer, &args);
770 if (park_status == 1) {
771 /* would be nice to play "invalid parking extension" */
780 /* Park call via masquraded channel */
781 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
783 return masq_park_call(rchan, peer, timeout, extout, 0);
786 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
788 return masq_park_call(rchan, peer, timeout, extout, 1);
793 #define FEATURE_SENSE_CHAN (1 << 0)
794 #define FEATURE_SENSE_PEER (1 << 1)
797 * \brief set caller and callee according to the direction
798 * \param caller, callee, peer, chan, sense
800 * Detect who triggered feature and set callee/caller variables accordingly
802 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
803 struct ast_channel *peer, struct ast_channel *chan, int sense)
805 if (sense == FEATURE_SENSE_PEER) {
815 * \brief support routing for one touch call parking
816 * \param chan channel parking call
817 * \param peer channel to be parked
818 * \param config unsed
820 * \param sense feature options
823 * Setup channel, set return exten,priority to 's,1'
824 * answer chan, sleep chan, park call
826 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
828 struct ast_channel *parker;
829 struct ast_channel *parkee;
832 set_peers(&parker, &parkee, peer, chan, sense);
833 /* Setup the exten/priority to be s/1 since we don't know
834 where this call should return */
835 strcpy(chan->exten, "s");
837 if (chan->_state != AST_STATE_UP)
838 res = ast_answer(chan);
840 res = ast_safe_sleep(chan, 1000);
843 if (sense == FEATURE_SENSE_CHAN) {
844 res = ast_park_call(parkee, parker, 0, NULL);
846 if (sense == FEATURE_SENSE_CHAN) {
847 res = AST_PBX_NO_HANGUP_PEER_PARKED;
849 res = AST_PBX_KEEPALIVE;
852 } else if (sense == FEATURE_SENSE_PEER) {
853 masq_park_call_announce(parkee, parker, 0, NULL);
854 res = 0; /* PBX should hangup zombie channel */
862 /*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
863 other channel during the message, so please don't use this for very long messages
865 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
867 /* First play for caller, put other channel on auto service */
868 if (ast_autoservice_start(callee_chan))
870 if (ast_stream_and_wait(caller_chan, audiofile, "")) {
871 ast_log(LOG_WARNING, "Failed to play automon message!\n");
872 ast_autoservice_stop(callee_chan);
875 if (ast_autoservice_stop(callee_chan))
877 /* Then play for callee, put other channel on auto service */
878 if (ast_autoservice_start(caller_chan))
880 if (ast_stream_and_wait(callee_chan, audiofile, "")) {
881 ast_log(LOG_WARNING, "Failed to play automon message !\n");
882 ast_autoservice_stop(caller_chan);
885 if (ast_autoservice_stop(caller_chan))
891 * \brief Monitor a channel by DTMF
892 * \param chan channel requesting monitor
893 * \param peer channel to be monitored
896 * \param sense feature options
899 * Check monitor app enabled, setup channels, both caller/callee chans not null
900 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
901 * \retval AST_FEATURE_RETURN_SUCCESS on success.
902 * \retval -1 on error.
904 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
906 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
909 struct ast_channel *caller_chan, *callee_chan;
910 const char *automon_message_start = NULL;
911 const char *automon_message_stop = NULL;
914 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
918 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
920 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
924 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
925 if (caller_chan) { /* Find extra messages */
926 automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
927 automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
930 if (!ast_strlen_zero(courtesytone)) { /* Play courtesy tone if configured */
931 if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
936 if (callee_chan->monitor) {
937 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
938 if (!ast_strlen_zero(automon_message_stop)) {
939 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
941 callee_chan->monitor->stop(callee_chan, 1);
942 return AST_FEATURE_RETURN_SUCCESS;
945 if (caller_chan && callee_chan) {
946 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
947 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
948 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
951 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
954 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
956 if (!touch_monitor_prefix)
957 touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
960 len = strlen(touch_monitor) + 50;
962 touch_filename = alloca(len);
963 snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
964 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
966 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
967 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
968 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
970 touch_filename = alloca(len);
971 snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
972 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
975 for(x = 0; x < strlen(args); x++) {
980 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
982 pbx_exec(callee_chan, monitor_app, args);
983 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
984 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
986 if (!ast_strlen_zero(automon_message_start)) { /* Play start message for both channels */
987 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
990 return AST_FEATURE_RETURN_SUCCESS;
993 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
997 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
999 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
1002 struct ast_channel *caller_chan, *callee_chan;
1003 const char *mixmonitor_spy_type = "MixMonitor";
1006 if (!mixmonitor_ok) {
1007 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1011 if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
1013 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
1017 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
1019 if (!ast_strlen_zero(courtesytone)) {
1020 if (ast_autoservice_start(callee_chan))
1022 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
1023 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1024 ast_autoservice_stop(callee_chan);
1027 if (ast_autoservice_stop(callee_chan))
1031 ast_channel_lock(callee_chan);
1032 count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1033 ast_channel_unlock(callee_chan);
1035 /* This means a mixmonitor is attached to the channel, running or not is unknown. */
1038 ast_verb(3, "User hit '%s' to stop recording call.\n", code);
1040 /* Make sure they are running */
1041 ast_channel_lock(callee_chan);
1042 count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
1043 ast_channel_unlock(callee_chan);
1045 if (!stopmixmonitor_ok) {
1046 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
1049 if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
1050 stopmixmonitor_ok = 0;
1051 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
1054 pbx_exec(callee_chan, stopmixmonitor_app, "");
1055 return AST_FEATURE_RETURN_SUCCESS;
1059 ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
1062 if (caller_chan && callee_chan) {
1063 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
1064 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
1067 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
1070 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
1072 if (touch_monitor) {
1073 len = strlen(touch_monitor) + 50;
1075 touch_filename = alloca(len);
1076 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
1077 snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
1079 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
1080 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
1081 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
1083 touch_filename = alloca(len);
1084 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
1085 snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
1088 for( x = 0; x < strlen(args); x++) {
1093 ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
1095 pbx_exec(callee_chan, mixmonitor_app, args);
1096 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1097 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1098 return AST_FEATURE_RETURN_SUCCESS;
1102 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
1107 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1109 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
1110 return AST_FEATURE_RETURN_HANGUP;
1113 static int finishup(struct ast_channel *chan)
1115 ast_indicate(chan, AST_CONTROL_UNHOLD);
1117 return ast_autoservice_stop(chan);
1121 * \brief Find the context for the transfer
1125 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
1126 * \return a context string
1128 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
1130 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
1131 if (ast_strlen_zero(s)) {
1132 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
1134 if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
1135 s = transferer->macrocontext;
1137 if (ast_strlen_zero(s)) {
1138 s = transferer->context;
1144 * \brief Blind transfer user to another extension
1145 * \param chan channel to be transfered
1146 * \param peer channel initiated blind transfer
1150 * \param sense feature options
1152 * Place chan on hold, check if transferred to parkinglot extension,
1153 * otherwise check extension exists and transfer caller.
1154 * \retval AST_FEATURE_RETURN_SUCCESS.
1155 * \retval -1 on failure.
1157 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1159 struct ast_channel *transferer;
1160 struct ast_channel *transferee;
1161 const char *transferer_real_context;
1165 set_peers(&transferer, &transferee, peer, chan, sense);
1166 transferer_real_context = real_ctx(transferer, transferee);
1167 /* Start autoservice on chan while we talk to the originator */
1168 ast_autoservice_start(transferee);
1169 ast_indicate(transferee, AST_CONTROL_HOLD);
1171 memset(xferto, 0, sizeof(xferto));
1174 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1176 finishup(transferee);
1177 return -1; /* error ? */
1179 if (res > 0) /* If they've typed a digit already, handle it */
1180 xferto[0] = (char) res;
1182 ast_stopstream(transferer);
1183 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1184 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
1185 finishup(transferee);
1188 if (!strcmp(xferto, ast_parking_ext())) {
1189 res = finishup(transferee);
1192 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
1193 /* We return non-zero, but tell the PBX not to hang the channel when
1194 the thread dies -- We have to be careful now though. We are responsible for
1195 hanging up the channel, else it will never be hung up! */
1197 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER_PARKED;
1199 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
1201 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
1202 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
1203 pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
1204 pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
1205 res=finishup(transferee);
1206 if (!transferer->cdr) {
1207 transferer->cdr=ast_cdr_alloc();
1209 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
1210 ast_cdr_start(transferer->cdr);
1213 if (transferer->cdr) {
1214 ast_cdr_setdestchan(transferer->cdr, transferee->name);
1215 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
1217 if (!transferee->pbx) {
1218 /* Doh! Use our handy async_goto functions */
1219 ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
1220 ,transferee->name, xferto, transferer_real_context);
1221 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
1222 ast_log(LOG_WARNING, "Async goto failed :-(\n");
1224 /* Set the channel's new extension, since it exists, using transferer context */
1225 set_c_e_p(transferee, transferer_real_context, xferto, 0);
1227 check_goto_on_transfer(transferer);
1230 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
1232 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
1233 finishup(transferee);
1236 ast_stopstream(transferer);
1237 res = finishup(transferee);
1239 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
1242 return AST_FEATURE_RETURN_SUCCESS;
1246 * \brief make channels compatible
1249 * \retval 0 on success.
1250 * \retval -1 on failure.
1252 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
1254 if (ast_channel_make_compatible(c, newchan) < 0) {
1255 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
1256 c->name, newchan->name);
1257 ast_hangup(newchan);
1264 * \brief Attended transfer
1265 * \param chan transfered user
1266 * \param peer person transfering call
1269 * \param sense feature options
1272 * Get extension to transfer to, if you cannot generate channel (or find extension)
1273 * return to host channel. After called channel answered wait for hangup of transferer,
1274 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
1276 * \return -1 on failure
1278 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1280 struct ast_channel *transferer;
1281 struct ast_channel *transferee;
1282 const char *transferer_real_context;
1283 char xferto[256] = "";
1286 struct ast_channel *newchan;
1287 struct ast_channel *xferchan;
1288 struct ast_bridge_thread_obj *tobj;
1289 struct ast_bridge_config bconfig;
1290 struct ast_frame *f;
1293 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
1294 set_peers(&transferer, &transferee, peer, chan, sense);
1295 transferer_real_context = real_ctx(transferer, transferee);
1296 /* Start autoservice on chan while we talk to the originator */
1297 ast_autoservice_start(transferee);
1298 ast_indicate(transferee, AST_CONTROL_HOLD);
1301 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1303 finishup(transferee);
1306 if (res > 0) /* If they've typed a digit already, handle it */
1307 xferto[0] = (char) res;
1309 /* this is specific of atxfer */
1310 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1311 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
1312 finishup(transferee);
1316 ast_log(LOG_WARNING, "Did not read data.\n");
1317 finishup(transferee);
1318 if (ast_stream_and_wait(transferer, "beeperr", ""))
1320 return AST_FEATURE_RETURN_SUCCESS;
1323 /* valid extension, res == 1 */
1324 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
1325 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
1326 finishup(transferee);
1327 if (ast_stream_and_wait(transferer, "beeperr", ""))
1329 return AST_FEATURE_RETURN_SUCCESS;
1333 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
1335 /* If we are performing an attended transfer and we have two channels involved then
1336 copy sound file information to play upon attended transfer completion */
1338 const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
1339 const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
1341 if (!ast_strlen_zero(chan1_attended_sound)) {
1342 pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
1344 if (!ast_strlen_zero(chan2_attended_sound)) {
1345 pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
1349 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1350 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1352 if (!ast_check_hangup(transferer)) {
1353 /* Transferer is up - old behaviour */
1354 ast_indicate(transferer, -1);
1356 finishup(transferee);
1357 /* any reason besides user requested cancel and busy triggers the failed sound */
1358 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
1359 ast_stream_and_wait(transferer, xferfailsound, ""))
1361 if (ast_stream_and_wait(transferer, xfersound, ""))
1362 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1363 return AST_FEATURE_RETURN_SUCCESS;
1366 if (check_compat(transferer, newchan)) {
1367 /* we do mean transferee here, NOT transferer */
1368 finishup(transferee);
1371 memset(&bconfig,0,sizeof(struct ast_bridge_config));
1372 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
1373 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
1374 res = ast_bridge_call(transferer, newchan, &bconfig);
1375 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
1376 ast_hangup(newchan);
1377 if (ast_stream_and_wait(transferer, xfersound, ""))
1378 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1379 finishup(transferee);
1380 transferer->_softhangup = 0;
1381 return AST_FEATURE_RETURN_SUCCESS;
1383 if (check_compat(transferee, newchan)) {
1384 finishup(transferee);
1387 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1389 if ((ast_autoservice_stop(transferee) < 0)
1390 || (ast_waitfordigit(transferee, 100) < 0)
1391 || (ast_waitfordigit(newchan, 100) < 0)
1392 || ast_check_hangup(transferee)
1393 || ast_check_hangup(newchan)) {
1394 ast_hangup(newchan);
1397 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1399 ast_hangup(newchan);
1402 /* Make formats okay */
1403 xferchan->visible_indication = transferer->visible_indication;
1404 xferchan->readformat = transferee->readformat;
1405 xferchan->writeformat = transferee->writeformat;
1406 ast_channel_masquerade(xferchan, transferee);
1407 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1408 xferchan->_state = AST_STATE_UP;
1409 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1410 xferchan->_softhangup = 0;
1411 if ((f = ast_read(xferchan)))
1413 newchan->_state = AST_STATE_UP;
1414 ast_clear_flag(newchan, AST_FLAGS_ALL);
1415 newchan->_softhangup = 0;
1416 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1417 ast_hangup(xferchan);
1418 ast_hangup(newchan);
1421 tobj->chan = newchan;
1422 tobj->peer = xferchan;
1423 tobj->bconfig = *config;
1425 if (ast_stream_and_wait(newchan, xfersound, ""))
1426 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1427 ast_bridge_call_thread_launch(tobj);
1428 return -1; /* XXX meaning the channel is bridged ? */
1429 } else if (!ast_check_hangup(transferee)) {
1430 /* act as blind transfer */
1431 if (ast_autoservice_stop(transferee) < 0) {
1432 ast_hangup(newchan);
1437 unsigned int tries = 0;
1438 char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
1440 transferer_tech = strsep(&transferer_name, "/");
1441 transferer_name = strsep(&transferer_name, "-");
1443 if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
1444 ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
1445 if (ast_stream_and_wait(transferee, "beeperr", ""))
1447 return AST_FEATURE_RETURN_SUCCESS;
1450 ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
1451 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1452 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1453 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1454 /* Trying to transfer again */
1455 ast_autoservice_start(transferee);
1456 ast_indicate(transferee, AST_CONTROL_HOLD);
1458 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1459 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1460 if (ast_autoservice_stop(transferee) < 0) {
1462 ast_hangup(newchan);
1466 /* Transfer failed, sleeping */
1467 ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1468 ast_safe_sleep(transferee, atxferloopdelay);
1469 ast_debug(1, "Trying to callback...\n");
1470 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1471 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1479 /* newchan is up, we should prepare transferee and bridge them */
1480 if (check_compat(transferee, newchan)) {
1481 finishup(transferee);
1484 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1486 if ((ast_waitfordigit(transferee, 100) < 0)
1487 || (ast_waitfordigit(newchan, 100) < 0)
1488 || ast_check_hangup(transferee)
1489 || ast_check_hangup(newchan)) {
1490 ast_hangup(newchan);
1494 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1496 ast_hangup(newchan);
1499 /* Make formats okay */
1500 xferchan->visible_indication = transferer->visible_indication;
1501 xferchan->readformat = transferee->readformat;
1502 xferchan->writeformat = transferee->writeformat;
1503 ast_channel_masquerade(xferchan, transferee);
1504 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1505 xferchan->_state = AST_STATE_UP;
1506 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1507 xferchan->_softhangup = 0;
1508 if ((f = ast_read(xferchan)))
1510 newchan->_state = AST_STATE_UP;
1511 ast_clear_flag(newchan, AST_FLAGS_ALL);
1512 newchan->_softhangup = 0;
1513 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1514 ast_hangup(xferchan);
1515 ast_hangup(newchan);
1518 tobj->chan = newchan;
1519 tobj->peer = xferchan;
1520 tobj->bconfig = *config;
1522 if (ast_stream_and_wait(newchan, xfersound, ""))
1523 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1524 ast_bridge_call_thread_launch(tobj);
1525 return -1; /* XXX meaning the channel is bridged ? */
1527 /* Transferee hung up */
1528 finishup(transferee);
1533 /* add atxfer and automon as undefined so you can only use em if you configure them */
1534 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1536 AST_RWLOCK_DEFINE_STATIC(features_lock);
1538 static struct ast_call_feature builtin_features[] =
1540 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1541 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1542 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1543 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1544 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1545 { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1549 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1551 /*! \brief register new feature into feature_list*/
1552 void ast_register_feature(struct ast_call_feature *feature)
1555 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1559 AST_LIST_LOCK(&feature_list);
1560 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1561 AST_LIST_UNLOCK(&feature_list);
1563 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1567 * \brief Add new feature group
1568 * \param fgname feature group name.
1570 * Add new feature group to the feature group list insert at head of list.
1571 * \note This function MUST be called while feature_groups is locked.
1573 static struct feature_group* register_group(const char *fgname)
1575 struct feature_group *fg;
1578 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1582 if (!(fg = ast_calloc(1, sizeof(*fg))))
1585 if (ast_string_field_init(fg, 128)) {
1590 ast_string_field_set(fg, gname, fgname);
1592 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1594 ast_verb(2, "Registered group '%s'\n", fg->gname);
1600 * \brief Add feature to group
1601 * \param fg feature group
1603 * \param feature feature to add.
1605 * Check fg and feature specified, add feature to list
1606 * \note This function MUST be called while feature_groups is locked.
1608 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
1610 struct feature_group_exten *fge;
1613 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1618 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1622 if (!(fge = ast_calloc(1, sizeof(*fge))))
1625 if (ast_string_field_init(fge, 128)) {
1630 ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
1632 fge->feature = feature;
1634 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
1636 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1637 feature->sname, fg->gname, exten);
1640 void ast_unregister_feature(struct ast_call_feature *feature)
1645 AST_LIST_LOCK(&feature_list);
1646 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1647 AST_LIST_UNLOCK(&feature_list);
1651 /*! \brief Remove all features in the list */
1652 static void ast_unregister_features(void)
1654 struct ast_call_feature *feature;
1656 AST_LIST_LOCK(&feature_list);
1657 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1659 AST_LIST_UNLOCK(&feature_list);
1662 /*! \brief find a call feature by name */
1663 static struct ast_call_feature *find_dynamic_feature(const char *name)
1665 struct ast_call_feature *tmp;
1667 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1668 if (!strcasecmp(tmp->sname, name))
1675 /*! \brief Remove all feature groups in the list */
1676 static void ast_unregister_groups(void)
1678 struct feature_group *fg;
1679 struct feature_group_exten *fge;
1681 AST_RWLIST_WRLOCK(&feature_groups);
1682 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1683 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1684 ast_string_field_free_memory(fge);
1688 ast_string_field_free_memory(fg);
1691 AST_RWLIST_UNLOCK(&feature_groups);
1695 * \brief Find a group by name
1696 * \param name feature name
1697 * \retval feature group on success.
1698 * \retval NULL on failure.
1700 static struct feature_group *find_group(const char *name) {
1701 struct feature_group *fg = NULL;
1703 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1704 if (!strcasecmp(fg->gname, name))
1711 void ast_rdlock_call_features(void)
1713 ast_rwlock_rdlock(&features_lock);
1716 void ast_unlock_call_features(void)
1718 ast_rwlock_unlock(&features_lock);
1721 struct ast_call_feature *ast_find_call_feature(const char *name)
1724 for (x = 0; x < FEATURES_COUNT; x++) {
1725 if (!strcasecmp(name, builtin_features[x].sname))
1726 return &builtin_features[x];
1732 * \brief exec an app by feature
1733 * \param chan,peer,config,code,sense,data
1735 * Find a feature, determine which channel activated
1736 * \retval AST_FEATURE_RETURN_PBX_KEEPALIVE,AST_FEATURE_RETURN_NO_HANGUP_PEER
1738 * \retval -2 when an application cannot be found.
1740 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1742 struct ast_app *app;
1743 struct ast_call_feature *feature = data;
1744 struct ast_channel *work, *idle;
1747 if (!feature) { /* shouldn't ever happen! */
1748 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1752 if (sense == FEATURE_SENSE_CHAN) {
1753 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1754 return AST_FEATURE_RETURN_KEEPTRYING;
1755 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1763 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1764 return AST_FEATURE_RETURN_KEEPTRYING;
1765 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1774 if (!(app = pbx_findapp(feature->app))) {
1775 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1779 ast_autoservice_start(idle);
1781 if (!ast_strlen_zero(feature->moh_class))
1782 ast_moh_start(idle, feature->moh_class, NULL);
1784 res = pbx_exec(work, app, feature->app_args);
1786 if (!ast_strlen_zero(feature->moh_class))
1789 ast_autoservice_stop(idle);
1791 if (res == AST_PBX_KEEPALIVE) {
1792 /* do not hangup peer if feature is to be activated on it */
1793 if ((ast_test_flag(feature, AST_FEATURE_FLAG_ONPEER) && sense == FEATURE_SENSE_CHAN) || (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF) && sense == FEATURE_SENSE_PEER))
1794 return AST_FEATURE_RETURN_NO_HANGUP_PEER;
1796 return AST_FEATURE_RETURN_PBX_KEEPALIVE;
1798 else if (res == AST_PBX_NO_HANGUP_PEER)
1799 return AST_FEATURE_RETURN_NO_HANGUP_PEER;
1800 else if (res == AST_PBX_NO_HANGUP_PEER_PARKED)
1801 return AST_FEATURE_RETURN_NO_HANGUP_PEER_PARKED;
1803 return AST_FEATURE_RETURN_SUCCESSBREAK;
1805 return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1808 static void unmap_features(void)
1812 ast_rwlock_wrlock(&features_lock);
1813 for (x = 0; x < FEATURES_COUNT; x++)
1814 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1815 ast_rwlock_unlock(&features_lock);
1818 static int remap_feature(const char *name, const char *value)
1822 ast_rwlock_wrlock(&features_lock);
1823 for (x = 0; x < FEATURES_COUNT; x++) {
1824 if (strcasecmp(builtin_features[x].sname, name))
1827 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1831 ast_rwlock_unlock(&features_lock);
1837 * \brief Check the dynamic features
1838 * \param chan,peer,config,code,sense
1840 * Lock features list, browse for code, unlock list
1841 * \retval res on success.
1842 * \retval -1 on failure.
1844 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1847 struct ast_flags features;
1848 struct ast_call_feature *feature;
1849 struct feature_group *fg = NULL;
1850 struct feature_group_exten *fge;
1851 const char *dynamic_features;
1853 int res = AST_FEATURE_RETURN_PASSDIGITS;
1854 int feature_detected = 0;
1856 if (sense == FEATURE_SENSE_CHAN) {
1857 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1858 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1861 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1862 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
1864 ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
1866 ast_rwlock_rdlock(&features_lock);
1867 for (x = 0; x < FEATURES_COUNT; x++) {
1868 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1869 !ast_strlen_zero(builtin_features[x].exten)) {
1870 /* Feature is up for consideration */
1871 if (!strcmp(builtin_features[x].exten, code)) {
1872 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1873 feature_detected = 1;
1875 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1876 if (res == AST_FEATURE_RETURN_PASSDIGITS)
1877 res = AST_FEATURE_RETURN_STOREDIGITS;
1881 ast_rwlock_unlock(&features_lock);
1883 if (ast_strlen_zero(dynamic_features) || feature_detected)
1886 tmp = ast_strdupa(dynamic_features);
1888 while ((tok = strsep(&tmp, "#"))) {
1889 AST_RWLIST_RDLOCK(&feature_groups);
1891 fg = find_group(tok);
1894 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1895 if (strcasecmp(fge->exten, code))
1898 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
1899 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
1900 AST_RWLIST_UNLOCK(&feature_groups);
1903 res = AST_FEATURE_RETURN_PASSDIGITS;
1909 AST_RWLIST_UNLOCK(&feature_groups);
1910 AST_LIST_LOCK(&feature_list);
1912 if(!(feature = find_dynamic_feature(tok))) {
1913 AST_LIST_UNLOCK(&feature_list);
1917 /* Feature is up for consideration */
1918 if (!strcmp(feature->exten, code)) {
1919 ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1920 res = feature->operation(chan, peer, config, code, sense, feature);
1921 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
1922 AST_LIST_UNLOCK(&feature_list);
1925 res = AST_FEATURE_RETURN_PASSDIGITS;
1926 } else if (!strncmp(feature->exten, code, strlen(code)))
1927 res = AST_FEATURE_RETURN_STOREDIGITS;
1929 AST_LIST_UNLOCK(&feature_list);
1935 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1939 ast_clear_flag(config, AST_FLAGS_ALL);
1941 ast_rwlock_rdlock(&features_lock);
1942 for (x = 0; x < FEATURES_COUNT; x++) {
1943 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1946 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1947 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1949 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1950 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1952 ast_rwlock_unlock(&features_lock);
1954 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1955 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1957 if (dynamic_features) {
1958 char *tmp = ast_strdupa(dynamic_features);
1960 struct ast_call_feature *feature;
1962 /* while we have a feature */
1963 while ((tok = strsep(&tmp, "#"))) {
1964 AST_LIST_LOCK(&feature_list);
1965 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1966 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1967 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1968 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1969 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1971 AST_LIST_UNLOCK(&feature_list);
1978 * \brief Get feature and dial
1979 * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1981 * Request channel, set channel variables, initiate call,check if they want to disconnect
1982 * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1983 * check for answer break loop, set cdr return channel.
1985 * \todo XXX Check - this is very similar to the code in channel.c
1986 * \return always a channel
1988 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language)
1993 struct ast_channel *chan;
1994 struct ast_channel *monitor_chans[2];
1995 struct ast_channel *active_channel;
1996 int res = 0, ready = 0;
1998 if ((chan = ast_request(type, format, data, &cause))) {
1999 ast_set_callerid(chan, cid_num, cid_name, cid_num);
2000 ast_string_field_set(chan, language, language);
2001 ast_channel_inherit_variables(caller, chan);
2002 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
2004 if (!ast_call(chan, data, timeout)) {
2005 struct timeval started;
2007 char *disconnect_code = NULL, *dialed_code = NULL;
2009 ast_indicate(caller, AST_CONTROL_RINGING);
2010 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
2011 ast_rwlock_rdlock(&features_lock);
2012 for (x = 0; x < FEATURES_COUNT; x++) {
2013 if (strcasecmp(builtin_features[x].sname, "disconnect"))
2016 disconnect_code = builtin_features[x].exten;
2017 len = strlen(disconnect_code) + 1;
2018 dialed_code = alloca(len);
2019 memset(dialed_code, 0, len);
2022 ast_rwlock_unlock(&features_lock);
2024 started = ast_tvnow();
2027 ast_poll_channel_add(caller, chan);
2029 while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
2030 struct ast_frame *f = NULL;
2032 monitor_chans[0] = caller;
2033 monitor_chans[1] = chan;
2034 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
2036 /* see if the timeout has been violated */
2037 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
2038 state = AST_CONTROL_UNHOLD;
2039 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
2040 break; /*doh! timeout*/
2043 if (!active_channel)
2046 if (chan && (chan == active_channel)){
2048 if (f == NULL) { /*doh! where'd he go?*/
2049 state = AST_CONTROL_HANGUP;
2054 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
2055 if (f->subclass == AST_CONTROL_RINGING) {
2056 state = f->subclass;
2057 ast_verb(3, "%s is ringing\n", chan->name);
2058 ast_indicate(caller, AST_CONTROL_RINGING);
2059 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
2060 state = f->subclass;
2061 ast_verb(3, "%s is busy\n", chan->name);
2062 ast_indicate(caller, AST_CONTROL_BUSY);
2066 } else if (f->subclass == AST_CONTROL_ANSWER) {
2067 /* This is what we are hoping for */
2068 state = f->subclass;
2073 } else if (f->subclass != -1) {
2074 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
2076 /* else who cares */
2079 } else if (caller && (active_channel == caller)) {
2080 f = ast_read(caller);
2081 if (f == NULL) { /*doh! where'd he go?*/
2082 if (!igncallerstate) {
2083 if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
2084 /* make this a blind transfer */
2088 state = AST_CONTROL_HANGUP;
2094 if (f->frametype == AST_FRAME_DTMF) {
2095 dialed_code[x++] = f->subclass;
2096 dialed_code[x] = '\0';
2097 if (strlen(dialed_code) == len) {
2099 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
2101 dialed_code[x] = '\0';
2103 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
2104 /* Caller Canceled the call */
2105 state = AST_CONTROL_UNHOLD;
2117 ast_poll_channel_del(caller, chan);
2120 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
2122 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
2124 case AST_CAUSE_BUSY:
2125 state = AST_CONTROL_BUSY;
2127 case AST_CAUSE_CONGESTION:
2128 state = AST_CONTROL_CONGESTION;
2133 ast_indicate(caller, -1);
2134 if (chan && ready) {
2135 if (chan->_state == AST_STATE_UP)
2136 state = AST_CONTROL_ANSWER;
2153 * \brief return the first unlocked cdr in a possible chain
2155 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
2157 struct ast_cdr *cdr_orig = cdr;
2159 if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
2163 return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
2167 * \brief bridge the call and set CDR
2168 * \param chan,peer,config
2170 * Set start time, check for two channels,check if monitor on
2171 * check for feature activation, create new CDR
2172 * \retval res on success.
2173 * \retval -1 on failure to bridge.
2175 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
2177 /* Copy voice back and forth between the two channels. Give the peer
2178 the ability to transfer calls with '#<extension' syntax. */
2179 struct ast_frame *f;
2180 struct ast_channel *who;
2181 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
2182 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
2183 char orig_channame[AST_MAX_EXTENSION];
2184 char orig_peername[AST_MAX_EXTENSION];
2190 struct ast_option_header *aoh;
2191 struct ast_bridge_config backup_config;
2192 struct ast_cdr *bridge_cdr = NULL;
2193 struct ast_cdr *orig_peer_cdr = NULL;
2194 struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
2195 struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
2196 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
2197 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
2199 memset(&backup_config, 0, sizeof(backup_config));
2201 config->start_time = ast_tvnow();
2204 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
2205 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
2207 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
2210 const char *monitor_exec;
2211 struct ast_channel *src = NULL;
2213 if (!(monitor_app = pbx_findapp("Monitor")))
2216 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
2218 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
2220 if (monitor_app && src) {
2221 char *tmp = ast_strdupa(monitor_exec);
2222 pbx_exec(src, monitor_app, tmp);
2226 set_config_flags(chan, peer, config);
2227 config->firstpass = 1;
2229 /* Answer if need be */
2230 if (ast_answer(chan))
2233 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
2234 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
2235 orig_peer_cdr = peer_cdr;
2237 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
2240 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
2241 ast_cdr_update(chan);
2242 bridge_cdr = ast_cdr_dup(chan_cdr);
2243 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
2244 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
2246 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
2247 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
2248 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
2249 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
2250 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
2251 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
2252 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
2253 ast_cdr_setcid(bridge_cdr, chan);
2254 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
2255 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
2256 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
2257 /* Destination information */
2258 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
2259 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
2261 bridge_cdr->start = peer_cdr->start;
2262 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
2264 ast_cdr_start(bridge_cdr);
2267 ast_debug(4,"bridge answer set, chan answer set\n");
2268 /* peer_cdr->answer will be set when a macro runs on the peer;
2269 in that case, the bridge answer will be delayed while the
2270 macro plays on the peer channel. The peer answered the call
2271 before the macro started playing. To the phone system,
2272 this is billable time for the call, even tho the caller
2273 hears nothing but ringing while the macro does its thing. */
2274 if (peer_cdr && !ast_tvzero(peer_cdr->answer)) {
2275 bridge_cdr->answer = peer_cdr->answer;
2276 chan_cdr->answer = peer_cdr->answer;
2277 bridge_cdr->disposition = peer_cdr->disposition;
2278 chan_cdr->disposition = peer_cdr->disposition;
2280 ast_cdr_answer(bridge_cdr);
2281 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
2283 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
2285 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
2289 struct ast_channel *other; /* used later */
2291 res = ast_channel_bridge(chan, peer, config, &f, &who);
2293 if (config->feature_timer) {
2294 /* Update time limit for next pass */
2295 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
2296 config->feature_timer -= diff;
2298 /* Running on backup config, meaning a feature might be being
2299 activated, but that's no excuse to keep things going
2301 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
2302 ast_debug(1, "Timed out, realtime this time!\n");
2303 config->feature_timer = 0;
2309 } else if (config->feature_timer <= 0) {
2310 /* Not *really* out of time, just out of time for
2311 digits to come in for features. */
2312 ast_debug(1, "Timed out for feature!\n");
2313 if (!ast_strlen_zero(peer_featurecode)) {
2314 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
2315 memset(peer_featurecode, 0, sizeof(peer_featurecode));
2317 if (!ast_strlen_zero(chan_featurecode)) {
2318 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
2319 memset(chan_featurecode, 0, sizeof(chan_featurecode));
2323 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
2325 /* Restore original (possibly time modified) bridge config */
2326 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
2327 memset(&backup_config, 0, sizeof(backup_config));
2329 hadfeatures = hasfeatures;
2330 /* Continue as we were */
2333 /* The bridge returned without a frame and there is a feature in progress.
2334 * However, we don't think the feature has quite yet timed out, so just
2335 * go back into the bridge. */
2339 if (config->feature_timer <=0) {
2340 /* We ran out of time */
2341 config->feature_timer = 0;
2351 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
2352 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
2356 if (!f || (f->frametype == AST_FRAME_CONTROL &&
2357 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
2358 f->subclass == AST_CONTROL_CONGESTION))) {
2362 /* many things should be sent to the 'other' channel */
2363 other = (who == chan) ? peer : chan;
2364 if (f->frametype == AST_FRAME_CONTROL) {
2365 switch (f->subclass) {
2366 case AST_CONTROL_RINGING:
2367 case AST_CONTROL_FLASH:
2369 ast_indicate(other, f->subclass);
2371 case AST_CONTROL_HOLD:
2372 case AST_CONTROL_UNHOLD:
2373 ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
2375 case AST_CONTROL_OPTION:
2377 /* Forward option Requests */
2378 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
2379 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
2380 f->datalen - sizeof(struct ast_option_header), 0);
2384 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
2386 } else if (f->frametype == AST_FRAME_DTMF) {
2390 hadfeatures = hasfeatures;
2391 /* This cannot overrun because the longest feature is one shorter than our buffer */
2393 sense = FEATURE_SENSE_CHAN;
2394 featurecode = chan_featurecode;
2396 sense = FEATURE_SENSE_PEER;
2397 featurecode = peer_featurecode;
2399 /*! append the event to featurecode. we rely on the string being zero-filled, and
2400 * not overflowing it.
2401 * \todo XXX how do we guarantee the latter ?
2403 featurecode[strlen(featurecode)] = f->subclass;
2404 /* Get rid of the frame before we start doing "stuff" with the channels */
2407 config->feature_timer = backup_config.feature_timer;
2408 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
2410 case AST_FEATURE_RETURN_PASSDIGITS:
2411 ast_dtmf_stream(other, who, featurecode, 0, 0);
2413 case AST_FEATURE_RETURN_SUCCESS:
2414 memset(featurecode, 0, sizeof(chan_featurecode));
2417 if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
2421 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
2422 if (hadfeatures && !hasfeatures) {
2423 /* Restore backup */
2424 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
2425 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
2426 } else if (hasfeatures) {
2428 /* Backup configuration */
2429 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
2430 /* Setup temporary config options */
2431 config->play_warning = 0;
2432 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
2433 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
2434 config->warning_freq = 0;
2435 config->warning_sound = NULL;
2436 config->end_sound = NULL;
2437 config->start_sound = NULL;
2438 config->firstpass = 0;
2440 config->start_time = ast_tvnow();
2441 config->feature_timer = featuredigittimeout;
2442 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
2450 if (res != AST_PBX_KEEPALIVE && config->end_bridge_callback) {
2451 config->end_bridge_callback();
2454 /* run the hangup exten on the chan object IFF it was NOT involved in a parking situation
2455 * if it were, then chan belongs to a different thread now, and might have been hung up long
2458 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
2459 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
2460 if (res != AST_PBX_KEEPALIVE && !ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
2461 struct ast_cdr *swapper;
2462 char savelastapp[AST_MAX_EXTENSION];
2463 char savelastdata[AST_MAX_EXTENSION];
2464 char save_exten[AST_MAX_EXTENSION];
2466 int found = 0; /* set if we find at least one match */
2467 int spawn_error = 0;
2469 if (ast_opt_end_cdr_before_h_exten) {
2470 ast_cdr_end(bridge_cdr);
2472 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
2473 dialplan code operate on it */
2474 swapper = chan->cdr;
2475 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
2476 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
2477 ast_channel_lock(chan);
2478 chan->cdr = bridge_cdr;
2479 ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
2480 save_prio = chan->priority;
2481 ast_copy_string(chan->exten, "h", sizeof(chan->exten));
2483 ast_channel_unlock(chan);
2484 while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) {
2487 if (found && spawn_error) {
2488 /* Something bad happened, or a hangup has been requested. */
2489 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
2490 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
2493 ast_channel_lock(chan);
2494 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
2495 chan->priority = save_prio;
2496 chan->cdr = swapper;
2497 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
2498 ast_channel_unlock(chan);
2499 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
2500 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
2501 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
2503 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
2505 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
2506 if (res != AST_PBX_KEEPALIVE) {
2507 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
2508 if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
2509 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
2512 /* we can post the bridge CDR at this point */
2513 ast_cdr_end(bridge_cdr);
2514 ast_cdr_detach(bridge_cdr);
2516 /* do a specialized reset on the beginning channel
2517 CDR's, if they still exist, so as not to mess up
2518 issues in future bridges;
2520 Here are the rules of the game:
2521 1. The chan and peer channel pointers will not change
2522 during the life of the bridge.
2523 2. But, in transfers, the channel names will change.
2524 between the time the bridge is started, and the
2525 time the channel ends.
2526 Usually, when a channel changes names, it will
2527 also change CDR pointers.
2528 3. Usually, only one of the two channels (chan or peer)
2530 4. Usually, if a channel changes names during a bridge,
2531 it is because of a transfer. Usually, in these situations,
2532 it is normal to see 2 bridges running simultaneously, and
2533 it is not unusual to see the two channels that change
2534 swapped between bridges.
2535 5. After a bridge occurs, we have 2 or 3 channels' CDRs
2536 to attend to; if the chan or peer changed names,
2537 we have the before and after attached CDR's.
2538 6. Parking has to be accounted for in the code:
2539 a. Parking will cause ast_bridge_call to return
2540 either AST_PBX_NO_HANGUP_PEER or AST_PBX_NO_HANGUP_PEER_PARKED;
2541 in the latter case, peer is (most likely) a bad
2542 pointer, you can no longer deref it. If it does still
2543 exist, it is under another's thread control, and
2544 could be destroyed at any time.
2545 b. The same applies to AST_PBX_KEEPALIVE, in which
2546 case, the chan ptr cannot be used, as another thread
2547 owns it and may have destroyed the channel.
2548 c. In the former case, you need to check peer to see if it
2549 still exists before you deref it, and obtain a lock.
2550 d. In neither case should you do an ast_hangup(peer).
2551 e. Do not overwrite the result code from ast_bridge_call.
2554 if (res != AST_PBX_KEEPALIVE && new_chan_cdr) {
2555 struct ast_channel *chan_ptr = NULL;
2557 if (strcasecmp(orig_channame, chan->name) != 0) {
2559 chan_ptr = ast_get_channel_by_name_locked(orig_channame);
2561 if (!ast_bridged_channel(chan_ptr)) {
2562 struct ast_cdr *cur;
2563 for (cur = chan_ptr->cdr; cur; cur = cur->next) {
2564 if (cur == chan_cdr) {
2569 ast_cdr_specialized_reset(chan_cdr,0);
2571 ast_channel_unlock(chan_ptr);
2574 ast_cdr_specialized_reset(new_chan_cdr,0);
2576 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */
2580 if (res != AST_PBX_NO_HANGUP_PEER_PARKED) { /* if the peer was involved in a park, don't even touch it; it's probably gone */
2581 struct ast_channel *chan_ptr = NULL;
2582 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
2583 if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
2584 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
2585 if (strcasecmp(orig_peername, peer->name) != 0) {
2587 chan_ptr = ast_get_channel_by_name_locked(orig_peername);
2589 if (!ast_bridged_channel(chan_ptr)) {
2590 struct ast_cdr *cur;
2591 for (cur = chan_ptr->cdr; cur; cur = cur->next) {
2592 if (cur == peer_cdr) {
2597 ast_cdr_specialized_reset(peer_cdr,0);
2599 ast_channel_unlock(chan_ptr);
2602 ast_cdr_specialized_reset(new_peer_cdr,0);
2604 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */
2610 /*! \brief Output parking event to manager */
2611 static void post_manager_event(const char *s, struct parkeduser *pu)
2613 manager_event(EVENT_FLAG_CALL, s,
2616 "Parkinglot: %s\r\n"
2617 "CallerIDNum: %s\r\n"
2618 "CallerIDName: %s\r\n"
2619 "UniqueID: %s\r\n\r\n",
2622 pu->parkinglot->name,
2623 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2624 S_OR(pu->chan->cid.cid_name, "<unknown>"),
2629 /*! \brief Run management on parkinglots, called once per parkinglot */
2630 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max)
2633 struct parkeduser *pu;
2635 char parkingslot[AST_MAX_EXTENSION];
2637 /* Lock parking list */
2638 AST_LIST_LOCK(&curlot->parkings);
2639 AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
2640 struct ast_channel *chan = pu->chan; /* shorthand */
2641 int tms; /* timeout for this item */
2642 int x; /* fd index in channel */
2643 struct ast_context *con;
2645 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
2648 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2649 if (tms > pu->parkingtime) {
2650 /* Stop music on hold */
2651 ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
2652 /* Get chan, exten from derived kludge */
2653 if (pu->peername[0]) {
2654 char *peername = ast_strdupa(pu->peername);
2655 char *cp = strrchr(peername, '-');
2656 char peername_flat[AST_MAX_EXTENSION]; /* using something like DAHDI/52 for an extension name is NOT a good idea */
2661 ast_copy_string(peername_flat,peername,sizeof(peername_flat));
2662 for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
2663 if (peername_flat[i] == '/')
2664 peername_flat[i]= '0';
2666 con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
2668 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
2671 char returnexten[AST_MAX_EXTENSION];
2672 struct ast_datastore *features_datastore;
2673 struct ast_dial_features *dialfeatures = NULL;
2675 ast_channel_lock(chan);
2677 if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
2678 dialfeatures = features_datastore->data;
2680 ast_channel_unlock(chan);
2683 snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
2684 else /* Existing default */
2685 snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
2687 ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
2689 if (comebacktoorigin) {
2690 set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
2692 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2693 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2694 pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
2695 set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
2698 /* They've been waiting too long, send them back to where they came. Theoretically they
2699 should have their original extensions and such, but we copy to be on the safe side */
2700 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2702 post_manager_event("ParkedCallTimeOut", pu);
2704 ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
2705 /* Start up the PBX, or hang them up */
2706 if (ast_pbx_start(chan)) {
2707 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
2710 /* And take them out of the parking lot */
2711 con = ast_context_find(pu->parkinglot->parking_con);
2713 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
2714 ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
2716 notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
2718 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2719 AST_LIST_REMOVE_CURRENT(list);
2720 } else { /* still within parking time, process descriptors */
2721 for (x = 0; x < AST_MAX_FDS; x++) {
2722 struct ast_frame *f;
2724 if ((chan->fds[x] == -1) || (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds)))
2727 if (FD_ISSET(chan->fds[x], efds))
2728 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2730 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2733 /* See if they need servicing */
2734 f = ast_read(pu->chan);
2736 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2739 post_manager_event("ParkedCallGiveUp", pu);
2741 /* There's a problem, hang them up*/
2742 ast_verb(2, "%s got tired of being parked\n", chan->name);
2744 /* And take them out of the parking lot */
2745 con = ast_context_find(curlot->parking_con);
2747 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
2748 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2750 notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
2752 ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
2753 AST_LIST_REMOVE_CURRENT(list);
2756 /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2758 if (pu->moh_trys < 3 && !chan->generatordata) {
2759 ast_debug(1, "MOH on parked call stopped by outside source. Restarting on channel %s.\n", chan->name);
2760 ast_indicate_data(chan, AST_CONTROL_HOLD,
2761 S_OR(curlot->mohclass, NULL),
2762 (!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
2765 goto std; /* XXX Ick: jumping into an else statement??? XXX */
2768 if (x >= AST_MAX_FDS) {
2769 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2770 if (chan->fds[x] > -1) {
2771 FD_SET(chan->fds[x], nrfds);
2772 FD_SET(chan->fds[x], nefds);
2773 if (chan->fds[x] > *max)
2774 *max = chan->fds[x];
2777 /* Keep track of our shortest wait */
2778 if (tms < *ms || *ms < 0)
2783 AST_LIST_TRAVERSE_SAFE_END;
2784 AST_LIST_UNLOCK(&curlot->parkings);
2789 * \brief Take care of parked calls and unpark them if needed
2790 * \param ignore unused var.
2792 * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2793 * if so, remove channel from parking lot and return it to the extension that parked it.
2794 * Check if parked channel decided to hangup, wait until next FD via select().
2796 static void *do_parking_thread(void *ignore)
2798 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
2799 fd_set nrfds, nefds; /* args for the next select */
2805 int ms = -1; /* select timeout, uninitialized */
2806 int max = -1; /* max fd, none there yet */
2807 struct ao2_iterator iter;
2808 struct ast_parkinglot *curlot;
2811 iter = ao2_iterator_init(parkinglots, 0);
2813 while ((curlot = ao2_iterator_next(&iter))) {
2814 res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max);
2815 ao2_ref(curlot, -1);
2821 struct timeval wait = ast_samp2tv(ms, 1000);
2822 /* Wait for something to happen */
2823 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &wait : NULL);
2825 pthread_testcancel();
2827 return NULL; /* Never reached */
2830 /*! \brief Find parkinglot by name */
2831 struct ast_parkinglot *find_parkinglot(const char *name)
2833 struct ast_parkinglot *parkinglot = NULL;
2834 struct ast_parkinglot tmp_parkinglot;
2836 if (ast_strlen_zero(name))
2839 ast_copy_string(tmp_parkinglot.name, name, sizeof(tmp_parkinglot.name));
2841 parkinglot = ao2_find(parkinglots, &tmp_parkinglot, OBJ_POINTER);
2843 if (parkinglot && option_debug)
2844 ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
2849 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
2850 AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
2851 AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
2852 AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
2855 /*! \brief Park a call */
2856 static int park_call_exec(struct ast_channel *chan, void *data)
2858 /* Cache the original channel name in case we get masqueraded in the middle
2859 * of a park--it is still theoretically possible for a transfer to happen before
2860 * we get here, but it is _really_ unlikely */
2861 char *orig_chan_name = ast_strdupa(chan->name);
2862 char orig_exten[AST_MAX_EXTENSION];
2863 int orig_priority = chan->priority;
2865 /* Data is unused at the moment but could contain a parking
2866 lot context eventually */
2870 AST_DECLARE_APP_ARGS(app_args,
2871 AST_APP_ARG(timeout);
2872 AST_APP_ARG(return_con);
2873 AST_APP_ARG(return_ext);
2874 AST_APP_ARG(return_pri);
2875 AST_APP_ARG(options);
2878 if (!ast_strlen_zero(data)) {
2879 parse = ast_strdupa(data);
2880 AST_STANDARD_APP_ARGS(app_args, parse);
2883 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
2885 /* Setup the exten/priority to be s/1 since we don't know
2886 where this call should return */
2887 strcpy(chan->exten, "s");
2890 /* Answer if call is not up */
2891 if (chan->_state != AST_STATE_UP)
2892 res = ast_answer(chan);
2894 /* Sleep to allow VoIP streams to settle down */
2896 res = ast_safe_sleep(chan, 1000);
2900 struct ast_park_call_args args = {
2901 .orig_chan_name = orig_chan_name,
2903 struct ast_flags flags = { 0 };
2906 if (!ast_strlen_zero(app_args.timeout)) {
2907 if (sscanf(app_args.timeout, "%d", &args.timeout) != 1) {
2908 ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
2912 if (!ast_strlen_zero(app_args.return_con)) {
2913 args.return_con = app_args.return_con;
2915 if (!ast_strlen_zero(app_args.return_ext)) {
2916 args.return_ext = app_args.return_ext;
2918 if (!ast_strlen_zero(app_args.return_pri)) {
2919 if (sscanf(app_args.return_pri, "%d", &args.return_pri) != 1) {
2920 ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
2921 args.return_pri = 0;
2926 ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
2927 args.flags = flags.flags;
2929 res = ast_park_call_full(chan, chan, &args);
2930 /* Continue on in the dialplan */
2932 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
2933 chan->priority = orig_priority;
2936 res = AST_PBX_KEEPALIVE;
2942 /*! \brief Pickup parked call */
2943 static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parkinglot *parkinglot)
2946 struct ast_channel *peer=NULL;
2947 struct parkeduser *pu;
2948 struct ast_context *con;
2950 struct ast_bridge_config config;
2953 park = atoi((char *)data);