2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, 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$")
38 #include <sys/signal.h>
39 #include <netinet/in.h>
41 #include "asterisk/lock.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/options.h"
47 #include "asterisk/causes.h"
48 #include "asterisk/module.h"
49 #include "asterisk/translate.h"
50 #include "asterisk/app.h"
51 #include "asterisk/say.h"
52 #include "asterisk/features.h"
53 #include "asterisk/musiconhold.h"
54 #include "asterisk/config.h"
55 #include "asterisk/cli.h"
56 #include "asterisk/manager.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/adsi.h"
59 #include "asterisk/devicestate.h"
60 #include "asterisk/monitor.h"
62 #define DEFAULT_PARK_TIME 45000
63 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
64 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
65 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
66 #define DEFAULT_ATXFER_DROP_CALL 0
67 #define DEFAULT_ATXFER_LOOP_DELAY 10000
68 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
70 #define AST_MAX_WATCHERS 256
73 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
74 AST_FEATURE_FLAG_ONPEER = (1 << 1),
75 AST_FEATURE_FLAG_ONSELF = (1 << 2),
76 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
77 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
78 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
81 struct feature_group_exten {
82 AST_LIST_ENTRY(feature_group_exten) entry;
83 AST_DECLARE_STRING_FIELDS(
84 AST_STRING_FIELD(exten);
86 struct ast_call_feature *feature;
89 struct feature_group {
90 AST_LIST_ENTRY(feature_group) entry;
91 AST_DECLARE_STRING_FIELDS(
92 AST_STRING_FIELD(gname);
94 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
97 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
99 static char *parkedcall = "ParkedCall";
101 static int parkaddhints = 0; /*!< Add parking hints automatically */
102 static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
103 static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
104 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
105 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
106 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
107 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
108 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
109 static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
110 static int parking_start; /*!< First available extension for parking */
111 static int parking_stop; /*!< Last available extension for parking */
113 static char courtesytone[256]; /*!< Courtesy tone */
114 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
115 static char xfersound[256]; /*!< Call transfer sound */
116 static char xferfailsound[256]; /*!< Call transfer failure sound */
118 static int parking_offset;
119 static int parkfindnext;
123 static int transferdigittimeout;
124 static int featuredigittimeout;
125 static int comebacktoorigin = 1;
127 static int atxfernoanswertimeout;
128 static unsigned int atxferdropcall;
129 static unsigned int atxferloopdelay;
130 static unsigned int atxfercallbackretries;
132 static char *registrar = "res_features"; /*!< Registrar for operations */
134 /* module and CLI command definitions */
135 static char *synopsis = "Answer a parked call";
137 static char *descrip = "ParkedCall(exten):"
138 "Used to connect to a parked call. This application is always\n"
139 "registered internally and does not need to be explicitly added\n"
140 "into the dialplan, although you should include the 'parkedcalls'\n"
143 static char *parkcall = "Park";
145 static char *synopsis2 = "Park yourself";
147 static char *descrip2 = "Park():"
148 "Used to park yourself (typically in combination with a supervised\n"
149 "transfer to know the parking space). This application is always\n"
150 "registered internally and does not need to be explicitly added\n"
151 "into the dialplan, although you should include the 'parkedcalls'\n"
152 "context (or the context specified in features.conf).\n\n"
153 "If you set the PARKINGEXTEN variable to an extension in your\n"
154 "parking context, park() will park the call on that extension, unless\n"
155 "it already exists. In that case, execution will continue at next\n"
158 static struct ast_app *monitor_app = NULL;
159 static int monitor_ok = 1;
162 struct ast_channel *chan; /*!< Parking channel */
163 struct timeval start; /*!< Time the parking started */
164 int parkingnum; /*!< Parking lot */
165 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
166 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
167 char exten[AST_MAX_EXTENSION];
169 int parkingtime; /*!< Maximum length in parking lot before return */
172 unsigned char moh_trys;
173 AST_LIST_ENTRY(parkeduser) list;
176 static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
178 static pthread_t parking_thread;
180 const char *ast_parking_ext(void)
185 const char *ast_pickup_ext(void)
190 struct ast_bridge_thread_obj
192 struct ast_bridge_config bconfig;
193 struct ast_channel *chan;
194 struct ast_channel *peer;
195 unsigned int return_to_pbx:1;
201 * \brief store context, extension and priority
202 * \param chan, context, ext, pri
204 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
206 ast_copy_string(chan->context, context, sizeof(chan->context));
207 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
208 chan->priority = pri;
212 * \brief Check goto on transfer
214 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
215 * When found make sure the types are compatible. Check if channel is valid
216 * if so start the new channel else hangup the call.
218 static void check_goto_on_transfer(struct ast_channel *chan)
220 struct ast_channel *xferchan;
221 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
222 char *x, *goto_on_transfer;
225 if (ast_strlen_zero(val))
228 goto_on_transfer = ast_strdupa(val);
230 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
233 for (x = goto_on_transfer; x && *x; x++) {
237 /* Make formats okay */
238 xferchan->readformat = chan->readformat;
239 xferchan->writeformat = chan->writeformat;
240 ast_channel_masquerade(xferchan, chan);
241 ast_parseable_goto(xferchan, goto_on_transfer);
242 xferchan->_state = AST_STATE_UP;
243 ast_clear_flag(xferchan, AST_FLAGS_ALL);
244 xferchan->_softhangup = 0;
245 if ((f = ast_read(xferchan))) {
248 ast_pbx_start(xferchan);
250 ast_hangup(xferchan);
254 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);
257 * \brief bridge the call
258 * \param data thread bridge
259 * Set Last Data for respective channels, reset cdr for channels
260 * bridge call, check if we're going back to dialplan
261 * if not hangup both legs of the call
263 static void *ast_bridge_call_thread(void *data)
265 struct ast_bridge_thread_obj *tobj = data;
268 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
269 tobj->chan->data = tobj->peer->name;
270 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
271 tobj->peer->data = tobj->chan->name;
273 if (tobj->chan->cdr) {
274 ast_cdr_reset(tobj->chan->cdr, NULL);
275 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
277 if (tobj->peer->cdr) {
278 ast_cdr_reset(tobj->peer->cdr, NULL);
279 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
282 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
284 if (tobj->return_to_pbx) {
285 if (!ast_check_hangup(tobj->peer)) {
286 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
287 res = ast_pbx_start(tobj->peer);
288 if (res != AST_PBX_SUCCESS)
289 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
291 ast_hangup(tobj->peer);
292 if (!ast_check_hangup(tobj->chan)) {
293 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
294 res = ast_pbx_start(tobj->chan);
295 if (res != AST_PBX_SUCCESS)
296 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
298 ast_hangup(tobj->chan);
300 ast_hangup(tobj->chan);
301 ast_hangup(tobj->peer);
310 * \brief create thread for the parked call
312 * Create thread and attributes, call ast_bridge_call_thread
314 static void ast_bridge_call_thread_launch(void *data)
318 struct sched_param sched;
320 pthread_attr_init(&attr);
321 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
322 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
323 pthread_attr_destroy(&attr);
324 memset(&sched, 0, sizeof(sched));
325 pthread_setschedparam(thread, SCHED_RR, &sched);
329 * \brief Announce call parking by ADSI
331 * \param parkingexten
332 * Create message to show for ADSI, display message.
333 * \retval 0 on success.
334 * \retval -1 on failure.
336 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
339 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
341 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
343 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
345 res = ast_adsi_load_session(chan, NULL, 0, 1);
348 return ast_adsi_print(chan, message, justify, 1);
351 /*! \brief Notify metermaids that we've changed an extension */
352 static void notify_metermaids(const char *exten, char *context)
354 ast_debug(4, "Notification of state change to metermaids %s@%s\n", exten, context);
356 /* Send notification to devicestate subsystem */
357 ast_device_state_changed("park:%s@%s", exten, context);
361 /*! \brief metermaids callback from devicestate.c */
362 static enum ast_device_state metermaidstate(const char *data)
367 context = ast_strdupa(data);
369 exten = strsep(&context, "@");
371 return AST_DEVICE_INVALID;
373 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
375 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
376 return AST_DEVICE_NOT_INUSE;
378 return AST_DEVICE_INUSE;
382 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
384 struct parkeduser *pu, *cur;
385 int i, x = -1, parking_range;
386 struct ast_context *con;
387 const char *parkingexten;
389 /* Allocate memory for parking data */
390 if (!(pu = ast_calloc(1, sizeof(*pu))))
393 /* Lock parking lot */
394 AST_LIST_LOCK(&parkinglot);
395 /* Check for channel variable PARKINGEXTEN */
396 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
397 if (!ast_strlen_zero(parkingexten)) {
398 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
399 AST_LIST_UNLOCK(&parkinglot);
401 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
402 return -1; /* We failed to park this call, plain and simple so we need to error out */
404 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
405 x = atoi(parkingexten);
407 /* Select parking space within range */
408 parking_range = parking_stop - parking_start+1;
409 for (i = 0; i < parking_range; i++) {
410 x = (i + parking_offset) % parking_range + parking_start;
411 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
412 if (cur->parkingnum == x)
419 if (!(i < parking_range)) {
420 ast_log(LOG_WARNING, "No more parking spaces\n");
422 AST_LIST_UNLOCK(&parkinglot);
425 /* Set pointer for next parking */
427 parking_offset = x - parking_start + 1;
430 chan->appl = "Parked Call";
435 /* Put the parked channel on hold if we have two different channels */
437 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
438 S_OR(parkmohclass, NULL),
439 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
442 pu->start = ast_tvnow();
444 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
449 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
451 /* Remember what had been dialed, so that if the parking
452 expires, we try to come back to the same place */
453 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
454 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
455 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
456 AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
458 /* If parking a channel directly, don't quiet yet get parking running on it */
461 AST_LIST_UNLOCK(&parkinglot);
462 /* Wake up the (presumably select()ing) thread */
463 pthread_kill(parking_thread, SIGURG);
464 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));
466 if (pu->parkingnum != -1)
467 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
468 manager_event(EVENT_FLAG_CALL, "ParkedCall",
473 "CallerIDNum: %s\r\n"
474 "CallerIDName: %s\r\n",
475 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
476 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
477 S_OR(pu->chan->cid.cid_num, "<unknown>"),
478 S_OR(pu->chan->cid.cid_name, "<unknown>")
481 if (peer && adsipark && ast_adsi_available(peer)) {
482 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
483 ast_adsi_unload_session(peer);
486 con = ast_context_find(parking_con);
488 con = ast_context_create(NULL, parking_con, registrar);
489 if (!con) /* Still no context? Bad */
490 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
491 /* Tell the peer channel the number of the parking space */
492 if (peer && pu->parkingnum != -1) /* Only say number if it's a number */
493 ast_say_digits(peer, pu->parkingnum, "", peer->language);
495 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free, registrar))
496 notify_metermaids(pu->parkingexten, parking_con);
498 if (pu->notquiteyet) {
499 /* Wake up parking thread if we're really done */
500 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
501 S_OR(parkmohclass, NULL),
502 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
504 pthread_kill(parking_thread, SIGURG);
509 /* Park call via masquraded channel */
510 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
512 struct ast_channel *chan;
515 /* Make a new, fake channel that we'll use to masquerade in the real one */
516 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
517 ast_log(LOG_WARNING, "Unable to create parked channel\n");
521 /* Make formats okay */
522 chan->readformat = rchan->readformat;
523 chan->writeformat = rchan->writeformat;
524 ast_channel_masquerade(chan, rchan);
526 /* Setup the extensions and such */
527 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
529 /* Make the masq execute */
534 ast_park_call(chan, peer, timeout, extout);
539 #define FEATURE_RETURN_HANGUP -1
540 #define FEATURE_RETURN_SUCCESSBREAK 0
541 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
542 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
543 #define FEATURE_RETURN_PASSDIGITS 21
544 #define FEATURE_RETURN_STOREDIGITS 22
545 #define FEATURE_RETURN_SUCCESS 23
547 #define FEATURE_SENSE_CHAN (1 << 0)
548 #define FEATURE_SENSE_PEER (1 << 1)
551 * \brief set caller and callee according to the direction
552 * \param caller, callee, peer, chan, sense
553 * Detect who triggered feature and set callee/caller variables accordingly
555 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
556 struct ast_channel *peer, struct ast_channel *chan, int sense)
558 if (sense == FEATURE_SENSE_PEER) {
568 * \brief support routing for one touch call parking
569 * \param chan channel parking call
570 * \param peer channel to be parked
571 * \param config unsed
573 * \param sense feature options
574 * Setup channel, set return exten,priority to 's,1'
575 * answer chan, sleep chan, park call
577 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
579 struct ast_channel *parker;
580 struct ast_channel *parkee;
582 struct ast_module_user *u;
584 u = ast_module_user_add(chan);
586 set_peers(&parker, &parkee, peer, chan, sense);
587 /* Setup the exten/priority to be s/1 since we don't know
588 where this call should return */
589 strcpy(chan->exten, "s");
591 if (chan->_state != AST_STATE_UP)
592 res = ast_answer(chan);
594 res = ast_safe_sleep(chan, 1000);
596 res = ast_park_call(parkee, parker, 0, NULL);
598 ast_module_user_remove(u);
601 if (sense == FEATURE_SENSE_CHAN)
602 res = AST_PBX_NO_HANGUP_PEER;
604 res = AST_PBX_KEEPALIVE;
611 * \brief Monitor a channel by DTMF
612 * \param chan channel requesting monitor
613 * \param peer channel to be monitored
617 * Check monitor app enabled, setup channels, both caller/callee chans not null
618 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
619 * \retval FEATURE_RETURN_SUCCESS on success.
620 * \retval -1 on error.
622 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
624 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
627 struct ast_channel *caller_chan, *callee_chan;
630 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
634 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
636 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
640 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
642 if (!ast_strlen_zero(courtesytone)) {
643 if (ast_autoservice_start(callee_chan))
645 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
646 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
647 ast_autoservice_stop(callee_chan);
650 if (ast_autoservice_stop(callee_chan))
654 if (callee_chan->monitor) {
655 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
656 ast_monitor_stop(callee_chan, 1);
657 return FEATURE_RETURN_SUCCESS;
660 if (caller_chan && callee_chan) {
661 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
662 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
665 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
668 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
671 len = strlen(touch_monitor) + 50;
673 touch_filename = alloca(len);
674 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
675 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
677 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
678 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
679 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
681 touch_filename = alloca(len);
682 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
683 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
686 for(x = 0; x < strlen(args); x++) {
691 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
693 pbx_exec(callee_chan, monitor_app, args);
694 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
695 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
697 return FEATURE_RETURN_SUCCESS;
700 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
704 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
706 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
707 return FEATURE_RETURN_HANGUP;
710 static int finishup(struct ast_channel *chan)
712 ast_indicate(chan, AST_CONTROL_UNHOLD);
714 return ast_autoservice_stop(chan);
718 * \brief Find the context for the transfer
721 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
722 * \return a context string
724 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
726 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
727 if (ast_strlen_zero(s))
728 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
729 if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
730 s = transferer->macrocontext;
731 if (ast_strlen_zero(s))
732 s = transferer->context;
737 * \brief Blind transfer user to another extension
738 * \param chan channel initiated blind transfer
739 * \param peer channel to be transfered
743 * Place peer on hold, check if tranfered to parkinglot extension,
744 * otherwise check extension exists and transfer caller.
745 * \retval FEATURE_RETURN_SUCCESS.
746 * \retval -1 on failure.
748 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
750 struct ast_channel *transferer;
751 struct ast_channel *transferee;
752 const char *transferer_real_context;
756 set_peers(&transferer, &transferee, peer, chan, sense);
757 transferer_real_context = real_ctx(transferer, transferee);
758 /* Start autoservice on chan while we talk to the originator */
759 ast_autoservice_start(transferee);
760 ast_indicate(transferee, AST_CONTROL_HOLD);
762 memset(xferto, 0, sizeof(xferto));
765 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
767 finishup(transferee);
768 return -1; /* error ? */
770 if (res > 0) /* If they've typed a digit already, handle it */
771 xferto[0] = (char) res;
773 ast_stopstream(transferer);
774 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
775 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
776 finishup(transferee);
779 if (!strcmp(xferto, ast_parking_ext())) {
780 res = finishup(transferee);
783 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
784 /* We return non-zero, but tell the PBX not to hang the channel when
785 the thread dies -- We have to be careful now though. We are responsible for
786 hanging up the channel, else it will never be hung up! */
788 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
790 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
792 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
793 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
794 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
795 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
796 res=finishup(transferee);
797 if (!transferer->cdr) {
798 transferer->cdr=ast_cdr_alloc();
800 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
801 ast_cdr_start(transferer->cdr);
804 if (transferer->cdr) {
805 ast_cdr_setdestchan(transferer->cdr, transferee->name);
806 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
809 if (!transferee->pbx)
812 /* Doh! Use our handy async_goto functions */
813 ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
814 ,transferee->name, xferto, transferer_real_context);
815 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
816 ast_log(LOG_WARNING, "Async goto failed :-(\n");
817 check_goto_on_transfer(transferer);
820 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
822 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
823 finishup(transferee);
826 ast_stopstream(transferer);
827 res = finishup(transferee);
829 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
832 return FEATURE_RETURN_SUCCESS;
836 * \brief make channels compatible
839 * \retval 0 on success.
840 * \retval -1 on failure.
842 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
844 if (ast_channel_make_compatible(c, newchan) < 0) {
845 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
846 c->name, newchan->name);
854 * \brief Attended transfer
860 * Get extension to transfer to, if you cannot generate channel (or find extension)
861 * return to host channel. After called channel answered wait for hangup of transferer,
862 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
863 * \return -1 means what failure/success both?
865 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
867 struct ast_channel *transferer;
868 struct ast_channel *transferee;
869 const char *transferer_real_context;
870 char xferto[256] = "";
871 char callbackto[256] = "";
874 struct ast_channel *newchan;
875 struct ast_channel *xferchan;
876 struct ast_bridge_thread_obj *tobj;
877 struct ast_bridge_config bconfig;
881 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
882 set_peers(&transferer, &transferee, peer, chan, sense);
883 transferer_real_context = real_ctx(transferer, transferee);
884 /* Start autoservice on chan while we talk to the originator */
885 ast_autoservice_start(transferee);
886 ast_indicate(transferee, AST_CONTROL_HOLD);
889 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
891 finishup(transferee);
894 if (res > 0) /* If they've typed a digit already, handle it */
895 xferto[0] = (char) res;
897 /* this is specific of atxfer */
898 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
899 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
900 finishup(transferee);
904 ast_log(LOG_WARNING, "Did not read data.\n");
905 finishup(transferee);
906 if (ast_stream_and_wait(transferer, "beeperr", ""))
908 return FEATURE_RETURN_SUCCESS;
911 /* valid extension, res == 1 */
912 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
913 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
914 finishup(transferee);
915 if (ast_stream_and_wait(transferer, "beeperr", ""))
917 return FEATURE_RETURN_SUCCESS;
921 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
922 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
923 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
925 if (!ast_check_hangup(transferer)) {
926 /* Transferer is up - old behaviour */
927 ast_indicate(transferer, -1);
929 finishup(transferee);
930 /* any reason besides user requested cancel and busy triggers the failed sound */
931 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
932 ast_stream_and_wait(transferer, xferfailsound, ""))
934 if (ast_stream_and_wait(transferer, xfersound, ""))
935 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
936 return FEATURE_RETURN_SUCCESS;
939 if (check_compat(transferer, newchan))
941 memset(&bconfig,0,sizeof(struct ast_bridge_config));
942 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
943 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
944 res = ast_bridge_call(transferer, newchan, &bconfig);
945 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
947 if (ast_stream_and_wait(transferer, xfersound, ""))
948 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
949 finishup(transferee);
950 transferer->_softhangup = 0;
951 return FEATURE_RETURN_SUCCESS;
953 if (check_compat(transferee, newchan))
955 ast_indicate(transferee, AST_CONTROL_UNHOLD);
957 if ((ast_autoservice_stop(transferee) < 0)
958 || (ast_waitfordigit(transferee, 100) < 0)
959 || (ast_waitfordigit(newchan, 100) < 0)
960 || ast_check_hangup(transferee)
961 || ast_check_hangup(newchan)) {
965 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
970 /* Make formats okay */
971 xferchan->readformat = transferee->readformat;
972 xferchan->writeformat = transferee->writeformat;
973 ast_channel_masquerade(xferchan, transferee);
974 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
975 xferchan->_state = AST_STATE_UP;
976 ast_clear_flag(xferchan, AST_FLAGS_ALL);
977 xferchan->_softhangup = 0;
978 if ((f = ast_read(xferchan)))
980 newchan->_state = AST_STATE_UP;
981 ast_clear_flag(newchan, AST_FLAGS_ALL);
982 newchan->_softhangup = 0;
983 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
984 ast_hangup(xferchan);
988 tobj->chan = xferchan;
989 tobj->peer = newchan;
990 tobj->bconfig = *config;
992 if (ast_stream_and_wait(newchan, xfersound, ""))
993 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
994 ast_bridge_call_thread_launch(tobj);
995 return -1; /* XXX meaning the channel is bridged ? */
996 } else if (!ast_check_hangup(transferee)) {
997 /* act as blind transfer */
998 if (ast_autoservice_stop(transferee) < 0) {
1004 unsigned int tries = 0;
1006 /* newchan wasn't created - we should callback to transferer */
1007 if (!ast_exists_extension(transferer, transferer_real_context, transferer->cid.cid_num, 1, transferee->cid.cid_num)) {
1008 ast_log(LOG_WARNING, "Extension %s does not exist in context %s - callback failed\n",transferer->cid.cid_num,transferer_real_context);
1009 if (ast_stream_and_wait(transferee, "beeperr", ""))
1011 return FEATURE_RETURN_SUCCESS;
1013 snprintf(callbackto, sizeof(callbackto), "%s@%s/n", transferer->cid.cid_num, transferer_real_context); /* append context */
1015 newchan = ast_feature_request_and_dial(transferee, NULL, "Local", ast_best_codec(transferee->nativeformats),
1016 callbackto, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
1017 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1018 /* Trying to transfer again */
1019 ast_autoservice_start(transferee);
1020 ast_indicate(transferee, AST_CONTROL_HOLD);
1022 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1023 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
1024 if (ast_autoservice_stop(transferee) < 0) {
1025 ast_hangup(newchan);
1029 /* Transfer failed, sleeping */
1030 ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1031 ast_safe_sleep(transferee, atxferloopdelay);
1032 ast_debug(1, "Trying to callback...\n");
1033 newchan = ast_feature_request_and_dial(transferee, NULL, "Local", ast_best_codec(transferee->nativeformats),
1034 callbackto, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
1042 /* newchan is up, we should prepare transferee and bridge them */
1043 if (check_compat(transferee, newchan))
1045 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1047 if ((ast_waitfordigit(transferee, 100) < 0)
1048 || (ast_waitfordigit(newchan, 100) < 0)
1049 || ast_check_hangup(transferee)
1050 || ast_check_hangup(newchan)) {
1051 ast_hangup(newchan);
1055 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1057 ast_hangup(newchan);
1060 /* Make formats okay */
1061 xferchan->readformat = transferee->readformat;
1062 xferchan->writeformat = transferee->writeformat;
1063 ast_channel_masquerade(xferchan, transferee);
1064 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1065 xferchan->_state = AST_STATE_UP;
1066 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1067 xferchan->_softhangup = 0;
1068 if ((f = ast_read(xferchan)))
1070 newchan->_state = AST_STATE_UP;
1071 ast_clear_flag(newchan, AST_FLAGS_ALL);
1072 newchan->_softhangup = 0;
1073 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1074 ast_hangup(xferchan);
1075 ast_hangup(newchan);
1078 tobj->chan = xferchan;
1079 tobj->peer = newchan;
1080 tobj->bconfig = *config;
1082 if (ast_stream_and_wait(newchan, xfersound, ""))
1083 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1084 ast_bridge_call_thread_launch(tobj);
1085 return -1; /* XXX meaning the channel is bridged ? */
1087 /* Transferee hung up */
1088 finishup(transferee);
1093 /* add atxfer and automon as undefined so you can only use em if you configure them */
1094 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1096 AST_RWLOCK_DEFINE_STATIC(features_lock);
1098 static struct ast_call_feature builtin_features[] =
1100 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1101 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1102 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1103 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1104 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1108 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1110 /*! \brief register new feature into feature_list*/
1111 void ast_register_feature(struct ast_call_feature *feature)
1114 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1118 AST_LIST_LOCK(&feature_list);
1119 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1120 AST_LIST_UNLOCK(&feature_list);
1122 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1126 * \brief Add new feature group
1127 * \param fgname feature group name
1128 * Add new feature group to the feature group list insert at head of list.
1129 * \note This function MUST be called while feature_groups is locked.
1131 static struct feature_group* register_group(const char *fgname)
1133 struct feature_group *fg;
1136 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1140 if (!(fg = ast_calloc(1, sizeof(*fg))))
1143 if (ast_string_field_init(fg, 128)) {
1148 ast_string_field_set(fg, gname, fgname);
1150 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1152 ast_verb(2, "Registered group '%s'\n", fg->gname);
1158 * \brief Add feature to group
1159 * \param fg feature group
1161 * \param feature feature to add
1162 * Check fg and feature specified, add feature to list
1163 * \note This function MUST be called while feature_groups is locked.
1165 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
1167 struct feature_group_exten *fge;
1169 if (!(fge = ast_calloc(1, sizeof(*fge))))
1172 if (ast_string_field_init(fge, 128)) {
1178 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1183 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1187 ast_string_field_set(fge, exten, (ast_strlen_zero(exten) ? feature->exten : exten));
1189 fge->feature = feature;
1191 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
1193 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1194 feature->sname, fg->gname, exten);
1197 void ast_unregister_feature(struct ast_call_feature *feature)
1202 AST_LIST_LOCK(&feature_list);
1203 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1204 AST_LIST_UNLOCK(&feature_list);
1208 /*! \brief Remove all features in the list */
1209 static void ast_unregister_features(void)
1211 struct ast_call_feature *feature;
1213 AST_LIST_LOCK(&feature_list);
1214 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1216 AST_LIST_UNLOCK(&feature_list);
1219 /*! \brief find a call feature by name */
1220 static struct ast_call_feature *find_dynamic_feature(const char *name)
1222 struct ast_call_feature *tmp;
1224 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1225 if (!strcasecmp(tmp->sname, name))
1232 /*! \brief Remove all feature groups in the list */
1233 static void ast_unregister_groups(void)
1235 struct feature_group *fg;
1236 struct feature_group_exten *fge;
1238 AST_RWLIST_WRLOCK(&feature_groups);
1239 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1240 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1241 ast_string_field_free_all(fge);
1245 ast_string_field_free_all(fg);
1248 AST_RWLIST_UNLOCK(&feature_groups);
1252 * \brief Find a group by name
1253 * \param name feature name
1254 * \retval feature group on success.
1255 * \retval NULL on failure.
1257 static struct feature_group *find_group(const char *name) {
1258 struct feature_group *fg = NULL;
1260 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1261 if (!strcasecmp(fg->gname, name))
1269 * \brief Find a feature extension
1271 * \retval feature group extension on success.
1272 * \retval NULL on failure.
1274 static struct feature_group_exten *find_group_exten(struct feature_group *fg, const char *code) {
1275 struct feature_group_exten *fge = NULL;
1277 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1278 if(!strcasecmp(fge->exten, code))
1285 void ast_rdlock_call_features(void)
1287 ast_rwlock_rdlock(&features_lock);
1290 void ast_unlock_call_features(void)
1292 ast_rwlock_unlock(&features_lock);
1295 struct ast_call_feature *ast_find_call_feature(const char *name)
1298 for (x = 0; x < FEATURES_COUNT; x++) {
1299 if (!strcasecmp(name, builtin_features[x].sname))
1300 return &builtin_features[x];
1306 * \brief exec an app by feature
1307 * \param chan,peer,config,code,sense
1308 * Find a feature, determine which channel activated
1309 * \retval FEATURE_RETURN_PBX_KEEPALIVE,FEATURE_RETURN_NO_HANGUP_PEER
1311 * \retval -2 when an application cannot be found.
1313 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1315 struct ast_app *app;
1316 struct ast_call_feature *feature;
1317 struct ast_channel *work, *idle;
1320 AST_LIST_LOCK(&feature_list);
1321 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1322 if (!strcasecmp(feature->exten, code))
1325 AST_LIST_UNLOCK(&feature_list);
1327 if (!feature) { /* shouldn't ever happen! */
1328 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1332 if (sense == FEATURE_SENSE_CHAN) {
1333 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1334 return FEATURE_RETURN_PASSDIGITS;
1335 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1343 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1344 return FEATURE_RETURN_PASSDIGITS;
1345 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1354 if (!(app = pbx_findapp(feature->app))) {
1355 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1359 ast_autoservice_start(idle);
1361 if (!ast_strlen_zero(feature->moh_class))
1362 ast_moh_start(idle, feature->moh_class, NULL);
1364 res = pbx_exec(work, app, feature->app_args);
1366 if (!ast_strlen_zero(feature->moh_class))
1369 ast_autoservice_stop(idle);
1371 if (res == AST_PBX_KEEPALIVE)
1372 return FEATURE_RETURN_PBX_KEEPALIVE;
1373 else if (res == AST_PBX_NO_HANGUP_PEER)
1374 return FEATURE_RETURN_NO_HANGUP_PEER;
1376 return FEATURE_RETURN_SUCCESSBREAK;
1378 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1381 static void unmap_features(void)
1385 ast_rwlock_wrlock(&features_lock);
1386 for (x = 0; x < FEATURES_COUNT; x++)
1387 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1388 ast_rwlock_unlock(&features_lock);
1391 static int remap_feature(const char *name, const char *value)
1395 ast_rwlock_wrlock(&features_lock);
1396 for (x = 0; x < FEATURES_COUNT; x++) {
1397 if (strcasecmp(builtin_features[x].sname, name))
1400 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1404 ast_rwlock_unlock(&features_lock);
1410 * \brief Check the dynamic features
1411 * \param chan,peer,config,code,sense
1412 * Lock features list, browse for code, unlock list
1413 * \retval res on success.
1414 * \retval -1 on failure.
1416 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1419 struct ast_flags features;
1420 int res = FEATURE_RETURN_PASSDIGITS;
1421 struct ast_call_feature *feature;
1422 struct feature_group *fg = NULL;
1423 struct feature_group_exten *fge;
1424 const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1427 if (sense == FEATURE_SENSE_CHAN)
1428 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1430 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1431 ast_debug(3, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1433 ast_rwlock_rdlock(&features_lock);
1434 for (x = 0; x < FEATURES_COUNT; x++) {
1435 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1436 !ast_strlen_zero(builtin_features[x].exten)) {
1437 /* Feature is up for consideration */
1438 if (!strcmp(builtin_features[x].exten, code)) {
1439 res = builtin_features[x].operation(chan, peer, config, code, sense);
1441 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1442 if (res == FEATURE_RETURN_PASSDIGITS)
1443 res = FEATURE_RETURN_STOREDIGITS;
1447 ast_rwlock_unlock(&features_lock);
1449 if (ast_strlen_zero(dynamic_features))
1452 tmp = ast_strdupa(dynamic_features);
1454 while ((tok = strsep(&tmp, "#"))) {
1455 AST_RWLIST_RDLOCK(&feature_groups);
1457 fg = find_group(tok);
1459 if (fg && (fge = find_group_exten(fg, code))) {
1460 res = fge->feature->operation(chan, peer, config, code, sense);
1461 AST_RWLIST_UNLOCK(&feature_groups);
1465 AST_RWLIST_UNLOCK(&feature_groups);
1466 AST_LIST_LOCK(&feature_list);
1468 if(!(feature = find_dynamic_feature(tok))) {
1469 AST_LIST_UNLOCK(&feature_list);
1473 /* Feature is up for consideration */
1474 if (!strcmp(feature->exten, code)) {
1475 ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1476 res = feature->operation(chan, peer, config, code, sense);
1477 AST_LIST_UNLOCK(&feature_list);
1479 } else if (!strncmp(feature->exten, code, strlen(code)))
1480 res = FEATURE_RETURN_STOREDIGITS;
1482 AST_LIST_UNLOCK(&feature_list);
1488 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1492 ast_clear_flag(config, AST_FLAGS_ALL);
1494 ast_rwlock_rdlock(&features_lock);
1495 for (x = 0; x < FEATURES_COUNT; x++) {
1496 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1499 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1500 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1502 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1503 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1505 ast_rwlock_unlock(&features_lock);
1507 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1508 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1510 if (dynamic_features) {
1511 char *tmp = ast_strdupa(dynamic_features);
1513 struct ast_call_feature *feature;
1515 /* while we have a feature */
1516 while ((tok = strsep(&tmp, "#"))) {
1517 AST_LIST_LOCK(&feature_list);
1518 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1519 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1520 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1521 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1522 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1524 AST_LIST_UNLOCK(&feature_list);
1532 * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1533 * Request channel, set channel variables, initiate call,check if they want to disconnect
1534 * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1535 * check for answer break loop, set cdr return channel.
1536 * \todo XXX Check - this is very similar to the code in channel.c
1537 * \return always a channel
1539 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)
1544 struct ast_channel *chan;
1545 struct ast_channel *monitor_chans[2];
1546 struct ast_channel *active_channel;
1547 int res = 0, ready = 0;
1549 if ((chan = ast_request(type, format, data, &cause))) {
1550 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1551 ast_channel_inherit_variables(caller, chan);
1552 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1554 chan->cdr=ast_cdr_alloc();
1556 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1557 ast_cdr_start(chan->cdr);
1561 if (!ast_call(chan, data, timeout)) {
1562 struct timeval started;
1564 char *disconnect_code = NULL, *dialed_code = NULL;
1566 ast_indicate(caller, AST_CONTROL_RINGING);
1567 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1568 ast_rwlock_rdlock(&features_lock);
1569 for (x = 0; x < FEATURES_COUNT; x++) {
1570 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1573 disconnect_code = builtin_features[x].exten;
1574 len = strlen(disconnect_code) + 1;
1575 dialed_code = alloca(len);
1576 memset(dialed_code, 0, len);
1579 ast_rwlock_unlock(&features_lock);
1581 started = ast_tvnow();
1583 while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1584 struct ast_frame *f = NULL;
1586 monitor_chans[0] = caller;
1587 monitor_chans[1] = chan;
1588 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1590 /* see if the timeout has been violated */
1591 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1592 state = AST_CONTROL_UNHOLD;
1593 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1594 break; /*doh! timeout*/
1597 if (!active_channel)
1600 if (chan && (chan == active_channel)){
1602 if (f == NULL) { /*doh! where'd he go?*/
1603 state = AST_CONTROL_HANGUP;
1608 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1609 if (f->subclass == AST_CONTROL_RINGING) {
1610 state = f->subclass;
1611 ast_verb(3, "%s is ringing\n", chan->name);
1612 ast_indicate(caller, AST_CONTROL_RINGING);
1613 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1614 state = f->subclass;
1615 ast_verb(3, "%s is busy\n", chan->name);
1616 ast_indicate(caller, AST_CONTROL_BUSY);
1620 } else if (f->subclass == AST_CONTROL_ANSWER) {
1621 /* This is what we are hoping for */
1622 state = f->subclass;
1628 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1630 /* else who cares */
1633 } else if (caller && (active_channel == caller)) {
1634 f = ast_read(caller);
1635 if (f == NULL) { /*doh! where'd he go?*/
1636 if (!igncallerstate) {
1637 if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
1638 /* make this a blind transfer */
1642 state = AST_CONTROL_HANGUP;
1648 if (f->frametype == AST_FRAME_DTMF) {
1649 dialed_code[x++] = f->subclass;
1650 dialed_code[x] = '\0';
1651 if (strlen(dialed_code) == len) {
1653 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1655 dialed_code[x] = '\0';
1657 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1658 /* Caller Canceled the call */
1659 state = AST_CONTROL_UNHOLD;
1671 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1673 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1675 case AST_CAUSE_BUSY:
1676 state = AST_CONTROL_BUSY;
1678 case AST_CAUSE_CONGESTION:
1679 state = AST_CONTROL_CONGESTION;
1684 ast_indicate(caller, -1);
1685 if (chan && ready) {
1686 if (chan->_state == AST_STATE_UP)
1687 state = AST_CONTROL_ANSWER;
1700 if (chan && res <= 0) {
1701 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1703 ast_cdr_init(chan->cdr, chan);
1704 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1705 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1706 ast_cdr_update(chan);
1707 ast_cdr_start(chan->cdr);
1708 ast_cdr_end(chan->cdr);
1709 /* If the cause wasn't handled properly */
1710 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1711 ast_cdr_failed(chan->cdr);
1713 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1721 * \brief bridge the call and set CDR
1722 * \param chan,peer,config
1723 * Set start time, check for two channels,check if monitor on
1724 * check for feature activation, create new CDR
1725 * \retval res on success.
1726 * \retval -1 on failure to bridge.
1728 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1730 /* Copy voice back and forth between the two channels. Give the peer
1731 the ability to transfer calls with '#<extension' syntax. */
1732 struct ast_frame *f;
1733 struct ast_channel *who;
1734 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1735 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1740 struct ast_option_header *aoh;
1741 struct ast_bridge_config backup_config;
1742 struct ast_cdr *bridge_cdr;
1744 memset(&backup_config, 0, sizeof(backup_config));
1746 config->start_time = ast_tvnow();
1749 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1750 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1752 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1755 const char *monitor_exec;
1756 struct ast_channel *src = NULL;
1758 if (!(monitor_app = pbx_findapp("Monitor")))
1761 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1763 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1765 if (monitor_app && src) {
1766 char *tmp = ast_strdupa(monitor_exec);
1767 pbx_exec(src, monitor_app, tmp);
1771 set_config_flags(chan, peer, config);
1772 config->firstpass = 1;
1774 /* Answer if need be */
1775 if (ast_answer(chan))
1777 peer->appl = "Bridged Call";
1778 peer->data = chan->name;
1780 /* copy the userfield from the B-leg to A-leg if applicable */
1781 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1783 if (!ast_strlen_zero(chan->cdr->userfield)) {
1784 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1785 ast_cdr_appenduserfield(chan, tmp);
1787 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1788 /* free the peer's cdr without ast_cdr_free complaining */
1789 ast_free(peer->cdr);
1794 struct ast_channel *other; /* used later */
1796 res = ast_channel_bridge(chan, peer, config, &f, &who);
1798 if (config->feature_timer) {
1799 /* Update time limit for next pass */
1800 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1801 config->feature_timer -= diff;
1803 /* Running on backup config, meaning a feature might be being
1804 activated, but that's no excuse to keep things going
1806 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1807 ast_debug(1, "Timed out, realtime this time!\n");
1808 config->feature_timer = 0;
1814 } else if (config->feature_timer <= 0) {
1815 /* Not *really* out of time, just out of time for
1816 digits to come in for features. */
1817 ast_debug(1, "Timed out for feature!\n");
1818 if (!ast_strlen_zero(peer_featurecode)) {
1819 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
1820 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1822 if (!ast_strlen_zero(chan_featurecode)) {
1823 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
1824 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1828 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1830 /* Restore original (possibly time modified) bridge config */
1831 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1832 memset(&backup_config, 0, sizeof(backup_config));
1834 hadfeatures = hasfeatures;
1835 /* Continue as we were */
1838 /* The bridge returned without a frame and there is a feature in progress.
1839 * However, we don't think the feature has quite yet timed out, so just
1840 * go back into the bridge. */
1844 if (config->feature_timer <=0) {
1845 /* We ran out of time */
1846 config->feature_timer = 0;
1856 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1860 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1861 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1862 f->subclass == AST_CONTROL_CONGESTION))) {
1866 /* many things should be sent to the 'other' channel */
1867 other = (who == chan) ? peer : chan;
1868 if (f->frametype == AST_FRAME_CONTROL) {
1869 switch (f->subclass) {
1870 case AST_CONTROL_RINGING:
1871 case AST_CONTROL_FLASH:
1873 ast_indicate(other, f->subclass);
1875 case AST_CONTROL_HOLD:
1876 case AST_CONTROL_UNHOLD:
1877 ast_indicate_data(other, f->subclass, f->data, f->datalen);
1879 case AST_CONTROL_OPTION:
1881 /* Forward option Requests */
1882 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
1883 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
1884 f->datalen - sizeof(struct ast_option_header), 0);
1888 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1890 } else if (f->frametype == AST_FRAME_DTMF) {
1894 hadfeatures = hasfeatures;
1895 /* This cannot overrun because the longest feature is one shorter than our buffer */
1897 sense = FEATURE_SENSE_CHAN;
1898 featurecode = chan_featurecode;
1900 sense = FEATURE_SENSE_PEER;
1901 featurecode = peer_featurecode;
1903 /*! append the event to featurecode. we rely on the string being zero-filled, and
1904 * not overflowing it.
1905 * \todo XXX how do we guarantee the latter ?
1907 featurecode[strlen(featurecode)] = f->subclass;
1908 /* Get rid of the frame before we start doing "stuff" with the channels */
1911 config->feature_timer = backup_config.feature_timer;
1912 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1914 case FEATURE_RETURN_PASSDIGITS:
1915 ast_dtmf_stream(other, who, featurecode, 0, 0);
1917 case FEATURE_RETURN_SUCCESS:
1918 memset(featurecode, 0, sizeof(chan_featurecode));
1921 if (res >= FEATURE_RETURN_PASSDIGITS) {
1925 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1926 if (hadfeatures && !hasfeatures) {
1927 /* Restore backup */
1928 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1929 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1930 } else if (hasfeatures) {
1932 /* Backup configuration */
1933 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1934 /* Setup temporary config options */
1935 config->play_warning = 0;
1936 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1937 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1938 config->warning_freq = 0;
1939 config->warning_sound = NULL;
1940 config->end_sound = NULL;
1941 config->start_sound = NULL;
1942 config->firstpass = 0;
1944 config->start_time = ast_tvnow();
1945 config->feature_timer = featuredigittimeout;
1946 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
1953 /* arrange the cdrs */
1954 bridge_cdr = ast_cdr_alloc();
1956 if (chan->cdr && peer->cdr) { /* both of them? merge */
1957 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
1958 ast_cdr_start(bridge_cdr); /* now is the time to start */
1960 /* absorb the channel cdr */
1961 ast_cdr_merge(bridge_cdr, chan->cdr);
1962 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
1963 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1965 /* absorb the peer cdr */
1966 ast_cdr_merge(bridge_cdr, peer->cdr);
1967 if (ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
1968 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
1971 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1972 } else if (chan->cdr) {
1973 /* take the cdr from the channel - literally */
1974 ast_cdr_init(bridge_cdr,chan);
1975 /* absorb this data */
1976 ast_cdr_merge(bridge_cdr, chan->cdr);
1977 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
1978 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1979 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1980 } else if (peer->cdr) {
1981 /* take the cdr from the peer - literally */
1982 ast_cdr_init(bridge_cdr,peer);
1983 /* absorb this data */
1984 ast_cdr_merge(bridge_cdr, peer->cdr);
1985 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
1986 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1988 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1990 /* make up a new cdr */
1991 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
1992 chan->cdr = bridge_cdr; /* */
1994 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
1995 if (strcmp(bridge_cdr->channel, peer->name) != 0)
1996 ast_cdr_setdestchan(bridge_cdr, peer->name);
1998 ast_cdr_setdestchan(bridge_cdr, chan->name);
2004 /*! \brief Output parking event to manager */
2005 static void post_manager_event(const char *s, struct parkeduser *pu)
2007 manager_event(EVENT_FLAG_CALL, s,
2010 "CallerIDNum: %s\r\n"
2011 "CallerIDName: %s\r\n\r\n",
2014 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2015 S_OR(pu->chan->cid.cid_name, "<unknown>")
2020 * \brief Take care of parked calls and unpark them if needed
2021 * \param ignore unused var
2022 * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2023 * if so, remove channel from parking lot and return it to the extension that parked it.
2024 * Check if parked channel decided to hangup, wait until next FD via select().
2026 static void *do_parking_thread(void *ignore)
2028 char parkingslot[AST_MAX_EXTENSION];
2029 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
2035 struct parkeduser *pu;
2036 int ms = -1; /* select timeout, uninitialized */
2037 int max = -1; /* max fd, none there yet */
2038 fd_set nrfds, nefds; /* args for the next select */
2042 AST_LIST_LOCK(&parkinglot);
2043 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2044 struct ast_channel *chan = pu->chan; /* shorthand */
2045 int tms; /* timeout for this item */
2046 int x; /* fd index in channel */
2047 struct ast_context *con;
2049 if (pu->notquiteyet) /* Pretend this one isn't here yet */
2051 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2052 if (tms > pu->parkingtime) {
2053 ast_indicate(chan, AST_CONTROL_UNHOLD);
2054 /* Get chan, exten from derived kludge */
2055 if (pu->peername[0]) {
2056 char *peername = ast_strdupa(pu->peername);
2057 char *cp = strrchr(peername, '-');
2060 con = ast_context_find(parking_con_dial);
2062 con = ast_context_create(NULL, parking_con_dial, registrar);
2064 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
2067 char returnexten[AST_MAX_EXTENSION];
2068 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
2069 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free, registrar);
2071 if (comebacktoorigin) {
2072 set_c_e_p(chan, parking_con_dial, peername, 1);
2074 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2075 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2076 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
2077 set_c_e_p(chan, "parkedcallstimeout", peername, 1);
2080 /* They've been waiting too long, send them back to where they came. Theoretically they
2081 should have their original extensions and such, but we copy to be on the safe side */
2082 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2085 post_manager_event("ParkedCallTimeOut", pu);
2087 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);
2088 /* Start up the PBX, or hang them up */
2089 if (ast_pbx_start(chan)) {
2090 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
2093 /* And take them out of the parking lot */
2094 AST_LIST_REMOVE_CURRENT(&parkinglot, list);
2095 con = ast_context_find(parking_con);
2097 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2098 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2100 notify_metermaids(pu->parkingexten, parking_con);
2102 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2104 } else { /* still within parking time, process descriptors */
2105 for (x = 0; x < AST_MAX_FDS; x++) {
2106 struct ast_frame *f;
2108 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
2109 continue; /* nothing on this descriptor */
2111 if (FD_ISSET(chan->fds[x], &efds))
2112 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2114 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2117 /* See if they need servicing */
2119 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
2122 post_manager_event("ParkedCallGiveUp", pu);
2124 /* There's a problem, hang them up*/
2125 ast_verb(2, "%s got tired of being parked\n", chan->name);
2127 /* And take them out of the parking lot */
2128 AST_LIST_REMOVE_CURRENT(&parkinglot, list);
2129 con = ast_context_find(parking_con);
2131 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2132 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2134 notify_metermaids(pu->parkingexten, parking_con);
2136 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2140 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2142 if (pu->moh_trys < 3 && !chan->generatordata) {
2143 ast_debug(1, "MOH on parked call stopped by outside source. Restarting.\n");
2144 ast_indicate_data(chan, AST_CONTROL_HOLD,
2145 S_OR(parkmohclass, NULL),
2146 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
2149 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
2153 if (x >= AST_MAX_FDS) {
2154 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2155 if (chan->fds[x] > -1) {
2156 FD_SET(chan->fds[x], &nrfds);
2157 FD_SET(chan->fds[x], &nefds);
2158 if (chan->fds[x] > max)
2162 /* Keep track of our shortest wait */
2163 if (tms < ms || ms < 0)
2168 AST_LIST_TRAVERSE_SAFE_END
2169 AST_LIST_UNLOCK(&parkinglot);
2173 struct timeval tv = ast_samp2tv(ms, 1000);
2174 /* Wait for something to happen */
2175 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2177 pthread_testcancel();
2179 return NULL; /* Never reached */
2182 /*! \brief Park a call */
2183 static int park_call_exec(struct ast_channel *chan, void *data)
2185 /* Data is unused at the moment but could contain a parking
2186 lot context eventually */
2188 struct ast_module_user *u;
2190 u = ast_module_user_add(chan);
2192 /* Setup the exten/priority to be s/1 since we don't know
2193 where this call should return */
2194 strcpy(chan->exten, "s");
2196 /* Answer if call is not up */
2197 if (chan->_state != AST_STATE_UP)
2198 res = ast_answer(chan);
2199 /* Sleep to allow VoIP streams to settle down */
2201 res = ast_safe_sleep(chan, 1000);
2204 res = ast_park_call(chan, chan, 0, NULL);
2206 ast_module_user_remove(u);
2208 return !res ? AST_PBX_KEEPALIVE : res;
2211 /*! \brief Pickup parked call */
2212 static int park_exec(struct ast_channel *chan, void *data)
2215 struct ast_module_user *u;
2216 struct ast_channel *peer=NULL;
2217 struct parkeduser *pu;
2218 struct ast_context *con;
2221 struct ast_bridge_config config;
2224 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
2228 u = ast_module_user_add(chan);
2230 park = atoi((char *)data);
2232 AST_LIST_LOCK(&parkinglot);
2233 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2234 if (pu->parkingnum == park) {
2235 AST_LIST_REMOVE_CURRENT(&parkinglot, list);
2239 AST_LIST_TRAVERSE_SAFE_END
2240 AST_LIST_UNLOCK(&parkinglot);
2244 con = ast_context_find(parking_con);
2246 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2247 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2249 notify_metermaids(pu->parkingexten, parking_con);
2251 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2253 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2257 "CallerIDNum: %s\r\n"
2258 "CallerIDName: %s\r\n",
2259 pu->parkingexten, pu->chan->name, chan->name,
2260 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2261 S_OR(pu->chan->cid.cid_name, "<unknown>")
2266 /* JK02: it helps to answer the channel if not already up */
2267 if (chan->_state != AST_STATE_UP)
2271 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2273 if (!ast_strlen_zero(courtesytone)) {
2275 ast_indicate(peer, AST_CONTROL_UNHOLD);
2276 if (parkedplay == 0) {
2277 error = ast_stream_and_wait(chan, courtesytone, "");
2278 } else if (parkedplay == 1) {
2279 error = ast_stream_and_wait(peer, courtesytone, "");
2280 } else if (parkedplay == 2) {
2281 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2282 !ast_streamfile(peer, courtesytone, chan->language)) {
2283 /*! \todo XXX we would like to wait on both! */
2284 res = ast_waitstream(chan, "");
2286 res = ast_waitstream(peer, "");
2292 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2297 ast_indicate(peer, AST_CONTROL_UNHOLD);
2299 res = ast_channel_make_compatible(chan, peer);
2301 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2305 /* This runs sorta backwards, since we give the incoming channel control, as if it
2306 were the person called. */
2307 ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
2309 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2310 ast_cdr_setdestchan(chan->cdr, peer->name);
2311 memset(&config, 0, sizeof(struct ast_bridge_config));
2312 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2313 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2314 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2315 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2316 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2317 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2318 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2319 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2320 res = ast_bridge_call(chan, peer, &config);
2322 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2323 ast_cdr_setdestchan(chan->cdr, peer->name);
2325 /* Simulate the PBX hanging up */
2326 if (res != AST_PBX_NO_HANGUP_PEER)
2330 /*! \todo XXX Play a message XXX */
2331 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2332 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2333 ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2337 ast_module_user_remove(u);
2342 static int handle_showfeatures(int fd, int argc, char *argv[])
2345 struct ast_call_feature *feature;
2346 char format[] = "%-25s %-7s %-7s\n";
2348 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
2349 ast_cli(fd, format, "---------------", "-------", "-------");
2351 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2353 ast_rwlock_rdlock(&features_lock);
2354 for (i = 0; i < FEATURES_COUNT; i++)
2355 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2356 ast_rwlock_unlock(&features_lock);
2359 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
2360 ast_cli(fd, format, "---------------", "-------", "-------");
2361 if (AST_LIST_EMPTY(&feature_list))
2362 ast_cli(fd, "(none)\n");
2364 AST_LIST_LOCK(&feature_list);
2365 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2366 ast_cli(fd, format, feature->sname, "no def", feature->exten);
2367 AST_LIST_UNLOCK(&feature_list);
2369 ast_cli(fd, "\nCall parking\n");
2370 ast_cli(fd, "------------\n");
2371 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
2372 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
2373 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2376 return RESULT_SUCCESS;
2379 static char mandescr_bridge[] =
2380 "Description: Bridge together two channels already in the PBX\n"
2381 "Variables: ( Headers marked with * are required )\n"
2382 " *Channel1: Channel to Bridge to Channel2\n"
2383 " *Channel2: Channel to Bridge to Channel1\n"
2384 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2388 * \brief Actual bridge
2391 * Stop hold music, lock both channels, masq channels,
2392 * after bridge return channel to next priority.
2394 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2397 ast_mutex_lock(&chan->lock);
2398 ast_setstate(tmpchan, chan->_state);
2399 tmpchan->readformat = chan->readformat;
2400 tmpchan->writeformat = chan->writeformat;
2401 ast_channel_masquerade(tmpchan, chan);
2402 ast_mutex_lock(&tmpchan->lock);
2403 ast_do_masquerade(tmpchan);
2404 /* when returning from bridge, the channel will continue at the next priority */
2405 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2406 ast_mutex_unlock(&tmpchan->lock);
2407 ast_mutex_unlock(&chan->lock);
2411 * \brief Bridge channels together
2414 * Make sure valid channels were specified,
2415 * send errors if any of the channels could not be found/locked, answer channels if needed,
2416 * create the placeholder channels and grab the other channels
2417 * make the channels compatible, send error if we fail doing so
2418 * setup the bridge thread object and start the bridge.
2419 * \retval 0 on success or on incorrect use.
2420 * \retval 1 on failure to bridge channels.
2422 static int action_bridge(struct mansession *s, const struct message *m)
2424 const char *channela = astman_get_header(m, "Channel1");
2425 const char *channelb = astman_get_header(m, "Channel2");
2426 const char *playtone = astman_get_header(m, "Tone");
2427 struct ast_channel *chana = NULL, *chanb = NULL;
2428 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
2429 struct ast_bridge_thread_obj *tobj = NULL;
2431 /* make sure valid channels were specified */
2432 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
2433 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
2434 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
2436 ast_mutex_unlock(&chana->lock);
2438 ast_mutex_unlock(&chanb->lock);
2440 /* send errors if any of the channels could not be found/locked */
2443 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
2444 astman_send_error(s, m, buf);
2449 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
2450 astman_send_error(s, m, buf);
2454 astman_send_error(s, m, "Missing channel parameter in request");
2458 /* Answer the channels if needed */
2459 if (chana->_state != AST_STATE_UP)
2461 if (chanb->_state != AST_STATE_UP)
2464 /* create the placeholder channels and grab the other channels */
2465 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2466 NULL, NULL, 0, "Bridge/%s", chana->name))) {
2467 astman_send_error(s, m, "Unable to create temporary channel!");
2471 if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2472 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
2473 astman_send_error(s, m, "Unable to create temporary channels!");
2474 ast_channel_free(tmpchana);
2478 do_bridge_masquerade(chana, tmpchana);
2479 do_bridge_masquerade(chanb, tmpchanb);
2481 /* make the channels compatible, send error if we fail doing so */
2482 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
2483 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
2484 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
2485 ast_hangup(tmpchana);
2486 ast_hangup(tmpchanb);
2490 /* setup the bridge thread object and start the bridge */
2491 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
2492 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
2493 astman_send_error(s, m, "Unable to spawn a new bridge thread");
2494 ast_hangup(tmpchana);
2495 ast_hangup(tmpchanb);
2499 tobj->chan = tmpchana;
2500 tobj->peer = tmpchanb;
2501 tobj->return_to_pbx = 1;
2503 if (ast_true(playtone)) {
2504 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
2505 if (ast_waitstream(tmpchanb, "") < 0)
2506 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
2510 ast_bridge_call_thread_launch(tobj);
2512 astman_send_ack(s, m, "Launched bridge thread with success");
2517 static char showfeatures_help[] =
2518 "Usage: feature list\n"
2519 " Lists currently configured features.\n";
2522 * \brief CLI command to list parked calls
2526 * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
2527 * \retval CLI_SUCCESS on success.
2528 * \retval CLI_SHOWUSAGE on incorrect number of arguements.
2529 * \retval NULL when tab completion is used.
2531 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2533 struct parkeduser *cur;
2538 e->command = "parkedcalls show";
2540 "Usage: parkedcalls show\n"
2541 " List currently parked calls\n";
2547 if (a->argc > e->args)
2548 return CLI_SHOWUSAGE;
2550 ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2551 , "Context", "Extension", "Pri", "Timeout");
2553 AST_LIST_LOCK(&parkinglot);
2554 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
2555 ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2556 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2557 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2561 AST_LIST_UNLOCK(&parkinglot);
2562 ast_cli(a->fd, "%d parked call%s.\n", numparked, ESS(numparked));
2568 static char *handle_parkedcalls_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2570 char *res = handle_parkedcalls(e, cmd, a);
2571 if (cmd == CLI_INIT)
2572 e->command = "show parkedcalls";
2576 static struct ast_cli_entry cli_show_parkedcalls_deprecated = NEW_CLI(handle_parkedcalls_deprecated, "List currently parked calls.");
2578 static struct ast_cli_entry cli_features[] = {
2579 { { "feature", "show", NULL },
2580 handle_showfeatures, "Lists configured features",
2581 showfeatures_help },
2583 NEW_CLI(handle_parkedcalls, "List currently parked calls", .deprecate_cmd = &cli_show_parkedcalls_deprecated),
2587 * \brief Dump parking lot status
2590 * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
2591 * \return Always RESULT_SUCCESS
2593 static int manager_parking_status(struct mansession *s, const struct message *m)
2595 struct parkeduser *cur;
2596 const char *id = astman_get_header(m, "ActionID");
2597 char idText[256] = "";
2599 if (!ast_strlen_zero(id))
2600 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2602 astman_send_ack(s, m, "Parked calls will follow");
2604 AST_LIST_LOCK(&parkinglot);
2606 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
2607 astman_append(s, "Event: ParkedCall\r\n"
2612 "CallerIDNum: %s\r\n"
2613 "CallerIDName: %s\r\n"
2616 cur->parkingnum, cur->chan->name, cur->peername,
2617 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2618 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
2619 S_OR(cur->chan->cid.cid_name, ""),
2624 "Event: ParkedCallsComplete\r\n"
2628 AST_LIST_UNLOCK(&parkinglot);
2630 return RESULT_SUCCESS;
2633 static char mandescr_park[] =
2634 "Description: Park a channel.\n"
2635 "Variables: (Names marked with * are required)\n"
2636 " *Channel: Channel name to park\n"
2637 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
2638 " Timeout: Number of milliseconds to wait before callback.\n";
2641 * \brief Create manager event for parked calls
2644 * Get channels involved in park, create event.
2647 static int manager_park(struct mansession *s, const struct message *m)
2649 const char *channel = astman_get_header(m, "Channel");
2650 const char *channel2 = astman_get_header(m, "Channel2");
2651 const char *timeout = astman_get_header(m, "Timeout");
2656 struct ast_channel *ch1, *ch2;
2658 if (ast_strlen_zero(channel)) {
2659 astman_send_error(s, m, "Channel not specified");
2663 if (ast_strlen_zero(channel2)) {
2664 astman_send_error(s, m, "Channel2 not specified");
2668 ch1 = ast_get_channel_by_name_locked(channel);
2670 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2671 astman_send_error(s, m, buf);
2675 ch2 = ast_get_channel_by_name_locked(channel2);
2677 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2678 astman_send_error(s, m, buf);
2679 ast_channel_unlock(ch1);
2683 if (!ast_strlen_zero(timeout)) {
2684 sscanf(timeout, "%d", &to);
2687 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2689 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2690 astman_send_ack(s, m, "Park successful");
2692 astman_send_error(s, m, "Park failure");
2695 ast_channel_unlock(ch1);
2696 ast_channel_unlock(ch2);
2702 * \brief Pickup a call
2703 * \param chan channel that initiated pickup
2704 * Walk list of channels, checking it is not itself, channel is pbx one,
2705 * check that the callgroup for both channels are the same and the channel is ringing.
2706 * Answer calling channel, flag channel as answered on queue, masq channels together.
2708 int ast_pickup_call(struct ast_channel *chan)
2710 struct ast_channel *cur = NULL;
2713 while ((cur = ast_channel_walk_locked(cur)) != NULL) {
2716 (chan->pickupgroup & cur->callgroup) &&
2717 ((cur->_state == AST_STATE_RINGING) ||
2718 (cur->_state == AST_STATE_RING))) {
2721 ast_channel_unlock(cur);
2724 ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2725 res = ast_answer(chan);
2727 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2728 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2730 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2731 res = ast_channel_masquerade(cur, chan);
2733 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
2734 ast_channel_unlock(cur);
2736 ast_debug(1, "No call pickup possible...\n");
2742 * \brief Add parking hints for all defined parking lots
2744 * \param start starting parkinglot number
2745 * \param stop ending parkinglot number
2747 static void park_add_hints(char *context, int start, int stop)
2750 char device[AST_MAX_EXTENSION];
2753 for (numext = start; numext <= stop; numext++) {
2754 snprintf(exten, sizeof(exten), "%d", numext);
2755 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2756 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2761 static int load_config(void)
2763 int start = 0, end = 0;
2766 struct ast_context *con = NULL;
2767 struct ast_config *cfg = NULL;
2768 struct ast_variable *var = NULL;
2769 struct feature_group *fg = NULL;
2770 char old_parking_ext[AST_MAX_EXTENSION];
2771 char old_parking_con[AST_MAX_EXTENSION] = "";
2773 static const char *categories[] = {
2774 /* Categories in features.conf that are not
2775 * to be parsed as group categories
2782 if (!ast_strlen_zero(parking_con)) {
2783 strcpy(old_parking_ext, parking_ext);
2784 strcpy(old_parking_con, parking_con);
2787 /* Reset to defaults */
2788 strcpy(parking_con, "parkedcalls");
2789 strcpy(parking_con_dial, "park-dial");
2790 strcpy(parking_ext, "700");
2791 strcpy(pickup_ext, "*8");
2792 strcpy(parkmohclass, "default");
2793 courtesytone[0] = '\0';
2794 strcpy(xfersound, "beep");
2795 strcpy(xferfailsound, "pbx-invalid");
2796 parking_start = 701;
2800 comebacktoorigin = 1;
2802 parkedcalltransfers = 0;
2803 parkedcallreparking = 0;
2805 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2806 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2807 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2808 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2809 atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2810 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2812 cfg = ast_config_load("features.conf");
2814 ast_log(LOG_WARNING,"Could not load features.conf\n");
2815 return AST_MODULE_LOAD_DECLINE;
2817 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2818 if (!strcasecmp(var->name, "parkext")) {
2819 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2820 } else if (!strcasecmp(var->name, "context")) {
2821 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2822 } else if (!strcasecmp(var->name, "parkingtime")) {
2823 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2824 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2825 parkingtime = DEFAULT_PARK_TIME;
2827 parkingtime = parkingtime * 1000;
2828 } else if (!strcasecmp(var->name, "parkpos")) {
2829 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2830 ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", var->lineno);
2832 parking_start = start;
2835 } else if (!strcasecmp(var->name, "findslot")) {
2836 parkfindnext = (!strcasecmp(var->value, "next"));
2837 } else if (!strcasecmp(var->name, "parkinghints")) {
2838 parkaddhints = ast_true(var->value);
2839 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2840 if (!strcasecmp(var->value, "both"))
2841 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2842 else if (!strcasecmp(var->value, "caller"))
2843 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2844 else if (!strcasecmp(var->value, "callee"))
2845 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2846 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2847 if (!strcasecmp(var->value, "both"))
2848 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2849 else if (!strcasecmp(var->value, "caller"))
2850 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2851 else if (!strcasecmp(var->value, "callee"))
2852 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2853 } else if (!strcasecmp(var->name, "adsipark")) {
2854 adsipark = ast_true(var->value);
2855 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2856 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2857 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2858 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2860 transferdigittimeout = transferdigittimeout * 1000;
2861 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2862 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2863 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2864 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2866 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2867 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2868 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2869 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2871 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2872 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2873 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2874 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2875 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2877 atxferloopdelay *= 1000;
2878 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2879 atxferdropcall = ast_true(var->value);
2880 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2881 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2882 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2883 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2885 } else if (!strcasecmp(var->name, "courtesytone")) {
2886 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2887 } else if (!strcasecmp(var->name, "parkedplay")) {
2888 if (!strcasecmp(var->value, "both"))
2890 else if (!strcasecmp(var->value, "parked"))
2894 } else if (!strcasecmp(var->name, "xfersound")) {
2895 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2896 } else if (!strcasecmp(var->name, "xferfailsound")) {
2897 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2898 } else if (!strcasecmp(var->name, "pickupexten")) {
2899 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2900 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2901 comebacktoorigin = ast_true(var->value);
2902 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2903 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2908 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2909 if (remap_feature(var->name, var->value))
2910 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2913 /* Map a key combination to an application*/
2914 ast_unregister_features();
2915 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2916 char *tmp_val = ast_strdupa(var->value);
2917 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2918 struct ast_call_feature *feature;
2920 /* strsep() sets the argument to NULL if match not found, and it
2921 * is safe to use it with a NULL argument, so we don't check
2924 exten = strsep(&tmp_val,",");
2925 activatedby = strsep(&tmp_val,",");
2926 app = strsep(&tmp_val,",");
2927 app_args = strsep(&tmp_val,",");
2928 moh_class = strsep(&tmp_val,",");
2930 activateon = strsep(&activatedby, "/");
2932 /*! \todo XXX var_name or app_args ? */
2933 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2934 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2935 app, exten, activateon, var->name);
2939 AST_LIST_LOCK(&feature_list);
2940 if ((feature = find_dynamic_feature(var->name))) {
2941 AST_LIST_UNLOCK(&feature_list);
2942 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2945 AST_LIST_UNLOCK(&feature_list);
2947 if (!(feature = ast_calloc(1, sizeof(*feature))))
2950 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2951 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2952 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2955 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2958 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2960 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2961 feature->operation = feature_exec_app;
2962 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2964 /* Allow caller and calle to be specified for backwards compatability */
2965 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2966 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2967 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2968 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2970 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2971 " must be 'self', or 'peer'\n", var->name);
2975 if (ast_strlen_zero(activatedby))
2976 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2977 else if (!strcasecmp(activatedby, "caller"))
2978 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2979 else if (!strcasecmp(activatedby, "callee"))
2980 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2981 else if (!strcasecmp(activatedby, "both"))
2982 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2984 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2985 " must be 'caller', or 'callee', or 'both'\n", var->name);
2989 ast_register_feature(feature);
2991 ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2994 ast_unregister_groups();
2995 AST_RWLIST_WRLOCK(&feature_groups);
2998 while ((ctg = ast_category_browse(cfg, ctg))) {
2999 for (i = 0; i < ARRAY_LEN(categories); i++) {
3000 if (!strcasecmp(categories[i], ctg))
3004 if (i < ARRAY_LEN(categories))
3007 if (!(fg = register_group(ctg)))
3010 for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
3011 struct ast_call_feature *feature;
3013 AST_LIST_LOCK(&feature_list);
3014 if(!(feature = find_dynamic_feature(var->name)) &&
3015 !(feature = ast_find_call_feature(var->name))) {
3016 AST_LIST_UNLOCK(&feature_list);
3017 ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
3020 AST_LIST_UNLOCK(&feature_list);
3022 register_group_feature(fg, var->value, feature);
3026 AST_RWLIST_UNLOCK(&feature_groups);
3028 ast_config_destroy(cfg);
3030 /* Remove the old parking extension */
3031 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
3032 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
3033 notify_metermaids(old_parking_ext, old_parking_con);
3034 ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
3037 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
3038 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
3041 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
3043 park_add_hints(parking_con, parking_start, parking_stop);
3045 notify_metermaids(ast_parking_ext(), parking_con);
3050 static char *app_bridge = "Bridge";
3051 static char *bridge_synopsis = "Bridge two channels";
3052 static char *bridge_descrip =
3053 "Usage: Bridge(channel[|options])\n"
3054 " Allows the ability to bridge two channels via the dialplan.\n"
3055 "The current channel is bridged to the specified 'channel'.\n"
3056 "The following options are supported:\n"
3057 " p - Play a courtesy tone to 'channel'.\n"
3058 "BRIDGERESULT dial plan variable will contain SUCCESS, FAILURE, LOOP, NONEXISTENT or INCOMPATIBLE.\n";
3061 BRIDGE_OPT_PLAYTONE = (1 << 0),
3064 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
3065 AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
3069 * \brief Bridge channels
3071 * \param data channel to bridge with
3072 * Split data, check we aren't bridging with ourself, check valid channel,
3073 * answer call if not already, check compatible channels, setup bridge config
3074 * now bridge call, if transfered party hangs up return to PBX extension.
3076 static int bridge_exec(struct ast_channel *chan, void *data)
3078 struct ast_module_user *u;
3079 struct ast_channel *current_dest_chan, *final_dest_chan;
3080 char *tmp_data = NULL;
3081 struct ast_flags opts = { 0, };
3082 struct ast_bridge_config bconfig = { { 0, }, };
3084 AST_DECLARE_APP_ARGS(args,
3085 AST_APP_ARG(dest_chan);
3086 AST_APP_ARG(options);
3089 if (ast_strlen_zero(data)) {
3090 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
3094 u = ast_module_user_add(chan);
3096 tmp_data = ast_strdupa(data);
3097 AST_STANDARD_APP_ARGS(args, tmp_data);
3098 if (!ast_strlen_zero(args.options))
3099 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
3101 /* avoid bridge with ourselves */
3102 if (!strncmp(chan->name, args.dest_chan,
3103 strlen(chan->name) < strlen(args.dest_chan) ?
3104 strlen(chan->name) : strlen(args.dest_chan))) {
3105 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
3106 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3107 "Response: Failed\r\n"
3108 "Reason: Unable to bridge channel to itself\r\n"
3111 chan->name, args.dest_chan);
3112 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
3113 ast_module_user_remove(u);
3117 /* make sure we have a valid end point */
3118 if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
3119 strlen(args.dest_chan)))) {
3120 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
3121 "cannot get its lock\n", args.dest_chan);
3122 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3123 "Response: Failed\r\n"
3124 "Reason: Cannot grab end point\r\n"
3126 "Channel2: %s\r\n", chan->name, args.dest_chan);
3127 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
3128 ast_module_user_remove(u);
3131 ast_mutex_unlock(¤t_dest_chan->lock);
3133 /* answer the channel if needed */
3134 if (current_dest_chan->_state != AST_STATE_UP)
3135 ast_answer(current_dest_chan);
3137 /* try to allocate a place holder where current_dest_chan will be placed */
3138 if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
3139 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
3140 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
3141 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3142 "Response: Failed\r\n"
3143 "Reason: cannot create placeholder\r\n"
3145 "Channel2: %s\r\n", chan->name, args.dest_chan);
3147 do_bridge_masquerade(current_dest_chan, final_dest_chan);
3149 /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
3150 /* try to make compatible, send error if we fail */
3151 if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
3152 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
3153 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3154 "Response: Failed\r\n"
3155 "Reason: Could not make channels compatible for bridge\r\n"
3157 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
3158 ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
3159 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
3160 ast_module_user_remove(u);
3164 /* Report that the bridge will be successfull */
3165 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3166 "Response: Success\r\n"
3168 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
3170 /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
3171 if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
3172 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
3173 if (ast_waitstream(final_dest_chan, "") < 0)
3174 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
3179 ast_bridge_call(chan, final_dest_chan, &bconfig);
3181 /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
3182 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
3183 if (!ast_check_hangup(final_dest_chan)) {
3184 ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
3185 final_dest_chan->context, final_dest_chan->exten,
3186 final_dest_chan->priority, final_dest_chan->name);
3188 if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
3189 ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
3190 ast_hangup(final_dest_chan);
3192 ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
3194 ast_debug(1, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
3195 ast_hangup(final_dest_chan);
3198 ast_module_user_remove(u);
3203 static int reload(void)
3205 return load_config();
3208 static int load_module(void)
3212 ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);
3214 memset(parking_ext, 0, sizeof(parking_ext));
3215 memset(parking_con, 0, sizeof(parking_con));
3217 if ((res = load_config()))
3219 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
3220 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
3221 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
3223 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
3225 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
3226 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
3227 "Park a channel", mandescr_park);
3228 ast_manager_register2("Bridge", EVENT_FLAG_COMMAND, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
3231 res |= ast_devstate_prov_add("Park", metermaidstate);
3237 static int unload_module(void)
3239 ast_manager_unregister("ParkedCalls");
3240 ast_manager_unregister("Bridge");
3241 ast_manager_unregister("Park");
3242 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
3243 ast_unregister_application(parkcall);
3244 ast_unregister_application(app_bridge);
3245 ast_devstate_prov_del("Park");
3246 return ast_unregister_application(parkedcall);
3249 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
3250 .load = load_module,
3251 .unload = unload_module,