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 static char *parkedcall = "ParkedCall";
83 static int parkaddhints = 0; /*!< Add parking hints automatically */
84 static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
85 static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
86 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
87 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
88 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
89 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
90 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
91 static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
92 static int parking_start; /*!< First available extension for parking */
93 static int parking_stop; /*!< Last available extension for parking */
95 static char courtesytone[256]; /*!< Courtesy tone */
96 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
97 static char xfersound[256]; /*!< Call transfer sound */
98 static char xferfailsound[256]; /*!< Call transfer failure sound */
100 static int parking_offset;
101 static int parkfindnext;
105 static int transferdigittimeout;
106 static int featuredigittimeout;
107 static int comebacktoorigin = 1;
109 static int atxfernoanswertimeout;
110 static unsigned int atxferdropcall;
111 static unsigned int atxferloopdelay;
112 static unsigned int atxfercallbackretries;
114 static char *registrar = "res_features"; /*!< Registrar for operations */
116 /* module and CLI command definitions */
117 static char *synopsis = "Answer a parked call";
119 static char *descrip = "ParkedCall(exten):"
120 "Used to connect to a parked call. This application is always\n"
121 "registered internally and does not need to be explicitly added\n"
122 "into the dialplan, although you should include the 'parkedcalls'\n"
125 static char *parkcall = "Park";
127 static char *synopsis2 = "Park yourself";
129 static char *descrip2 = "Park():"
130 "Used to park yourself (typically in combination with a supervised\n"
131 "transfer to know the parking space). This application is always\n"
132 "registered internally and does not need to be explicitly added\n"
133 "into the dialplan, although you should include the 'parkedcalls'\n"
134 "context (or the context specified in features.conf).\n\n"
135 "If you set the PARKINGEXTEN variable to an extension in your\n"
136 "parking context, park() will park the call on that extension, unless\n"
137 "it already exists. In that case, execution will continue at next\n"
140 static struct ast_app *monitor_app = NULL;
141 static int monitor_ok = 1;
144 struct ast_channel *chan; /*!< Parking channel */
145 struct timeval start; /*!< Time the parking started */
146 int parkingnum; /*!< Parking lot */
147 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
148 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
149 char exten[AST_MAX_EXTENSION];
151 int parkingtime; /*!< Maximum length in parking lot before return */
154 unsigned char moh_trys;
155 struct parkeduser *next;
158 static struct parkeduser *parkinglot;
160 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
162 static pthread_t parking_thread;
164 char *ast_parking_ext(void)
169 char *ast_pickup_ext(void)
174 struct ast_bridge_thread_obj
176 struct ast_bridge_config bconfig;
177 struct ast_channel *chan;
178 struct ast_channel *peer;
179 unsigned int return_to_pbx:1;
184 /*! \brief store context, priority and extension */
185 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
187 ast_copy_string(chan->context, context, sizeof(chan->context));
188 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
189 chan->priority = pri;
192 static void check_goto_on_transfer(struct ast_channel *chan)
194 struct ast_channel *xferchan;
195 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
196 char *x, *goto_on_transfer;
199 if (ast_strlen_zero(val))
202 goto_on_transfer = ast_strdupa(val);
204 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
207 for (x = goto_on_transfer; x && *x; x++) {
211 /* Make formats okay */
212 xferchan->readformat = chan->readformat;
213 xferchan->writeformat = chan->writeformat;
214 ast_channel_masquerade(xferchan, chan);
215 ast_parseable_goto(xferchan, goto_on_transfer);
216 xferchan->_state = AST_STATE_UP;
217 ast_clear_flag(xferchan, AST_FLAGS_ALL);
218 xferchan->_softhangup = 0;
219 if ((f = ast_read(xferchan))) {
222 ast_pbx_start(xferchan);
224 ast_hangup(xferchan);
228 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);
231 static void *ast_bridge_call_thread(void *data)
233 struct ast_bridge_thread_obj *tobj = data;
236 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
237 tobj->chan->data = tobj->peer->name;
238 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
239 tobj->peer->data = tobj->chan->name;
241 if (tobj->chan->cdr) {
242 ast_cdr_reset(tobj->chan->cdr, NULL);
243 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
245 if (tobj->peer->cdr) {
246 ast_cdr_reset(tobj->peer->cdr, NULL);
247 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
250 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
252 if (tobj->return_to_pbx) {
253 if (!ast_check_hangup(tobj->peer)) {
254 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
255 res = ast_pbx_start(tobj->peer);
256 if (res != AST_PBX_SUCCESS)
257 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
259 ast_hangup(tobj->peer);
260 if (!ast_check_hangup(tobj->chan)) {
261 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
262 res = ast_pbx_start(tobj->chan);
263 if (res != AST_PBX_SUCCESS)
264 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
266 ast_hangup(tobj->chan);
268 ast_hangup(tobj->chan);
269 ast_hangup(tobj->peer);
277 static void ast_bridge_call_thread_launch(void *data)
281 struct sched_param sched;
283 pthread_attr_init(&attr);
284 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
285 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
286 pthread_attr_destroy(&attr);
287 memset(&sched, 0, sizeof(sched));
288 pthread_setschedparam(thread, SCHED_RR, &sched);
291 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
294 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
296 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
298 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
300 res = ast_adsi_load_session(chan, NULL, 0, 1);
303 return ast_adsi_print(chan, message, justify, 1);
306 /*! \brief Notify metermaids that we've changed an extension */
307 static void notify_metermaids(char *exten, char *context)
309 if (option_debug > 3)
310 ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
312 /* Send notification to devicestate subsystem */
313 ast_device_state_changed("park:%s@%s", exten, context);
317 /*! \brief metermaids callback from devicestate.c */
318 static enum ast_device_state metermaidstate(const char *data)
320 enum ast_device_state res = AST_DEVICE_INVALID;
321 char *context = ast_strdupa(data);
324 exten = strsep(&context, "@");
328 if (option_debug > 3)
329 ast_log(LOG_DEBUG, "Checking state of exten %s in context %s\n", exten, context);
331 res = ast_exists_extension(NULL, context, exten, 1, NULL);
333 if (res == AST_DEVICE_UNKNOWN)
334 return AST_DEVICE_NOT_INUSE;
336 return AST_DEVICE_INUSE;
339 /*! \brief Park a call
340 \note We put the user in the parking list, then wake up the parking thread to be sure it looks
341 after these channels too */
342 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
344 struct parkeduser *pu, *cur;
345 int i, x = -1, parking_range;
346 struct ast_context *con;
347 const char *parkingexten;
349 /* Allocate memory for parking data */
350 if (!(pu = ast_calloc(1, sizeof(*pu))))
353 /* Lock parking lot */
354 ast_mutex_lock(&parking_lock);
355 /* Check for channel variable PARKINGEXTEN */
356 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
357 if (!ast_strlen_zero(parkingexten)) {
358 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
359 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
360 return 0; /* Continue execution if possible */
362 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
364 /* Select parking space within range */
365 parking_range = parking_stop - parking_start+1;
366 for (i = 0; i < parking_range; i++) {
367 x = (i + parking_offset) % parking_range + parking_start;
370 if (cur->parkingnum == x)
378 if (!(i < parking_range)) {
379 ast_log(LOG_WARNING, "No more parking spaces\n");
381 ast_mutex_unlock(&parking_lock);
384 /* Set pointer for next parking */
386 parking_offset = x - parking_start + 1;
389 chan->appl = "Parked Call";
394 /* Put the parked channel on hold if we have two different channels */
396 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
397 S_OR(parkmohclass, NULL),
398 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
401 pu->start = ast_tvnow();
403 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
408 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
410 /* Remember what had been dialed, so that if the parking
411 expires, we try to come back to the same place */
412 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
413 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
414 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
415 pu->next = parkinglot;
418 /* If parking a channel directly, don't quiet yet get parking running on it */
421 ast_mutex_unlock(&parking_lock);
422 /* Wake up the (presumably select()ing) thread */
423 pthread_kill(parking_thread, SIGURG);
424 if (option_verbose > 1)
425 ast_verbose(VERBOSE_PREFIX_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));
427 if (pu->parkingnum != -1)
428 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
429 manager_event(EVENT_FLAG_CALL, "ParkedCall",
434 "CallerIDNum: %s\r\n"
435 "CallerIDName: %s\r\n",
436 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
437 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
438 S_OR(pu->chan->cid.cid_num, "<unknown>"),
439 S_OR(pu->chan->cid.cid_name, "<unknown>")
442 if (peer && adsipark && ast_adsi_available(peer)) {
443 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
444 ast_adsi_unload_session(peer);
447 con = ast_context_find(parking_con);
449 con = ast_context_create(NULL, parking_con, registrar);
450 if (!con) /* Still no context? Bad */
451 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
452 else { /* Add extension to context */
453 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar))
454 notify_metermaids(pu->parkingexten, parking_con);
456 /* Tell the peer channel the number of the parking space */
457 if (peer && pu->parkingnum != -1) /* Only say number if it's a number */
458 ast_say_digits(peer, pu->parkingnum, "", peer->language);
459 if (pu->notquiteyet) {
460 /* Wake up parking thread if we're really done */
461 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
462 S_OR(parkmohclass, NULL),
463 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
465 pthread_kill(parking_thread, SIGURG);
470 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
472 struct ast_channel *chan;
475 /* Make a new, fake channel that we'll use to masquerade in the real one */
476 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
477 ast_log(LOG_WARNING, "Unable to create parked channel\n");
481 /* Make formats okay */
482 chan->readformat = rchan->readformat;
483 chan->writeformat = rchan->writeformat;
484 ast_channel_masquerade(chan, rchan);
486 /* Setup the extensions and such */
487 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
489 /* Make the masq execute */
494 ast_park_call(chan, peer, timeout, extout);
499 #define FEATURE_RETURN_HANGUP -1
500 #define FEATURE_RETURN_SUCCESSBREAK 0
501 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
502 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
503 #define FEATURE_RETURN_PASSDIGITS 21
504 #define FEATURE_RETURN_STOREDIGITS 22
505 #define FEATURE_RETURN_SUCCESS 23
507 #define FEATURE_SENSE_CHAN (1 << 0)
508 #define FEATURE_SENSE_PEER (1 << 1)
511 * set caller and callee according to the direction
513 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
514 struct ast_channel *peer, struct ast_channel *chan, int sense)
516 if (sense == FEATURE_SENSE_PEER) {
525 /*! \brief support routing for one touch call parking */
526 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
528 struct ast_channel *parker;
529 struct ast_channel *parkee;
531 struct ast_module_user *u;
533 u = ast_module_user_add(chan);
535 set_peers(&parker, &parkee, peer, chan, sense);
536 /* Setup the exten/priority to be s/1 since we don't know
537 where this call should return */
538 strcpy(chan->exten, "s");
540 if (chan->_state != AST_STATE_UP)
541 res = ast_answer(chan);
543 res = ast_safe_sleep(chan, 1000);
545 res = ast_park_call(parkee, parker, 0, NULL);
547 ast_module_user_remove(u);
550 if (sense == FEATURE_SENSE_CHAN)
551 res = AST_PBX_NO_HANGUP_PEER;
553 res = AST_PBX_KEEPALIVE;
559 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
561 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
564 struct ast_channel *caller_chan, *callee_chan;
567 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
571 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
573 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
577 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
579 if (!ast_strlen_zero(courtesytone)) {
580 if (ast_autoservice_start(callee_chan))
582 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
583 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
584 ast_autoservice_stop(callee_chan);
587 if (ast_autoservice_stop(callee_chan))
591 if (callee_chan->monitor) {
592 if (option_verbose > 3)
593 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
594 ast_monitor_stop(callee_chan, 1);
595 return FEATURE_RETURN_SUCCESS;
598 if (caller_chan && callee_chan) {
599 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
600 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
603 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
606 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
609 len = strlen(touch_monitor) + 50;
611 touch_filename = alloca(len);
612 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
613 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
615 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
616 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
617 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
619 touch_filename = alloca(len);
620 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
621 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
624 for(x = 0; x < strlen(args); x++) {
629 if (option_verbose > 3)
630 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
632 pbx_exec(callee_chan, monitor_app, args);
633 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
634 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
636 return FEATURE_RETURN_SUCCESS;
639 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
643 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
645 if (option_verbose > 3)
646 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
647 return FEATURE_RETURN_HANGUP;
650 static int finishup(struct ast_channel *chan)
652 ast_indicate(chan, AST_CONTROL_UNHOLD);
654 return ast_autoservice_stop(chan);
657 /*! \brief Find the context for the transfer */
658 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
660 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
661 if (ast_strlen_zero(s))
662 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
663 if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
664 s = transferer->macrocontext;
665 if (ast_strlen_zero(s))
666 s = transferer->context;
670 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
672 struct ast_channel *transferer;
673 struct ast_channel *transferee;
674 const char *transferer_real_context;
678 set_peers(&transferer, &transferee, peer, chan, sense);
679 transferer_real_context = real_ctx(transferer, transferee);
680 /* Start autoservice on chan while we talk to the originator */
681 ast_autoservice_start(transferee);
682 ast_indicate(transferee, AST_CONTROL_HOLD);
684 memset(xferto, 0, sizeof(xferto));
687 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
689 finishup(transferee);
690 return -1; /* error ? */
692 if (res > 0) /* If they've typed a digit already, handle it */
693 xferto[0] = (char) res;
695 ast_stopstream(transferer);
696 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
697 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
698 finishup(transferee);
701 if (!strcmp(xferto, ast_parking_ext())) {
702 res = finishup(transferee);
705 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
706 /* We return non-zero, but tell the PBX not to hang the channel when
707 the thread dies -- We have to be careful now though. We are responsible for
708 hanging up the channel, else it will never be hung up! */
710 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
712 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
714 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
715 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
716 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
717 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
718 res=finishup(transferee);
719 if (!transferer->cdr) {
720 transferer->cdr=ast_cdr_alloc();
722 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
723 ast_cdr_start(transferer->cdr);
726 if (transferer->cdr) {
727 ast_cdr_setdestchan(transferer->cdr, transferee->name);
728 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
730 if (!transferee->pbx) {
731 /* Doh! Use our handy async_goto functions */
732 if (option_verbose > 2)
733 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
734 ,transferee->name, xferto, transferer_real_context);
735 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
736 ast_log(LOG_WARNING, "Async goto failed :-(\n");
739 /* Set the channel's new extension, since it exists, using transferer context */
740 set_c_e_p(transferee, transferer_real_context, xferto, 0);
742 check_goto_on_transfer(transferer);
745 if (option_verbose > 2)
746 ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
748 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
749 finishup(transferee);
752 ast_stopstream(transferer);
753 res = finishup(transferee);
755 if (option_verbose > 1)
756 ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
759 return FEATURE_RETURN_SUCCESS;
762 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
764 if (ast_channel_make_compatible(c, newchan) < 0) {
765 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
766 c->name, newchan->name);
773 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
775 struct ast_channel *transferer;
776 struct ast_channel *transferee;
777 const char *transferer_real_context;
778 char xferto[256] = "";
779 char callbackto[256] = "";
782 struct ast_channel *newchan;
783 struct ast_channel *xferchan;
784 struct ast_bridge_thread_obj *tobj;
785 struct ast_bridge_config bconfig;
790 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
791 set_peers(&transferer, &transferee, peer, chan, sense);
792 transferer_real_context = real_ctx(transferer, transferee);
793 /* Start autoservice on chan while we talk to the originator */
794 ast_autoservice_start(transferee);
795 ast_indicate(transferee, AST_CONTROL_HOLD);
798 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
800 finishup(transferee);
803 if (res > 0) /* If they've typed a digit already, handle it */
804 xferto[0] = (char) res;
806 /* this is specific of atxfer */
807 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
808 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
809 finishup(transferee);
813 ast_log(LOG_WARNING, "Did not read data.\n");
814 finishup(transferee);
815 if (ast_stream_and_wait(transferer, "beeperr", ""))
817 return FEATURE_RETURN_SUCCESS;
820 /* valid extension, res == 1 */
821 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
822 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
823 finishup(transferee);
824 if (ast_stream_and_wait(transferer, "beeperr", ""))
826 return FEATURE_RETURN_SUCCESS;
830 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
831 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
832 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
834 if (!ast_check_hangup(transferer)) {
835 /* Transferer is up - old behaviour */
836 ast_indicate(transferer, -1);
838 finishup(transferee);
839 /* any reason besides user requested cancel and busy triggers the failed sound */
840 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
841 ast_stream_and_wait(transferer, xferfailsound, ""))
843 if (ast_stream_and_wait(transferer, xfersound, ""))
844 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
845 return FEATURE_RETURN_SUCCESS;
848 if (check_compat(transferer, newchan))
850 memset(&bconfig,0,sizeof(struct ast_bridge_config));
851 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
852 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
853 res = ast_bridge_call(transferer, newchan, &bconfig);
854 if (newchan->_softhangup || !transferer->_softhangup) {
856 if (ast_stream_and_wait(transferer, xfersound, ""))
857 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
858 finishup(transferee);
859 transferer->_softhangup = 0;
860 return FEATURE_RETURN_SUCCESS;
862 if (check_compat(transferee, newchan))
864 ast_indicate(transferee, AST_CONTROL_UNHOLD);
866 if ((ast_autoservice_stop(transferee) < 0)
867 || (ast_waitfordigit(transferee, 100) < 0)
868 || (ast_waitfordigit(newchan, 100) < 0)
869 || ast_check_hangup(transferee)
870 || ast_check_hangup(newchan)) {
874 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
879 /* Make formats okay */
880 xferchan->readformat = transferee->readformat;
881 xferchan->writeformat = transferee->writeformat;
882 ast_channel_masquerade(xferchan, transferee);
883 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
884 xferchan->_state = AST_STATE_UP;
885 ast_clear_flag(xferchan, AST_FLAGS_ALL);
886 xferchan->_softhangup = 0;
887 if ((f = ast_read(xferchan)))
889 newchan->_state = AST_STATE_UP;
890 ast_clear_flag(newchan, AST_FLAGS_ALL);
891 newchan->_softhangup = 0;
892 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
893 ast_hangup(xferchan);
897 tobj->chan = xferchan;
898 tobj->peer = newchan;
899 tobj->bconfig = *config;
901 if (ast_stream_and_wait(newchan, xfersound, ""))
902 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
903 ast_bridge_call_thread_launch(tobj);
904 return -1; /* XXX meaning the channel is bridged ? */
905 } else if (!ast_check_hangup(transferee)) {
906 /* act as blind transfer */
907 if (ast_autoservice_stop(transferee) < 0) {
913 unsigned int tries = 0;
915 /* newchan wasn't created - we should callback to transferer */
916 if (!ast_exists_extension(transferer, transferer_real_context, transferer->cid.cid_num, 1, transferee->cid.cid_num)) {
917 ast_log(LOG_WARNING, "Extension %s does not exist in context %s - callback failed\n",transferer->cid.cid_num,transferer_real_context);
918 if (ast_stream_and_wait(transferee, "beeperr", ""))
920 return FEATURE_RETURN_SUCCESS;
922 snprintf(callbackto, sizeof(callbackto), "%s@%s/n", transferer->cid.cid_num, transferer_real_context); /* append context */
924 newchan = ast_feature_request_and_dial(transferee, NULL, "Local", ast_best_codec(transferee->nativeformats),
925 callbackto, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
926 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
927 /* Trying to transfer again */
928 ast_autoservice_start(transferee);
929 ast_indicate(transferee, AST_CONTROL_HOLD);
931 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
932 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
933 if (ast_autoservice_stop(transferee) < 0) {
938 /* Transfer failed, sleeping */
940 ast_log(LOG_DEBUG, "Sleeping for %d ms before callback.\n", atxferloopdelay);
941 ast_safe_sleep(transferee, atxferloopdelay);
943 ast_log(LOG_DEBUG, "Trying to callback...\n");
944 newchan = ast_feature_request_and_dial(transferee, NULL, "Local", ast_best_codec(transferee->nativeformats),
945 callbackto, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
953 /* newchan is up, we should prepare transferee and bridge them */
954 if (check_compat(transferee, newchan))
956 ast_indicate(transferee, AST_CONTROL_UNHOLD);
958 if ((ast_waitfordigit(transferee, 100) < 0)
959 || (ast_waitfordigit(newchan, 100) < 0)
960 || ast_check_hangup(transferee)
961 || ast_check_hangup(newchan)) {
966 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
971 /* Make formats okay */
972 xferchan->readformat = transferee->readformat;
973 xferchan->writeformat = transferee->writeformat;
974 ast_channel_masquerade(xferchan, transferee);
975 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
976 xferchan->_state = AST_STATE_UP;
977 ast_clear_flag(xferchan, AST_FLAGS_ALL);
978 xferchan->_softhangup = 0;
979 if ((f = ast_read(xferchan)))
981 newchan->_state = AST_STATE_UP;
982 ast_clear_flag(newchan, AST_FLAGS_ALL);
983 newchan->_softhangup = 0;
984 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
985 ast_hangup(xferchan);
989 tobj->chan = xferchan;
990 tobj->peer = newchan;
991 tobj->bconfig = *config;
993 if (ast_stream_and_wait(newchan, xfersound, ""))
994 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
995 ast_bridge_call_thread_launch(tobj);
996 return -1; /* XXX meaning the channel is bridged ? */
998 /* Transferee hung up */
999 finishup(transferee);
1004 /* add atxfer and automon as undefined so you can only use em if you configure them */
1005 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1007 AST_RWLOCK_DEFINE_STATIC(features_lock);
1009 static struct ast_call_feature builtin_features[] =
1011 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1012 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1013 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1014 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1015 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1019 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1021 /*! \brief register new feature into feature_list*/
1022 void ast_register_feature(struct ast_call_feature *feature)
1025 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1029 AST_LIST_LOCK(&feature_list);
1030 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1031 AST_LIST_UNLOCK(&feature_list);
1033 if (option_verbose >= 2)
1034 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
1037 /*! \brief unregister feature from feature_list */
1038 void ast_unregister_feature(struct ast_call_feature *feature)
1043 AST_LIST_LOCK(&feature_list);
1044 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1045 AST_LIST_UNLOCK(&feature_list);
1049 /*! \brief Remove all features in the list */
1050 static void ast_unregister_features(void)
1052 struct ast_call_feature *feature;
1054 AST_LIST_LOCK(&feature_list);
1055 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1057 AST_LIST_UNLOCK(&feature_list);
1060 /*! \brief find a call feature by name */
1061 static struct ast_call_feature *find_feature(const char *name)
1063 struct ast_call_feature *tmp;
1065 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1066 if (!strcasecmp(tmp->sname, name))
1073 /*! \brief find a call feature by name */
1074 struct ast_call_feature *ast_find_call_feature(char *name)
1077 for (x = 0; x < FEATURES_COUNT; x++) {
1078 if (!strcasecmp(name, builtin_features[x].sname)) {
1079 return &builtin_features[x];
1085 /*! \brief exec an app by feature */
1086 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1088 struct ast_app *app;
1089 struct ast_call_feature *feature;
1090 struct ast_channel *work, *idle;
1093 AST_LIST_LOCK(&feature_list);
1094 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1095 if (!strcasecmp(feature->exten, code))
1098 AST_LIST_UNLOCK(&feature_list);
1100 if (!feature) { /* shouldn't ever happen! */
1101 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1105 if (sense == FEATURE_SENSE_CHAN) {
1106 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1107 return FEATURE_RETURN_PASSDIGITS;
1108 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1116 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1117 return FEATURE_RETURN_PASSDIGITS;
1118 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1127 if (!(app = pbx_findapp(feature->app))) {
1128 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1132 ast_autoservice_start(idle);
1134 if (!ast_strlen_zero(feature->moh_class))
1135 ast_moh_start(idle, feature->moh_class, NULL);
1137 res = pbx_exec(work, app, feature->app_args);
1139 if (!ast_strlen_zero(feature->moh_class))
1142 ast_autoservice_stop(idle);
1144 if (res == AST_PBX_KEEPALIVE)
1145 return FEATURE_RETURN_PBX_KEEPALIVE;
1146 else if (res == AST_PBX_NO_HANGUP_PEER)
1147 return FEATURE_RETURN_NO_HANGUP_PEER;
1149 return FEATURE_RETURN_SUCCESSBREAK;
1151 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1154 static void unmap_features(void)
1158 ast_rwlock_wrlock(&features_lock);
1159 for (x = 0; x < FEATURES_COUNT; x++)
1160 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1161 ast_rwlock_unlock(&features_lock);
1164 static int remap_feature(const char *name, const char *value)
1167 struct ast_call_feature *feature;
1169 ast_rwlock_wrlock(&features_lock);
1170 if ((feature = find_feature(name))) {
1171 ast_copy_string(feature->exten, value, sizeof(feature->exten));
1174 ast_rwlock_unlock(&features_lock);
1179 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1182 struct ast_flags features;
1183 int res = FEATURE_RETURN_PASSDIGITS;
1184 struct ast_call_feature *feature;
1185 const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1188 if (sense == FEATURE_SENSE_CHAN)
1189 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1191 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1192 if (option_debug > 2)
1193 ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1195 ast_rwlock_rdlock(&features_lock);
1196 for (x = 0; x < FEATURES_COUNT; x++) {
1197 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1198 !ast_strlen_zero(builtin_features[x].exten)) {
1199 /* Feature is up for consideration */
1200 if (!strcmp(builtin_features[x].exten, code)) {
1201 res = builtin_features[x].operation(chan, peer, config, code, sense);
1203 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1204 if (res == FEATURE_RETURN_PASSDIGITS)
1205 res = FEATURE_RETURN_STOREDIGITS;
1209 ast_rwlock_unlock(&features_lock);
1211 if (ast_strlen_zero(dynamic_features))
1214 tmp = ast_strdupa(dynamic_features);
1216 while ((tok = strsep(&tmp, "#"))) {
1217 ast_rwlock_rdlock(&features_lock);
1218 if (!(feature = find_feature(tok))) {
1219 ast_rwlock_unlock(&features_lock);
1223 /* Feature is up for consideration */
1224 if (!strcmp(feature->exten, code)) {
1225 if (option_verbose > 2)
1226 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1227 res = feature->operation(chan, peer, config, code, sense);
1228 ast_rwlock_unlock(&features_lock);
1230 } else if (!strncmp(feature->exten, code, strlen(code)))
1231 res = FEATURE_RETURN_STOREDIGITS;
1233 ast_rwlock_unlock(&features_lock);
1239 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1243 ast_clear_flag(config, AST_FLAGS_ALL);
1245 ast_rwlock_rdlock(&features_lock);
1246 for (x = 0; x < FEATURES_COUNT; x++) {
1247 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1250 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1251 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1253 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1254 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1256 ast_rwlock_unlock(&features_lock);
1258 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1259 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1261 if (dynamic_features) {
1262 char *tmp = ast_strdupa(dynamic_features);
1264 struct ast_call_feature *feature;
1266 /* while we have a feature */
1267 while ((tok = strsep(&tmp, "#"))) {
1268 ast_rwlock_rdlock(&features_lock);
1269 if ((feature = find_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1270 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1271 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1272 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1273 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1275 ast_rwlock_unlock(&features_lock);
1281 /*! \todo XXX Check - this is very similar to the code in channel.c */
1282 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)
1287 struct ast_channel *chan;
1288 struct ast_channel *monitor_chans[2];
1289 struct ast_channel *active_channel;
1290 int res = 0, ready = 0;
1292 if ((chan = ast_request(type, format, data, &cause))) {
1293 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1294 ast_channel_inherit_variables(caller, chan);
1295 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1297 chan->cdr=ast_cdr_alloc();
1299 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1300 ast_cdr_start(chan->cdr);
1304 if (!ast_call(chan, data, timeout)) {
1305 struct timeval started;
1307 char *disconnect_code = NULL, *dialed_code = NULL;
1309 ast_indicate(caller, AST_CONTROL_RINGING);
1310 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1311 ast_rwlock_rdlock(&features_lock);
1312 for (x = 0; x < FEATURES_COUNT; x++) {
1313 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1316 disconnect_code = builtin_features[x].exten;
1317 len = strlen(disconnect_code) + 1;
1318 dialed_code = alloca(len);
1319 memset(dialed_code, 0, len);
1322 ast_rwlock_unlock(&features_lock);
1324 started = ast_tvnow();
1326 while (!((transferee && transferee->_softhangup) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1327 struct ast_frame *f = NULL;
1329 monitor_chans[0] = caller;
1330 monitor_chans[1] = chan;
1331 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1333 /* see if the timeout has been violated */
1334 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1335 state = AST_CONTROL_UNHOLD;
1336 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1337 break; /*doh! timeout*/
1340 if (!active_channel)
1343 if (chan && (chan == active_channel)){
1345 if (f == NULL) { /*doh! where'd he go?*/
1346 state = AST_CONTROL_HANGUP;
1351 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1352 if (f->subclass == AST_CONTROL_RINGING) {
1353 state = f->subclass;
1354 if (option_verbose > 2)
1355 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1356 ast_indicate(caller, AST_CONTROL_RINGING);
1357 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1358 state = f->subclass;
1359 if (option_verbose > 2)
1360 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
1361 ast_indicate(caller, AST_CONTROL_BUSY);
1365 } else if (f->subclass == AST_CONTROL_ANSWER) {
1366 /* This is what we are hoping for */
1367 state = f->subclass;
1373 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1375 /* else who cares */
1378 } else if (caller && (active_channel == caller)) {
1379 f = ast_read(caller);
1380 if (f == NULL) { /*doh! where'd he go?*/
1381 if (!igncallerstate) {
1382 if (caller->_softhangup && !chan->_softhangup) {
1383 /* make this a blind transfer */
1387 state = AST_CONTROL_HANGUP;
1393 if (f->frametype == AST_FRAME_DTMF) {
1394 dialed_code[x++] = f->subclass;
1395 dialed_code[x] = '\0';
1396 if (strlen(dialed_code) == len) {
1398 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1400 dialed_code[x] = '\0';
1402 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1403 /* Caller Canceled the call */
1404 state = AST_CONTROL_UNHOLD;
1416 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1418 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1420 case AST_CAUSE_BUSY:
1421 state = AST_CONTROL_BUSY;
1423 case AST_CAUSE_CONGESTION:
1424 state = AST_CONTROL_CONGESTION;
1429 ast_indicate(caller, -1);
1430 if (chan && ready) {
1431 if (chan->_state == AST_STATE_UP)
1432 state = AST_CONTROL_ANSWER;
1445 if (chan && res <= 0) {
1446 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1448 ast_cdr_init(chan->cdr, chan);
1449 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1450 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1451 ast_cdr_update(chan);
1452 ast_cdr_start(chan->cdr);
1453 ast_cdr_end(chan->cdr);
1454 /* If the cause wasn't handled properly */
1455 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1456 ast_cdr_failed(chan->cdr);
1458 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1465 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1467 /* Copy voice back and forth between the two channels. Give the peer
1468 the ability to transfer calls with '#<extension' syntax. */
1469 struct ast_frame *f;
1470 struct ast_channel *who;
1471 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1472 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1477 struct ast_option_header *aoh;
1478 struct ast_bridge_config backup_config;
1479 struct ast_cdr *bridge_cdr;
1481 memset(&backup_config, 0, sizeof(backup_config));
1483 config->start_time = ast_tvnow();
1486 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1487 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1489 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1492 const char *monitor_exec;
1493 struct ast_channel *src = NULL;
1495 if (!(monitor_app = pbx_findapp("Monitor")))
1498 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1500 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1502 if (monitor_app && src) {
1503 char *tmp = ast_strdupa(monitor_exec);
1504 pbx_exec(src, monitor_app, tmp);
1508 set_config_flags(chan, peer, config);
1509 config->firstpass = 1;
1511 /* Answer if need be */
1512 if (ast_answer(chan))
1514 peer->appl = "Bridged Call";
1515 peer->data = chan->name;
1517 /* copy the userfield from the B-leg to A-leg if applicable */
1518 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1520 if (!ast_strlen_zero(chan->cdr->userfield)) {
1521 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1522 ast_cdr_appenduserfield(chan, tmp);
1524 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1525 /* free the peer's cdr without ast_cdr_free complaining */
1531 struct ast_channel *other; /* used later */
1533 res = ast_channel_bridge(chan, peer, config, &f, &who);
1535 if (config->feature_timer) {
1536 /* Update time limit for next pass */
1537 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1538 config->feature_timer -= diff;
1540 /* Running on backup config, meaning a feature might be being
1541 activated, but that's no excuse to keep things going
1543 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1545 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1546 config->feature_timer = 0;
1552 } else if (config->feature_timer <= 0) {
1553 /* Not *really* out of time, just out of time for
1554 digits to come in for features. */
1556 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1557 if (!ast_strlen_zero(peer_featurecode)) {
1558 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1559 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1561 if (!ast_strlen_zero(chan_featurecode)) {
1562 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1563 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1567 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1569 /* Restore original (possibly time modified) bridge config */
1570 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1571 memset(&backup_config, 0, sizeof(backup_config));
1573 hadfeatures = hasfeatures;
1574 /* Continue as we were */
1577 /* The bridge returned without a frame and there is a feature in progress.
1578 * However, we don't think the feature has quite yet timed out, so just
1579 * go back into the bridge. */
1583 if (config->feature_timer <=0) {
1584 /* We ran out of time */
1585 config->feature_timer = 0;
1595 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1599 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1600 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1601 f->subclass == AST_CONTROL_CONGESTION))) {
1605 /* many things should be sent to the 'other' channel */
1606 other = (who == chan) ? peer : chan;
1607 if (f->frametype == AST_FRAME_CONTROL) {
1608 if (f->subclass == AST_CONTROL_RINGING)
1609 ast_indicate(other, AST_CONTROL_RINGING);
1610 else if (f->subclass == -1)
1611 ast_indicate(other, -1);
1612 else if (f->subclass == AST_CONTROL_FLASH)
1613 ast_indicate(other, AST_CONTROL_FLASH);
1614 else if (f->subclass == AST_CONTROL_OPTION) {
1616 /* Forward option Requests */
1617 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST)
1618 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1620 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1622 } else if (f->frametype == AST_FRAME_DTMF) {
1626 hadfeatures = hasfeatures;
1627 /* This cannot overrun because the longest feature is one shorter than our buffer */
1629 sense = FEATURE_SENSE_CHAN;
1630 featurecode = chan_featurecode;
1632 sense = FEATURE_SENSE_PEER;
1633 featurecode = peer_featurecode;
1635 /*! append the event to featurecode. we rely on the string being zero-filled, and
1636 * not overflowing it.
1637 * \todo XXX how do we guarantee the latter ?
1639 featurecode[strlen(featurecode)] = f->subclass;
1640 /* Get rid of the frame before we start doing "stuff" with the channels */
1643 config->feature_timer = backup_config.feature_timer;
1644 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1646 case FEATURE_RETURN_PASSDIGITS:
1647 ast_dtmf_stream(other, who, featurecode, 0);
1649 case FEATURE_RETURN_SUCCESS:
1650 memset(featurecode, 0, sizeof(chan_featurecode));
1653 if (res >= FEATURE_RETURN_PASSDIGITS) {
1657 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1658 if (hadfeatures && !hasfeatures) {
1659 /* Restore backup */
1660 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1661 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1662 } else if (hasfeatures) {
1664 /* Backup configuration */
1665 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1666 /* Setup temporary config options */
1667 config->play_warning = 0;
1668 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1669 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1670 config->warning_freq = 0;
1671 config->warning_sound = NULL;
1672 config->end_sound = NULL;
1673 config->start_sound = NULL;
1674 config->firstpass = 0;
1676 config->start_time = ast_tvnow();
1677 config->feature_timer = featuredigittimeout;
1679 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1686 /* arrange the cdrs */
1687 bridge_cdr = ast_cdr_alloc();
1689 if (chan->cdr && peer->cdr) { /* both of them? merge */
1690 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
1691 ast_cdr_start(bridge_cdr); /* now is the time to start */
1693 /* absorb the channel cdr */
1694 ast_cdr_merge(bridge_cdr, chan->cdr);
1695 ast_cdr_discard(chan->cdr); /* no posting these guys */
1697 /* absorb the peer cdr */
1698 ast_cdr_merge(bridge_cdr, peer->cdr);
1699 ast_cdr_discard(peer->cdr); /* no posting these guys */
1701 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1702 } else if (chan->cdr) {
1703 /* take the cdr from the channel - literally */
1704 ast_cdr_init(bridge_cdr,chan);
1705 /* absorb this data */
1706 ast_cdr_merge(bridge_cdr, chan->cdr);
1707 ast_cdr_discard(chan->cdr); /* no posting these guys */
1708 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1709 } else if (peer->cdr) {
1710 /* take the cdr from the peer - literally */
1711 ast_cdr_init(bridge_cdr,peer);
1712 /* absorb this data */
1713 ast_cdr_merge(bridge_cdr, peer->cdr);
1714 ast_cdr_discard(peer->cdr); /* no posting these guys */
1716 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1718 /* make up a new cdr */
1719 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
1720 chan->cdr = bridge_cdr; /* */
1722 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
1723 if (strcmp(bridge_cdr->channel, peer->name) != 0)
1724 ast_cdr_setdestchan(bridge_cdr, peer->name);
1726 ast_cdr_setdestchan(bridge_cdr, chan->name);
1732 /*! \brief Output parking event to manager */
1733 static void post_manager_event(const char *s, struct parkeduser *pu)
1735 manager_event(EVENT_FLAG_CALL, s,
1738 "CallerIDNum: %s\r\n"
1739 "CallerIDName: %s\r\n\r\n",
1742 S_OR(pu->chan->cid.cid_num, "<unknown>"),
1743 S_OR(pu->chan->cid.cid_name, "<unknown>")
1747 /*! \brief Take care of parked calls and unpark them if needed */
1748 static void *do_parking_thread(void *ignore)
1750 char parkingslot[AST_MAX_EXTENSION];
1751 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
1757 struct parkeduser *pu, *pl, *pt = NULL;
1758 int ms = -1; /* select timeout, uninitialized */
1759 int max = -1; /* max fd, none there yet */
1760 fd_set nrfds, nefds; /* args for the next select */
1764 ast_mutex_lock(&parking_lock);
1767 /* navigate the list with prev-cur pointers to support removals */
1769 struct ast_channel *chan = pu->chan; /* shorthand */
1770 int tms; /* timeout for this item */
1771 int x; /* fd index in channel */
1772 struct ast_context *con;
1774 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
1779 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1780 if (tms > pu->parkingtime) {
1781 ast_indicate(chan, AST_CONTROL_UNHOLD);
1782 /* Get chan, exten from derived kludge */
1783 if (pu->peername[0]) {
1784 char *peername = ast_strdupa(pu->peername);
1785 char *cp = strrchr(peername, '-');
1788 con = ast_context_find(parking_con_dial);
1790 con = ast_context_create(NULL, parking_con_dial, registrar);
1792 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1795 char returnexten[AST_MAX_EXTENSION];
1796 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1797 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
1799 if (comebacktoorigin) {
1800 set_c_e_p(chan, parking_con_dial, peername, 1);
1802 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
1803 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
1804 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
1805 set_c_e_p(chan, "parkedcallstimeout", peername, 1);
1808 /* They've been waiting too long, send them back to where they came. Theoretically they
1809 should have their original extensions and such, but we copy to be on the safe side */
1810 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1813 post_manager_event("ParkedCallTimeOut", pu);
1815 if (option_verbose > 1)
1816 ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
1817 /* Start up the PBX, or hang them up */
1818 if (ast_pbx_start(chan)) {
1819 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1822 /* And take them out of the parking lot */
1824 pl->next = pu->next;
1826 parkinglot = pu->next;
1829 con = ast_context_find(parking_con);
1831 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1832 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1834 notify_metermaids(pt->parkingexten, parking_con);
1836 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1838 } else { /* still within parking time, process descriptors */
1839 for (x = 0; x < AST_MAX_FDS; x++) {
1840 struct ast_frame *f;
1842 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1843 continue; /* nothing on this descriptor */
1845 if (FD_ISSET(chan->fds[x], &efds))
1846 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1848 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1851 /* See if they need servicing */
1853 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
1856 post_manager_event("ParkedCallGiveUp", pu);
1858 /* There's a problem, hang them up*/
1859 if (option_verbose > 1)
1860 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1862 /* And take them out of the parking lot */
1864 pl->next = pu->next;
1866 parkinglot = pu->next;
1869 con = ast_context_find(parking_con);
1871 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1872 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1874 notify_metermaids(pt->parkingexten, parking_con);
1876 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1880 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1882 if (pu->moh_trys < 3 && !chan->generatordata) {
1884 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
1885 ast_indicate_data(chan, AST_CONTROL_HOLD,
1886 S_OR(parkmohclass, NULL),
1887 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
1890 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
1894 if (x >= AST_MAX_FDS) {
1895 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
1896 if (chan->fds[x] > -1) {
1897 FD_SET(chan->fds[x], &nrfds);
1898 FD_SET(chan->fds[x], &nefds);
1899 if (chan->fds[x] > max)
1903 /* Keep track of our shortest wait */
1904 if (tms < ms || ms < 0)
1911 ast_mutex_unlock(&parking_lock);
1915 struct timeval tv = ast_samp2tv(ms, 1000);
1916 /* Wait for something to happen */
1917 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1919 pthread_testcancel();
1921 return NULL; /* Never reached */
1924 /*! \brief Park a call */
1925 static int park_call_exec(struct ast_channel *chan, void *data)
1927 /* Data is unused at the moment but could contain a parking
1928 lot context eventually */
1930 struct ast_module_user *u;
1932 u = ast_module_user_add(chan);
1934 /* Setup the exten/priority to be s/1 since we don't know
1935 where this call should return */
1936 strcpy(chan->exten, "s");
1938 /* Answer if call is not up */
1939 if (chan->_state != AST_STATE_UP)
1940 res = ast_answer(chan);
1941 /* Sleep to allow VoIP streams to settle down */
1943 res = ast_safe_sleep(chan, 1000);
1946 res = ast_park_call(chan, chan, 0, NULL);
1948 ast_module_user_remove(u);
1950 return !res ? AST_PBX_KEEPALIVE : res;
1953 /*! \brief Pickup parked call */
1954 static int park_exec(struct ast_channel *chan, void *data)
1957 struct ast_module_user *u;
1958 struct ast_channel *peer=NULL;
1959 struct parkeduser *pu, *pl=NULL;
1960 struct ast_context *con;
1963 struct ast_bridge_config config;
1966 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
1970 u = ast_module_user_add(chan);
1972 park = atoi((char *)data);
1973 ast_mutex_lock(&parking_lock);
1976 if (pu->parkingnum == park) {
1978 pl->next = pu->next;
1980 parkinglot = pu->next;
1986 ast_mutex_unlock(&parking_lock);
1989 con = ast_context_find(parking_con);
1991 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
1992 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1994 notify_metermaids(pu->parkingexten, parking_con);
1996 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1998 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2002 "CallerIDNum: %s\r\n"
2003 "CallerIDName: %s\r\n",
2004 pu->parkingexten, pu->chan->name, chan->name,
2005 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2006 S_OR(pu->chan->cid.cid_name, "<unknown>")
2011 /* JK02: it helps to answer the channel if not already up */
2012 if (chan->_state != AST_STATE_UP)
2016 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2018 if (!ast_strlen_zero(courtesytone)) {
2020 ast_indicate(peer, AST_CONTROL_UNHOLD);
2021 if (parkedplay == 0) {
2022 error = ast_stream_and_wait(chan, courtesytone, "");
2023 } else if (parkedplay == 1) {
2024 error = ast_stream_and_wait(peer, courtesytone, "");
2025 } else if (parkedplay == 2) {
2026 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2027 !ast_streamfile(peer, courtesytone, chan->language)) {
2028 /*! \todo XXX we would like to wait on both! */
2029 res = ast_waitstream(chan, "");
2031 res = ast_waitstream(peer, "");
2037 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2042 ast_indicate(peer, AST_CONTROL_UNHOLD);
2044 res = ast_channel_make_compatible(chan, peer);
2046 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2050 /* This runs sorta backwards, since we give the incoming channel control, as if it
2051 were the person called. */
2052 if (option_verbose > 2)
2053 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
2055 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2056 ast_cdr_setdestchan(chan->cdr, peer->name);
2057 memset(&config, 0, sizeof(struct ast_bridge_config));
2058 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2059 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2060 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2061 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2062 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2063 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2064 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2065 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2066 res = ast_bridge_call(chan, peer, &config);
2068 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2069 ast_cdr_setdestchan(chan->cdr, peer->name);
2071 /* Simulate the PBX hanging up */
2072 if (res != AST_PBX_NO_HANGUP_PEER)
2076 /*! \todo XXX Play a message XXX */
2077 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2078 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2079 if (option_verbose > 2)
2080 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2084 ast_module_user_remove(u);
2089 static int handle_showfeatures(int fd, int argc, char *argv[])
2092 struct ast_call_feature *feature;
2093 char format[] = "%-25s %-7s %-7s\n";
2095 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
2096 ast_cli(fd, format, "---------------", "-------", "-------");
2098 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2100 ast_rwlock_rdlock(&features_lock);
2101 for (i = 0; i < FEATURES_COUNT; i++)
2102 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2103 ast_rwlock_unlock(&features_lock);
2106 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
2107 ast_cli(fd, format, "---------------", "-------", "-------");
2108 if (AST_LIST_EMPTY(&feature_list))
2109 ast_cli(fd, "(none)\n");
2111 AST_LIST_LOCK(&feature_list);
2112 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2113 ast_cli(fd, format, feature->sname, "no def", feature->exten);
2114 AST_LIST_UNLOCK(&feature_list);
2116 ast_cli(fd, "\nCall parking\n");
2117 ast_cli(fd, "------------\n");
2118 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
2119 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
2120 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2123 return RESULT_SUCCESS;
2126 static char mandescr_bridge[] =
2127 "Description: Bridge together two channels already in the PBX\n"
2128 "Variables: ( Headers marked with * are required )\n"
2129 " *Channel1: Channel to Bridge to Channel2\n"
2130 " *Channel2: Channel to Bridge to Channel1\n"
2131 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2134 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2137 ast_mutex_lock(&chan->lock);
2138 ast_setstate(tmpchan, chan->_state);
2139 tmpchan->readformat = chan->readformat;
2140 tmpchan->writeformat = chan->writeformat;
2141 ast_channel_masquerade(tmpchan, chan);
2142 ast_mutex_lock(&tmpchan->lock);
2143 ast_do_masquerade(tmpchan);
2144 /* when returning from bridge, the channel will continue at the next priority */
2145 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2146 ast_mutex_unlock(&tmpchan->lock);
2147 ast_mutex_unlock(&chan->lock);
2150 static int action_bridge(struct mansession *s, const struct message *m)
2152 const char *channela = astman_get_header(m, "Channel1");
2153 const char *channelb = astman_get_header(m, "Channel2");
2154 const char *playtone = astman_get_header(m, "Tone");
2155 struct ast_channel *chana = NULL, *chanb = NULL;
2156 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
2157 struct ast_bridge_thread_obj *tobj = NULL;
2159 /* make sure valid channels were specified */
2160 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
2161 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
2162 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
2164 ast_mutex_unlock(&chana->lock);
2166 ast_mutex_unlock(&chanb->lock);
2168 /* send errors if any of the channels could not be found/locked */
2171 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
2172 astman_send_error(s, m, buf);
2177 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
2178 astman_send_error(s, m, buf);
2182 astman_send_error(s, m, "Missing channel parameter in request");
2186 /* Answer the channels if needed */
2187 if (chana->_state != AST_STATE_UP)
2189 if (chanb->_state != AST_STATE_UP)
2192 /* create the placeholder channels and grab the other channels */
2193 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2194 NULL, NULL, 0, "Bridge/%s", chana->name))) {
2195 astman_send_error(s, m, "Unable to create temporary channel!");
2199 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2200 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
2201 astman_send_error(s, m, "Unable to create temporary channels!");
2202 ast_channel_free(tmpchana);
2206 do_bridge_masquerade(chana, tmpchana);
2207 do_bridge_masquerade(chanb, tmpchanb);
2209 /* make the channels compatible, send error if we fail doing so */
2210 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
2211 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
2212 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
2213 ast_hangup(tmpchana);
2214 ast_hangup(tmpchanb);
2218 /* setup the bridge thread object and start the bridge */
2219 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
2220 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
2221 astman_send_error(s, m, "Unable to spawn a new bridge thread");
2222 ast_hangup(tmpchana);
2223 ast_hangup(tmpchanb);
2227 tobj->chan = tmpchana;
2228 tobj->peer = tmpchanb;
2229 tobj->return_to_pbx = 1;
2231 if (ast_true(playtone)) {
2232 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
2233 if (ast_waitstream(tmpchanb, "") < 0)
2234 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
2238 ast_bridge_call_thread_launch(tobj);
2240 astman_send_ack(s, m, "Launched bridge thread with success");
2245 static char showfeatures_help[] =
2246 "Usage: feature list\n"
2247 " Lists currently configured features.\n";
2249 static int handle_parkedcalls(int fd, int argc, char *argv[])
2251 struct parkeduser *cur;
2254 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2255 , "Context", "Extension", "Pri", "Timeout");
2257 ast_mutex_lock(&parking_lock);
2259 for (cur = parkinglot; cur; cur = cur->next) {
2260 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2261 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2262 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2266 ast_mutex_unlock(&parking_lock);
2267 ast_cli(fd, "%d parked call%s.\n", numparked, ESS(numparked));
2270 return RESULT_SUCCESS;
2273 static char showparked_help[] =
2274 "Usage: show parkedcalls\n"
2275 " Lists currently parked calls.\n";
2277 static struct ast_cli_entry cli_features[] = {
2278 { { "feature", "show", NULL },
2279 handle_showfeatures, "Lists configured features",
2280 showfeatures_help },
2282 { { "show", "parkedcalls", NULL },
2283 handle_parkedcalls, "Lists parked calls",
2287 /*! \brief Dump lot status */
2288 static int manager_parking_status(struct mansession *s, const struct message *m)
2290 struct parkeduser *cur;
2291 const char *id = astman_get_header(m, "ActionID");
2292 char idText[256] = "";
2294 if (!ast_strlen_zero(id))
2295 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2297 astman_send_ack(s, m, "Parked calls will follow");
2299 ast_mutex_lock(&parking_lock);
2301 for (cur = parkinglot; cur; cur = cur->next) {
2302 astman_append(s, "Event: ParkedCall\r\n"
2307 "CallerIDNum: %s\r\n"
2308 "CallerIDName: %s\r\n"
2311 cur->parkingnum, cur->chan->name, cur->peername,
2312 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2313 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
2314 S_OR(cur->chan->cid.cid_name, ""),
2319 "Event: ParkedCallsComplete\r\n"
2323 ast_mutex_unlock(&parking_lock);
2325 return RESULT_SUCCESS;
2328 static char mandescr_park[] =
2329 "Description: Park a channel.\n"
2330 "Variables: (Names marked with * are required)\n"
2331 " *Channel: Channel name to park\n"
2332 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
2333 " Timeout: Number of milliseconds to wait before callback.\n";
2335 static int manager_park(struct mansession *s, const struct message *m)
2337 const char *channel = astman_get_header(m, "Channel");
2338 const char *channel2 = astman_get_header(m, "Channel2");
2339 const char *timeout = astman_get_header(m, "Timeout");
2344 struct ast_channel *ch1, *ch2;
2346 if (ast_strlen_zero(channel)) {
2347 astman_send_error(s, m, "Channel not specified");
2351 if (ast_strlen_zero(channel2)) {
2352 astman_send_error(s, m, "Channel2 not specified");
2356 ch1 = ast_get_channel_by_name_locked(channel);
2358 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2359 astman_send_error(s, m, buf);
2363 ch2 = ast_get_channel_by_name_locked(channel2);
2365 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2366 astman_send_error(s, m, buf);
2367 ast_channel_unlock(ch1);
2371 if (!ast_strlen_zero(timeout)) {
2372 sscanf(timeout, "%d", &to);
2375 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2377 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2378 astman_send_ack(s, m, "Park successful");
2380 astman_send_error(s, m, "Park failure");
2383 ast_channel_unlock(ch1);
2384 ast_channel_unlock(ch2);
2390 int ast_pickup_call(struct ast_channel *chan)
2392 struct ast_channel *cur = NULL;
2395 while ((cur = ast_channel_walk_locked(cur)) != NULL) {
2398 (chan->pickupgroup & cur->callgroup) &&
2399 ((cur->_state == AST_STATE_RINGING) ||
2400 (cur->_state == AST_STATE_RING))) {
2403 ast_channel_unlock(cur);
2407 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2408 res = ast_answer(chan);
2410 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2411 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2413 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2414 res = ast_channel_masquerade(cur, chan);
2416 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
2417 ast_channel_unlock(cur);
2420 ast_log(LOG_DEBUG, "No call pickup possible...\n");
2425 /*! \brief Add parking hints for all defined parking lots */
2426 static void park_add_hints(char *context, int start, int stop)
2429 char device[AST_MAX_EXTENSION];
2432 for (numext = start; numext <= stop; numext++) {
2433 snprintf(exten, sizeof(exten), "%d", numext);
2434 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2435 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2440 static int load_config(void)
2442 int start = 0, end = 0;
2444 struct ast_context *con = NULL;
2445 struct ast_config *cfg = NULL;
2446 struct ast_variable *var = NULL;
2447 char old_parking_ext[AST_MAX_EXTENSION];
2448 char old_parking_con[AST_MAX_EXTENSION] = "";
2450 if (!ast_strlen_zero(parking_con)) {
2451 strcpy(old_parking_ext, parking_ext);
2452 strcpy(old_parking_con, parking_con);
2455 /* Reset to defaults */
2456 strcpy(parking_con, "parkedcalls");
2457 strcpy(parking_con_dial, "park-dial");
2458 strcpy(parking_ext, "700");
2459 strcpy(pickup_ext, "*8");
2460 strcpy(parkmohclass, "default");
2461 courtesytone[0] = '\0';
2462 strcpy(xfersound, "beep");
2463 strcpy(xferfailsound, "pbx-invalid");
2464 parking_start = 701;
2468 comebacktoorigin = 1;
2470 parkedcalltransfers = 0;
2471 parkedcallreparking = 0;
2473 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2474 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2475 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2476 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2477 atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2478 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2480 cfg = ast_config_load("features.conf");
2482 ast_log(LOG_WARNING,"Could not load features.conf\n");
2483 return AST_MODULE_LOAD_DECLINE;
2485 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2486 if (!strcasecmp(var->name, "parkext")) {
2487 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2488 } else if (!strcasecmp(var->name, "context")) {
2489 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2490 } else if (!strcasecmp(var->name, "parkingtime")) {
2491 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2492 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2493 parkingtime = DEFAULT_PARK_TIME;
2495 parkingtime = parkingtime * 1000;
2496 } else if (!strcasecmp(var->name, "parkpos")) {
2497 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2498 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);
2500 parking_start = start;
2503 } else if (!strcasecmp(var->name, "findslot")) {
2504 parkfindnext = (!strcasecmp(var->value, "next"));
2505 } else if (!strcasecmp(var->name, "parkinghints")) {
2506 parkaddhints = ast_true(var->value);
2507 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2508 if (!strcasecmp(var->value, "both"))
2509 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2510 else if (!strcasecmp(var->value, "caller"))
2511 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2512 else if (!strcasecmp(var->value, "callee"))
2513 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2514 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2515 if (!strcasecmp(var->value, "both"))
2516 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2517 else if (!strcasecmp(var->value, "caller"))
2518 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2519 else if (!strcasecmp(var->value, "callee"))
2520 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2521 } else if (!strcasecmp(var->name, "adsipark")) {
2522 adsipark = ast_true(var->value);
2523 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2524 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2525 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2526 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2528 transferdigittimeout = transferdigittimeout * 1000;
2529 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2530 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2531 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2532 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2534 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2535 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2536 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2537 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2539 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2540 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2541 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2542 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2543 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2545 atxferloopdelay *= 1000;
2546 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2547 atxferdropcall = ast_true(var->value);
2548 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2549 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2550 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2551 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2553 } else if (!strcasecmp(var->name, "courtesytone")) {
2554 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2555 } else if (!strcasecmp(var->name, "parkedplay")) {
2556 if (!strcasecmp(var->value, "both"))
2558 else if (!strcasecmp(var->value, "parked"))
2562 } else if (!strcasecmp(var->name, "xfersound")) {
2563 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2564 } else if (!strcasecmp(var->name, "xferfailsound")) {
2565 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2566 } else if (!strcasecmp(var->name, "pickupexten")) {
2567 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2568 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2569 comebacktoorigin = ast_true(var->value);
2570 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2571 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2576 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2577 if (remap_feature(var->name, var->value))
2578 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2581 /* Map a key combination to an application*/
2582 ast_unregister_features();
2583 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2584 char *tmp_val = ast_strdupa(var->value);
2585 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2586 struct ast_call_feature *feature;
2588 /* strsep() sets the argument to NULL if match not found, and it
2589 * is safe to use it with a NULL argument, so we don't check
2592 exten = strsep(&tmp_val,",");
2593 activatedby = strsep(&tmp_val,",");
2594 app = strsep(&tmp_val,",");
2595 app_args = strsep(&tmp_val,",");
2596 moh_class = strsep(&tmp_val,",");
2598 activateon = strsep(&activatedby, "/");
2600 /*! \todo XXX var_name or app_args ? */
2601 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2602 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2603 app, exten, activateon, var->name);
2607 if ((feature = find_feature(var->name))) {
2608 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2612 if (!(feature = ast_calloc(1, sizeof(*feature))))
2615 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2616 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2617 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2620 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2623 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2625 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2626 feature->operation = feature_exec_app;
2627 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2629 /* Allow caller and calle to be specified for backwards compatability */
2630 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2631 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2632 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2633 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2635 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2636 " must be 'self', or 'peer'\n", var->name);
2640 if (ast_strlen_zero(activatedby))
2641 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2642 else if (!strcasecmp(activatedby, "caller"))
2643 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2644 else if (!strcasecmp(activatedby, "callee"))
2645 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2646 else if (!strcasecmp(activatedby, "both"))
2647 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2649 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2650 " must be 'caller', or 'callee', or 'both'\n", var->name);
2654 ast_register_feature(feature);
2656 if (option_verbose >= 1)
2657 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2659 ast_config_destroy(cfg);
2661 /* Remove the old parking extension */
2662 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2663 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2664 notify_metermaids(old_parking_ext, old_parking_con);
2666 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2669 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2670 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2673 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2675 park_add_hints(parking_con, parking_start, parking_stop);
2677 notify_metermaids(ast_parking_ext(), parking_con);
2682 static char *app_bridge = "Bridge";
2683 static char *bridge_synopsis = "Bridge two channels";
2684 static char *bridge_descrip =
2685 "Usage: Bridge(channel[|options])\n"
2686 " Allows the ability to bridge two channels via the dialplan.\n"
2687 "The current channel is bridged to the specified 'channel'.\n"
2688 "The following options are supported:\n"
2689 " p - Play a courtesy tone to 'channel'.\n"
2690 "BRIDGERESULT dial plan variable will contain SUCCESS, FAILURE, LOOP, NONEXISTENT or INCOMPATIBLE.\n";
2693 BRIDGE_OPT_PLAYTONE = (1 << 0),
2696 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
2697 AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
2700 static int bridge_exec(struct ast_channel *chan, void *data)
2702 struct ast_module_user *u;
2703 struct ast_channel *current_dest_chan, *final_dest_chan;
2704 char *tmp_data = NULL;
2705 struct ast_flags opts = { 0, };
2706 struct ast_bridge_config bconfig = { { 0, }, };
2708 AST_DECLARE_APP_ARGS(args,
2709 AST_APP_ARG(dest_chan);
2710 AST_APP_ARG(options);
2713 if (ast_strlen_zero(data)) {
2714 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
2718 u = ast_module_user_add(chan);
2720 tmp_data = ast_strdupa(data);
2721 AST_STANDARD_APP_ARGS(args, tmp_data);
2722 if (!ast_strlen_zero(args.options))
2723 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
2725 /* avoid bridge with ourselves */
2726 if (!strncmp(chan->name, args.dest_chan,
2727 strlen(chan->name) < strlen(args.dest_chan) ?
2728 strlen(chan->name) : strlen(args.dest_chan))) {
2729 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
2730 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2731 "Response: Failed\r\n"
2732 "Reason: Unable to bridge channel to itself\r\n"
2735 chan->name, args.dest_chan);
2736 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
2737 ast_module_user_remove(u);
2741 /* make sure we have a valid end point */
2742 if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
2743 strlen(args.dest_chan)))) {
2744 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
2745 "cannot get its lock\n", args.dest_chan);
2746 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2747 "Response: Failed\r\n"
2748 "Reason: Cannot grab end point\r\n"
2750 "Channel2: %s\r\n", chan->name, args.dest_chan);
2751 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
2752 ast_module_user_remove(u);
2755 ast_mutex_unlock(¤t_dest_chan->lock);
2757 /* answer the channel if needed */
2758 if (current_dest_chan->_state != AST_STATE_UP)
2759 ast_answer(current_dest_chan);
2761 /* try to allocate a place holder where current_dest_chan will be placed */
2762 if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2763 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
2764 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
2765 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2766 "Response: Failed\r\n"
2767 "Reason: cannot create placeholder\r\n"
2769 "Channel2: %s\r\n", chan->name, args.dest_chan);
2771 do_bridge_masquerade(current_dest_chan, final_dest_chan);
2773 /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
2774 /* try to make compatible, send error if we fail */
2775 if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
2776 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
2777 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2778 "Response: Failed\r\n"
2779 "Reason: Could not make channels compatible for bridge\r\n"
2781 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
2782 ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
2783 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
2784 ast_module_user_remove(u);
2788 /* Report that the bridge will be successfull */
2789 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2790 "Response: Success\r\n"
2792 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
2794 /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
2795 if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
2796 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
2797 if (ast_waitstream(final_dest_chan, "") < 0)
2798 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
2803 ast_bridge_call(chan, final_dest_chan, &bconfig);
2805 /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
2806 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
2807 if (!ast_check_hangup(final_dest_chan)) {
2809 ast_log(LOG_DEBUG, "starting new PBX in %s,%s,%d for chan %s\n",
2810 final_dest_chan->context, final_dest_chan->exten,
2811 final_dest_chan->priority, final_dest_chan->name);
2814 if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
2815 ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
2816 ast_hangup(final_dest_chan);
2817 } else if (option_debug)
2818 ast_log(LOG_DEBUG, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
2821 ast_log(LOG_DEBUG, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
2822 ast_hangup(final_dest_chan);
2825 ast_module_user_remove(u);
2830 static int reload(void)
2832 return load_config();
2835 static int load_module(void)
2839 ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);
2841 memset(parking_ext, 0, sizeof(parking_ext));
2842 memset(parking_con, 0, sizeof(parking_con));
2844 if ((res = load_config()))
2846 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2847 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2848 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2850 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2852 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
2853 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2854 "Park a channel", mandescr_park);
2855 ast_manager_register2("Bridge", EVENT_FLAG_COMMAND, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
2858 res |= ast_devstate_prov_add("Park", metermaidstate);
2864 static int unload_module(void)
2866 ast_module_user_hangup_all();
2868 ast_manager_unregister("ParkedCalls");
2869 ast_manager_unregister("Bridge");
2870 ast_manager_unregister("Park");
2871 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2872 ast_unregister_application(parkcall);
2873 ast_unregister_application(app_bridge);
2874 ast_devstate_prov_del("Park");
2875 return ast_unregister_application(parkedcall);
2878 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
2879 .load = load_module,
2880 .unload = unload_module,