(closes issue #13139)
[asterisk-bristuff.git] / res / res_features.c
blob6b5bc6b18f02a5dc367b3c20407131c5194e98e9
1 /*
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.
19 /*! \file
21 * \brief Routines implementing call features as call pickup, parking and transfer
23 * \author Mark Spencer <markster@digium.com>
26 /*** MODULEINFO
27 <depend>chan_local</depend>
28 ***/
30 #include "asterisk.h"
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include <pthread.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <sys/time.h>
42 #include <sys/signal.h>
43 #include <netinet/in.h>
45 #include "asterisk/lock.h"
46 #include "asterisk/file.h"
47 #include "asterisk/logger.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/pbx.h"
50 #include "asterisk/options.h"
51 #include "asterisk/causes.h"
52 #include "asterisk/module.h"
53 #include "asterisk/translate.h"
54 #include "asterisk/app.h"
55 #include "asterisk/say.h"
56 #include "asterisk/features.h"
57 #include "asterisk/musiconhold.h"
58 #include "asterisk/config.h"
59 #include "asterisk/cli.h"
60 #include "asterisk/manager.h"
61 #include "asterisk/utils.h"
62 #include "asterisk/adsi.h"
63 #include "asterisk/devicestate.h"
64 #include "asterisk/monitor.h"
65 #include "asterisk/global_datastores.h"
67 #define DEFAULT_PARK_TIME 45000
68 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
69 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
70 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
72 #define AST_MAX_WATCHERS 256
74 enum {
75 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
76 AST_FEATURE_FLAG_ONPEER = (1 << 1),
77 AST_FEATURE_FLAG_ONSELF = (1 << 2),
78 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
79 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
80 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
83 static char *parkedcall = "ParkedCall";
85 static int parkaddhints = 0; /*!< Add parking hints automatically */
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;
103 static int adsipark;
105 static int transferdigittimeout;
106 static int featuredigittimeout;
108 static int atxfernoanswertimeout;
110 static char *registrar = "res_features"; /*!< Registrar for operations */
112 /* module and CLI command definitions */
113 static char *synopsis = "Answer a parked call";
115 static char *descrip = "ParkedCall(exten):"
116 "Used to connect to a parked call. This application is always\n"
117 "registered internally and does not need to be explicitly added\n"
118 "into the dialplan, although you should include the 'parkedcalls'\n"
119 "context.\n";
121 static char *parkcall = PARK_APP_NAME;
123 static char *synopsis2 = "Park yourself";
125 static char *descrip2 = "Park():"
126 "Used to park yourself (typically in combination with a supervised\n"
127 "transfer to know the parking space). This application is always\n"
128 "registered internally and does not need to be explicitly added\n"
129 "into the dialplan, although you should include the 'parkedcalls'\n"
130 "context (or the context specified in features.conf).\n\n"
131 "If you set the PARKINGEXTEN variable to an extension in your\n"
132 "parking context, park() will park the call on that extension, unless\n"
133 "it already exists. In that case, execution will continue at next\n"
134 "priority.\n" ;
136 static struct ast_app *monitor_app = NULL;
137 static int monitor_ok = 1;
139 struct parkeduser {
140 struct ast_channel *chan; /*!< Parking channel */
141 struct timeval start; /*!< Time the parking started */
142 int parkingnum; /*!< Parking lot */
143 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
144 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
145 char exten[AST_MAX_EXTENSION];
146 int priority;
147 int parkingtime; /*!< Maximum length in parking lot before return */
148 int notquiteyet;
149 char peername[1024];
150 unsigned char moh_trys;
151 struct parkeduser *next;
154 static struct parkeduser *parkinglot;
156 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
158 static pthread_t parking_thread;
160 char *ast_parking_ext(void)
162 return parking_ext;
165 char *ast_pickup_ext(void)
167 return pickup_ext;
170 struct ast_bridge_thread_obj
172 struct ast_bridge_config bconfig;
173 struct ast_channel *chan;
174 struct ast_channel *peer;
179 /*! \brief store context, priority and extension */
180 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
182 ast_copy_string(chan->context, context, sizeof(chan->context));
183 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
184 chan->priority = pri;
187 static void check_goto_on_transfer(struct ast_channel *chan)
189 struct ast_channel *xferchan;
190 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
191 char *x, *goto_on_transfer;
192 struct ast_frame *f;
194 if (ast_strlen_zero(val))
195 return;
197 goto_on_transfer = ast_strdupa(val);
199 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
200 return;
202 for (x = goto_on_transfer; x && *x; x++) {
203 if (*x == '^')
204 *x = '|';
206 /* Make formats okay */
207 xferchan->readformat = chan->readformat;
208 xferchan->writeformat = chan->writeformat;
209 ast_channel_masquerade(xferchan, chan);
210 ast_parseable_goto(xferchan, goto_on_transfer);
211 xferchan->_state = AST_STATE_UP;
212 ast_clear_flag(xferchan, AST_FLAGS_ALL);
213 xferchan->_softhangup = 0;
214 if ((f = ast_read(xferchan))) {
215 ast_frfree(f);
216 f = NULL;
217 ast_pbx_start(xferchan);
218 } else {
219 ast_hangup(xferchan);
223 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, const char *language);
226 static void *ast_bridge_call_thread(void *data)
228 struct ast_bridge_thread_obj *tobj = data;
230 tobj->chan->appl = "Transferred Call";
231 tobj->chan->data = tobj->peer->name;
232 tobj->peer->appl = "Transferred Call";
233 tobj->peer->data = tobj->chan->name;
235 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
236 ast_hangup(tobj->chan);
237 ast_hangup(tobj->peer);
238 bzero(tobj, sizeof(*tobj)); /*! \todo XXX for safety */
239 free(tobj);
240 return NULL;
243 static void ast_bridge_call_thread_launch(void *data)
245 pthread_t thread;
246 pthread_attr_t attr;
247 struct sched_param sched;
249 pthread_attr_init(&attr);
250 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
251 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
252 pthread_attr_destroy(&attr);
253 memset(&sched, 0, sizeof(sched));
254 pthread_setschedparam(thread, SCHED_RR, &sched);
257 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
259 int res;
260 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
261 char tmp[256];
262 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
264 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
265 message[0] = tmp;
266 res = ast_adsi_load_session(chan, NULL, 0, 1);
267 if (res == -1)
268 return res;
269 return ast_adsi_print(chan, message, justify, 1);
272 /*! \brief Notify metermaids that we've changed an extension */
273 static void notify_metermaids(char *exten, char *context)
275 if (option_debug > 3)
276 ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
278 /* Send notification to devicestate subsystem */
279 ast_device_state_changed("park:%s@%s", exten, context);
280 return;
283 /*! \brief metermaids callback from devicestate.c */
284 static int metermaidstate(const char *data)
286 int res = AST_DEVICE_INVALID;
287 char *context = ast_strdupa(data);
288 char *exten;
290 exten = strsep(&context, "@");
291 if (!context)
292 return res;
294 if (option_debug > 3)
295 ast_log(LOG_DEBUG, "Checking state of exten %s in context %s\n", exten, context);
297 res = ast_exists_extension(NULL, context, exten, 1, NULL);
299 if (!res)
300 return AST_DEVICE_NOT_INUSE;
301 else
302 return AST_DEVICE_INUSE;
305 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name)
307 struct parkeduser *pu, *cur;
308 int i, x = -1, parking_range, parkingnum_copy;
309 struct ast_context *con;
310 const char *parkingexten;
312 /* Allocate memory for parking data */
313 if (!(pu = ast_calloc(1, sizeof(*pu))))
314 return -1;
316 /* Lock parking lot */
317 ast_mutex_lock(&parking_lock);
318 /* Check for channel variable PARKINGEXTEN */
319 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
320 if (!ast_strlen_zero(parkingexten)) {
321 /*!\note The API forces us to specify a numeric parking slot, even
322 * though the architecture would tend to support non-numeric extensions
323 * (as are possible with SIP, for example). Hence, we enforce that
324 * limitation here. If extout was not numeric, we could permit
325 * arbitrary non-numeric extensions.
327 if (sscanf(parkingexten, "%d", &x) != 1 || x < 0) {
328 ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
329 ast_mutex_unlock(&parking_lock);
330 free(pu);
331 return 1; /* Continue execution if possible */
333 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
335 if (ast_exists_extension(NULL, parking_con, pu->parkingexten, 1, NULL)) {
336 ast_mutex_unlock(&parking_lock);
337 free(pu);
338 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
339 return 1; /* Continue execution if possible */
341 } else {
342 /* Select parking space within range */
343 parking_range = parking_stop - parking_start+1;
344 for (i = 0; i < parking_range; i++) {
345 x = (i + parking_offset) % parking_range + parking_start;
346 cur = parkinglot;
347 while(cur) {
348 if (cur->parkingnum == x)
349 break;
350 cur = cur->next;
352 if (!cur)
353 break;
356 if (!(i < parking_range)) {
357 ast_log(LOG_WARNING, "No more parking spaces\n");
358 free(pu);
359 ast_mutex_unlock(&parking_lock);
360 return -1;
362 /* Set pointer for next parking */
363 if (parkfindnext)
364 parking_offset = x - parking_start + 1;
365 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
368 chan->appl = "Parked Call";
369 chan->data = NULL;
371 pu->chan = chan;
373 /* Put the parked channel on hold if we have two different channels */
374 if (chan != peer) {
375 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
376 S_OR(parkmohclass, NULL),
377 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
380 pu->start = ast_tvnow();
381 pu->parkingnum = x;
382 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
383 if (extout)
384 *extout = x;
386 if (peer) {
387 /* This is so ugly that it hurts, but implementing get_base_channel() on local channels
388 could have ugly side effects. We could have transferer<->local,1<->local,2<->parking
389 and we need the callback name to be that of transferer. Since local,1/2 have the same
390 name we can be tricky and just grab the bridged channel from the other side of the local
392 if (!strcasecmp(peer->tech->type, "Local")) {
393 struct ast_channel *tmpchan, *base_peer;
394 char other_side[AST_CHANNEL_NAME];
395 char *c;
396 ast_copy_string(other_side, peer->name, sizeof(other_side));
397 if ((c = strrchr(other_side, ','))) {
398 *++c = '1';
400 if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
401 if ((base_peer = ast_bridged_channel(tmpchan))) {
402 ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
404 ast_channel_unlock(tmpchan);
406 } else {
407 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
411 /* Remember what had been dialed, so that if the parking
412 expires, we try to come back to the same place */
413 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
414 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
415 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
416 pu->next = parkinglot;
417 parkinglot = pu;
418 parkingnum_copy = pu->parkingnum;
419 /* If parking a channel directly, don't quite yet get parking running on it */
420 if (peer == chan)
421 pu->notquiteyet = 1;
423 if (option_verbose > 1)
424 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));
426 manager_event(EVENT_FLAG_CALL, "ParkedCall",
427 "Exten: %s\r\n"
428 "Channel: %s\r\n"
429 "From: %s\r\n"
430 "Timeout: %ld\r\n"
431 "CallerID: %s\r\n"
432 "CallerIDName: %s\r\n",
433 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
434 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
435 S_OR(pu->chan->cid.cid_num, "<unknown>"),
436 S_OR(pu->chan->cid.cid_name, "<unknown>")
439 if (peer && adsipark && ast_adsi_available(peer)) {
440 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
441 ast_adsi_unload_session(peer);
444 con = ast_context_find(parking_con);
445 if (!con)
446 con = ast_context_create(NULL, parking_con, registrar);
447 if (!con) /* Still no context? Bad */
448 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
449 if (con) {
450 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar)) {
451 notify_metermaids(pu->parkingexten, parking_con);
455 ast_mutex_unlock(&parking_lock);
456 /* Wake up the (presumably select()ing) thread */
457 pthread_kill(parking_thread, SIGURG);
459 /* Only say number if it's a number and the channel hasn't been masqueraded away */
460 if (peer && (ast_strlen_zero(orig_chan_name) || !strcasecmp(peer->name, orig_chan_name))) {
461 /* Make sure we don't start saying digits to the channel being parked */
462 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
463 /* Tell the peer channel the number of the parking space */
464 ast_say_digits(peer, parkingnum_copy, "", peer->language);
465 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
468 if (peer == chan) { /* pu->notquiteyet = 1 */
469 /* Wake up parking thread if we're really done */
470 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
471 S_OR(parkmohclass, NULL),
472 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
473 pu->notquiteyet = 0;
474 pthread_kill(parking_thread, SIGURG);
476 return 0;
479 /*! \brief Park a call
480 \note We put the user in the parking list, then wake up the parking thread to be sure it looks
481 after these channels too */
482 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
484 return park_call_full(chan, peer, timeout, extout, NULL);
487 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement)
489 struct ast_channel *chan;
490 struct ast_frame *f;
491 char *orig_chan_name = NULL;
492 int park_status;
494 /* Make a new, fake channel that we'll use to masquerade in the real one */
495 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
496 ast_log(LOG_WARNING, "Unable to create parked channel\n");
497 return -1;
500 /* Make formats okay */
501 chan->readformat = rchan->readformat;
502 chan->writeformat = rchan->writeformat;
503 ast_channel_masquerade(chan, rchan);
505 /* Setup the extensions and such */
506 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
508 /* Make the masq execute */
509 if ((f = ast_read(chan))) {
510 ast_frfree(f);
513 if (!play_announcement) {
514 orig_chan_name = ast_strdupa(chan->name);
517 park_status = park_call_full(chan, peer, timeout, extout, orig_chan_name);
518 if (park_status == 1) {
519 /* would be nice to play: "invalid parking extension" */
520 ast_hangup(chan);
521 return -1;
524 return 0;
527 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
529 return masq_park_call(rchan, peer, timeout, extout, 0);
532 static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
534 return masq_park_call(rchan, peer, timeout, extout, 1);
537 #define FEATURE_RETURN_HANGUP -1
538 #define FEATURE_RETURN_SUCCESSBREAK 0
539 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
540 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
541 #define FEATURE_RETURN_PASSDIGITS 21
542 #define FEATURE_RETURN_STOREDIGITS 22
543 #define FEATURE_RETURN_SUCCESS 23
544 #define FEATURE_RETURN_KEEPTRYING 24
546 #define FEATURE_SENSE_CHAN (1 << 0)
547 #define FEATURE_SENSE_PEER (1 << 1)
549 /*! \brief
550 * set caller and callee according to the direction
552 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
553 struct ast_channel *peer, struct ast_channel *chan, int sense)
555 if (sense == FEATURE_SENSE_PEER) {
556 *caller = peer;
557 *callee = chan;
558 } else {
559 *callee = peer;
560 *caller = chan;
564 /*! \brief support routing for one touch call parking */
565 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
567 struct ast_channel *parker;
568 struct ast_channel *parkee;
569 int res = 0;
570 struct ast_module_user *u;
572 u = ast_module_user_add(chan);
574 set_peers(&parker, &parkee, peer, chan, sense);
575 /* Setup the exten/priority to be s/1 since we don't know
576 where this call should return */
577 strcpy(chan->exten, "s");
578 chan->priority = 1;
579 if (chan->_state != AST_STATE_UP)
580 res = ast_answer(chan);
581 if (!res)
582 res = ast_safe_sleep(chan, 1000);
584 if (!res) {
585 if (sense == FEATURE_SENSE_CHAN) {
586 res = ast_park_call(parkee, parker, 0, NULL);
587 if (!res) {
588 if (sense == FEATURE_SENSE_CHAN) {
589 res = AST_PBX_NO_HANGUP_PEER;
590 } else {
591 res = AST_PBX_KEEPALIVE;
595 else if (sense == FEATURE_SENSE_PEER) {
596 masq_park_call_announce(parkee, parker, 0, NULL);
597 res = 0; /* PBX should hangup zombie channel */
601 ast_module_user_remove(u);
602 return res;
606 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
608 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
609 int x = 0;
610 size_t len;
611 struct ast_channel *caller_chan, *callee_chan;
613 if (!monitor_ok) {
614 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
615 return -1;
618 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
619 monitor_ok = 0;
620 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
621 return -1;
624 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
626 if (!ast_strlen_zero(courtesytone)) {
627 if (ast_autoservice_start(callee_chan))
628 return -1;
629 if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
630 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
631 ast_autoservice_stop(callee_chan);
632 return -1;
634 if (ast_autoservice_stop(callee_chan))
635 return -1;
638 if (callee_chan->monitor) {
639 if (option_verbose > 3)
640 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
641 ast_monitor_stop(callee_chan, 1);
642 return FEATURE_RETURN_SUCCESS;
645 if (caller_chan && callee_chan) {
646 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
647 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
649 if (!touch_format)
650 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
652 if (!touch_monitor)
653 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
655 if (touch_monitor) {
656 len = strlen(touch_monitor) + 50;
657 args = alloca(len);
658 touch_filename = alloca(len);
659 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
660 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
661 } else {
662 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
663 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
664 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
665 args = alloca(len);
666 touch_filename = alloca(len);
667 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
668 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
671 for( x = 0; x < strlen(args); x++) {
672 if (args[x] == '/')
673 args[x] = '-';
676 if (option_verbose > 3)
677 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
679 pbx_exec(callee_chan, monitor_app, args);
680 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
681 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
683 return FEATURE_RETURN_SUCCESS;
686 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
687 return -1;
690 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
692 if (option_verbose > 3)
693 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
694 return FEATURE_RETURN_HANGUP;
697 static int finishup(struct ast_channel *chan)
699 ast_indicate(chan, AST_CONTROL_UNHOLD);
701 return ast_autoservice_stop(chan);
704 /*! \brief Find the context for the transfer */
705 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
707 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
708 if (ast_strlen_zero(s))
709 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
710 if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
711 s = transferer->macrocontext;
712 if (ast_strlen_zero(s))
713 s = transferer->context;
714 return s;
717 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
719 struct ast_channel *transferer;
720 struct ast_channel *transferee;
721 const char *transferer_real_context;
722 char xferto[256];
723 int res;
725 set_peers(&transferer, &transferee, peer, chan, sense);
726 transferer_real_context = real_ctx(transferer, transferee);
727 /* Start autoservice on chan while we talk to the originator */
728 ast_autoservice_start(transferee);
729 ast_indicate(transferee, AST_CONTROL_HOLD);
731 memset(xferto, 0, sizeof(xferto));
733 /* Transfer */
734 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
735 if (res < 0) {
736 finishup(transferee);
737 return -1; /* error ? */
739 if (res > 0) /* If they've typed a digit already, handle it */
740 xferto[0] = (char) res;
742 ast_stopstream(transferer);
743 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
744 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
745 finishup(transferee);
746 return res;
748 if (!strcmp(xferto, ast_parking_ext())) {
749 res = finishup(transferee);
750 if (res)
751 res = -1;
752 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
753 /* We return non-zero, but tell the PBX not to hang the channel when
754 the thread dies -- We have to be careful now though. We are responsible for
755 hanging up the channel, else it will never be hung up! */
757 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
758 } else {
759 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
761 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
762 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
763 pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
764 pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
765 res=finishup(transferee);
766 if (!transferer->cdr) {
767 transferer->cdr=ast_cdr_alloc();
768 if (transferer) {
769 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
770 ast_cdr_start(transferer->cdr);
773 if (transferer->cdr) {
774 ast_cdr_setdestchan(transferer->cdr, transferee->name);
775 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
777 if (!transferee->pbx) {
778 /* Doh! Use our handy async_goto functions */
779 if (option_verbose > 2)
780 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
781 ,transferee->name, xferto, transferer_real_context);
782 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
783 ast_log(LOG_WARNING, "Async goto failed :-(\n");
784 res = -1;
785 } else {
786 /* Set the channel's new extension, since it exists, using transferer context */
787 set_c_e_p(transferee, transferer_real_context, xferto, 0);
789 check_goto_on_transfer(transferer);
790 return res;
791 } else {
792 if (option_verbose > 2)
793 ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
795 if (ast_stream_and_wait(transferer, xferfailsound, transferer->language, AST_DIGIT_ANY) < 0 ) {
796 finishup(transferee);
797 return -1;
799 ast_stopstream(transferer);
800 res = finishup(transferee);
801 if (res) {
802 if (option_verbose > 1)
803 ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
804 return res;
806 return FEATURE_RETURN_SUCCESS;
809 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
811 if (ast_channel_make_compatible(c, newchan) < 0) {
812 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
813 c->name, newchan->name);
814 ast_hangup(newchan);
815 return -1;
817 return 0;
820 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
822 struct ast_channel *transferer;
823 struct ast_channel *transferee;
824 const char *transferer_real_context;
825 char xferto[256] = "";
826 int res;
827 int outstate=0;
828 struct ast_channel *newchan;
829 struct ast_channel *xferchan;
830 struct ast_bridge_thread_obj *tobj;
831 struct ast_bridge_config bconfig;
832 struct ast_frame *f;
833 int l;
834 struct ast_datastore *features_datastore;
835 struct ast_dial_features *dialfeatures = NULL;
837 if (option_debug)
838 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
839 set_peers(&transferer, &transferee, peer, chan, sense);
840 transferer_real_context = real_ctx(transferer, transferee);
841 /* Start autoservice on chan while we talk to the originator */
842 ast_autoservice_start(transferee);
843 ast_indicate(transferee, AST_CONTROL_HOLD);
845 /* Transfer */
846 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
847 if (res < 0) {
848 finishup(transferee);
849 return res;
851 if (res > 0) /* If they've typed a digit already, handle it */
852 xferto[0] = (char) res;
854 /* this is specific of atxfer */
855 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
856 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
857 finishup(transferee);
858 return res;
860 if (res == 0) {
861 ast_log(LOG_WARNING, "Did not read data.\n");
862 finishup(transferee);
863 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
864 return -1;
865 return FEATURE_RETURN_SUCCESS;
868 /* valid extension, res == 1 */
869 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
870 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
871 finishup(transferee);
872 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
873 return -1;
874 return FEATURE_RETURN_SUCCESS;
877 l = strlen(xferto);
878 snprintf(xferto + l, sizeof(xferto) - l, "@%s", transferer_real_context); /* append context */
879 newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
880 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, transferer->language);
882 /* If we are the callee and we are being transferred, after the masquerade
883 * caller features will really be the original callee features */
884 ast_channel_lock(transferee);
885 if ((features_datastore = ast_channel_datastore_find(transferee, &dial_features_info, NULL))) {
886 dialfeatures = features_datastore->data;
888 ast_channel_unlock(transferee);
890 if (dialfeatures && !dialfeatures->is_caller) {
891 ast_copy_flags(&(config->features_caller), &(dialfeatures->features_callee), AST_FLAGS_ALL);
894 ast_indicate(transferer, -1);
895 if (!newchan) {
896 finishup(transferee);
897 /* any reason besides user requested cancel and busy triggers the failed sound */
898 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
899 ast_stream_and_wait(transferer, xferfailsound, transferer->language, ""))
900 return -1;
901 return FEATURE_RETURN_SUCCESS;
904 if (check_compat(transferer, newchan)) {
905 /* we do mean transferee here, NOT transferer */
906 finishup(transferee);
907 return -1;
909 memset(&bconfig,0,sizeof(struct ast_bridge_config));
910 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
911 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
912 res = ast_bridge_call(transferer, newchan, &bconfig);
913 if (newchan->_softhangup || !transferer->_softhangup) {
914 ast_hangup(newchan);
915 if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
916 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
917 finishup(transferee);
918 transferer->_softhangup = 0;
919 return FEATURE_RETURN_SUCCESS;
922 if (check_compat(transferee, newchan)) {
923 finishup(transferee);
924 return -1;
927 ast_indicate(transferee, AST_CONTROL_UNHOLD);
929 if ((ast_autoservice_stop(transferee) < 0)
930 || (ast_waitfordigit(transferee, 100) < 0)
931 || (ast_waitfordigit(newchan, 100) < 0)
932 || ast_check_hangup(transferee)
933 || ast_check_hangup(newchan)) {
934 ast_hangup(newchan);
935 return -1;
938 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
939 if (!xferchan) {
940 ast_hangup(newchan);
941 return -1;
943 /* Make formats okay */
944 xferchan->visible_indication = transferer->visible_indication;
945 xferchan->readformat = transferee->readformat;
946 xferchan->writeformat = transferee->writeformat;
947 ast_channel_masquerade(xferchan, transferee);
948 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
949 xferchan->_state = AST_STATE_UP;
950 ast_clear_flag(xferchan, AST_FLAGS_ALL);
951 xferchan->_softhangup = 0;
953 if ((f = ast_read(xferchan)))
954 ast_frfree(f);
956 newchan->_state = AST_STATE_UP;
957 ast_clear_flag(newchan, AST_FLAGS_ALL);
958 newchan->_softhangup = 0;
960 tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
961 if (!tobj) {
962 ast_hangup(xferchan);
963 ast_hangup(newchan);
964 return -1;
967 /* For the case where the transfer target is being connected with the original
968 caller store the target's original features, and apply to the bridge */
969 ast_channel_lock(newchan);
970 if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
971 dialfeatures = features_datastore->data;
973 ast_channel_unlock(newchan);
975 if (dialfeatures) {
976 ast_copy_flags(&(config->features_callee), &(dialfeatures->features_callee), AST_FLAGS_ALL);
979 tobj->chan = newchan;
980 tobj->peer = xferchan;
981 tobj->bconfig = *config;
983 if (ast_stream_and_wait(newchan, xfersound, newchan->language, ""))
984 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
985 ast_bridge_call_thread_launch(tobj);
986 return -1; /* XXX meaning the channel is bridged ? */
990 /* add atxfer and automon as undefined so you can only use em if you configure them */
991 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
993 AST_RWLOCK_DEFINE_STATIC(features_lock);
995 static struct ast_call_feature builtin_features[] =
997 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
998 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
999 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1000 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1001 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1005 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1007 /*! \brief register new feature into feature_list*/
1008 void ast_register_feature(struct ast_call_feature *feature)
1010 if (!feature) {
1011 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1012 return;
1015 AST_LIST_LOCK(&feature_list);
1016 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1017 AST_LIST_UNLOCK(&feature_list);
1019 if (option_verbose >= 2)
1020 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
1023 /*! \brief unregister feature from feature_list */
1024 void ast_unregister_feature(struct ast_call_feature *feature)
1026 if (!feature)
1027 return;
1029 AST_LIST_LOCK(&feature_list);
1030 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1031 AST_LIST_UNLOCK(&feature_list);
1032 free(feature);
1035 /*! \brief Remove all features in the list */
1036 static void ast_unregister_features(void)
1038 struct ast_call_feature *feature;
1040 AST_LIST_LOCK(&feature_list);
1041 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1042 free(feature);
1043 AST_LIST_UNLOCK(&feature_list);
1046 /*! \brief find a feature by name */
1047 static struct ast_call_feature *find_dynamic_feature(const char *name)
1049 struct ast_call_feature *tmp;
1051 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1052 if (!strcasecmp(tmp->sname, name))
1053 break;
1056 return tmp;
1059 /*! \brief exec an app by feature */
1060 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1062 struct ast_app *app;
1063 struct ast_call_feature *feature = data;
1064 struct ast_channel *work, *idle;
1065 int res;
1067 if (!feature) { /* shouldn't ever happen! */
1068 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1069 return -1;
1072 if (sense == FEATURE_SENSE_CHAN) {
1073 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1074 return FEATURE_RETURN_KEEPTRYING;
1075 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1076 work = chan;
1077 idle = peer;
1078 } else {
1079 work = peer;
1080 idle = chan;
1082 } else {
1083 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1084 return FEATURE_RETURN_KEEPTRYING;
1085 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1086 work = peer;
1087 idle = chan;
1088 } else {
1089 work = chan;
1090 idle = peer;
1094 if (!(app = pbx_findapp(feature->app))) {
1095 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1096 return -2;
1099 ast_autoservice_start(idle);
1101 if (!ast_strlen_zero(feature->moh_class))
1102 ast_moh_start(idle, feature->moh_class, NULL);
1104 res = pbx_exec(work, app, feature->app_args);
1106 if (!ast_strlen_zero(feature->moh_class))
1107 ast_moh_stop(idle);
1109 ast_autoservice_stop(idle);
1111 if (res == AST_PBX_KEEPALIVE) {
1112 /* do not hangup peer if feature is to be activated on it */
1113 if ((ast_test_flag(feature, AST_FEATURE_FLAG_ONPEER) && sense == FEATURE_SENSE_CHAN) || (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF) && sense == FEATURE_SENSE_PEER))
1114 return FEATURE_RETURN_NO_HANGUP_PEER;
1115 else
1116 return FEATURE_RETURN_PBX_KEEPALIVE;
1118 else if (res == AST_PBX_NO_HANGUP_PEER)
1119 return FEATURE_RETURN_NO_HANGUP_PEER;
1120 else if (res)
1121 return FEATURE_RETURN_SUCCESSBREAK;
1123 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1126 static void unmap_features(void)
1128 int x;
1130 ast_rwlock_wrlock(&features_lock);
1131 for (x = 0; x < FEATURES_COUNT; x++)
1132 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1133 ast_rwlock_unlock(&features_lock);
1136 static int remap_feature(const char *name, const char *value)
1138 int x, res = -1;
1140 ast_rwlock_wrlock(&features_lock);
1141 for (x = 0; x < FEATURES_COUNT; x++) {
1142 if (strcasecmp(builtin_features[x].sname, name))
1143 continue;
1145 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1146 res = 0;
1147 break;
1149 ast_rwlock_unlock(&features_lock);
1151 return res;
1154 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1156 int x;
1157 struct ast_flags features;
1158 struct ast_call_feature *feature;
1159 const char *dynamic_features;
1160 char *tmp, *tok;
1161 int res = FEATURE_RETURN_PASSDIGITS;
1162 int feature_detected = 0;
1164 if (sense == FEATURE_SENSE_CHAN) {
1165 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1166 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1167 } else {
1168 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1169 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
1171 if (option_debug > 2)
1172 ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
1174 ast_rwlock_rdlock(&features_lock);
1175 for (x = 0; x < FEATURES_COUNT; x++) {
1176 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1177 !ast_strlen_zero(builtin_features[x].exten)) {
1178 /* Feature is up for consideration */
1179 if (!strcmp(builtin_features[x].exten, code)) {
1180 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1181 feature_detected = 1;
1182 break;
1183 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1184 if (res == FEATURE_RETURN_PASSDIGITS)
1185 res = FEATURE_RETURN_STOREDIGITS;
1189 ast_rwlock_unlock(&features_lock);
1191 if (ast_strlen_zero(dynamic_features) || feature_detected)
1192 return res;
1194 tmp = ast_strdupa(dynamic_features);
1196 while ((tok = strsep(&tmp, "#"))) {
1197 AST_LIST_LOCK(&feature_list);
1198 if (!(feature = find_dynamic_feature(tok))) {
1199 AST_LIST_UNLOCK(&feature_list);
1200 continue;
1203 /* Feature is up for consideration */
1204 if (!strcmp(feature->exten, code)) {
1205 if (option_verbose > 2)
1206 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1207 res = feature->operation(chan, peer, config, code, sense, feature);
1208 if (res != FEATURE_RETURN_KEEPTRYING) {
1209 AST_LIST_UNLOCK(&feature_list);
1210 break;
1212 res = FEATURE_RETURN_PASSDIGITS;
1213 } else if (!strncmp(feature->exten, code, strlen(code)))
1214 res = FEATURE_RETURN_STOREDIGITS;
1216 AST_LIST_UNLOCK(&feature_list);
1219 return res;
1222 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1224 int x;
1226 ast_clear_flag(config, AST_FLAGS_ALL);
1228 ast_rwlock_rdlock(&features_lock);
1229 for (x = 0; x < FEATURES_COUNT; x++) {
1230 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1231 continue;
1233 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1234 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1236 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1237 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1239 ast_rwlock_unlock(&features_lock);
1241 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1242 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1244 if (dynamic_features) {
1245 char *tmp = ast_strdupa(dynamic_features);
1246 char *tok;
1247 struct ast_call_feature *feature;
1249 /* while we have a feature */
1250 while ((tok = strsep(&tmp, "#"))) {
1251 AST_LIST_LOCK(&feature_list);
1252 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1253 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1254 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1255 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1256 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1258 AST_LIST_UNLOCK(&feature_list);
1264 /*! \todo XXX Check - this is very similar to the code in channel.c */
1265 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, const char *language)
1267 int state = 0;
1268 int cause = 0;
1269 int to;
1270 struct ast_channel *chan;
1271 struct ast_channel *monitor_chans[2];
1272 struct ast_channel *active_channel;
1273 int res = 0, ready = 0;
1275 if ((chan = ast_request(type, format, data, &cause))) {
1276 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1277 ast_string_field_set(chan, language, language);
1278 ast_channel_inherit_variables(caller, chan);
1279 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1281 if (!ast_call(chan, data, timeout)) {
1282 struct timeval started;
1283 int x, len = 0;
1284 char *disconnect_code = NULL, *dialed_code = NULL;
1286 ast_indicate(caller, AST_CONTROL_RINGING);
1287 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1288 ast_rwlock_rdlock(&features_lock);
1289 for (x = 0; x < FEATURES_COUNT; x++) {
1290 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1291 continue;
1293 disconnect_code = builtin_features[x].exten;
1294 len = strlen(disconnect_code) + 1;
1295 dialed_code = alloca(len);
1296 memset(dialed_code, 0, len);
1297 break;
1299 ast_rwlock_unlock(&features_lock);
1300 x = 0;
1301 started = ast_tvnow();
1302 to = timeout;
1303 while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1304 struct ast_frame *f = NULL;
1306 monitor_chans[0] = caller;
1307 monitor_chans[1] = chan;
1308 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1310 /* see if the timeout has been violated */
1311 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1312 state = AST_CONTROL_UNHOLD;
1313 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1314 break; /*doh! timeout*/
1317 if (!active_channel)
1318 continue;
1320 if (chan && (chan == active_channel)){
1321 f = ast_read(chan);
1322 if (f == NULL) { /*doh! where'd he go?*/
1323 state = AST_CONTROL_HANGUP;
1324 res = 0;
1325 break;
1328 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1329 if (f->subclass == AST_CONTROL_RINGING) {
1330 state = f->subclass;
1331 if (option_verbose > 2)
1332 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1333 ast_indicate(caller, AST_CONTROL_RINGING);
1334 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1335 state = f->subclass;
1336 if (option_verbose > 2)
1337 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
1338 ast_indicate(caller, AST_CONTROL_BUSY);
1339 ast_frfree(f);
1340 f = NULL;
1341 break;
1342 } else if (f->subclass == AST_CONTROL_ANSWER) {
1343 /* This is what we are hoping for */
1344 state = f->subclass;
1345 ast_frfree(f);
1346 f = NULL;
1347 ready=1;
1348 break;
1349 } else if (f->subclass != -1) {
1350 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1352 /* else who cares */
1355 } else if (caller && (active_channel == caller)) {
1356 f = ast_read(caller);
1357 if (f == NULL) { /*doh! where'd he go?*/
1358 if (caller->_softhangup && !chan->_softhangup) {
1359 /* make this a blind transfer */
1360 ready = 1;
1361 break;
1363 state = AST_CONTROL_HANGUP;
1364 res = 0;
1365 break;
1368 if (f->frametype == AST_FRAME_DTMF) {
1369 dialed_code[x++] = f->subclass;
1370 dialed_code[x] = '\0';
1371 if (strlen(dialed_code) == len) {
1372 x = 0;
1373 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1374 x = 0;
1375 dialed_code[x] = '\0';
1377 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1378 /* Caller Canceled the call */
1379 state = AST_CONTROL_UNHOLD;
1380 ast_frfree(f);
1381 f = NULL;
1382 break;
1386 if (f)
1387 ast_frfree(f);
1388 } /* end while */
1389 } else
1390 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1391 } else {
1392 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1393 switch(cause) {
1394 case AST_CAUSE_BUSY:
1395 state = AST_CONTROL_BUSY;
1396 break;
1397 case AST_CAUSE_CONGESTION:
1398 state = AST_CONTROL_CONGESTION;
1399 break;
1403 ast_indicate(caller, -1);
1404 if (chan && ready) {
1405 if (chan->_state == AST_STATE_UP)
1406 state = AST_CONTROL_ANSWER;
1407 res = 0;
1408 } else if(chan) {
1409 res = -1;
1410 ast_hangup(chan);
1411 chan = NULL;
1412 } else {
1413 res = -1;
1416 if (outstate)
1417 *outstate = state;
1419 return chan;
1422 static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
1424 struct ast_cdr *cdr_orig = cdr;
1425 while (cdr) {
1426 if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
1427 return cdr;
1428 cdr = cdr->next;
1430 return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
1434 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1436 /* Copy voice back and forth between the two channels. Give the peer
1437 the ability to transfer calls with '#<extension' syntax. */
1438 struct ast_frame *f;
1439 struct ast_channel *who;
1440 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1441 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1442 char orig_channame[AST_MAX_EXTENSION];
1443 char orig_peername[AST_MAX_EXTENSION];
1445 int res;
1446 int diff;
1447 int hasfeatures=0;
1448 int hadfeatures=0;
1449 struct ast_option_header *aoh;
1450 struct ast_bridge_config backup_config;
1451 struct ast_cdr *bridge_cdr = NULL;
1452 struct ast_cdr *orig_peer_cdr = NULL;
1453 struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
1454 struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
1455 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
1456 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
1458 memset(&backup_config, 0, sizeof(backup_config));
1460 config->start_time = ast_tvnow();
1462 if (chan && peer) {
1463 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1464 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1465 } else if (chan)
1466 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1468 if (monitor_ok) {
1469 const char *monitor_exec;
1470 struct ast_channel *src = NULL;
1471 if (!monitor_app) {
1472 if (!(monitor_app = pbx_findapp("Monitor")))
1473 monitor_ok=0;
1475 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1476 src = chan;
1477 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1478 src = peer;
1479 if (monitor_app && src) {
1480 char *tmp = ast_strdupa(monitor_exec);
1481 pbx_exec(src, monitor_app, tmp);
1485 set_config_flags(chan, peer, config);
1486 config->firstpass = 1;
1488 /* Answer if need be */
1489 if (ast_answer(chan))
1490 return -1;
1492 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
1493 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
1494 orig_peer_cdr = peer_cdr;
1496 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
1498 if (chan_cdr) {
1499 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
1500 ast_cdr_update(chan);
1501 bridge_cdr = ast_cdr_dup(chan_cdr);
1502 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
1503 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
1504 } else {
1505 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
1506 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
1507 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
1508 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
1509 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
1510 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
1511 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
1512 ast_cdr_setcid(bridge_cdr, chan);
1513 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
1514 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
1515 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
1516 /* Destination information */
1517 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
1518 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
1519 if (peer_cdr) {
1520 bridge_cdr->start = peer_cdr->start;
1521 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
1522 } else {
1523 ast_cdr_start(bridge_cdr);
1526 /* peer_cdr->answer will be set when a macro runs on the peer;
1527 in that case, the bridge answer will be delayed while the
1528 macro plays on the peer channel. The peer answered the call
1529 before the macro started playing. To the phone system,
1530 this is billable time for the call, even tho the caller
1531 hears nothing but ringing while the macro does its thing. */
1532 if (peer_cdr && !ast_tvzero(peer_cdr->answer)) {
1533 bridge_cdr->answer = peer_cdr->answer;
1534 chan_cdr->answer = peer_cdr->answer;
1535 bridge_cdr->disposition = peer_cdr->disposition;
1536 chan_cdr->disposition = peer_cdr->disposition;
1537 } else {
1538 ast_cdr_answer(bridge_cdr);
1539 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
1541 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
1542 if (peer_cdr) {
1543 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
1547 for (;;) {
1548 struct ast_channel *other; /* used later */
1550 res = ast_channel_bridge(chan, peer, config, &f, &who);
1552 if (config->feature_timer) {
1553 /* Update time limit for next pass */
1554 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1555 config->feature_timer -= diff;
1556 if (hasfeatures) {
1557 /* Running on backup config, meaning a feature might be being
1558 activated, but that's no excuse to keep things going
1559 indefinitely! */
1560 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1561 if (option_debug)
1562 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1563 config->feature_timer = 0;
1564 who = chan;
1565 if (f)
1566 ast_frfree(f);
1567 f = NULL;
1568 res = 0;
1569 } else if (config->feature_timer <= 0) {
1570 /* Not *really* out of time, just out of time for
1571 digits to come in for features. */
1572 if (option_debug)
1573 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1574 if (!ast_strlen_zero(peer_featurecode)) {
1575 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1576 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1578 if (!ast_strlen_zero(chan_featurecode)) {
1579 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1580 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1582 if (f)
1583 ast_frfree(f);
1584 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1585 if (!hasfeatures) {
1586 /* Restore original (possibly time modified) bridge config */
1587 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1588 memset(&backup_config, 0, sizeof(backup_config));
1590 hadfeatures = hasfeatures;
1591 /* Continue as we were */
1592 continue;
1593 } else if (!f) {
1594 /* The bridge returned without a frame and there is a feature in progress.
1595 * However, we don't think the feature has quite yet timed out, so just
1596 * go back into the bridge. */
1597 continue;
1599 } else {
1600 if (config->feature_timer <=0) {
1601 /* We ran out of time */
1602 config->feature_timer = 0;
1603 who = chan;
1604 if (f)
1605 ast_frfree(f);
1606 f = NULL;
1607 res = 0;
1611 if (res < 0) {
1612 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
1613 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1614 goto before_you_go;
1617 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1618 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1619 f->subclass == AST_CONTROL_CONGESTION ) ) ) {
1620 res = -1;
1621 break;
1623 /* many things should be sent to the 'other' channel */
1624 other = (who == chan) ? peer : chan;
1625 if (f->frametype == AST_FRAME_CONTROL) {
1626 switch (f->subclass) {
1627 case AST_CONTROL_RINGING:
1628 case AST_CONTROL_FLASH:
1629 case -1:
1630 ast_indicate(other, f->subclass);
1631 break;
1632 case AST_CONTROL_HOLD:
1633 case AST_CONTROL_UNHOLD:
1634 ast_indicate_data(other, f->subclass, f->data, f->datalen);
1635 break;
1636 case AST_CONTROL_OPTION:
1637 aoh = f->data;
1638 /* Forward option Requests */
1639 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
1640 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
1641 f->datalen - sizeof(struct ast_option_header), 0);
1643 break;
1645 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1646 /* eat it */
1647 } else if (f->frametype == AST_FRAME_DTMF) {
1648 char *featurecode;
1649 int sense;
1651 hadfeatures = hasfeatures;
1652 /* This cannot overrun because the longest feature is one shorter than our buffer */
1653 if (who == chan) {
1654 sense = FEATURE_SENSE_CHAN;
1655 featurecode = chan_featurecode;
1656 } else {
1657 sense = FEATURE_SENSE_PEER;
1658 featurecode = peer_featurecode;
1660 /*! append the event to featurecode. we rely on the string being zero-filled, and
1661 * not overflowing it.
1662 * \todo XXX how do we guarantee the latter ?
1664 featurecode[strlen(featurecode)] = f->subclass;
1665 /* Get rid of the frame before we start doing "stuff" with the channels */
1666 ast_frfree(f);
1667 f = NULL;
1668 config->feature_timer = backup_config.feature_timer;
1669 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1670 switch(res) {
1671 case FEATURE_RETURN_PASSDIGITS:
1672 ast_dtmf_stream(other, who, featurecode, 0);
1673 /* Fall through */
1674 case FEATURE_RETURN_SUCCESS:
1675 memset(featurecode, 0, sizeof(chan_featurecode));
1676 break;
1678 if (res >= FEATURE_RETURN_PASSDIGITS) {
1679 res = 0;
1680 } else
1681 break;
1682 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1683 if (hadfeatures && !hasfeatures) {
1684 /* Restore backup */
1685 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1686 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1687 } else if (hasfeatures) {
1688 if (!hadfeatures) {
1689 /* Backup configuration */
1690 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1691 /* Setup temporary config options */
1692 config->play_warning = 0;
1693 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1694 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1695 config->warning_freq = 0;
1696 config->warning_sound = NULL;
1697 config->end_sound = NULL;
1698 config->start_sound = NULL;
1699 config->firstpass = 0;
1701 config->start_time = ast_tvnow();
1702 config->feature_timer = featuredigittimeout;
1703 if (option_debug)
1704 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1707 if (f)
1708 ast_frfree(f);
1711 before_you_go:
1712 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
1713 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
1715 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
1716 struct ast_cdr *swapper;
1717 char savelastapp[AST_MAX_EXTENSION];
1718 char savelastdata[AST_MAX_EXTENSION];
1719 char save_exten[AST_MAX_EXTENSION];
1720 int save_prio;
1722 if (ast_opt_end_cdr_before_h_exten) {
1723 ast_cdr_end(bridge_cdr);
1725 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
1726 dialplan code operate on it */
1727 swapper = chan->cdr;
1728 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
1729 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
1730 ast_channel_lock(chan);
1731 chan->cdr = bridge_cdr;
1732 ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
1733 ast_copy_string(chan->exten, "h", sizeof(chan->exten));
1734 save_prio = chan->priority;
1735 chan->priority = 1;
1736 ast_channel_unlock(chan);
1737 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
1738 if (ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
1739 /* Something bad happened, or a hangup has been requested. */
1740 if (option_debug)
1741 ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
1742 if (option_verbose > 1)
1743 ast_verbose( VERBOSE_PREFIX_2 "Spawn h extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
1744 break;
1746 chan->priority++;
1748 /* swap it back */
1749 ast_channel_lock(chan);
1750 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
1751 chan->priority = save_prio;
1752 chan->cdr = swapper;
1753 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
1754 ast_channel_unlock(chan);
1755 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
1756 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
1757 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
1760 /* obey the NoCDR() wishes. */
1761 if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
1762 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
1763 if (!new_chan_cdr || (new_chan_cdr && !ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
1764 struct ast_channel *chan_ptr = NULL;
1766 ast_cdr_end(bridge_cdr);
1768 ast_cdr_detach(bridge_cdr);
1770 /* do a specialized reset on the beginning channel
1771 CDR's, if they still exist, so as not to mess up
1772 issues in future bridges;
1774 Here are the rules of the game:
1775 1. The chan and peer channel pointers will not change
1776 during the life of the bridge.
1777 2. But, in transfers, the channel names will change.
1778 between the time the bridge is started, and the
1779 time the channel ends.
1780 Usually, when a channel changes names, it will
1781 also change CDR pointers.
1782 3. Usually, only one of the two channels (chan or peer)
1783 will change names.
1784 4. Usually, if a channel changes names during a bridge,
1785 it is because of a transfer. Usually, in these situations,
1786 it is normal to see 2 bridges running simultaneously, and
1787 it is not unusual to see the two channels that change
1788 swapped between bridges.
1789 5. After a bridge occurs, we have 2 or 3 channels' CDRs
1790 to attend to; if the chan or peer changed names,
1791 we have the before and after attached CDR's.
1794 if (strcasecmp(orig_channame, chan->name) != 0) {
1795 /* old channel */
1796 chan_ptr = ast_get_channel_by_name_locked(orig_channame);
1797 if (chan_ptr) {
1798 if (!ast_bridged_channel(chan_ptr)) {
1799 struct ast_cdr *cur;
1800 for (cur = chan_ptr->cdr; cur; cur = cur->next) {
1801 if (cur == chan_cdr) {
1802 break;
1805 if (cur)
1806 ast_cdr_specialized_reset(chan_cdr,0);
1808 ast_channel_unlock(chan_ptr);
1810 /* new channel */
1811 ast_cdr_specialized_reset(new_chan_cdr,0);
1812 } else {
1813 ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */
1815 if (strcasecmp(orig_peername, peer->name) != 0) {
1816 /* old channel */
1817 chan_ptr = ast_get_channel_by_name_locked(orig_peername);
1818 if (chan_ptr) {
1819 if (!ast_bridged_channel(chan_ptr)) {
1820 struct ast_cdr *cur;
1821 for (cur = chan_ptr->cdr; cur; cur = cur->next) {
1822 if (cur == peer_cdr) {
1823 break;
1826 if (cur)
1827 ast_cdr_specialized_reset(peer_cdr,0);
1829 ast_channel_unlock(chan_ptr);
1831 /* new channel */
1832 ast_cdr_specialized_reset(new_peer_cdr,0);
1833 } else {
1834 ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */
1837 return res;
1840 static void post_manager_event(const char *s, char *parkingexten, struct ast_channel *chan)
1842 manager_event(EVENT_FLAG_CALL, s,
1843 "Exten: %s\r\n"
1844 "Channel: %s\r\n"
1845 "CallerID: %s\r\n"
1846 "CallerIDName: %s\r\n\r\n",
1847 parkingexten,
1848 chan->name,
1849 S_OR(chan->cid.cid_num, "<unknown>"),
1850 S_OR(chan->cid.cid_name, "<unknown>")
1854 /*! \brief Take care of parked calls and unpark them if needed */
1855 static void *do_parking_thread(void *ignore)
1857 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
1858 FD_ZERO(&rfds);
1859 FD_ZERO(&efds);
1861 for (;;) {
1862 struct parkeduser *pu, *pl, *pt = NULL;
1863 int ms = -1; /* select timeout, uninitialized */
1864 int max = -1; /* max fd, none there yet */
1865 fd_set nrfds, nefds; /* args for the next select */
1866 FD_ZERO(&nrfds);
1867 FD_ZERO(&nefds);
1869 ast_mutex_lock(&parking_lock);
1870 pl = NULL;
1871 pu = parkinglot;
1872 /* navigate the list with prev-cur pointers to support removals */
1873 while (pu) {
1874 struct ast_channel *chan = pu->chan; /* shorthand */
1875 int tms; /* timeout for this item */
1876 int x; /* fd index in channel */
1877 struct ast_context *con;
1879 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
1880 pl = pu;
1881 pu = pu->next;
1882 continue;
1884 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1885 if (tms > pu->parkingtime) {
1886 ast_indicate(chan, AST_CONTROL_UNHOLD);
1887 /* Get chan, exten from derived kludge */
1888 if (pu->peername[0]) {
1889 char *peername = ast_strdupa(pu->peername);
1890 char *cp = strrchr(peername, '-');
1891 if (cp)
1892 *cp = 0;
1893 con = ast_context_find(parking_con_dial);
1894 if (!con) {
1895 con = ast_context_create(NULL, parking_con_dial, registrar);
1896 if (!con)
1897 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1899 if (con) {
1900 char returnexten[AST_MAX_EXTENSION];
1901 struct ast_datastore *features_datastore;
1902 struct ast_dial_features *dialfeatures = NULL;
1904 ast_channel_lock(chan);
1906 if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
1907 dialfeatures = features_datastore->data;
1909 ast_channel_unlock(chan);
1911 if (dialfeatures)
1912 snprintf(returnexten, sizeof(returnexten), "%s|30|%s", peername, dialfeatures->options);
1913 else /* Existing default */
1914 snprintf(returnexten, sizeof(returnexten), "%s|30|t", peername);
1916 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
1918 set_c_e_p(chan, parking_con_dial, peername, 1);
1919 } else {
1920 /* They've been waiting too long, send them back to where they came. Theoretically they
1921 should have their original extensions and such, but we copy to be on the safe side */
1922 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1925 post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
1927 if (option_verbose > 1)
1928 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);
1929 /* Start up the PBX, or hang them up */
1930 if (ast_pbx_start(chan)) {
1931 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1932 ast_hangup(chan);
1934 /* And take them out of the parking lot */
1935 if (pl)
1936 pl->next = pu->next;
1937 else
1938 parkinglot = pu->next;
1939 pt = pu;
1940 pu = pu->next;
1941 con = ast_context_find(parking_con);
1942 if (con) {
1943 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1944 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1945 else
1946 notify_metermaids(pt->parkingexten, parking_con);
1947 } else
1948 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1949 free(pt);
1950 } else { /* still within parking time, process descriptors */
1951 for (x = 0; x < AST_MAX_FDS; x++) {
1952 struct ast_frame *f;
1954 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1955 continue; /* nothing on this descriptor */
1957 if (FD_ISSET(chan->fds[x], &efds))
1958 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1959 else
1960 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1961 chan->fdno = x;
1963 /* See if they need servicing */
1964 f = ast_read(chan);
1965 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
1966 if (f)
1967 ast_frfree(f);
1968 post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
1970 /* There's a problem, hang them up*/
1971 if (option_verbose > 1)
1972 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1973 ast_hangup(chan);
1974 /* And take them out of the parking lot */
1975 if (pl)
1976 pl->next = pu->next;
1977 else
1978 parkinglot = pu->next;
1979 pt = pu;
1980 pu = pu->next;
1981 con = ast_context_find(parking_con);
1982 if (con) {
1983 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1984 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1985 else {
1986 notify_metermaids(pt->parkingexten, parking_con);
1988 } else
1989 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1990 free(pt);
1991 break;
1992 } else {
1993 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1994 ast_frfree(f);
1995 if (pu->moh_trys < 3 && !chan->generatordata) {
1996 if (option_debug)
1997 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
1998 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
1999 S_OR(parkmohclass, NULL),
2000 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
2001 pu->moh_trys++;
2003 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
2006 } /* end for */
2007 if (x >= AST_MAX_FDS) {
2008 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2009 if (chan->fds[x] > -1) {
2010 FD_SET(chan->fds[x], &nrfds);
2011 FD_SET(chan->fds[x], &nefds);
2012 if (chan->fds[x] > max)
2013 max = chan->fds[x];
2016 /* Keep track of our shortest wait */
2017 if (tms < ms || ms < 0)
2018 ms = tms;
2019 pl = pu;
2020 pu = pu->next;
2023 } /* end while */
2024 ast_mutex_unlock(&parking_lock);
2025 rfds = nrfds;
2026 efds = nefds;
2028 struct timeval tv = ast_samp2tv(ms, 1000);
2029 /* Wait for something to happen */
2030 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2032 pthread_testcancel();
2034 return NULL; /* Never reached */
2037 /*! \brief Park a call */
2038 static int park_call_exec(struct ast_channel *chan, void *data)
2040 /* Cache the original channel name in case we get masqueraded in the middle
2041 * of a park--it is still theoretically possible for a transfer to happen before
2042 * we get here, but it is _really_ unlikely */
2043 char *orig_chan_name = ast_strdupa(chan->name);
2044 char orig_exten[AST_MAX_EXTENSION];
2045 int orig_priority = chan->priority;
2047 /* Data is unused at the moment but could contain a parking
2048 lot context eventually */
2049 int res = 0;
2050 struct ast_module_user *u;
2052 u = ast_module_user_add(chan);
2054 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
2056 /* Setup the exten/priority to be s/1 since we don't know
2057 where this call should return */
2058 strcpy(chan->exten, "s");
2059 chan->priority = 1;
2060 /* Answer if call is not up */
2061 if (chan->_state != AST_STATE_UP)
2062 res = ast_answer(chan);
2063 /* Sleep to allow VoIP streams to settle down */
2064 if (!res)
2065 res = ast_safe_sleep(chan, 1000);
2066 /* Park the call */
2067 if (!res) {
2068 res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
2069 /* Continue on in the dialplan */
2070 if (res == 1) {
2071 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
2072 chan->priority = orig_priority;
2073 res = 0;
2074 } else if (!res)
2075 res = AST_PBX_KEEPALIVE;
2078 ast_module_user_remove(u);
2080 return res;
2083 /*! \brief Pickup parked call */
2084 static int park_exec(struct ast_channel *chan, void *data)
2086 int res = 0;
2087 struct ast_module_user *u;
2088 struct ast_channel *peer=NULL;
2089 struct parkeduser *pu, *pl=NULL;
2090 struct ast_context *con;
2092 int park;
2093 struct ast_bridge_config config;
2095 if (!data) {
2096 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
2097 return -1;
2100 u = ast_module_user_add(chan);
2102 park = atoi((char *)data);
2103 ast_mutex_lock(&parking_lock);
2104 pu = parkinglot;
2105 while(pu) {
2106 if (pu->parkingnum == park) {
2107 if (pu->chan->pbx) { /* do not allow call to be picked up until the PBX thread is finished */
2108 ast_mutex_unlock(&parking_lock);
2109 ast_module_user_remove(u);
2110 return -1;
2112 if (pl)
2113 pl->next = pu->next;
2114 else
2115 parkinglot = pu->next;
2116 break;
2118 pl = pu;
2119 pu = pu->next;
2121 ast_mutex_unlock(&parking_lock);
2122 if (pu) {
2123 peer = pu->chan;
2124 con = ast_context_find(parking_con);
2125 if (con) {
2126 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2127 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2128 else
2129 notify_metermaids(pu->parkingexten, parking_con);
2130 } else
2131 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2133 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2134 "Exten: %s\r\n"
2135 "Channel: %s\r\n"
2136 "From: %s\r\n"
2137 "CallerID: %s\r\n"
2138 "CallerIDName: %s\r\n",
2139 pu->parkingexten, pu->chan->name, chan->name,
2140 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2141 S_OR(pu->chan->cid.cid_name, "<unknown>")
2144 free(pu);
2146 /* JK02: it helps to answer the channel if not already up */
2147 if (chan->_state != AST_STATE_UP)
2148 ast_answer(chan);
2150 if (peer) {
2151 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2153 if (!ast_strlen_zero(courtesytone)) {
2154 int error = 0;
2155 ast_indicate(peer, AST_CONTROL_UNHOLD);
2156 if (parkedplay == 0) {
2157 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
2158 } else if (parkedplay == 1) {
2159 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
2160 } else if (parkedplay == 2) {
2161 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2162 !ast_streamfile(peer, courtesytone, chan->language)) {
2163 /*! \todo XXX we would like to wait on both! */
2164 res = ast_waitstream(chan, "");
2165 if (res >= 0)
2166 res = ast_waitstream(peer, "");
2167 if (res < 0)
2168 error = 1;
2171 if (error) {
2172 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2173 ast_hangup(peer);
2174 ast_module_user_remove(u);
2175 return -1;
2177 } else
2178 ast_indicate(peer, AST_CONTROL_UNHOLD);
2180 res = ast_channel_make_compatible(chan, peer);
2181 if (res < 0) {
2182 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2183 ast_hangup(peer);
2184 ast_module_user_remove(u);
2185 return -1;
2187 /* This runs sorta backwards, since we give the incoming channel control, as if it
2188 were the person called. */
2189 if (option_verbose > 2)
2190 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
2192 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2193 ast_cdr_setdestchan(chan->cdr, peer->name);
2194 memset(&config, 0, sizeof(struct ast_bridge_config));
2195 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2196 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2197 res = ast_bridge_call(chan, peer, &config);
2199 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2200 ast_cdr_setdestchan(chan->cdr, peer->name);
2202 /* Simulate the PBX hanging up */
2203 if (res != AST_PBX_NO_HANGUP_PEER)
2204 ast_hangup(peer);
2205 ast_module_user_remove(u);
2206 return res;
2207 } else {
2208 /*! \todo XXX Play a message XXX */
2209 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
2210 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2211 if (option_verbose > 2)
2212 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2213 res = -1;
2216 ast_module_user_remove(u);
2218 return res;
2221 static int handle_showfeatures(int fd, int argc, char *argv[])
2223 int i;
2224 struct ast_call_feature *feature;
2225 char format[] = "%-25s %-7s %-7s\n";
2227 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
2228 ast_cli(fd, format, "---------------", "-------", "-------");
2230 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2232 ast_rwlock_rdlock(&features_lock);
2233 for (i = 0; i < FEATURES_COUNT; i++)
2234 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2235 ast_rwlock_unlock(&features_lock);
2237 ast_cli(fd, "\n");
2238 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
2239 ast_cli(fd, format, "---------------", "-------", "-------");
2240 if (AST_LIST_EMPTY(&feature_list))
2241 ast_cli(fd, "(none)\n");
2242 else {
2243 AST_LIST_LOCK(&feature_list);
2244 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2245 ast_cli(fd, format, feature->sname, "no def", feature->exten);
2246 AST_LIST_UNLOCK(&feature_list);
2248 ast_cli(fd, "\nCall parking\n");
2249 ast_cli(fd, "------------\n");
2250 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
2251 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
2252 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2253 ast_cli(fd,"\n");
2255 return RESULT_SUCCESS;
2258 static char showfeatures_help[] =
2259 "Usage: feature list\n"
2260 " Lists currently configured features.\n";
2262 static int handle_parkedcalls(int fd, int argc, char *argv[])
2264 struct parkeduser *cur;
2265 int numparked = 0;
2267 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2268 , "Context", "Extension", "Pri", "Timeout");
2270 ast_mutex_lock(&parking_lock);
2272 for (cur = parkinglot; cur; cur = cur->next) {
2273 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2274 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2275 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2277 numparked++;
2279 ast_mutex_unlock(&parking_lock);
2280 ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
2283 return RESULT_SUCCESS;
2286 static char showparked_help[] =
2287 "Usage: show parkedcalls\n"
2288 " Lists currently parked calls.\n";
2290 static struct ast_cli_entry cli_show_features_deprecated = {
2291 { "show", "features", NULL },
2292 handle_showfeatures, NULL,
2293 NULL };
2295 static struct ast_cli_entry cli_features[] = {
2296 { { "feature", "show", NULL },
2297 handle_showfeatures, "Lists configured features",
2298 showfeatures_help, NULL, &cli_show_features_deprecated },
2300 { { "show", "parkedcalls", NULL },
2301 handle_parkedcalls, "Lists parked calls",
2302 showparked_help },
2305 /*! \brief Dump lot status */
2306 static int manager_parking_status( struct mansession *s, const struct message *m)
2308 struct parkeduser *cur;
2309 const char *id = astman_get_header(m, "ActionID");
2310 char idText[256] = "";
2312 if (!ast_strlen_zero(id))
2313 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2315 astman_send_ack(s, m, "Parked calls will follow");
2317 ast_mutex_lock(&parking_lock);
2319 for (cur = parkinglot; cur; cur = cur->next) {
2320 astman_append(s, "Event: ParkedCall\r\n"
2321 "Exten: %d\r\n"
2322 "Channel: %s\r\n"
2323 "From: %s\r\n"
2324 "Timeout: %ld\r\n"
2325 "CallerID: %s\r\n"
2326 "CallerIDName: %s\r\n"
2327 "%s"
2328 "\r\n",
2329 cur->parkingnum, cur->chan->name, cur->peername,
2330 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2331 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
2332 S_OR(cur->chan->cid.cid_name, ""),
2333 idText);
2336 astman_append(s,
2337 "Event: ParkedCallsComplete\r\n"
2338 "%s"
2339 "\r\n",idText);
2341 ast_mutex_unlock(&parking_lock);
2343 return RESULT_SUCCESS;
2346 static char mandescr_park[] =
2347 "Description: Park a channel.\n"
2348 "Variables: (Names marked with * are required)\n"
2349 " *Channel: Channel name to park\n"
2350 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
2351 " Timeout: Number of milliseconds to wait before callback.\n";
2353 static int manager_park(struct mansession *s, const struct message *m)
2355 const char *channel = astman_get_header(m, "Channel");
2356 const char *channel2 = astman_get_header(m, "Channel2");
2357 const char *timeout = astman_get_header(m, "Timeout");
2358 char buf[BUFSIZ];
2359 int to = 0;
2360 int res = 0;
2361 int parkExt = 0;
2362 struct ast_channel *ch1, *ch2;
2364 if (ast_strlen_zero(channel)) {
2365 astman_send_error(s, m, "Channel not specified");
2366 return 0;
2369 if (ast_strlen_zero(channel2)) {
2370 astman_send_error(s, m, "Channel2 not specified");
2371 return 0;
2374 ch1 = ast_get_channel_by_name_locked(channel);
2375 if (!ch1) {
2376 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2377 astman_send_error(s, m, buf);
2378 return 0;
2381 ch2 = ast_get_channel_by_name_locked(channel2);
2382 if (!ch2) {
2383 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2384 astman_send_error(s, m, buf);
2385 ast_channel_unlock(ch1);
2386 return 0;
2389 if (!ast_strlen_zero(timeout)) {
2390 sscanf(timeout, "%d", &to);
2393 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2394 if (!res) {
2395 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2396 astman_send_ack(s, m, "Park successful");
2397 } else {
2398 astman_send_error(s, m, "Park failure");
2401 ast_channel_unlock(ch1);
2402 ast_channel_unlock(ch2);
2404 return 0;
2408 int ast_pickup_call(struct ast_channel *chan)
2410 struct ast_channel *cur = NULL;
2411 int res = -1;
2413 while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
2414 if (!cur->pbx &&
2415 (cur != chan) &&
2416 (chan->pickupgroup & cur->callgroup) &&
2417 ((cur->_state == AST_STATE_RINGING) ||
2418 (cur->_state == AST_STATE_RING))) {
2419 break;
2421 ast_channel_unlock(cur);
2423 if (cur) {
2424 if (option_debug)
2425 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2426 res = ast_answer(chan);
2427 if (res)
2428 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2429 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2430 if (res)
2431 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2432 res = ast_channel_masquerade(cur, chan);
2433 if (res)
2434 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
2435 ast_channel_unlock(cur);
2436 } else {
2437 if (option_debug)
2438 ast_log(LOG_DEBUG, "No call pickup possible...\n");
2440 return res;
2443 /*! \brief Add parking hints for all defined parking lots */
2444 static void park_add_hints(char *context, int start, int stop)
2446 int numext;
2447 char device[AST_MAX_EXTENSION];
2448 char exten[10];
2450 for (numext = start; numext <= stop; numext++) {
2451 snprintf(exten, sizeof(exten), "%d", numext);
2452 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2453 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2458 static int load_config(void)
2460 int start = 0, end = 0;
2461 int res;
2462 struct ast_context *con = NULL;
2463 struct ast_config *cfg = NULL;
2464 struct ast_variable *var = NULL;
2465 char old_parking_ext[AST_MAX_EXTENSION];
2466 char old_parking_con[AST_MAX_EXTENSION] = "";
2468 if (!ast_strlen_zero(parking_con)) {
2469 strcpy(old_parking_ext, parking_ext);
2470 strcpy(old_parking_con, parking_con);
2473 /* Reset to defaults */
2474 strcpy(parking_con, "parkedcalls");
2475 strcpy(parking_con_dial, "park-dial");
2476 strcpy(parking_ext, "700");
2477 strcpy(pickup_ext, "*8");
2478 strcpy(parkmohclass, "default");
2479 courtesytone[0] = '\0';
2480 strcpy(xfersound, "beep");
2481 strcpy(xferfailsound, "pbx-invalid");
2482 parking_start = 701;
2483 parking_stop = 750;
2484 parkfindnext = 0;
2485 adsipark = 0;
2486 parkaddhints = 0;
2488 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2489 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2490 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2492 cfg = ast_config_load("features.conf");
2493 if (!cfg) {
2494 ast_log(LOG_WARNING,"Could not load features.conf\n");
2495 return AST_MODULE_LOAD_DECLINE;
2497 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2498 if (!strcasecmp(var->name, "parkext")) {
2499 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2500 } else if (!strcasecmp(var->name, "context")) {
2501 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2502 } else if (!strcasecmp(var->name, "parkingtime")) {
2503 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2504 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2505 parkingtime = DEFAULT_PARK_TIME;
2506 } else
2507 parkingtime = parkingtime * 1000;
2508 } else if (!strcasecmp(var->name, "parkpos")) {
2509 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2510 ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
2511 } else {
2512 parking_start = start;
2513 parking_stop = end;
2515 } else if (!strcasecmp(var->name, "findslot")) {
2516 parkfindnext = (!strcasecmp(var->value, "next"));
2517 } else if (!strcasecmp(var->name, "parkinghints")) {
2518 parkaddhints = ast_true(var->value);
2519 } else if (!strcasecmp(var->name, "adsipark")) {
2520 adsipark = ast_true(var->value);
2521 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2522 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2523 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2524 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2525 } else
2526 transferdigittimeout = transferdigittimeout * 1000;
2527 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2528 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2529 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2530 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2532 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2533 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2534 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2535 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2536 } else
2537 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2538 } else if (!strcasecmp(var->name, "courtesytone")) {
2539 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2540 } else if (!strcasecmp(var->name, "parkedplay")) {
2541 if (!strcasecmp(var->value, "both"))
2542 parkedplay = 2;
2543 else if (!strcasecmp(var->value, "parked"))
2544 parkedplay = 1;
2545 else
2546 parkedplay = 0;
2547 } else if (!strcasecmp(var->name, "xfersound")) {
2548 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2549 } else if (!strcasecmp(var->name, "xferfailsound")) {
2550 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2551 } else if (!strcasecmp(var->name, "pickupexten")) {
2552 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2553 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2554 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2558 unmap_features();
2559 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2560 if (remap_feature(var->name, var->value))
2561 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2564 /* Map a key combination to an application*/
2565 ast_unregister_features();
2566 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2567 char *tmp_val = ast_strdupa(var->value);
2568 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2569 struct ast_call_feature *feature;
2571 /* strsep() sets the argument to NULL if match not found, and it
2572 * is safe to use it with a NULL argument, so we don't check
2573 * between calls.
2575 exten = strsep(&tmp_val,",");
2576 activatedby = strsep(&tmp_val,",");
2577 app = strsep(&tmp_val,",");
2578 app_args = strsep(&tmp_val,",");
2579 moh_class = strsep(&tmp_val,",");
2581 activateon = strsep(&activatedby, "/");
2583 /*! \todo XXX var_name or app_args ? */
2584 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2585 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2586 app, exten, activateon, var->name);
2587 continue;
2590 AST_LIST_LOCK(&feature_list);
2591 if ((feature = find_dynamic_feature(var->name))) {
2592 AST_LIST_UNLOCK(&feature_list);
2593 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2594 continue;
2596 AST_LIST_UNLOCK(&feature_list);
2598 if (!(feature = ast_calloc(1, sizeof(*feature))))
2599 continue;
2601 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2602 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2603 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2605 if (app_args)
2606 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2608 if (moh_class)
2609 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2611 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2612 feature->operation = feature_exec_app;
2613 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2615 /* Allow caller and calle to be specified for backwards compatability */
2616 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2617 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2618 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2619 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2620 else {
2621 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2622 " must be 'self', or 'peer'\n", var->name);
2623 continue;
2626 if (ast_strlen_zero(activatedby))
2627 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2628 else if (!strcasecmp(activatedby, "caller"))
2629 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2630 else if (!strcasecmp(activatedby, "callee"))
2631 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2632 else if (!strcasecmp(activatedby, "both"))
2633 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2634 else {
2635 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2636 " must be 'caller', or 'callee', or 'both'\n", var->name);
2637 continue;
2640 ast_register_feature(feature);
2642 if (option_verbose >= 1)
2643 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2645 ast_config_destroy(cfg);
2647 /* Remove the old parking extension */
2648 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2649 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2650 notify_metermaids(old_parking_ext, old_parking_con);
2651 if (option_debug)
2652 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2655 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2656 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2657 return -1;
2659 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2660 if (parkaddhints)
2661 park_add_hints(parking_con, parking_start, parking_stop);
2662 if (!res)
2663 notify_metermaids(ast_parking_ext(), parking_con);
2664 return res;
2668 static int reload(void)
2670 return load_config();
2673 static int load_module(void)
2675 int res;
2677 memset(parking_ext, 0, sizeof(parking_ext));
2678 memset(parking_con, 0, sizeof(parking_con));
2680 if ((res = load_config()))
2681 return res;
2682 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2683 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2684 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2685 if (!res)
2686 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2687 if (!res) {
2688 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2689 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2690 "Park a channel", mandescr_park);
2693 res |= ast_devstate_prov_add("Park", metermaidstate);
2695 return res;
2699 static int unload_module(void)
2701 ast_module_user_hangup_all();
2703 ast_manager_unregister("ParkedCalls");
2704 ast_manager_unregister("Park");
2705 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2706 ast_unregister_application(parkcall);
2707 ast_devstate_prov_del("Park");
2708 return ast_unregister_application(parkedcall);
2711 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
2712 .load = load_module,
2713 .unload = unload_module,
2714 .reload = reload,