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 struct ast_call_feature builtin_features[] =
1009 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1010 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1011 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1012 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1013 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1017 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1019 /*! \brief register new feature into feature_list*/
1020 void ast_register_feature(struct ast_call_feature *feature)
1023 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1027 AST_LIST_LOCK(&feature_list);
1028 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1029 AST_LIST_UNLOCK(&feature_list);
1031 if (option_verbose >= 2)
1032 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
1035 /*! \brief unregister feature from feature_list */
1036 void ast_unregister_feature(struct ast_call_feature *feature)
1041 AST_LIST_LOCK(&feature_list);
1042 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1043 AST_LIST_UNLOCK(&feature_list);
1047 /*! \brief Remove all features in the list */
1048 static void ast_unregister_features(void)
1050 struct ast_call_feature *feature;
1052 AST_LIST_LOCK(&feature_list);
1053 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1055 AST_LIST_UNLOCK(&feature_list);
1058 /*! \brief find a call feature by name */
1059 static struct ast_call_feature *find_feature(char *name)
1061 struct ast_call_feature *tmp;
1063 AST_LIST_LOCK(&feature_list);
1064 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1065 if (!strcasecmp(tmp->sname, name))
1068 AST_LIST_UNLOCK(&feature_list);
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)
1157 for (x = 0; x < FEATURES_COUNT; x++)
1158 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1161 static int remap_feature(const char *name, const char *value)
1165 for (x = 0; x < FEATURES_COUNT; x++) {
1166 if (!strcasecmp(name, builtin_features[x].sname)) {
1167 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1168 if (option_verbose > 1)
1169 ast_verbose(VERBOSE_PREFIX_2 "Remapping feature %s (%s) to sequence '%s'\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
1171 } else if (!strcmp(value, builtin_features[x].exten))
1172 ast_log(LOG_WARNING, "Sequence '%s' already mapped to function %s (%s) while assigning to %s\n", value, builtin_features[x].fname, builtin_features[x].sname, name);
1177 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1180 struct ast_flags features;
1181 int res = FEATURE_RETURN_PASSDIGITS;
1182 struct ast_call_feature *feature;
1183 const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1185 if (sense == FEATURE_SENSE_CHAN)
1186 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1188 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1189 if (option_debug > 2)
1190 ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1192 for (x=0; x < FEATURES_COUNT; x++) {
1193 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1194 !ast_strlen_zero(builtin_features[x].exten)) {
1195 /* Feature is up for consideration */
1196 if (!strcmp(builtin_features[x].exten, code)) {
1197 res = builtin_features[x].operation(chan, peer, config, code, sense);
1199 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1200 if (res == FEATURE_RETURN_PASSDIGITS)
1201 res = FEATURE_RETURN_STOREDIGITS;
1207 if (!ast_strlen_zero(dynamic_features)) {
1208 char *tmp = ast_strdupa(dynamic_features);
1211 while ((tok = strsep(&tmp, "#")) != NULL) {
1212 feature = find_feature(tok);
1215 /* Feature is up for consideration */
1216 if (!strcmp(feature->exten, code)) {
1217 if (option_verbose > 2)
1218 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1219 res = feature->operation(chan, peer, config, code, sense);
1221 } else if (!strncmp(feature->exten, code, strlen(code))) {
1222 res = FEATURE_RETURN_STOREDIGITS;
1231 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1235 ast_clear_flag(config, AST_FLAGS_ALL);
1236 for (x = 0; x < FEATURES_COUNT; x++) {
1237 if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
1238 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1239 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1241 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1242 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1246 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1247 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1249 if (dynamic_features) {
1250 char *tmp = ast_strdupa(dynamic_features);
1252 struct ast_call_feature *feature;
1254 /* while we have a feature */
1255 while ((tok = strsep(&tmp, "#"))) {
1256 if ((feature = find_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1257 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1258 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1259 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1260 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1267 /*! \todo XXX Check - this is very similar to the code in channel.c */
1268 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)
1273 struct ast_channel *chan;
1274 struct ast_channel *monitor_chans[2];
1275 struct ast_channel *active_channel;
1276 int res = 0, ready = 0;
1278 if ((chan = ast_request(type, format, data, &cause))) {
1279 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1280 ast_channel_inherit_variables(caller, chan);
1281 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1283 chan->cdr=ast_cdr_alloc();
1285 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1286 ast_cdr_start(chan->cdr);
1290 if (!ast_call(chan, data, timeout)) {
1291 struct timeval started;
1293 char *disconnect_code = NULL, *dialed_code = NULL;
1295 ast_indicate(caller, AST_CONTROL_RINGING);
1296 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1297 for (x=0; x < FEATURES_COUNT; x++) {
1298 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1301 disconnect_code = builtin_features[x].exten;
1302 len = strlen(disconnect_code) + 1;
1303 dialed_code = alloca(len);
1304 memset(dialed_code, 0, len);
1308 started = ast_tvnow();
1310 while (!((transferee && transferee->_softhangup) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1311 struct ast_frame *f = NULL;
1313 monitor_chans[0] = caller;
1314 monitor_chans[1] = chan;
1315 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1317 /* see if the timeout has been violated */
1318 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1319 state = AST_CONTROL_UNHOLD;
1320 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1321 break; /*doh! timeout*/
1324 if (!active_channel)
1327 if (chan && (chan == active_channel)){
1329 if (f == NULL) { /*doh! where'd he go?*/
1330 state = AST_CONTROL_HANGUP;
1335 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1336 if (f->subclass == AST_CONTROL_RINGING) {
1337 state = f->subclass;
1338 if (option_verbose > 2)
1339 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1340 ast_indicate(caller, AST_CONTROL_RINGING);
1341 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1342 state = f->subclass;
1343 if (option_verbose > 2)
1344 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
1345 ast_indicate(caller, AST_CONTROL_BUSY);
1349 } else if (f->subclass == AST_CONTROL_ANSWER) {
1350 /* This is what we are hoping for */
1351 state = f->subclass;
1357 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1359 /* else who cares */
1362 } else if (caller && (active_channel == caller)) {
1363 f = ast_read(caller);
1364 if (f == NULL) { /*doh! where'd he go?*/
1365 if (!igncallerstate) {
1366 if (caller->_softhangup && !chan->_softhangup) {
1367 /* make this a blind transfer */
1371 state = AST_CONTROL_HANGUP;
1377 if (f->frametype == AST_FRAME_DTMF) {
1378 dialed_code[x++] = f->subclass;
1379 dialed_code[x] = '\0';
1380 if (strlen(dialed_code) == len) {
1382 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1384 dialed_code[x] = '\0';
1386 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1387 /* Caller Canceled the call */
1388 state = AST_CONTROL_UNHOLD;
1400 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1402 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1404 case AST_CAUSE_BUSY:
1405 state = AST_CONTROL_BUSY;
1407 case AST_CAUSE_CONGESTION:
1408 state = AST_CONTROL_CONGESTION;
1413 ast_indicate(caller, -1);
1414 if (chan && ready) {
1415 if (chan->_state == AST_STATE_UP)
1416 state = AST_CONTROL_ANSWER;
1429 if (chan && res <= 0) {
1430 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1432 ast_cdr_init(chan->cdr, chan);
1433 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1434 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1435 ast_cdr_update(chan);
1436 ast_cdr_start(chan->cdr);
1437 ast_cdr_end(chan->cdr);
1438 /* If the cause wasn't handled properly */
1439 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1440 ast_cdr_failed(chan->cdr);
1442 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1449 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1451 /* Copy voice back and forth between the two channels. Give the peer
1452 the ability to transfer calls with '#<extension' syntax. */
1453 struct ast_frame *f;
1454 struct ast_channel *who;
1455 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1456 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1461 struct ast_option_header *aoh;
1462 struct ast_bridge_config backup_config;
1463 struct ast_cdr *bridge_cdr;
1465 memset(&backup_config, 0, sizeof(backup_config));
1467 config->start_time = ast_tvnow();
1470 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1471 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1473 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1476 const char *monitor_exec;
1477 struct ast_channel *src = NULL;
1479 if (!(monitor_app = pbx_findapp("Monitor")))
1482 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1484 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1486 if (monitor_app && src) {
1487 char *tmp = ast_strdupa(monitor_exec);
1488 pbx_exec(src, monitor_app, tmp);
1492 set_config_flags(chan, peer, config);
1493 config->firstpass = 1;
1495 /* Answer if need be */
1496 if (ast_answer(chan))
1498 peer->appl = "Bridged Call";
1499 peer->data = chan->name;
1501 /* copy the userfield from the B-leg to A-leg if applicable */
1502 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1504 if (!ast_strlen_zero(chan->cdr->userfield)) {
1505 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1506 ast_cdr_appenduserfield(chan, tmp);
1508 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1509 /* free the peer's cdr without ast_cdr_free complaining */
1515 struct ast_channel *other; /* used later */
1517 res = ast_channel_bridge(chan, peer, config, &f, &who);
1519 if (config->feature_timer) {
1520 /* Update time limit for next pass */
1521 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1522 config->feature_timer -= diff;
1524 /* Running on backup config, meaning a feature might be being
1525 activated, but that's no excuse to keep things going
1527 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1529 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1530 config->feature_timer = 0;
1536 } else if (config->feature_timer <= 0) {
1537 /* Not *really* out of time, just out of time for
1538 digits to come in for features. */
1540 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1541 if (!ast_strlen_zero(peer_featurecode)) {
1542 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1543 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1545 if (!ast_strlen_zero(chan_featurecode)) {
1546 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1547 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1551 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1553 /* Restore original (possibly time modified) bridge config */
1554 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1555 memset(&backup_config, 0, sizeof(backup_config));
1557 hadfeatures = hasfeatures;
1558 /* Continue as we were */
1561 /* The bridge returned without a frame and there is a feature in progress.
1562 * However, we don't think the feature has quite yet timed out, so just
1563 * go back into the bridge. */
1567 if (config->feature_timer <=0) {
1568 /* We ran out of time */
1569 config->feature_timer = 0;
1579 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1583 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1584 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1585 f->subclass == AST_CONTROL_CONGESTION))) {
1589 /* many things should be sent to the 'other' channel */
1590 other = (who == chan) ? peer : chan;
1591 if (f->frametype == AST_FRAME_CONTROL) {
1592 if (f->subclass == AST_CONTROL_RINGING)
1593 ast_indicate(other, AST_CONTROL_RINGING);
1594 else if (f->subclass == -1)
1595 ast_indicate(other, -1);
1596 else if (f->subclass == AST_CONTROL_FLASH)
1597 ast_indicate(other, AST_CONTROL_FLASH);
1598 else if (f->subclass == AST_CONTROL_OPTION) {
1600 /* Forward option Requests */
1601 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST)
1602 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1604 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1606 } else if (f->frametype == AST_FRAME_DTMF) {
1610 hadfeatures = hasfeatures;
1611 /* This cannot overrun because the longest feature is one shorter than our buffer */
1613 sense = FEATURE_SENSE_CHAN;
1614 featurecode = chan_featurecode;
1616 sense = FEATURE_SENSE_PEER;
1617 featurecode = peer_featurecode;
1619 /*! append the event to featurecode. we rely on the string being zero-filled, and
1620 * not overflowing it.
1621 * \todo XXX how do we guarantee the latter ?
1623 featurecode[strlen(featurecode)] = f->subclass;
1624 /* Get rid of the frame before we start doing "stuff" with the channels */
1627 config->feature_timer = backup_config.feature_timer;
1628 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1630 case FEATURE_RETURN_PASSDIGITS:
1631 ast_dtmf_stream(other, who, featurecode, 0);
1633 case FEATURE_RETURN_SUCCESS:
1634 memset(featurecode, 0, sizeof(chan_featurecode));
1637 if (res >= FEATURE_RETURN_PASSDIGITS) {
1641 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1642 if (hadfeatures && !hasfeatures) {
1643 /* Restore backup */
1644 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1645 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1646 } else if (hasfeatures) {
1648 /* Backup configuration */
1649 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1650 /* Setup temporary config options */
1651 config->play_warning = 0;
1652 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1653 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1654 config->warning_freq = 0;
1655 config->warning_sound = NULL;
1656 config->end_sound = NULL;
1657 config->start_sound = NULL;
1658 config->firstpass = 0;
1660 config->start_time = ast_tvnow();
1661 config->feature_timer = featuredigittimeout;
1663 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1670 /* arrange the cdrs */
1671 bridge_cdr = ast_cdr_alloc();
1673 if (chan->cdr && peer->cdr) { /* both of them? merge */
1674 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
1675 ast_cdr_start(bridge_cdr); /* now is the time to start */
1677 /* absorb the channel cdr */
1678 ast_cdr_merge(bridge_cdr, chan->cdr);
1679 ast_cdr_discard(chan->cdr); /* no posting these guys */
1681 /* absorb the peer cdr */
1682 ast_cdr_merge(bridge_cdr, peer->cdr);
1683 ast_cdr_discard(peer->cdr); /* no posting these guys */
1685 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1686 } else if (chan->cdr) {
1687 /* take the cdr from the channel - literally */
1688 ast_cdr_init(bridge_cdr,chan);
1689 /* absorb this data */
1690 ast_cdr_merge(bridge_cdr, chan->cdr);
1691 ast_cdr_discard(chan->cdr); /* no posting these guys */
1692 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1693 } else if (peer->cdr) {
1694 /* take the cdr from the peer - literally */
1695 ast_cdr_init(bridge_cdr,peer);
1696 /* absorb this data */
1697 ast_cdr_merge(bridge_cdr, peer->cdr);
1698 ast_cdr_discard(peer->cdr); /* no posting these guys */
1700 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1702 /* make up a new cdr */
1703 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
1704 chan->cdr = bridge_cdr; /* */
1706 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
1707 if (strcmp(bridge_cdr->channel, peer->name) != 0)
1708 ast_cdr_setdestchan(bridge_cdr, peer->name);
1710 ast_cdr_setdestchan(bridge_cdr, chan->name);
1716 /*! \brief Output parking event to manager */
1717 static void post_manager_event(const char *s, struct parkeduser *pu)
1719 manager_event(EVENT_FLAG_CALL, s,
1722 "CallerIDNum: %s\r\n"
1723 "CallerIDName: %s\r\n\r\n",
1726 S_OR(pu->chan->cid.cid_num, "<unknown>"),
1727 S_OR(pu->chan->cid.cid_name, "<unknown>")
1731 /*! \brief Take care of parked calls and unpark them if needed */
1732 static void *do_parking_thread(void *ignore)
1734 char parkingslot[AST_MAX_EXTENSION];
1735 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
1741 struct parkeduser *pu, *pl, *pt = NULL;
1742 int ms = -1; /* select timeout, uninitialized */
1743 int max = -1; /* max fd, none there yet */
1744 fd_set nrfds, nefds; /* args for the next select */
1748 ast_mutex_lock(&parking_lock);
1751 /* navigate the list with prev-cur pointers to support removals */
1753 struct ast_channel *chan = pu->chan; /* shorthand */
1754 int tms; /* timeout for this item */
1755 int x; /* fd index in channel */
1756 struct ast_context *con;
1758 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
1763 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1764 if (tms > pu->parkingtime) {
1765 ast_indicate(chan, AST_CONTROL_UNHOLD);
1766 /* Get chan, exten from derived kludge */
1767 if (pu->peername[0]) {
1768 char *peername = ast_strdupa(pu->peername);
1769 char *cp = strrchr(peername, '-');
1772 con = ast_context_find(parking_con_dial);
1774 con = ast_context_create(NULL, parking_con_dial, registrar);
1776 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1779 char returnexten[AST_MAX_EXTENSION];
1780 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1781 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
1783 if (comebacktoorigin) {
1784 set_c_e_p(chan, parking_con_dial, peername, 1);
1786 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
1787 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
1788 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
1789 set_c_e_p(chan, "parkedcallstimeout", peername, 1);
1792 /* They've been waiting too long, send them back to where they came. Theoretically they
1793 should have their original extensions and such, but we copy to be on the safe side */
1794 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1797 post_manager_event("ParkedCallTimeOut", pu);
1799 if (option_verbose > 1)
1800 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);
1801 /* Start up the PBX, or hang them up */
1802 if (ast_pbx_start(chan)) {
1803 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1806 /* And take them out of the parking lot */
1808 pl->next = pu->next;
1810 parkinglot = pu->next;
1813 con = ast_context_find(parking_con);
1815 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1816 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1818 notify_metermaids(pt->parkingexten, parking_con);
1820 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1822 } else { /* still within parking time, process descriptors */
1823 for (x = 0; x < AST_MAX_FDS; x++) {
1824 struct ast_frame *f;
1826 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1827 continue; /* nothing on this descriptor */
1829 if (FD_ISSET(chan->fds[x], &efds))
1830 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1832 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1835 /* See if they need servicing */
1837 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
1840 post_manager_event("ParkedCallGiveUp", pu);
1842 /* There's a problem, hang them up*/
1843 if (option_verbose > 1)
1844 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1846 /* And take them out of the parking lot */
1848 pl->next = pu->next;
1850 parkinglot = pu->next;
1853 con = ast_context_find(parking_con);
1855 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1856 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1858 notify_metermaids(pt->parkingexten, parking_con);
1860 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1864 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1866 if (pu->moh_trys < 3 && !chan->generatordata) {
1868 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
1869 ast_indicate_data(chan, AST_CONTROL_HOLD,
1870 S_OR(parkmohclass, NULL),
1871 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
1874 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
1878 if (x >= AST_MAX_FDS) {
1879 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
1880 if (chan->fds[x] > -1) {
1881 FD_SET(chan->fds[x], &nrfds);
1882 FD_SET(chan->fds[x], &nefds);
1883 if (chan->fds[x] > max)
1887 /* Keep track of our shortest wait */
1888 if (tms < ms || ms < 0)
1895 ast_mutex_unlock(&parking_lock);
1899 struct timeval tv = ast_samp2tv(ms, 1000);
1900 /* Wait for something to happen */
1901 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1903 pthread_testcancel();
1905 return NULL; /* Never reached */
1908 /*! \brief Park a call */
1909 static int park_call_exec(struct ast_channel *chan, void *data)
1911 /* Data is unused at the moment but could contain a parking
1912 lot context eventually */
1914 struct ast_module_user *u;
1916 u = ast_module_user_add(chan);
1918 /* Setup the exten/priority to be s/1 since we don't know
1919 where this call should return */
1920 strcpy(chan->exten, "s");
1922 /* Answer if call is not up */
1923 if (chan->_state != AST_STATE_UP)
1924 res = ast_answer(chan);
1925 /* Sleep to allow VoIP streams to settle down */
1927 res = ast_safe_sleep(chan, 1000);
1930 res = ast_park_call(chan, chan, 0, NULL);
1932 ast_module_user_remove(u);
1934 return !res ? AST_PBX_KEEPALIVE : res;
1937 /*! \brief Pickup parked call */
1938 static int park_exec(struct ast_channel *chan, void *data)
1941 struct ast_module_user *u;
1942 struct ast_channel *peer=NULL;
1943 struct parkeduser *pu, *pl=NULL;
1944 struct ast_context *con;
1947 struct ast_bridge_config config;
1950 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
1954 u = ast_module_user_add(chan);
1956 park = atoi((char *)data);
1957 ast_mutex_lock(&parking_lock);
1960 if (pu->parkingnum == park) {
1962 pl->next = pu->next;
1964 parkinglot = pu->next;
1970 ast_mutex_unlock(&parking_lock);
1973 con = ast_context_find(parking_con);
1975 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
1976 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1978 notify_metermaids(pu->parkingexten, parking_con);
1980 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1982 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
1986 "CallerIDNum: %s\r\n"
1987 "CallerIDName: %s\r\n",
1988 pu->parkingexten, pu->chan->name, chan->name,
1989 S_OR(pu->chan->cid.cid_num, "<unknown>"),
1990 S_OR(pu->chan->cid.cid_name, "<unknown>")
1995 /* JK02: it helps to answer the channel if not already up */
1996 if (chan->_state != AST_STATE_UP)
2000 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2002 if (!ast_strlen_zero(courtesytone)) {
2004 ast_indicate(peer, AST_CONTROL_UNHOLD);
2005 if (parkedplay == 0) {
2006 error = ast_stream_and_wait(chan, courtesytone, "");
2007 } else if (parkedplay == 1) {
2008 error = ast_stream_and_wait(peer, courtesytone, "");
2009 } else if (parkedplay == 2) {
2010 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2011 !ast_streamfile(peer, courtesytone, chan->language)) {
2012 /*! \todo XXX we would like to wait on both! */
2013 res = ast_waitstream(chan, "");
2015 res = ast_waitstream(peer, "");
2021 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2026 ast_indicate(peer, AST_CONTROL_UNHOLD);
2028 res = ast_channel_make_compatible(chan, peer);
2030 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2034 /* This runs sorta backwards, since we give the incoming channel control, as if it
2035 were the person called. */
2036 if (option_verbose > 2)
2037 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
2039 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2040 ast_cdr_setdestchan(chan->cdr, peer->name);
2041 memset(&config, 0, sizeof(struct ast_bridge_config));
2042 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2043 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2044 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2045 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2046 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2047 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2048 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2049 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2050 res = ast_bridge_call(chan, peer, &config);
2052 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2053 ast_cdr_setdestchan(chan->cdr, peer->name);
2055 /* Simulate the PBX hanging up */
2056 if (res != AST_PBX_NO_HANGUP_PEER)
2060 /*! \todo XXX Play a message XXX */
2061 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2062 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2063 if (option_verbose > 2)
2064 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2068 ast_module_user_remove(u);
2073 static int handle_showfeatures(int fd, int argc, char *argv[])
2077 struct ast_call_feature *feature;
2078 char format[] = "%-25s %-7s %-7s\n";
2080 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
2081 ast_cli(fd, format, "---------------", "-------", "-------");
2083 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2085 fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
2087 for (i = 0; i < fcount; i++)
2089 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2092 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
2093 ast_cli(fd, format, "---------------", "-------", "-------");
2094 if (AST_LIST_EMPTY(&feature_list)) {
2095 ast_cli(fd, "(none)\n");
2098 AST_LIST_LOCK(&feature_list);
2099 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
2100 ast_cli(fd, format, feature->sname, "no def", feature->exten);
2102 AST_LIST_UNLOCK(&feature_list);
2104 ast_cli(fd, "\nCall parking\n");
2105 ast_cli(fd, "------------\n");
2106 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
2107 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
2108 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2111 return RESULT_SUCCESS;
2114 static char mandescr_bridge[] =
2115 "Description: Bridge together two channels already in the PBX\n"
2116 "Variables: ( Headers marked with * are required )\n"
2117 " *Channel1: Channel to Bridge to Channel2\n"
2118 " *Channel2: Channel to Bridge to Channel1\n"
2119 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2122 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2125 ast_mutex_lock(&chan->lock);
2126 ast_setstate(tmpchan, chan->_state);
2127 tmpchan->readformat = chan->readformat;
2128 tmpchan->writeformat = chan->writeformat;
2129 ast_channel_masquerade(tmpchan, chan);
2130 ast_mutex_lock(&tmpchan->lock);
2131 ast_do_masquerade(tmpchan);
2132 /* when returning from bridge, the channel will continue at the next priority */
2133 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2134 ast_mutex_unlock(&tmpchan->lock);
2135 ast_mutex_unlock(&chan->lock);
2138 static int action_bridge(struct mansession *s, const struct message *m)
2140 const char *channela = astman_get_header(m, "Channel1");
2141 const char *channelb = astman_get_header(m, "Channel2");
2142 const char *playtone = astman_get_header(m, "Tone");
2143 struct ast_channel *chana = NULL, *chanb = NULL;
2144 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
2145 struct ast_bridge_thread_obj *tobj = NULL;
2147 /* make sure valid channels were specified */
2148 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
2149 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
2150 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
2152 ast_mutex_unlock(&chana->lock);
2154 ast_mutex_unlock(&chanb->lock);
2156 /* send errors if any of the channels could not be found/locked */
2159 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
2160 astman_send_error(s, m, buf);
2165 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
2166 astman_send_error(s, m, buf);
2170 astman_send_error(s, m, "Missing channel parameter in request");
2174 /* Answer the channels if needed */
2175 if (chana->_state != AST_STATE_UP)
2177 if (chanb->_state != AST_STATE_UP)
2180 /* create the placeholder channels and grab the other channels */
2181 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2182 NULL, NULL, 0, "Bridge/%s", chana->name))) {
2183 astman_send_error(s, m, "Unable to create temporary channel!");
2187 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2188 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
2189 astman_send_error(s, m, "Unable to create temporary channels!");
2190 ast_channel_free(tmpchana);
2194 do_bridge_masquerade(chana, tmpchana);
2195 do_bridge_masquerade(chanb, tmpchanb);
2197 /* make the channels compatible, send error if we fail doing so */
2198 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
2199 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
2200 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
2201 ast_hangup(tmpchana);
2202 ast_hangup(tmpchanb);
2206 /* setup the bridge thread object and start the bridge */
2207 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
2208 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
2209 astman_send_error(s, m, "Unable to spawn a new bridge thread");
2210 ast_hangup(tmpchana);
2211 ast_hangup(tmpchanb);
2215 tobj->chan = tmpchana;
2216 tobj->peer = tmpchanb;
2217 tobj->return_to_pbx = 1;
2219 if (ast_true(playtone)) {
2220 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
2221 if (ast_waitstream(tmpchanb, "") < 0)
2222 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
2226 ast_bridge_call_thread_launch(tobj);
2228 astman_send_ack(s, m, "Launched bridge thread with success");
2233 static char showfeatures_help[] =
2234 "Usage: feature list\n"
2235 " Lists currently configured features.\n";
2237 static int handle_parkedcalls(int fd, int argc, char *argv[])
2239 struct parkeduser *cur;
2242 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2243 , "Context", "Extension", "Pri", "Timeout");
2245 ast_mutex_lock(&parking_lock);
2247 for (cur = parkinglot; cur; cur = cur->next) {
2248 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2249 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2250 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2254 ast_mutex_unlock(&parking_lock);
2255 ast_cli(fd, "%d parked call%s.\n", numparked, ESS(numparked));
2258 return RESULT_SUCCESS;
2261 static char showparked_help[] =
2262 "Usage: show parkedcalls\n"
2263 " Lists currently parked calls.\n";
2265 static struct ast_cli_entry cli_features[] = {
2266 { { "feature", "show", NULL },
2267 handle_showfeatures, "Lists configured features",
2268 showfeatures_help },
2270 { { "show", "parkedcalls", NULL },
2271 handle_parkedcalls, "Lists parked calls",
2275 /*! \brief Dump lot status */
2276 static int manager_parking_status(struct mansession *s, const struct message *m)
2278 struct parkeduser *cur;
2279 const char *id = astman_get_header(m, "ActionID");
2280 char idText[256] = "";
2282 if (!ast_strlen_zero(id))
2283 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2285 astman_send_ack(s, m, "Parked calls will follow");
2287 ast_mutex_lock(&parking_lock);
2289 for (cur = parkinglot; cur; cur = cur->next) {
2290 astman_append(s, "Event: ParkedCall\r\n"
2295 "CallerIDNum: %s\r\n"
2296 "CallerIDName: %s\r\n"
2299 cur->parkingnum, cur->chan->name, cur->peername,
2300 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2301 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
2302 S_OR(cur->chan->cid.cid_name, ""),
2307 "Event: ParkedCallsComplete\r\n"
2311 ast_mutex_unlock(&parking_lock);
2313 return RESULT_SUCCESS;
2316 static char mandescr_park[] =
2317 "Description: Park a channel.\n"
2318 "Variables: (Names marked with * are required)\n"
2319 " *Channel: Channel name to park\n"
2320 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
2321 " Timeout: Number of milliseconds to wait before callback.\n";
2323 static int manager_park(struct mansession *s, const struct message *m)
2325 const char *channel = astman_get_header(m, "Channel");
2326 const char *channel2 = astman_get_header(m, "Channel2");
2327 const char *timeout = astman_get_header(m, "Timeout");
2332 struct ast_channel *ch1, *ch2;
2334 if (ast_strlen_zero(channel)) {
2335 astman_send_error(s, m, "Channel not specified");
2339 if (ast_strlen_zero(channel2)) {
2340 astman_send_error(s, m, "Channel2 not specified");
2344 ch1 = ast_get_channel_by_name_locked(channel);
2346 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2347 astman_send_error(s, m, buf);
2351 ch2 = ast_get_channel_by_name_locked(channel2);
2353 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2354 astman_send_error(s, m, buf);
2355 ast_channel_unlock(ch1);
2359 if (!ast_strlen_zero(timeout)) {
2360 sscanf(timeout, "%d", &to);
2363 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2365 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2366 astman_send_ack(s, m, "Park successful");
2368 astman_send_error(s, m, "Park failure");
2371 ast_channel_unlock(ch1);
2372 ast_channel_unlock(ch2);
2378 int ast_pickup_call(struct ast_channel *chan)
2380 struct ast_channel *cur = NULL;
2383 while ((cur = ast_channel_walk_locked(cur)) != NULL) {
2386 (chan->pickupgroup & cur->callgroup) &&
2387 ((cur->_state == AST_STATE_RINGING) ||
2388 (cur->_state == AST_STATE_RING))) {
2391 ast_channel_unlock(cur);
2395 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2396 res = ast_answer(chan);
2398 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2399 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2401 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2402 res = ast_channel_masquerade(cur, chan);
2404 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
2405 ast_channel_unlock(cur);
2408 ast_log(LOG_DEBUG, "No call pickup possible...\n");
2413 /*! \brief Add parking hints for all defined parking lots */
2414 static void park_add_hints(char *context, int start, int stop)
2417 char device[AST_MAX_EXTENSION];
2420 for (numext = start; numext <= stop; numext++) {
2421 snprintf(exten, sizeof(exten), "%d", numext);
2422 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2423 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2428 static int load_config(void)
2430 int start = 0, end = 0;
2432 struct ast_context *con = NULL;
2433 struct ast_config *cfg = NULL;
2434 struct ast_variable *var = NULL;
2435 char old_parking_ext[AST_MAX_EXTENSION];
2436 char old_parking_con[AST_MAX_EXTENSION] = "";
2438 if (!ast_strlen_zero(parking_con)) {
2439 strcpy(old_parking_ext, parking_ext);
2440 strcpy(old_parking_con, parking_con);
2443 /* Reset to defaults */
2444 strcpy(parking_con, "parkedcalls");
2445 strcpy(parking_con_dial, "park-dial");
2446 strcpy(parking_ext, "700");
2447 strcpy(pickup_ext, "*8");
2448 strcpy(parkmohclass, "default");
2449 courtesytone[0] = '\0';
2450 strcpy(xfersound, "beep");
2451 strcpy(xferfailsound, "pbx-invalid");
2452 parking_start = 701;
2456 comebacktoorigin = 1;
2458 parkedcalltransfers = 0;
2459 parkedcallreparking = 0;
2461 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2462 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2463 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2464 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2465 atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2466 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2468 cfg = ast_config_load("features.conf");
2470 ast_log(LOG_WARNING,"Could not load features.conf\n");
2471 return AST_MODULE_LOAD_DECLINE;
2473 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2474 if (!strcasecmp(var->name, "parkext")) {
2475 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2476 } else if (!strcasecmp(var->name, "context")) {
2477 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2478 } else if (!strcasecmp(var->name, "parkingtime")) {
2479 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2480 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2481 parkingtime = DEFAULT_PARK_TIME;
2483 parkingtime = parkingtime * 1000;
2484 } else if (!strcasecmp(var->name, "parkpos")) {
2485 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2486 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);
2488 parking_start = start;
2491 } else if (!strcasecmp(var->name, "findslot")) {
2492 parkfindnext = (!strcasecmp(var->value, "next"));
2493 } else if (!strcasecmp(var->name, "parkinghints")) {
2494 parkaddhints = ast_true(var->value);
2495 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2496 if (!strcasecmp(var->value, "both"))
2497 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2498 else if (!strcasecmp(var->value, "caller"))
2499 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2500 else if (!strcasecmp(var->value, "callee"))
2501 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2502 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2503 if (!strcasecmp(var->value, "both"))
2504 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2505 else if (!strcasecmp(var->value, "caller"))
2506 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2507 else if (!strcasecmp(var->value, "callee"))
2508 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2509 } else if (!strcasecmp(var->name, "adsipark")) {
2510 adsipark = ast_true(var->value);
2511 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2512 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2513 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2514 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2516 transferdigittimeout = transferdigittimeout * 1000;
2517 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2518 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2519 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2520 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2522 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2523 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2524 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2525 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2527 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2528 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2529 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2530 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2531 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2533 atxferloopdelay *= 1000;
2534 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2535 atxferdropcall = ast_true(var->value);
2536 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2537 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2538 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2539 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2541 } else if (!strcasecmp(var->name, "courtesytone")) {
2542 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2543 } else if (!strcasecmp(var->name, "parkedplay")) {
2544 if (!strcasecmp(var->value, "both"))
2546 else if (!strcasecmp(var->value, "parked"))
2550 } else if (!strcasecmp(var->name, "xfersound")) {
2551 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2552 } else if (!strcasecmp(var->name, "xferfailsound")) {
2553 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2554 } else if (!strcasecmp(var->name, "pickupexten")) {
2555 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2556 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2557 comebacktoorigin = ast_true(var->value);
2558 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2559 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2564 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2565 if (remap_feature(var->name, var->value))
2566 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2569 /* Map a key combination to an application*/
2570 ast_unregister_features();
2571 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2572 char *tmp_val = ast_strdupa(var->value);
2573 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2574 struct ast_call_feature *feature;
2576 /* strsep() sets the argument to NULL if match not found, and it
2577 * is safe to use it with a NULL argument, so we don't check
2580 exten = strsep(&tmp_val,",");
2581 activatedby = strsep(&tmp_val,",");
2582 app = strsep(&tmp_val,",");
2583 app_args = strsep(&tmp_val,",");
2584 moh_class = strsep(&tmp_val,",");
2586 activateon = strsep(&activatedby, "/");
2588 /*! \todo XXX var_name or app_args ? */
2589 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2590 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2591 app, exten, activateon, var->name);
2595 if ((feature = find_feature(var->name))) {
2596 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2600 if (!(feature = ast_calloc(1, sizeof(*feature))))
2603 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2604 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2605 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2608 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2611 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2613 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2614 feature->operation = feature_exec_app;
2615 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2617 /* Allow caller and calle to be specified for backwards compatability */
2618 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2619 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2620 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2621 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2623 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2624 " must be 'self', or 'peer'\n", var->name);
2628 if (ast_strlen_zero(activatedby))
2629 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2630 else if (!strcasecmp(activatedby, "caller"))
2631 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2632 else if (!strcasecmp(activatedby, "callee"))
2633 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2634 else if (!strcasecmp(activatedby, "both"))
2635 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2637 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2638 " must be 'caller', or 'callee', or 'both'\n", var->name);
2642 ast_register_feature(feature);
2644 if (option_verbose >= 1)
2645 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2647 ast_config_destroy(cfg);
2649 /* Remove the old parking extension */
2650 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2651 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2652 notify_metermaids(old_parking_ext, old_parking_con);
2654 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2657 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2658 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2661 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2663 park_add_hints(parking_con, parking_start, parking_stop);
2665 notify_metermaids(ast_parking_ext(), parking_con);
2670 static char *app_bridge = "Bridge";
2671 static char *bridge_synopsis = "Bridge two channels";
2672 static char *bridge_descrip =
2673 "Usage: Bridge(channel[|options])\n"
2674 " Allows the ability to bridge two channels via the dialplan.\n"
2675 "The current channel is bridged to the specified 'channel'.\n"
2676 "The following options are supported:\n"
2677 " p - Play a courtesy tone to 'channel'.\n"
2678 "BRIDGERESULT dial plan variable will contain SUCCESS, FAILURE, LOOP, NONEXISTENT or INCOMPATIBLE.\n";
2681 BRIDGE_OPT_PLAYTONE = (1 << 0),
2684 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
2685 AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
2688 static int bridge_exec(struct ast_channel *chan, void *data)
2690 struct ast_module_user *u;
2691 struct ast_channel *current_dest_chan, *final_dest_chan;
2692 char *tmp_data = NULL;
2693 struct ast_flags opts = { 0, };
2694 struct ast_bridge_config bconfig = { { 0, }, };
2696 AST_DECLARE_APP_ARGS(args,
2697 AST_APP_ARG(dest_chan);
2698 AST_APP_ARG(options);
2701 if (ast_strlen_zero(data)) {
2702 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
2706 u = ast_module_user_add(chan);
2708 tmp_data = ast_strdupa(data);
2709 AST_STANDARD_APP_ARGS(args, tmp_data);
2710 if (!ast_strlen_zero(args.options))
2711 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
2713 /* avoid bridge with ourselves */
2714 if (!strncmp(chan->name, args.dest_chan,
2715 strlen(chan->name) < strlen(args.dest_chan) ?
2716 strlen(chan->name) : strlen(args.dest_chan))) {
2717 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
2718 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2719 "Response: Failed\r\n"
2720 "Reason: Unable to bridge channel to itself\r\n"
2723 chan->name, args.dest_chan);
2724 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
2725 ast_module_user_remove(u);
2729 /* make sure we have a valid end point */
2730 if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
2731 strlen(args.dest_chan)))) {
2732 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
2733 "cannot get its lock\n", args.dest_chan);
2734 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2735 "Response: Failed\r\n"
2736 "Reason: Cannot grab end point\r\n"
2738 "Channel2: %s\r\n", chan->name, args.dest_chan);
2739 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
2740 ast_module_user_remove(u);
2743 ast_mutex_unlock(¤t_dest_chan->lock);
2745 /* answer the channel if needed */
2746 if (current_dest_chan->_state != AST_STATE_UP)
2747 ast_answer(current_dest_chan);
2749 /* try to allocate a place holder where current_dest_chan will be placed */
2750 if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2751 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
2752 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
2753 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2754 "Response: Failed\r\n"
2755 "Reason: cannot create placeholder\r\n"
2757 "Channel2: %s\r\n", chan->name, args.dest_chan);
2759 do_bridge_masquerade(current_dest_chan, final_dest_chan);
2761 /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
2762 /* try to make compatible, send error if we fail */
2763 if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
2764 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
2765 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2766 "Response: Failed\r\n"
2767 "Reason: Could not make channels compatible for bridge\r\n"
2769 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
2770 ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
2771 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
2772 ast_module_user_remove(u);
2776 /* Report that the bridge will be successfull */
2777 manager_event(EVENT_FLAG_CALL, "BridgeExec",
2778 "Response: Success\r\n"
2780 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
2782 /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
2783 if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
2784 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
2785 if (ast_waitstream(final_dest_chan, "") < 0)
2786 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
2791 ast_bridge_call(chan, final_dest_chan, &bconfig);
2793 /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
2794 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
2795 if (!ast_check_hangup(final_dest_chan)) {
2797 ast_log(LOG_DEBUG, "starting new PBX in %s,%s,%d for chan %s\n",
2798 final_dest_chan->context, final_dest_chan->exten,
2799 final_dest_chan->priority, final_dest_chan->name);
2802 if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
2803 ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
2804 ast_hangup(final_dest_chan);
2805 } else if (option_debug)
2806 ast_log(LOG_DEBUG, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
2809 ast_log(LOG_DEBUG, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
2810 ast_hangup(final_dest_chan);
2813 ast_module_user_remove(u);
2818 static int reload(void)
2820 return load_config();
2823 static int load_module(void)
2827 ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);
2829 memset(parking_ext, 0, sizeof(parking_ext));
2830 memset(parking_con, 0, sizeof(parking_con));
2832 if ((res = load_config()))
2834 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2835 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2836 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2838 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2840 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
2841 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2842 "Park a channel", mandescr_park);
2843 ast_manager_register2("Bridge", EVENT_FLAG_COMMAND, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
2846 res |= ast_devstate_prov_add("Park", metermaidstate);
2852 static int unload_module(void)
2854 ast_module_user_hangup_all();
2856 ast_manager_unregister("ParkedCalls");
2857 ast_manager_unregister("Bridge");
2858 ast_manager_unregister("Park");
2859 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2860 ast_unregister_application(parkcall);
2861 ast_unregister_application(app_bridge);
2862 ast_devstate_prov_del("Park");
2863 return ast_unregister_application(parkedcall);
2866 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
2867 .load = load_module,
2868 .unload = unload_module,