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"
59 #define DEFAULT_PARK_TIME 45000
60 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
61 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
62 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
63 #define DEFAULT_PARKINGLOT "default" /*!< Default parking lot */
64 #define DEFAULT_ATXFER_DROP_CALL 0
65 #define DEFAULT_ATXFER_LOOP_DELAY 10000
66 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
68 #define AST_MAX_WATCHERS 256
70 struct feature_group_exten {
71 AST_LIST_ENTRY(feature_group_exten) entry;
72 AST_DECLARE_STRING_FIELDS(
73 AST_STRING_FIELD(exten);
75 struct ast_call_feature *feature;
78 struct feature_group {
79 AST_LIST_ENTRY(feature_group) entry;
80 AST_DECLARE_STRING_FIELDS(
81 AST_STRING_FIELD(gname);
83 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
86 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
88 static char *parkedcall = "ParkedCall";
90 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
92 /*! \brief Description of one parked call, added to a list while active, then removed.
93 The list belongs to a parkinglot
96 struct ast_channel *chan; /*!< Parking channel */
97 struct timeval start; /*!< Time the parking started */
98 int parkingnum; /*!< Parking lot */
99 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
100 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
101 char exten[AST_MAX_EXTENSION];
103 int parkingtime; /*!< Maximum length in parking lot before return */
106 unsigned char moh_trys;
107 struct ast_parkinglot *parkinglot;
108 AST_LIST_ENTRY(parkeduser) list;
111 /*! \brief Structure for parking lots which are put in a container. */
112 struct ast_parkinglot {
113 char name[AST_MAX_CONTEXT];
114 char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
115 char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
116 int parking_start; /*!< First available extension for parking */
117 int parking_stop; /*!< Last available extension for parking */
120 int parkingtime; /*!< Default parking time */
121 char mohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
122 int parkaddhints; /*!< Add parking hints automatically */
123 int parkedcalltransfers; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
124 int parkedcallreparking; /*!< Enable DTMF based parking on bridge when picking up parked calls */
125 AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
128 /*! \brief The list of parking lots configured. Always at least one - the default parking lot */
129 static struct ao2_container *parkinglots;
131 struct ast_parkinglot *default_parkinglot;
132 char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
134 static char courtesytone[256]; /*!< Courtesy tone */
135 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
136 static char xfersound[256]; /*!< Call transfer sound */
137 static char xferfailsound[256]; /*!< Call transfer failure sound */
141 static int transferdigittimeout;
142 static int featuredigittimeout;
143 static int comebacktoorigin = 1;
145 static int atxfernoanswertimeout;
146 static unsigned int atxferdropcall;
147 static unsigned int atxferloopdelay;
148 static unsigned int atxfercallbackretries;
150 static char *registrar = "features"; /*!< Registrar for operations */
152 /* module and CLI command definitions */
153 static char *synopsis = "Answer a parked call";
155 static char *descrip = "ParkedCall(exten): "
156 "Used to connect to a parked call. This application is always\n"
157 "registered internally and does not need to be explicitly added\n"
158 "into the dialplan, although you should include the 'parkedcalls'\n"
159 "context. If no extension is provided, then the first available\n"
160 "parked call will be acquired.\n";
162 static char *parkcall = "Park";
164 static char *synopsis2 = "Park yourself";
166 static char *descrip2 =
167 " Park([timeout,[return_context,[return_exten,[return_priority,[options]]]]]):"
168 "Used to park yourself (typically in combination with a supervised\n"
169 "transfer to know the parking space). This application is always\n"
170 "registered internally and does not need to be explicitly added\n"
171 "into the dialplan, although you should include the 'parkedcalls'\n"
172 "context (or the context specified in features.conf).\n\n"
173 "If you set the PARKINGEXTEN variable to an extension in your\n"
174 "parking context, Park() will park the call on that extension, unless\n"
175 "it already exists. In that case, execution will continue at next\n"
177 " This application can accept arguments as well.\n"
178 " timeout - A custom parking timeout for this parked call.\n"
179 " return_context - The context to return the call to after it times out.\n"
180 " return_exten - The extension to return the call to after it times out.\n"
181 " return_priority - The priority to return the call to after it times out.\n"
182 " options - A list of options for this parked call. Valid options are:\n"
183 " 'r' - Send ringing instead of MOH to the parked call.\n"
184 " 'R' - Randomize the selection of a parking space.\n"
185 " 's' - Silence announcement of the parking space number.\n"
188 static struct ast_app *monitor_app = NULL;
189 static int monitor_ok = 1;
191 static struct ast_app *mixmonitor_app = NULL;
192 static int mixmonitor_ok = 1;
194 static struct ast_app *stopmixmonitor_app = NULL;
195 static int stopmixmonitor_ok = 1;
197 static pthread_t parking_thread;
199 /* Forward declarations */
200 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
201 static void parkinglot_unref(struct ast_parkinglot *parkinglot);
202 static void parkinglot_destroy(void *obj);
203 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
204 struct ast_parkinglot *find_parkinglot(const char *name);
207 const char *ast_parking_ext(void)
212 const char *ast_pickup_ext(void)
217 struct ast_bridge_thread_obj
219 struct ast_bridge_config bconfig;
220 struct ast_channel *chan;
221 struct ast_channel *peer;
222 unsigned int return_to_pbx:1;
225 static int parkinglot_hash_cb(const void *obj, const int flags)
227 const struct ast_parkinglot *parkinglot = obj;
228 return ast_str_hash(parkinglot->name);
231 static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
233 struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
234 return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH | CMP_STOP : 0;
238 * \brief store context, extension and priority
239 * \param chan, context, ext, pri
241 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
243 ast_copy_string(chan->context, context, sizeof(chan->context));
244 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
245 chan->priority = pri;
249 * \brief Check goto on transfer
252 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
253 * When found make sure the types are compatible. Check if channel is valid
254 * if so start the new channel else hangup the call.
256 static void check_goto_on_transfer(struct ast_channel *chan)
258 struct ast_channel *xferchan;
259 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
260 char *x, *goto_on_transfer;
263 if (ast_strlen_zero(val))
266 goto_on_transfer = ast_strdupa(val);
268 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
271 for (x = goto_on_transfer; x && *x; x++) {
275 /* Make formats okay */
276 xferchan->readformat = chan->readformat;
277 xferchan->writeformat = chan->writeformat;
278 ast_channel_masquerade(xferchan, chan);
279 ast_parseable_goto(xferchan, goto_on_transfer);
280 xferchan->_state = AST_STATE_UP;
281 ast_clear_flag(xferchan, AST_FLAGS_ALL);
282 xferchan->_softhangup = 0;
283 if ((f = ast_read(xferchan))) {
286 ast_pbx_start(xferchan);
288 ast_hangup(xferchan);
292 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);
295 * \brief bridge the call
296 * \param data thread bridge.
298 * Set Last Data for respective channels, reset cdr for channels
299 * bridge call, check if we're going back to dialplan
300 * if not hangup both legs of the call
302 static void *ast_bridge_call_thread(void *data)
304 struct ast_bridge_thread_obj *tobj = data;
307 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
308 tobj->chan->data = tobj->peer->name;
309 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
310 tobj->peer->data = tobj->chan->name;
312 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
314 if (tobj->return_to_pbx) {
315 if (!ast_check_hangup(tobj->peer)) {
316 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
317 res = ast_pbx_start(tobj->peer);
318 if (res != AST_PBX_SUCCESS)
319 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
321 ast_hangup(tobj->peer);
322 if (!ast_check_hangup(tobj->chan)) {
323 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
324 res = ast_pbx_start(tobj->chan);
325 if (res != AST_PBX_SUCCESS)
326 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
328 ast_hangup(tobj->chan);
330 ast_hangup(tobj->chan);
331 ast_hangup(tobj->peer);
340 * \brief create thread for the parked call
343 * Create thread and attributes, call ast_bridge_call_thread
345 static void ast_bridge_call_thread_launch(void *data)
349 struct sched_param sched;
351 pthread_attr_init(&attr);
352 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
353 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
354 pthread_attr_destroy(&attr);
355 memset(&sched, 0, sizeof(sched));
356 pthread_setschedparam(thread, SCHED_RR, &sched);
360 * \brief Announce call parking by ADSI
362 * \param parkingexten .
363 * Create message to show for ADSI, display message.
364 * \retval 0 on success.
365 * \retval -1 on failure.
367 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
370 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
372 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
374 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
376 res = ast_adsi_load_session(chan, NULL, 0, 1);
379 return ast_adsi_print(chan, message, justify, 1);
382 /*! \brief Find parking lot name from channel */
383 static const char *findparkinglotname(struct ast_channel *chan)
385 const char *temp, *parkinglot = NULL;
387 /* Check if the channel has a parking lot */
388 if (!ast_strlen_zero(chan->parkinglot))
389 parkinglot = chan->parkinglot;
391 /* Channel variables override everything */
393 if ((temp = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
399 /*! \brief Notify metermaids that we've changed an extension */
400 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
402 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
403 exten, context, devstate2str(state));
405 ast_devstate_changed(state, "park:%s@%s", exten, context);
408 /*! \brief metermaids callback from devicestate.c */
409 static enum ast_device_state metermaidstate(const char *data)
414 context = ast_strdupa(data);
416 exten = strsep(&context, "@");
418 return AST_DEVICE_INVALID;
420 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
422 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
423 return AST_DEVICE_NOT_INUSE;
425 return AST_DEVICE_INUSE;
428 /*! Options to pass to ast_park_call_full */
429 enum ast_park_call_options {
430 /*! Provide ringing to the parked caller instead of music on hold */
431 AST_PARK_OPT_RINGING = (1 << 0),
432 /*! Randomly choose a parking spot for the caller instead of choosing
433 * the first one that is available. */
434 AST_PARK_OPT_RANDOMIZE = (1 << 1),
435 /*! Do not announce the parking number */
436 AST_PARK_OPT_SILENCE = (1 << 2),
439 struct ast_park_call_args {
440 /*! How long to wait in the parking lot before the call gets sent back
441 * to the specified return extension (or a best guess at where it came
442 * from if not explicitly specified). */
444 /*! An output parameter to store the parking space where the parked caller
447 const char *orig_chan_name;
448 const char *return_con;
449 const char *return_ext;
455 static int ast_park_call_full(struct ast_channel *chan, struct ast_channel *peer,
456 struct ast_park_call_args *args)
458 struct parkeduser *pu;
459 int i, x = -1, parking_range;
460 struct ast_context *con;
461 const char *parkinglotname = NULL;
462 const char *parkingexten;
463 struct ast_parkinglot *parkinglot = NULL;
466 parkinglotname = findparkinglotname(peer);
468 if (parkinglotname) {
470 ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
471 parkinglot = find_parkinglot(parkinglotname);
474 parkinglot = default_parkinglot;
476 parkinglot_addref(parkinglot);
478 ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
480 /* Allocate memory for parking data */
481 if (!(pu = ast_calloc(1, sizeof(*pu)))) {
482 parkinglot_unref(parkinglot);
486 /* Lock parking list */
487 AST_LIST_LOCK(&parkinglot->parkings);
488 /* Check for channel variable PARKINGEXTEN */
489 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
490 if (!ast_strlen_zero(parkingexten)) {
491 /*!\note The API forces us to specify a numeric parking slot, even
492 * though the architecture would tend to support non-numeric extensions
493 * (as are possible with SIP, for example). Hence, we enforce that
494 * limitation here. If extout was not numeric, we could permit
495 * arbitrary non-numeric extensions.
497 if (sscanf(parkingexten, "%d", &x) != 1 || x < 0) {
498 AST_LIST_UNLOCK(&parkinglot->parkings);
499 parkinglot_unref(parkinglot);
501 ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
502 return 1; /* Continue execution if possible */
504 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
506 if (ast_exists_extension(NULL, parkinglot->parking_con, pu->parkingexten, 1, NULL)) {
507 AST_LIST_UNLOCK(&parkinglot->parkings);
508 parkinglot_unref(parkinglot);
510 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
511 return 1; /* Continue execution if possible */
515 struct parkeduser *cur = NULL;
517 /* Select parking space within range */
518 parking_range = parkinglot->parking_stop - parkinglot->parking_start + 1;
520 if (ast_test_flag(args, AST_PARK_OPT_RANDOMIZE)) {
521 start = ast_random() % (parkinglot->parking_stop - parkinglot->parking_start + 1);
523 start = parkinglot->parking_start;
526 for (i = start; 1; i++) {
527 if (i == parkinglot->parking_stop + 1) {
528 i = parkinglot->parking_start - 1;
532 AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
533 if (cur->parkingnum == i) {
538 if (!cur || i == start - 1) {
544 if (i == start - 1 && cur) {
545 ast_log(LOG_WARNING, "No more parking spaces\n");
547 AST_LIST_UNLOCK(&parkinglot->parkings);
548 parkinglot_unref(parkinglot);
551 /* Set pointer for next parking */
552 if (parkinglot->parkfindnext)
553 parkinglot->parking_offset = x - parkinglot->parking_start + 1;
554 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
557 chan->appl = "Parked Call";
562 /* Put the parked channel on hold if we have two different channels */
564 if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
565 ast_indicate(pu->chan, AST_CONTROL_RINGING);
567 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
568 S_OR(parkinglot->mohclass, NULL),
569 !ast_strlen_zero(parkinglot->mohclass) ? strlen(parkinglot->mohclass) + 1 : 0);
573 pu->start = ast_tvnow();
575 pu->parkinglot = parkinglot;
576 pu->parkingtime = (args->timeout > 0) ? args->timeout : parkinglot->parkingtime;
581 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
583 /* Remember what had been dialed, so that if the parking
584 expires, we try to come back to the same place */
585 ast_copy_string(pu->context,
586 S_OR(args->return_con, S_OR(chan->macrocontext, chan->context)),
587 sizeof(pu->context));
588 ast_copy_string(pu->exten,
589 S_OR(args->return_ext, S_OR(chan->macroexten, chan->exten)),
591 pu->priority = pu->priority ? pu->priority :
592 (chan->macropriority ? chan->macropriority : chan->priority);
594 AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
596 /* If parking a channel directly, don't quiet yet get parking running on it */
599 AST_LIST_UNLOCK(&parkinglot->parkings);
602 /* Wake up the (presumably select()ing) thread */
603 pthread_kill(parking_thread, SIGURG);
604 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));
606 manager_event(EVENT_FLAG_CALL, "ParkedCall",
612 "CallerIDNum: %s\r\n"
613 "CallerIDName: %s\r\n"
615 pu->parkingexten, pu->chan->name, pu->parkinglot->name, peer ? peer->name : "",
616 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
617 S_OR(pu->chan->cid.cid_num, "<unknown>"),
618 S_OR(pu->chan->cid.cid_name, "<unknown>"),
622 if (peer && adsipark && ast_adsi_available(peer)) {
623 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
624 ast_adsi_unload_session(peer);
627 con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar);
628 if (!con) /* Still no context? Bad */
629 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
630 /* Tell the peer channel the number of the parking space */
631 if (peer && !ast_test_flag(args, AST_PARK_OPT_SILENCE) && (ast_strlen_zero(args->orig_chan_name) || !strcasecmp(peer->name, args->orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
632 /* 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. */
633 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
634 ast_say_digits(peer, pu->parkingnum, "", peer->language);
635 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
638 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
639 notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_INUSE);
641 if (pu->notquiteyet) {
642 /* Wake up parking thread if we're really done */
643 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
644 S_OR(parkinglot->mohclass, NULL),
645 !ast_strlen_zero(parkinglot->mohclass) ? strlen(parkinglot->mohclass) + 1 : 0);
647 pthread_kill(parking_thread, SIGURG);
652 /*! \brief Park a call */
653 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
655 struct ast_park_call_args args = {
660 return ast_park_call_full(chan, peer, &args);
663 /* Park call via masquraded channel */
664 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
666 struct ast_channel *chan;
668 char *orig_chan_name = NULL;
671 /* Make a new, fake channel that we'll use to masquerade in the real one */
672 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
673 ast_log(LOG_WARNING, "Unable to create parked channel\n");
677 /* Make formats okay */
678 chan->readformat = rchan->readformat;
679 chan->writeformat = rchan->writeformat;
680 ast_channel_masquerade(chan, rchan);
682 /* Setup the extensions and such */
683 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
685 /* Make the masq execute */
686 if ((f = ast_read(chan)))
689 orig_chan_name = ast_strdupa(chan->name);
692 struct ast_park_call_args args = {
695 .orig_chan_name = orig_chan_name,
698 park_status = ast_park_call_full(chan, peer, &args);
699 if (park_status == 1) {
700 /* would be nice to play "invalid parking extension" */
710 #define FEATURE_SENSE_CHAN (1 << 0)
711 #define FEATURE_SENSE_PEER (1 << 1)
714 * \brief set caller and callee according to the direction
715 * \param caller, callee, peer, chan, sense
717 * Detect who triggered feature and set callee/caller variables accordingly
719 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
720 struct ast_channel *peer, struct ast_channel *chan, int sense)
722 if (sense == FEATURE_SENSE_PEER) {
732 * \brief support routing for one touch call parking
733 * \param chan channel parking call
734 * \param peer channel to be parked
735 * \param config unsed
737 * \param sense feature options
740 * Setup channel, set return exten,priority to 's,1'
741 * answer chan, sleep chan, park call
743 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
745 struct ast_channel *parker;
746 struct ast_channel *parkee;
749 set_peers(&parker, &parkee, peer, chan, sense);
750 /* Setup the exten/priority to be s/1 since we don't know
751 where this call should return */
752 strcpy(chan->exten, "s");
754 if (chan->_state != AST_STATE_UP)
755 res = ast_answer(chan);
757 res = ast_safe_sleep(chan, 1000);
759 res = ast_park_call(parkee, parker, 0, NULL);
762 if (sense == FEATURE_SENSE_CHAN)
763 res = AST_PBX_NO_HANGUP_PEER;
765 res = AST_PBX_KEEPALIVE;
771 /*! \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
772 other channel during the message, so please don't use this for very long messages
774 static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
776 /* First play for caller, put other channel on auto service */
777 if (ast_autoservice_start(callee_chan))
779 if (ast_stream_and_wait(caller_chan, audiofile, "")) {
780 ast_log(LOG_WARNING, "Failed to play automon message!\n");
781 ast_autoservice_stop(callee_chan);
784 if (ast_autoservice_stop(callee_chan))
786 /* Then play for callee, put other channel on auto service */
787 if (ast_autoservice_start(caller_chan))
789 if (ast_stream_and_wait(callee_chan, audiofile, "")) {
790 ast_log(LOG_WARNING, "Failed to play automon message !\n");
791 ast_autoservice_stop(caller_chan);
794 if (ast_autoservice_stop(caller_chan))
800 * \brief Monitor a channel by DTMF
801 * \param chan channel requesting monitor
802 * \param peer channel to be monitored
805 * \param sense feature options
808 * Check monitor app enabled, setup channels, both caller/callee chans not null
809 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
810 * \retval AST_FEATURE_RETURN_SUCCESS on success.
811 * \retval -1 on error.
813 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
815 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
818 struct ast_channel *caller_chan, *callee_chan;
819 const char *automon_message_start = NULL;
820 const char *automon_message_stop = NULL;
823 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
827 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
829 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
833 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
834 if (caller_chan) { /* Find extra messages */
835 automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
836 automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
839 if (!ast_strlen_zero(courtesytone)) { /* Play courtesy tone if configured */
840 if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
845 if (callee_chan->monitor) {
846 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
847 if (!ast_strlen_zero(automon_message_stop)) {
848 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
850 callee_chan->monitor->stop(callee_chan, 1);
851 return AST_FEATURE_RETURN_SUCCESS;
854 if (caller_chan && callee_chan) {
855 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
856 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
857 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
860 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
863 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
865 if (!touch_monitor_prefix)
866 touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
869 len = strlen(touch_monitor) + 50;
871 touch_filename = alloca(len);
872 snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
873 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
875 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
876 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
877 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
879 touch_filename = alloca(len);
880 snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
881 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
884 for(x = 0; x < strlen(args); x++) {
889 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
891 pbx_exec(callee_chan, monitor_app, args);
892 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
893 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
895 if (!ast_strlen_zero(automon_message_start)) { /* Play start message for both channels */
896 play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
899 return AST_FEATURE_RETURN_SUCCESS;
902 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
906 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
908 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
911 struct ast_channel *caller_chan, *callee_chan;
912 const char *mixmonitor_spy_type = "MixMonitor";
915 if (!mixmonitor_ok) {
916 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
920 if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
922 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
926 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
928 if (!ast_strlen_zero(courtesytone)) {
929 if (ast_autoservice_start(callee_chan))
931 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
932 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
933 ast_autoservice_stop(callee_chan);
936 if (ast_autoservice_stop(callee_chan))
940 ast_channel_lock(callee_chan);
941 count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
942 ast_channel_unlock(callee_chan);
944 /* This means a mixmonitor is attached to the channel, running or not is unknown. */
947 ast_verb(3, "User hit '%s' to stop recording call.\n", code);
949 /* Make sure they are running */
950 ast_channel_lock(callee_chan);
951 count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
952 ast_channel_unlock(callee_chan);
954 if (!stopmixmonitor_ok) {
955 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
958 if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
959 stopmixmonitor_ok = 0;
960 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
963 pbx_exec(callee_chan, stopmixmonitor_app, "");
964 return AST_FEATURE_RETURN_SUCCESS;
968 ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
971 if (caller_chan && callee_chan) {
972 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
973 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
976 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
979 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
982 len = strlen(touch_monitor) + 50;
984 touch_filename = alloca(len);
985 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
986 snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
988 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
989 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
990 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
992 touch_filename = alloca(len);
993 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
994 snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
997 for( x = 0; x < strlen(args); x++) {
1002 ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
1004 pbx_exec(callee_chan, mixmonitor_app, args);
1005 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1006 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
1007 return AST_FEATURE_RETURN_SUCCESS;
1011 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
1016 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1018 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
1019 return AST_FEATURE_RETURN_HANGUP;
1022 static int finishup(struct ast_channel *chan)
1024 ast_indicate(chan, AST_CONTROL_UNHOLD);
1026 return ast_autoservice_stop(chan);
1030 * \brief Find the context for the transfer
1034 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
1035 * \return a context string
1037 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
1039 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
1040 if (ast_strlen_zero(s)) {
1041 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
1043 if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
1044 s = transferer->macrocontext;
1046 if (ast_strlen_zero(s)) {
1047 s = transferer->context;
1053 * \brief Blind transfer user to another extension
1054 * \param chan channel to be transfered
1055 * \param peer channel initiated blind transfer
1059 * \param sense feature options
1061 * Place chan on hold, check if transferred to parkinglot extension,
1062 * otherwise check extension exists and transfer caller.
1063 * \retval AST_FEATURE_RETURN_SUCCESS.
1064 * \retval -1 on failure.
1066 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1068 struct ast_channel *transferer;
1069 struct ast_channel *transferee;
1070 const char *transferer_real_context;
1074 set_peers(&transferer, &transferee, peer, chan, sense);
1075 transferer_real_context = real_ctx(transferer, transferee);
1076 /* Start autoservice on chan while we talk to the originator */
1077 ast_autoservice_start(transferee);
1078 ast_indicate(transferee, AST_CONTROL_HOLD);
1080 memset(xferto, 0, sizeof(xferto));
1083 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1085 finishup(transferee);
1086 return -1; /* error ? */
1088 if (res > 0) /* If they've typed a digit already, handle it */
1089 xferto[0] = (char) res;
1091 ast_stopstream(transferer);
1092 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1093 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
1094 finishup(transferee);
1097 if (!strcmp(xferto, ast_parking_ext())) {
1098 res = finishup(transferee);
1101 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
1102 /* We return non-zero, but tell the PBX not to hang the channel when
1103 the thread dies -- We have to be careful now though. We are responsible for
1104 hanging up the channel, else it will never be hung up! */
1106 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
1108 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
1110 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
1111 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
1112 pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
1113 pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
1114 res=finishup(transferee);
1115 if (!transferer->cdr) {
1116 transferer->cdr=ast_cdr_alloc();
1118 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
1119 ast_cdr_start(transferer->cdr);
1122 if (transferer->cdr) {
1123 ast_cdr_setdestchan(transferer->cdr, transferee->name);
1124 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
1126 if (!transferee->pbx) {
1127 /* Doh! Use our handy async_goto functions */
1128 ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
1129 ,transferee->name, xferto, transferer_real_context);
1130 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
1131 ast_log(LOG_WARNING, "Async goto failed :-(\n");
1133 /* Set the channel's new extension, since it exists, using transferer context */
1134 set_c_e_p(transferee, transferer_real_context, xferto, 0);
1136 check_goto_on_transfer(transferer);
1139 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
1141 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
1142 finishup(transferee);
1145 ast_stopstream(transferer);
1146 res = finishup(transferee);
1148 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
1151 return AST_FEATURE_RETURN_SUCCESS;
1155 * \brief make channels compatible
1158 * \retval 0 on success.
1159 * \retval -1 on failure.
1161 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
1163 if (ast_channel_make_compatible(c, newchan) < 0) {
1164 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
1165 c->name, newchan->name);
1166 ast_hangup(newchan);
1173 * \brief Attended transfer
1174 * \param chan transfered user
1175 * \param peer person transfering call
1178 * \param sense feature options
1181 * Get extension to transfer to, if you cannot generate channel (or find extension)
1182 * return to host channel. After called channel answered wait for hangup of transferer,
1183 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
1185 * \return -1 on failure
1187 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1189 struct ast_channel *transferer;
1190 struct ast_channel *transferee;
1191 const char *transferer_real_context;
1192 char xferto[256] = "";
1195 struct ast_channel *newchan;
1196 struct ast_channel *xferchan;
1197 struct ast_bridge_thread_obj *tobj;
1198 struct ast_bridge_config bconfig;
1199 struct ast_frame *f;
1202 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
1203 set_peers(&transferer, &transferee, peer, chan, sense);
1204 transferer_real_context = real_ctx(transferer, transferee);
1205 /* Start autoservice on chan while we talk to the originator */
1206 ast_autoservice_start(transferee);
1207 ast_indicate(transferee, AST_CONTROL_HOLD);
1210 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1212 finishup(transferee);
1215 if (res > 0) /* If they've typed a digit already, handle it */
1216 xferto[0] = (char) res;
1218 /* this is specific of atxfer */
1219 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1220 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
1221 finishup(transferee);
1225 ast_log(LOG_WARNING, "Did not read data.\n");
1226 finishup(transferee);
1227 if (ast_stream_and_wait(transferer, "beeperr", ""))
1229 return AST_FEATURE_RETURN_SUCCESS;
1232 /* valid extension, res == 1 */
1233 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
1234 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
1235 finishup(transferee);
1236 if (ast_stream_and_wait(transferer, "beeperr", ""))
1238 return AST_FEATURE_RETURN_SUCCESS;
1242 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
1244 /* If we are performing an attended transfer and we have two channels involved then
1245 copy sound file information to play upon attended transfer completion */
1247 const char *chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
1248 const char *chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
1250 if (!ast_strlen_zero(chan1_attended_sound)) {
1251 pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
1253 if (!ast_strlen_zero(chan2_attended_sound)) {
1254 pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
1258 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1259 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1261 if (!ast_check_hangup(transferer)) {
1262 /* Transferer is up - old behaviour */
1263 ast_indicate(transferer, -1);
1265 finishup(transferee);
1266 /* any reason besides user requested cancel and busy triggers the failed sound */
1267 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
1268 ast_stream_and_wait(transferer, xferfailsound, ""))
1270 if (ast_stream_and_wait(transferer, xfersound, ""))
1271 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1272 return AST_FEATURE_RETURN_SUCCESS;
1275 if (check_compat(transferer, newchan)) {
1276 /* we do mean transferee here, NOT transferer */
1277 finishup(transferee);
1280 memset(&bconfig,0,sizeof(struct ast_bridge_config));
1281 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
1282 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
1283 res = ast_bridge_call(transferer, newchan, &bconfig);
1284 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
1285 ast_hangup(newchan);
1286 if (ast_stream_and_wait(transferer, xfersound, ""))
1287 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1288 finishup(transferee);
1289 transferer->_softhangup = 0;
1290 return AST_FEATURE_RETURN_SUCCESS;
1292 if (check_compat(transferee, newchan)) {
1293 finishup(transferee);
1296 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1298 if ((ast_autoservice_stop(transferee) < 0)
1299 || (ast_waitfordigit(transferee, 100) < 0)
1300 || (ast_waitfordigit(newchan, 100) < 0)
1301 || ast_check_hangup(transferee)
1302 || ast_check_hangup(newchan)) {
1303 ast_hangup(newchan);
1306 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1308 ast_hangup(newchan);
1311 /* Make formats okay */
1312 xferchan->visible_indication = transferer->visible_indication;
1313 xferchan->readformat = transferee->readformat;
1314 xferchan->writeformat = transferee->writeformat;
1315 ast_channel_masquerade(xferchan, transferee);
1316 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1317 xferchan->_state = AST_STATE_UP;
1318 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1319 xferchan->_softhangup = 0;
1320 if ((f = ast_read(xferchan)))
1322 newchan->_state = AST_STATE_UP;
1323 ast_clear_flag(newchan, AST_FLAGS_ALL);
1324 newchan->_softhangup = 0;
1325 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1326 ast_hangup(xferchan);
1327 ast_hangup(newchan);
1330 tobj->chan = newchan;
1331 tobj->peer = xferchan;
1332 tobj->bconfig = *config;
1334 if (ast_stream_and_wait(newchan, xfersound, ""))
1335 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1336 ast_bridge_call_thread_launch(tobj);
1337 return -1; /* XXX meaning the channel is bridged ? */
1338 } else if (!ast_check_hangup(transferee)) {
1339 /* act as blind transfer */
1340 if (ast_autoservice_stop(transferee) < 0) {
1341 ast_hangup(newchan);
1346 unsigned int tries = 0;
1347 char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
1349 transferer_tech = strsep(&transferer_name, "/");
1350 transferer_name = strsep(&transferer_name, "-");
1352 if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
1353 ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
1354 if (ast_stream_and_wait(transferee, "beeperr", ""))
1356 return AST_FEATURE_RETURN_SUCCESS;
1359 ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
1360 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1361 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1362 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1363 /* Trying to transfer again */
1364 ast_autoservice_start(transferee);
1365 ast_indicate(transferee, AST_CONTROL_HOLD);
1367 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1368 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1369 if (ast_autoservice_stop(transferee) < 0) {
1371 ast_hangup(newchan);
1375 /* Transfer failed, sleeping */
1376 ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1377 ast_safe_sleep(transferee, atxferloopdelay);
1378 ast_debug(1, "Trying to callback...\n");
1379 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1380 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1388 /* newchan is up, we should prepare transferee and bridge them */
1389 if (check_compat(transferee, newchan)) {
1390 finishup(transferee);
1393 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1395 if ((ast_waitfordigit(transferee, 100) < 0)
1396 || (ast_waitfordigit(newchan, 100) < 0)
1397 || ast_check_hangup(transferee)
1398 || ast_check_hangup(newchan)) {
1399 ast_hangup(newchan);
1403 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1405 ast_hangup(newchan);
1408 /* Make formats okay */
1409 xferchan->visible_indication = transferer->visible_indication;
1410 xferchan->readformat = transferee->readformat;
1411 xferchan->writeformat = transferee->writeformat;
1412 ast_channel_masquerade(xferchan, transferee);
1413 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1414 xferchan->_state = AST_STATE_UP;
1415 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1416 xferchan->_softhangup = 0;
1417 if ((f = ast_read(xferchan)))
1419 newchan->_state = AST_STATE_UP;
1420 ast_clear_flag(newchan, AST_FLAGS_ALL);
1421 newchan->_softhangup = 0;
1422 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1423 ast_hangup(xferchan);
1424 ast_hangup(newchan);
1427 tobj->chan = newchan;
1428 tobj->peer = xferchan;
1429 tobj->bconfig = *config;
1431 if (ast_stream_and_wait(newchan, xfersound, ""))
1432 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1433 ast_bridge_call_thread_launch(tobj);
1434 return -1; /* XXX meaning the channel is bridged ? */
1436 /* Transferee hung up */
1437 finishup(transferee);
1442 /* add atxfer and automon as undefined so you can only use em if you configure them */
1443 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1445 AST_RWLOCK_DEFINE_STATIC(features_lock);
1447 static struct ast_call_feature builtin_features[] =
1449 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1450 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1451 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1452 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1453 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1454 { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1458 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1460 /*! \brief register new feature into feature_list*/
1461 void ast_register_feature(struct ast_call_feature *feature)
1464 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1468 AST_LIST_LOCK(&feature_list);
1469 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1470 AST_LIST_UNLOCK(&feature_list);
1472 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1476 * \brief Add new feature group
1477 * \param fgname feature group name.
1479 * Add new feature group to the feature group list insert at head of list.
1480 * \note This function MUST be called while feature_groups is locked.
1482 static struct feature_group* register_group(const char *fgname)
1484 struct feature_group *fg;
1487 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1491 if (!(fg = ast_calloc(1, sizeof(*fg))))
1494 if (ast_string_field_init(fg, 128)) {
1499 ast_string_field_set(fg, gname, fgname);
1501 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1503 ast_verb(2, "Registered group '%s'\n", fg->gname);
1509 * \brief Add feature to group
1510 * \param fg feature group
1512 * \param feature feature to add.
1514 * Check fg and feature specified, add feature to list
1515 * \note This function MUST be called while feature_groups is locked.
1517 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
1519 struct feature_group_exten *fge;
1522 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1527 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1531 if (!(fge = ast_calloc(1, sizeof(*fge))))
1534 if (ast_string_field_init(fge, 128)) {
1539 ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
1541 fge->feature = feature;
1543 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
1545 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1546 feature->sname, fg->gname, exten);
1549 void ast_unregister_feature(struct ast_call_feature *feature)
1554 AST_LIST_LOCK(&feature_list);
1555 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1556 AST_LIST_UNLOCK(&feature_list);
1560 /*! \brief Remove all features in the list */
1561 static void ast_unregister_features(void)
1563 struct ast_call_feature *feature;
1565 AST_LIST_LOCK(&feature_list);
1566 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1568 AST_LIST_UNLOCK(&feature_list);
1571 /*! \brief find a call feature by name */
1572 static struct ast_call_feature *find_dynamic_feature(const char *name)
1574 struct ast_call_feature *tmp;
1576 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1577 if (!strcasecmp(tmp->sname, name))
1584 /*! \brief Remove all feature groups in the list */
1585 static void ast_unregister_groups(void)
1587 struct feature_group *fg;
1588 struct feature_group_exten *fge;
1590 AST_RWLIST_WRLOCK(&feature_groups);
1591 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1592 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1593 ast_string_field_free_memory(fge);
1597 ast_string_field_free_memory(fg);
1600 AST_RWLIST_UNLOCK(&feature_groups);
1604 * \brief Find a group by name
1605 * \param name feature name
1606 * \retval feature group on success.
1607 * \retval NULL on failure.
1609 static struct feature_group *find_group(const char *name) {
1610 struct feature_group *fg = NULL;
1612 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1613 if (!strcasecmp(fg->gname, name))
1620 void ast_rdlock_call_features(void)
1622 ast_rwlock_rdlock(&features_lock);
1625 void ast_unlock_call_features(void)
1627 ast_rwlock_unlock(&features_lock);
1630 struct ast_call_feature *ast_find_call_feature(const char *name)
1633 for (x = 0; x < FEATURES_COUNT; x++) {
1634 if (!strcasecmp(name, builtin_features[x].sname))
1635 return &builtin_features[x];
1641 * \brief exec an app by feature
1642 * \param chan,peer,config,code,sense,data
1644 * Find a feature, determine which channel activated
1645 * \retval AST_FEATURE_RETURN_PBX_KEEPALIVE,AST_FEATURE_RETURN_NO_HANGUP_PEER
1647 * \retval -2 when an application cannot be found.
1649 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1651 struct ast_app *app;
1652 struct ast_call_feature *feature = data;
1653 struct ast_channel *work, *idle;
1656 if (!feature) { /* shouldn't ever happen! */
1657 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1661 if (sense == FEATURE_SENSE_CHAN) {
1662 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1663 return AST_FEATURE_RETURN_KEEPTRYING;
1664 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1672 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1673 return AST_FEATURE_RETURN_KEEPTRYING;
1674 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1683 if (!(app = pbx_findapp(feature->app))) {
1684 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1688 ast_autoservice_start(idle);
1690 if (!ast_strlen_zero(feature->moh_class))
1691 ast_moh_start(idle, feature->moh_class, NULL);
1693 res = pbx_exec(work, app, feature->app_args);
1695 if (!ast_strlen_zero(feature->moh_class))
1698 ast_autoservice_stop(idle);
1700 if (res == AST_PBX_KEEPALIVE) {
1701 /* do not hangup peer if feature is to be activated on it */
1702 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))
1703 return AST_FEATURE_RETURN_NO_HANGUP_PEER;
1705 return AST_FEATURE_RETURN_PBX_KEEPALIVE;
1707 else if (res == AST_PBX_NO_HANGUP_PEER)
1708 return AST_FEATURE_RETURN_NO_HANGUP_PEER;
1710 return AST_FEATURE_RETURN_SUCCESSBREAK;
1712 return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1715 static void unmap_features(void)
1719 ast_rwlock_wrlock(&features_lock);
1720 for (x = 0; x < FEATURES_COUNT; x++)
1721 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1722 ast_rwlock_unlock(&features_lock);
1725 static int remap_feature(const char *name, const char *value)
1729 ast_rwlock_wrlock(&features_lock);
1730 for (x = 0; x < FEATURES_COUNT; x++) {
1731 if (strcasecmp(builtin_features[x].sname, name))
1734 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1738 ast_rwlock_unlock(&features_lock);
1744 * \brief Check the dynamic features
1745 * \param chan,peer,config,code,sense
1747 * Lock features list, browse for code, unlock list
1748 * \retval res on success.
1749 * \retval -1 on failure.
1751 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1754 struct ast_flags features;
1755 struct ast_call_feature *feature;
1756 struct feature_group *fg = NULL;
1757 struct feature_group_exten *fge;
1758 const char *dynamic_features;
1760 int res = AST_FEATURE_RETURN_PASSDIGITS;
1761 int feature_detected = 0;
1763 if (sense == FEATURE_SENSE_CHAN) {
1764 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1765 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1768 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1769 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
1771 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);
1773 ast_rwlock_rdlock(&features_lock);
1774 for (x = 0; x < FEATURES_COUNT; x++) {
1775 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1776 !ast_strlen_zero(builtin_features[x].exten)) {
1777 /* Feature is up for consideration */
1778 if (!strcmp(builtin_features[x].exten, code)) {
1779 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1780 feature_detected = 1;
1782 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1783 if (res == AST_FEATURE_RETURN_PASSDIGITS)
1784 res = AST_FEATURE_RETURN_STOREDIGITS;
1788 ast_rwlock_unlock(&features_lock);
1790 if (ast_strlen_zero(dynamic_features) || feature_detected)
1793 tmp = ast_strdupa(dynamic_features);
1795 while ((tok = strsep(&tmp, "#"))) {
1796 AST_RWLIST_RDLOCK(&feature_groups);
1798 fg = find_group(tok);
1801 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1802 if (strcasecmp(fge->exten, code))
1805 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
1806 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
1807 AST_RWLIST_UNLOCK(&feature_groups);
1810 res = AST_FEATURE_RETURN_PASSDIGITS;
1816 AST_RWLIST_UNLOCK(&feature_groups);
1817 AST_LIST_LOCK(&feature_list);
1819 if(!(feature = find_dynamic_feature(tok))) {
1820 AST_LIST_UNLOCK(&feature_list);
1824 /* Feature is up for consideration */
1825 if (!strcmp(feature->exten, code)) {
1826 ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1827 res = feature->operation(chan, peer, config, code, sense, feature);
1828 if (res != AST_FEATURE_RETURN_KEEPTRYING) {
1829 AST_LIST_UNLOCK(&feature_list);
1832 res = AST_FEATURE_RETURN_PASSDIGITS;
1833 } else if (!strncmp(feature->exten, code, strlen(code)))
1834 res = AST_FEATURE_RETURN_STOREDIGITS;
1836 AST_LIST_UNLOCK(&feature_list);
1842 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1846 ast_clear_flag(config, AST_FLAGS_ALL);
1848 ast_rwlock_rdlock(&features_lock);
1849 for (x = 0; x < FEATURES_COUNT; x++) {
1850 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1853 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1854 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1856 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1857 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1859 ast_rwlock_unlock(&features_lock);
1861 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1862 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1864 if (dynamic_features) {
1865 char *tmp = ast_strdupa(dynamic_features);
1867 struct ast_call_feature *feature;
1869 /* while we have a feature */
1870 while ((tok = strsep(&tmp, "#"))) {
1871 AST_LIST_LOCK(&feature_list);
1872 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1873 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1874 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1875 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1876 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1878 AST_LIST_UNLOCK(&feature_list);
1885 * \brief Get feature and dial
1886 * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1888 * Request channel, set channel variables, initiate call,check if they want to disconnect
1889 * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1890 * check for answer break loop, set cdr return channel.
1892 * \todo XXX Check - this is very similar to the code in channel.c
1893 * \return always a channel
1895 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)
1900 struct ast_channel *chan;
1901 struct ast_channel *monitor_chans[2];
1902 struct ast_channel *active_channel;
1903 int res = 0, ready = 0;
1905 if ((chan = ast_request(type, format, data, &cause))) {
1906 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1907 ast_string_field_set(chan, language, language);
1908 ast_channel_inherit_variables(caller, chan);
1909 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1911 if (!ast_call(chan, data, timeout)) {
1912 struct timeval started;
1914 char *disconnect_code = NULL, *dialed_code = NULL;
1916 ast_indicate(caller, AST_CONTROL_RINGING);
1917 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1918 ast_rwlock_rdlock(&features_lock);
1919 for (x = 0; x < FEATURES_COUNT; x++) {
1920 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1923 disconnect_code = builtin_features[x].exten;
1924 len = strlen(disconnect_code) + 1;
1925 dialed_code = alloca(len);
1926 memset(dialed_code, 0, len);
1929 ast_rwlock_unlock(&features_lock);
1931 started = ast_tvnow();
1934 ast_poll_channel_add(caller, chan);
1936 while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1937 struct ast_frame *f = NULL;
1939 monitor_chans[0] = caller;
1940 monitor_chans[1] = chan;
1941 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1943 /* see if the timeout has been violated */
1944 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1945 state = AST_CONTROL_UNHOLD;
1946 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1947 break; /*doh! timeout*/
1950 if (!active_channel)
1953 if (chan && (chan == active_channel)){
1955 if (f == NULL) { /*doh! where'd he go?*/
1956 state = AST_CONTROL_HANGUP;
1961 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1962 if (f->subclass == AST_CONTROL_RINGING) {
1963 state = f->subclass;
1964 ast_verb(3, "%s is ringing\n", chan->name);
1965 ast_indicate(caller, AST_CONTROL_RINGING);
1966 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1967 state = f->subclass;
1968 ast_verb(3, "%s is busy\n", chan->name);
1969 ast_indicate(caller, AST_CONTROL_BUSY);
1973 } else if (f->subclass == AST_CONTROL_ANSWER) {
1974 /* This is what we are hoping for */
1975 state = f->subclass;
1980 } else if (f->subclass != -1) {
1981 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1983 /* else who cares */
1986 } else if (caller && (active_channel == caller)) {
1987 f = ast_read(caller);
1988 if (f == NULL) { /*doh! where'd he go?*/
1989 if (!igncallerstate) {
1990 if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
1991 /* make this a blind transfer */
1995 state = AST_CONTROL_HANGUP;
2001 if (f->frametype == AST_FRAME_DTMF) {
2002 dialed_code[x++] = f->subclass;
2003 dialed_code[x] = '\0';
2004 if (strlen(dialed_code) == len) {
2006 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
2008 dialed_code[x] = '\0';
2010 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
2011 /* Caller Canceled the call */
2012 state = AST_CONTROL_UNHOLD;
2024 ast_poll_channel_del(caller, chan);
2027 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
2029 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
2031 case AST_CAUSE_BUSY:
2032 state = AST_CONTROL_BUSY;
2034 case AST_CAUSE_CONGESTION:
2035 state = AST_CONTROL_CONGESTION;
2040 ast_indicate(caller, -1);
2041 if (chan && ready) {
2042 if (chan->_state == AST_STATE_UP)
2043 state = AST_CONTROL_ANSWER;
2060 * \brief return the first unlocked cdr in a possible chain
2062 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
2064 struct ast_cdr *cdr_orig = cdr;
2066 if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
2070 return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
2074 * \brief bridge the call and set CDR
2075 * \param chan,peer,config
2077 * Set start time, check for two channels,check if monitor on
2078 * check for feature activation, create new CDR
2079 * \retval res on success.
2080 * \retval -1 on failure to bridge.
2082 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
2084 /* Copy voice back and forth between the two channels. Give the peer
2085 the ability to transfer calls with '#<extension' syntax. */
2086 struct ast_frame *f;
2087 struct ast_channel *who;
2088 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
2089 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
2090 char orig_channame[AST_MAX_EXTENSION];
2091 char orig_peername[AST_MAX_EXTENSION];
2096 struct ast_option_header *aoh;
2097 struct ast_bridge_config backup_config;
2098 struct ast_cdr *bridge_cdr = NULL;
2099 struct ast_cdr *orig_peer_cdr = NULL;
2100 struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
2101 struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
2102 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
2103 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
2105 memset(&backup_config, 0, sizeof(backup_config));
2107 config->start_time = ast_tvnow();
2110 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
2111 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
2113 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
2116 const char *monitor_exec;
2117 struct ast_channel *src = NULL;
2119 if (!(monitor_app = pbx_findapp("Monitor")))
2122 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
2124 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
2126 if (monitor_app && src) {
2127 char *tmp = ast_strdupa(monitor_exec);
2128 pbx_exec(src, monitor_app, tmp);
2132 set_config_flags(chan, peer, config);
2133 config->firstpass = 1;
2135 /* Answer if need be */
2136 if (ast_answer(chan))
2139 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
2140 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
2141 orig_peer_cdr = peer_cdr;
2143 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
2146 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
2147 ast_cdr_update(chan);
2148 bridge_cdr = ast_cdr_dup(chan_cdr);
2149 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
2150 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
2152 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
2153 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
2154 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
2155 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
2156 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
2157 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
2158 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
2159 ast_cdr_setcid(bridge_cdr, chan);
2160 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
2161 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
2162 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
2163 /* Destination information */
2164 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
2165 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
2167 bridge_cdr->start = peer_cdr->start;
2168 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
2170 ast_cdr_start(bridge_cdr);
2173 ast_debug(4,"bridge answer set, chan answer set\n");
2174 /* peer_cdr->answer will be set when a macro runs on the peer;
2175 in that case, the bridge answer will be delayed while the
2176 macro plays on the peer channel. The peer answered the call
2177 before the macro started playing. To the phone system,
2178 this is billable time for the call, even tho the caller
2179 hears nothing but ringing while the macro does its thing. */
2180 if (peer_cdr && !ast_tvzero(peer_cdr->answer)) {
2181 bridge_cdr->answer = peer_cdr->answer;
2182 chan_cdr->answer = peer_cdr->answer;
2183 bridge_cdr->disposition = peer_cdr->disposition;
2184 chan_cdr->disposition = peer_cdr->disposition;
2186 ast_cdr_answer(bridge_cdr);
2187 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
2189 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
2191 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
2195 struct ast_channel *other; /* used later */
2197 res = ast_channel_bridge(chan, peer, config, &f, &who);
2199 if (config->feature_timer) {
2200 /* Update time limit for next pass */
2201 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
2202 config->feature_timer -= diff;
2204 /* Running on backup config, meaning a feature might be being
2205 activated, but that's no excuse to keep things going
2207 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
2208 ast_debug(1, "Timed out, realtime this time!\n");
2209 config->feature_timer = 0;
2215 } else if (config->feature_timer <= 0) {
2216 /* Not *really* out of time, just out of time for
2217 digits to come in for features. */
2218 ast_debug(1, "Timed out for feature!\n");
2219 if (!ast_strlen_zero(peer_featurecode)) {
2220 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
2221 memset(peer_featurecode, 0, sizeof(peer_featurecode));
2223 if (!ast_strlen_zero(chan_featurecode)) {
2224 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
2225 memset(chan_featurecode, 0, sizeof(chan_featurecode));
2229 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
2231 /* Restore original (possibly time modified) bridge config */
2232 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
2233 memset(&backup_config, 0, sizeof(backup_config));
2235 hadfeatures = hasfeatures;
2236 /* Continue as we were */
2239 /* The bridge returned without a frame and there is a feature in progress.
2240 * However, we don't think the feature has quite yet timed out, so just
2241 * go back into the bridge. */
2245 if (config->feature_timer <=0) {
2246 /* We ran out of time */
2247 config->feature_timer = 0;
2257 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
2258 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
2262 if (!f || (f->frametype == AST_FRAME_CONTROL &&
2263 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
2264 f->subclass == AST_CONTROL_CONGESTION))) {
2268 /* many things should be sent to the 'other' channel */
2269 other = (who == chan) ? peer : chan;
2270 if (f->frametype == AST_FRAME_CONTROL) {
2271 switch (f->subclass) {
2272 case AST_CONTROL_RINGING:
2273 case AST_CONTROL_FLASH:
2275 ast_indicate(other, f->subclass);
2277 case AST_CONTROL_HOLD:
2278 case AST_CONTROL_UNHOLD:
2279 ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
2281 case AST_CONTROL_OPTION:
2283 /* Forward option Requests */
2284 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
2285 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
2286 f->datalen - sizeof(struct ast_option_header), 0);
2290 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
2292 } else if (f->frametype == AST_FRAME_DTMF) {
2296 hadfeatures = hasfeatures;
2297 /* This cannot overrun because the longest feature is one shorter than our buffer */
2299 sense = FEATURE_SENSE_CHAN;
2300 featurecode = chan_featurecode;
2302 sense = FEATURE_SENSE_PEER;
2303 featurecode = peer_featurecode;
2305 /*! append the event to featurecode. we rely on the string being zero-filled, and
2306 * not overflowing it.
2307 * \todo XXX how do we guarantee the latter ?
2309 featurecode[strlen(featurecode)] = f->subclass;
2310 /* Get rid of the frame before we start doing "stuff" with the channels */
2313 config->feature_timer = backup_config.feature_timer;
2314 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
2316 case AST_FEATURE_RETURN_PASSDIGITS:
2317 ast_dtmf_stream(other, who, featurecode, 0, 0);
2319 case AST_FEATURE_RETURN_SUCCESS:
2320 memset(featurecode, 0, sizeof(chan_featurecode));
2323 if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
2327 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
2328 if (hadfeatures && !hasfeatures) {
2329 /* Restore backup */
2330 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
2331 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
2332 } else if (hasfeatures) {
2334 /* Backup configuration */
2335 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
2336 /* Setup temporary config options */
2337 config->play_warning = 0;
2338 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
2339 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
2340 config->warning_freq = 0;
2341 config->warning_sound = NULL;
2342 config->end_sound = NULL;
2343 config->start_sound = NULL;
2344 config->firstpass = 0;
2346 config->start_time = ast_tvnow();
2347 config->feature_timer = featuredigittimeout;
2348 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
2356 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
2357 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
2359 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
2360 struct ast_cdr *swapper;
2361 char savelastapp[AST_MAX_EXTENSION];
2362 char savelastdata[AST_MAX_EXTENSION];
2363 char save_exten[AST_MAX_EXTENSION];
2365 int found = 0; /* set if we find at least one match */
2367 if (ast_opt_end_cdr_before_h_exten) {
2368 ast_cdr_end(bridge_cdr);
2370 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
2371 dialplan code operate on it */
2372 swapper = chan->cdr;
2373 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
2374 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
2375 ast_channel_lock(chan);
2376 chan->cdr = bridge_cdr;
2377 ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
2378 save_prio = chan->priority;
2379 ast_copy_string(chan->exten, "h", sizeof(chan->exten));
2381 ast_channel_unlock(chan);
2382 while ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1))) {
2387 /* Something bad happened, or a hangup has been requested. */
2388 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
2389 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
2392 ast_channel_lock(chan);
2393 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
2394 chan->priority = save_prio;
2395 chan->cdr = swapper;
2396 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
2397 ast_channel_unlock(chan);
2398 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
2399 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
2400 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
2403 /* obey the NoCDR() wishes. */
2404 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))
2405 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
2406 if (!new_chan_cdr || (new_chan_cdr && !ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
2407 struct ast_channel *chan_ptr = NULL;
2409 ast_cdr_end(bridge_cdr);
2411 ast_cdr_detach(bridge_cdr);
2413 /* do a specialized reset on the beginning channel
2414 CDR's, if they still exist, so as not to mess up
2415 issues in future bridges;
2417 Here are the rules of the game:
2418 1. The chan and peer channel pointers will not change
2419 during the life of the bridge.
2420 2. But, in transfers, the channel names will change.
2421 between the time the bridge is started, and the
2422 time the channel ends.
2423 Usually, when a channel changes names, it will
2424 also change CDR pointers.
2425 3. Usually, only one of the two channels (chan or peer)
2427 4. Usually, if a channel changes names during a bridge,
2428 it is because of a transfer. Usually, in these situations,
2429 it is normal to see 2 bridges running simultaneously, and
2430 it is not unusual to see the two channels that change
2431 swapped between bridges.
2432 5. After a bridge occurs, we have 2 or 3 channels' CDRs
2433 to attend to; if the chan or peer changed names,
2434 we have the before and after attached CDR's.
2437 if (strcasecmp(orig_channame, chan->name) != 0) {
2439 chan_ptr = ast_get_channel_by_name_locked(orig_channame);
2441 if (!ast_bridged_channel(chan_ptr)) {
2442 struct ast_cdr *cur;
2443 for (cur = chan_ptr->cdr; cur; cur = cur->next) {
2444 if (cur == chan_cdr) {
2449 ast_cdr_specialized_reset(chan_cdr,0);
2451 ast_channel_unlock(chan_ptr);
2454 ast_cdr_specialized_reset(new_chan_cdr,0);
2456 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */
2458 if (strcasecmp(orig_peername, peer->name) != 0) {
2460 chan_ptr = ast_get_channel_by_name_locked(orig_peername);
2462 if (!ast_bridged_channel(chan_ptr)) {
2463 struct ast_cdr *cur;
2464 for (cur = chan_ptr->cdr; cur; cur = cur->next) {
2465 if (cur == peer_cdr) {
2470 ast_cdr_specialized_reset(peer_cdr,0);
2472 ast_channel_unlock(chan_ptr);
2475 ast_cdr_specialized_reset(new_peer_cdr,0);
2477 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */
2483 /*! \brief Output parking event to manager */
2484 static void post_manager_event(const char *s, struct parkeduser *pu)
2486 manager_event(EVENT_FLAG_CALL, s,
2489 "Parkinglot: %s\r\n"
2490 "CallerIDNum: %s\r\n"
2491 "CallerIDName: %s\r\n"
2492 "UniqueID: %s\r\n\r\n",
2495 pu->parkinglot->name,
2496 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2497 S_OR(pu->chan->cid.cid_name, "<unknown>"),
2502 /*! \brief Run management on parkinglots, collad once per parkinglot */
2503 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max)
2506 struct parkeduser *pu;
2508 char parkingslot[AST_MAX_EXTENSION];
2510 /* TODO: I believe this reference increase is not necessary since the iterator in the calling function already did so */
2511 //parkinglot_addref(curlot);
2512 /* Lock parking list */
2513 AST_LIST_LOCK(&curlot->parkings);
2514 AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
2515 struct ast_channel *chan = pu->chan; /* shorthand */
2516 int tms; /* timeout for this item */
2517 int x; /* fd index in channel */
2518 struct ast_context *con;
2520 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
2523 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2524 if (tms > pu->parkingtime) {
2525 /* Stop music on hold */
2526 ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
2527 /* Get chan, exten from derived kludge */
2528 if (pu->peername[0]) {
2529 char *peername = ast_strdupa(pu->peername);
2530 char *cp = strrchr(peername, '-');
2531 char peername_flat[AST_MAX_EXTENSION]; /* using something like DAHDI/52 for an extension name is NOT a good idea */
2536 ast_copy_string(peername_flat,peername,sizeof(peername_flat));
2537 for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
2538 if (peername_flat[i] == '/')
2539 peername_flat[i]= '0';
2541 con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
2543 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
2546 char returnexten[AST_MAX_EXTENSION];
2547 struct ast_datastore *features_datastore;
2548 struct ast_dial_features *dialfeatures = NULL;
2550 ast_channel_lock(chan);
2552 if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
2553 dialfeatures = features_datastore->data;
2555 ast_channel_unlock(chan);
2558 snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
2559 else /* Existing default */
2560 snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
2562 ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
2564 if (comebacktoorigin) {
2565 set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
2567 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2568 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2569 pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
2570 set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
2573 /* They've been waiting too long, send them back to where they came. Theoretically they
2574 should have their original extensions and such, but we copy to be on the safe side */
2575 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2577 post_manager_event("ParkedCallTimeOut", pu);
2579 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);
2580 /* Start up the PBX, or hang them up */
2581 if (ast_pbx_start(chan)) {
2582 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
2585 /* And take them out of the parking lot */
2586 con = ast_context_find(pu->parkinglot->parking_con);
2588 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
2589 ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
2591 notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
2593 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2594 AST_LIST_REMOVE_CURRENT(list);
2595 parkinglot_unref(curlot);
2596 } else { /* still within parking time, process descriptors */
2597 for (x = 0; x < AST_MAX_FDS; x++) {
2598 struct ast_frame *f;
2600 if ((chan->fds[x] == -1) || (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds)))
2603 if (FD_ISSET(chan->fds[x], efds))
2604 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2606 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2609 /* See if they need servicing */
2610 f = ast_read(pu->chan);
2612 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2615 post_manager_event("ParkedCallGiveUp", pu);
2617 /* There's a problem, hang them up*/
2618 ast_verb(2, "%s got tired of being parked\n", chan->name);
2620 /* And take them out of the parking lot */
2621 con = ast_context_find(curlot->parking_con);
2623 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
2624 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2626 notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
2628 ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
2629 AST_LIST_REMOVE_CURRENT(list);
2630 parkinglot_unref(curlot);
2633 /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2635 if (pu->moh_trys < 3 && !chan->generatordata) {
2636 ast_debug(1, "MOH on parked call stopped by outside source. Restarting on channel %s.\n", chan->name);
2637 ast_indicate_data(chan, AST_CONTROL_HOLD,
2638 S_OR(curlot->mohclass, NULL),
2639 (!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
2642 goto std; /* XXX Ick: jumping into an else statement??? XXX */
2645 if (x >= AST_MAX_FDS) {
2646 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2647 if (chan->fds[x] > -1) {
2648 FD_SET(chan->fds[x], nrfds);
2649 FD_SET(chan->fds[x], nefds);
2650 if (chan->fds[x] > *max)
2651 *max = chan->fds[x];
2654 /* Keep track of our shortest wait */
2655 if (tms < *ms || *ms < 0)
2660 AST_LIST_TRAVERSE_SAFE_END;
2661 AST_LIST_UNLOCK(&curlot->parkings);
2666 * \brief Take care of parked calls and unpark them if needed
2667 * \param ignore unused var.
2669 * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2670 * if so, remove channel from parking lot and return it to the extension that parked it.
2671 * Check if parked channel decided to hangup, wait until next FD via select().
2673 static void *do_parking_thread(void *ignore)
2675 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
2676 fd_set nrfds, nefds; /* args for the next select */
2682 int ms = -1; /* select timeout, uninitialized */
2683 int max = -1; /* max fd, none there yet */
2684 struct ao2_iterator iter;
2685 struct ast_parkinglot *curlot;
2688 iter = ao2_iterator_init(parkinglots, 0);
2690 while ((curlot = ao2_iterator_next(&iter))) {
2691 res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max);
2692 ao2_ref(curlot, -1);
2698 struct timeval wait = ast_samp2tv(ms, 1000);
2699 /* Wait for something to happen */
2700 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &wait : NULL);
2702 pthread_testcancel();
2704 return NULL; /* Never reached */
2707 /*! \brief Find parkinglot by name */
2708 struct ast_parkinglot *find_parkinglot(const char *name)
2710 struct ast_parkinglot *parkinglot = NULL;
2711 struct ast_parkinglot tmp_parkinglot;
2713 if (ast_strlen_zero(name))
2716 ast_copy_string(tmp_parkinglot.name, name, sizeof(tmp_parkinglot.name));
2718 parkinglot = ao2_find(parkinglots, &tmp_parkinglot, OBJ_POINTER);
2720 if (parkinglot && option_debug)
2721 ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
2726 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
2727 AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
2728 AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
2729 AST_APP_OPTION('s', AST_PARK_OPT_SILENCE),
2732 /*! \brief Park a call */
2733 static int park_call_exec(struct ast_channel *chan, void *data)
2735 /* Cache the original channel name in case we get masqueraded in the middle
2736 * of a park--it is still theoretically possible for a transfer to happen before
2737 * we get here, but it is _really_ unlikely */
2738 char *orig_chan_name = ast_strdupa(chan->name);
2739 char orig_exten[AST_MAX_EXTENSION];
2740 int orig_priority = chan->priority;
2742 /* Data is unused at the moment but could contain a parking
2743 lot context eventually */
2747 AST_DECLARE_APP_ARGS(app_args,
2748 AST_APP_ARG(timeout);
2749 AST_APP_ARG(return_con);
2750 AST_APP_ARG(return_ext);
2751 AST_APP_ARG(return_pri);
2752 AST_APP_ARG(options);
2755 if (!ast_strlen_zero(data)) {
2756 parse = ast_strdupa(data);
2757 AST_STANDARD_APP_ARGS(app_args, parse);
2760 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
2762 /* Setup the exten/priority to be s/1 since we don't know
2763 where this call should return */
2764 strcpy(chan->exten, "s");
2767 /* Answer if call is not up */
2768 if (chan->_state != AST_STATE_UP)
2769 res = ast_answer(chan);
2771 /* Sleep to allow VoIP streams to settle down */
2773 res = ast_safe_sleep(chan, 1000);
2777 struct ast_park_call_args args = {
2778 .orig_chan_name = orig_chan_name,
2780 struct ast_flags flags = { 0 };
2782 if (parse && !ast_strlen_zero(app_args.timeout)) {
2783 if (sscanf(app_args.timeout, "%d", &args.timeout) != 1) {
2784 ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout);
2789 args.return_con = app_args.return_con;
2790 args.return_ext = app_args.return_ext;
2791 if (parse && !ast_strlen_zero(app_args.return_pri)) {
2792 if (sscanf(app_args.return_pri, "%d", &args.return_pri) != 1) {
2793 ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri);
2794 args.return_pri = 0;
2798 ast_app_parse_options(park_call_options, &flags, NULL, app_args.options);
2799 args.flags = flags.flags;
2801 res = ast_park_call_full(chan, chan, &args);
2802 /* Continue on in the dialplan */
2804 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
2805 chan->priority = orig_priority;
2808 res = AST_PBX_KEEPALIVE;
2814 /*! \brief Pickup parked call */
2815 static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parkinglot *parkinglot)
2818 struct ast_channel *peer=NULL;
2819 struct parkeduser *pu;
2820 struct ast_context *con;
2822 struct ast_bridge_config config;
2825 park = atoi((char *)data);
2827 parkinglot = find_parkinglot(findparkinglotname(chan));
2829 parkinglot = default_parkinglot;
2831 AST_LIST_LOCK(&parkinglot->parkings);
2832 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
2833 if (!data || pu->parkingnum == park) {
2834 AST_LIST_REMOVE_CURRENT(list);
2838 AST_LIST_TRAVERSE_SAFE_END
2839 AST_LIST_UNLOCK(&parkinglot->parkings);
2843 con = ast_context_find(parkinglot->parking_con);
2845 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
2846 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2848 notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
2850 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2852 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2856 "CallerIDNum: %s\r\n"
2857 "CallerIDName: %s\r\n",
2858 pu->parkingexten, pu->chan->name, chan->name,
2859 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2860 S_OR(pu->chan->cid.cid_name, "<unknown>")
2865 /* JK02: it helps to answer the channel if not already up */
2866 if (chan->_state != AST_STATE_UP)
2869 //XXX Why do we unlock here ?
2870 // uncomment it for now, till my setup with debug_threads and detect_deadlocks starts to complain
2871 //ASTOBJ_UNLOCK(parkinglot);
2874 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2876 if (!ast_strlen_zero(courtesytone)) {
2878 ast_indicate(peer, AST_CONTROL_UNHOLD);
2879 if (parkedplay == 0) {
2880 error = ast_stream_and_wait(chan, courtesytone, "");
2881 } else if (parkedplay == 1) {
2882 error = ast_stream_and_wait(peer, courtesytone, "");
2883 } else if (parkedplay == 2) {
2884 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2885 !ast_streamfile(peer, courtesytone, chan->language)) {
2886 /*! \todo XXX we would like to wait on both! */
2887 res = ast_waitstream(chan, "");
2889 res = ast_waitstream(peer, "");
2895 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2900 ast_indicate(peer, AST_CONTROL_UNHOLD);
2902 res = ast_channel_make_compatible(chan, peer);
2904 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2908 /* This runs sorta backwards, since we give the incoming channel control, as if it
2909 were the person called. */
2910 ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
2912 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2913 ast_cdr_setdestchan(chan->cdr, peer->name);
2914 memset(&config, 0, sizeof(struct ast_bridge_config));
2915 if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2916 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2917 if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2918 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2919 if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2920 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2921 if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2922 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2923 res = ast_bridge_call(chan, peer, &config);
2925 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2926 ast_cdr_setdestchan(chan->cdr, peer->name);
2928 /* Simulate the PBX hanging up */
2929 if (res != AST_PBX_NO_HANGUP_PEER)
2933 /*! \todo XXX Play a message XXX */
2934 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2935 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2936 ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2943 static int park_exec(struct ast_channel *chan, void *data)
2945 return park_exec_full(chan, data, default_parkinglot);
2948 /*! \brief Unreference parkinglot object. If no more references,
2949 then go ahead and delete it */
2950 static void parkinglot_unref(struct ast_parkinglot *parkinglot)
2952 int refcount = ao2_ref(parkinglot, -1);
2953 if (option_debug > 2)
2954 ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
2957 static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
2959 int refcount = ao2_ref(parkinglot, +1);
2960 if (option_debug > 2)
2961 ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
2965 /*! \brief Allocate parking lot structure */
2966 static struct ast_parkinglot *create_parkinglot(char *name)
2968 struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
2973 newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);