Command-line application HoldedCalls
[asterisk-bristuff.git] / res / res_features.c
blob8b49dd450329901d12d3459797333afe8bb0e779
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 /*! size of the uniqueid field
74 * \todo Originally bristuff defines this one in channel.h but only uses it here.
76 #define AST_MAX_UNIQUEID 64
78 #define AST_MAX_WATCHERS 256
80 enum {
81 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
82 AST_FEATURE_FLAG_ONPEER = (1 << 1),
83 AST_FEATURE_FLAG_ONSELF = (1 << 2),
84 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
85 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
86 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
89 static char *parkedcall = "ParkedCall";
90 static char *holdedcall = "HoldedCall";
92 static int parkaddhints = 0; /*!< Add parking hints automatically */
93 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
94 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
95 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
96 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
97 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
98 static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
99 static int parking_start; /*!< First available extension for parking */
100 static int parking_stop; /*!< Last available extension for parking */
102 static char courtesytone[256]; /*!< Courtesy tone */
103 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
104 static char xfersound[256]; /*!< Call transfer sound */
105 static char xferfailsound[256]; /*!< Call transfer failure sound */
107 static int parking_offset;
108 static int parkfindnext;
110 static int adsipark;
112 static int transferdigittimeout;
113 static int featuredigittimeout;
115 static int atxfernoanswertimeout;
117 static char *registrar = "res_features"; /*!< Registrar for operations */
119 /* module and CLI command definitions */
120 static char *synopsis = "Answer a parked call";
122 static char *descrip = "ParkedCall(exten):"
123 "Used to connect to a parked call. This application is always\n"
124 "registered internally and does not need to be explicitly added\n"
125 "into the dialplan, although you should include the 'parkedcalls'\n"
126 "context.\n";
128 static char *parkcall = "Park";
130 static char *synopsis2 = "Park yourself";
132 static char *descrip2 = "Park():"
133 "Used to park yourself (typically in combination with a supervised\n"
134 "transfer to know the parking space). This application is always\n"
135 "registered internally and does not need to be explicitly added\n"
136 "into the dialplan, although you should include the 'parkedcalls'\n"
137 "context (or the context specified in features.conf).\n\n"
138 "If you set the PARKINGEXTEN variable to an extension in your\n"
139 "parking context, park() will park the call on that extension, unless\n"
140 "it already exists. In that case, execution will continue at next\n"
141 "priority.\n" ;
143 static struct ast_app *monitor_app = NULL;
144 static int monitor_ok = 1;
146 struct parkeduser {
147 struct ast_channel *chan; /*!< Parking channel */
148 struct timeval start; /*!< Time the parking started */
149 int parkingnum; /*!< Parking lot */
150 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
151 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
152 char exten[AST_MAX_EXTENSION];
153 int priority;
154 int parkingtime; /*!< Maximum length in parking lot before return */
155 int notquiteyet;
156 char peername[1024];
157 unsigned char moh_trys;
158 struct parkeduser *next;
161 struct holdeduser {
162 struct ast_channel *chan;
163 struct timeval start;
164 int parkingnum;
165 int cref;
166 int tei;
167 /* Where to go if our parking time expires */
168 char context[AST_MAX_EXTENSION];
169 char exten[AST_MAX_EXTENSION];
170 int priority;
171 int parkingtime;
172 char uniqueid[AST_MAX_UNIQUEID];
173 char uniqueidpeer[AST_MAX_UNIQUEID];
174 struct holdeduser *next;
177 static struct parkeduser *parkinglot;
179 static struct holdeduser *holdlist;
181 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
183 AST_MUTEX_DEFINE_STATIC(holding_lock);
185 static pthread_t parking_thread;
187 static pthread_t holding_thread;
189 char *ast_parking_ext(void)
191 return parking_ext;
194 char *ast_pickup_ext(void)
196 return pickup_ext;
199 struct ast_bridge_thread_obj
201 struct ast_bridge_config bconfig;
202 struct ast_channel *chan;
203 struct ast_channel *peer;
208 /*! \brief store context, priority and extension */
209 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
211 ast_copy_string(chan->context, context, sizeof(chan->context));
212 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
213 chan->priority = pri;
216 static void check_goto_on_transfer(struct ast_channel *chan)
218 struct ast_channel *xferchan;
219 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
220 char *x, *goto_on_transfer;
221 struct ast_frame *f;
223 if (ast_strlen_zero(val))
224 return;
226 goto_on_transfer = ast_strdupa(val);
228 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
229 return;
231 for (x = goto_on_transfer; x && *x; x++) {
232 if (*x == '^')
233 *x = '|';
235 /* Make formats okay */
236 xferchan->readformat = chan->readformat;
237 xferchan->writeformat = chan->writeformat;
238 ast_channel_masquerade(xferchan, chan);
239 ast_parseable_goto(xferchan, goto_on_transfer);
240 xferchan->_state = AST_STATE_UP;
241 ast_clear_flag(xferchan, AST_FLAGS_ALL);
242 xferchan->_softhangup = 0;
243 if ((f = ast_read(xferchan))) {
244 ast_frfree(f);
245 f = NULL;
246 ast_pbx_start(xferchan);
247 } else {
248 ast_hangup(xferchan);
252 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);
255 static void *ast_bridge_call_thread(void *data)
257 struct ast_bridge_thread_obj *tobj = data;
259 tobj->chan->appl = "Transferred Call";
260 tobj->chan->data = tobj->peer->name;
261 tobj->peer->appl = "Transferred Call";
262 tobj->peer->data = tobj->chan->name;
264 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
265 ast_hangup(tobj->chan);
266 ast_hangup(tobj->peer);
267 bzero(tobj, sizeof(*tobj)); /*! \todo XXX for safety */
268 free(tobj);
269 return NULL;
272 static void ast_bridge_call_thread_launch(void *data)
274 pthread_t thread;
275 pthread_attr_t attr;
276 struct sched_param sched;
278 pthread_attr_init(&attr);
279 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
280 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
281 pthread_attr_destroy(&attr);
282 memset(&sched, 0, sizeof(sched));
283 pthread_setschedparam(thread, SCHED_RR, &sched);
286 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
288 int res;
289 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
290 char tmp[256];
291 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
293 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
294 message[0] = tmp;
295 res = ast_adsi_load_session(chan, NULL, 0, 1);
296 if (res == -1)
297 return res;
298 return ast_adsi_print(chan, message, justify, 1);
301 /*! \brief Notify metermaids that we've changed an extension */
302 static void notify_metermaids(char *exten, char *context)
304 if (option_debug > 3)
305 ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
307 /* Send notification to devicestate subsystem */
308 ast_device_state_changed("park:%s@%s", exten, context);
309 return;
312 /*! \brief metermaids callback from devicestate.c */
313 static int metermaidstate(const char *data)
315 int res = AST_DEVICE_INVALID;
316 char *context = ast_strdupa(data);
317 char *exten;
319 exten = strsep(&context, "@");
320 if (!context)
321 return res;
323 if (option_debug > 3)
324 ast_log(LOG_DEBUG, "Checking state of exten %s in context %s\n", exten, context);
326 res = ast_exists_extension(NULL, context, exten, 1, NULL);
328 if (!res)
329 return AST_DEVICE_NOT_INUSE;
330 else
331 return AST_DEVICE_INUSE;
334 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name)
336 struct parkeduser *pu, *cur;
337 int i, x = -1, parking_range;
338 struct ast_context *con;
339 const char *parkingexten;
341 /* Allocate memory for parking data */
342 if (!(pu = ast_calloc(1, sizeof(*pu))))
343 return -1;
345 /* Lock parking lot */
346 ast_mutex_lock(&parking_lock);
347 /* Check for channel variable PARKINGEXTEN */
348 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
349 if (!ast_strlen_zero(parkingexten)) {
350 /*!\note The API forces us to specify a numeric parking slot, even
351 * though the architecture would tend to support non-numeric extensions
352 * (as are possible with SIP, for example). Hence, we enforce that
353 * limitation here. If extout was not numeric, we could permit
354 * arbitrary non-numeric extensions.
356 if (sscanf(parkingexten, "%d", &x) != 1 || x < 0) {
357 ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
358 ast_mutex_unlock(&parking_lock);
359 free(pu);
360 return 1; /* Continue execution if possible */
362 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
364 if (ast_exists_extension(NULL, parking_con, pu->parkingexten, 1, NULL)) {
365 ast_mutex_unlock(&parking_lock);
366 free(pu);
367 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
368 return 1; /* Continue execution if possible */
370 } else {
371 /* Select parking space within range */
372 parking_range = parking_stop - parking_start+1;
373 for (i = 0; i < parking_range; i++) {
374 x = (i + parking_offset) % parking_range + parking_start;
375 cur = parkinglot;
376 while(cur) {
377 if (cur->parkingnum == x)
378 break;
379 cur = cur->next;
381 if (!cur)
382 break;
385 if (!(i < parking_range)) {
386 ast_log(LOG_WARNING, "No more parking spaces\n");
387 free(pu);
388 ast_mutex_unlock(&parking_lock);
389 return -1;
391 /* Set pointer for next parking */
392 if (parkfindnext)
393 parking_offset = x - parking_start + 1;
394 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
397 chan->appl = "Parked Call";
398 chan->data = NULL;
400 pu->chan = chan;
402 /* Put the parked channel on hold if we have two different channels */
403 if (chan != peer) {
404 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
405 S_OR(parkmohclass, NULL),
406 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
409 pu->start = ast_tvnow();
410 pu->parkingnum = x;
411 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
412 if (extout)
413 *extout = x;
415 if (peer) {
416 /* This is so ugly that it hurts, but implementing get_base_channel() on local channels
417 could have ugly side effects. We could have transferer<->local,1<->local,2<->parking
418 and we need the callback name to be that of transferer. Since local,1/2 have the same
419 name we can be tricky and just grab the bridged channel from the other side of the local
421 if (!strcasecmp(peer->tech->type, "Local")) {
422 struct ast_channel *tmpchan, *base_peer;
423 char other_side[AST_CHANNEL_NAME];
424 char *c;
425 ast_copy_string(other_side, peer->name, sizeof(other_side));
426 if ((c = strrchr(other_side, ','))) {
427 *++c = '1';
429 if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
430 if ((base_peer = ast_bridged_channel(tmpchan))) {
431 ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
433 ast_channel_unlock(tmpchan);
435 } else {
436 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
440 /* Remember what had been dialed, so that if the parking
441 expires, we try to come back to the same place */
442 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
443 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
444 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
445 pu->next = parkinglot;
446 parkinglot = pu;
448 /* If parking a channel directly, don't quiet yet get parking running on it */
449 if (peer == chan)
450 pu->notquiteyet = 1;
451 ast_mutex_unlock(&parking_lock);
452 /* Wake up the (presumably select()ing) thread */
453 pthread_kill(parking_thread, SIGURG);
454 if (option_verbose > 1)
455 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));
457 manager_event(EVENT_FLAG_CALL, "ParkedCall",
458 "Exten: %s\r\n"
459 "Channel: %s\r\n"
460 "From: %s\r\n"
461 "Timeout: %ld\r\n"
462 "CallerID: %s\r\n"
463 "CallerIDName: %s\r\n",
464 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
465 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
466 S_OR(pu->chan->cid.cid_num, "<unknown>"),
467 S_OR(pu->chan->cid.cid_name, "<unknown>")
470 if (peer && adsipark && ast_adsi_available(peer)) {
471 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
472 ast_adsi_unload_session(peer);
475 con = ast_context_find(parking_con);
476 if (!con)
477 con = ast_context_create(NULL, parking_con, registrar);
478 if (!con) /* Still no context? Bad */
479 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
480 /* Tell the peer channel the number of the parking space */
481 if (peer && (ast_strlen_zero(orig_chan_name) || !strcasecmp(peer->name, orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
482 /* Make sure we don't start saying digits to the channel being parked */
483 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
484 ast_say_digits(peer, pu->parkingnum, "", peer->language);
485 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
487 if (con) {
488 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar))
489 notify_metermaids(pu->parkingexten, parking_con);
491 if (pu->notquiteyet) {
492 /* Wake up parking thread if we're really done */
493 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
494 S_OR(parkmohclass, NULL),
495 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
496 pu->notquiteyet = 0;
497 pthread_kill(parking_thread, SIGURG);
499 return 0;
502 /*! \brief Park a call
503 \note We put the user in the parking list, then wake up the parking thread to be sure it looks
504 after these channels too */
505 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
507 return park_call_full(chan, peer, timeout, extout, NULL);
510 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
512 struct ast_channel *chan;
513 struct ast_frame *f;
514 char *orig_chan_name = NULL;
515 int park_status;
517 /* Make a new, fake channel that we'll use to masquerade in the real one */
518 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
519 ast_log(LOG_WARNING, "Unable to create parked channel\n");
520 return -1;
523 /* Make formats okay */
524 chan->readformat = rchan->readformat;
525 chan->writeformat = rchan->writeformat;
526 ast_channel_masquerade(chan, rchan);
528 /* Setup the extensions and such */
529 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
531 /* Make the masq execute */
532 f = ast_read(chan);
533 if (f)
534 ast_frfree(f);
536 orig_chan_name = ast_strdupa(chan->name);
538 park_status = park_call_full(chan, peer, timeout, extout, orig_chan_name);
539 if (park_status == 1) {
540 /* would be nice to play: "invalid parking extension" */
541 ast_hangup(chan);
542 return -1;
545 return 0;
549 #define FEATURE_RETURN_HANGUP -1
550 #define FEATURE_RETURN_SUCCESSBREAK 0
551 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
552 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
553 #define FEATURE_RETURN_PASSDIGITS 21
554 #define FEATURE_RETURN_STOREDIGITS 22
555 #define FEATURE_RETURN_SUCCESS 23
556 #define FEATURE_RETURN_KEEPTRYING 24
558 #define FEATURE_SENSE_CHAN (1 << 0)
559 #define FEATURE_SENSE_PEER (1 << 1)
561 /*! \brief
562 * set caller and callee according to the direction
564 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
565 struct ast_channel *peer, struct ast_channel *chan, int sense)
567 if (sense == FEATURE_SENSE_PEER) {
568 *caller = peer;
569 *callee = chan;
570 } else {
571 *callee = peer;
572 *caller = chan;
576 /*! \brief support routing for one touch call parking */
577 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
579 struct ast_channel *parker;
580 struct ast_channel *parkee;
581 int res = 0;
582 struct ast_module_user *u;
584 u = ast_module_user_add(chan);
586 set_peers(&parker, &parkee, peer, chan, sense);
587 /* Setup the exten/priority to be s/1 since we don't know
588 where this call should return */
589 strcpy(chan->exten, "s");
590 chan->priority = 1;
591 if (chan->_state != AST_STATE_UP)
592 res = ast_answer(chan);
593 if (!res)
594 res = ast_safe_sleep(chan, 1000);
595 if (!res)
596 res = ast_park_call(parkee, parker, 0, NULL);
598 ast_module_user_remove(u);
600 if (!res) {
601 if (sense == FEATURE_SENSE_CHAN)
602 res = AST_PBX_NO_HANGUP_PEER;
603 else
604 res = AST_PBX_KEEPALIVE;
606 return res;
610 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
612 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
613 int x = 0;
614 size_t len;
615 struct ast_channel *caller_chan, *callee_chan;
617 if (!monitor_ok) {
618 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
619 return -1;
622 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
623 monitor_ok = 0;
624 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
625 return -1;
628 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
630 if (!ast_strlen_zero(courtesytone)) {
631 if (ast_autoservice_start(callee_chan))
632 return -1;
633 if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
634 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
635 ast_autoservice_stop(callee_chan);
636 return -1;
638 if (ast_autoservice_stop(callee_chan))
639 return -1;
642 if (callee_chan->monitor) {
643 if (option_verbose > 3)
644 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
645 ast_monitor_stop(callee_chan, 1);
646 return FEATURE_RETURN_SUCCESS;
649 if (caller_chan && callee_chan) {
650 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
651 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
653 if (!touch_format)
654 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
656 if (!touch_monitor)
657 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
659 if (touch_monitor) {
660 len = strlen(touch_monitor) + 50;
661 args = alloca(len);
662 touch_filename = alloca(len);
663 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
664 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
665 } else {
666 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
667 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
668 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
669 args = alloca(len);
670 touch_filename = alloca(len);
671 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
672 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
675 for( x = 0; x < strlen(args); x++) {
676 if (args[x] == '/')
677 args[x] = '-';
680 if (option_verbose > 3)
681 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
683 pbx_exec(callee_chan, monitor_app, args);
684 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
685 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
687 return FEATURE_RETURN_SUCCESS;
690 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
691 return -1;
694 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
696 if (option_verbose > 3)
697 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
698 return FEATURE_RETURN_HANGUP;
701 static int finishup(struct ast_channel *chan)
703 ast_indicate(chan, AST_CONTROL_UNHOLD);
705 return ast_autoservice_stop(chan);
708 /*! \brief Find the context for the transfer */
709 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
711 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
712 if (ast_strlen_zero(s))
713 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
714 if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
715 s = transferer->macrocontext;
716 if (ast_strlen_zero(s))
717 s = transferer->context;
718 return s;
721 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
723 struct ast_channel *transferer;
724 struct ast_channel *transferee;
725 const char *transferer_real_context;
726 char xferto[256];
727 int res;
729 set_peers(&transferer, &transferee, peer, chan, sense);
730 transferer_real_context = real_ctx(transferer, transferee);
731 /* Start autoservice on chan while we talk to the originator */
732 ast_autoservice_start(transferee);
733 ast_indicate(transferee, AST_CONTROL_HOLD);
735 memset(xferto, 0, sizeof(xferto));
737 /* Transfer */
738 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
739 if (res < 0) {
740 finishup(transferee);
741 return -1; /* error ? */
743 if (res > 0) /* If they've typed a digit already, handle it */
744 xferto[0] = (char) res;
746 ast_stopstream(transferer);
747 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
748 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
749 finishup(transferee);
750 return res;
752 if (!strcmp(xferto, ast_parking_ext())) {
753 res = finishup(transferee);
754 if (res)
755 res = -1;
756 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
757 /* We return non-zero, but tell the PBX not to hang the channel when
758 the thread dies -- We have to be careful now though. We are responsible for
759 hanging up the channel, else it will never be hung up! */
761 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
762 } else {
763 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
765 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
766 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
767 pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
768 pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
769 res=finishup(transferee);
770 if (!transferer->cdr) {
771 transferer->cdr=ast_cdr_alloc();
772 if (transferer) {
773 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
774 ast_cdr_start(transferer->cdr);
777 if (transferer->cdr) {
778 ast_cdr_setdestchan(transferer->cdr, transferee->name);
779 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
781 if (!transferee->pbx) {
782 /* Doh! Use our handy async_goto functions */
783 if (option_verbose > 2)
784 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
785 ,transferee->name, xferto, transferer_real_context);
786 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
787 ast_log(LOG_WARNING, "Async goto failed :-(\n");
788 res = -1;
789 } else {
790 /* Set the channel's new extension, since it exists, using transferer context */
791 set_c_e_p(transferee, transferer_real_context, xferto, 0);
793 check_goto_on_transfer(transferer);
794 return res;
795 } else {
796 if (option_verbose > 2)
797 ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
799 if (ast_stream_and_wait(transferer, xferfailsound, transferer->language, AST_DIGIT_ANY) < 0 ) {
800 finishup(transferee);
801 return -1;
803 ast_stopstream(transferer);
804 res = finishup(transferee);
805 if (res) {
806 if (option_verbose > 1)
807 ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
808 return res;
810 return FEATURE_RETURN_SUCCESS;
813 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
815 if (ast_channel_make_compatible(c, newchan) < 0) {
816 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
817 c->name, newchan->name);
818 ast_hangup(newchan);
819 return -1;
821 return 0;
824 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
826 struct ast_channel *transferer;
827 struct ast_channel *transferee;
828 const char *transferer_real_context;
829 char xferto[256] = "";
830 int res;
831 int outstate=0;
832 struct ast_channel *newchan;
833 struct ast_channel *xferchan;
834 struct ast_bridge_thread_obj *tobj;
835 struct ast_bridge_config bconfig;
836 struct ast_frame *f;
837 int l;
838 struct ast_datastore *features_datastore;
839 struct ast_dial_features *dialfeatures = NULL;
841 if (option_debug)
842 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
843 set_peers(&transferer, &transferee, peer, chan, sense);
844 transferer_real_context = real_ctx(transferer, transferee);
845 /* Start autoservice on chan while we talk to the originator */
846 ast_autoservice_start(transferee);
847 ast_indicate(transferee, AST_CONTROL_HOLD);
849 /* Transfer */
850 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
851 if (res < 0) {
852 finishup(transferee);
853 return res;
855 if (res > 0) /* If they've typed a digit already, handle it */
856 xferto[0] = (char) res;
858 /* this is specific of atxfer */
859 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
860 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
861 finishup(transferee);
862 return res;
864 if (res == 0) {
865 ast_log(LOG_WARNING, "Did not read data.\n");
866 finishup(transferee);
867 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
868 return -1;
869 return FEATURE_RETURN_SUCCESS;
872 /* valid extension, res == 1 */
873 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
874 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
875 finishup(transferee);
876 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
877 return -1;
878 return FEATURE_RETURN_SUCCESS;
881 l = strlen(xferto);
882 snprintf(xferto + l, sizeof(xferto) - l, "@%s", transferer_real_context); /* append context */
883 newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
884 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, transferer->language);
886 /* If we are the callee and we are being transferred, after the masquerade
887 * caller features will really be the original callee features */
888 ast_channel_lock(transferee);
889 if ((features_datastore = ast_channel_datastore_find(transferee, &dial_features_info, NULL))) {
890 dialfeatures = features_datastore->data;
892 ast_channel_unlock(transferee);
894 if (dialfeatures && !dialfeatures->is_caller) {
895 ast_copy_flags(&(config->features_caller), &(dialfeatures->features_callee), AST_FLAGS_ALL);
898 ast_indicate(transferer, -1);
899 if (!newchan) {
900 finishup(transferee);
901 /* any reason besides user requested cancel and busy triggers the failed sound */
902 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
903 ast_stream_and_wait(transferer, xferfailsound, transferer->language, ""))
904 return -1;
905 return FEATURE_RETURN_SUCCESS;
908 if (check_compat(transferer, newchan)) {
909 /* we do mean transferee here, NOT transferer */
910 finishup(transferee);
911 return -1;
913 memset(&bconfig,0,sizeof(struct ast_bridge_config));
914 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
915 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
916 res = ast_bridge_call(transferer, newchan, &bconfig);
917 if (newchan->_softhangup || !transferer->_softhangup) {
918 ast_hangup(newchan);
919 if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
920 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
921 finishup(transferee);
922 transferer->_softhangup = 0;
923 return FEATURE_RETURN_SUCCESS;
926 if (check_compat(transferee, newchan)) {
927 finishup(transferee);
928 return -1;
931 ast_indicate(transferee, AST_CONTROL_UNHOLD);
933 if ((ast_autoservice_stop(transferee) < 0)
934 || (ast_waitfordigit(transferee, 100) < 0)
935 || (ast_waitfordigit(newchan, 100) < 0)
936 || ast_check_hangup(transferee)
937 || ast_check_hangup(newchan)) {
938 ast_hangup(newchan);
939 return -1;
942 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
943 if (!xferchan) {
944 ast_hangup(newchan);
945 return -1;
947 /* Make formats okay */
948 xferchan->visible_indication = transferer->visible_indication;
949 xferchan->readformat = transferee->readformat;
950 xferchan->writeformat = transferee->writeformat;
951 ast_channel_masquerade(xferchan, transferee);
952 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
953 xferchan->_state = AST_STATE_UP;
954 ast_clear_flag(xferchan, AST_FLAGS_ALL);
955 xferchan->_softhangup = 0;
957 if ((f = ast_read(xferchan)))
958 ast_frfree(f);
960 newchan->_state = AST_STATE_UP;
961 ast_clear_flag(newchan, AST_FLAGS_ALL);
962 newchan->_softhangup = 0;
964 tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
965 if (!tobj) {
966 ast_hangup(xferchan);
967 ast_hangup(newchan);
968 return -1;
971 /* For the case where the transfer target is being connected with the original
972 caller store the target's original features, and apply to the bridge */
973 ast_channel_lock(newchan);
974 if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
975 dialfeatures = features_datastore->data;
977 ast_channel_unlock(newchan);
979 if (dialfeatures) {
980 ast_copy_flags(&(config->features_callee), &(dialfeatures->features_callee), AST_FLAGS_ALL);
983 tobj->chan = newchan;
984 tobj->peer = xferchan;
985 tobj->bconfig = *config;
987 if (ast_stream_and_wait(newchan, xfersound, newchan->language, ""))
988 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
989 ast_bridge_call_thread_launch(tobj);
990 return -1; /* XXX meaning the channel is bridged ? */
994 /* add atxfer and automon as undefined so you can only use em if you configure them */
995 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
997 AST_RWLOCK_DEFINE_STATIC(features_lock);
999 static struct ast_call_feature builtin_features[] =
1001 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1002 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1003 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1004 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1005 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1009 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1011 /*! \brief register new feature into feature_list*/
1012 void ast_register_feature(struct ast_call_feature *feature)
1014 if (!feature) {
1015 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1016 return;
1019 AST_LIST_LOCK(&feature_list);
1020 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1021 AST_LIST_UNLOCK(&feature_list);
1023 if (option_verbose >= 2)
1024 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
1027 /*! \brief unregister feature from feature_list */
1028 void ast_unregister_feature(struct ast_call_feature *feature)
1030 if (!feature)
1031 return;
1033 AST_LIST_LOCK(&feature_list);
1034 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1035 AST_LIST_UNLOCK(&feature_list);
1036 free(feature);
1039 /*! \brief Remove all features in the list */
1040 static void ast_unregister_features(void)
1042 struct ast_call_feature *feature;
1044 AST_LIST_LOCK(&feature_list);
1045 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1046 free(feature);
1047 AST_LIST_UNLOCK(&feature_list);
1050 /*! \brief find a feature by name */
1051 static struct ast_call_feature *find_dynamic_feature(const char *name)
1053 struct ast_call_feature *tmp;
1055 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1056 if (!strcasecmp(tmp->sname, name))
1057 break;
1060 return tmp;
1063 /*! \brief exec an app by feature */
1064 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1066 struct ast_app *app;
1067 struct ast_call_feature *feature = data;
1068 struct ast_channel *work, *idle;
1069 int res;
1071 if (!feature) { /* shouldn't ever happen! */
1072 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1073 return -1;
1076 if (sense == FEATURE_SENSE_CHAN) {
1077 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1078 return FEATURE_RETURN_KEEPTRYING;
1079 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1080 work = chan;
1081 idle = peer;
1082 } else {
1083 work = peer;
1084 idle = chan;
1086 } else {
1087 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1088 return FEATURE_RETURN_KEEPTRYING;
1089 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1090 work = peer;
1091 idle = chan;
1092 } else {
1093 work = chan;
1094 idle = peer;
1098 if (!(app = pbx_findapp(feature->app))) {
1099 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1100 return -2;
1103 ast_autoservice_start(idle);
1105 if (!ast_strlen_zero(feature->moh_class))
1106 ast_moh_start(idle, feature->moh_class, NULL);
1108 res = pbx_exec(work, app, feature->app_args);
1110 if (!ast_strlen_zero(feature->moh_class))
1111 ast_moh_stop(idle);
1113 ast_autoservice_stop(idle);
1115 if (res == AST_PBX_KEEPALIVE) {
1116 /* do not hangup peer if feature is to be activated on it */
1117 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))
1118 return FEATURE_RETURN_NO_HANGUP_PEER;
1119 else
1120 return FEATURE_RETURN_PBX_KEEPALIVE;
1122 else if (res == AST_PBX_NO_HANGUP_PEER)
1123 return FEATURE_RETURN_NO_HANGUP_PEER;
1124 else if (res)
1125 return FEATURE_RETURN_SUCCESSBREAK;
1127 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1130 static void unmap_features(void)
1132 int x;
1134 ast_rwlock_wrlock(&features_lock);
1135 for (x = 0; x < FEATURES_COUNT; x++)
1136 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1137 ast_rwlock_unlock(&features_lock);
1140 static int remap_feature(const char *name, const char *value)
1142 int x, res = -1;
1144 ast_rwlock_wrlock(&features_lock);
1145 for (x = 0; x < FEATURES_COUNT; x++) {
1146 if (strcasecmp(builtin_features[x].sname, name))
1147 continue;
1149 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1150 res = 0;
1151 break;
1153 ast_rwlock_unlock(&features_lock);
1155 return res;
1158 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1160 int x;
1161 struct ast_flags features;
1162 struct ast_call_feature *feature;
1163 const char *dynamic_features;
1164 char *tmp, *tok;
1165 int res = FEATURE_RETURN_PASSDIGITS;
1166 int feature_detected = 0;
1168 if (sense == FEATURE_SENSE_CHAN) {
1169 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1170 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1171 } else {
1172 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1173 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
1175 if (option_debug > 2)
1176 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);
1178 ast_rwlock_rdlock(&features_lock);
1179 for (x = 0; x < FEATURES_COUNT; x++) {
1180 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1181 !ast_strlen_zero(builtin_features[x].exten)) {
1182 /* Feature is up for consideration */
1183 if (!strcmp(builtin_features[x].exten, code)) {
1184 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1185 feature_detected = 1;
1186 break;
1187 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1188 if (res == FEATURE_RETURN_PASSDIGITS)
1189 res = FEATURE_RETURN_STOREDIGITS;
1193 ast_rwlock_unlock(&features_lock);
1195 if (ast_strlen_zero(dynamic_features) || feature_detected)
1196 return res;
1198 tmp = ast_strdupa(dynamic_features);
1200 while ((tok = strsep(&tmp, "#"))) {
1201 AST_LIST_LOCK(&feature_list);
1202 if (!(feature = find_dynamic_feature(tok))) {
1203 AST_LIST_UNLOCK(&feature_list);
1204 continue;
1207 /* Feature is up for consideration */
1208 if (!strcmp(feature->exten, code)) {
1209 if (option_verbose > 2)
1210 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1211 res = feature->operation(chan, peer, config, code, sense, feature);
1212 if (res != FEATURE_RETURN_KEEPTRYING) {
1213 AST_LIST_UNLOCK(&feature_list);
1214 break;
1216 res = FEATURE_RETURN_PASSDIGITS;
1217 } else if (!strncmp(feature->exten, code, strlen(code)))
1218 res = FEATURE_RETURN_STOREDIGITS;
1220 AST_LIST_UNLOCK(&feature_list);
1223 return res;
1226 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1228 int x;
1230 ast_clear_flag(config, AST_FLAGS_ALL);
1232 ast_rwlock_rdlock(&features_lock);
1233 for (x = 0; x < FEATURES_COUNT; x++) {
1234 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1235 continue;
1237 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1238 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1240 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1241 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1243 ast_rwlock_unlock(&features_lock);
1245 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1246 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1248 if (dynamic_features) {
1249 char *tmp = ast_strdupa(dynamic_features);
1250 char *tok;
1251 struct ast_call_feature *feature;
1253 /* while we have a feature */
1254 while ((tok = strsep(&tmp, "#"))) {
1255 AST_LIST_LOCK(&feature_list);
1256 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1257 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1258 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1259 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1260 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1262 AST_LIST_UNLOCK(&feature_list);
1268 /*! \todo XXX Check - this is very similar to the code in channel.c */
1269 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)
1271 int state = 0;
1272 int cause = 0;
1273 int to;
1274 struct ast_channel *chan;
1275 struct ast_channel *monitor_chans[2];
1276 struct ast_channel *active_channel;
1277 int res = 0, ready = 0;
1279 if ((chan = ast_request(type, format, data, &cause))) {
1280 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1281 ast_string_field_set(chan, language, language);
1282 ast_channel_inherit_variables(caller, chan);
1283 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1285 if (!ast_call(chan, data, timeout)) {
1286 struct timeval started;
1287 int x, len = 0;
1288 char *disconnect_code = NULL, *dialed_code = NULL;
1290 ast_indicate(caller, AST_CONTROL_RINGING);
1291 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1292 ast_rwlock_rdlock(&features_lock);
1293 for (x = 0; x < FEATURES_COUNT; x++) {
1294 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1295 continue;
1297 disconnect_code = builtin_features[x].exten;
1298 len = strlen(disconnect_code) + 1;
1299 dialed_code = alloca(len);
1300 memset(dialed_code, 0, len);
1301 break;
1303 ast_rwlock_unlock(&features_lock);
1304 x = 0;
1305 started = ast_tvnow();
1306 to = timeout;
1307 while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1308 struct ast_frame *f = NULL;
1310 monitor_chans[0] = caller;
1311 monitor_chans[1] = chan;
1312 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1314 /* see if the timeout has been violated */
1315 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1316 state = AST_CONTROL_UNHOLD;
1317 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1318 break; /*doh! timeout*/
1321 if (!active_channel)
1322 continue;
1324 if (chan && (chan == active_channel)){
1325 f = ast_read(chan);
1326 if (f == NULL) { /*doh! where'd he go?*/
1327 state = AST_CONTROL_HANGUP;
1328 res = 0;
1329 break;
1332 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1333 if (f->subclass == AST_CONTROL_RINGING) {
1334 state = f->subclass;
1335 if (option_verbose > 2)
1336 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1337 ast_indicate(caller, AST_CONTROL_RINGING);
1338 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1339 state = f->subclass;
1340 if (option_verbose > 2)
1341 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
1342 ast_indicate(caller, AST_CONTROL_BUSY);
1343 ast_frfree(f);
1344 f = NULL;
1345 break;
1346 } else if (f->subclass == AST_CONTROL_ANSWER) {
1347 /* This is what we are hoping for */
1348 state = f->subclass;
1349 ast_frfree(f);
1350 f = NULL;
1351 ready=1;
1352 break;
1353 } else if (f->subclass != -1) {
1354 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1356 /* else who cares */
1359 } else if (caller && (active_channel == caller)) {
1360 f = ast_read(caller);
1361 if (f == NULL) { /*doh! where'd he go?*/
1362 if (caller->_softhangup && !chan->_softhangup) {
1363 /* make this a blind transfer */
1364 ready = 1;
1365 break;
1367 state = AST_CONTROL_HANGUP;
1368 res = 0;
1369 break;
1372 if (f->frametype == AST_FRAME_DTMF) {
1373 dialed_code[x++] = f->subclass;
1374 dialed_code[x] = '\0';
1375 if (strlen(dialed_code) == len) {
1376 x = 0;
1377 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1378 x = 0;
1379 dialed_code[x] = '\0';
1381 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1382 /* Caller Canceled the call */
1383 state = AST_CONTROL_UNHOLD;
1384 ast_frfree(f);
1385 f = NULL;
1386 break;
1390 if (f)
1391 ast_frfree(f);
1392 } /* end while */
1393 } else
1394 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1395 } else {
1396 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1397 switch(cause) {
1398 case AST_CAUSE_BUSY:
1399 state = AST_CONTROL_BUSY;
1400 break;
1401 case AST_CAUSE_CONGESTION:
1402 state = AST_CONTROL_CONGESTION;
1403 break;
1407 ast_indicate(caller, -1);
1408 if (chan && ready) {
1409 if (chan->_state == AST_STATE_UP)
1410 state = AST_CONTROL_ANSWER;
1411 res = 0;
1412 } else if(chan) {
1413 res = -1;
1414 ast_hangup(chan);
1415 chan = NULL;
1416 } else {
1417 res = -1;
1420 if (outstate)
1421 *outstate = state;
1423 return chan;
1426 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1428 /* Copy voice back and forth between the two channels. Give the peer
1429 the ability to transfer calls with '#<extension' syntax. */
1430 struct ast_frame *f;
1431 struct ast_channel *who;
1432 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1433 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1434 char orig_channame[AST_MAX_EXTENSION];
1435 char orig_peername[AST_MAX_EXTENSION];
1437 int res;
1438 int diff;
1439 int hasfeatures=0;
1440 int hadfeatures=0;
1441 struct ast_option_header *aoh;
1442 struct ast_bridge_config backup_config;
1443 struct ast_cdr *bridge_cdr = NULL;
1444 struct ast_cdr *orig_peer_cdr = NULL;
1446 memset(&backup_config, 0, sizeof(backup_config));
1448 config->start_time = ast_tvnow();
1450 if (chan && peer) {
1451 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1452 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1453 } else if (chan)
1454 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1456 if (monitor_ok) {
1457 const char *monitor_exec;
1458 struct ast_channel *src = NULL;
1459 if (!monitor_app) {
1460 if (!(monitor_app = pbx_findapp("Monitor")))
1461 monitor_ok=0;
1463 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1464 src = chan;
1465 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1466 src = peer;
1467 if (monitor_app && src) {
1468 char *tmp = ast_strdupa(monitor_exec);
1469 pbx_exec(src, monitor_app, tmp);
1473 set_config_flags(chan, peer, config);
1474 config->firstpass = 1;
1476 /* Answer if need be */
1477 if (ast_answer(chan))
1478 return -1;
1480 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
1481 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
1482 orig_peer_cdr = peer->cdr;
1484 if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
1486 if (chan->cdr) {
1487 ast_set_flag(chan->cdr, AST_CDR_FLAG_MAIN);
1488 ast_cdr_update(chan);
1489 bridge_cdr = ast_cdr_dup(chan->cdr);
1490 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
1491 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
1492 } else {
1493 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
1494 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
1495 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
1496 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
1497 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
1498 ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
1499 ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
1500 ast_cdr_setcid(bridge_cdr, chan);
1501 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
1502 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
1503 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
1504 /* Destination information */
1505 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
1506 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
1507 if (peer->cdr) {
1508 bridge_cdr->start = peer->cdr->start;
1509 ast_copy_string(bridge_cdr->userfield, peer->cdr->userfield, sizeof(bridge_cdr->userfield));
1510 } else {
1511 ast_cdr_start(bridge_cdr);
1514 /* peer->cdr->answer will be set when a macro runs on the peer;
1515 in that case, the bridge answer will be delayed while the
1516 macro plays on the peer channel. The peer answered the call
1517 before the macro started playing. To the phone system,
1518 this is billable time for the call, even tho the caller
1519 hears nothing but ringing while the macro does its thing. */
1520 if (peer->cdr && !ast_tvzero(peer->cdr->answer)) {
1521 bridge_cdr->answer = peer->cdr->answer;
1522 chan->cdr->answer = peer->cdr->answer;
1523 } else {
1524 ast_cdr_answer(bridge_cdr);
1525 ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
1527 ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
1528 if (peer->cdr) {
1529 ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
1533 for (;;) {
1534 struct ast_channel *other; /* used later */
1536 res = ast_channel_bridge(chan, peer, config, &f, &who);
1538 if (config->feature_timer) {
1539 /* Update time limit for next pass */
1540 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1541 config->feature_timer -= diff;
1542 if (hasfeatures) {
1543 /* Running on backup config, meaning a feature might be being
1544 activated, but that's no excuse to keep things going
1545 indefinitely! */
1546 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1547 if (option_debug)
1548 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1549 config->feature_timer = 0;
1550 who = chan;
1551 if (f)
1552 ast_frfree(f);
1553 f = NULL;
1554 res = 0;
1555 } else if (config->feature_timer <= 0) {
1556 /* Not *really* out of time, just out of time for
1557 digits to come in for features. */
1558 if (option_debug)
1559 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1560 if (!ast_strlen_zero(peer_featurecode)) {
1561 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1562 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1564 if (!ast_strlen_zero(chan_featurecode)) {
1565 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1566 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1568 if (f)
1569 ast_frfree(f);
1570 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1571 if (!hasfeatures) {
1572 /* Restore original (possibly time modified) bridge config */
1573 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1574 memset(&backup_config, 0, sizeof(backup_config));
1576 hadfeatures = hasfeatures;
1577 /* Continue as we were */
1578 continue;
1579 } else if (!f) {
1580 /* The bridge returned without a frame and there is a feature in progress.
1581 * However, we don't think the feature has quite yet timed out, so just
1582 * go back into the bridge. */
1583 continue;
1585 } else {
1586 if (config->feature_timer <=0) {
1587 /* We ran out of time */
1588 config->feature_timer = 0;
1589 who = chan;
1590 if (f)
1591 ast_frfree(f);
1592 f = NULL;
1593 res = 0;
1597 if (res < 0) {
1598 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
1599 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1600 goto before_you_go;
1603 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1604 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1605 f->subclass == AST_CONTROL_CONGESTION ) ) ) {
1606 res = -1;
1607 break;
1609 /* many things should be sent to the 'other' channel */
1610 other = (who == chan) ? peer : chan;
1611 if (f->frametype == AST_FRAME_CONTROL) {
1612 switch (f->subclass) {
1613 case AST_CONTROL_RINGING:
1614 case AST_CONTROL_FLASH:
1615 case -1:
1616 ast_indicate(other, f->subclass);
1617 break;
1618 case AST_CONTROL_HOLD:
1619 case AST_CONTROL_UNHOLD:
1620 ast_indicate_data(other, f->subclass, f->data, f->datalen);
1621 break;
1622 case AST_CONTROL_OPTION:
1623 aoh = f->data;
1624 /* Forward option Requests */
1625 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
1626 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
1627 f->datalen - sizeof(struct ast_option_header), 0);
1629 break;
1631 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1632 /* eat it */
1633 } else if (f->frametype == AST_FRAME_DTMF) {
1634 char *featurecode;
1635 int sense;
1637 hadfeatures = hasfeatures;
1638 /* This cannot overrun because the longest feature is one shorter than our buffer */
1639 if (who == chan) {
1640 sense = FEATURE_SENSE_CHAN;
1641 featurecode = chan_featurecode;
1642 } else {
1643 sense = FEATURE_SENSE_PEER;
1644 featurecode = peer_featurecode;
1646 /*! append the event to featurecode. we rely on the string being zero-filled, and
1647 * not overflowing it.
1648 * \todo XXX how do we guarantee the latter ?
1650 featurecode[strlen(featurecode)] = f->subclass;
1651 /* Get rid of the frame before we start doing "stuff" with the channels */
1652 ast_frfree(f);
1653 f = NULL;
1654 config->feature_timer = backup_config.feature_timer;
1655 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1656 switch(res) {
1657 case FEATURE_RETURN_PASSDIGITS:
1658 ast_dtmf_stream(other, who, featurecode, 0);
1659 /* Fall through */
1660 case FEATURE_RETURN_SUCCESS:
1661 memset(featurecode, 0, sizeof(chan_featurecode));
1662 break;
1664 if (res >= FEATURE_RETURN_PASSDIGITS) {
1665 res = 0;
1666 } else
1667 break;
1668 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1669 if (hadfeatures && !hasfeatures) {
1670 /* Restore backup */
1671 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1672 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1673 } else if (hasfeatures) {
1674 if (!hadfeatures) {
1675 /* Backup configuration */
1676 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1677 /* Setup temporary config options */
1678 config->play_warning = 0;
1679 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1680 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1681 config->warning_freq = 0;
1682 config->warning_sound = NULL;
1683 config->end_sound = NULL;
1684 config->start_sound = NULL;
1685 config->firstpass = 0;
1687 config->start_time = ast_tvnow();
1688 config->feature_timer = featuredigittimeout;
1689 if (option_debug)
1690 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1693 if (f)
1694 ast_frfree(f);
1697 before_you_go:
1698 /* obey the NoCDR() wishes. */
1699 if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
1701 ast_cdr_end(bridge_cdr);
1703 ast_cdr_detach(bridge_cdr);
1705 /* just in case, these channels get bridged again before hangup */
1706 if (chan->cdr) {
1707 ast_cdr_specialized_reset(chan->cdr,0);
1709 if (peer->cdr) {
1710 struct ast_cdr *cur;
1712 ast_channel_lock(peer);
1713 for (cur = peer->cdr; cur; cur = cur->next) {
1714 if (cur == orig_peer_cdr) {
1715 break;
1719 if (!cur) {
1720 /* orig_peer_cdr is gone, probably because of a masquerade
1721 * during the bridge. */
1722 ast_channel_unlock(peer);
1723 return res;
1726 /* before resetting the peer cdr, throw a copy of it to the
1727 backend, just in case the cdr.conf file is calling for
1728 unanswered CDR's. */
1730 /* When peer->cdr isn't the same addr as orig_peer_cdr,
1731 this can only happen if there was a transfer, methinks;
1732 at any rate, only pay attention to the original*/
1733 if (ast_cdr_isset_unanswered()) {
1734 struct ast_cdr *dupd = ast_cdr_dup(orig_peer_cdr);
1735 if (dupd) {
1736 if (ast_tvzero(dupd->end) && ast_cdr_isset_unanswered())
1737 ast_cdr_end(dupd);
1738 ast_cdr_detach(dupd);
1741 ast_cdr_specialized_reset(orig_peer_cdr,0);
1742 ast_channel_unlock(peer);
1745 return res;
1748 static void post_manager_event(const char *s, char *parkingexten, struct ast_channel *chan)
1750 manager_event(EVENT_FLAG_CALL, s,
1751 "Exten: %s\r\n"
1752 "Channel: %s\r\n"
1753 "CallerID: %s\r\n"
1754 "CallerIDName: %s\r\n\r\n",
1755 parkingexten,
1756 chan->name,
1757 S_OR(chan->cid.cid_num, "<unknown>"),
1758 S_OR(chan->cid.cid_name, "<unknown>")
1762 /*! \brief Take care of parked calls and unpark them if needed */
1763 static void *do_parking_thread(void *ignore)
1765 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
1766 FD_ZERO(&rfds);
1767 FD_ZERO(&efds);
1769 for (;;) {
1770 struct parkeduser *pu, *pl, *pt = NULL;
1771 int ms = -1; /* select timeout, uninitialized */
1772 int max = -1; /* max fd, none there yet */
1773 fd_set nrfds, nefds; /* args for the next select */
1774 FD_ZERO(&nrfds);
1775 FD_ZERO(&nefds);
1777 ast_mutex_lock(&parking_lock);
1778 pl = NULL;
1779 pu = parkinglot;
1780 /* navigate the list with prev-cur pointers to support removals */
1781 while (pu) {
1782 struct ast_channel *chan = pu->chan; /* shorthand */
1783 int tms; /* timeout for this item */
1784 int x; /* fd index in channel */
1785 struct ast_context *con;
1787 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
1788 pl = pu;
1789 pu = pu->next;
1790 continue;
1792 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1793 if (tms > pu->parkingtime) {
1794 ast_indicate(chan, AST_CONTROL_UNHOLD);
1795 /* Get chan, exten from derived kludge */
1796 if (pu->peername[0]) {
1797 char *peername = ast_strdupa(pu->peername);
1798 char *cp = strrchr(peername, '-');
1799 if (cp)
1800 *cp = 0;
1801 con = ast_context_find(parking_con_dial);
1802 if (!con) {
1803 con = ast_context_create(NULL, parking_con_dial, registrar);
1804 if (!con)
1805 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1807 if (con) {
1808 char returnexten[AST_MAX_EXTENSION];
1809 struct ast_datastore *features_datastore;
1810 struct ast_dial_features *dialfeatures = NULL;
1812 ast_channel_lock(chan);
1814 if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
1815 dialfeatures = features_datastore->data;
1817 ast_channel_unlock(chan);
1819 if (dialfeatures)
1820 snprintf(returnexten, sizeof(returnexten), "%s|30|%s", peername, dialfeatures->options);
1821 else /* Existing default */
1822 snprintf(returnexten, sizeof(returnexten), "%s|30|t", peername);
1824 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
1826 set_c_e_p(chan, parking_con_dial, peername, 1);
1827 } else {
1828 /* They've been waiting too long, send them back to where they came. Theoretically they
1829 should have their original extensions and such, but we copy to be on the safe side */
1830 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1833 post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
1835 if (option_verbose > 1)
1836 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);
1837 /* Start up the PBX, or hang them up */
1838 if (ast_pbx_start(chan)) {
1839 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1840 ast_hangup(chan);
1842 /* And take them out of the parking lot */
1843 if (pl)
1844 pl->next = pu->next;
1845 else
1846 parkinglot = pu->next;
1847 pt = pu;
1848 pu = pu->next;
1849 con = ast_context_find(parking_con);
1850 if (con) {
1851 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1852 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1853 else
1854 notify_metermaids(pt->parkingexten, parking_con);
1855 } else
1856 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1857 free(pt);
1858 } else { /* still within parking time, process descriptors */
1859 for (x = 0; x < AST_MAX_FDS; x++) {
1860 struct ast_frame *f;
1862 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1863 continue; /* nothing on this descriptor */
1865 if (FD_ISSET(chan->fds[x], &efds))
1866 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1867 else
1868 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1869 chan->fdno = x;
1871 /* See if they need servicing */
1872 f = ast_read(chan);
1873 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
1874 if (f)
1875 ast_frfree(f);
1876 post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
1878 /* There's a problem, hang them up*/
1879 if (option_verbose > 1)
1880 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1881 ast_hangup(chan);
1882 /* And take them out of the parking lot */
1883 if (pl)
1884 pl->next = pu->next;
1885 else
1886 parkinglot = pu->next;
1887 pt = pu;
1888 pu = pu->next;
1889 con = ast_context_find(parking_con);
1890 if (con) {
1891 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1892 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1893 else
1894 notify_metermaids(pt->parkingexten, parking_con);
1895 } else
1896 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1897 free(pt);
1898 break;
1899 } else {
1900 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1901 ast_frfree(f);
1902 if (pu->moh_trys < 3 && !chan->generatordata) {
1903 if (option_debug)
1904 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
1905 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
1906 S_OR(parkmohclass, NULL),
1907 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
1908 pu->moh_trys++;
1910 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
1913 } /* end for */
1914 if (x >= AST_MAX_FDS) {
1915 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
1916 if (chan->fds[x] > -1) {
1917 FD_SET(chan->fds[x], &nrfds);
1918 FD_SET(chan->fds[x], &nefds);
1919 if (chan->fds[x] > max)
1920 max = chan->fds[x];
1923 /* Keep track of our shortest wait */
1924 if (tms < ms || ms < 0)
1925 ms = tms;
1926 pl = pu;
1927 pu = pu->next;
1930 } /* end while */
1931 ast_mutex_unlock(&parking_lock);
1932 rfds = nrfds;
1933 efds = nefds;
1935 struct timeval tv = ast_samp2tv(ms, 1000);
1936 /* Wait for something to happen */
1937 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1939 pthread_testcancel();
1941 return NULL; /* Never reached */
1944 /*! \brief Park a call */
1945 static int park_call_exec(struct ast_channel *chan, void *data)
1947 /* Cache the original channel name in case we get masqueraded in the middle
1948 * of a park--it is still theoretically possible for a transfer to happen before
1949 * we get here, but it is _really_ unlikely */
1950 char *orig_chan_name = ast_strdupa(chan->name);
1951 char orig_exten[AST_MAX_EXTENSION];
1952 int orig_priority = chan->priority;
1954 /* Data is unused at the moment but could contain a parking
1955 lot context eventually */
1956 int res = 0;
1957 struct ast_module_user *u;
1959 u = ast_module_user_add(chan);
1961 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
1963 /* Setup the exten/priority to be s/1 since we don't know
1964 where this call should return */
1965 strcpy(chan->exten, "s");
1966 chan->priority = 1;
1967 /* Answer if call is not up */
1968 if (chan->_state != AST_STATE_UP)
1969 res = ast_answer(chan);
1970 /* Sleep to allow VoIP streams to settle down */
1971 if (!res)
1972 res = ast_safe_sleep(chan, 1000);
1973 /* Park the call */
1974 if (!res) {
1975 res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
1976 /* Continue on in the dialplan */
1977 if (res == 1) {
1978 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
1979 chan->priority = orig_priority;
1980 res = 0;
1981 } else if (!res)
1982 res = AST_PBX_KEEPALIVE;
1985 ast_module_user_remove(u);
1987 return res;
1990 /*! \brief Pickup parked call */
1991 static int park_exec(struct ast_channel *chan, void *data)
1993 int res = 0;
1994 struct ast_module_user *u;
1995 struct ast_channel *peer=NULL;
1996 struct parkeduser *pu, *pl=NULL;
1997 struct ast_context *con;
1999 int park;
2000 struct ast_bridge_config config;
2002 if (!data) {
2003 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
2004 return -1;
2007 u = ast_module_user_add(chan);
2009 park = atoi((char *)data);
2010 ast_mutex_lock(&parking_lock);
2011 pu = parkinglot;
2012 while(pu) {
2013 if (pu->parkingnum == park) {
2014 if (pl)
2015 pl->next = pu->next;
2016 else
2017 parkinglot = pu->next;
2018 break;
2020 pl = pu;
2021 pu = pu->next;
2023 ast_mutex_unlock(&parking_lock);
2024 if (pu) {
2025 peer = pu->chan;
2026 con = ast_context_find(parking_con);
2027 if (con) {
2028 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2029 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2030 else
2031 notify_metermaids(pu->parkingexten, parking_con);
2032 } else
2033 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2035 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2036 "Exten: %s\r\n"
2037 "Channel: %s\r\n"
2038 "From: %s\r\n"
2039 "CallerID: %s\r\n"
2040 "CallerIDName: %s\r\n",
2041 pu->parkingexten, pu->chan->name, chan->name,
2042 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2043 S_OR(pu->chan->cid.cid_name, "<unknown>")
2046 free(pu);
2048 /* JK02: it helps to answer the channel if not already up */
2049 if (chan->_state != AST_STATE_UP)
2050 ast_answer(chan);
2052 if (peer) {
2053 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2055 if (!ast_strlen_zero(courtesytone)) {
2056 int error = 0;
2057 ast_indicate(peer, AST_CONTROL_UNHOLD);
2058 if (parkedplay == 0) {
2059 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
2060 } else if (parkedplay == 1) {
2061 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
2062 } else if (parkedplay == 2) {
2063 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2064 !ast_streamfile(peer, courtesytone, chan->language)) {
2065 /*! \todo XXX we would like to wait on both! */
2066 res = ast_waitstream(chan, "");
2067 if (res >= 0)
2068 res = ast_waitstream(peer, "");
2069 if (res < 0)
2070 error = 1;
2073 if (error) {
2074 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2075 ast_hangup(peer);
2076 ast_module_user_remove(u);
2077 return -1;
2079 } else
2080 ast_indicate(peer, AST_CONTROL_UNHOLD);
2082 res = ast_channel_make_compatible(chan, peer);
2083 if (res < 0) {
2084 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2085 ast_hangup(peer);
2086 ast_module_user_remove(u);
2087 return -1;
2089 /* This runs sorta backwards, since we give the incoming channel control, as if it
2090 were the person called. */
2091 if (option_verbose > 2)
2092 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
2094 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2095 ast_cdr_setdestchan(chan->cdr, peer->name);
2096 memset(&config, 0, sizeof(struct ast_bridge_config));
2097 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2098 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2099 res = ast_bridge_call(chan, peer, &config);
2101 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2102 ast_cdr_setdestchan(chan->cdr, peer->name);
2104 /* Simulate the PBX hanging up */
2105 if (res != AST_PBX_NO_HANGUP_PEER)
2106 ast_hangup(peer);
2107 ast_module_user_remove(u);
2108 return res;
2109 } else {
2110 /*! \todo XXX Play a message XXX */
2111 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
2112 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2113 if (option_verbose > 2)
2114 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2115 res = -1;
2118 ast_module_user_remove(u);
2120 return res;
2123 int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
2125 /* We put the user in the parking list, then wake up the parking thread to be sure it looks
2126 after these channels too */
2127 struct holdeduser *pu;
2128 pu = malloc(sizeof(struct holdeduser));
2129 if (pu) {
2130 memset(pu, 0, sizeof(pu));
2131 ast_mutex_lock(&holding_lock);
2132 chan->appl = "Holded Call";
2133 chan->data = NULL;
2135 pu->chan = chan;
2136 strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
2137 strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
2138 /* Start music on hold */
2139 ast_moh_start(pu->chan, NULL, NULL);
2140 gettimeofday(&pu->start, NULL);
2141 pu->next = holdlist;
2142 holdlist = pu;
2143 ast_mutex_unlock(&holding_lock);
2144 /* Wake up the (presumably select()ing) thread */
2145 pthread_kill(holding_thread, SIGURG);
2147 manager_event(EVENT_FLAG_CALL, "HoldedCall",
2148 "Channel1: %s\r\n"
2149 "Channel2: %s\r\n"
2150 "Uniqueid1: %s\r\n"
2151 "Uniqueid2: %s\r\n"
2152 ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
2154 } else {
2155 ast_log(LOG_WARNING, "Out of memory\n");
2156 return -1;
2158 return 0;
2161 int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
2163 struct ast_channel *chan;
2164 struct ast_frame *f;
2165 /* Make a new, fake channel that we'll use to masquerade in the real one */
2166 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
2167 if (chan) {
2168 /* Let us keep track of the channel name */
2169 ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
2170 /* Make formats okay */
2171 chan->readformat = rchan->readformat;
2172 chan->writeformat = rchan->writeformat;
2173 ast_channel_masquerade(chan, rchan);
2174 /* Setup the extensions and such */
2175 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
2176 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
2177 chan->priority = rchan->priority;
2178 /* this might be dirty, but we need to preserve the uniqueid */
2179 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
2180 /* Make the masq execute */
2181 f = ast_read(chan);
2182 if (f)
2183 ast_frfree(f);
2184 ast_hold_call(chan, peer);
2185 return -1;
2186 } else {
2187 ast_log(LOG_WARNING, "Unable to create holded channel\n");
2188 return -1;
2190 return 0;
2193 int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
2195 int res=-1, dres=-1;
2196 struct ast_channel *peer=NULL;
2197 struct ast_bridge_config config;
2199 peer = ast_get_holded_call(uniqueid);
2201 /* JK02: it helps to answer the channel if not already up */
2202 if (chan->_state != AST_STATE_UP) {
2203 ast_answer(chan);
2206 if (peer) {
2207 ast_mutex_unlock(&peer->lock);
2208 ast_moh_stop(peer);
2209 res = ast_channel_make_compatible(chan, peer);
2210 if (res < 0) {
2211 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2212 ast_hangup(peer);
2213 return -1;
2215 /* This runs sorta backwards, since we give the incoming channel control, as if it
2216 were the person called. */
2217 if (option_verbose > 2)
2218 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
2220 memset(&config,0,sizeof(struct ast_bridge_config));
2221 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2222 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2223 config.timelimit = 0;
2224 config.play_warning = 0;
2225 config.warning_freq = 0;
2226 config.warning_sound=NULL;
2227 res = ast_bridge_call(chan,peer,&config);
2229 /* Simulate the PBX hanging up */
2230 if (res != AST_PBX_NO_HANGUP_PEER)
2231 ast_hangup(peer);
2232 return res;
2233 } else {
2234 /* XXX Play a message XXX */
2235 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
2236 if (!dres)
2237 dres = ast_waitstream(chan, "");
2238 else {
2239 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2240 dres = 0;
2243 return res;
2246 int ast_retrieve_call_to_death(char *uniqueid)
2248 int res=-1;
2249 struct ast_channel *peer=NULL;
2251 peer = ast_get_holded_call(uniqueid);
2253 if (peer) {
2254 res=0;
2255 if (option_verbose > 2)
2256 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
2257 ast_mutex_unlock(&peer->lock);
2258 ast_hangup(peer);
2259 } else {
2260 ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
2262 return res;
2265 struct ast_channel *ast_get_holded_call(char *uniqueid)
2267 int res=-1;
2268 struct ast_channel *peer=NULL;
2269 struct holdeduser *pu, *pl=NULL;
2271 ast_mutex_lock(&holding_lock);
2272 pu = holdlist;
2273 while(pu) {
2274 if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
2275 if (pl)
2276 pl->next = pu->next;
2277 else
2278 holdlist = pu->next;
2279 break;
2281 pl = pu;
2282 pu = pu->next;
2284 ast_mutex_unlock(&holding_lock);
2285 if (pu) {
2286 peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
2287 free(pu);
2288 if (peer) {
2289 res=0;
2290 if (option_verbose > 2)
2291 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
2292 ast_moh_stop(peer);
2293 return peer;
2294 } else {
2295 if (option_verbose > 2)
2296 ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
2297 return NULL;
2299 } else {
2300 ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
2302 return NULL;
2305 /* this is our autmagically service thread that keeps channels onhold happy */
2306 static void *do_holding_thread(void *ignore)
2308 int ms, tms, max;
2309 struct holdeduser *pu, *pl, *pt = NULL;
2310 struct timeval tv;
2311 struct ast_frame *f;
2312 int x;
2313 fd_set rfds, efds;
2314 fd_set nrfds, nefds;
2315 FD_ZERO(&rfds);
2316 FD_ZERO(&efds);
2317 for (;;) {
2318 ms = -1;
2319 max = -1;
2320 ast_mutex_lock(&holding_lock);
2321 pl = NULL;
2322 pu = holdlist;
2323 gettimeofday(&tv, NULL);
2324 FD_ZERO(&nrfds);
2325 FD_ZERO(&nefds);
2326 while(pu) {
2327 tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
2328 for (x=0;x<AST_MAX_FDS;x++) {
2329 if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
2330 if (FD_ISSET(pu->chan->fds[x], &efds))
2331 ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
2332 else
2333 ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
2334 pu->chan->fdno = x;
2335 /* See if they need servicing */
2336 f = ast_read(pu->chan);
2337 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
2338 /* There's a problem, hang them up*/
2339 if (option_verbose > 1)
2340 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
2341 ast_hangup(pu->chan);
2342 /* find the corresponding channel and hang them up too! */
2343 /* but only if it is not bridged yet! */
2344 /* And take them out of the parking lot */
2345 if (pl)
2346 pl->next = pu->next;
2347 else
2348 holdlist = pu->next;
2349 pt = pu;
2350 pu = pu->next;
2351 free(pt);
2352 break;
2353 } else {
2354 /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2355 ast_frfree(f);
2356 goto std; /* XXX Ick: jumping into an else statement??? XXX */
2360 if (x >= AST_MAX_FDS) {
2361 std: for (x=0;x<AST_MAX_FDS;x++) {
2362 /* Keep this one for next one */
2363 if (pu->chan->fds[x] > -1) {
2364 FD_SET(pu->chan->fds[x], &nrfds);
2365 FD_SET(pu->chan->fds[x], &nefds);
2366 if (pu->chan->fds[x] > max)
2367 max = pu->chan->fds[x];
2370 /* Keep track of our longest wait */
2371 if ((tms < ms) || (ms < 0))
2372 ms = tms;
2373 pl = pu;
2374 pu = pu->next;
2377 ast_mutex_unlock(&holding_lock);
2378 rfds = nrfds;
2379 efds = nefds;
2380 tv.tv_sec = ms / 1000;
2381 tv.tv_usec = (ms % 1000) * 1000;
2382 /* Wait for something to happen */
2383 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2384 pthread_testcancel();
2386 return NULL; /* Never reached */
2389 static int retrieve_call_exec(struct ast_channel *chan, void *data) {
2390 int res=0;
2391 struct ast_module_user *u;
2392 char *uniqueid = (char *)data;
2393 u = ast_module_user_add(chan);
2394 res = ast_retrieve_call(chan, uniqueid);
2395 ast_module_user_remove(u);
2396 return res;
2399 static int handle_showfeatures(int fd, int argc, char *argv[])
2401 int i;
2402 struct ast_call_feature *feature;
2403 char format[] = "%-25s %-7s %-7s\n";
2405 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
2406 ast_cli(fd, format, "---------------", "-------", "-------");
2408 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2410 ast_rwlock_rdlock(&features_lock);
2411 for (i = 0; i < FEATURES_COUNT; i++)
2412 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2413 ast_rwlock_unlock(&features_lock);
2415 ast_cli(fd, "\n");
2416 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
2417 ast_cli(fd, format, "---------------", "-------", "-------");
2418 if (AST_LIST_EMPTY(&feature_list))
2419 ast_cli(fd, "(none)\n");
2420 else {
2421 AST_LIST_LOCK(&feature_list);
2422 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2423 ast_cli(fd, format, feature->sname, "no def", feature->exten);
2424 AST_LIST_UNLOCK(&feature_list);
2426 ast_cli(fd, "\nCall parking\n");
2427 ast_cli(fd, "------------\n");
2428 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
2429 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
2430 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2431 ast_cli(fd,"\n");
2433 return RESULT_SUCCESS;
2436 static char showfeatures_help[] =
2437 "Usage: feature list\n"
2438 " Lists currently configured features.\n";
2440 static int handle_parkedcalls(int fd, int argc, char *argv[])
2442 struct parkeduser *cur;
2443 int numparked = 0;
2445 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2446 , "Context", "Extension", "Pri", "Timeout");
2448 ast_mutex_lock(&parking_lock);
2450 for (cur = parkinglot; cur; cur = cur->next) {
2451 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2452 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2453 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2455 numparked++;
2457 ast_mutex_unlock(&parking_lock);
2458 ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
2461 return RESULT_SUCCESS;
2464 static char showparked_help[] =
2465 "Usage: show parkedcalls\n"
2466 " Lists currently parked calls.\n";
2468 static struct ast_cli_entry cli_show_features_deprecated = {
2469 { "show", "features", NULL },
2470 handle_showfeatures, NULL,
2471 NULL };
2473 static struct ast_cli_entry cli_features[] = {
2474 { { "feature", "show", NULL },
2475 handle_showfeatures, "Lists configured features",
2476 showfeatures_help, NULL, &cli_show_features_deprecated },
2478 { { "show", "parkedcalls", NULL },
2479 handle_parkedcalls, "Lists parked calls",
2480 showparked_help },
2483 /*! \brief Dump lot status */
2484 static int manager_parking_status( struct mansession *s, const struct message *m)
2486 struct parkeduser *cur;
2487 const char *id = astman_get_header(m, "ActionID");
2488 char idText[256] = "";
2490 if (!ast_strlen_zero(id))
2491 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2493 astman_send_ack(s, m, "Parked calls will follow");
2495 ast_mutex_lock(&parking_lock);
2497 for (cur = parkinglot; cur; cur = cur->next) {
2498 astman_append(s, "Event: ParkedCall\r\n"
2499 "Exten: %d\r\n"
2500 "Channel: %s\r\n"
2501 "From: %s\r\n"
2502 "Timeout: %ld\r\n"
2503 "CallerID: %s\r\n"
2504 "CallerIDName: %s\r\n"
2505 "%s"
2506 "\r\n",
2507 cur->parkingnum, cur->chan->name, cur->peername,
2508 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2509 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
2510 S_OR(cur->chan->cid.cid_name, ""),
2511 idText);
2514 astman_append(s,
2515 "Event: ParkedCallsComplete\r\n"
2516 "%s"
2517 "\r\n",idText);
2519 ast_mutex_unlock(&parking_lock);
2521 return RESULT_SUCCESS;
2524 static char mandescr_park[] =
2525 "Description: Park a channel.\n"
2526 "Variables: (Names marked with * are required)\n"
2527 " *Channel: Channel name to park\n"
2528 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
2529 " Timeout: Number of milliseconds to wait before callback.\n";
2531 static int manager_park(struct mansession *s, const struct message *m)
2533 const char *channel = astman_get_header(m, "Channel");
2534 const char *channel2 = astman_get_header(m, "Channel2");
2535 const char *timeout = astman_get_header(m, "Timeout");
2536 char buf[BUFSIZ];
2537 int to = 0;
2538 int res = 0;
2539 int parkExt = 0;
2540 struct ast_channel *ch1, *ch2;
2542 if (ast_strlen_zero(channel)) {
2543 astman_send_error(s, m, "Channel not specified");
2544 return 0;
2547 if (ast_strlen_zero(channel2)) {
2548 astman_send_error(s, m, "Channel2 not specified");
2549 return 0;
2552 ch1 = ast_get_channel_by_name_locked(channel);
2553 if (!ch1) {
2554 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2555 astman_send_error(s, m, buf);
2556 return 0;
2559 ch2 = ast_get_channel_by_name_locked(channel2);
2560 if (!ch2) {
2561 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2562 astman_send_error(s, m, buf);
2563 ast_channel_unlock(ch1);
2564 return 0;
2567 if (!ast_strlen_zero(timeout)) {
2568 sscanf(timeout, "%d", &to);
2571 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2572 if (!res) {
2573 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2574 astman_send_ack(s, m, "Park successful");
2575 } else {
2576 astman_send_error(s, m, "Park failure");
2579 ast_channel_unlock(ch1);
2580 ast_channel_unlock(ch2);
2582 return 0;
2586 int ast_pickup_call(struct ast_channel *chan)
2588 struct ast_channel *cur = NULL;
2589 int res = -1;
2591 while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
2592 if (!cur->pbx &&
2593 (cur != chan) &&
2594 (chan->pickupgroup & cur->callgroup) &&
2595 ((cur->_state == AST_STATE_RINGING) ||
2596 (cur->_state == AST_STATE_RING))) {
2597 break;
2599 ast_channel_unlock(cur);
2601 if (cur) {
2602 if (option_debug)
2603 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2604 res = ast_answer(chan);
2605 if (res)
2606 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2607 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2608 if (res)
2609 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2610 res = ast_channel_masquerade(cur, chan);
2611 if (res)
2612 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
2613 ast_channel_unlock(cur);
2614 } else {
2615 if (option_debug)
2616 ast_log(LOG_DEBUG, "No call pickup possible...\n");
2618 return res;
2621 /*! \brief Add parking hints for all defined parking lots */
2622 static void park_add_hints(char *context, int start, int stop)
2624 int numext;
2625 char device[AST_MAX_EXTENSION];
2626 char exten[10];
2628 for (numext = start; numext <= stop; numext++) {
2629 snprintf(exten, sizeof(exten), "%d", numext);
2630 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2631 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2636 static int load_config(void)
2638 int start = 0, end = 0;
2639 int res;
2640 struct ast_context *con = NULL;
2641 struct ast_config *cfg = NULL;
2642 struct ast_variable *var = NULL;
2643 char old_parking_ext[AST_MAX_EXTENSION];
2644 char old_parking_con[AST_MAX_EXTENSION] = "";
2646 if (!ast_strlen_zero(parking_con)) {
2647 strcpy(old_parking_ext, parking_ext);
2648 strcpy(old_parking_con, parking_con);
2651 /* Reset to defaults */
2652 strcpy(parking_con, "parkedcalls");
2653 strcpy(parking_con_dial, "park-dial");
2654 strcpy(parking_ext, "700");
2655 strcpy(pickup_ext, "*8");
2656 strcpy(parkmohclass, "default");
2657 courtesytone[0] = '\0';
2658 strcpy(xfersound, "beep");
2659 strcpy(xferfailsound, "pbx-invalid");
2660 parking_start = 701;
2661 parking_stop = 750;
2662 parkfindnext = 0;
2663 adsipark = 0;
2664 parkaddhints = 0;
2666 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2667 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2668 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2670 cfg = ast_config_load("features.conf");
2671 if (!cfg) {
2672 ast_log(LOG_WARNING,"Could not load features.conf\n");
2673 return AST_MODULE_LOAD_DECLINE;
2675 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2676 if (!strcasecmp(var->name, "parkext")) {
2677 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2678 } else if (!strcasecmp(var->name, "context")) {
2679 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2680 } else if (!strcasecmp(var->name, "parkingtime")) {
2681 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2682 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2683 parkingtime = DEFAULT_PARK_TIME;
2684 } else
2685 parkingtime = parkingtime * 1000;
2686 } else if (!strcasecmp(var->name, "parkpos")) {
2687 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2688 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);
2689 } else {
2690 parking_start = start;
2691 parking_stop = end;
2693 } else if (!strcasecmp(var->name, "findslot")) {
2694 parkfindnext = (!strcasecmp(var->value, "next"));
2695 } else if (!strcasecmp(var->name, "parkinghints")) {
2696 parkaddhints = ast_true(var->value);
2697 } else if (!strcasecmp(var->name, "adsipark")) {
2698 adsipark = ast_true(var->value);
2699 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2700 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2701 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2702 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2703 } else
2704 transferdigittimeout = transferdigittimeout * 1000;
2705 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2706 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2707 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2708 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2710 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2711 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2712 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2713 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2714 } else
2715 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2716 } else if (!strcasecmp(var->name, "courtesytone")) {
2717 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2718 } else if (!strcasecmp(var->name, "parkedplay")) {
2719 if (!strcasecmp(var->value, "both"))
2720 parkedplay = 2;
2721 else if (!strcasecmp(var->value, "parked"))
2722 parkedplay = 1;
2723 else
2724 parkedplay = 0;
2725 } else if (!strcasecmp(var->name, "xfersound")) {
2726 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2727 } else if (!strcasecmp(var->name, "xferfailsound")) {
2728 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2729 } else if (!strcasecmp(var->name, "pickupexten")) {
2730 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2731 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2732 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2736 unmap_features();
2737 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2738 if (remap_feature(var->name, var->value))
2739 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2742 /* Map a key combination to an application*/
2743 ast_unregister_features();
2744 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2745 char *tmp_val = ast_strdupa(var->value);
2746 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2747 struct ast_call_feature *feature;
2749 /* strsep() sets the argument to NULL if match not found, and it
2750 * is safe to use it with a NULL argument, so we don't check
2751 * between calls.
2753 exten = strsep(&tmp_val,",");
2754 activatedby = strsep(&tmp_val,",");
2755 app = strsep(&tmp_val,",");
2756 app_args = strsep(&tmp_val,",");
2757 moh_class = strsep(&tmp_val,",");
2759 activateon = strsep(&activatedby, "/");
2761 /*! \todo XXX var_name or app_args ? */
2762 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2763 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2764 app, exten, activateon, var->name);
2765 continue;
2768 AST_LIST_LOCK(&feature_list);
2769 if ((feature = find_dynamic_feature(var->name))) {
2770 AST_LIST_UNLOCK(&feature_list);
2771 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2772 continue;
2774 AST_LIST_UNLOCK(&feature_list);
2776 if (!(feature = ast_calloc(1, sizeof(*feature))))
2777 continue;
2779 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2780 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2781 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2783 if (app_args)
2784 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2786 if (moh_class)
2787 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2789 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2790 feature->operation = feature_exec_app;
2791 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2793 /* Allow caller and calle to be specified for backwards compatability */
2794 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2795 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2796 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2797 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2798 else {
2799 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2800 " must be 'self', or 'peer'\n", var->name);
2801 continue;
2804 if (ast_strlen_zero(activatedby))
2805 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2806 else if (!strcasecmp(activatedby, "caller"))
2807 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2808 else if (!strcasecmp(activatedby, "callee"))
2809 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2810 else if (!strcasecmp(activatedby, "both"))
2811 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2812 else {
2813 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2814 " must be 'caller', or 'callee', or 'both'\n", var->name);
2815 continue;
2818 ast_register_feature(feature);
2820 if (option_verbose >= 1)
2821 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2823 ast_config_destroy(cfg);
2825 /* Remove the old parking extension */
2826 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2827 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2828 notify_metermaids(old_parking_ext, old_parking_con);
2829 if (option_debug)
2830 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2833 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2834 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2835 return -1;
2837 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2838 if (parkaddhints)
2839 park_add_hints(parking_con, parking_start, parking_stop);
2840 if (!res)
2841 notify_metermaids(ast_parking_ext(), parking_con);
2842 return res;
2846 static int reload(void)
2848 return load_config();
2851 static int load_module(void)
2853 int res;
2855 memset(parking_ext, 0, sizeof(parking_ext));
2856 memset(parking_con, 0, sizeof(parking_con));
2858 if ((res = load_config()))
2859 return res;
2860 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2861 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2862 ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
2863 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2864 if (!res)
2865 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2866 if (!res) {
2867 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2868 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2869 "Park a channel", mandescr_park);
2872 res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
2873 res |= ast_devstate_prov_add("Park", metermaidstate);
2875 return res;
2879 static int unload_module(void)
2881 ast_module_user_hangup_all();
2883 ast_manager_unregister("ParkedCalls");
2884 ast_manager_unregister("Park");
2885 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2886 ast_unregister_application(parkcall);
2887 ast_unregister_application(holdedcall);
2888 ast_devstate_prov_del("Park");
2889 return ast_unregister_application(parkedcall);
2892 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
2893 .load = load_module,
2894 .unload = unload_module,
2895 .reload = reload,