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"
58 #define DEFAULT_PARK_TIME 45000
59 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
60 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
61 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
62 #define DEFAULT_ATXFER_DROP_CALL 0
63 #define DEFAULT_ATXFER_LOOP_DELAY 10000
64 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
66 #define AST_MAX_WATCHERS 256
69 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
70 AST_FEATURE_FLAG_ONPEER = (1 << 1),
71 AST_FEATURE_FLAG_ONSELF = (1 << 2),
72 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
73 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
74 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
77 struct feature_group_exten {
78 AST_LIST_ENTRY(feature_group_exten) entry;
79 AST_DECLARE_STRING_FIELDS(
80 AST_STRING_FIELD(exten);
82 struct ast_call_feature *feature;
85 struct feature_group {
86 AST_LIST_ENTRY(feature_group) entry;
87 AST_DECLARE_STRING_FIELDS(
88 AST_STRING_FIELD(gname);
90 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
93 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
95 static char *parkedcall = "ParkedCall";
97 static int parkaddhints = 0; /*!< Add parking hints automatically */
98 static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
99 static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
100 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
101 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
102 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
103 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
104 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
105 static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
106 static int parking_start; /*!< First available extension for parking */
107 static int parking_stop; /*!< Last available extension for parking */
109 static char courtesytone[256]; /*!< Courtesy tone */
110 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
111 static char xfersound[256]; /*!< Call transfer sound */
112 static char xferfailsound[256]; /*!< Call transfer failure sound */
114 static int parking_offset;
115 static int parkfindnext;
119 static int transferdigittimeout;
120 static int featuredigittimeout;
121 static int comebacktoorigin = 1;
123 static int atxfernoanswertimeout;
124 static unsigned int atxferdropcall;
125 static unsigned int atxferloopdelay;
126 static unsigned int atxfercallbackretries;
128 static char *registrar = "features"; /*!< Registrar for operations */
130 /* module and CLI command definitions */
131 static char *synopsis = "Answer a parked call";
133 static char *descrip = "ParkedCall(exten): "
134 "Used to connect to a parked call. This application is always\n"
135 "registered internally and does not need to be explicitly added\n"
136 "into the dialplan, although you should include the 'parkedcalls'\n"
137 "context. If no extension is provided, then the first available\n"
138 "parked call will be acquired.\n";
140 static char *parkcall = "Park";
142 static char *synopsis2 = "Park yourself";
144 static char *descrip2 = "Park(): "
145 "Used to park yourself (typically in combination with a supervised\n"
146 "transfer to know the parking space). This application is always\n"
147 "registered internally and does not need to be explicitly added\n"
148 "into the dialplan, although you should include the 'parkedcalls'\n"
149 "context (or the context specified in features.conf).\n\n"
150 "If you set the PARKINGEXTEN variable to an extension in your\n"
151 "parking context, Park() will park the call on that extension, unless\n"
152 "it already exists. In that case, execution will continue at next\n"
155 static struct ast_app *monitor_app = NULL;
156 static int monitor_ok = 1;
158 static struct ast_app *mixmonitor_app = NULL;
159 static int mixmonitor_ok = 1;
161 static struct ast_app *stopmixmonitor_app = NULL;
162 static int stopmixmonitor_ok = 1;
165 struct ast_channel *chan; /*!< Parking channel */
166 struct timeval start; /*!< Time the parking started */
167 int parkingnum; /*!< Parking lot */
168 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
169 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
170 char exten[AST_MAX_EXTENSION];
172 int parkingtime; /*!< Maximum length in parking lot before return */
175 unsigned char moh_trys;
176 AST_LIST_ENTRY(parkeduser) list;
179 static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
181 static pthread_t parking_thread;
183 const char *ast_parking_ext(void)
188 const char *ast_pickup_ext(void)
193 struct ast_bridge_thread_obj
195 struct ast_bridge_config bconfig;
196 struct ast_channel *chan;
197 struct ast_channel *peer;
198 unsigned int return_to_pbx:1;
204 * \brief store context, extension and priority
205 * \param chan, context, ext, pri
207 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
209 ast_copy_string(chan->context, context, sizeof(chan->context));
210 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
211 chan->priority = pri;
215 * \brief Check goto on transfer
218 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
219 * When found make sure the types are compatible. Check if channel is valid
220 * if so start the new channel else hangup the call.
222 static void check_goto_on_transfer(struct ast_channel *chan)
224 struct ast_channel *xferchan;
225 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
226 char *x, *goto_on_transfer;
229 if (ast_strlen_zero(val))
232 goto_on_transfer = ast_strdupa(val);
234 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
237 for (x = goto_on_transfer; x && *x; x++) {
241 /* Make formats okay */
242 xferchan->readformat = chan->readformat;
243 xferchan->writeformat = chan->writeformat;
244 ast_channel_masquerade(xferchan, chan);
245 ast_parseable_goto(xferchan, goto_on_transfer);
246 xferchan->_state = AST_STATE_UP;
247 ast_clear_flag(xferchan, AST_FLAGS_ALL);
248 xferchan->_softhangup = 0;
249 if ((f = ast_read(xferchan))) {
252 ast_pbx_start(xferchan);
254 ast_hangup(xferchan);
258 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);
261 * \brief bridge the call
262 * \param data thread bridge.
264 * Set Last Data for respective channels, reset cdr for channels
265 * bridge call, check if we're going back to dialplan
266 * if not hangup both legs of the call
268 static void *ast_bridge_call_thread(void *data)
270 struct ast_bridge_thread_obj *tobj = data;
273 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
274 tobj->chan->data = tobj->peer->name;
275 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
276 tobj->peer->data = tobj->chan->name;
278 if (tobj->chan->cdr) {
279 ast_cdr_reset(tobj->chan->cdr, NULL);
280 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
282 if (tobj->peer->cdr) {
283 ast_cdr_reset(tobj->peer->cdr, NULL);
284 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
287 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
289 if (tobj->return_to_pbx) {
290 if (!ast_check_hangup(tobj->peer)) {
291 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
292 res = ast_pbx_start(tobj->peer);
293 if (res != AST_PBX_SUCCESS)
294 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
296 ast_hangup(tobj->peer);
297 if (!ast_check_hangup(tobj->chan)) {
298 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
299 res = ast_pbx_start(tobj->chan);
300 if (res != AST_PBX_SUCCESS)
301 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
303 ast_hangup(tobj->chan);
305 ast_hangup(tobj->chan);
306 ast_hangup(tobj->peer);
315 * \brief create thread for the parked call
318 * Create thread and attributes, call ast_bridge_call_thread
320 static void ast_bridge_call_thread_launch(void *data)
324 struct sched_param sched;
326 pthread_attr_init(&attr);
327 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
328 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
329 pthread_attr_destroy(&attr);
330 memset(&sched, 0, sizeof(sched));
331 pthread_setschedparam(thread, SCHED_RR, &sched);
335 * \brief Announce call parking by ADSI
337 * \param parkingexten .
338 * Create message to show for ADSI, display message.
339 * \retval 0 on success.
340 * \retval -1 on failure.
342 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
345 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
347 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
349 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
351 res = ast_adsi_load_session(chan, NULL, 0, 1);
354 return ast_adsi_print(chan, message, justify, 1);
357 /*! \brief Notify metermaids that we've changed an extension */
358 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
360 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
361 exten, context, devstate2str(state));
363 ast_devstate_changed(state, "park:%s@%s", exten, context);
366 /*! \brief metermaids callback from devicestate.c */
367 static enum ast_device_state metermaidstate(const char *data)
372 context = ast_strdupa(data);
374 exten = strsep(&context, "@");
376 return AST_DEVICE_INVALID;
378 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
380 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
381 return AST_DEVICE_NOT_INUSE;
383 return AST_DEVICE_INUSE;
387 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name)
389 struct parkeduser *pu, *cur;
390 int i, x = -1, parking_range;
391 struct ast_context *con;
392 const char *parkingexten;
394 /* Allocate memory for parking data */
395 if (!(pu = ast_calloc(1, sizeof(*pu))))
398 /* Lock parking lot */
399 AST_LIST_LOCK(&parkinglot);
400 /* Check for channel variable PARKINGEXTEN */
401 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
402 if (!ast_strlen_zero(parkingexten)) {
403 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
404 AST_LIST_UNLOCK(&parkinglot);
406 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
407 return 1; /* Continue execution if possible */
409 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
410 x = atoi(parkingexten);
412 /* Select parking space within range */
413 parking_range = parking_stop - parking_start+1;
414 for (i = 0; i < parking_range; i++) {
415 x = (i + parking_offset) % parking_range + parking_start;
416 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
417 if (cur->parkingnum == x)
424 if (!(i < parking_range)) {
425 ast_log(LOG_WARNING, "No more parking spaces\n");
427 AST_LIST_UNLOCK(&parkinglot);
430 /* Set pointer for next parking */
432 parking_offset = x - parking_start + 1;
435 chan->appl = "Parked Call";
440 /* Put the parked channel on hold if we have two different channels */
442 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
443 S_OR(parkmohclass, NULL),
444 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
447 pu->start = ast_tvnow();
449 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
454 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
456 /* Remember what had been dialed, so that if the parking
457 expires, we try to come back to the same place */
458 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
459 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
460 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
461 AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
463 /* If parking a channel directly, don't quiet yet get parking running on it */
466 AST_LIST_UNLOCK(&parkinglot);
467 /* Wake up the (presumably select()ing) thread */
468 pthread_kill(parking_thread, SIGURG);
469 ast_verb(2, "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
471 if (pu->parkingnum != -1)
472 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
473 manager_event(EVENT_FLAG_CALL, "ParkedCall",
478 "CallerIDNum: %s\r\n"
479 "CallerIDName: %s\r\n",
480 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
481 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
482 S_OR(pu->chan->cid.cid_num, "<unknown>"),
483 S_OR(pu->chan->cid.cid_name, "<unknown>")
486 if (peer && adsipark && ast_adsi_available(peer)) {
487 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
488 ast_adsi_unload_session(peer);
491 con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
492 if (!con) /* Still no context? Bad */
493 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
494 /* Tell the peer channel the number of the parking space */
495 if (peer && ((pu->parkingnum != -1 && ast_strlen_zero(orig_chan_name)) || !strcasecmp(peer->name, orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
496 /* 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. */
497 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
498 ast_say_digits(peer, pu->parkingnum, "", peer->language);
499 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
502 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
503 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
505 if (pu->notquiteyet) {
506 /* Wake up parking thread if we're really done */
507 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
508 S_OR(parkmohclass, NULL),
509 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
511 pthread_kill(parking_thread, SIGURG);
516 /*! \brief Park a call */
517 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
519 return park_call_full(chan, peer, timeout, extout, NULL);
522 /* Park call via masquraded channel */
523 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
525 struct ast_channel *chan;
527 char *orig_chan_name = NULL;
529 /* Make a new, fake channel that we'll use to masquerade in the real one */
530 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
531 ast_log(LOG_WARNING, "Unable to create parked channel\n");
535 /* Make formats okay */
536 chan->readformat = rchan->readformat;
537 chan->writeformat = rchan->writeformat;
538 ast_channel_masquerade(chan, rchan);
540 /* Setup the extensions and such */
541 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
543 /* Make the masq execute */
544 if ((f = ast_read(chan)))
547 orig_chan_name = ast_strdupa(chan->name);
549 park_call_full(chan, peer, timeout, extout, orig_chan_name);
555 #define FEATURE_RETURN_HANGUP -1
556 #define FEATURE_RETURN_SUCCESSBREAK 0
557 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
558 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
559 #define FEATURE_RETURN_PASSDIGITS 21
560 #define FEATURE_RETURN_STOREDIGITS 22
561 #define FEATURE_RETURN_SUCCESS 23
562 #define FEATURE_RETURN_KEEPTRYING 24
564 #define FEATURE_SENSE_CHAN (1 << 0)
565 #define FEATURE_SENSE_PEER (1 << 1)
568 * \brief set caller and callee according to the direction
569 * \param caller, callee, peer, chan, sense
571 * Detect who triggered feature and set callee/caller variables accordingly
573 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
574 struct ast_channel *peer, struct ast_channel *chan, int sense)
576 if (sense == FEATURE_SENSE_PEER) {
586 * \brief support routing for one touch call parking
587 * \param chan channel parking call
588 * \param peer channel to be parked
589 * \param config unsed
591 * \param sense feature options
594 * Setup channel, set return exten,priority to 's,1'
595 * answer chan, sleep chan, park call
597 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
599 struct ast_channel *parker;
600 struct ast_channel *parkee;
603 set_peers(&parker, &parkee, peer, chan, sense);
604 /* Setup the exten/priority to be s/1 since we don't know
605 where this call should return */
606 strcpy(chan->exten, "s");
608 if (chan->_state != AST_STATE_UP)
609 res = ast_answer(chan);
611 res = ast_safe_sleep(chan, 1000);
613 res = ast_park_call(parkee, parker, 0, NULL);
616 if (sense == FEATURE_SENSE_CHAN)
617 res = AST_PBX_NO_HANGUP_PEER;
619 res = AST_PBX_KEEPALIVE;
626 * \brief Monitor a channel by DTMF
627 * \param chan channel requesting monitor
628 * \param peer channel to be monitored
631 * \param sense feature options
634 * Check monitor app enabled, setup channels, both caller/callee chans not null
635 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
636 * \retval FEATURE_RETURN_SUCCESS on success.
637 * \retval -1 on error.
639 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
641 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
644 struct ast_channel *caller_chan, *callee_chan;
647 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
651 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
653 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
657 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
659 if (!ast_strlen_zero(courtesytone)) {
660 if (ast_autoservice_start(callee_chan))
662 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
663 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
664 ast_autoservice_stop(callee_chan);
667 if (ast_autoservice_stop(callee_chan))
671 if (callee_chan->monitor) {
672 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
673 callee_chan->monitor->stop(callee_chan, 1);
674 return FEATURE_RETURN_SUCCESS;
677 if (caller_chan && callee_chan) {
678 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
679 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
680 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
683 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
686 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
688 if (!touch_monitor_prefix)
689 touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
692 len = strlen(touch_monitor) + 50;
694 touch_filename = alloca(len);
695 snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
696 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
698 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
699 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
700 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
702 touch_filename = alloca(len);
703 snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
704 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
707 for(x = 0; x < strlen(args); x++) {
712 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
714 pbx_exec(callee_chan, monitor_app, args);
715 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
716 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
718 return FEATURE_RETURN_SUCCESS;
721 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
725 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
727 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
730 struct ast_channel *caller_chan, *callee_chan;
731 const char *mixmonitor_spy_type = "MixMonitor";
734 if (!mixmonitor_ok) {
735 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
739 if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
741 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
745 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
747 if (!ast_strlen_zero(courtesytone)) {
748 if (ast_autoservice_start(callee_chan))
750 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
751 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
752 ast_autoservice_stop(callee_chan);
755 if (ast_autoservice_stop(callee_chan))
759 ast_channel_lock(callee_chan);
760 count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
761 ast_channel_unlock(callee_chan);
763 // This means a mixmonitor is attached to the channel, running or not is unknown.
766 ast_verb(3, "User hit '%s' to stop recording call.\n", code);
768 //Make sure they are running
769 ast_channel_lock(callee_chan);
770 count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
771 ast_channel_unlock(callee_chan);
773 if (!stopmixmonitor_ok) {
774 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
777 if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
778 stopmixmonitor_ok = 0;
779 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
782 pbx_exec(callee_chan, stopmixmonitor_app, "");
783 return FEATURE_RETURN_SUCCESS;
787 ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
790 if (caller_chan && callee_chan) {
791 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
792 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
795 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
798 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
801 len = strlen(touch_monitor) + 50;
803 touch_filename = alloca(len);
804 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
805 snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
807 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
808 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
809 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
811 touch_filename = alloca(len);
812 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
813 snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
816 for( x = 0; x < strlen(args); x++) {
821 ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
823 pbx_exec(callee_chan, mixmonitor_app, args);
824 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
825 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
826 return FEATURE_RETURN_SUCCESS;
830 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
835 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
837 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
838 return FEATURE_RETURN_HANGUP;
841 static int finishup(struct ast_channel *chan)
843 ast_indicate(chan, AST_CONTROL_UNHOLD);
845 return ast_autoservice_stop(chan);
849 * \brief Find the context for the transfer
853 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
854 * \return a context string
856 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
858 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
859 if (ast_strlen_zero(s)) {
860 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
862 if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
863 s = transferer->macrocontext;
865 if (ast_strlen_zero(s)) {
866 s = transferer->context;
872 * \brief Blind transfer user to another extension
873 * \param chan channel to be transfered
874 * \param peer channel initiated blind transfer
878 * \param sense feature options
880 * Place chan on hold, check if transferred to parkinglot extension,
881 * otherwise check extension exists and transfer caller.
882 * \retval FEATURE_RETURN_SUCCESS.
883 * \retval -1 on failure.
885 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
887 struct ast_channel *transferer;
888 struct ast_channel *transferee;
889 const char *transferer_real_context;
893 set_peers(&transferer, &transferee, peer, chan, sense);
894 transferer_real_context = real_ctx(transferer, transferee);
895 /* Start autoservice on chan while we talk to the originator */
896 ast_autoservice_start(transferee);
897 ast_indicate(transferee, AST_CONTROL_HOLD);
899 memset(xferto, 0, sizeof(xferto));
902 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
904 finishup(transferee);
905 return -1; /* error ? */
907 if (res > 0) /* If they've typed a digit already, handle it */
908 xferto[0] = (char) res;
910 ast_stopstream(transferer);
911 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
912 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
913 finishup(transferee);
916 if (!strcmp(xferto, ast_parking_ext())) {
917 res = finishup(transferee);
920 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
921 /* We return non-zero, but tell the PBX not to hang the channel when
922 the thread dies -- We have to be careful now though. We are responsible for
923 hanging up the channel, else it will never be hung up! */
925 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
927 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
929 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
930 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
931 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
932 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
933 res=finishup(transferee);
934 if (!transferer->cdr) {
935 transferer->cdr=ast_cdr_alloc();
937 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
938 ast_cdr_start(transferer->cdr);
941 if (transferer->cdr) {
942 ast_cdr_setdestchan(transferer->cdr, transferee->name);
943 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
945 if (!transferee->pbx) {
946 /* Doh! Use our handy async_goto functions */
947 ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
948 ,transferee->name, xferto, transferer_real_context);
949 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
950 ast_log(LOG_WARNING, "Async goto failed :-(\n");
952 /* Set the channel's new extension, since it exists, using transferer context */
953 set_c_e_p(transferee, transferer_real_context, xferto, 0);
955 check_goto_on_transfer(transferer);
958 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
960 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
961 finishup(transferee);
964 ast_stopstream(transferer);
965 res = finishup(transferee);
967 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
970 return FEATURE_RETURN_SUCCESS;
974 * \brief make channels compatible
977 * \retval 0 on success.
978 * \retval -1 on failure.
980 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
982 if (ast_channel_make_compatible(c, newchan) < 0) {
983 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
984 c->name, newchan->name);
992 * \brief Attended transfer
993 * \param chan transfered user
994 * \param peer person transfering call
997 * \param sense feature options
1000 * Get extension to transfer to, if you cannot generate channel (or find extension)
1001 * return to host channel. After called channel answered wait for hangup of transferer,
1002 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
1004 * \return -1 on failure
1006 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1008 struct ast_channel *transferer;
1009 struct ast_channel *transferee;
1010 const char *transferer_real_context;
1011 char xferto[256] = "";
1014 struct ast_channel *newchan;
1015 struct ast_channel *xferchan;
1016 struct ast_bridge_thread_obj *tobj;
1017 struct ast_bridge_config bconfig;
1018 struct ast_frame *f;
1021 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
1022 set_peers(&transferer, &transferee, peer, chan, sense);
1023 transferer_real_context = real_ctx(transferer, transferee);
1024 /* Start autoservice on chan while we talk to the originator */
1025 ast_autoservice_start(transferee);
1026 ast_indicate(transferee, AST_CONTROL_HOLD);
1029 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1031 finishup(transferee);
1034 if (res > 0) /* If they've typed a digit already, handle it */
1035 xferto[0] = (char) res;
1037 /* this is specific of atxfer */
1038 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1039 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
1040 finishup(transferee);
1044 ast_log(LOG_WARNING, "Did not read data.\n");
1045 finishup(transferee);
1046 if (ast_stream_and_wait(transferer, "beeperr", ""))
1048 return FEATURE_RETURN_SUCCESS;
1051 /* valid extension, res == 1 */
1052 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
1053 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
1054 finishup(transferee);
1055 if (ast_stream_and_wait(transferer, "beeperr", ""))
1057 return FEATURE_RETURN_SUCCESS;
1061 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
1062 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1063 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1065 if (!ast_check_hangup(transferer)) {
1066 /* Transferer is up - old behaviour */
1067 ast_indicate(transferer, -1);
1069 finishup(transferee);
1070 /* any reason besides user requested cancel and busy triggers the failed sound */
1071 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
1072 ast_stream_and_wait(transferer, xferfailsound, ""))
1074 if (ast_stream_and_wait(transferer, xfersound, ""))
1075 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1076 return FEATURE_RETURN_SUCCESS;
1079 if (check_compat(transferer, newchan)) {
1080 /* we do mean transferee here, NOT transferer */
1081 finishup(transferee);
1084 memset(&bconfig,0,sizeof(struct ast_bridge_config));
1085 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
1086 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
1087 res = ast_bridge_call(transferer, newchan, &bconfig);
1088 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
1089 ast_hangup(newchan);
1090 if (ast_stream_and_wait(transferer, xfersound, ""))
1091 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1092 finishup(transferee);
1093 transferer->_softhangup = 0;
1094 return FEATURE_RETURN_SUCCESS;
1096 if (check_compat(transferee, newchan)) {
1097 finishup(transferee);
1100 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1102 if ((ast_autoservice_stop(transferee) < 0)
1103 || (ast_waitfordigit(transferee, 100) < 0)
1104 || (ast_waitfordigit(newchan, 100) < 0)
1105 || ast_check_hangup(transferee)
1106 || ast_check_hangup(newchan)) {
1107 ast_hangup(newchan);
1110 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1112 ast_hangup(newchan);
1115 /* Make formats okay */
1116 xferchan->readformat = transferee->readformat;
1117 xferchan->writeformat = transferee->writeformat;
1118 ast_channel_masquerade(xferchan, transferee);
1119 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1120 xferchan->_state = AST_STATE_UP;
1121 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1122 xferchan->_softhangup = 0;
1123 if ((f = ast_read(xferchan)))
1125 newchan->_state = AST_STATE_UP;
1126 ast_clear_flag(newchan, AST_FLAGS_ALL);
1127 newchan->_softhangup = 0;
1128 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1129 ast_hangup(xferchan);
1130 ast_hangup(newchan);
1133 tobj->chan = newchan;
1134 tobj->peer = xferchan;
1135 tobj->bconfig = *config;
1137 if (ast_stream_and_wait(newchan, xfersound, ""))
1138 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1139 ast_bridge_call_thread_launch(tobj);
1140 return -1; /* XXX meaning the channel is bridged ? */
1141 } else if (!ast_check_hangup(transferee)) {
1142 /* act as blind transfer */
1143 if (ast_autoservice_stop(transferee) < 0) {
1144 ast_hangup(newchan);
1149 unsigned int tries = 0;
1150 char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
1152 transferer_tech = strsep(&transferer_name, "/");
1153 transferer_name = strsep(&transferer_name, "-");
1155 if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
1156 ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
1157 if (ast_stream_and_wait(transferee, "beeperr", ""))
1159 return FEATURE_RETURN_SUCCESS;
1162 ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
1163 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1164 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1165 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1166 /* Trying to transfer again */
1167 ast_autoservice_start(transferee);
1168 ast_indicate(transferee, AST_CONTROL_HOLD);
1170 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1171 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1172 if (ast_autoservice_stop(transferee) < 0) {
1174 ast_hangup(newchan);
1178 /* Transfer failed, sleeping */
1179 ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1180 ast_safe_sleep(transferee, atxferloopdelay);
1181 ast_debug(1, "Trying to callback...\n");
1182 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1183 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1191 /* newchan is up, we should prepare transferee and bridge them */
1192 if (check_compat(transferee, newchan)) {
1193 finishup(transferee);
1196 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1198 if ((ast_waitfordigit(transferee, 100) < 0)
1199 || (ast_waitfordigit(newchan, 100) < 0)
1200 || ast_check_hangup(transferee)
1201 || ast_check_hangup(newchan)) {
1202 ast_hangup(newchan);
1206 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1208 ast_hangup(newchan);
1211 /* Make formats okay */
1212 xferchan->readformat = transferee->readformat;
1213 xferchan->writeformat = transferee->writeformat;
1214 ast_channel_masquerade(xferchan, transferee);
1215 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1216 xferchan->_state = AST_STATE_UP;
1217 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1218 xferchan->_softhangup = 0;
1219 if ((f = ast_read(xferchan)))
1221 newchan->_state = AST_STATE_UP;
1222 ast_clear_flag(newchan, AST_FLAGS_ALL);
1223 newchan->_softhangup = 0;
1224 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1225 ast_hangup(xferchan);
1226 ast_hangup(newchan);
1229 tobj->chan = newchan;
1230 tobj->peer = xferchan;
1231 tobj->bconfig = *config;
1233 if (ast_stream_and_wait(newchan, xfersound, ""))
1234 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1235 ast_bridge_call_thread_launch(tobj);
1236 return -1; /* XXX meaning the channel is bridged ? */
1238 /* Transferee hung up */
1239 finishup(transferee);
1244 /* add atxfer and automon as undefined so you can only use em if you configure them */
1245 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1247 AST_RWLOCK_DEFINE_STATIC(features_lock);
1249 static struct ast_call_feature builtin_features[] =
1251 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1252 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1253 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1254 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1255 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1256 { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1260 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1262 /*! \brief register new feature into feature_list*/
1263 void ast_register_feature(struct ast_call_feature *feature)
1266 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1270 AST_LIST_LOCK(&feature_list);
1271 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1272 AST_LIST_UNLOCK(&feature_list);
1274 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1278 * \brief Add new feature group
1279 * \param fgname feature group name.
1281 * Add new feature group to the feature group list insert at head of list.
1282 * \note This function MUST be called while feature_groups is locked.
1284 static struct feature_group* register_group(const char *fgname)
1286 struct feature_group *fg;
1289 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1293 if (!(fg = ast_calloc(1, sizeof(*fg))))
1296 if (ast_string_field_init(fg, 128)) {
1301 ast_string_field_set(fg, gname, fgname);
1303 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1305 ast_verb(2, "Registered group '%s'\n", fg->gname);
1311 * \brief Add feature to group
1312 * \param fg feature group
1314 * \param feature feature to add.
1316 * Check fg and feature specified, add feature to list
1317 * \note This function MUST be called while feature_groups is locked.
1319 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
1321 struct feature_group_exten *fge;
1323 if (!(fge = ast_calloc(1, sizeof(*fge))))
1326 if (ast_string_field_init(fge, 128)) {
1332 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1337 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1341 ast_string_field_set(fge, exten, (ast_strlen_zero(exten) ? feature->exten : exten));
1343 fge->feature = feature;
1345 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
1347 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1348 feature->sname, fg->gname, exten);
1351 void ast_unregister_feature(struct ast_call_feature *feature)
1356 AST_LIST_LOCK(&feature_list);
1357 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1358 AST_LIST_UNLOCK(&feature_list);
1362 /*! \brief Remove all features in the list */
1363 static void ast_unregister_features(void)
1365 struct ast_call_feature *feature;
1367 AST_LIST_LOCK(&feature_list);
1368 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1370 AST_LIST_UNLOCK(&feature_list);
1373 /*! \brief find a call feature by name */
1374 static struct ast_call_feature *find_dynamic_feature(const char *name)
1376 struct ast_call_feature *tmp;
1378 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1379 if (!strcasecmp(tmp->sname, name))
1386 /*! \brief Remove all feature groups in the list */
1387 static void ast_unregister_groups(void)
1389 struct feature_group *fg;
1390 struct feature_group_exten *fge;
1392 AST_RWLIST_WRLOCK(&feature_groups);
1393 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1394 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1395 ast_string_field_free_memory(fge);
1399 ast_string_field_free_memory(fg);
1402 AST_RWLIST_UNLOCK(&feature_groups);
1406 * \brief Find a group by name
1407 * \param name feature name
1408 * \retval feature group on success.
1409 * \retval NULL on failure.
1411 static struct feature_group *find_group(const char *name) {
1412 struct feature_group *fg = NULL;
1414 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1415 if (!strcasecmp(fg->gname, name))
1422 void ast_rdlock_call_features(void)
1424 ast_rwlock_rdlock(&features_lock);
1427 void ast_unlock_call_features(void)
1429 ast_rwlock_unlock(&features_lock);
1432 struct ast_call_feature *ast_find_call_feature(const char *name)
1435 for (x = 0; x < FEATURES_COUNT; x++) {
1436 if (!strcasecmp(name, builtin_features[x].sname))
1437 return &builtin_features[x];
1443 * \brief exec an app by feature
1444 * \param chan,peer,config,code,sense,data
1446 * Find a feature, determine which channel activated
1447 * \retval FEATURE_RETURN_PBX_KEEPALIVE,FEATURE_RETURN_NO_HANGUP_PEER
1449 * \retval -2 when an application cannot be found.
1451 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1453 struct ast_app *app;
1454 struct ast_call_feature *feature = data;
1455 struct ast_channel *work, *idle;
1458 if (!feature) { /* shouldn't ever happen! */
1459 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1463 if (sense == FEATURE_SENSE_CHAN) {
1464 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1465 return FEATURE_RETURN_KEEPTRYING;
1466 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1474 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1475 return FEATURE_RETURN_KEEPTRYING;
1476 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1485 if (!(app = pbx_findapp(feature->app))) {
1486 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1490 ast_autoservice_start(idle);
1492 if (!ast_strlen_zero(feature->moh_class))
1493 ast_moh_start(idle, feature->moh_class, NULL);
1495 res = pbx_exec(work, app, feature->app_args);
1497 if (!ast_strlen_zero(feature->moh_class))
1500 ast_autoservice_stop(idle);
1502 if (res == AST_PBX_KEEPALIVE)
1503 return FEATURE_RETURN_PBX_KEEPALIVE;
1504 else if (res == AST_PBX_NO_HANGUP_PEER)
1505 return FEATURE_RETURN_NO_HANGUP_PEER;
1507 return FEATURE_RETURN_SUCCESSBREAK;
1509 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1512 static void unmap_features(void)
1516 ast_rwlock_wrlock(&features_lock);
1517 for (x = 0; x < FEATURES_COUNT; x++)
1518 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1519 ast_rwlock_unlock(&features_lock);
1522 static int remap_feature(const char *name, const char *value)
1526 ast_rwlock_wrlock(&features_lock);
1527 for (x = 0; x < FEATURES_COUNT; x++) {
1528 if (strcasecmp(builtin_features[x].sname, name))
1531 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1535 ast_rwlock_unlock(&features_lock);
1541 * \brief Check the dynamic features
1542 * \param chan,peer,config,code,sense
1544 * Lock features list, browse for code, unlock list
1545 * \retval res on success.
1546 * \retval -1 on failure.
1548 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1551 struct ast_flags features;
1552 int res = FEATURE_RETURN_PASSDIGITS;
1553 struct ast_call_feature *feature;
1554 struct feature_group *fg = NULL;
1555 struct feature_group_exten *fge;
1556 const char *dynamic_features;
1559 if (sense == FEATURE_SENSE_CHAN) {
1560 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1561 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1564 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1565 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
1567 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);
1569 ast_rwlock_rdlock(&features_lock);
1570 for (x = 0; x < FEATURES_COUNT; x++) {
1571 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1572 !ast_strlen_zero(builtin_features[x].exten)) {
1573 /* Feature is up for consideration */
1574 if (!strcmp(builtin_features[x].exten, code)) {
1575 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1577 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1578 if (res == FEATURE_RETURN_PASSDIGITS)
1579 res = FEATURE_RETURN_STOREDIGITS;
1583 ast_rwlock_unlock(&features_lock);
1585 if (ast_strlen_zero(dynamic_features))
1588 tmp = ast_strdupa(dynamic_features);
1590 while ((tok = strsep(&tmp, "#"))) {
1591 AST_RWLIST_RDLOCK(&feature_groups);
1593 fg = find_group(tok);
1596 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1597 if (strcasecmp(fge->exten, code))
1600 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
1601 if (res != FEATURE_RETURN_KEEPTRYING) {
1602 AST_RWLIST_UNLOCK(&feature_groups);
1605 res = FEATURE_RETURN_PASSDIGITS;
1611 AST_RWLIST_UNLOCK(&feature_groups);
1612 AST_LIST_LOCK(&feature_list);
1614 if(!(feature = find_dynamic_feature(tok))) {
1615 AST_LIST_UNLOCK(&feature_list);
1619 /* Feature is up for consideration */
1620 if (!strcmp(feature->exten, code)) {
1621 ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1622 res = feature->operation(chan, peer, config, code, sense, feature);
1623 if (res != FEATURE_RETURN_KEEPTRYING) {
1624 AST_LIST_UNLOCK(&feature_list);
1627 res = FEATURE_RETURN_PASSDIGITS;
1628 } else if (!strncmp(feature->exten, code, strlen(code)))
1629 res = FEATURE_RETURN_STOREDIGITS;
1631 AST_LIST_UNLOCK(&feature_list);
1637 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1641 ast_clear_flag(config, AST_FLAGS_ALL);
1643 ast_rwlock_rdlock(&features_lock);
1644 for (x = 0; x < FEATURES_COUNT; x++) {
1645 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1648 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1649 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1651 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1652 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1654 ast_rwlock_unlock(&features_lock);
1656 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1657 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1659 if (dynamic_features) {
1660 char *tmp = ast_strdupa(dynamic_features);
1662 struct ast_call_feature *feature;
1664 /* while we have a feature */
1665 while ((tok = strsep(&tmp, "#"))) {
1666 AST_LIST_LOCK(&feature_list);
1667 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1668 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1669 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1670 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1671 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1673 AST_LIST_UNLOCK(&feature_list);
1680 * \brief Get feature and dial
1681 * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1683 * Request channel, set channel variables, initiate call,check if they want to disconnect
1684 * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1685 * check for answer break loop, set cdr return channel.
1687 * \todo XXX Check - this is very similar to the code in channel.c
1688 * \return always a channel
1690 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)
1695 struct ast_channel *chan;
1696 struct ast_channel *monitor_chans[2];
1697 struct ast_channel *active_channel;
1698 int res = 0, ready = 0;
1700 if ((chan = ast_request(type, format, data, &cause))) {
1701 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1702 ast_string_field_set(chan, language, language);
1703 ast_channel_inherit_variables(caller, chan);
1704 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1706 chan->cdr=ast_cdr_alloc();
1708 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1709 ast_cdr_start(chan->cdr);
1713 if (!ast_call(chan, data, timeout)) {
1714 struct timeval started;
1716 char *disconnect_code = NULL, *dialed_code = NULL;
1718 ast_indicate(caller, AST_CONTROL_RINGING);
1719 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1720 ast_rwlock_rdlock(&features_lock);
1721 for (x = 0; x < FEATURES_COUNT; x++) {
1722 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1725 disconnect_code = builtin_features[x].exten;
1726 len = strlen(disconnect_code) + 1;
1727 dialed_code = alloca(len);
1728 memset(dialed_code, 0, len);
1731 ast_rwlock_unlock(&features_lock);
1733 started = ast_tvnow();
1736 ast_poll_channel_add(caller, chan);
1738 while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1739 struct ast_frame *f = NULL;
1741 monitor_chans[0] = caller;
1742 monitor_chans[1] = chan;
1743 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1745 /* see if the timeout has been violated */
1746 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1747 state = AST_CONTROL_UNHOLD;
1748 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1749 break; /*doh! timeout*/
1752 if (!active_channel)
1755 if (chan && (chan == active_channel)){
1757 if (f == NULL) { /*doh! where'd he go?*/
1758 state = AST_CONTROL_HANGUP;
1763 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1764 if (f->subclass == AST_CONTROL_RINGING) {
1765 state = f->subclass;
1766 ast_verb(3, "%s is ringing\n", chan->name);
1767 ast_indicate(caller, AST_CONTROL_RINGING);
1768 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1769 state = f->subclass;
1770 ast_verb(3, "%s is busy\n", chan->name);
1771 ast_indicate(caller, AST_CONTROL_BUSY);
1775 } else if (f->subclass == AST_CONTROL_ANSWER) {
1776 /* This is what we are hoping for */
1777 state = f->subclass;
1782 } else if (f->subclass != -1) {
1783 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1785 /* else who cares */
1788 } else if (caller && (active_channel == caller)) {
1789 f = ast_read(caller);
1790 if (f == NULL) { /*doh! where'd he go?*/
1791 if (!igncallerstate) {
1792 if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
1793 /* make this a blind transfer */
1797 state = AST_CONTROL_HANGUP;
1803 if (f->frametype == AST_FRAME_DTMF) {
1804 dialed_code[x++] = f->subclass;
1805 dialed_code[x] = '\0';
1806 if (strlen(dialed_code) == len) {
1808 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1810 dialed_code[x] = '\0';
1812 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1813 /* Caller Canceled the call */
1814 state = AST_CONTROL_UNHOLD;
1826 ast_poll_channel_del(caller, chan);
1829 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1831 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1833 case AST_CAUSE_BUSY:
1834 state = AST_CONTROL_BUSY;
1836 case AST_CAUSE_CONGESTION:
1837 state = AST_CONTROL_CONGESTION;
1842 ast_indicate(caller, -1);
1843 if (chan && ready) {
1844 if (chan->_state == AST_STATE_UP)
1845 state = AST_CONTROL_ANSWER;
1858 if (chan && res <= 0) {
1859 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1861 ast_cdr_init(chan->cdr, chan);
1862 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1863 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1864 ast_cdr_update(chan);
1865 ast_cdr_start(chan->cdr);
1866 ast_cdr_end(chan->cdr);
1867 /* If the cause wasn't handled properly */
1868 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1869 ast_cdr_failed(chan->cdr);
1871 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1879 * \brief bridge the call and set CDR
1880 * \param chan,peer,config
1882 * Set start time, check for two channels,check if monitor on
1883 * check for feature activation, create new CDR
1884 * \retval res on success.
1885 * \retval -1 on failure to bridge.
1887 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1889 /* Copy voice back and forth between the two channels. Give the peer
1890 the ability to transfer calls with '#<extension' syntax. */
1891 struct ast_frame *f;
1892 struct ast_channel *who;
1893 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1894 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1899 struct ast_option_header *aoh;
1900 struct ast_bridge_config backup_config;
1901 struct ast_cdr *bridge_cdr;
1903 memset(&backup_config, 0, sizeof(backup_config));
1905 config->start_time = ast_tvnow();
1908 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1909 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1911 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1914 const char *monitor_exec;
1915 struct ast_channel *src = NULL;
1917 if (!(monitor_app = pbx_findapp("Monitor")))
1920 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1922 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1924 if (monitor_app && src) {
1925 char *tmp = ast_strdupa(monitor_exec);
1926 pbx_exec(src, monitor_app, tmp);
1930 set_config_flags(chan, peer, config);
1931 config->firstpass = 1;
1933 /* Answer if need be */
1934 if (ast_answer(chan))
1936 peer->appl = "Bridged Call";
1937 peer->data = chan->name;
1939 /* copy the userfield from the B-leg to A-leg if applicable */
1940 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1942 if (!ast_strlen_zero(chan->cdr->userfield)) {
1943 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1944 ast_cdr_appenduserfield(chan, tmp);
1946 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1947 /* free the peer's cdr without ast_cdr_free complaining */
1948 ast_free(peer->cdr);
1953 struct ast_channel *other; /* used later */
1955 res = ast_channel_bridge(chan, peer, config, &f, &who);
1957 if (config->feature_timer) {
1958 /* Update time limit for next pass */
1959 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1960 config->feature_timer -= diff;
1962 /* Running on backup config, meaning a feature might be being
1963 activated, but that's no excuse to keep things going
1965 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1966 ast_debug(1, "Timed out, realtime this time!\n");
1967 config->feature_timer = 0;
1973 } else if (config->feature_timer <= 0) {
1974 /* Not *really* out of time, just out of time for
1975 digits to come in for features. */
1976 ast_debug(1, "Timed out for feature!\n");
1977 if (!ast_strlen_zero(peer_featurecode)) {
1978 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
1979 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1981 if (!ast_strlen_zero(chan_featurecode)) {
1982 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
1983 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1987 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1989 /* Restore original (possibly time modified) bridge config */
1990 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1991 memset(&backup_config, 0, sizeof(backup_config));
1993 hadfeatures = hasfeatures;
1994 /* Continue as we were */
1997 /* The bridge returned without a frame and there is a feature in progress.
1998 * However, we don't think the feature has quite yet timed out, so just
1999 * go back into the bridge. */
2003 if (config->feature_timer <=0) {
2004 /* We ran out of time */
2005 config->feature_timer = 0;
2015 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
2016 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
2020 if (!f || (f->frametype == AST_FRAME_CONTROL &&
2021 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
2022 f->subclass == AST_CONTROL_CONGESTION))) {
2026 /* many things should be sent to the 'other' channel */
2027 other = (who == chan) ? peer : chan;
2028 if (f->frametype == AST_FRAME_CONTROL) {
2029 switch (f->subclass) {
2030 case AST_CONTROL_RINGING:
2031 case AST_CONTROL_FLASH:
2033 ast_indicate(other, f->subclass);
2035 case AST_CONTROL_HOLD:
2036 case AST_CONTROL_UNHOLD:
2037 ast_indicate_data(other, f->subclass, f->data, f->datalen);
2039 case AST_CONTROL_OPTION:
2041 /* Forward option Requests */
2042 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
2043 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
2044 f->datalen - sizeof(struct ast_option_header), 0);
2048 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
2050 } else if (f->frametype == AST_FRAME_DTMF) {
2054 hadfeatures = hasfeatures;
2055 /* This cannot overrun because the longest feature is one shorter than our buffer */
2057 sense = FEATURE_SENSE_CHAN;
2058 featurecode = chan_featurecode;
2060 sense = FEATURE_SENSE_PEER;
2061 featurecode = peer_featurecode;
2063 /*! append the event to featurecode. we rely on the string being zero-filled, and
2064 * not overflowing it.
2065 * \todo XXX how do we guarantee the latter ?
2067 featurecode[strlen(featurecode)] = f->subclass;
2068 /* Get rid of the frame before we start doing "stuff" with the channels */
2071 config->feature_timer = backup_config.feature_timer;
2072 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
2074 case FEATURE_RETURN_PASSDIGITS:
2075 ast_dtmf_stream(other, who, featurecode, 0, 0);
2077 case FEATURE_RETURN_SUCCESS:
2078 memset(featurecode, 0, sizeof(chan_featurecode));
2081 if (res >= FEATURE_RETURN_PASSDIGITS) {
2085 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
2086 if (hadfeatures && !hasfeatures) {
2087 /* Restore backup */
2088 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
2089 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
2090 } else if (hasfeatures) {
2092 /* Backup configuration */
2093 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
2094 /* Setup temporary config options */
2095 config->play_warning = 0;
2096 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
2097 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
2098 config->warning_freq = 0;
2099 config->warning_sound = NULL;
2100 config->end_sound = NULL;
2101 config->start_sound = NULL;
2102 config->firstpass = 0;
2104 config->start_time = ast_tvnow();
2105 config->feature_timer = featuredigittimeout;
2106 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
2113 /* arrange the cdrs */
2114 bridge_cdr = ast_cdr_alloc();
2116 if (chan->cdr && peer->cdr) { /* both of them? merge */
2117 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
2118 ast_cdr_start(bridge_cdr); /* now is the time to start */
2120 /* absorb the channel cdr */
2121 ast_cdr_merge(bridge_cdr, chan->cdr);
2122 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
2123 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2125 /* absorb the peer cdr */
2126 ast_cdr_merge(bridge_cdr, peer->cdr);
2127 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
2128 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
2131 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2132 } else if (chan->cdr) {
2133 /* take the cdr from the channel - literally */
2134 ast_cdr_init(bridge_cdr,chan);
2135 /* absorb this data */
2136 ast_cdr_merge(bridge_cdr, chan->cdr);
2137 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
2138 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2139 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2140 } else if (peer->cdr) {
2141 /* take the cdr from the peer - literally */
2142 ast_cdr_init(bridge_cdr,peer);
2143 /* absorb this data */
2144 ast_cdr_merge(bridge_cdr, peer->cdr);
2145 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
2146 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2148 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2150 /* make up a new cdr */
2151 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
2152 chan->cdr = bridge_cdr; /* */
2154 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
2155 if (strcmp(bridge_cdr->channel, peer->name) != 0)
2156 ast_cdr_setdestchan(bridge_cdr, peer->name);
2158 ast_cdr_setdestchan(bridge_cdr, chan->name);
2164 /*! \brief Output parking event to manager */
2165 static void post_manager_event(const char *s, struct parkeduser *pu)
2167 manager_event(EVENT_FLAG_CALL, s,
2170 "CallerIDNum: %s\r\n"
2171 "CallerIDName: %s\r\n\r\n",
2174 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2175 S_OR(pu->chan->cid.cid_name, "<unknown>")
2180 * \brief Take care of parked calls and unpark them if needed
2181 * \param ignore unused var.
2183 * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2184 * if so, remove channel from parking lot and return it to the extension that parked it.
2185 * Check if parked channel decided to hangup, wait until next FD via select().
2187 static void *do_parking_thread(void *ignore)
2189 char parkingslot[AST_MAX_EXTENSION];
2190 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
2196 struct parkeduser *pu;
2197 int ms = -1; /* select timeout, uninitialized */
2198 int max = -1; /* max fd, none there yet */
2199 fd_set nrfds, nefds; /* args for the next select */
2203 AST_LIST_LOCK(&parkinglot);
2204 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2205 struct ast_channel *chan = pu->chan; /* shorthand */
2206 int tms; /* timeout for this item */
2207 int x; /* fd index in channel */
2208 struct ast_context *con;
2210 if (pu->notquiteyet) /* Pretend this one isn't here yet */
2212 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2213 if (tms > pu->parkingtime) {
2214 ast_indicate(chan, AST_CONTROL_UNHOLD);
2215 /* Get chan, exten from derived kludge */
2216 if (pu->peername[0]) {
2217 char *peername = ast_strdupa(pu->peername);
2218 char *cp = strrchr(peername, '-');
2219 char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
2224 ast_copy_string(peername_flat,peername,sizeof(peername_flat));
2225 for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
2226 if (peername_flat[i] == '/')
2227 peername_flat[i]= '0';
2229 con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
2231 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
2233 char returnexten[AST_MAX_EXTENSION];
2234 struct ast_datastore *features_datastore;
2235 struct ast_dial_features *dialfeatures = NULL;
2237 ast_channel_lock(chan);
2239 if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
2240 dialfeatures = features_datastore->data;
2242 ast_channel_unlock(chan);
2245 snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
2246 else /* Existing default */
2247 snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
2249 ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
2251 if (comebacktoorigin) {
2252 set_c_e_p(chan, parking_con_dial, peername_flat, 1);
2254 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2255 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2256 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
2257 set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
2260 /* They've been waiting too long, send them back to where they came. Theoretically they
2261 should have their original extensions and such, but we copy to be on the safe side */
2262 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2265 post_manager_event("ParkedCallTimeOut", pu);
2267 ast_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
2268 /* Start up the PBX, or hang them up */
2269 if (ast_pbx_start(chan)) {
2270 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
2273 /* And take them out of the parking lot */
2274 AST_LIST_REMOVE_CURRENT(list);
2275 con = ast_context_find(parking_con);
2277 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2278 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2280 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2282 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2284 } else { /* still within parking time, process descriptors */
2285 for (x = 0; x < AST_MAX_FDS; x++) {
2286 struct ast_frame *f;
2288 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
2289 continue; /* nothing on this descriptor */
2291 if (FD_ISSET(chan->fds[x], &efds))
2292 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2294 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2297 /* See if they need servicing */
2299 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
2302 post_manager_event("ParkedCallGiveUp", pu);
2304 /* There's a problem, hang them up*/
2305 ast_verb(2, "%s got tired of being parked\n", chan->name);
2307 /* And take them out of the parking lot */
2308 AST_LIST_REMOVE_CURRENT(list);
2309 con = ast_context_find(parking_con);
2311 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2312 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2314 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2316 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2320 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2322 if (pu->moh_trys < 3 && !chan->generatordata) {
2323 ast_debug(1, "MOH on parked call stopped by outside source. Restarting.\n");
2324 ast_indicate_data(chan, AST_CONTROL_HOLD,
2325 S_OR(parkmohclass, NULL),
2326 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
2329 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
2333 if (x >= AST_MAX_FDS) {
2334 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2335 if (chan->fds[x] > -1) {
2336 FD_SET(chan->fds[x], &nrfds);
2337 FD_SET(chan->fds[x], &nefds);
2338 if (chan->fds[x] > max)
2342 /* Keep track of our shortest wait */
2343 if (tms < ms || ms < 0)
2348 AST_LIST_TRAVERSE_SAFE_END
2349 AST_LIST_UNLOCK(&parkinglot);
2353 struct timeval tv = ast_samp2tv(ms, 1000);
2354 /* Wait for something to happen */
2355 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2357 pthread_testcancel();
2359 return NULL; /* Never reached */
2362 /*! \brief Park a call */
2363 static int park_call_exec(struct ast_channel *chan, void *data)
2365 /* Cache the original channel name in case we get masqueraded in the middle
2366 * of a park--it is still theoretically possible for a transfer to happen before
2367 * we get here, but it is _really_ unlikely */
2368 char *orig_chan_name = ast_strdupa(chan->name);
2369 char orig_exten[AST_MAX_EXTENSION];
2370 int orig_priority = chan->priority;
2372 /* Data is unused at the moment but could contain a parking
2373 lot context eventually */
2376 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
2378 /* Setup the exten/priority to be s/1 since we don't know
2379 where this call should return */
2380 strcpy(chan->exten, "s");
2382 /* Answer if call is not up */
2383 if (chan->_state != AST_STATE_UP)
2384 res = ast_answer(chan);
2385 /* Sleep to allow VoIP streams to settle down */
2387 res = ast_safe_sleep(chan, 1000);
2390 res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
2391 /* Continue on in the dialplan */
2393 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
2394 chan->priority = orig_priority;
2397 res = AST_PBX_KEEPALIVE;
2403 /*! \brief Pickup parked call */
2404 static int park_exec(struct ast_channel *chan, void *data)
2407 struct ast_channel *peer=NULL;
2408 struct parkeduser *pu;
2409 struct ast_context *con;
2411 struct ast_bridge_config config;
2414 park = atoi((char *)data);
2416 AST_LIST_LOCK(&parkinglot);
2417 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2418 if (!data || pu->parkingnum == park) {
2419 AST_LIST_REMOVE_CURRENT(list);
2423 AST_LIST_TRAVERSE_SAFE_END
2424 AST_LIST_UNLOCK(&parkinglot);
2428 con = ast_context_find(parking_con);
2430 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2431 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2433 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2435 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2437 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2441 "CallerIDNum: %s\r\n"
2442 "CallerIDName: %s\r\n",
2443 pu->parkingexten, pu->chan->name, chan->name,
2444 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2445 S_OR(pu->chan->cid.cid_name, "<unknown>")
2450 /* JK02: it helps to answer the channel if not already up */
2451 if (chan->_state != AST_STATE_UP)
2455 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2457 if (!ast_strlen_zero(courtesytone)) {
2459 ast_indicate(peer, AST_CONTROL_UNHOLD);
2460 if (parkedplay == 0) {
2461 error = ast_stream_and_wait(chan, courtesytone, "");
2462 } else if (parkedplay == 1) {
2463 error = ast_stream_and_wait(peer, courtesytone, "");
2464 } else if (parkedplay == 2) {
2465 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2466 !ast_streamfile(peer, courtesytone, chan->language)) {
2467 /*! \todo XXX we would like to wait on both! */
2468 res = ast_waitstream(chan, "");
2470 res = ast_waitstream(peer, "");
2476 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2481 ast_indicate(peer, AST_CONTROL_UNHOLD);
2483 res = ast_channel_make_compatible(chan, peer);
2485 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2489 /* This runs sorta backwards, since we give the incoming channel control, as if it
2490 were the person called. */
2491 ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
2493 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2494 ast_cdr_setdestchan(chan->cdr, peer->name);
2495 memset(&config, 0, sizeof(struct ast_bridge_config));
2496 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2497 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2498 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2499 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2500 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2501 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2502 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2503 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2504 res = ast_bridge_call(chan, peer, &config);
2506 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2507 ast_cdr_setdestchan(chan->cdr, peer->name);
2509 /* Simulate the PBX hanging up */
2510 if (res != AST_PBX_NO_HANGUP_PEER)
2514 /*! \todo XXX Play a message XXX */
2515 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2516 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2517 ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2525 * \brief Add parking hints for all defined parking lots
2527 * \param start starting parkinglot number
2528 * \param stop ending parkinglot number
2530 static void park_add_hints(char *context, int start, int stop)
2533 char device[AST_MAX_EXTENSION];
2536 for (numext = start; numext <= stop; numext++) {
2537 snprintf(exten, sizeof(exten), "%d", numext);
2538 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2539 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2543 static int load_config(void)
2545 int start = 0, end = 0;
2548 struct ast_context *con = NULL;
2549 struct ast_config *cfg = NULL;
2550 struct ast_variable *var = NULL;
2551 struct feature_group *fg = NULL;
2552 struct ast_flags config_flags = { 0 };
2553 char old_parking_ext[AST_MAX_EXTENSION];
2554 char old_parking_con[AST_MAX_EXTENSION] = "";
2556 static const char *categories[] = {
2557 /* Categories in features.conf that are not
2558 * to be parsed as group categories
2565 if (!ast_strlen_zero(parking_con)) {
2566 strcpy(old_parking_ext, parking_ext);
2567 strcpy(old_parking_con, parking_con);
2570 /* Reset to defaults */
2571 strcpy(parking_con, "parkedcalls");
2572 strcpy(parking_con_dial, "park-dial");
2573 strcpy(parking_ext, "700");
2574 strcpy(pickup_ext, "*8");
2575 strcpy(parkmohclass, "default");
2576 courtesytone[0] = '\0';
2577 strcpy(xfersound, "beep");
2578 strcpy(xferfailsound, "pbx-invalid");
2579 parking_start = 701;
2583 comebacktoorigin = 1;
2585 parkedcalltransfers = 0;
2586 parkedcallreparking = 0;
2588 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2589 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2590 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2591 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2592 atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2593 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2595 cfg = ast_config_load("features.conf", config_flags);
2597 ast_log(LOG_WARNING,"Could not load features.conf\n");
2600 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2601 if (!strcasecmp(var->name, "parkext")) {
2602 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2603 } else if (!strcasecmp(var->name, "context")) {
2604 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2605 } else if (!strcasecmp(var->name, "parkingtime")) {
2606 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2607 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2608 parkingtime = DEFAULT_PARK_TIME;
2610 parkingtime = parkingtime * 1000;
2611 } else if (!strcasecmp(var->name, "parkpos")) {
2612 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2613 ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
2615 parking_start = start;
2618 } else if (!strcasecmp(var->name, "findslot")) {
2619 parkfindnext = (!strcasecmp(var->value, "next"));
2620 } else if (!strcasecmp(var->name, "parkinghints")) {
2621 parkaddhints = ast_true(var->value);
2622 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2623 if (!strcasecmp(var->value, "both"))
2624 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2625 else if (!strcasecmp(var->value, "caller"))
2626 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2627 else if (!strcasecmp(var->value, "callee"))
2628 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2629 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2630 if (!strcasecmp(var->value, "both"))
2631 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2632 else if (!strcasecmp(var->value, "caller"))
2633 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2634 else if (!strcasecmp(var->value, "callee"))
2635 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2636 } else if (!strcasecmp(var->name, "adsipark")) {
2637 adsipark = ast_true(var->value);
2638 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2639 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2640 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2641 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2643 transferdigittimeout = transferdigittimeout * 1000;
2644 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2645 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2646 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2647 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2649 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2650 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2651 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2652 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2654 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2655 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2656 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2657 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2658 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2660 atxferloopdelay *= 1000;
2661 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2662 atxferdropcall = ast_true(var->value);
2663 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2664 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2665 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2666 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2668 } else if (!strcasecmp(var->name, "courtesytone")) {
2669 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2670 } else if (!strcasecmp(var->name, "parkedplay")) {
2671 if (!strcasecmp(var->value, "both"))
2673 else if (!strcasecmp(var->value, "parked"))
2677 } else if (!strcasecmp(var->name, "xfersound")) {
2678 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2679 } else if (!strcasecmp(var->name, "xferfailsound")) {
2680 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2681 } else if (!strcasecmp(var->name, "pickupexten")) {
2682 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2683 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2684 comebacktoorigin = ast_true(var->value);
2685 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2686 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2691 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2692 if (remap_feature(var->name, var->value))
2693 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2696 /* Map a key combination to an application*/
2697 ast_unregister_features();
2698 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2699 char *tmp_val = ast_strdupa(var->value);
2700 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2701 struct ast_call_feature *feature;
2703 /* strsep() sets the argument to NULL if match not found, and it
2704 * is safe to use it with a NULL argument, so we don't check
2707 exten = strsep(&tmp_val,",");
2708 activatedby = strsep(&tmp_val,",");
2709 app = strsep(&tmp_val,",");
2710 app_args = strsep(&tmp_val,",");
2711 moh_class = strsep(&tmp_val,",");
2713 activateon = strsep(&activatedby, "/");
2715 /*! \todo XXX var_name or app_args ? */
2716 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2717 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2718 app, exten, activateon, var->name);
2722 AST_LIST_LOCK(&feature_list);
2723 if ((feature = find_dynamic_feature(var->name))) {
2724 AST_LIST_UNLOCK(&feature_list);
2725 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2728 AST_LIST_UNLOCK(&feature_list);
2730 if (!(feature = ast_calloc(1, sizeof(*feature))))
2733 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2734 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2735 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2738 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2741 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2743 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2744 feature->operation = feature_exec_app;
2745 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2747 /* Allow caller and calle to be specified for backwards compatability */
2748 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2749 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2750 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2751 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2753 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2754 " must be 'self', or 'peer'\n", var->name);
2758 if (ast_strlen_zero(activatedby))
2759 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2760 else if (!strcasecmp(activatedby, "caller"))
2761 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2762 else if (!strcasecmp(activatedby, "callee"))
2763 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2764 else if (!strcasecmp(activatedby, "both"))
2765 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2767 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2768 " must be 'caller', or 'callee', or 'both'\n", var->name);
2772 ast_register_feature(feature);
2774 ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2777 ast_unregister_groups();
2778 AST_RWLIST_WRLOCK(&feature_groups);
2781 while ((ctg = ast_category_browse(cfg, ctg))) {
2782 for (i = 0; i < ARRAY_LEN(categories); i++) {
2783 if (!strcasecmp(categories[i], ctg))
2787 if (i < ARRAY_LEN(categories))
2790 if (!(fg = register_group(ctg)))
2793 for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
2794 struct ast_call_feature *feature;
2796 AST_LIST_LOCK(&feature_list);
2797 if(!(feature = find_dynamic_feature(var->name)) &&
2798 !(feature = ast_find_call_feature(var->name))) {
2799 AST_LIST_UNLOCK(&feature_list);
2800 ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
2803 AST_LIST_UNLOCK(&feature_list);
2805 register_group_feature(fg, var->value, feature);
2809 AST_RWLIST_UNLOCK(&feature_groups);
2811 ast_config_destroy(cfg);
2813 /* Remove the old parking extension */
2814 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2815 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2816 notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
2817 ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2820 if (!(con = ast_context_find_or_create(NULL, NULL, parking_con, registrar))) {
2821 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2824 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2826 park_add_hints(parking_con, parking_start, parking_stop);
2828 notify_metermaids(ast_parking_ext(), parking_con, AST_DEVICE_INUSE);
2834 * \brief CLI command to list configured features
2839 * \retval CLI_SUCCESS on success.
2840 * \retval NULL when tab completion is used.
2842 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2845 struct ast_call_feature *feature;
2846 char format[] = "%-25s %-7s %-7s\n";
2851 e->command = "features show";
2853 "Usage: features show\n"
2854 " Lists configured features\n";
2860 ast_cli(a->fd, format, "Builtin Feature", "Default", "Current");
2861 ast_cli(a->fd, format, "---------------", "-------", "-------");
2863 ast_cli(a->fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2865 ast_rwlock_rdlock(&features_lock);
2866 for (i = 0; i < FEATURES_COUNT; i++)
2867 ast_cli(a->fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2868 ast_rwlock_unlock(&features_lock);
2870 ast_cli(a->fd, "\n");
2871 ast_cli(a->fd, format, "Dynamic Feature", "Default", "Current");
2872 ast_cli(a->fd, format, "---------------", "-------", "-------");
2873 if (AST_LIST_EMPTY(&feature_list))
2874 ast_cli(a->fd, "(none)\n");
2876 AST_LIST_LOCK(&feature_list);
2877 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2878 ast_cli(a->fd, format, feature->sname, "no def", feature->exten);
2879 AST_LIST_UNLOCK(&feature_list);
2881 ast_cli(a->fd, "\nCall parking\n");
2882 ast_cli(a->fd, "------------\n");
2883 ast_cli(a->fd,"%-20s: %s\n", "Parking extension", parking_ext);
2884 ast_cli(a->fd,"%-20s: %s\n", "Parking context", parking_con);
2885 ast_cli(a->fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2886 ast_cli(a->fd,"\n");
2891 int ast_features_reload(void)
2895 return RESULT_SUCCESS;
2898 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2902 e->command = "features reload";
2904 "Usage: features reload\n"
2905 " Reloads configured call features from features.conf\n";
2915 static char mandescr_bridge[] =
2916 "Description: Bridge together two channels already in the PBX\n"
2917 "Variables: ( Headers marked with * are required )\n"
2918 " *Channel1: Channel to Bridge to Channel2\n"
2919 " *Channel2: Channel to Bridge to Channel1\n"
2920 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2924 * \brief Actual bridge
2928 * Stop hold music, lock both channels, masq channels,
2929 * after bridge return channel to next priority.
2931 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2934 ast_channel_lock(chan);
2935 ast_setstate(tmpchan, chan->_state);
2936 tmpchan->readformat = chan->readformat;
2937 tmpchan->writeformat = chan->writeformat;
2938 ast_channel_masquerade(tmpchan, chan);
2939 ast_channel_lock(tmpchan);
2940 ast_do_masquerade(tmpchan);
2941 /* when returning from bridge, the channel will continue at the next priority */
2942 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2943 ast_channel_unlock(tmpchan);
2944 ast_channel_unlock(chan);
2948 * \brief Bridge channels together
2952 * Make sure valid channels were specified,
2953 * send errors if any of the channels could not be found/locked, answer channels if needed,
2954 * create the placeholder channels and grab the other channels
2955 * make the channels compatible, send error if we fail doing so
2956 * setup the bridge thread object and start the bridge.
2958 * \retval 0 on success or on incorrect use.
2959 * \retval 1 on failure to bridge channels.
2961 static int action_bridge(struct mansession *s, const struct message *m)
2963 const char *channela = astman_get_header(m, "Channel1");
2964 const char *channelb = astman_get_header(m, "Channel2");
2965 const char *playtone = astman_get_header(m, "Tone");
2966 struct ast_channel *chana = NULL, *chanb = NULL;
2967 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
2968 struct ast_bridge_thread_obj *tobj = NULL;
2970 /* make sure valid channels were specified */
2971 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
2972 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
2973 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
2975 ast_channel_unlock(chana);
2977 ast_channel_unlock(chanb);
2979 /* send errors if any of the channels could not be found/locked */
2982 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
2983 astman_send_error(s, m, buf);
2988 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
2989 astman_send_error(s, m, buf);
2993 astman_send_error(s, m, "Missing channel parameter in request");
2997 /* Answer the channels if needed */
2998 if (chana->_state != AST_STATE_UP)
3000 if (chanb->_state != AST_STATE_UP)
3003 /* create the placeholder channels and grab the other channels */
3004 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
3005 NULL, NULL, 0, "Bridge/%s", chana->name))) {
3006 astman_send_error(s, m, "Unable to create temporary channel!");
3010 if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
3011 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
3012 astman_send_error(s, m, "Unable to create temporary channels!");
3013 ast_channel_free(tmpchana);
3017 do_bridge_masquerade(chana, tmpchana);
3018 do_bridge_masquerade(chanb, tmpchanb);
3020 /* make the channels compatible, send error if we fail doing so */
3021 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
3022 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
3023 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
3024 ast_hangup(tmpchana);
3025 ast_hangup(tmpchanb);
3029 /* setup the bridge thread object and start the bridge */
3030 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
3031 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
3032 astman_send_error(s, m, "Unable to spawn a new bridge thread");
3033 ast_hangup(tmpchana);
3034 ast_hangup(tmpchanb);
3038 tobj->chan = tmpchana;
3039 tobj->peer = tmpchanb;
3040 tobj->return_to_pbx = 1;
3042 if (ast_true(playtone)) {
3043 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
3044 if (ast_waitstream(tmpchanb, "") < 0)
3045 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
3049 ast_bridge_call_thread_launch(tobj);
3051 astman_send_ack(s, m, "Launched bridge thread with success");
3057 * \brief CLI command to list parked calls
3062 * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
3063 * \retval CLI_SUCCESS on success.
3064 * \retval CLI_SHOWUSAGE on incorrect number of arguments.
3065 * \retval NULL when tab completion is used.
3067 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3069 struct parkeduser *cur;
3074 e->command = "parkedcalls show";
3076 "Usage: parkedcalls show\n"
3077 " List currently parked calls\n";
3083 if (a->argc > e->args)
3084 return CLI_SHOWUSAGE;
3086 ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
3087 , "Context", "Extension", "Pri", "Timeout");
3089 AST_LIST_LOCK(&parkinglot);
3090 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
3091 ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
3092 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
3093 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
3097 AST_LIST_UNLOCK(&parkinglot);
3098 ast_cli(a->fd, "%d parked call%s.\n", numparked, ESS(numparked));
3104 static char *handle_parkedcalls_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3106 char *res = handle_parkedcalls(e, cmd, a);
3107 if (cmd == CLI_INIT)
3108 e->command = "show parkedcalls";
3112 static struct ast_cli_entry cli_show_parkedcalls_deprecated = AST_CLI_DEFINE(handle_parkedcalls_deprecated, "List currently parked calls.");
3114 static struct ast_cli_entry cli_features[] = {
3115 AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
3116 AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
3117 AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls", .deprecate_cmd = &cli_show_parkedcalls_deprecated),
3121 * \brief Dump parking lot status
3125 * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
3126 * \return Always RESULT_SUCCESS
3128 static int manager_parking_status(struct mansession *s, const struct message *m)
3130 struct parkeduser *cur;
3131 const char *id = astman_get_header(m, "ActionID");
3132 char idText[256] = "";
3134 if (!ast_strlen_zero(id))
3135 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
3137 astman_send_ack(s, m, "Parked calls will follow");
3139 AST_LIST_LOCK(&parkinglot);
3141 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
3142 astman_append(s, "Event: ParkedCall\r\n"
3147 "CallerIDNum: %s\r\n"
3148 "CallerIDName: %s\r\n"
3151 cur->parkingnum, cur->chan->name, cur->peername,
3152 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
3153 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
3154 S_OR(cur->chan->cid.cid_name, ""),
3159 "Event: ParkedCallsComplete\r\n"
3163 AST_LIST_UNLOCK(&parkinglot);
3165 return RESULT_SUCCESS;
3168 static char mandescr_park[] =
3169 "Description: Park a channel.\n"
3170 "Variables: (Names marked with * are required)\n"
3171 " *Channel: Channel name to park\n"
3172 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
3173 " Timeout: Number of milliseconds to wait before callback.\n";
3176 * \brief Create manager event for parked calls
3180 * Get channels involved in park, create event.
3183 static int manager_park(struct mansession *s, const struct message *m)
3185 const char *channel = astman_get_header(m, "Channel");
3186 const char *channel2 = astman_get_header(m, "Channel2");
3187 const char *timeout = astman_get_header(m, "Timeout");
3192 struct ast_channel *ch1, *ch2;
3194 if (ast_strlen_zero(channel)) {
3195 astman_send_error(s, m, "Channel not specified");
3199 if (ast_strlen_zero(channel2)) {
3200 astman_send_error(s, m, "Channel2 not specified");
3204 ch1 = ast_get_channel_by_name_locked(channel);
3206 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
3207 astman_send_error(s, m, buf);
3211 ch2 = ast_get_channel_by_name_locked(channel2);
3213 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
3214 astman_send_error(s, m, buf);
3215 ast_channel_unlock(ch1);
3219 if (!ast_strlen_zero(timeout)) {
3220 sscanf(timeout, "%d", &to);
3223 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
3225 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
3226 astman_send_ack(s, m, "Park successful");
3228 astman_send_error(s, m, "Park failure");
3231 ast_channel_unlock(ch1);
3232 ast_channel_unlock(ch2);
3238 * \brief Pickup a call
3239 * \param chan channel that initiated pickup.
3241 * Walk list of channels, checking it is not itself, channel is pbx one,
3242 * check that the callgroup for both channels are the same and the channel is ringing.
3243 * Answer calling channel, flag channel as answered on queue, masq channels together.
3245 int ast_pickup_call(struct ast_channel *chan)
3247 struct ast_channel *cur = NULL;
3250 while ((cur = ast_channel_walk_locked(cur)) != NULL) {
3253 (chan->pickupgroup & cur->callgroup) &&
3254 ((cur->_state == AST_STATE_RINGING) ||
3255 (cur->_state == AST_STATE_RING))) {
3258 ast_channel_unlock(cur);
3261 ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
3262 res = ast_answer(chan);
3264 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
3265 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
3267 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
3268 res = ast_channel_masquerade(cur, chan);
3270 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
3271 ast_channel_unlock(cur);
3273 ast_debug(1, "No call pickup possible...\n");
3278 static char *app_bridge = "Bridge";
3279 static char *bridge_synopsis = "Bridge two channels";
3280 static char *bridge_descrip =
3281 "Usage: Bridge(channel[,options])\n"
3282 " Allows the ability to bridge two channels via the dialplan.\n"
3283 "The current channel is bridged to the specified 'channel'.\n"
3285 " p - Play a courtesy tone to 'channel'.\n"
3286 "This application sets the following channel variable upon completion:\n"
3287 " BRIDGERESULT The result of the bridge attempt as a text string, one of\n"
3288 " SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n";
3291 BRIDGE_OPT_PLAYTONE = (1 << 0),
3294 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
3295 AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
3299 * \brief Bridge channels
3301 * \param data channel to bridge with.
3303 * Split data, check we aren't bridging with ourself, check valid channel,
3304 * answer call if not already, check compatible channels, setup bridge config
3305 * now bridge call, if transfered party hangs up return to PBX extension.
3307 static int bridge_exec(struct ast_channel *chan, void *data)
3309 struct ast_channel *current_dest_chan, *final_dest_chan;
3310 char *tmp_data = NULL;
3311 struct ast_flags opts = { 0, };
3312 struct ast_bridge_config bconfig = { { 0, }, };
3314 AST_DECLARE_APP_ARGS(args,
3315 AST_APP_ARG(dest_chan);
3316 AST_APP_ARG(options);
3319 if (ast_strlen_zero(data)) {
3320 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
3324 tmp_data = ast_strdupa(data);
3325 AST_STANDARD_APP_ARGS(args, tmp_data);
3326 if (!ast_strlen_zero(args.options))
3327 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
3329 /* avoid bridge with ourselves */
3330 if (!strncmp(chan->name, args.dest_chan,
3331 strlen(chan->name) < strlen(args.dest_chan) ?
3332 strlen(chan->name) : strlen(args.dest_chan))) {
3333 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
3334 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3335 "Response: Failed\r\n"
3336 "Reason: Unable to bridge channel to itself\r\n"
3339 chan->name, args.dest_chan);
3340 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
3344 /* make sure we have a valid end point */
3345 if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
3346 strlen(args.dest_chan)))) {
3347 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
3348 "cannot get its lock\n", args.dest_chan);
3349 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3350 "Response: Failed\r\n"
3351 "Reason: Cannot grab end point\r\n"
3353 "Channel2: %s\r\n", chan->name, args.dest_chan);
3354 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
3357 ast_channel_unlock(current_dest_chan);
3359 /* answer the channel if needed */
3360 if (current_dest_chan->_state != AST_STATE_UP)
3361 ast_answer(current_dest_chan);
3363 /* try to allocate a place holder where current_dest_chan will be placed */
3364 if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
3365 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
3366 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
3367 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3368 "Response: Failed\r\n"
3369 "Reason: cannot create placeholder\r\n"
3371 "Channel2: %s\r\n", chan->name, args.dest_chan);
3373 do_bridge_masquerade(current_dest_chan, final_dest_chan);
3375 /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
3376 /* try to make compatible, send error if we fail */
3377 if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
3378 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
3379 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3380 "Response: Failed\r\n"
3381 "Reason: Could not make channels compatible for bridge\r\n"
3383 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
3384 ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
3385 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
3389 /* Report that the bridge will be successfull */
3390 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3391 "Response: Success\r\n"
3393 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
3395 /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
3396 if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
3397 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
3398 if (ast_waitstream(final_dest_chan, "") < 0)
3399 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
3404 ast_bridge_call(chan, final_dest_chan, &bconfig);
3406 /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
3407 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
3408 if (!ast_check_hangup(final_dest_chan)) {
3409 ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
3410 final_dest_chan->context, final_dest_chan->exten,
3411 final_dest_chan->priority, final_dest_chan->name);